LCOV - code coverage report
Current view: directory - build/unix/elfhack - elf.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 557 490 88.0 %
Date: 2012-06-02 Functions: 98 49 50.0 %

       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                 : #undef NDEBUG
      39                 : #include <cstring>
      40                 : #include <assert.h>
      41                 : #include "elfxx.h"
      42                 : 
      43                 : template <class endian, typename R, typename T>
      44              46 : void Elf_Ehdr_Traits::swap(T &t, R &r)
      45                 : {
      46              46 :     memcpy(r.e_ident, t.e_ident, sizeof(r.e_ident));
      47              46 :     r.e_type = endian::swap(t.e_type);
      48              46 :     r.e_machine = endian::swap(t.e_machine);
      49              46 :     r.e_version = endian::swap(t.e_version);
      50              46 :     r.e_entry = endian::swap(t.e_entry);
      51              46 :     r.e_phoff = endian::swap(t.e_phoff);
      52              46 :     r.e_shoff = endian::swap(t.e_shoff);
      53              46 :     r.e_flags = endian::swap(t.e_flags);
      54              46 :     r.e_ehsize = endian::swap(t.e_ehsize);
      55              46 :     r.e_phentsize = endian::swap(t.e_phentsize);
      56              46 :     r.e_phnum = endian::swap(t.e_phnum);
      57              46 :     r.e_shentsize = endian::swap(t.e_shentsize);
      58              46 :     r.e_shnum = endian::swap(t.e_shnum);
      59              46 :     r.e_shstrndx = endian::swap(t.e_shstrndx);
      60              46 : }
      61                 : 
      62                 : template <class endian, typename R, typename T>
      63             115 : void Elf_Phdr_Traits::swap(T &t, R &r)
      64                 : {
      65             115 :     r.p_type = endian::swap(t.p_type);
      66             115 :     r.p_offset = endian::swap(t.p_offset);
      67             115 :     r.p_vaddr = endian::swap(t.p_vaddr);
      68             115 :     r.p_paddr = endian::swap(t.p_paddr);
      69             115 :     r.p_filesz = endian::swap(t.p_filesz);
      70             115 :     r.p_memsz = endian::swap(t.p_memsz);
      71             115 :     r.p_flags = endian::swap(t.p_flags);
      72             115 :     r.p_align = endian::swap(t.p_align);
      73             115 : }
      74                 : 
      75                 : template <class endian, typename R, typename T>
      76            1179 : void Elf_Shdr_Traits::swap(T &t, R &r)
      77                 : {
      78            1179 :     r.sh_name = endian::swap(t.sh_name);
      79            1179 :     r.sh_type = endian::swap(t.sh_type);
      80            1179 :     r.sh_flags = endian::swap(t.sh_flags);
      81            1179 :     r.sh_addr = endian::swap(t.sh_addr);
      82            1179 :     r.sh_offset = endian::swap(t.sh_offset);
      83            1179 :     r.sh_size = endian::swap(t.sh_size);
      84            1179 :     r.sh_link = endian::swap(t.sh_link);
      85            1179 :     r.sh_info = endian::swap(t.sh_info);
      86            1179 :     r.sh_addralign = endian::swap(t.sh_addralign);
      87            1179 :     r.sh_entsize = endian::swap(t.sh_entsize);
      88            1179 : }
      89                 : 
      90                 : template <class endian, typename R, typename T>
      91             895 : void Elf_Dyn_Traits::swap(T &t, R &r)
      92                 : {
      93             895 :     r.d_tag = endian::swap(t.d_tag);
      94             895 :     r.d_un.d_val = endian::swap(t.d_un.d_val);
      95             895 : }
      96                 : 
      97                 : template <class endian, typename R, typename T>
      98          787943 : void Elf_Sym_Traits::swap(T &t, R &r)
      99                 : {
     100          787943 :     r.st_name = endian::swap(t.st_name);
     101          787943 :     r.st_value = endian::swap(t.st_value);
     102          787943 :     r.st_size = endian::swap(t.st_size);
     103          787943 :     r.st_info = t.st_info;
     104          787943 :     r.st_other = t.st_other;
     105          787943 :     r.st_shndx = endian::swap(t.st_shndx);
     106          787943 : }
     107                 : 
     108                 : template <class endian>
     109                 : struct _Rel_info {
     110          342792 :     static inline void swap(Elf32_Word &t, Elf32_Word &r) { r = endian::swap(t); }
     111                 :     static inline void swap(Elf64_Xword &t, Elf64_Xword &r) { r = endian::swap(t); }
     112               0 :     static inline void swap(Elf64_Xword &t, Elf32_Word &r) {
     113               0 :         r = endian::swap(ELF32_R_INFO(ELF64_R_SYM(t), ELF64_R_TYPE(t)));
     114               0 :     }
     115               0 :     static inline void swap(Elf32_Word &t, Elf64_Xword &r) {
     116               0 :         r = endian::swap(ELF64_R_INFO(ELF32_R_SYM(t), ELF32_R_TYPE(t)));
     117               0 :     }
     118                 : };
     119                 : 
     120                 : template <class endian, typename R, typename T>
     121          342792 : void Elf_Rel_Traits::swap(T &t, R &r)
     122                 : {
     123          342792 :     r.r_offset = endian::swap(t.r_offset);
     124          342792 :     _Rel_info<endian>::swap(t.r_info, r.r_info);
     125          342792 : }
     126                 : 
     127                 : template <class endian, typename R, typename T>
     128               0 : void Elf_Rela_Traits::swap(T &t, R &r)
     129                 : {
     130               0 :     r.r_offset = endian::swap(t.r_offset);
     131               0 :     _Rel_info<endian>::swap(t.r_info, r.r_info);
     132               0 :     r.r_addend = endian::swap(t.r_addend);
     133               0 : }
     134                 : 
     135                 : static const Elf32_Shdr null32_section =
     136                 :     { 0, SHT_NULL, 0, 0, 0, 0, SHN_UNDEF, 0, 0, 0 };
     137                 : 
     138               2 : Elf_Shdr null_section(null32_section);
     139                 : 
     140              42 : Elf_Ehdr::Elf_Ehdr(std::ifstream &file, char ei_class, char ei_data)
     141                 : : serializable<Elf_Ehdr_Traits>(file, ei_class, ei_data),
     142              42 :   ElfSection(null_section, NULL, NULL)
     143                 : {
     144              42 :     shdr.sh_size = Elf_Ehdr::size(ei_class);
     145              42 : }
     146                 : 
     147              42 : Elf::Elf(std::ifstream &file)
     148                 : {
     149              42 :     if (!file.is_open())
     150               0 :         throw std::runtime_error("Error opening file");
     151                 : 
     152              42 :     file.exceptions(std::ifstream::eofbit | std::ifstream::failbit | std::ifstream::badbit);
     153                 :     // Read ELF magic number and identification information
     154                 :     char e_ident[EI_VERSION];
     155              42 :     file.seekg(0);
     156              42 :     file.read(e_ident, sizeof(e_ident));
     157              42 :     file.seekg(0);
     158              42 :     ehdr = new Elf_Ehdr(file, e_ident[EI_CLASS], e_ident[EI_DATA]);
     159                 : 
     160                 :     // ELFOSABI_LINUX is kept unsupported because I haven't looked whether
     161                 :     // STB_GNU_UNIQUE or STT_GNU_IFUNC would need special casing.
     162              42 :     if ((ehdr->e_ident[EI_OSABI] != ELFOSABI_NONE) && (ehdr->e_ident[EI_ABIVERSION] != 0))
     163               0 :         throw std::runtime_error("unsupported ELF ABI");
     164                 : 
     165              42 :     if (ehdr->e_version != 1)
     166               0 :         throw std::runtime_error("unsupported ELF version");
     167                 : 
     168                 :     // Sanity checks
     169              42 :     if (ehdr->e_shnum == 0)
     170               0 :         throw std::runtime_error("sstripped ELF files aren't supported");
     171                 : 
     172              42 :     if (ehdr->e_ehsize != Elf_Ehdr::size(e_ident[EI_CLASS]))
     173               0 :         throw std::runtime_error("unsupported ELF inconsistency: ehdr.e_ehsize != sizeof(ehdr)");
     174                 : 
     175              42 :     if (ehdr->e_shentsize != Elf_Shdr::size(e_ident[EI_CLASS]))
     176               0 :         throw std::runtime_error("unsupported ELF inconsistency: ehdr.e_shentsize != sizeof(shdr)");
     177                 : 
     178              42 :     if (ehdr->e_phnum == 0) {
     179              21 :         if (ehdr->e_phoff != 0)
     180               0 :             throw std::runtime_error("unsupported ELF inconsistency: e_phnum == 0 && e_phoff != 0");
     181              21 :         if (ehdr->e_phentsize != 0)
     182               0 :             throw std::runtime_error("unsupported ELF inconsistency: e_phnum == 0 && e_phentsize != 0");
     183              21 :     } else if (ehdr->e_phoff != ehdr->e_ehsize)
     184               0 :         throw std::runtime_error("unsupported ELF inconsistency: ehdr->e_phoff != ehdr->e_ehsize");
     185              21 :     else if (ehdr->e_phentsize != Elf_Phdr::size(e_ident[EI_CLASS]))
     186               0 :         throw std::runtime_error("unsupported ELF inconsistency: ehdr->e_phentsize != sizeof(phdr)");
     187                 : 
     188                 :     // Read section headers
     189              42 :     Elf_Shdr **shdr = new Elf_Shdr *[ehdr->e_shnum];
     190              42 :     file.seekg(ehdr->e_shoff);
     191            1070 :     for (int i = 0; i < ehdr->e_shnum; i++)
     192            1028 :         shdr[i] = new Elf_Shdr(file, e_ident[EI_CLASS], e_ident[EI_DATA]);
     193                 : 
     194                 :     // Sanity check in section header for index 0
     195             378 :     if ((shdr[0]->sh_name != 0) || (shdr[0]->sh_type != SHT_NULL) ||
     196              84 :         (shdr[0]->sh_flags != 0) || (shdr[0]->sh_addr != 0) ||
     197              84 :         (shdr[0]->sh_offset != 0) || (shdr[0]->sh_size != 0) ||
     198              84 :         (shdr[0]->sh_link != SHN_UNDEF) || (shdr[0]->sh_info != 0) ||
     199              84 :         (shdr[0]->sh_addralign != 0) || (shdr[0]->sh_entsize != 0))
     200               0 :         throw std::runtime_error("Section header for index 0 contains unsupported values");
     201                 : 
     202              42 :     if ((shdr[ehdr->e_shstrndx]->sh_link != 0) || (shdr[ehdr->e_shstrndx]->sh_info != 0))
     203               0 :         throw std::runtime_error("unsupported ELF content: string table with sh_link != 0 || sh_info != 0");
     204                 : 
     205                 :     // Store these temporarily
     206              42 :     tmp_shdr = shdr;
     207              42 :     tmp_file = &file;
     208                 : 
     209                 :     // Fill sections list
     210              42 :     sections = new ElfSection *[ehdr->e_shnum];
     211            1070 :     for (int i = 0; i < ehdr->e_shnum; i++)
     212            1028 :         sections[i] = NULL;
     213            1028 :     for (int i = 1; i < ehdr->e_shnum; i++) {
     214             986 :         if (sections[i] != NULL)
     215             402 :             continue;
     216             584 :         getSection(i);
     217                 :     }
     218              42 :     Elf_Shdr s;
     219              42 :     s.sh_name = 0;
     220              42 :     s.sh_type = SHT_NULL;
     221              42 :     s.sh_flags = 0;
     222              42 :     s.sh_addr = 0;
     223              42 :     s.sh_offset = ehdr->e_shoff;
     224              42 :     s.sh_entsize = Elf_Shdr::size(e_ident[EI_CLASS]);
     225              42 :     s.sh_size = s.sh_entsize * ehdr->e_shnum;
     226              42 :     s.sh_link = 0;
     227              42 :     s.sh_info = 0;
     228              42 :     s.sh_addralign = (e_ident[EI_CLASS] == ELFCLASS32) ? 4 : 8;
     229              42 :     shdr_section = new ElfSection(s, NULL, NULL);
     230                 : 
     231                 :     // Fake section for program headers
     232              42 :     s.sh_offset = ehdr->e_phoff;
     233              42 :     s.sh_addr = ehdr->e_phoff;
     234              42 :     s.sh_entsize = Elf_Phdr::size(e_ident[EI_CLASS]);
     235              42 :     s.sh_size = s.sh_entsize * ehdr->e_phnum;
     236              42 :     phdr_section = new ElfSection(s, NULL, NULL);
     237                 : 
     238              42 :     phdr_section->insertAfter(ehdr, false);
     239                 : 
     240              42 :     sections[1]->insertAfter(phdr_section, false);
     241             986 :     for (int i = 2; i < ehdr->e_shnum; i++) {
     242                 :         // TODO: this should be done in a better way
     243             944 :         if ((shdr_section->getPrevious() == NULL) && (shdr[i]->sh_offset > ehdr->e_shoff)) {
     244              42 :             shdr_section->insertAfter(sections[i - 1], false);
     245              42 :             sections[i]->insertAfter(shdr_section, false);
     246                 :         } else
     247             902 :             sections[i]->insertAfter(sections[i - 1], false);
     248                 :     }
     249              42 :     if (shdr_section->getPrevious() == NULL)
     250               0 :         shdr_section->insertAfter(sections[ehdr->e_shnum - 1], false);
     251                 : 
     252              42 :     tmp_file = NULL;
     253              42 :     tmp_shdr = NULL;
     254            1070 :     for (int i = 0; i < ehdr->e_shnum; i++)
     255            1028 :         delete shdr[i];
     256              42 :     delete[] shdr;
     257                 : 
     258              42 :     eh_shstrndx = (ElfStrtab_Section *)sections[ehdr->e_shstrndx];
     259                 : 
     260                 :     // Skip reading program headers if there aren't any
     261              42 :     if (ehdr->e_phnum == 0)
     262              21 :         return;
     263                 : 
     264                 :     // Read program headers
     265              21 :     file.seekg(ehdr->e_phoff);
     266             111 :     for (int i = 0; i < ehdr->e_phnum; i++) {
     267              90 :         Elf_Phdr phdr(file, e_ident[EI_CLASS], e_ident[EI_DATA]);
     268              90 :         if (phdr.p_type == PT_LOAD) {
     269                 :             // Default alignment for PT_LOAD on x86-64 prevents elfhack from
     270                 :             // doing anything useful. However, the system doesn't actually
     271                 :             // require such a big alignment, so in order for elfhack to work
     272                 :             // efficiently, reduce alignment when it's originally the default
     273                 :             // one.
     274              42 :             if ((ehdr->e_machine == EM_X86_64) && (phdr.p_align == 0x200000))
     275               0 :               phdr.p_align = 0x1000;
     276                 :         }
     277              90 :         ElfSegment *segment = new ElfSegment(&phdr);
     278                 :         // Some segments aren't entirely filled (if at all) by sections
     279                 :         // For those, we use fake sections
     280              90 :         if ((phdr.p_type == PT_LOAD) && (phdr.p_offset == 0)) {
     281                 :             // Use a fake section for ehdr and phdr
     282              21 :             ehdr->getShdr().sh_addr = phdr.p_vaddr;
     283              21 :             phdr_section->getShdr().sh_addr += phdr.p_vaddr;
     284              21 :             segment->addSection(ehdr);
     285              21 :             segment->addSection(phdr_section);
     286                 :         }
     287              90 :         if (phdr.p_type == PT_PHDR)
     288               0 :             segment->addSection(phdr_section);
     289            3326 :         for (int j = 1; j < ehdr->e_shnum; j++)
     290            3236 :             if (phdr.contains(sections[j]))
     291             499 :                 segment->addSection(sections[j]);
     292                 :         // Make sure that our view of segments corresponds to the original
     293                 :         // ELF file.
     294              90 :         assert(segment->getFileSize() == phdr.p_filesz);
     295              90 :         assert(segment->getMemSize() == phdr.p_memsz);
     296              90 :         segments.push_back(segment);
     297                 :     }
     298                 : 
     299              21 :     new (&eh_entry) ElfLocation(ehdr->e_entry, this);
     300                 : }
     301                 : 
     302              84 : Elf::~Elf()
     303                 : {
     304             136 :     for (std::vector<ElfSegment *>::iterator seg = segments.begin(); seg != segments.end(); seg++)
     305              94 :         delete *seg;
     306              42 :     delete[] sections;
     307              42 :     ElfSection *section = ehdr;
     308            1238 :     while (section != NULL) {
     309            1154 :         ElfSection *next = section->getNext();
     310            1154 :         delete section;
     311            1154 :         section = next;
     312                 :     }
     313              42 : }
     314                 : 
     315                 : // TODO: This shouldn't fail after inserting sections
     316         6740860 : ElfSection *Elf::getSection(int index)
     317                 : {
     318         6740860 :     if ((index < -1) || (index >= ehdr->e_shnum))
     319               0 :         throw std::runtime_error("Section index out of bounds");
     320         6740860 :     if (index == -1)
     321             986 :         index = ehdr->e_shstrndx; // TODO: should be fixed to use the actual current number
     322                 :     // Special case: the section at index 0 is void
     323         6740860 :     if (index == 0)
     324            9115 :         return NULL;
     325                 :     // Infinite recursion guard
     326         6731745 :     if (sections[index] == (ElfSection *)this)
     327              84 :         return NULL;
     328         6731661 :     if (sections[index] == NULL) {
     329             986 :         sections[index] = (ElfSection *)this;
     330             986 :         switch (tmp_shdr[index]->sh_type) {
     331                 :         case SHT_DYNAMIC:
     332              21 :             sections[index] = new ElfDynamic_Section(*tmp_shdr[index], tmp_file, this);
     333              21 :             break;
     334                 :         case SHT_REL:
     335              63 :             sections[index] = new ElfRel_Section<Elf_Rel>(*tmp_shdr[index], tmp_file, this);
     336              63 :             break;
     337                 :         case SHT_RELA:
     338               0 :             sections[index] = new ElfRel_Section<Elf_Rela>(*tmp_shdr[index], tmp_file, this);
     339               0 :             break;
     340                 :         case SHT_DYNSYM:
     341                 :         case SHT_SYMTAB:
     342              63 :             sections[index] = new ElfSymtab_Section(*tmp_shdr[index], tmp_file, this);
     343              63 :             break;
     344                 :         case SHT_STRTAB:
     345             105 :             sections[index] = new ElfStrtab_Section(*tmp_shdr[index], tmp_file, this);
     346             105 :             break;
     347                 :         default:
     348             734 :             sections[index] = new ElfSection(*tmp_shdr[index], tmp_file, this);
     349                 :         }
     350                 :     }
     351         6731661 :     return sections[index];
     352                 : }
     353                 : 
     354          311842 : ElfSection *Elf::getSectionAt(unsigned int offset)
     355                 : {
     356         6336980 :     for (int i = 1; i < ehdr->e_shnum; i++) {
     357         6336980 :         ElfSection *section = getSection(i);
     358        18411486 :         if ((section != NULL) && (section->getFlags() & SHF_ALLOC) && !(section->getFlags() & SHF_TLS) &&
     359        12074506 :             (offset >= section->getAddr()) && (offset < section->getAddr() + section->getSize()))
     360          311842 :             return section;
     361                 :     }
     362               0 :     return NULL;
     363                 : }
     364                 : 
     365              21 : ElfSegment *Elf::getSegmentByType(unsigned int type)
     366                 : {
     367             111 :     for (std::vector<ElfSegment *>::iterator seg = segments.begin(); seg != segments.end(); seg++)
     368              90 :         if ((*seg)->getType() == type)
     369               0 :             return *seg;
     370              21 :     return NULL;
     371                 : }
     372                 : 
     373              42 : ElfDynamic_Section *Elf::getDynSection()
     374                 : {
     375             126 :     for (std::vector<ElfSegment *>::iterator seg = segments.begin(); seg != segments.end(); seg++)
     376             168 :         if (((*seg)->getType() == PT_DYNAMIC) && ((*seg)->getFirstSection() != NULL) &&
     377              42 :             (*seg)->getFirstSection()->getType() == SHT_DYNAMIC)
     378              42 :             return (ElfDynamic_Section *)(*seg)->getFirstSection();
     379                 : 
     380               0 :     return NULL;
     381                 : }
     382                 : 
     383               4 : void Elf::write(std::ofstream &file)
     384                 : {
     385                 :     // fixup section headers sh_name; TODO: that should be done by sections
     386                 :     // themselves
     387             163 :     for (ElfSection *section = ehdr; section != NULL; section = section->getNext()) {
     388             159 :         if (section->getIndex() == 0)
     389              12 :             continue;
     390                 :         else
     391             147 :             ehdr->e_shnum = section->getIndex() + 1;
     392             147 :         section->getShdr().sh_name = eh_shstrndx->getStrIndex(section->getName());
     393                 :     }
     394               4 :     ehdr->markDirty();
     395                 :     // Adjust PT_LOAD segments
     396               4 :     int i = 0;
     397              29 :     for (std::vector<ElfSegment *>::iterator seg = segments.begin(); seg != segments.end(); seg++, i++) {
     398              25 :         if ((*seg)->getType() == PT_LOAD) {
     399              12 :             std::list<ElfSection *>::iterator it = (*seg)->begin();
     400             100 :             for (ElfSection *last = *(it++); it != (*seg)->end(); last = *(it++)) {
     401             268 :                if (((*it)->getType() != SHT_NOBITS) &&
     402             176 :                    ((*it)->getAddr() - last->getAddr()) != ((*it)->getOffset() - last->getOffset())) {
     403               4 :                    std::vector<ElfSegment *>::iterator next = seg;
     404               4 :                    segments.insert(++next, (*seg)->splitBefore(*it));
     405               4 :                    seg = segments.begin() + i;
     406               4 :                    break;
     407                 :                }
     408                 :            }
     409                 :         }
     410                 :     }
     411                 :     // fixup ehdr before writing
     412               4 :     if (ehdr->e_phnum != segments.size()) {
     413               4 :         ehdr->e_phnum = segments.size();
     414               4 :         phdr_section->getShdr().sh_size = segments.size() * Elf_Phdr::size(ehdr->e_ident[EI_CLASS]);
     415               4 :         phdr_section->getNext()->markDirty();
     416                 :     }
     417                 :     // fixup shdr before writing
     418               4 :     if (ehdr->e_shnum != shdr_section->getSize() / shdr_section->getEntSize())
     419               4 :         shdr_section->getShdr().sh_size = ehdr->e_shnum * Elf_Shdr::size(ehdr->e_ident[EI_CLASS]);
     420               4 :     ehdr->e_shoff = shdr_section->getOffset();
     421               4 :     ehdr->e_entry = eh_entry.getValue();
     422               4 :     ehdr->e_shstrndx = eh_shstrndx->getIndex();
     423             163 :     for (ElfSection *section = ehdr;
     424                 :          section != NULL; section = section->getNext()) {
     425             159 :         file.seekp(section->getOffset());
     426             159 :         if (section == phdr_section) {
     427              29 :             for (std::vector<ElfSegment *>::iterator seg = segments.begin(); seg != segments.end(); seg++) {
     428              25 :                 Elf_Phdr phdr;
     429              25 :                 phdr.p_type = (*seg)->getType();
     430              25 :                 phdr.p_flags = (*seg)->getFlags();
     431              25 :                 phdr.p_offset = (*seg)->getOffset();
     432              25 :                 phdr.p_vaddr = (*seg)->getAddr();
     433              25 :                 phdr.p_paddr = phdr.p_vaddr + (*seg)->getVPDiff();
     434              25 :                 phdr.p_filesz = (*seg)->getFileSize();
     435              25 :                 phdr.p_memsz = (*seg)->getMemSize();
     436              25 :                 phdr.p_align = (*seg)->getAlign();
     437              25 :                 phdr.serialize(file, ehdr->e_ident[EI_CLASS], ehdr->e_ident[EI_DATA]);
     438                 :             }
     439             155 :         } else if (section == shdr_section) {
     440               4 :             null_section.serialize(file, ehdr->e_ident[EI_CLASS], ehdr->e_ident[EI_DATA]);
     441             163 :             for (ElfSection *sec = ehdr; sec!= NULL; sec = sec->getNext()) {
     442             159 :                 if (sec->getType() != SHT_NULL)
     443             147 :                     sec->getShdr().serialize(file, ehdr->e_ident[EI_CLASS], ehdr->e_ident[EI_DATA]);
     444                 :             }
     445                 :         } else
     446             151 :            section->serialize(file, ehdr->e_ident[EI_CLASS], ehdr->e_ident[EI_DATA]);
     447                 :     }
     448               4 : }
     449                 : 
     450            1154 : ElfSection::ElfSection(Elf_Shdr &s, std::ifstream *file, Elf *parent)
     451                 : : shdr(s),
     452             239 :   link(shdr.sh_link == SHN_UNDEF ? NULL : parent->getSection(shdr.sh_link)),
     453            1393 :   next(NULL), previous(NULL), index(-1)
     454                 : {
     455            1154 :     if ((file == NULL) || (shdr.sh_type == SHT_NULL) || (shdr.sh_type == SHT_NOBITS))
     456             212 :         data = NULL;
     457                 :     else {
     458             942 :         data = new char[shdr.sh_size];
     459             942 :         int pos = file->tellg();
     460             942 :         file->seekg(shdr.sh_offset);
     461             942 :         file->read(data, shdr.sh_size);
     462             942 :         file->seekg(pos);
     463                 :     }
     464            1154 :     if (shdr.sh_name == 0)
     465             168 :         name = NULL;
     466                 :     else {
     467             986 :         ElfStrtab_Section *strtab = (ElfStrtab_Section *) parent->getSection(-1);
     468                 :         // Special case (see elfgeneric.cpp): if strtab is NULL, the
     469                 :         // section being created is the strtab.
     470             986 :         if (strtab == NULL)
     471              42 :             name = &data[shdr.sh_name];
     472                 :         else
     473             944 :             name = strtab->getStr(shdr.sh_name);
     474                 :     }
     475                 :     // Only SHT_REL/SHT_RELA sections use sh_info to store a section
     476                 :     // number.
     477            1154 :     if ((shdr.sh_type == SHT_REL) || (shdr.sh_type == SHT_RELA))
     478              63 :         info.section = shdr.sh_info ? parent->getSection(shdr.sh_info) : NULL;
     479                 :     else
     480            1091 :         info.index = shdr.sh_info;
     481            1154 : }
     482                 : 
     483        12885272 : unsigned int ElfSection::getAddr()
     484                 : {
     485        12885272 :     if (shdr.sh_addr != (Elf32_Word)-1)
     486        12885140 :         return shdr.sh_addr;
     487                 : 
     488                 :     // It should be safe to adjust sh_addr for all allocated sections that
     489                 :     // are neither SHT_NOBITS nor SHT_PROGBITS
     490             132 :     if ((previous != NULL) && isRelocatable()) {
     491             132 :         unsigned int addr = previous->getAddr();
     492             132 :         if (previous->getType() != SHT_NOBITS)
     493             132 :             addr += previous->getSize();
     494                 : 
     495             132 :         if (addr & (getAddrAlign() - 1))
     496              58 :             addr = (addr | (getAddrAlign() - 1)) + 1;
     497                 : 
     498             132 :         return (shdr.sh_addr = addr);
     499                 :     }
     500               0 :     return shdr.sh_addr;
     501                 : }
     502                 : 
     503            2343 : unsigned int ElfSection::getOffset()
     504                 : {
     505            2343 :     if (shdr.sh_offset != (Elf32_Word)-1)
     506            1481 :         return shdr.sh_offset;
     507                 : 
     508             862 :     if (previous == NULL)
     509               4 :         return (shdr.sh_offset = 0);
     510                 : 
     511             858 :     unsigned int offset = previous->getOffset();
     512             858 :     if (previous->getType() != SHT_NOBITS)
     513             830 :         offset += previous->getSize();
     514                 : 
     515             858 :     Elf32_Word align = 0x1000;
     516            1376 :     for (std::vector<ElfSegment *>::iterator seg = segments.begin(); seg != segments.end(); seg++)
     517             518 :         align = std::max(align, (*seg)->getAlign());
     518                 : 
     519             858 :     Elf32_Word mask = align - 1;
     520                 :     // SHF_TLS is used for .tbss which is some kind of special case.
     521             858 :     if (((getType() != SHT_NOBITS) || (getFlags() & SHF_TLS)) && (getFlags() & SHF_ALLOC)) {
     522             511 :         if ((getAddr() & mask) < (offset & mask))
     523              24 :             offset = (offset | mask) + (getAddr() & mask) + 1;
     524                 :         else
     525             487 :             offset = (offset & ~mask) + (getAddr() & mask);
     526                 :     }
     527             858 :     if ((getType() != SHT_NOBITS) && (offset & (getAddrAlign() - 1)))
     528              36 :         offset = (offset | (getAddrAlign() - 1)) + 1;
     529                 : 
     530                 :     // Two subsequent sections can't be mapped in the same page in memory
     531                 :     // if they aren't in the same 4K block on disk.
     532             858 :     if ((getType() != SHT_NOBITS) && getAddr()) {
     533             815 :         if (((offset >> 12) != (previous->getOffset() >> 12)) &&
     534             306 :             ((getAddr() >> 12) == (previous->getAddr() >> 12)))
     535               0 :             throw std::runtime_error("Moving section would require overlapping segments");
     536                 :     }
     537                 : 
     538             858 :     return (shdr.sh_offset = offset);
     539                 : }
     540                 : 
     541          374321 : int ElfSection::getIndex()
     542                 : {
     543          374321 :     if (index != -1)
     544          374036 :         return index;
     545             285 :     if (getType() == SHT_NULL)
     546              12 :         return (index = 0);
     547                 :     ElfSection *reference;
     548             273 :     for (reference = previous; (reference != NULL) && (reference->getType() == SHT_NULL); reference = reference->getPrevious());
     549             273 :     if (reference == NULL)
     550              25 :         return (index = 1);
     551             248 :     return (index = reference->getIndex() + 1);
     552                 : }
     553                 : 
     554             415 : Elf_Shdr &ElfSection::getShdr()
     555                 : {
     556             415 :     getOffset();
     557             415 :     if (shdr.sh_link == (Elf32_Word)-1)
     558              44 :         shdr.sh_link = getLink() ? getLink()->getIndex() : 0;
     559             415 :     if (shdr.sh_info == (Elf32_Word)-1)
     560              40 :         shdr.sh_info = ((getType() == SHT_REL) || (getType() == SHT_RELA)) ?
     561               8 :                        (getInfo().section ? getInfo().section->getIndex() : 0) :
     562              48 :                        getInfo().index;
     563                 : 
     564             415 :     return shdr;
     565                 : }
     566                 : 
     567              94 : ElfSegment::ElfSegment(Elf_Phdr *phdr)
     568                 : : type(phdr->p_type), v_p_diff(phdr->p_paddr - phdr->p_vaddr),
     569                 :   flags(phdr->p_flags), align(phdr->p_align), vaddr(phdr->p_vaddr),
     570              94 :   filesz(phdr->p_filesz), memsz(phdr->p_memsz) {}
     571                 : 
     572             569 : void ElfSegment::addSection(ElfSection *section)
     573                 : {
     574                 :     // Make sure all sections in PT_GNU_RELRO won't be moved by elfhack
     575             569 :     assert(!((type == PT_GNU_RELRO) && (section->isRelocatable())));
     576                 : 
     577                 :     //TODO: Check overlapping sections
     578             569 :     std::list<ElfSection *>::iterator i;
     579            3789 :     for (i = sections.begin(); i != sections.end(); ++i)
     580            3220 :         if ((*i)->getAddr() > section->getAddr())
     581               0 :             break;
     582             569 :     sections.insert(i, section);
     583             569 :     section->addToSegment(this);
     584             569 : }
     585                 : 
     586             115 : unsigned int ElfSegment::getFileSize()
     587                 : {
     588             115 :     if (type == PT_GNU_RELRO)
     589               0 :         return filesz;
     590                 : 
     591             115 :     if (sections.empty())
     592              25 :         return 0;
     593                 :     // Search the last section that is not SHT_NOBITS
     594              90 :     std::list<ElfSection *>::reverse_iterator i;
     595              90 :     for (i = sections.rbegin(); (i != sections.rend()) && ((*i)->getType() == SHT_NOBITS); ++i);
     596                 :     // All sections are SHT_NOBITS
     597              90 :     if (i == sections.rend())
     598               4 :         return 0;
     599                 : 
     600              86 :     unsigned int end = (*i)->getAddr() + (*i)->getSize();
     601                 : 
     602              86 :     return end - sections.front()->getAddr();
     603                 : }
     604                 : 
     605             115 : unsigned int ElfSegment::getMemSize()
     606                 : {
     607             115 :     if (type == PT_GNU_RELRO)
     608               0 :         return memsz;
     609                 : 
     610             115 :     if (sections.empty())
     611              25 :         return 0;
     612                 : 
     613              90 :     unsigned int end = sections.back()->getAddr() + sections.back()->getSize();
     614                 : 
     615              90 :     return end - sections.front()->getAddr();
     616                 : }
     617                 : 
     618              25 : unsigned int ElfSegment::getOffset()
     619                 : {
     620              25 :     if ((type == PT_GNU_RELRO) && !sections.empty() &&
     621               0 :         (sections.front()->getAddr() != vaddr))
     622               0 :         throw std::runtime_error("PT_GNU_RELRO segment doesn't start on a section start");
     623                 : 
     624              25 :     return sections.empty() ? 0 : sections.front()->getOffset();
     625                 : }
     626                 : 
     627              25 : unsigned int ElfSegment::getAddr()
     628                 : {
     629              25 :     if ((type == PT_GNU_RELRO) && !sections.empty() &&
     630               0 :         (sections.front()->getAddr() != vaddr))
     631               0 :         throw std::runtime_error("PT_GNU_RELRO segment doesn't start on a section start");
     632                 : 
     633              25 :     return sections.empty() ? 0 : sections.front()->getAddr();
     634                 : }
     635                 : 
     636               4 : ElfSegment *ElfSegment::splitBefore(ElfSection *section)
     637                 : {
     638               4 :     std::list<ElfSection *>::iterator i, rm;
     639               4 :     for (i = sections.begin(); (*i != section) && (i != sections.end()); ++i);
     640               4 :     if (i == sections.end())
     641               0 :         return NULL;
     642                 : 
     643                 :     // Probably very wrong.
     644               4 :     Elf_Phdr phdr;
     645               4 :     phdr.p_type = type;
     646               4 :     phdr.p_vaddr = 0;
     647               4 :     phdr.p_paddr = phdr.p_vaddr + v_p_diff;
     648               4 :     phdr.p_flags = flags;
     649               4 :     phdr.p_align = getAlign();
     650               4 :     phdr.p_filesz = (unsigned int)-1;
     651               4 :     phdr.p_memsz = (unsigned int)-1;
     652               4 :     ElfSegment *segment = new ElfSegment(&phdr);
     653                 : 
     654              32 :     for (rm = i; i != sections.end(); ++i) {
     655              28 :         (*i)->removeFromSegment(this);
     656              28 :         segment->addSection(*i);
     657                 :     }
     658               4 :     sections.erase(rm, sections.end());
     659                 : 
     660               4 :     return segment;
     661                 : }
     662                 : 
     663             168 : ElfValue *ElfDynamic_Section::getValueForType(unsigned int tag)
     664                 : {
     665            3599 :     for (unsigned int i = 0; i < shdr.sh_size / shdr.sh_entsize; i++)
     666            3599 :         if (dyns[i].tag == tag)
     667             168 :             return dyns[i].value;
     668                 : 
     669               0 :     return NULL;
     670                 : }
     671                 : 
     672             147 : ElfSection *ElfDynamic_Section::getSectionForType(unsigned int tag)
     673                 : {
     674             147 :     ElfValue *value = getValueForType(tag);
     675             147 :     return value ? value->getSection() : NULL;
     676                 : }
     677                 : 
     678              42 : void ElfDynamic_Section::setValueForType(unsigned int tag, ElfValue *val)
     679                 : {
     680                 :     unsigned int i;
     681             917 :     for (i = 0; (i < shdr.sh_size / shdr.sh_entsize) && (dyns[i].tag != DT_NULL); i++)
     682             917 :         if (dyns[i].tag == tag) {
     683              42 :             delete dyns[i].value;
     684              42 :             dyns[i].value = val;
     685              42 :             return;
     686                 :         }
     687                 :     // This should never happen, as the last entry is always tagged DT_NULL
     688               0 :     assert(i < shdr.sh_size / shdr.sh_entsize);
     689                 :     // If we get here, this means we didn't match for the given tag
     690               0 :     dyns[i].tag = tag;
     691               0 :     dyns[i++].value = val;
     692                 : 
     693                 :     // If we were on the last entry, we need to grow the section.
     694                 :     // Most of the time, though, there are a few DT_NULL entries.
     695               0 :     if (i < shdr.sh_size / shdr.sh_entsize)
     696               0 :         return;
     697                 : 
     698                 :     Elf_DynValue value;
     699               0 :     value.tag = DT_NULL;
     700               0 :     value.value = NULL;
     701               0 :     dyns.push_back(value);
     702                 :     // Resize the section accordingly
     703               0 :     shdr.sh_size += shdr.sh_entsize;
     704               0 :     if (getNext() != NULL)
     705               0 :         getNext()->markDirty();
     706                 : }
     707                 : 
     708              21 : ElfDynamic_Section::ElfDynamic_Section(Elf_Shdr &s, std::ifstream *file, Elf *parent)
     709              21 : : ElfSection(s, file, parent)
     710                 : {
     711              21 :     int pos = file->tellg();
     712              21 :     dyns.resize(s.sh_size / s.sh_entsize);
     713              21 :     file->seekg(shdr.sh_offset);
     714                 :     // Here we assume tags refer to only one section (e.g. DT_RELSZ accounts
     715                 :     // for .rel.dyn size)
     716             771 :     for (unsigned int i = 0; i < s.sh_size / s.sh_entsize; i++) {
     717             750 :         Elf_Dyn dyn(*file, parent->getClass(), parent->getData());
     718             750 :         dyns[i].tag = dyn.d_tag;
     719             750 :         switch (dyn.d_tag) {
     720                 :         case DT_NULL:
     721                 :         case DT_SYMBOLIC:
     722                 :         case DT_TEXTREL:
     723                 :         case DT_BIND_NOW:
     724             110 :             dyns[i].value = new ElfValue();
     725             110 :             break;
     726                 :         case DT_NEEDED:
     727                 :         case DT_SONAME:
     728                 :         case DT_RPATH:
     729                 :         case DT_PLTREL:
     730                 :         case DT_RUNPATH:
     731                 :         case DT_FLAGS:
     732                 :         case DT_RELACOUNT:
     733                 :         case DT_RELCOUNT:
     734                 :         case DT_VERDEFNUM:
     735                 :         case DT_VERNEEDNUM:
     736             317 :             dyns[i].value = new ElfPlainValue(dyn.d_un.d_val);
     737             317 :             break;
     738                 :         case DT_PLTGOT:
     739                 :         case DT_HASH:
     740                 :         case DT_STRTAB:
     741                 :         case DT_SYMTAB:
     742                 :         case DT_RELA:
     743                 :         case DT_INIT:
     744                 :         case DT_FINI:
     745                 :         case DT_REL:
     746                 :         case DT_JMPREL:
     747                 :         case DT_INIT_ARRAY:
     748                 :         case DT_FINI_ARRAY:
     749                 :         case DT_GNU_HASH:
     750                 :         case DT_VERSYM:
     751                 :         case DT_VERNEED:
     752                 :         case DT_VERDEF:
     753             218 :             dyns[i].value = new ElfLocation(dyn.d_un.d_ptr, parent);
     754             218 :             break;
     755                 :         default:
     756             105 :             dyns[i].value = NULL;
     757                 :         }
     758                 :     }
     759                 :     // Another loop to get the section sizes
     760             771 :     for (unsigned int i = 0; i < s.sh_size / s.sh_entsize; i++)
     761             750 :         switch (dyns[i].tag) {
     762                 :         case DT_PLTRELSZ:
     763              21 :             dyns[i].value = new ElfSize(getSectionForType(DT_JMPREL));
     764              21 :             break;
     765                 :         case DT_RELASZ:
     766               0 :             dyns[i].value = new ElfSize(getSectionForType(DT_RELA));
     767               0 :             break;
     768                 :         case DT_STRSZ:
     769              21 :             dyns[i].value = new ElfSize(getSectionForType(DT_STRTAB));
     770              21 :             break;
     771                 :         case DT_RELSZ:
     772              21 :             dyns[i].value = new ElfSize(getSectionForType(DT_REL));
     773              21 :             break;
     774                 :         case DT_INIT_ARRAYSZ:
     775               0 :             dyns[i].value = new ElfSize(getSectionForType(DT_INIT_ARRAY));
     776               0 :             break;
     777                 :         case DT_FINI_ARRAYSZ:
     778               0 :             dyns[i].value = new ElfSize(getSectionForType(DT_FINI_ARRAY));
     779               0 :             break;
     780                 :         case DT_RELAENT:
     781               0 :             dyns[i].value = new ElfEntSize(getSectionForType(DT_RELA));
     782               0 :             break;
     783                 :         case DT_SYMENT:
     784              21 :             dyns[i].value = new ElfEntSize(getSectionForType(DT_SYMTAB));
     785              21 :             break;
     786                 :         case DT_RELENT:
     787              21 :             dyns[i].value = new ElfEntSize(getSectionForType(DT_REL));
     788              21 :             break;
     789                 :         }
     790                 : 
     791              21 :     file->seekg(pos);
     792              21 : }
     793                 : 
     794              63 : ElfDynamic_Section::~ElfDynamic_Section()
     795                 : {
     796             771 :     for (unsigned int i = 0; i < shdr.sh_size / shdr.sh_entsize; i++)
     797             750 :         delete dyns[i].value;
     798              42 : }
     799                 : 
     800               4 : void ElfDynamic_Section::serialize(std::ofstream &file, char ei_class, char ei_data)
     801                 : {
     802             149 :     for (unsigned int i = 0; i < shdr.sh_size / shdr.sh_entsize; i++) {
     803             145 :         Elf_Dyn dyn;
     804             145 :         dyn.d_tag = dyns[i].tag;
     805             145 :         dyn.d_un.d_val = (dyns[i].value != NULL) ? dyns[i].value->getValue() : 0;
     806             145 :         dyn.serialize(file, ei_class, ei_data);
     807                 :     }
     808               4 : }
     809                 : 
     810              63 : ElfSymtab_Section::ElfSymtab_Section(Elf_Shdr &s, std::ifstream *file, Elf *parent)
     811              63 : : ElfSection(s, file, parent)
     812                 : {
     813              63 :     int pos = file->tellg();
     814              63 :     syms.resize(s.sh_size / s.sh_entsize);
     815              63 :     ElfStrtab_Section *strtab = (ElfStrtab_Section *)getLink();
     816              63 :     file->seekg(shdr.sh_offset);
     817          406012 :     for (unsigned int i = 0; i < shdr.sh_size / shdr.sh_entsize; i++) {
     818          405949 :         Elf_Sym sym(*file, parent->getClass(), parent->getData());
     819          405949 :         syms[i].name = strtab->getStr(sym.st_name);
     820          405949 :         syms[i].info = sym.st_info;
     821          405949 :         syms[i].other = sym.st_other;
     822          405949 :         ElfSection *section = (sym.st_shndx == SHN_ABS) ? NULL : parent->getSection(sym.st_shndx);
     823          405949 :         new (&syms[i].value) ElfLocation(section, sym.st_value, ElfLocation::ABSOLUTE);
     824          405949 :         syms[i].size = sym.st_size;
     825          405949 :         syms[i].defined = (sym.st_shndx != SHN_UNDEF);
     826                 :     }
     827              63 :     file->seekg(pos);
     828              63 : }
     829                 : 
     830                 : void
     831               8 : ElfSymtab_Section::serialize(std::ofstream &file, char ei_class, char ei_data)
     832                 : {
     833               8 :     ElfStrtab_Section *strtab = (ElfStrtab_Section *)getLink();
     834          382002 :     for (unsigned int i = 0; i < shdr.sh_size / shdr.sh_entsize; i++) {
     835          381994 :         Elf_Sym sym;
     836          381994 :         sym.st_name = strtab->getStrIndex(syms[i].name);
     837          381994 :         sym.st_info = syms[i].info;
     838          381994 :         sym.st_other = syms[i].other;
     839          381994 :         sym.st_value = syms[i].value.getValue();
     840          381994 :         ElfSection *section = syms[i].value.getSection();
     841          381994 :         if (syms[i].defined)
     842          376889 :             sym.st_shndx = section ? section->getIndex() : SHN_ABS;
     843                 :         else
     844            5105 :             sym.st_shndx = SHN_UNDEF;
     845          381994 :         sym.st_size = syms[i].size;
     846          381994 :         sym.serialize(file, ei_class, ei_data);
     847                 :     }
     848               8 : }
     849                 : 
     850                 : Elf_SymValue *
     851              42 : ElfSymtab_Section::lookup(const char *name, unsigned int type_filter)
     852                 : {
     853           14892 :     for (std::vector<Elf_SymValue>::iterator sym = syms.begin();
     854            7446 :          sym != syms.end(); sym++) {
     855           14568 :         if ((type_filter & (1 << ELF32_ST_TYPE(sym->info))) &&
     856            7138 :             (strcmp(sym->name, name) == 0)) {
     857              26 :             return &*sym;
     858                 :         }
     859                 :     }
     860              16 :     return NULL;
     861                 : }
     862                 : 
     863                 : const char *
     864          406893 : ElfStrtab_Section::getStr(unsigned int index)
     865                 : {
     866          813786 :     for (std::vector<table_storage>::iterator t = table.begin();
     867          406893 :          t != table.end(); t++) {
     868          406893 :         if (index < t->used)
     869          406893 :             return t->buf + index;
     870               0 :         index -= t->used;
     871                 :     }
     872               0 :     assert(1 == 0);
     873                 :     return NULL;
     874                 : }
     875                 : 
     876                 : const char *
     877          382141 : ElfStrtab_Section::getStr(const char *string)
     878                 : {
     879          382141 :     if (string == NULL)
     880               0 :         return NULL;
     881                 : 
     882                 :     // If the given string is within the section, return it
     883          764306 :     for (std::vector<table_storage>::iterator t = table.begin();
     884          382153 :          t != table.end(); t++)
     885          382145 :         if ((string >= t->buf) && (string < t->buf + t->used))
     886          382133 :             return string;
     887                 : 
     888                 :     // TODO: should scan in the section to find an existing string
     889                 : 
     890                 :     // If not, we need to allocate the string in the section
     891               8 :     size_t len = strlen(string) + 1;
     892                 : 
     893               8 :     if (table.back().size - table.back().used < len)
     894               4 :         table.resize(table.size() + 1);
     895                 : 
     896               8 :     char *alloc_str = table.back().buf + table.back().used;
     897               8 :     memcpy(alloc_str, string, len);
     898               8 :     table.back().used += len;
     899                 : 
     900               8 :     shdr.sh_size += len;
     901               8 :     markDirty();
     902                 : 
     903               8 :     return alloc_str;
     904                 : }
     905                 : 
     906                 : unsigned int
     907          382141 : ElfStrtab_Section::getStrIndex(const char *string)
     908                 : {
     909          382141 :     if (string == NULL)
     910               0 :         return 0;
     911                 : 
     912          382141 :     unsigned int index = 0;
     913          382141 :     string = getStr(string);
     914          764298 :     for (std::vector<table_storage>::iterator t = table.begin();
     915          382149 :          t != table.end(); t++) {
     916          382149 :         if ((string >= t->buf) && (string < t->buf + t->used))
     917          382141 :             return index + (string - t->buf);
     918               8 :         index += t->used;
     919                 :     }
     920                 : 
     921               0 :     assert(1 == 0);
     922                 :     return 0;
     923                 : }
     924                 : 
     925                 : void
     926              12 : ElfStrtab_Section::serialize(std::ofstream &file, char ei_class, char ei_data)
     927                 : {
     928              12 :     file.seekp(getOffset());
     929              56 :     for (std::vector<table_storage>::iterator t = table.begin();
     930              28 :          t != table.end(); t++)
     931              16 :         file.write(t->buf, t->used);
     932              18 : }

Generated by: LCOV version 1.7