LCOV - app.info - build/unix/elfhack/elf.cpp

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-04-07 | 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          808233 : void Elf_Sym_Traits::swap(T &t, R &r)
          99                 : {
         100          808233 :     r.st_name = endian::swap(t.st_name);
         101          808233 :     r.st_value = endian::swap(t.st_value);
         102          808233 :     r.st_size = endian::swap(t.st_size);
         103          808233 :     r.st_info = t.st_info;
         104          808233 :     r.st_other = t.st_other;
         105          808233 :     r.st_shndx = endian::swap(t.st_shndx);
         106          808233 : }
         107                 :
         108                 : template <class endian>
         109                 : struct _Rel_info {
         110          352818 :     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          352818 : void Elf_Rel_Traits::swap(T &t, R &r)
         122                 : {
         123          352818 :     r.r_offset = endian::swap(t.r_offset);
         124          352818 :     _Rel_info<endian>::swap(t.r_info, r.r_info);
         125          352818 : }
         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         6949422 : ElfSection *Elf::getSection(int index)
         317                 : {
         318         6949422 :     if ((index < -1) || (index >= ehdr->e_shnum))
         319               0 :         throw std::runtime_error("Section index out of bounds");
         320         6949422 :     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         6949422 :     if (index == 0)
         324            9137 :         return NULL;
         325                 :     // Infinite recursion guard
         326         6940285 :     if (sections[index] == (ElfSection *)this)
         327              84 :         return NULL;
         328         6940201 :     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         6940201 :     return sections[index];
         352                 : }
         353                 :
         354          321707 : ElfSection *Elf::getSectionAt(unsigned int offset)
         355                 : {
         356         6535419 :     for (int i = 1; i < ehdr->e_shnum; i++) {
         357         6535419 :         ElfSection *section = getSection(i);
         358        18987077 :         if ((section != NULL) && (section->getFlags() & SHF_ALLOC) && !(section->getFlags() & SHF_TLS) &&
         359        12451658 :             (offset >= section->getAddr()) && (offset < section->getAddr() + section->getSize()))
         360          321707 :             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        13285759 : unsigned int ElfSection::getAddr()
         484                 : {
         485        13285759 :     if (shdr.sh_addr != (Elf32_Word)-1)
         486        13285627 :         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              56 :             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              18 :             offset = (offset | mask) + (getAddr() & mask) + 1;
         524                 :         else
         525             493 :             offset = (offset & ~mask) + (getAddr() & mask);
         526                 :     }
         527             858 :     if ((getType() != SHT_NOBITS) && (offset & (getAddrAlign() - 1)))
         528              39 :         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          384420 : int ElfSection::getIndex()
         542                 : {
         543          384420 :     if (index != -1)
         544          384135 :         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          416158 :     for (unsigned int i = 0; i < shdr.sh_size / shdr.sh_entsize; i++) {
         818          416095 :         Elf_Sym sym(*file, parent->getClass(), parent->getData());
         819          416095 :         syms[i].name = strtab->getStr(sym.st_name);
         820          416095 :         syms[i].info = sym.st_info;
         821          416095 :         syms[i].other = sym.st_other;
         822          416095 :         ElfSection *section = (sym.st_shndx == SHN_ABS) ? NULL : parent->getSection(sym.st_shndx);
         823          416095 :         new (&syms[i].value) ElfLocation(section, sym.st_value, ElfLocation::ABSOLUTE);
         824          416095 :         syms[i].size = sym.st_size;
         825          416095 :         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          392146 :     for (unsigned int i = 0; i < shdr.sh_size / shdr.sh_entsize; i++) {
         835          392138 :         Elf_Sym sym;
         836          392138 :         sym.st_name = strtab->getStrIndex(syms[i].name);
         837          392138 :         sym.st_info = syms[i].info;
         838          392138 :         sym.st_other = syms[i].other;
         839          392138 :         sym.st_value = syms[i].value.getValue();
         840          392138 :         ElfSection *section = syms[i].value.getSection();
         841          392138 :         if (syms[i].defined)
         842          387011 :             sym.st_shndx = section ? section->getIndex() : SHN_ABS;
         843                 :         else
         844            5127 :             sym.st_shndx = SHN_UNDEF;
         845          392138 :         sym.st_size = syms[i].size;
         846          392138 :         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           14922 :     for (std::vector<Elf_SymValue>::iterator sym = syms.begin();
         854            7461 :          sym != syms.end(); sym++) {
         855           14598 :         if ((type_filter & (1 << ELF32_ST_TYPE(sym->info))) &&
         856            7153 :             (strcmp(sym->name, name) == 0)) {
         857              26 :             return &*sym;
         858                 :         }
         859                 :     }
         860              16 :     return NULL;
         861                 : }
         862                 :
         863                 : const char *
         864          417039 : ElfStrtab_Section::getStr(unsigned int index)
         865                 : {
         866          834078 :     for (std::vector<table_storage>::iterator t = table.begin();
         867          417039 :          t != table.end(); t++) {
         868          417039 :         if (index < t->used)
         869          417039 :             return t->buf + index;
         870               0 :         index -= t->used;
         871                 :     }
         872               0 :     assert(1 == 0);
         873                 :     return NULL;
         874                 : }
         875                 :
         876                 : const char *
         877          392285 : ElfStrtab_Section::getStr(const char *string)
         878                 : {
         879          392285 :     if (string == NULL)
         880               0 :         return NULL;
         881                 :
         882                 :     // If the given string is within the section, return it
         883          784594 :     for (std::vector<table_storage>::iterator t = table.begin();
         884          392297 :          t != table.end(); t++)
         885          392289 :         if ((string >= t->buf) && (string < t->buf + t->used))
         886          392277 :             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          392285 : ElfStrtab_Section::getStrIndex(const char *string)
         908                 : {
         909          392285 :     if (string == NULL)
         910               0 :         return 0;
         911                 :
         912          392285 :     unsigned int index = 0;
         913          392285 :     string = getStr(string);
         914          784586 :     for (std::vector<table_storage>::iterator t = table.begin();
         915          392293 :          t != table.end(); t++) {
         916          392293 :         if ((string >= t->buf) && (string < t->buf + t->used))
         917          392285 :             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