LCOV - code coverage report
Current view: directory - build/unix/elfhack - elfxx.h (source / functions) Found Hit Coverage
Test: app.info Lines: 256 187 73.0 %
Date: 2012-06-02 Functions: 123 95 77.2 %

       1                 : /* ***** BEGIN LICENSE BLOCK *****
       2                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       3                 :  *
       4                 :  * The contents of this file are subject to the Mozilla Public License Version
       5                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       6                 :  * the License. You may obtain a copy of the License at
       7                 :  * http://www.mozilla.org/MPL/
       8                 :  *
       9                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      10                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      11                 :  * for the specific language governing rights and limitations under the
      12                 :  * License.
      13                 :  *
      14                 :  * The Original Code is elfhack.
      15                 :  *
      16                 :  * The Initial Developer of the Original Code is
      17                 :  * Mozilla Foundation.
      18                 :  * Portions created by the Initial Developer are Copyright (C) 2010
      19                 :  * the Initial Developer. All Rights Reserved.
      20                 :  *
      21                 :  * Contributor(s):
      22                 :  *   Mike Hommey <mh@glandium.org>
      23                 :  *
      24                 :  * Alternatively, the contents of this file may be used under the terms of
      25                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      26                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      27                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      28                 :  * of those above. If you wish to allow use of your version of this file only
      29                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      30                 :  * use your version of this file under the terms of the MPL, indicate your
      31                 :  * decision by deleting the provisions above and replace them with the notice
      32                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      33                 :  * the provisions above, a recipient may use your version of this file under
      34                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      35                 :  *
      36                 :  * ***** END LICENSE BLOCK ***** */
      37                 : 
      38                 : #include <stdexcept>
      39                 : #include <list>
      40                 : #include <vector>
      41                 : #include <cstring>
      42                 : #include <iostream>
      43                 : #include <fstream>
      44                 : #include <algorithm>
      45                 : #include <elf.h>
      46                 : #include <asm/byteorder.h>
      47                 : 
      48                 : // Technically, __*_to_cpu and __cpu_to* function are equivalent,
      49                 : // so swap can use either of both.
      50                 : #define def_swap(endian, type, bits) \
      51                 : static inline type ## bits ## _t swap(type ## bits ## _t i) { \
      52                 :     return __ ## endian ## bits ## _to_cpu(i); \
      53                 : }
      54                 : 
      55                 : class little_endian {
      56                 : public:
      57          788311 : def_swap(le, uint, 16);
      58         3135342 : def_swap(le, uint, 32);
      59               0 : def_swap(le, uint, 64);
      60                 : def_swap(le, int, 16);
      61             895 : def_swap(le, int, 32);
      62               0 : def_swap(le, int, 64);
      63                 : };
      64                 : 
      65                 : class big_endian {
      66                 : public:
      67               0 : def_swap(be, uint, 16);
      68               0 : def_swap(be, uint, 32);
      69               0 : def_swap(be, uint, 64);
      70                 : def_swap(be, int, 16);
      71               0 : def_swap(be, int, 32);
      72               0 : def_swap(be, int, 64);
      73                 : };
      74                 : 
      75                 : // forward declaration
      76                 : class ElfSection;
      77                 : class ElfSegment;
      78                 : // TODO: Rename Elf_* types
      79                 : class Elf_Ehdr;
      80                 : class Elf_Phdr;
      81                 : class Elf;
      82                 : class ElfDynamic_Section;
      83                 : class ElfStrtab_Section;
      84                 : 
      85                 : class Elf_Ehdr_Traits {
      86                 : public:
      87                 :     typedef Elf32_Ehdr Type32;
      88                 :     typedef Elf64_Ehdr Type64;
      89                 : 
      90                 :     template <class endian, typename R, typename T>
      91                 :     static void swap(T &t, R &r);
      92                 : };
      93                 : 
      94                 : class Elf_Phdr_Traits {
      95                 : public:
      96                 :     typedef Elf32_Phdr Type32;
      97                 :     typedef Elf64_Phdr Type64;
      98                 : 
      99                 :     template <class endian, typename R, typename T>
     100                 :     static void swap(T &t, R &r);
     101                 : };
     102                 : 
     103                 : class Elf_Shdr_Traits {
     104                 : public:
     105                 :     typedef Elf32_Shdr Type32;
     106                 :     typedef Elf64_Shdr Type64;
     107                 : 
     108                 :     template <class endian, typename R, typename T>
     109                 :     static void swap(T &t, R &r);
     110                 : };
     111                 : 
     112                 : class Elf_Dyn_Traits {
     113                 : public:
     114                 :     typedef Elf32_Dyn Type32;
     115                 :     typedef Elf64_Dyn Type64;
     116                 : 
     117                 :     template <class endian, typename R, typename T>
     118                 :     static void swap(T &t, R &r);
     119                 : };
     120                 : 
     121                 : class Elf_Sym_Traits {
     122                 : public:
     123                 :     typedef Elf32_Sym Type32;
     124                 :     typedef Elf64_Sym Type64;
     125                 : 
     126                 :     template <class endian, typename R, typename T>
     127                 :     static void swap(T &t, R &r);
     128                 : };
     129                 : 
     130                 : class Elf_Rel_Traits {
     131                 : public:
     132                 :     typedef Elf32_Rel Type32;
     133                 :     typedef Elf64_Rel Type64;
     134                 : 
     135                 :     template <class endian, typename R, typename T>
     136                 :     static void swap(T &t, R &r);
     137                 : };
     138                 : 
     139                 : class Elf_Rela_Traits {
     140                 : public:
     141                 :     typedef Elf32_Rela Type32;
     142                 :     typedef Elf64_Rela Type64;
     143                 : 
     144                 :     template <class endian, typename R, typename T>
     145                 :     static void swap(T &t, R &r);
     146                 : };
     147                 : 
     148          812816 : class ElfValue {
     149                 : public:
     150              20 :     virtual unsigned int getValue() { return 0; }
     151               0 :     virtual ElfSection *getSection() { return NULL; }
     152                 : };
     153                 : 
     154                 : class ElfPlainValue: public ElfValue {
     155                 :     unsigned int value;
     156                 : public:
     157             338 :     ElfPlainValue(unsigned int val): value(val) {};
     158              65 :     unsigned int getValue() { return value; }
     159                 : };
     160                 : 
     161          405949 : class ElfLocation: public ElfValue {
     162                 :     ElfSection *section;
     163                 :     unsigned int offset;
     164                 : public:
     165                 :     enum position { ABSOLUTE, RELATIVE };
     166             105 :     ElfLocation(): section(NULL), offset(0) {};
     167                 :     ElfLocation(ElfSection *section, unsigned int off, enum position pos = RELATIVE);
     168                 :     ElfLocation(unsigned int location, Elf *elf);
     169                 :     unsigned int getValue();
     170          382190 :     ElfSection *getSection() { return section; }
     171                 : };
     172                 : 
     173                 : class ElfSize: public ElfValue {
     174                 :     ElfSection *section;
     175                 : public:
     176              63 :     ElfSize(ElfSection *s): section(s) {};
     177                 :     unsigned int getValue();
     178               0 :     ElfSection *getSection() { return section; }
     179                 : };
     180                 : 
     181                 : class ElfEntSize: public ElfValue {
     182                 :     ElfSection *section;
     183                 : public:
     184              42 :     ElfEntSize(ElfSection *s): section(s) {};
     185                 :     unsigned int getValue();
     186               0 :     ElfSection *getSection() { return section; }
     187                 : };
     188                 : 
     189                 : template <typename T>
     190               0 : class serializable: public T::Type32 {
     191                 : public:
     192          382231 :     serializable() {};
     193              44 :     serializable(const typename T::Type32 &p): T::Type32(p) {};
     194                 : 
     195                 : private:
     196                 :     template <typename R>
     197               0 :     void init(const char *buf, size_t len, char ei_data)
     198                 :     {
     199                 :         R e;
     200               0 :         assert(len <= sizeof(e));
     201               0 :         memcpy(&e, buf, sizeof(e));
     202               0 :         if (ei_data == ELFDATA2LSB) {
     203               0 :             T::template swap<little_endian>(e, *this);
     204               0 :             return;
     205               0 :         } else if (ei_data == ELFDATA2MSB) {
     206               0 :             T::template swap<big_endian>(e, *this);
     207               0 :             return;
     208                 :         }
     209               0 :         throw std::runtime_error("Unsupported ELF data encoding");
     210                 :     }
     211                 : 
     212                 : public:
     213               0 :     serializable(const char *buf, size_t len, char ei_class, char ei_data)
     214               0 :     {
     215               0 :         if (ei_class == ELFCLASS32) {
     216               0 :             init<typename T::Type32>(buf, len, ei_data);
     217               0 :             return;
     218               0 :         } else if (ei_class == ELFCLASS64) {
     219               0 :             init<typename T::Type64>(buf, len, ei_data);
     220               0 :             return;
     221                 :         }
     222               0 :         throw std::runtime_error("Unsupported ELF class");
     223                 :     }
     224                 : 
     225          735082 :     serializable(std::ifstream &file, char ei_class, char ei_data)
     226          735082 :     {
     227          735082 :         if (ei_class == ELFCLASS32) {
     228                 :             typename T::Type32 e;
     229          735082 :             file.read((char *)&e, sizeof(e));
     230          735082 :             if (ei_data == ELFDATA2LSB) {
     231          735082 :                 T::template swap<little_endian>(e, *this);
     232          735082 :                 return;
     233               0 :             } else if (ei_data == ELFDATA2MSB) {
     234               0 :                 T::template swap<big_endian>(e, *this);
     235               0 :                 return;
     236                 :             }
     237               0 :         } else if (ei_class == ELFCLASS64) {
     238                 :             typename T::Type64 e;
     239               0 :             file.read((char *)&e, sizeof(e));
     240               0 :             if (ei_data == ELFDATA2LSB) {
     241               0 :                 T::template swap<little_endian>(e, *this);
     242               0 :                 return;
     243               0 :             } else if (ei_data == ELFDATA2MSB) {
     244               0 :                 T::template swap<big_endian>(e, *this);
     245               0 :                 return;
     246                 :             }
     247                 :         }
     248               0 :         throw std::runtime_error("Unsupported ELF class or data encoding");
     249                 :     }
     250                 : 
     251          433935 :     void serialize(std::ofstream &file, char ei_class, char ei_data)
     252                 :     {
     253          433935 :         if (ei_class == ELFCLASS32) {
     254                 :             typename T::Type32 e;
     255          433935 :             if (ei_data == ELFDATA2LSB) {
     256          433935 :                 T::template swap<little_endian>(*this, e);
     257          433935 :                 file.write((char *)&e, sizeof(e));
     258          433935 :                 return;
     259               0 :             } else if (ei_data == ELFDATA2MSB) {
     260               0 :                 T::template swap<big_endian>(*this, e);
     261               0 :                 file.write((char *)&e, sizeof(e));
     262               0 :                 return;
     263                 :             }
     264               0 :         } else if (ei_class == ELFCLASS64) {
     265                 :             typename T::Type64 e;
     266               0 :             if (ei_data == ELFDATA2LSB) {
     267               0 :                 T::template swap<little_endian>(*this, e);
     268               0 :                 file.write((char *)&e, sizeof(e));
     269               0 :                 return;
     270               0 :             } else if (ei_data == ELFDATA2MSB) {
     271               0 :                 T::template swap<big_endian>(*this, e);
     272               0 :                 file.write((char *)&e, sizeof(e));
     273               0 :                 return;
     274                 :             }
     275                 :         }
     276               0 :         throw std::runtime_error("Unsupported ELF class or data encoding");
     277                 :     }
     278                 : 
     279             281 :     static inline unsigned int size(char ei_class)
     280                 :     {
     281             281 :         if (ei_class == ELFCLASS32)
     282             281 :             return sizeof(typename T::Type32);
     283               0 :         else if (ei_class == ELFCLASS64)
     284               0 :             return sizeof(typename T::Type64);
     285               0 :         return 0;
     286                 :     }
     287                 : };
     288                 : 
     289                 : typedef serializable<Elf_Shdr_Traits> Elf_Shdr;
     290                 : 
     291                 : class Elf {
     292                 : public:
     293                 :     Elf(std::ifstream &file);
     294                 :     ~Elf();
     295                 : 
     296                 :     /* index == -1 is treated as index == ehdr.e_shstrndx */
     297                 :     ElfSection *getSection(int index);
     298                 : 
     299                 :     ElfSection *getSectionAt(unsigned int offset);
     300                 : 
     301                 :     ElfSegment *getSegmentByType(unsigned int type);
     302                 : 
     303                 :     ElfDynamic_Section *getDynSection();
     304                 : 
     305                 :     void write(std::ofstream &file);
     306                 : 
     307                 :     char getClass();
     308                 :     char getData();
     309                 :     char getType();
     310                 :     char getMachine();
     311                 :     unsigned int getSize();
     312                 : private:
     313                 :     Elf_Ehdr *ehdr;
     314                 :     ElfLocation eh_entry;
     315                 :     ElfStrtab_Section *eh_shstrndx;
     316                 :     ElfSection **sections;
     317                 :     std::vector<ElfSegment *> segments;
     318                 :     ElfSection *shdr_section, *phdr_section;
     319                 :     /* Values used only during initialization */
     320                 :     Elf_Shdr **tmp_shdr;
     321                 :     std::ifstream *tmp_file;
     322                 : };
     323                 : 
     324                 : class ElfSection {
     325                 : public:
     326                 :     typedef union {
     327                 :         ElfSection *section;
     328                 :         int index;
     329                 :     } SectionInfo;
     330                 : 
     331                 :     ElfSection(Elf_Shdr &s, std::ifstream *file, Elf *parent);
     332                 : 
     333            3126 :     virtual ~ElfSection() {
     334            1154 :         delete[] data;
     335            1972 :     }
     336                 : 
     337            1678 :     const char *getName() { return name; }
     338           28268 :     unsigned int getType() { return shdr.sh_type; }
     339        12958836 :     unsigned int getFlags() { return shdr.sh_flags; }
     340                 :     unsigned int getAddr();
     341         6041958 :     unsigned int getSize() { return shdr.sh_size; }
     342            1140 :     unsigned int getAddrAlign() { return shdr.sh_addralign; }
     343              33 :     unsigned int getEntSize() { return shdr.sh_entsize; }
     344           31417 :     const char *getData() { return data; }
     345             184 :     ElfSection *getLink() { return link; }
     346              36 :     SectionInfo getInfo() { return info; }
     347                 : 
     348              21 :     void shrink(unsigned int newsize) {
     349              21 :         if (newsize < shdr.sh_size) {
     350              21 :             shdr.sh_size = newsize;
     351              21 :             if (next)
     352              21 :                 next->markDirty();
     353                 :         }
     354              21 :     }
     355                 : 
     356                 :     unsigned int getOffset();
     357                 :     int getIndex();
     358                 :     Elf_Shdr &getShdr();
     359                 : 
     360            2929 :     ElfSection *getNext() { return next; }
     361            1069 :     ElfSection *getPrevious() { return previous; }
     362                 : 
     363            2326 :     virtual bool isRelocatable() {
     364            2326 :         return ((getType() == SHT_SYMTAB) ||
     365            2247 :                 (getType() == SHT_STRTAB) ||
     366            2073 :                 (getType() == SHT_RELA) ||
     367            2073 :                 (getType() == SHT_HASH) ||
     368            2057 :                 (getType() == SHT_NOTE) ||
     369            2057 :                 (getType() == SHT_REL) ||
     370            1944 :                 (getType() == SHT_DYNSYM) ||
     371            1928 :                 (getType() == SHT_GNU_HASH) ||
     372            1928 :                 (getType() == SHT_GNU_verdef) ||
     373            1928 :                 (getType() == SHT_GNU_verneed) ||
     374            1912 :                 (getType() == SHT_GNU_versym) ||
     375            1896 :                 isInSegmentType(PT_INTERP)) &&
     376           24369 :                 (getFlags() & SHF_ALLOC);
     377                 :     }
     378                 : 
     379            1112 :     void insertAfter(ElfSection *section, bool dirty = true) {
     380            1112 :         if (previous != NULL)
     381               0 :             previous->next = next;
     382            1112 :         if (next != NULL)
     383               0 :             next->previous = previous;
     384            1112 :         previous = section;
     385            1112 :         if (section != NULL) {
     386            1112 :             next = section->next;
     387            1112 :             section->next = this;
     388                 :         } else
     389               0 :             next = NULL;
     390            1112 :         if (next != NULL)
     391              42 :             next->previous = this;
     392            1112 :         if (dirty)
     393              42 :             markDirty();
     394            1112 :     }
     395                 : 
     396            2352 :     void markDirty() {
     397            2352 :         if (link != NULL)
     398             261 :             shdr.sh_link = -1;
     399            2352 :         if (info.index)
     400             166 :             shdr.sh_info = -1;
     401            2352 :         shdr.sh_offset = -1;
     402            2352 :         if (isRelocatable())
     403             219 :             shdr.sh_addr = -1;
     404            2352 :         if (next)
     405            2273 :             next->markDirty();
     406            2352 :     }
     407                 : 
     408             111 :     virtual void serialize(std::ofstream &file, char ei_class, char ei_data)
     409                 :     {
     410             111 :         if (getType() == SHT_NOBITS)
     411               6 :             return;
     412             105 :         file.seekp(getOffset());
     413             105 :         file.write(data, getSize());
     414                 :     }
     415                 : 
     416                 : private:
     417                 :     friend class ElfSegment;
     418                 : 
     419             569 :     void addToSegment(ElfSegment *segment) {
     420             569 :         segments.push_back(segment);
     421             569 :     }
     422                 : 
     423              28 :     void removeFromSegment(ElfSegment *segment) {
     424              28 :         std::vector<ElfSegment *>::iterator i = std::find(segments.begin(), segments.end(), segment);
     425              28 :         segments.erase(i, i + 1);
     426              28 :     }
     427                 : 
     428                 :     bool isInSegmentType(unsigned int type);
     429                 : protected:
     430                 :     Elf_Shdr shdr;
     431                 :     char *data;
     432                 :     const char *name;
     433                 : private:
     434                 :     ElfSection *link;
     435                 :     SectionInfo info;
     436                 :     ElfSection *next, *previous;
     437                 :     int index;
     438                 :     std::vector<ElfSegment *> segments;
     439                 : };
     440                 : 
     441              94 : class ElfSegment {
     442                 : public:
     443                 :     ElfSegment(Elf_Phdr *phdr);
     444                 : 
     445            1452 :     unsigned int getType() { return type; }
     446              25 :     unsigned int getFlags() { return flags; }
     447             547 :     unsigned int getAlign() { return align; }
     448                 : 
     449             126 :     ElfSection *getFirstSection() { return sections.empty() ? NULL : sections.front(); }
     450              25 :     int getVPDiff() { return v_p_diff; }
     451                 :     unsigned int getFileSize();
     452                 :     unsigned int getMemSize();
     453                 :     unsigned int getOffset();
     454                 :     unsigned int getAddr();
     455                 : 
     456                 :     void addSection(ElfSection *section);
     457                 : 
     458              12 :     std::list<ElfSection *>::iterator begin() { return sections.begin(); }
     459             100 :     std::list<ElfSection *>::iterator end() { return sections.end(); }
     460                 : 
     461                 :     ElfSegment *splitBefore(ElfSection *section);
     462                 : private:
     463                 :     unsigned int type;
     464                 :     int v_p_diff; // Difference between physical and virtual address
     465                 :     unsigned int flags;
     466                 :     unsigned int align;
     467                 :     std::list<ElfSection *> sections;
     468                 :     // The following are only really used for PT_GNU_RELRO until something
     469                 :     // better is found.
     470                 :     unsigned int vaddr;
     471                 :     unsigned int filesz, memsz;
     472                 : };
     473                 : 
     474              84 : class Elf_Ehdr: public serializable<Elf_Ehdr_Traits>, public ElfSection {
     475                 : public:
     476                 :     Elf_Ehdr(std::ifstream &file, char ei_class, char ei_data);
     477               4 :     void serialize(std::ofstream &file, char ei_class, char ei_data)
     478                 :     {
     479               4 :         serializable<Elf_Ehdr_Traits>::serialize(file, ei_class, ei_data);
     480               4 :     }
     481                 : };
     482                 : 
     483                 : class Elf_Phdr: public serializable<Elf_Phdr_Traits> {
     484                 : public:
     485              29 :     Elf_Phdr() {};
     486              90 :     Elf_Phdr(std::ifstream &file, char ei_class, char ei_data)
     487              90 :     : serializable<Elf_Phdr_Traits>(file, ei_class, ei_data) {};
     488            3236 :     bool contains(ElfSection *section)
     489                 :     {
     490            3236 :         unsigned int size = section->getSize();
     491            3236 :         unsigned int addr = section->getAddr();
     492                 :         // This may be biased, but should work in most cases
     493            3236 :         if ((section->getFlags() & SHF_ALLOC) == 0)
     494            1202 :             return false;
     495                 :         // Special case for PT_DYNAMIC. Eventually, this should
     496                 :         // be better handled than special cases
     497            2034 :         if ((p_type == PT_DYNAMIC) && (section->getType() != SHT_DYNAMIC))
     498             452 :             return false;
     499                 :         // Special case for PT_TLS.
     500            1582 :         if ((p_type == PT_TLS) && !(section->getFlags() & SHF_TLS))
     501              45 :             return false;
     502                 :         return (addr >= p_vaddr) &&
     503            1537 :                (addr + size <= p_vaddr + p_memsz);
     504                 : 
     505                 :     }
     506                 : };
     507                 : 
     508                 : typedef serializable<Elf_Dyn_Traits> Elf_Dyn;
     509                 : 
     510               0 : struct Elf_DynValue {
     511                 :     unsigned int tag;
     512                 :     ElfValue *value;
     513                 : };
     514                 : 
     515                 : class ElfDynamic_Section: public ElfSection {
     516                 : public:
     517                 :     ElfDynamic_Section(Elf_Shdr &s, std::ifstream *file, Elf *parent);
     518                 :     ~ElfDynamic_Section();
     519                 : 
     520                 :     void serialize(std::ofstream &file, char ei_class, char ei_data);
     521                 : 
     522                 :     ElfValue *getValueForType(unsigned int tag);
     523                 :     ElfSection *getSectionForType(unsigned int tag);
     524                 :     void setValueForType(unsigned int tag, ElfValue *val);
     525                 : private:
     526                 :     std::vector<Elf_DynValue> dyns;
     527                 : };
     528                 : 
     529                 : typedef serializable<Elf_Sym_Traits> Elf_Sym;
     530                 : 
     531          406012 : struct Elf_SymValue {
     532                 :     const char *name;
     533                 :     unsigned char info;
     534                 :     unsigned char other;
     535                 :     ElfLocation value;
     536                 :     unsigned int size;
     537                 :     bool defined;
     538                 : };
     539                 : 
     540                 : #define STT(type) (1 << STT_ ##type)
     541                 : 
     542             126 : class ElfSymtab_Section: public ElfSection {
     543                 : public:
     544                 :     ElfSymtab_Section(Elf_Shdr &s, std::ifstream *file, Elf *parent);
     545                 : 
     546                 :     void serialize(std::ofstream &file, char ei_class, char ei_data);
     547                 : 
     548                 :     Elf_SymValue *lookup(const char *name, unsigned int type_filter = STT(OBJECT) | STT(FUNC));
     549                 : 
     550                 : //private: // Until we have a real API
     551                 :     std::vector<Elf_SymValue> syms;
     552                 : };
     553                 : 
     554               0 : class Elf_Rel: public serializable<Elf_Rel_Traits> {
     555                 : public:
     556          327223 :     Elf_Rel(std::ifstream &file, char ei_class, char ei_data)
     557          327223 :     : serializable<Elf_Rel_Traits>(file, ei_class, ei_data) {};
     558                 : 
     559                 :     static const unsigned int sh_type = SHT_REL;
     560                 :     static const unsigned int d_tag = DT_REL;
     561                 :     static const unsigned int d_tag_count = DT_RELCOUNT;
     562                 : };
     563                 : 
     564               0 : class Elf_Rela: public serializable<Elf_Rela_Traits> {
     565                 : public:
     566               0 :     Elf_Rela(std::ifstream &file, char ei_class, char ei_data)
     567               0 :     : serializable<Elf_Rela_Traits>(file, ei_class, ei_data) {};
     568                 : 
     569                 :     static const unsigned int sh_type = SHT_RELA;
     570                 :     static const unsigned int d_tag = DT_RELA;
     571                 :     static const unsigned int d_tag_count = DT_RELACOUNT;
     572                 : };
     573                 : 
     574                 : template <class Rel>
     575             126 : class ElfRel_Section: public ElfSection {
     576                 : public:
     577              63 :     ElfRel_Section(Elf_Shdr &s, std::ifstream *file, Elf *parent)
     578              63 :     : ElfSection(s, file, parent)
     579                 :     {
     580              63 :         int pos = file->tellg();
     581              63 :         file->seekg(shdr.sh_offset);
     582          327286 :         for (unsigned int i = 0; i < s.sh_size / s.sh_entsize; i++) {
     583          327223 :             Rel r(*file, parent->getClass(), parent->getData());
     584          327223 :             rels.push_back(r);
     585                 :         }
     586              63 :         file->seekg(pos);
     587              63 :     }
     588                 : 
     589               8 :     void serialize(std::ofstream &file, char ei_class, char ei_data)
     590                 :     {
     591           15577 :         for (typename std::vector<Rel>::iterator i = rels.begin();
     592                 :              i != rels.end(); ++i)
     593           15569 :             (*i).serialize(file, ei_class, ei_data);
     594               8 :     }
     595                 : //private: // Until we have a real API
     596                 :     std::vector<Rel> rels;
     597                 : };
     598                 : 
     599                 : class ElfStrtab_Section: public ElfSection {
     600                 : public:
     601             105 :     ElfStrtab_Section(Elf_Shdr &s, std::ifstream *file, Elf *parent)
     602             105 :     : ElfSection(s, file, parent)
     603                 :     {
     604             105 :         table.push_back(table_storage(data, shdr.sh_size));
     605             105 :     }
     606                 : 
     607             210 :     ~ElfStrtab_Section()
     608             210 :     {
     609             218 :         for (std::vector<table_storage>::iterator t = table.begin() + 1;
     610             109 :              t != table.end(); t++)
     611               4 :             delete[] t->buf;
     612             210 :     }
     613                 : 
     614                 :     const char *getStr(unsigned int index);
     615                 : 
     616                 :     const char *getStr(const char *string);
     617                 : 
     618                 :     unsigned int getStrIndex(const char *string);
     619                 : 
     620                 :     void serialize(std::ofstream &file, char ei_class, char ei_data);
     621                 : private:
     622               0 :     struct table_storage {
     623                 :         unsigned int size, used;
     624                 :         char *buf;
     625                 : 
     626               4 :         table_storage(): size(4096), used(0), buf(new char[4096]) {}
     627             105 :         table_storage(const char *data, unsigned int sz)
     628             105 :         : size(sz), used(sz), buf(const_cast<char *>(data)) {}
     629                 :     };
     630                 :     std::vector<table_storage> table;
     631                 : };
     632                 : 
     633          733985 : inline char Elf::getClass() {
     634          733985 :     return ehdr->e_ident[EI_CLASS];
     635                 : }
     636                 : 
     637          733922 : inline char Elf::getData() {
     638          733922 :     return ehdr->e_ident[EI_DATA];
     639                 : }
     640                 : 
     641              42 : inline char Elf::getType() {
     642              42 :     return ehdr->e_type;
     643                 : }
     644                 : 
     645             108 : inline char Elf::getMachine() {
     646             108 :     return ehdr->e_machine;
     647                 : }
     648                 : 
     649              42 : inline unsigned int Elf::getSize() {
     650                 :     ElfSection *section;
     651             168 :     for (section = shdr_section /* It's usually not far from the end */;
     652             126 :         section->getNext() != NULL; section = section->getNext());
     653              42 :     return section->getOffset() + section->getSize();
     654                 : }
     655                 : 
     656            1896 : inline bool ElfSection::isInSegmentType(unsigned int type) {
     657            3082 :     for (std::vector<ElfSegment *>::iterator seg = segments.begin(); seg != segments.end(); seg++)
     658            1186 :         if ((*seg)->getType() == type)
     659               0 :             return true;
     660            1896 :     return false;
     661                 : }
     662                 : 
     663          405970 : inline ElfLocation::ElfLocation(ElfSection *section, unsigned int off, enum position pos)
     664          405970 : : section(section) {
     665          405970 :     if ((pos == ABSOLUTE) && section)
     666          392843 :         offset = off - section->getAddr();
     667                 :     else
     668           13127 :         offset = off;
     669          405970 : }
     670                 : 
     671             239 : inline ElfLocation::ElfLocation(unsigned int location, Elf *elf) {
     672             239 :     section = elf->getSectionAt(location);
     673             239 :     offset = location - (section ? section->getAddr() : 0);
     674             239 : }
     675                 : 
     676          382063 : inline unsigned int ElfLocation::getValue() {
     677          382063 :     return (section ? section->getAddr() : 0) + offset;
     678                 : }
     679                 : 
     680              12 : inline unsigned int ElfSize::getValue() {
     681              12 :     return section->getSize();
     682                 : }
     683                 : 
     684               8 : inline unsigned int ElfEntSize::getValue() {
     685               8 :     return section->getEntSize();
     686                 : }

Generated by: LCOV version 1.7