build/unix/elfhack/elfxx.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/build/unix/elfhack/elfxx.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,703 @@
     1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.7 +
     1.8 +#include "mozilla/NullPtr.h"
     1.9 +
    1.10 +#include <stdexcept>
    1.11 +#include <list>
    1.12 +#include <vector>
    1.13 +#include <cstring>
    1.14 +#include <iostream>
    1.15 +#include <fstream>
    1.16 +#include <algorithm>
    1.17 +#include <elf.h>
    1.18 +#include <asm/byteorder.h>
    1.19 +
    1.20 +// Technically, __*_to_cpu and __cpu_to* function are equivalent,
    1.21 +// so swap can use either of both.
    1.22 +#define def_swap(endian, type, bits) \
    1.23 +static inline type ## bits ## _t swap(type ## bits ## _t i) { \
    1.24 +    return __ ## endian ## bits ## _to_cpu(i); \
    1.25 +}
    1.26 +
    1.27 +class little_endian {
    1.28 +public:
    1.29 +def_swap(le, uint, 16);
    1.30 +def_swap(le, uint, 32);
    1.31 +def_swap(le, uint, 64);
    1.32 +def_swap(le, int, 16);
    1.33 +def_swap(le, int, 32);
    1.34 +def_swap(le, int, 64);
    1.35 +};
    1.36 +
    1.37 +class big_endian {
    1.38 +public:
    1.39 +def_swap(be, uint, 16);
    1.40 +def_swap(be, uint, 32);
    1.41 +def_swap(be, uint, 64);
    1.42 +def_swap(be, int, 16);
    1.43 +def_swap(be, int, 32);
    1.44 +def_swap(be, int, 64);
    1.45 +};
    1.46 +
    1.47 +// forward declaration
    1.48 +class ElfSection;
    1.49 +class ElfSegment;
    1.50 +// TODO: Rename Elf_* types
    1.51 +class Elf_Ehdr;
    1.52 +class Elf_Phdr;
    1.53 +class Elf;
    1.54 +class ElfDynamic_Section;
    1.55 +class ElfStrtab_Section;
    1.56 +
    1.57 +class Elf_Ehdr_Traits {
    1.58 +public:
    1.59 +    typedef Elf32_Ehdr Type32;
    1.60 +    typedef Elf64_Ehdr Type64;
    1.61 +
    1.62 +    template <class endian, typename R, typename T>
    1.63 +    static void swap(T &t, R &r);
    1.64 +};
    1.65 +
    1.66 +class Elf_Phdr_Traits {
    1.67 +public:
    1.68 +    typedef Elf32_Phdr Type32;
    1.69 +    typedef Elf64_Phdr Type64;
    1.70 +
    1.71 +    template <class endian, typename R, typename T>
    1.72 +    static void swap(T &t, R &r);
    1.73 +};
    1.74 +
    1.75 +class Elf_Shdr_Traits {
    1.76 +public:
    1.77 +    typedef Elf32_Shdr Type32;
    1.78 +    typedef Elf64_Shdr Type64;
    1.79 +
    1.80 +    template <class endian, typename R, typename T>
    1.81 +    static void swap(T &t, R &r);
    1.82 +};
    1.83 +
    1.84 +class Elf_Dyn_Traits {
    1.85 +public:
    1.86 +    typedef Elf32_Dyn Type32;
    1.87 +    typedef Elf64_Dyn Type64;
    1.88 +
    1.89 +    template <class endian, typename R, typename T>
    1.90 +    static void swap(T &t, R &r);
    1.91 +};
    1.92 +
    1.93 +class Elf_Sym_Traits {
    1.94 +public:
    1.95 +    typedef Elf32_Sym Type32;
    1.96 +    typedef Elf64_Sym Type64;
    1.97 +
    1.98 +    template <class endian, typename R, typename T>
    1.99 +    static void swap(T &t, R &r);
   1.100 +};
   1.101 +
   1.102 +class Elf_Rel_Traits {
   1.103 +public:
   1.104 +    typedef Elf32_Rel Type32;
   1.105 +    typedef Elf64_Rel Type64;
   1.106 +
   1.107 +    template <class endian, typename R, typename T>
   1.108 +    static void swap(T &t, R &r);
   1.109 +};
   1.110 +
   1.111 +class Elf_Rela_Traits {
   1.112 +public:
   1.113 +    typedef Elf32_Rela Type32;
   1.114 +    typedef Elf64_Rela Type64;
   1.115 +
   1.116 +    template <class endian, typename R, typename T>
   1.117 +    static void swap(T &t, R &r);
   1.118 +};
   1.119 +
   1.120 +class ElfValue {
   1.121 +public:
   1.122 +    virtual unsigned int getValue() { return 0; }
   1.123 +    virtual ElfSection *getSection() { return nullptr; }
   1.124 +};
   1.125 +
   1.126 +class ElfPlainValue: public ElfValue {
   1.127 +    unsigned int value;
   1.128 +public:
   1.129 +    ElfPlainValue(unsigned int val): value(val) {};
   1.130 +    unsigned int getValue() { return value; }
   1.131 +};
   1.132 +
   1.133 +class ElfLocation: public ElfValue {
   1.134 +    ElfSection *section;
   1.135 +    unsigned int offset;
   1.136 +public:
   1.137 +    enum position { ABSOLUTE, RELATIVE };
   1.138 +    ElfLocation(): section(nullptr), offset(0) {};
   1.139 +    ElfLocation(ElfSection *section, unsigned int off, enum position pos = RELATIVE);
   1.140 +    ElfLocation(unsigned int location, Elf *elf);
   1.141 +    unsigned int getValue();
   1.142 +    ElfSection *getSection() { return section; }
   1.143 +    const char *getBuffer();
   1.144 +};
   1.145 +
   1.146 +class ElfSize: public ElfValue {
   1.147 +    ElfSection *section;
   1.148 +public:
   1.149 +    ElfSize(ElfSection *s): section(s) {};
   1.150 +    unsigned int getValue();
   1.151 +    ElfSection *getSection() { return section; }
   1.152 +};
   1.153 +
   1.154 +class ElfEntSize: public ElfValue {
   1.155 +    ElfSection *section;
   1.156 +public:
   1.157 +    ElfEntSize(ElfSection *s): section(s) {};
   1.158 +    unsigned int getValue();
   1.159 +    ElfSection *getSection() { return section; }
   1.160 +};
   1.161 +
   1.162 +template <typename T>
   1.163 +class serializable: public T::Type32 {
   1.164 +public:
   1.165 +    serializable() {};
   1.166 +    serializable(const typename T::Type32 &p): T::Type32(p) {};
   1.167 +
   1.168 +private:
   1.169 +    template <typename R>
   1.170 +    void init(const char *buf, size_t len, char ei_data)
   1.171 +    {
   1.172 +        R e;
   1.173 +        assert(len >= sizeof(e));
   1.174 +        memcpy(&e, buf, sizeof(e));
   1.175 +        if (ei_data == ELFDATA2LSB) {
   1.176 +            T::template swap<little_endian>(e, *this);
   1.177 +            return;
   1.178 +        } else if (ei_data == ELFDATA2MSB) {
   1.179 +            T::template swap<big_endian>(e, *this);
   1.180 +            return;
   1.181 +        }
   1.182 +        throw std::runtime_error("Unsupported ELF data encoding");
   1.183 +    }
   1.184 +
   1.185 +    template <typename R>
   1.186 +    void serialize(const char *buf, size_t len, char ei_data)
   1.187 +    {
   1.188 +        assert(len >= sizeof(R));
   1.189 +        if (ei_data == ELFDATA2LSB) {
   1.190 +            T::template swap<little_endian>(*this, *(R *)buf);
   1.191 +            return;
   1.192 +        } else if (ei_data == ELFDATA2MSB) {
   1.193 +            T::template swap<big_endian>(*this, *(R *)buf);
   1.194 +            return;
   1.195 +        }
   1.196 +        throw std::runtime_error("Unsupported ELF data encoding");
   1.197 +    }
   1.198 +
   1.199 +public:
   1.200 +    serializable(const char *buf, size_t len, char ei_class, char ei_data)
   1.201 +    {
   1.202 +        if (ei_class == ELFCLASS32) {
   1.203 +            init<typename T::Type32>(buf, len, ei_data);
   1.204 +            return;
   1.205 +        } else if (ei_class == ELFCLASS64) {
   1.206 +            init<typename T::Type64>(buf, len, ei_data);
   1.207 +            return;
   1.208 +        }
   1.209 +        throw std::runtime_error("Unsupported ELF class");
   1.210 +    }
   1.211 +
   1.212 +    serializable(std::ifstream &file, char ei_class, char ei_data)
   1.213 +    {
   1.214 +        if (ei_class == ELFCLASS32) {
   1.215 +            typename T::Type32 e;
   1.216 +            file.read((char *)&e, sizeof(e));
   1.217 +            init<typename T::Type32>((char *)&e, sizeof(e), ei_data);
   1.218 +            return;
   1.219 +        } else if (ei_class == ELFCLASS64) {
   1.220 +            typename T::Type64 e;
   1.221 +            file.read((char *)&e, sizeof(e));
   1.222 +            init<typename T::Type64>((char *)&e, sizeof(e), ei_data);
   1.223 +            return;
   1.224 +        }
   1.225 +        throw std::runtime_error("Unsupported ELF class or data encoding");
   1.226 +    }
   1.227 +
   1.228 +    void serialize(std::ofstream &file, char ei_class, char ei_data)
   1.229 +    {
   1.230 +        if (ei_class == ELFCLASS32) {
   1.231 +            typename T::Type32 e;
   1.232 +            serialize<typename T::Type32>((char *)&e, sizeof(e), ei_data);
   1.233 +            file.write((char *)&e, sizeof(e));
   1.234 +            return;
   1.235 +        } else if (ei_class == ELFCLASS64) {
   1.236 +            typename T::Type64 e;
   1.237 +            serialize<typename T::Type64>((char *)&e, sizeof(e), ei_data);
   1.238 +            file.write((char *)&e, sizeof(e));
   1.239 +            return;
   1.240 +        }
   1.241 +        throw std::runtime_error("Unsupported ELF class or data encoding");
   1.242 +    }
   1.243 +
   1.244 +    void serialize(char *buf, size_t len, char ei_class, char ei_data)
   1.245 +    {
   1.246 +        if (ei_class == ELFCLASS32) {
   1.247 +            serialize<typename T::Type32>(buf, len, ei_data);
   1.248 +            return;
   1.249 +        } else if (ei_class == ELFCLASS64) {
   1.250 +            serialize<typename T::Type64>(buf, len, ei_data);
   1.251 +            return;
   1.252 +        }
   1.253 +        throw std::runtime_error("Unsupported ELF class");
   1.254 +    }
   1.255 +
   1.256 +    static inline unsigned int size(char ei_class)
   1.257 +    {
   1.258 +        if (ei_class == ELFCLASS32)
   1.259 +            return sizeof(typename T::Type32);
   1.260 +        else if (ei_class == ELFCLASS64)
   1.261 +            return sizeof(typename T::Type64);
   1.262 +        return 0;
   1.263 +    }
   1.264 +};
   1.265 +
   1.266 +typedef serializable<Elf_Shdr_Traits> Elf_Shdr;
   1.267 +
   1.268 +class Elf {
   1.269 +public:
   1.270 +    Elf(std::ifstream &file);
   1.271 +    ~Elf();
   1.272 +
   1.273 +    /* index == -1 is treated as index == ehdr.e_shstrndx */
   1.274 +    ElfSection *getSection(int index);
   1.275 +
   1.276 +    ElfSection *getSectionAt(unsigned int offset);
   1.277 +
   1.278 +    ElfSegment *getSegmentByType(unsigned int type, ElfSegment *last = nullptr);
   1.279 +
   1.280 +    ElfDynamic_Section *getDynSection();
   1.281 +
   1.282 +    void normalize();
   1.283 +    void write(std::ofstream &file);
   1.284 +
   1.285 +    char getClass();
   1.286 +    char getData();
   1.287 +    char getType();
   1.288 +    char getMachine();
   1.289 +    unsigned int getSize();
   1.290 +
   1.291 +    void insertSegmentAfter(ElfSegment *previous, ElfSegment *segment) {
   1.292 +        std::vector<ElfSegment *>::iterator prev = std::find(segments.begin(), segments.end(), previous);
   1.293 +        segments.insert(prev + 1, segment);
   1.294 +    }
   1.295 +
   1.296 +    void removeSegment(ElfSegment *segment);
   1.297 +
   1.298 +private:
   1.299 +    Elf_Ehdr *ehdr;
   1.300 +    ElfLocation eh_entry;
   1.301 +    ElfStrtab_Section *eh_shstrndx;
   1.302 +    ElfSection **sections;
   1.303 +    std::vector<ElfSegment *> segments;
   1.304 +    ElfSection *shdr_section, *phdr_section;
   1.305 +    /* Values used only during initialization */
   1.306 +    Elf_Shdr **tmp_shdr;
   1.307 +    std::ifstream *tmp_file;
   1.308 +};
   1.309 +
   1.310 +class ElfSection {
   1.311 +public:
   1.312 +    typedef union {
   1.313 +        ElfSection *section;
   1.314 +        int index;
   1.315 +    } SectionInfo;
   1.316 +
   1.317 +    ElfSection(Elf_Shdr &s, std::ifstream *file, Elf *parent);
   1.318 +
   1.319 +    virtual ~ElfSection() {
   1.320 +        delete[] data;
   1.321 +    }
   1.322 +
   1.323 +    const char *getName() { return name; }
   1.324 +    unsigned int getType() { return shdr.sh_type; }
   1.325 +    unsigned int getFlags() { return shdr.sh_flags; }
   1.326 +    unsigned int getAddr();
   1.327 +    unsigned int getSize() { return shdr.sh_size; }
   1.328 +    unsigned int getAddrAlign() { return shdr.sh_addralign; }
   1.329 +    unsigned int getEntSize() { return shdr.sh_entsize; }
   1.330 +    const char *getData() { return data; }
   1.331 +    ElfSection *getLink() { return link; }
   1.332 +    SectionInfo getInfo() { return info; }
   1.333 +
   1.334 +    void shrink(unsigned int newsize) {
   1.335 +        if (newsize < shdr.sh_size)
   1.336 +            shdr.sh_size = newsize;
   1.337 +    }
   1.338 +
   1.339 +    unsigned int getOffset();
   1.340 +    int getIndex();
   1.341 +    Elf_Shdr &getShdr();
   1.342 +
   1.343 +    ElfSection *getNext() { return next; }
   1.344 +    ElfSection *getPrevious() { return previous; }
   1.345 +
   1.346 +    virtual bool isRelocatable() {
   1.347 +        return ((getType() == SHT_SYMTAB) ||
   1.348 +                (getType() == SHT_STRTAB) ||
   1.349 +                (getType() == SHT_RELA) ||
   1.350 +                (getType() == SHT_HASH) ||
   1.351 +                (getType() == SHT_NOTE) ||
   1.352 +                (getType() == SHT_REL) ||
   1.353 +                (getType() == SHT_DYNSYM) ||
   1.354 +                (getType() == SHT_GNU_HASH) ||
   1.355 +                (getType() == SHT_GNU_verdef) ||
   1.356 +                (getType() == SHT_GNU_verneed) ||
   1.357 +                (getType() == SHT_GNU_versym) ||
   1.358 +                getSegmentByType(PT_INTERP)) &&
   1.359 +                (getFlags() & SHF_ALLOC);
   1.360 +    }
   1.361 +
   1.362 +    void insertAfter(ElfSection *section, bool dirty = true) {
   1.363 +        if (previous != nullptr)
   1.364 +            previous->next = next;
   1.365 +        if (next != nullptr)
   1.366 +            next->previous = previous;
   1.367 +        previous = section;
   1.368 +        if (section != nullptr) {
   1.369 +            next = section->next;
   1.370 +            section->next = this;
   1.371 +        } else
   1.372 +            next = nullptr;
   1.373 +        if (next != nullptr)
   1.374 +            next->previous = this;
   1.375 +        if (dirty)
   1.376 +            markDirty();
   1.377 +        insertInSegments(section->segments);
   1.378 +    }
   1.379 +
   1.380 +    void insertBefore(ElfSection *section, bool dirty = true) {
   1.381 +        if (previous != nullptr)
   1.382 +            previous->next = next;
   1.383 +        if (next != nullptr)
   1.384 +            next->previous = previous;
   1.385 +        next = section;
   1.386 +        if (section != nullptr) {
   1.387 +            previous = section->previous;
   1.388 +            section->previous = this;
   1.389 +        } else
   1.390 +            previous = nullptr;
   1.391 +        if (previous != nullptr)
   1.392 +            previous->next = this;
   1.393 +        if (dirty)
   1.394 +            markDirty();
   1.395 +        insertInSegments(section->segments);
   1.396 +    }
   1.397 +
   1.398 +    void markDirty() {
   1.399 +        if (link != nullptr)
   1.400 +            shdr.sh_link = -1;
   1.401 +        if (info.index)
   1.402 +            shdr.sh_info = -1;
   1.403 +        shdr.sh_offset = -1;
   1.404 +        if (isRelocatable())
   1.405 +            shdr.sh_addr = -1;
   1.406 +        if (next)
   1.407 +            next->markDirty();
   1.408 +    }
   1.409 +
   1.410 +    virtual void serialize(std::ofstream &file, char ei_class, char ei_data)
   1.411 +    {
   1.412 +        if (getType() == SHT_NOBITS)
   1.413 +            return;
   1.414 +        file.seekp(getOffset());
   1.415 +        file.write(data, getSize());
   1.416 +    }
   1.417 +
   1.418 +private:
   1.419 +    friend class ElfSegment;
   1.420 +
   1.421 +    void addToSegment(ElfSegment *segment) {
   1.422 +        segments.push_back(segment);
   1.423 +    }
   1.424 +
   1.425 +    void removeFromSegment(ElfSegment *segment) {
   1.426 +        std::vector<ElfSegment *>::iterator i = std::find(segments.begin(), segments.end(), segment);
   1.427 +        segments.erase(i, i + 1);
   1.428 +    }
   1.429 +
   1.430 +    ElfSegment *getSegmentByType(unsigned int type);
   1.431 +
   1.432 +    void insertInSegments(std::vector<ElfSegment *> &segs);
   1.433 +
   1.434 +protected:
   1.435 +    Elf_Shdr shdr;
   1.436 +    char *data;
   1.437 +    const char *name;
   1.438 +private:
   1.439 +    ElfSection *link;
   1.440 +    SectionInfo info;
   1.441 +    ElfSection *next, *previous;
   1.442 +    int index;
   1.443 +    std::vector<ElfSegment *> segments;
   1.444 +};
   1.445 +
   1.446 +class ElfSegment {
   1.447 +public:
   1.448 +    ElfSegment(Elf_Phdr *phdr);
   1.449 +
   1.450 +    unsigned int getType() { return type; }
   1.451 +    unsigned int getFlags() { return flags; }
   1.452 +    unsigned int getAlign() { return align; }
   1.453 +
   1.454 +    ElfSection *getFirstSection() { return sections.empty() ? nullptr : sections.front(); }
   1.455 +    int getVPDiff() { return v_p_diff; }
   1.456 +    unsigned int getFileSize();
   1.457 +    unsigned int getMemSize();
   1.458 +    unsigned int getOffset();
   1.459 +    unsigned int getAddr();
   1.460 +
   1.461 +    void addSection(ElfSection *section);
   1.462 +    void removeSection(ElfSection *section);
   1.463 +
   1.464 +    std::list<ElfSection *>::iterator begin() { return sections.begin(); }
   1.465 +    std::list<ElfSection *>::iterator end() { return sections.end(); }
   1.466 +
   1.467 +    void clear();
   1.468 +
   1.469 +    bool isElfHackFillerSegment() {
   1.470 +      return type == PT_LOAD && flags == 0;
   1.471 +    }
   1.472 +private:
   1.473 +    unsigned int type;
   1.474 +    int v_p_diff; // Difference between physical and virtual address
   1.475 +    unsigned int flags;
   1.476 +    unsigned int align;
   1.477 +    std::list<ElfSection *> sections;
   1.478 +    // The following are only really used for PT_GNU_RELRO until something
   1.479 +    // better is found.
   1.480 +    unsigned int vaddr;
   1.481 +    unsigned int filesz, memsz;
   1.482 +};
   1.483 +
   1.484 +class Elf_Ehdr: public serializable<Elf_Ehdr_Traits>, public ElfSection {
   1.485 +public:
   1.486 +    Elf_Ehdr(std::ifstream &file, char ei_class, char ei_data);
   1.487 +    void serialize(std::ofstream &file, char ei_class, char ei_data)
   1.488 +    {
   1.489 +        serializable<Elf_Ehdr_Traits>::serialize(file, ei_class, ei_data);
   1.490 +    }
   1.491 +};
   1.492 +
   1.493 +class Elf_Phdr: public serializable<Elf_Phdr_Traits> {
   1.494 +public:
   1.495 +    Elf_Phdr() {};
   1.496 +    Elf_Phdr(std::ifstream &file, char ei_class, char ei_data)
   1.497 +    : serializable<Elf_Phdr_Traits>(file, ei_class, ei_data) {};
   1.498 +    bool contains(ElfSection *section)
   1.499 +    {
   1.500 +        unsigned int size = section->getSize();
   1.501 +        unsigned int addr = section->getAddr();
   1.502 +        // This may be biased, but should work in most cases
   1.503 +        if ((section->getFlags() & SHF_ALLOC) == 0)
   1.504 +            return false;
   1.505 +        // Special case for PT_DYNAMIC. Eventually, this should
   1.506 +        // be better handled than special cases
   1.507 +        if ((p_type == PT_DYNAMIC) && (section->getType() != SHT_DYNAMIC))
   1.508 +            return false;
   1.509 +        // Special case for PT_TLS.
   1.510 +        if ((p_type == PT_TLS) && !(section->getFlags() & SHF_TLS))
   1.511 +            return false;
   1.512 +        return (addr >= p_vaddr) &&
   1.513 +               (addr + size <= p_vaddr + p_memsz);
   1.514 +
   1.515 +    }
   1.516 +};
   1.517 +
   1.518 +typedef serializable<Elf_Dyn_Traits> Elf_Dyn;
   1.519 +
   1.520 +struct Elf_DynValue {
   1.521 +    unsigned int tag;
   1.522 +    ElfValue *value;
   1.523 +};
   1.524 +
   1.525 +class ElfDynamic_Section: public ElfSection {
   1.526 +public:
   1.527 +    ElfDynamic_Section(Elf_Shdr &s, std::ifstream *file, Elf *parent);
   1.528 +    ~ElfDynamic_Section();
   1.529 +
   1.530 +    void serialize(std::ofstream &file, char ei_class, char ei_data);
   1.531 +
   1.532 +    ElfValue *getValueForType(unsigned int tag);
   1.533 +    ElfSection *getSectionForType(unsigned int tag);
   1.534 +    bool setValueForType(unsigned int tag, ElfValue *val);
   1.535 +private:
   1.536 +    std::vector<Elf_DynValue> dyns;
   1.537 +};
   1.538 +
   1.539 +typedef serializable<Elf_Sym_Traits> Elf_Sym;
   1.540 +
   1.541 +struct Elf_SymValue {
   1.542 +    const char *name;
   1.543 +    unsigned char info;
   1.544 +    unsigned char other;
   1.545 +    ElfLocation value;
   1.546 +    unsigned int size;
   1.547 +    bool defined;
   1.548 +};
   1.549 +
   1.550 +#define STT(type) (1 << STT_ ##type)
   1.551 +
   1.552 +class ElfSymtab_Section: public ElfSection {
   1.553 +public:
   1.554 +    ElfSymtab_Section(Elf_Shdr &s, std::ifstream *file, Elf *parent);
   1.555 +
   1.556 +    void serialize(std::ofstream &file, char ei_class, char ei_data);
   1.557 +
   1.558 +    Elf_SymValue *lookup(const char *name, unsigned int type_filter = STT(OBJECT) | STT(FUNC));
   1.559 +
   1.560 +//private: // Until we have a real API
   1.561 +    std::vector<Elf_SymValue> syms;
   1.562 +};
   1.563 +
   1.564 +class Elf_Rel: public serializable<Elf_Rel_Traits> {
   1.565 +public:
   1.566 +    Elf_Rel(std::ifstream &file, char ei_class, char ei_data)
   1.567 +    : serializable<Elf_Rel_Traits>(file, ei_class, ei_data) {};
   1.568 +
   1.569 +    static const unsigned int sh_type = SHT_REL;
   1.570 +    static const unsigned int d_tag = DT_REL;
   1.571 +    static const unsigned int d_tag_count = DT_RELCOUNT;
   1.572 +};
   1.573 +
   1.574 +class Elf_Rela: public serializable<Elf_Rela_Traits> {
   1.575 +public:
   1.576 +    Elf_Rela(std::ifstream &file, char ei_class, char ei_data)
   1.577 +    : serializable<Elf_Rela_Traits>(file, ei_class, ei_data) {};
   1.578 +
   1.579 +    static const unsigned int sh_type = SHT_RELA;
   1.580 +    static const unsigned int d_tag = DT_RELA;
   1.581 +    static const unsigned int d_tag_count = DT_RELACOUNT;
   1.582 +};
   1.583 +
   1.584 +template <class Rel>
   1.585 +class ElfRel_Section: public ElfSection {
   1.586 +public:
   1.587 +    ElfRel_Section(Elf_Shdr &s, std::ifstream *file, Elf *parent)
   1.588 +    : ElfSection(s, file, parent)
   1.589 +    {
   1.590 +        int pos = file->tellg();
   1.591 +        file->seekg(shdr.sh_offset);
   1.592 +        for (unsigned int i = 0; i < s.sh_size / s.sh_entsize; i++) {
   1.593 +            Rel r(*file, parent->getClass(), parent->getData());
   1.594 +            rels.push_back(r);
   1.595 +        }
   1.596 +        file->seekg(pos);
   1.597 +    }
   1.598 +
   1.599 +    void serialize(std::ofstream &file, char ei_class, char ei_data)
   1.600 +    {
   1.601 +        for (typename std::vector<Rel>::iterator i = rels.begin();
   1.602 +             i != rels.end(); ++i)
   1.603 +            (*i).serialize(file, ei_class, ei_data);
   1.604 +    }
   1.605 +//private: // Until we have a real API
   1.606 +    std::vector<Rel> rels;
   1.607 +};
   1.608 +
   1.609 +class ElfStrtab_Section: public ElfSection {
   1.610 +public:
   1.611 +    ElfStrtab_Section(Elf_Shdr &s, std::ifstream *file, Elf *parent)
   1.612 +    : ElfSection(s, file, parent)
   1.613 +    {
   1.614 +        table.push_back(table_storage(data, shdr.sh_size));
   1.615 +    }
   1.616 +
   1.617 +    ~ElfStrtab_Section()
   1.618 +    {
   1.619 +        for (std::vector<table_storage>::iterator t = table.begin() + 1;
   1.620 +             t != table.end(); t++)
   1.621 +            delete[] t->buf;
   1.622 +    }
   1.623 +
   1.624 +    const char *getStr(unsigned int index);
   1.625 +
   1.626 +    const char *getStr(const char *string);
   1.627 +
   1.628 +    unsigned int getStrIndex(const char *string);
   1.629 +
   1.630 +    void serialize(std::ofstream &file, char ei_class, char ei_data);
   1.631 +private:
   1.632 +    struct table_storage {
   1.633 +        unsigned int size, used;
   1.634 +        char *buf;
   1.635 +
   1.636 +        table_storage(): size(4096), used(0), buf(new char[4096]) {}
   1.637 +        table_storage(const char *data, unsigned int sz)
   1.638 +        : size(sz), used(sz), buf(const_cast<char *>(data)) {}
   1.639 +    };
   1.640 +    std::vector<table_storage> table;
   1.641 +};
   1.642 +
   1.643 +inline char Elf::getClass() {
   1.644 +    return ehdr->e_ident[EI_CLASS];
   1.645 +}
   1.646 +
   1.647 +inline char Elf::getData() {
   1.648 +    return ehdr->e_ident[EI_DATA];
   1.649 +}
   1.650 +
   1.651 +inline char Elf::getType() {
   1.652 +    return ehdr->e_type;
   1.653 +}
   1.654 +
   1.655 +inline char Elf::getMachine() {
   1.656 +    return ehdr->e_machine;
   1.657 +}
   1.658 +
   1.659 +inline unsigned int Elf::getSize() {
   1.660 +    ElfSection *section;
   1.661 +    for (section = shdr_section /* It's usually not far from the end */;
   1.662 +        section->getNext() != nullptr; section = section->getNext());
   1.663 +    return section->getOffset() + section->getSize();
   1.664 +}
   1.665 +
   1.666 +inline ElfSegment *ElfSection::getSegmentByType(unsigned int type) {
   1.667 +    for (std::vector<ElfSegment *>::iterator seg = segments.begin(); seg != segments.end(); seg++)
   1.668 +        if ((*seg)->getType() == type)
   1.669 +            return *seg;
   1.670 +    return nullptr;
   1.671 +}
   1.672 +
   1.673 +inline void ElfSection::insertInSegments(std::vector<ElfSegment *> &segs) {
   1.674 +    for (std::vector<ElfSegment *>::iterator it = segs.begin(); it != segs.end(); ++it) {
   1.675 +        (*it)->addSection(this);
   1.676 +    }
   1.677 +}
   1.678 +
   1.679 +inline ElfLocation::ElfLocation(ElfSection *section, unsigned int off, enum position pos)
   1.680 +: section(section) {
   1.681 +    if ((pos == ABSOLUTE) && section)
   1.682 +        offset = off - section->getAddr();
   1.683 +    else
   1.684 +        offset = off;
   1.685 +}
   1.686 +
   1.687 +inline ElfLocation::ElfLocation(unsigned int location, Elf *elf) {
   1.688 +    section = elf->getSectionAt(location);
   1.689 +    offset = location - (section ? section->getAddr() : 0);
   1.690 +}
   1.691 +
   1.692 +inline unsigned int ElfLocation::getValue() {
   1.693 +    return (section ? section->getAddr() : 0) + offset;
   1.694 +}
   1.695 +
   1.696 +inline const char *ElfLocation::getBuffer() {
   1.697 +    return section ? section->getData() + offset : nullptr;
   1.698 +}
   1.699 +
   1.700 +inline unsigned int ElfSize::getValue() {
   1.701 +    return section->getSize();
   1.702 +}
   1.703 +
   1.704 +inline unsigned int ElfEntSize::getValue() {
   1.705 +    return section->getEntSize();
   1.706 +}

mercurial