Elf_X.C

Go to the documentation of this file.
00001 /*
00002  * See the dyninst/COPYRIGHT file for copyright information.
00003  * 
00004  * We provide the Paradyn Tools (below described as "Paradyn")
00005  * on an AS IS basis, and do not warrant its validity or performance.
00006  * We reserve the right to update, modify, or discontinue this
00007  * software at any time.  We shall have no obligation to supply such
00008  * updates or modifications or any other form of support to you.
00009  * 
00010  * By your use of Paradyn, you understand and agree that we (or any
00011  * other person or entity with proprietary rights in Paradyn) are
00012  * under no obligation to provide either maintenance services,
00013  * update services, notices of latent defects, or correction of
00014  * defects for Paradyn.
00015  * 
00016  * This library is free software; you can redistribute it and/or
00017  * modify it under the terms of the GNU Lesser General Public
00018  * License as published by the Free Software Foundation; either
00019  * version 2.1 of the License, or (at your option) any later version.
00020  * 
00021  * This library is distributed in the hope that it will be useful,
00022  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00023  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00024  * Lesser General Public License for more details.
00025  * 
00026  * You should have received a copy of the GNU Lesser General Public
00027  * License along with this library; if not, write to the Free Software
00028  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00029  */
00030 
00031 #include <sys/mman.h>
00032 #include <sys/types.h>
00033 #include <sys/stat.h>
00034 #include <fcntl.h>
00035 #include <unistd.h>
00036 #include <libgen.h>
00037 
00038 #include <boost/crc.hpp>
00039 #include <boost/assign/list_of.hpp>
00040 #include <boost/assign/std/set.hpp>
00041 #include <boost/assign/std/vector.hpp>
00042 
00043 #include "common/h/headers.h"
00044 #include "elf/h/Elf_X.h"
00045 #include <iostream>
00046 #include <iomanip>
00047 #include <sstream>
00048 
00049 using namespace std;
00050 using boost::crc_32_type;
00051 using namespace boost::assign;
00052 
00053 using namespace Dyninst;
00054 
00055 #define DEBUGLINK_NAME ".gnu_debuglink"
00056 #define BUILD_ID_NAME ".note.gnu.build-id"
00057 
00058 map<pair<string, int>, Elf_X *> Elf_X::elf_x_by_fd;
00059 map<pair<string, char *>, Elf_X *> Elf_X::elf_x_by_ptr;
00060 
00061 #define APPEND(X) X ## 1
00062 #define APPEND2(X) APPEND(X)
00063 #define LIBELF_TEST APPEND2(_LIBELF_H)
00064 #if (LIBELF_TEST == 11)
00065 #define USES_ELFUTILS
00066 #endif
00067 
00068 Elf_X *Elf_X::newElf_X(int input, Elf_Cmd cmd, Elf_X *ref, string name)
00069 {
00070 #if defined(USES_ELFUTILS)
00071    //If using libelf via elfutils from RedHat
00072    if (cmd == ELF_C_READ) {
00073       cmd = ELF_C_READ_MMAP;
00074    }
00075 #endif
00076    if (name.empty()) {
00077       return new Elf_X(input, cmd, ref);
00078    }
00079    auto i = elf_x_by_fd.find(make_pair(name, input));
00080    if (i != elf_x_by_fd.end()) {
00081      Elf_X *ret = i->second;
00082      ret->ref_count++;
00083      return ret;
00084    }
00085    Elf_X *ret = new Elf_X(input, cmd, ref);
00086    ret->filename = name;
00087    elf_x_by_fd.insert(make_pair(make_pair(name, input), ret));
00088    return ret;
00089 }
00090 
00091 Elf_X *Elf_X::newElf_X(char *mem_image, size_t mem_size, string name)
00092 {
00093    if (name.empty()) {
00094       return new Elf_X(mem_image, mem_size);
00095    }
00096    auto i = elf_x_by_ptr.find(make_pair(name, mem_image));
00097    if (i != elf_x_by_ptr.end()) {
00098      Elf_X *ret = i->second;
00099      
00100      ret->ref_count++;
00101      return ret;
00102    }
00103    Elf_X *ret = new Elf_X(mem_image, mem_size);
00104    ret->filename = name;
00105    elf_x_by_ptr.insert(make_pair(make_pair(name, mem_image), ret));
00106    return ret;
00107 }
00108 
00109 // ------------------------------------------------------------------------
00110 // Class Elf_X simulates the Elf(32|64)_Ehdr structure.
00111 // Also works for ELF archives. 
00112 Elf_X::Elf_X()
00113     : elf(NULL), ehdr32(NULL), ehdr64(NULL), phdr32(NULL), phdr64(NULL),
00114       filedes(-1), is64(false), isArchive(false), ref_count(1),
00115       cached_debug_buffer(NULL), cached_debug_size(0), cached_debug(false)
00116 { }
00117 
00118 Elf_X::Elf_X(int input, Elf_Cmd cmd, Elf_X *ref)
00119     : ehdr32(NULL), ehdr64(NULL), phdr32(NULL), phdr64(NULL),
00120       filedes(input), is64(false), isArchive(false), ref_count(1),
00121       cached_debug_buffer(NULL), cached_debug_size(0), cached_debug(false)
00122 {
00123     if (elf_version(EV_CURRENT) == EV_NONE) {
00124        return;
00125     }
00126     elf_errno(); // Reset elf_errno to zero.
00127     if (ref)
00128        elf = elf_begin(input, cmd, ref->e_elfp());
00129     else {
00130        elf = elf_begin(input, cmd, NULL);
00131     }
00132     int errnum;
00133     if ((errnum = elf_errno()) != 0) {
00134        const char *msg = elf_errmsg(errnum);
00135        fprintf(stderr, "Elf error: %s\n", msg);
00136     }
00137     if (elf) {
00138        if (elf_kind(elf) == ELF_K_ELF) {
00139           char *identp = elf_getident(elf, NULL);
00140           is64 = (identp && identp[EI_CLASS] == ELFCLASS64);
00141        }
00142        else if(elf_kind(elf) == ELF_K_AR) {
00143           char *identp = elf_getident(elf, NULL);
00144           is64 = (identp && identp[EI_CLASS] == ELFCLASS64);
00145           isArchive = true;
00146        }
00147        
00148        if (!is64)  ehdr32 = elf32_getehdr(elf);
00149        else       ehdr64 = elf64_getehdr(elf);
00150        
00151        if (!is64) phdr32 = elf32_getphdr(elf);
00152        else       phdr64 = elf64_getphdr(elf);
00153     }
00154 
00155     if (elf_kind(elf) == ELF_K_ELF) {
00156        size_t phdrnum = e_phnum();
00157        size_t shdrnum = e_shnum();
00158        shdrs.resize(shdrnum);
00159        phdrs.resize(phdrnum);
00160     }
00161 }
00162 
00163 Elf_X::Elf_X(char *mem_image, size_t mem_size)
00164     : ehdr32(NULL), ehdr64(NULL), phdr32(NULL), phdr64(NULL),
00165       is64(false), isArchive(false), ref_count(1),
00166       cached_debug_buffer(NULL), cached_debug_size(0), cached_debug(false)
00167 {
00168     if (elf_version(EV_CURRENT) == EV_NONE) {
00169        return;
00170     }
00171 
00172     elf_errno(); // Reset elf_errno to zero.
00173     elf = elf_memory(mem_image, mem_size);
00174     
00175     int err;
00176     if ( (err = elf_errno()) != 0) {
00177        //const char *msg = elf_errmsg(err);
00178     }
00179     
00180     if (elf) {
00181        if (elf_kind(elf) == ELF_K_ELF) {
00182           char *identp = elf_getident(elf, NULL);
00183           is64 = (identp && identp[EI_CLASS] == ELFCLASS64);
00184        }
00185        
00186        if (!is64) ehdr32 = elf32_getehdr(elf);
00187        else       ehdr64 = elf64_getehdr(elf);
00188        
00189        if (!is64) phdr32 = elf32_getphdr(elf);
00190        else       phdr64 = elf64_getphdr(elf);
00191     }
00192 
00193     if (elf_kind(elf) == ELF_K_ELF) {
00194        size_t phdrnum = e_phnum();
00195        size_t shdrnum = e_shnum();
00196        shdrs.resize(shdrnum);
00197        phdrs.resize(phdrnum);
00198     }
00199 }
00200 
00201 void Elf_X::end()
00202 {
00203    if (ref_count > 1) {
00204       ref_count--;
00205       return;
00206    }
00207    /*
00208      Stop cleaning Elf_X.  Leads to constant remapping of file.
00209    if (elf) {
00210       elf_end(elf);
00211       elf = NULL;
00212       ehdr32 = NULL;
00213       ehdr64 = NULL;
00214       phdr32 = NULL;
00215       phdr64 = NULL;
00216    }
00217    delete this;*/
00218 }
00219 
00220 Elf_X::~Elf_X()
00221 {
00222   // Unfortunately, we have to be slow here
00223   for (auto iter = elf_x_by_fd.begin(); iter != elf_x_by_fd.end(); ++iter) {
00224     if (iter->second == this) {
00225       elf_x_by_fd.erase(iter);
00226       return;
00227     }
00228   }
00229 
00230   for (auto iter = elf_x_by_ptr.begin(); iter != elf_x_by_ptr.end(); ++iter) {
00231     if (iter->second == this) {
00232       elf_x_by_ptr.erase(iter);
00233     }
00234   }
00235 }
00236 
00237 // Read Interface
00238 Elf *Elf_X::e_elfp() const
00239 {
00240     return elf;
00241 }
00242 
00243 unsigned char *Elf_X::e_ident() const
00244 {
00245     return (!is64 ?
00246             static_cast<unsigned char*>(ehdr32->e_ident) :
00247             static_cast<unsigned char*>(ehdr64->e_ident));
00248 }
00249 
00250 unsigned short Elf_X::e_type() const
00251 {
00252     return (!is64 ?
00253             static_cast<unsigned short>(ehdr32->e_type) :
00254             static_cast<unsigned short>(ehdr64->e_type));
00255 }
00256 
00257 unsigned short Elf_X::e_machine() const
00258 {
00259     return (!is64 ?
00260             static_cast<unsigned short>(ehdr32->e_machine) :
00261             static_cast<unsigned short>(ehdr64->e_machine));
00262 }
00263 
00264 unsigned long Elf_X::e_version() const
00265 {
00266     return (!is64 ?
00267             static_cast<unsigned long>(ehdr32->e_version) :
00268             static_cast<unsigned long>(ehdr64->e_version));
00269 }
00270 
00271 unsigned long Elf_X::e_entry() const
00272 {
00273     return (!is64 ?
00274             static_cast<unsigned long>(ehdr32->e_entry) :
00275             static_cast<unsigned long>(ehdr64->e_entry));
00276 }
00277 
00278 unsigned long Elf_X::e_phoff() const
00279 {
00280     return (!is64 ?
00281             static_cast<unsigned long>(ehdr32->e_phoff) :
00282             static_cast<unsigned long>(ehdr64->e_phoff));
00283 }
00284 
00285 unsigned long Elf_X::e_shoff() const
00286 {
00287     return (!is64 ?
00288             static_cast<unsigned long>(ehdr32->e_shoff) :
00289             static_cast<unsigned long>(ehdr64->e_shoff));
00290 }
00291 
00292 unsigned long Elf_X::e_flags() const
00293 {
00294     return (!is64 ?
00295             static_cast<unsigned long>(ehdr32->e_flags) :
00296             static_cast<unsigned long>(ehdr64->e_flags));
00297 }
00298 
00299 unsigned short Elf_X::e_ehsize() const
00300 {
00301     return (!is64 ?
00302             static_cast<unsigned short>(ehdr32->e_ehsize) :
00303             static_cast<unsigned short>(ehdr64->e_ehsize));
00304 }
00305 
00306 unsigned short Elf_X::e_phentsize() const {
00307     return (!is64 ?
00308             static_cast<unsigned short>(ehdr32->e_phentsize) :
00309             static_cast<unsigned short>(ehdr64->e_phentsize));
00310 }
00311 
00312 unsigned short Elf_X::e_phnum() const
00313 {
00314     return (!is64 ?
00315             static_cast<unsigned short>(ehdr32->e_phnum) :
00316             static_cast<unsigned short>(ehdr64->e_phnum));
00317 }
00318 
00319 unsigned short Elf_X::e_shentsize() const
00320 {
00321     return (!is64 ?
00322             static_cast<unsigned short>(ehdr32->e_shentsize) :
00323             static_cast<unsigned short>(ehdr64->e_shentsize));
00324 }
00325 
00326 unsigned short Elf_X::e_shnum() const
00327 {
00328     return (!is64 ?
00329             static_cast<unsigned short>(ehdr32->e_shnum) :
00330             static_cast<unsigned short>(ehdr64->e_shnum));
00331 }
00332 
00333 unsigned short Elf_X::e_shstrndx() const
00334 {
00335     return (!is64 ?
00336             static_cast<unsigned short>(ehdr32->e_shstrndx) :
00337             static_cast<unsigned short>(ehdr64->e_shstrndx));
00338 }
00339 
00340 const char *Elf_X::e_rawfile(size_t &nbytes) const
00341 {
00342     return elf_rawfile(elf, &nbytes);
00343 }
00344 
00345 Elf_X *Elf_X::e_next(Elf_X *ref)
00346 {
00347     if (!isArchive)
00348         return NULL;
00349     Elf_Cmd cmd = elf_next(ref->e_elfp());
00350     return Elf_X::newElf_X(filedes, cmd, this);
00351 }
00352 
00353 Elf_X *Elf_X::e_rand(unsigned offset)
00354 {
00355     if (!isArchive)
00356         return NULL;
00357     elf_rand(elf, offset);
00358     return Elf_X::newElf_X(filedes, ELF_C_READ, this);
00359 }
00360 
00361 // Write Interface
00362 void Elf_X::e_ident(unsigned char *input)
00363 {
00364     if (!is64) P_memcpy(ehdr32->e_ident, input, EI_NIDENT);
00365     else       P_memcpy(ehdr64->e_ident, input, EI_NIDENT);
00366 }
00367 
00368 void Elf_X::e_type(unsigned short input)
00369 {
00370     if (!is64) ehdr32->e_type = input;
00371     else       ehdr64->e_type = input;
00372 }
00373 
00374 void Elf_X::e_machine(unsigned short input)
00375 {
00376     if (!is64) ehdr32->e_machine = input;
00377     else       ehdr64->e_machine = input;
00378 }
00379 
00380 void Elf_X::e_version(unsigned long input)
00381 {
00382     if (!is64) ehdr32->e_version = input;
00383     else       ehdr64->e_version = input;
00384 }
00385 
00386 void Elf_X::e_entry(unsigned long input)
00387 {
00388     if (!is64) ehdr32->e_entry = input;
00389     else       ehdr64->e_entry = input;
00390 }
00391 
00392 void Elf_X::e_phoff(unsigned long input)
00393 {
00394     if (!is64) ehdr32->e_phoff = input;
00395     else       ehdr64->e_phoff = input;
00396 }
00397 
00398 void Elf_X::e_shoff(unsigned long input)
00399 {
00400     if (!is64) ehdr32->e_shoff = input;
00401     else       ehdr64->e_shoff = input;
00402 }
00403 
00404 void Elf_X::e_flags(unsigned long input)
00405 {
00406     if (!is64) ehdr32->e_flags = input;
00407     else       ehdr64->e_flags = input;
00408 }
00409 
00410 void Elf_X::e_ehsize(unsigned short input)
00411 {
00412     if (!is64) ehdr32->e_ehsize = input;
00413     else       ehdr64->e_ehsize = input;
00414 }
00415 
00416 void Elf_X::e_phentsize(unsigned short input)
00417 {
00418     if (!is64) ehdr32->e_phentsize = input;
00419     else       ehdr64->e_phentsize = input;
00420 }
00421 
00422 void Elf_X::e_phnum(unsigned short input)
00423 {
00424     if (!is64) ehdr32->e_phnum = input;
00425     else       ehdr64->e_phnum = input;
00426 }
00427 
00428 void Elf_X::e_shentsize(unsigned short input)
00429 {
00430     if (!is64) ehdr32->e_shentsize = input;
00431     else       ehdr64->e_shentsize = input;
00432 }
00433 
00434 void Elf_X::e_shnum(unsigned short input)
00435 {
00436     if (!is64) ehdr32->e_shnum = input;
00437     else       ehdr64->e_shnum = input;
00438 }
00439 
00440 void Elf_X::e_shstrndx(unsigned short input)
00441 {
00442     if (!is64) ehdr32->e_shstrndx = input;
00443     else       ehdr64->e_shstrndx = input;
00444 }
00445 
00446 // Data Interface
00447 bool Elf_X::isValid() const
00448 {
00449     return (ehdr32 || ehdr64);
00450 }
00451 
00452 int Elf_X::wordSize() const
00453 {
00454     return (!is64 ? 4 : 8);
00455 }
00456 
00457 Elf_X_Phdr &Elf_X::get_phdr(unsigned int i)
00458 {
00459    if (is64 && !phdrs[i].phdr64) {
00460       phdrs[i] = Elf_X_Phdr(is64, phdr64 + i);
00461    }
00462    else if (!is64 && !phdrs[i].phdr32) {
00463       phdrs[i] = Elf_X_Phdr(is64, phdr32 + i);
00464    }
00465    return phdrs[i];
00466 }
00467 
00468 Elf_X_Shdr &Elf_X::get_shdr(unsigned int i)
00469 {
00470    if (!shdrs[i]._elf) {
00471       Elf_Scn *scn = elf_getscn(elf, i);
00472       shdrs[i] = Elf_X_Shdr(is64, scn);
00473       shdrs[i]._elf = this;
00474    }
00475    return shdrs[i];
00476 }
00477 
00478 // ------------------------------------------------------------------------
00479 // Class Elf_X_Phdr simulates the Elf(32|64)_Phdr structure.
00480 Elf_X_Phdr::Elf_X_Phdr()
00481     : phdr32(NULL), phdr64(NULL), is64(false)
00482 { }
00483 
00484 Elf_X_Phdr::Elf_X_Phdr(bool is64_, void *input)
00485     : phdr32(NULL), phdr64(NULL), is64(is64_)
00486 {
00487     if (input) {
00488         if (!is64) phdr32 = (Elf32_Phdr *)input;
00489         else       phdr64 = (Elf64_Phdr *)input;
00490     }
00491 }
00492 
00493 // Read Interface
00494 unsigned long Elf_X_Phdr::p_type() const
00495 {
00496     return (!is64 ?
00497             static_cast<unsigned long>(phdr32->p_type) :
00498             static_cast<unsigned long>(phdr64->p_type));
00499 }
00500 
00501 unsigned long Elf_X_Phdr::p_offset() const
00502 {
00503     return (!is64 ?
00504             static_cast<unsigned long>(phdr32->p_offset) :
00505             static_cast<unsigned long>(phdr64->p_offset));
00506 }
00507 
00508 unsigned long Elf_X_Phdr::p_vaddr() const
00509 {
00510     return (!is64 ?
00511             static_cast<unsigned long>(phdr32->p_vaddr) :
00512             static_cast<unsigned long>(phdr64->p_vaddr));
00513 }
00514 
00515 unsigned long Elf_X_Phdr::p_paddr() const
00516 {
00517     return (!is64 ?
00518             static_cast<unsigned long>(phdr32->p_paddr) :
00519             static_cast<unsigned long>(phdr64->p_paddr));
00520 }
00521 
00522 unsigned long Elf_X_Phdr::p_filesz() const
00523 {
00524     return (!is64 ?
00525             static_cast<unsigned long>(phdr32->p_filesz) :
00526             static_cast<unsigned long>(phdr64->p_filesz));
00527 }
00528 
00529 unsigned long Elf_X_Phdr::p_memsz() const
00530 {
00531     return (!is64 ?
00532             static_cast<unsigned long>(phdr32->p_memsz) :
00533             static_cast<unsigned long>(phdr64->p_memsz));
00534 }
00535 
00536 unsigned long Elf_X_Phdr::p_flags() const
00537 {
00538     return (!is64 ?
00539             static_cast<unsigned long>(phdr32->p_flags) :
00540             static_cast<unsigned long>(phdr64->p_flags));
00541 }
00542 
00543 unsigned long Elf_X_Phdr::p_align() const
00544 {
00545     return (!is64 ?
00546             static_cast<unsigned long>(phdr32->p_align) :
00547             static_cast<unsigned long>(phdr64->p_align));
00548 }
00549 
00550 // Write Interface
00551 void Elf_X_Phdr::p_type(unsigned long input)
00552 {
00553     if (!is64) phdr32->p_type = input;
00554     else       phdr64->p_type = input;
00555 }
00556 
00557 void Elf_X_Phdr::p_offset(unsigned long input)
00558 {
00559     if (!is64) phdr32->p_offset = input;
00560     else       phdr64->p_offset = input;
00561 }
00562 
00563 void Elf_X_Phdr::p_vaddr(unsigned long input)
00564 {
00565     if (!is64) phdr32->p_vaddr = input;
00566     else       phdr64->p_vaddr = input;
00567 }
00568 
00569 void Elf_X_Phdr::p_paddr(unsigned long input)
00570 {
00571     if (!is64) phdr32->p_paddr = input;
00572     else       phdr64->p_paddr = input;
00573 }
00574 
00575 void Elf_X_Phdr::p_filesz(unsigned long input)
00576 {
00577     if (!is64) phdr32->p_filesz = input;
00578     else       phdr64->p_filesz = input;
00579 }
00580 
00581 void Elf_X_Phdr::p_memsz(unsigned long input)
00582 {
00583     if (!is64) phdr32->p_memsz = input;
00584     else       phdr64->p_memsz = input;
00585 }
00586 
00587 void Elf_X_Phdr::p_flags(unsigned long input)
00588 {
00589     if (!is64) phdr32->p_flags = input;
00590     else       phdr64->p_flags = input;
00591 }
00592 
00593 void Elf_X_Phdr::p_align(unsigned long input)
00594 {
00595     if (!is64) phdr32->p_align = input;
00596     else       phdr64->p_align = input;
00597 }
00598 
00599 bool Elf_X_Phdr::isValid() const
00600 {
00601     return (phdr32 || phdr64);
00602 }
00603 
00604 // ------------------------------------------------------------------------
00605 // Class Elf_X_Shdr simulates the Elf(32|64)_Shdr structure.
00606 Elf_X_Shdr::Elf_X_Shdr()
00607     : scn(NULL), data(NULL), shdr32(NULL), shdr64(NULL), is64(false),
00608       fromDebugFile(false), _elf(NULL)
00609 { }
00610 
00611 Elf_X_Shdr::Elf_X_Shdr(bool is64_, Elf_Scn *input)
00612     : scn(input), data(NULL), shdr32(NULL), shdr64(NULL), is64(is64_),
00613       fromDebugFile(false), _elf(NULL)
00614 {
00615     if (input) {
00616         first_data();
00617         if (!is64) shdr32 = elf32_getshdr(scn);
00618         else       shdr64 = elf64_getshdr(scn);
00619     }
00620 }
00621 
00622 // Read Interface
00623 unsigned long Elf_X_Shdr::sh_name() const
00624 {
00625     return (!is64 ?
00626             static_cast<unsigned long>(shdr32->sh_name) :
00627             static_cast<unsigned long>(shdr64->sh_name));
00628 }
00629 
00630 unsigned long Elf_X_Shdr::sh_type() const
00631 {
00632     return (!is64 ?
00633             static_cast<unsigned long>(shdr32->sh_type) :
00634             static_cast<unsigned long>(shdr64->sh_type));
00635 }
00636 
00637 unsigned long Elf_X_Shdr::sh_flags() const
00638 {
00639     return (!is64 ?
00640             static_cast<unsigned long>(shdr32->sh_flags) :
00641             static_cast<unsigned long>(shdr64->sh_flags));
00642 }
00643 
00644 unsigned long Elf_X_Shdr::sh_addr() const
00645 {
00646 #if defined(os_vxworks)
00647     assert(_elf);
00648     if (_elf->e_type() == ET_REL) {
00649         // VxWorks relocatable object files (kernel modules) don't have
00650         // the address filled out.  Return the disk offset instead.
00651         return (!is64 ?
00652                 static_cast<unsigned long>(shdr32->sh_offset) :
00653                 static_cast<unsigned long>(shdr64->sh_offset));
00654     }
00655 #endif
00656 
00657     return (!is64 ?
00658             static_cast<unsigned long>(shdr32->sh_addr) :
00659             static_cast<unsigned long>(shdr64->sh_addr));
00660 }
00661 
00662 unsigned long Elf_X_Shdr::sh_offset() const
00663 {
00664     return (!is64 ?
00665             static_cast<unsigned long>(shdr32->sh_offset) :
00666             static_cast<unsigned long>(shdr64->sh_offset));
00667 }
00668 
00669 unsigned long Elf_X_Shdr::sh_size() const
00670 {
00671     return (!is64 ?
00672             static_cast<unsigned long>(shdr32->sh_size) :
00673             static_cast<unsigned long>(shdr64->sh_size));
00674 }
00675 
00676 unsigned long Elf_X_Shdr::sh_link() const
00677 {
00678     return (!is64 ?
00679             shdr32->sh_link :
00680             shdr64->sh_link);
00681 }
00682 
00683 unsigned long Elf_X_Shdr::sh_info() const
00684 {
00685     return (!is64 ?
00686             static_cast<unsigned long>(shdr32->sh_info) :
00687             static_cast<unsigned long>(shdr64->sh_info));
00688 }
00689 
00690 unsigned long Elf_X_Shdr::sh_addralign() const
00691 {
00692     return (!is64 ?
00693             static_cast<unsigned long>(shdr32->sh_addralign) :
00694             static_cast<unsigned long>(shdr64->sh_addralign));
00695 }
00696 
00697 unsigned long Elf_X_Shdr::sh_entsize() const
00698 {
00699     return (!is64 ?
00700             static_cast<unsigned long>(shdr32->sh_entsize) :
00701             static_cast<unsigned long>(shdr64->sh_entsize));
00702 }
00703 
00704 bool Elf_X_Shdr::isFromDebugFile() const
00705 {
00706     return fromDebugFile;
00707 }
00708 
00709 // Write Interface
00710 void Elf_X_Shdr::sh_name(unsigned long input)
00711 {
00712     if (!is64) shdr32->sh_name = input;
00713     else       shdr64->sh_name = input;
00714 }
00715 
00716 void Elf_X_Shdr::sh_type(unsigned long input)
00717 {
00718     if (!is64) shdr32->sh_type = input;
00719     else       shdr64->sh_type = input;
00720 }
00721 
00722 void Elf_X_Shdr::sh_flags(unsigned long input)
00723 {
00724     if (!is64) shdr32->sh_flags = input;
00725     else       shdr64->sh_flags = input;
00726 }
00727 
00728 void Elf_X_Shdr::sh_addr(unsigned long input)
00729 {
00730     if (!is64) shdr32->sh_flags = input;
00731     else       shdr64->sh_flags = input;
00732 }
00733 
00734 void Elf_X_Shdr::sh_offset(unsigned long input)
00735 {
00736     if (!is64) shdr32->sh_offset = input;
00737     else       shdr64->sh_offset = input;
00738 }
00739 
00740 void Elf_X_Shdr::sh_size(unsigned long input)
00741 {
00742     if (!is64) shdr32->sh_size = input;
00743     else       shdr64->sh_size = input;
00744 }
00745 
00746 void Elf_X_Shdr::sh_link(unsigned long input)
00747 {
00748     if (!is64) shdr32->sh_link = input;
00749     else       shdr64->sh_link = input;
00750 }
00751 
00752 void Elf_X_Shdr::sh_info(unsigned long input)
00753 {
00754     if (!is64) shdr32->sh_info = input;
00755     else       shdr64->sh_info = input;
00756 }
00757 
00758 void Elf_X_Shdr::sh_addralign(unsigned long input)
00759 {
00760     if (!is64) shdr32->sh_addralign = input;
00761     else       shdr64->sh_addralign = input;
00762 }
00763 
00764 void Elf_X_Shdr::sh_entsize(unsigned long input)
00765 {
00766     if (!is64) shdr32->sh_entsize = input;
00767     else       shdr64->sh_entsize = input;
00768 }
00769 
00770 void Elf_X_Shdr::setDebugFile(bool b)
00771 {
00772     fromDebugFile = b;
00773 }
00774 
00775 // Section Data Interface
00776 Elf_X_Data Elf_X_Shdr::get_data() const
00777 {
00778     return Elf_X_Data(is64, data);
00779 }
00780 
00781 // For Sections with Multiple Data Sections
00782 void Elf_X_Shdr::first_data()
00783 {
00784     data = elf_getdata(scn, NULL);
00785 }
00786 
00787 bool Elf_X_Shdr::next_data()
00788 {
00789     Elf_Data *nextData = elf_getdata(scn, data);
00790     if (nextData) data = nextData;
00791     return nextData;
00792 }
00793 
00794 bool Elf_X_Shdr::isValid() const
00795 {
00796     return (shdr32 || shdr64);
00797 }
00798 
00799 unsigned Elf_X_Shdr::wordSize() const
00800 {
00801     return is64 ? 8 : 4;
00802 }
00803 
00804 Elf_Scn *Elf_X_Shdr::getScn() const
00805 {
00806     return scn;
00807 }
00808 
00809 Elf_X_Nhdr Elf_X_Shdr::get_note() const
00810 {
00811     if (sh_type() != SHT_NOTE)
00812         return Elf_X_Nhdr();
00813     return Elf_X_Nhdr(data, 0);
00814 }
00815 
00816 // ------------------------------------------------------------------------
00817 // Class Elf_X_Data simulates the Elf_Data structure.
00818 Elf_X_Data::Elf_X_Data()
00819     : data(NULL), is64(false)
00820 { }
00821 
00822 Elf_X_Data::Elf_X_Data(bool is64_, Elf_Data *input)
00823     : data(input), is64(is64_)
00824 { }
00825 
00826 // Read Interface
00827 void *Elf_X_Data::d_buf() const
00828 {
00829     return data->d_buf;
00830 }
00831 
00832 Elf_Type Elf_X_Data::d_type() const
00833 {
00834     return data->d_type;
00835 }
00836 
00837 unsigned int Elf_X_Data::d_version() const
00838 {
00839     return data->d_version;
00840 }
00841 
00842 size_t Elf_X_Data::d_size() const
00843 {
00844     return data->d_size;
00845 }
00846 
00847 off_t Elf_X_Data::d_off() const
00848 {
00849     return (off_t) data->d_off;
00850 }
00851 
00852 size_t Elf_X_Data::d_align() const
00853 {
00854     return data->d_align;
00855 }
00856 
00857 // Write Interface
00858 void Elf_X_Data::d_buf(void *input)
00859 {
00860     data->d_buf = input;
00861 }
00862 
00863 void Elf_X_Data::d_type(Elf_Type input)
00864 {
00865     data->d_type = input;
00866 }
00867 
00868 void Elf_X_Data::d_version(unsigned int input)
00869 {
00870     data->d_version = input;
00871 }
00872 
00873 void Elf_X_Data::d_size(unsigned int input)
00874 {
00875     data->d_size = input;
00876 }
00877 
00878 void Elf_X_Data::d_off(signed int input)
00879 {
00880     data->d_off = input;
00881 }
00882 
00883 void Elf_X_Data::d_align(unsigned int input)
00884 {
00885     data->d_align = input;
00886 }
00887 
00888 // Data Interface
00889 const char *Elf_X_Data::get_string() const
00890 {
00891     return (const char *)data->d_buf;
00892 }
00893 
00894 Elf_X_Dyn Elf_X_Data::get_dyn()
00895 {
00896     return Elf_X_Dyn(is64, data);
00897 }
00898 
00899 Elf_X_Versym Elf_X_Data::get_versyms()
00900 {
00901     return Elf_X_Versym(is64, data);
00902 }
00903 
00904 Elf_X_Verneed *Elf_X_Data::get_verNeedSym()
00905 {
00906     return new Elf_X_Verneed(is64, data->d_buf);
00907 }
00908 
00909 Elf_X_Verdef *Elf_X_Data::get_verDefSym()
00910 {
00911     return new Elf_X_Verdef(is64, data->d_buf);
00912 }
00913 
00914 Elf_X_Rel Elf_X_Data::get_rel()
00915 {
00916     return Elf_X_Rel(is64, data);
00917 }
00918 
00919 Elf_X_Rela Elf_X_Data::get_rela()
00920 {
00921     return Elf_X_Rela(is64, data);
00922 }
00923 
00924 Elf_X_Sym Elf_X_Data::get_sym()
00925 {
00926     return Elf_X_Sym(is64, data);
00927 }
00928 
00929 #if defined(arch_mips)
00930 Elf_X_Options Elf_X_Data::get_options()
00931 {
00932     return Elf_X_Options(is64, data);
00933 }
00934 #endif
00935 
00936 bool Elf_X_Data::isValid() const
00937 {
00938     return data;
00939 }
00940 
00941 // ------------------------------------------------------------------------
00942 // Class Elf_X_Versym simulates the SHT_GNU_versym structure.
00943 Elf_X_Versym::Elf_X_Versym()
00944     : data(NULL), versym32(NULL), versym64(NULL), is64(false)
00945 { }
00946 
00947 Elf_X_Versym::Elf_X_Versym(bool is64_, Elf_Data *input)
00948     : data(input), versym32(NULL), versym64(NULL), is64(is64_)
00949 {
00950     if (input) {
00951         if (!is64) versym32 = (Elf32_Half *)data->d_buf;
00952         else       versym64 = (Elf64_Half *)data->d_buf;
00953     }
00954 }
00955 
00956 // Read Interface
00957 unsigned long Elf_X_Versym::get(int i) const
00958 {
00959     return (!is64 ? versym32[i]
00960                   : versym64[i]);
00961 }
00962 
00963 // Meta-Info Interface
00964 unsigned long Elf_X_Versym::count() const
00965 {
00966     return (data->d_size / (!is64 ? sizeof(Elf32_Half)
00967                                   : sizeof(Elf64_Half) ));
00968 }
00969 
00970 bool Elf_X_Versym::isValid() const
00971 {
00972     return (versym32 || versym64);
00973 }
00974 
00975 // ------------------------------------------------------------------------
00976 // Class Elf_X_Verdaux simulates the Elf(32|64)_Verdaux structure.
00977 Elf_X_Verdaux::Elf_X_Verdaux()
00978     : data(NULL), verdaux32(NULL), verdaux64(NULL), is64(false)
00979 { }
00980 
00981 Elf_X_Verdaux::Elf_X_Verdaux(bool is64_, void *input)
00982     : data(input), verdaux32(NULL), verdaux64(NULL), is64(is64_)
00983 {
00984     if (input) {
00985         if (!is64) verdaux32 = (Elf32_Verdaux *)data;
00986         else       verdaux64 = (Elf64_Verdaux *)data;
00987     }
00988 }
00989 
00990 // Read Interface
00991 unsigned long Elf_X_Verdaux::vda_name() const
00992 {
00993     return (!is64 ? verdaux32->vda_name
00994                   : verdaux64->vda_name);
00995 }
00996 
00997 unsigned long Elf_X_Verdaux::vda_next() const
00998 {
00999     return (!is64 ? verdaux32->vda_next
01000                   : verdaux64->vda_next);
01001 }
01002 
01003 Elf_X_Verdaux *Elf_X_Verdaux::get_next() const
01004 {
01005     if (vda_next() == 0)
01006         return NULL;
01007     return new Elf_X_Verdaux(is64, (char *)data+vda_next());
01008 }
01009 
01010 // Meta-Info Interface
01011 bool Elf_X_Verdaux::isValid() const
01012 {
01013     return (verdaux32 || verdaux64);
01014 }
01015 
01016 // ------------------------------------------------------------------------
01017 // Class Elf_X_Verdef simulates the Elf(32|64)_Verdef structure.
01018 Elf_X_Verdef::Elf_X_Verdef()
01019     : data(NULL), verdef32(NULL), verdef64(NULL), is64(false)
01020 { }
01021 
01022 Elf_X_Verdef::Elf_X_Verdef(bool is64_, void *input)
01023     : data(input), verdef32(NULL), verdef64(NULL), is64(is64_)
01024 {
01025     if (input) {
01026         if (!is64) verdef32 = (Elf32_Verdef *)data;
01027         else       verdef64 = (Elf64_Verdef *)data;
01028     }
01029 }
01030 
01031 // Read Interface
01032 unsigned long Elf_X_Verdef::vd_version() const
01033 {
01034     return (!is64 ? verdef32->vd_version
01035                   : verdef64->vd_version);
01036 }
01037 
01038 unsigned long Elf_X_Verdef::vd_flags() const
01039 {
01040     return (!is64 ? verdef32->vd_flags
01041                   : verdef64->vd_flags);
01042 }
01043 
01044 unsigned long Elf_X_Verdef::vd_ndx() const
01045 {
01046     return (!is64 ? verdef32->vd_ndx
01047                   : verdef64->vd_ndx);
01048 }
01049 
01050 unsigned long Elf_X_Verdef::vd_cnt() const
01051 {
01052     return (!is64 ? verdef32->vd_cnt
01053                   : verdef64->vd_cnt);
01054 }
01055 
01056 unsigned long Elf_X_Verdef::vd_hash() const
01057 {
01058     return (!is64 ? verdef32->vd_hash
01059                   : verdef64->vd_hash);
01060 }
01061 
01062 unsigned long Elf_X_Verdef::vd_aux() const
01063 {
01064     return (!is64 ? verdef32->vd_aux
01065                   : verdef64->vd_aux);
01066 }
01067 
01068 unsigned long Elf_X_Verdef::vd_next() const
01069 {
01070     return (!is64 ? verdef32->vd_next
01071                   : verdef64->vd_next);
01072 }
01073 
01074 Elf_X_Verdaux *Elf_X_Verdef::get_aux() const
01075 {
01076     if (vd_cnt() == 0)
01077         return NULL;
01078     return new Elf_X_Verdaux(is64, (char *)data+vd_aux());
01079 }
01080 
01081 Elf_X_Verdef *Elf_X_Verdef::get_next() const
01082 {
01083     if (vd_next() == 0)
01084         return NULL;
01085     return new Elf_X_Verdef(is64, (char *)data+vd_next());
01086 }
01087 
01088 // Meta-Info Interface
01089 bool Elf_X_Verdef::isValid() const
01090 {
01091     return (verdef32 || verdef64);
01092 }
01093 
01094 // ------------------------------------------------------------------------
01095 // Class Elf_X_Vernaux simulates the Elf(32|64)_Vernaux structure.
01096 Elf_X_Vernaux::Elf_X_Vernaux()
01097     : data(NULL), vernaux32(NULL), vernaux64(NULL), is64(false)
01098 { }
01099 
01100 Elf_X_Vernaux::Elf_X_Vernaux(bool is64_, void *input)
01101     : data(input), vernaux32(NULL), vernaux64(NULL), is64(is64_)
01102 {
01103     if (input) {
01104         if (!is64) vernaux32 = (Elf32_Vernaux *)data;
01105         else       vernaux64 = (Elf64_Vernaux *)data;
01106     }
01107 }
01108 
01109 // Read Interface
01110 unsigned long Elf_X_Vernaux::vna_hash() const
01111 {
01112     return (!is64 ? vernaux32->vna_hash
01113                   : vernaux64->vna_hash);
01114 }
01115 
01116 unsigned long Elf_X_Vernaux::vna_flags() const
01117 {
01118     return (!is64 ? vernaux32->vna_flags
01119                   : vernaux64->vna_flags);
01120 }
01121 
01122 unsigned long Elf_X_Vernaux::vna_other() const
01123 {
01124     return (!is64 ? vernaux32->vna_other
01125                   : vernaux64->vna_other);
01126 }
01127 
01128 unsigned long Elf_X_Vernaux::vna_name() const
01129 {
01130     return (!is64 ? vernaux32->vna_name
01131                   : vernaux64->vna_name);
01132 }
01133 
01134 unsigned long Elf_X_Vernaux::vna_next() const
01135 {
01136     return (!is64 ? vernaux32->vna_next
01137                   : vernaux64->vna_next);
01138 }
01139 
01140 Elf_X_Vernaux *Elf_X_Vernaux::get_next() const
01141 {
01142     if (vna_next() == 0)
01143         return NULL;
01144     return new Elf_X_Vernaux(is64, (char *)data+vna_next());
01145 }
01146 
01147 // Meta-Info Interface
01148 bool Elf_X_Vernaux::isValid() const
01149 {
01150     return (vernaux32 || vernaux64);
01151 }
01152 
01153 // ------------------------------------------------------------------------
01154 // Class Elf_X_Verneed simulates the Elf(32|64)_Verneed structure.
01155 Elf_X_Verneed::Elf_X_Verneed()
01156     : data(NULL), verneed32(NULL), verneed64(NULL), is64(false)
01157 { }
01158 
01159 Elf_X_Verneed::Elf_X_Verneed(bool is64_, void *input)
01160     : data(input), verneed32(NULL), verneed64(NULL), is64(is64_)
01161 {
01162     if (input) {
01163         if (!is64) verneed32 = (Elf32_Verneed *)data;
01164         else       verneed64 = (Elf64_Verneed *)data;
01165     }
01166 }
01167 
01168 // Read Interface
01169 unsigned long Elf_X_Verneed::vn_version() const
01170 {
01171     return (!is64 ? verneed32->vn_version
01172                   : verneed64->vn_version);
01173 }
01174 
01175 unsigned long Elf_X_Verneed::vn_cnt() const
01176 {
01177     return (!is64 ? verneed32->vn_cnt
01178             : verneed64->vn_cnt);
01179 }
01180 
01181 unsigned long Elf_X_Verneed::vn_file() const
01182 {
01183     return (!is64 ? verneed32->vn_file
01184                   : verneed64->vn_file);
01185 }
01186 
01187 unsigned long Elf_X_Verneed::vn_aux() const
01188 {
01189     return (!is64 ? verneed32->vn_aux
01190                   : verneed64->vn_aux);
01191 }
01192 
01193 unsigned long Elf_X_Verneed::vn_next() const
01194 {
01195     return (!is64 ? verneed32->vn_next
01196             : verneed64->vn_next);
01197 }
01198 
01199 Elf_X_Vernaux *Elf_X_Verneed::get_aux() const
01200 {
01201     if (vn_cnt() == 0)
01202         return NULL;
01203     return new Elf_X_Vernaux(is64, (char *)data+vn_aux());
01204 }
01205 
01206 Elf_X_Verneed *Elf_X_Verneed::get_next() const
01207 {
01208     if (vn_next() == 0)
01209         return NULL;
01210     return new Elf_X_Verneed(is64, (char *)data+vn_next());
01211 }
01212 
01213 // Meta-Info Interface
01214 bool Elf_X_Verneed::isValid() const
01215 {
01216     return (verneed32 || verneed64);
01217 }
01218 
01219 
01220 // ------------------------------------------------------------------------
01221 // Class Elf_X_Sym simulates the Elf(32|64)_Sym structure.
01222 Elf_X_Sym::Elf_X_Sym()
01223     : data(NULL), sym32(NULL), sym64(NULL), is64(false)
01224 { }
01225 
01226 Elf_X_Sym::Elf_X_Sym(bool is64_, Elf_Data *input)
01227     : data(input), sym32(NULL), sym64(NULL), is64(is64_)
01228 {
01229     if (input) {
01230         if (!is64) sym32 = (Elf32_Sym *)data->d_buf;
01231         else       sym64 = (Elf64_Sym *)data->d_buf;
01232     }
01233 }
01234 
01235 // Read Interface
01236 unsigned long Elf_X_Sym::st_name(int i) const
01237 {
01238     return (!is64 ?
01239             static_cast<unsigned long>(sym32[i].st_name) :
01240             static_cast<unsigned long>(sym64[i].st_name));
01241 }
01242 
01243 unsigned long Elf_X_Sym::st_value(int i) const
01244 {
01245     return (!is64 ?
01246             static_cast<unsigned long>(sym32[i].st_value) :
01247             static_cast<unsigned long>(sym64[i].st_value));
01248 }
01249 
01250 unsigned long Elf_X_Sym::st_size(int i) const
01251 {
01252     return (!is64 ?
01253             static_cast<unsigned long>(sym32[i].st_size) :
01254             static_cast<unsigned long>(sym64[i].st_size));
01255 }
01256 
01257 unsigned char Elf_X_Sym::st_info(int i) const
01258 {
01259     return (!is64 ?
01260             sym32[i].st_info :
01261             sym64[i].st_info);
01262 }
01263 
01264 unsigned char Elf_X_Sym::st_other(int i) const
01265 {
01266     return (!is64 ?
01267             sym32[i].st_other :
01268             sym64[i].st_other);
01269 }
01270 
01271 unsigned short Elf_X_Sym::st_shndx(int i) const
01272 {
01273     return (!is64 ?
01274             sym32[i].st_shndx :
01275             sym64[i].st_shndx);
01276 }
01277 
01278 unsigned char Elf_X_Sym::ST_BIND(int i) const
01279 {
01280     return (!is64 ?
01281             static_cast<unsigned char>(ELF32_ST_BIND(sym32[i].st_info)) :
01282             static_cast<unsigned char>(ELF64_ST_BIND(sym64[i].st_info)));
01283 }
01284 
01285 unsigned char Elf_X_Sym::ST_TYPE(int i) const
01286 {
01287     return (!is64 ?
01288             static_cast<unsigned char>(ELF32_ST_TYPE(sym32[i].st_info)) :
01289             static_cast<unsigned char>(ELF64_ST_TYPE(sym64[i].st_info)));
01290 }
01291 
01292 unsigned char Elf_X_Sym::ST_VISIBILITY(int i) const
01293 {
01294     return (!is64 ?
01295             static_cast<unsigned char>(ELF32_ST_VISIBILITY(sym32[i].st_other)) :
01296             static_cast<unsigned char>(ELF64_ST_VISIBILITY(sym64[i].st_other)));
01297 }
01298 
01299 void *Elf_X_Sym::st_symptr(int i) const
01300 {
01301     return (!is64 ?
01302             (void *)(sym32 + i) :
01303             (void *)(sym64 + i));
01304 }
01305 
01306 unsigned Elf_X_Sym::st_entsize() const
01307 {
01308     return (is64 ?
01309             sizeof(Elf64_Sym) :
01310             sizeof(Elf32_Sym));
01311 }
01312 
01313 // Write Interface
01314 void Elf_X_Sym::st_name(int i, unsigned long input)
01315 {
01316     if (!is64) sym32[i].st_name = input;
01317     else       sym64[i].st_name = input;
01318 }
01319 
01320 void Elf_X_Sym::st_value(int i, unsigned long input)
01321 {
01322     if (!is64) sym32[i].st_value = input;
01323     else       sym64[i].st_value = input;
01324 }
01325 
01326 void Elf_X_Sym::st_size(int i, unsigned long input)
01327 {
01328     if (!is64) sym32[i].st_size = input;
01329     else       sym64[i].st_size = input;
01330 }
01331 
01332 void Elf_X_Sym::st_info(int i, unsigned char input)
01333 {
01334     if (!is64) sym32[i].st_info = input;
01335     else       sym64[i].st_info = input;
01336 }
01337 
01338 void Elf_X_Sym::st_other(int i, unsigned char input)
01339 {
01340     if (!is64) sym32[i].st_other = input;
01341     else       sym64[i].st_other = input;
01342 }
01343 
01344 void Elf_X_Sym::st_shndx(int i, unsigned short input)
01345 {
01346     if (!is64) sym32[i].st_shndx = input;
01347     else       sym64[i].st_shndx = input;
01348 }
01349 
01350 // Meta-Info Interface
01351 unsigned long Elf_X_Sym::count() const
01352 {
01353     return (data->d_size / (!is64 ? sizeof(Elf32_Sym)
01354                                   : sizeof(Elf64_Sym)));
01355 }
01356 
01357 bool Elf_X_Sym::isValid() const
01358 {
01359     return sym32 || sym64;
01360 }
01361 
01362 // ------------------------------------------------------------------------
01363 // Class Elf_X_Rel simulates the Elf(32|64)_Rel structure.
01364 Elf_X_Rel::Elf_X_Rel()
01365     : data(NULL), rel32(NULL), rel64(NULL), is64(false)
01366 { }
01367 
01368 Elf_X_Rel::Elf_X_Rel(bool is64_, Elf_Data *input)
01369     : data(input), rel32(NULL), rel64(NULL), is64(is64_)
01370 {
01371     if (input) {
01372         if (!is64) 
01373             rel32 = (Elf32_Rel *)data->d_buf;
01374         else       
01375             rel64 = (Elf64_Rel *)data->d_buf;
01376     }
01377 }
01378 
01379 // Read Interface
01380 unsigned long Elf_X_Rel::r_offset(int i) const
01381 {
01382     return (!is64 ?
01383             static_cast<unsigned long>(rel32[i].r_offset) :
01384             static_cast<unsigned long>(rel64[i].r_offset));
01385 }
01386 
01387 unsigned long Elf_X_Rel::r_info(int i) const
01388 {
01389     return (!is64 ?
01390             static_cast<unsigned long>(rel32[i].r_info) :
01391             static_cast<unsigned long>(rel64[i].r_info));
01392 }
01393 
01394 unsigned long Elf_X_Rel::R_SYM(int i) const
01395 {
01396     return (!is64 ?
01397             static_cast<unsigned long>(ELF32_R_SYM(rel32[i].r_info)) :
01398             static_cast<unsigned long>(ELF64_R_SYM(rel64[i].r_info)));
01399 }
01400 
01401 unsigned long Elf_X_Rel::R_TYPE(int i) const
01402 {
01403     return (!is64 ?
01404             static_cast<unsigned long>(ELF32_R_TYPE(rel32[i].r_info)) :
01405             static_cast<unsigned long>(ELF64_R_TYPE(rel64[i].r_info)));
01406 };
01407 
01408 // Write Interface
01409 void Elf_X_Rel::r_offset(int i, unsigned long input)
01410 {
01411     if (!is64)
01412         rel32[i].r_offset = input;
01413     else
01414         rel64[i].r_offset = input;
01415 }
01416 
01417 void Elf_X_Rel::r_info(int i, unsigned long input)
01418 {
01419     if (!is64)
01420         rel32[i].r_info = input;
01421     else
01422         rel64[i].r_info = input;
01423 }
01424 
01425 // Meta-Info Interface
01426 unsigned long Elf_X_Rel::count() const
01427 {
01428     return (data->d_size / (!is64 ? sizeof(Elf32_Rel)
01429                                   : sizeof(Elf64_Rel)) );
01430 }
01431 
01432 bool Elf_X_Rel::isValid() const
01433 {
01434     return (rel32 || rel64);
01435 }
01436 
01437 // ------------------------------------------------------------------------
01438 // Class Elf_X_Rela simulates the Elf(32|64)_Rela structure.
01439 Elf_X_Rela::Elf_X_Rela()
01440     : data(NULL), rela32(NULL), rela64(NULL), is64(false)
01441 { }
01442 
01443 Elf_X_Rela::Elf_X_Rela(bool is64_, Elf_Data *input)
01444     : data(input), rela32(NULL), rela64(NULL), is64(is64_)
01445 {
01446     if (input) {
01447         if (!is64) 
01448             rela32 = (Elf32_Rela *)data->d_buf;
01449         else       
01450             rela64 = (Elf64_Rela *)data->d_buf;
01451     }
01452 }
01453 
01454 // Read Interface
01455 unsigned long Elf_X_Rela::r_offset(int i) const
01456 {
01457     return (!is64 ?
01458             static_cast<unsigned long>(rela32[i].r_offset) :
01459             static_cast<unsigned long>(rela64[i].r_offset));
01460 }
01461 
01462 unsigned long Elf_X_Rela::r_info(int i) const
01463 {
01464     return (!is64 ?
01465             static_cast<unsigned long>(rela32[i].r_info) :
01466             static_cast<unsigned long>(rela64[i].r_info));
01467 }
01468 
01469 signed long Elf_X_Rela::r_addend(int i) const
01470 {
01471     return (!is64 ?
01472             static_cast<signed long>(rela32[i].r_addend) :
01473             static_cast<signed long>(rela64[i].r_addend));
01474 }
01475 
01476 unsigned long Elf_X_Rela::R_SYM(int i) const
01477 {
01478     return (!is64 ?
01479             static_cast<unsigned long>(ELF32_R_SYM(rela32[i].r_info)) :
01480             static_cast<unsigned long>(ELF64_R_SYM(rela64[i].r_info)));
01481 }
01482 
01483 unsigned long Elf_X_Rela::R_TYPE(int i) const
01484 {
01485     return (!is64 ?
01486             static_cast<unsigned long>(ELF32_R_TYPE(rela32[i].r_info)) :
01487             static_cast<unsigned long>(ELF64_R_TYPE(rela64[i].r_info)));
01488 }
01489 
01490 // Write Interface
01491 void Elf_X_Rela::r_offset(int i, unsigned long input)
01492 {
01493     if (!is64)
01494         rela32[i].r_offset = input;
01495     else
01496         rela64[i].r_offset = input;
01497 }
01498 
01499 void Elf_X_Rela::r_info(int i, unsigned long input)
01500 {
01501     if (!is64)
01502         rela32[i].r_info = input;
01503     else
01504         rela64[i].r_info = input;
01505 }
01506 
01507 void Elf_X_Rela::r_addend(int i, signed long input)
01508 {
01509     if (!is64)
01510         rela32[i].r_addend = input;
01511     else
01512         rela64[i].r_addend = input;
01513 }
01514 
01515 // Meta-Info Interface
01516 unsigned long Elf_X_Rela::count() const
01517 {
01518     return (data->d_size / (!is64 ? sizeof(Elf32_Rela)
01519                                   : sizeof(Elf64_Rela)));
01520 }
01521 
01522 bool Elf_X_Rela::isValid() const
01523 {
01524     return (rela32 || rela64);
01525 }
01526 
01527 
01528 // ------------------------------------------------------------------------
01529 // Class Elf_X_Dyn simulates the Elf(32|64)_Dyn structure.
01530 Elf_X_Dyn::Elf_X_Dyn()
01531     : data(NULL), dyn32(NULL), dyn64(NULL), is64(false)
01532 { }
01533 
01534 Elf_X_Dyn::Elf_X_Dyn(bool is64_, Elf_Data *input)
01535     : data(input), dyn32(NULL), dyn64(NULL), is64(is64_)
01536 {
01537     if (input) {
01538         if (!is64) dyn32 = (Elf32_Dyn *)data->d_buf;
01539         else       dyn64 = (Elf64_Dyn *)data->d_buf;
01540     }
01541 }
01542 
01543 // Read Interface
01544 signed long Elf_X_Dyn::d_tag(int i) const
01545 { 
01546     return (!is64 ?
01547             static_cast<signed long>(dyn32[i].d_tag) :
01548             static_cast<signed long>(dyn64[i].d_tag));
01549 }
01550 
01551 unsigned long Elf_X_Dyn::d_val(int i) const
01552 {
01553     return (!is64 ?
01554             static_cast<unsigned long>(dyn32[i].d_un.d_val) :
01555             static_cast<unsigned long>(dyn64[i].d_un.d_val));
01556 }
01557 
01558 unsigned long Elf_X_Dyn::d_ptr(int i) const
01559 {
01560     return (!is64 ?
01561             static_cast<unsigned long>(dyn32[i].d_un.d_ptr) :
01562             static_cast<unsigned long>(dyn64[i].d_un.d_ptr));
01563 }
01564 
01565 // Write Interface
01566 void Elf_X_Dyn::d_tag(int i, signed long input)
01567 {
01568     if (!is64) dyn32[i].d_tag = input;
01569     else       dyn64[i].d_tag = input;
01570 }
01571 
01572 void Elf_X_Dyn::d_val(int i, unsigned long input)
01573 {
01574     if (!is64) dyn32[i].d_un.d_val = input;
01575     else       dyn64[i].d_un.d_val = input;
01576 }
01577 
01578 void Elf_X_Dyn::d_ptr(int i, unsigned long input)
01579 {
01580     if (!is64) dyn32[i].d_un.d_ptr = input;
01581     else       dyn64[i].d_un.d_ptr = input;
01582 }
01583 
01584 // Meta-Info Interface
01585 unsigned long Elf_X_Dyn::count() const
01586 {
01587     return (data->d_size / (!is64 ? sizeof(Elf32_Dyn)
01588                                   : sizeof(Elf64_Dyn) ));
01589 }
01590 
01591 bool Elf_X_Dyn::isValid() const
01592 {
01593     return (dyn32 || dyn64);
01594 }
01595 
01596 static bool loadDebugFileFromDisk(string name, char* &output_buffer, unsigned long &output_buffer_size)
01597 {
01598    struct stat fileStat;
01599    int result = stat(name.c_str(), &fileStat);
01600    if (result == -1)
01601       return false;
01602    if (S_ISDIR(fileStat.st_mode))
01603       return false;
01604    int fd = open(name.c_str(), O_RDONLY);
01605    if (fd == -1)
01606       return false;
01607 
01608    char *buffer = (char *) mmap(NULL, fileStat.st_size, PROT_READ, MAP_SHARED, fd, 0);
01609    close(fd);
01610    if (!buffer)
01611       return false;
01612 
01613    output_buffer = buffer;
01614    output_buffer_size = fileStat.st_size;
01615 
01616    return true;
01617 }
01618 
01619 // The standard procedure to look for a separate debug information file
01620 // is as follows:
01621 // 1. Lookup build_id from .note.gnu.build-id section and debug-file-name and
01622 //    crc from .gnu_debuglink section of the original binary.
01623 // 2. Look for the following files:
01624 //        /usr/lib/debug/.build-id/<path-obtained-using-build-id>.debug
01625 //        <debug-file-name> in <directory-of-executable>
01626 //        <debug-file-name> in <directory-of-executable>/.debug
01627 //        <debug-file-name> in /usr/lib/debug/<directory-of-executable>
01628 // Reference: http://sourceware.org/gdb/current/onlinedocs/gdb_16.html#SEC157
01629 bool Elf_X::findDebugFile(std::string origfilename, string &output_name, char* &output_buffer, unsigned long &output_buffer_size)
01630 {
01631    if (cached_debug) {
01632       output_buffer = cached_debug_buffer;
01633       output_buffer_size = cached_debug_size;
01634       output_name = cached_debug_name;
01635       return (output_buffer != NULL);
01636    }
01637    cached_debug = true;
01638 
01639    uint16_t shnames_idx = e_shstrndx();
01640    Elf_X_Shdr shnames_hdr = get_shdr(shnames_idx);
01641    if (!shnames_hdr.isValid())
01642       return false;
01643    const char *shnames = (const char *) shnames_hdr.get_data().d_buf();
01644    
01645   string debugFileFromDebugLink, debugFileFromBuildID;
01646   unsigned debugFileCrc = 0;
01647 
01648   for(int i = 0; i < e_shnum(); i++) {
01649      Elf_X_Shdr scn = get_shdr(i);
01650      if (!scn.isValid()) { // section is malformed
01651         continue;
01652      }
01653 
01654      const char *name = &shnames[scn.sh_name()];
01655      if(strcmp(name, DEBUGLINK_NAME) == 0) {
01656         Elf_X_Data data = scn.get_data();
01657         debugFileFromDebugLink = (char *) data.d_buf();
01658         void *crcLocation = ((char *) data.d_buf() + data.d_size() - 4);
01659         debugFileCrc = *(unsigned *) crcLocation;
01660      }
01661      else if (scn.sh_type() == SHT_NOTE) {
01662         // Look for a build-id note in this section.  It is usually a note by
01663         // itself in section .note.gnu.build-id, but not necessarily so.
01664         for (Elf_X_Nhdr note = scn.get_note();
01665               note.isValid(); note = note.next()) {
01666            if (note.n_type() == 3 // NT_GNU_BUILD_ID
01667                  && note.n_namesz() == sizeof("GNU")
01668                  && strcmp(note.get_name(), "GNU") == 0
01669                  && note.n_descsz() >= 2) {
01670               // This is a raw build-id, now convert it to hex
01671               const unsigned char *desc = (const unsigned char *)note.get_desc();
01672               stringstream buildid_path;
01673               buildid_path << "/usr/lib/debug/.build-id/"
01674                  << hex << setfill('0') << setw(2) << (unsigned)desc[0] << '/';
01675               for (unsigned long j = 1; j < note.n_descsz(); ++j)
01676                  buildid_path << (unsigned)desc[j];
01677               buildid_path << ".debug";
01678               debugFileFromBuildID = buildid_path.str();
01679               break;
01680            }
01681         }
01682      }
01683   }
01684 
01685   if (!debugFileFromBuildID.empty()) {
01686      bool result = loadDebugFileFromDisk(debugFileFromBuildID, output_buffer, output_buffer_size);
01687      if (result) {
01688         output_name = debugFileFromBuildID;
01689         cached_debug_buffer = output_buffer;
01690         cached_debug_size = output_buffer_size;
01691         cached_debug_name = output_name;
01692         return true;
01693      }
01694   }
01695 
01696   if (debugFileFromDebugLink.empty())
01697      return false;
01698 
01699   char *mfPathNameCopy = strdup(origfilename.c_str());
01700   string objectFileDirName = dirname(mfPathNameCopy);
01701 
01702   vector<string> fnames = list_of
01703     (objectFileDirName + "/" + debugFileFromDebugLink)
01704     (objectFileDirName + "/.debug/" + debugFileFromDebugLink)
01705     ("/usr/lib/debug/" + objectFileDirName + "/" + debugFileFromDebugLink);
01706 
01707   free(mfPathNameCopy);
01708 
01709   for(unsigned i = 0; i < fnames.size(); i++) {
01710      bool result = loadDebugFileFromDisk(fnames[i], output_buffer, output_buffer_size);
01711      if (!result)
01712         continue;
01713     
01714     boost::crc_32_type crcComputer;
01715     crcComputer.process_bytes(output_buffer, output_buffer_size);
01716     if(crcComputer.checksum() != debugFileCrc) {
01717        munmap(output_buffer, output_buffer_size);
01718        continue;
01719     }
01720 
01721     output_name = fnames[i];
01722     cached_debug_buffer = output_buffer;
01723     cached_debug_size = output_buffer_size;
01724     cached_debug_name = output_name;
01725     return true;
01726   }
01727 
01728   return false;
01729 }
01730 
01731 // ------------------------------------------------------------------------
01732 // Class Elf_X_Nhdr simulates the Elf(32|64)_Nhdr structure.
01733 Elf_X_Nhdr::Elf_X_Nhdr()
01734     : data(NULL), nhdr(NULL)
01735 { }
01736 
01737 Elf_X_Nhdr::Elf_X_Nhdr(Elf_Data *data_, size_t offset)
01738     : data(data_), nhdr(NULL)
01739 {
01740     // 32|64 are actually the same, which simplifies things
01741     assert(sizeof(Elf32_Nhdr) == sizeof(Elf64_Nhdr));
01742 
01743     if (data && offset < data->d_size) {
01744         size_t size = data->d_size - offset;
01745         if (sizeof(*nhdr) <= size) {
01746             size -= sizeof(*nhdr);
01747             nhdr = (Elf32_Nhdr *)((char *)data->d_buf + offset);
01748             if (n_namesz() > size || n_descsz() > size - n_namesz())
01749                 nhdr = NULL;
01750         }
01751     }
01752     if (!nhdr)
01753         data = NULL;
01754 }
01755 
01756 // Read Interface
01757 unsigned long Elf_X_Nhdr::n_namesz() const
01758 {
01759     return isValid() ? nhdr->n_namesz : 0;
01760 }
01761 
01762 unsigned long Elf_X_Nhdr::n_descsz() const
01763 {
01764     return isValid() ? nhdr->n_descsz : 0;
01765 }
01766 
01767 unsigned long Elf_X_Nhdr::n_type() const
01768 {
01769     return isValid() ? nhdr->n_type : 0;
01770 }
01771 
01772 bool Elf_X_Nhdr::isValid() const
01773 {
01774     return (data && nhdr);
01775 }
01776 
01777 const char* Elf_X_Nhdr::get_name() const
01778 {
01779     return isValid() ? (char *)nhdr + sizeof(*nhdr) : NULL;
01780 }
01781 
01782 const void* Elf_X_Nhdr::get_desc() const
01783 {
01784     return isValid() ? get_name() + n_namesz() : NULL;
01785 }
01786 
01787 Elf_X_Nhdr Elf_X_Nhdr::next() const
01788 {
01789     if (!isValid())
01790         return Elf_X_Nhdr();
01791 
01792     size_t offset = (char *)get_desc() + n_descsz() - (char *)data->d_buf;
01793     return Elf_X_Nhdr(data, offset);
01794 }
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on 12 Jul 2013 for SymtabAPI by  doxygen 1.6.1