00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include "ElfBinaryFile.h"
00035 #include <sys/types.h>
00036 #include <sys/stat.h>
00037 #include <fcntl.h>
00038 #include <iostream>
00039 #include <assert.h>
00040 #include "config.h"
00041 #if defined(_MSC_VER) && _MSC_VER >= 1400
00042 #pragma warning(disable:4996) // Warnings about e.g. _strdup deprecated in VS 2005
00043 #endif
00044
00045 typedef std::map<std::string, int, std::less<std::string> > StrIntMap;
00046
00047 ElfBinaryFile::ElfBinaryFile(bool bArchive )
00048 : BinaryFile(bArchive),
00049 next_extern(0)
00050 {
00051 m_fd = 0;
00052 m_pFileName = 0;
00053 Init();
00054 }
00055
00056 ElfBinaryFile::~ElfBinaryFile()
00057 {
00058 if (m_pImportStubs)
00059
00060 delete [] m_pImportStubs;
00061 }
00062
00063
00064
00065 void ElfBinaryFile::Init()
00066 {
00067 m_pImage = 0;
00068 m_pPhdrs = 0;
00069 m_pShdrs = 0;
00070 m_pStrings = 0;
00071 m_pReloc = 0;
00072 m_pSym = 0;
00073 m_uPltMin = 0;
00074 m_uPltMax = 0;
00075 m_iLastSize = 0;
00076 m_pImportStubs = 0;
00077 }
00078
00079
00080 extern "C" {
00081 unsigned elf_hash(const char* o0) {
00082 int o3 = *o0;
00083 const char* g1 = o0;
00084 unsigned o4 = 0;
00085 while (o3 != 0) {
00086 o4 <<= 4;
00087 o3 += o4;
00088 g1++;
00089 o4 = o3 & 0xf0000000;
00090 if (o4 != 0) {
00091 int o2 = (int)((unsigned)o4 >> 24);
00092 o3 = o3 ^ o2;
00093 }
00094 o4 = o3 & ~o4;
00095 o3 = *g1;
00096 }
00097 return o4;
00098 }
00099 }
00100
00101
00102 bool ElfBinaryFile::RealLoad(const char* sName)
00103 {
00104 int i;
00105
00106 if (m_bArchive) {
00107
00108 return false;
00109 }
00110
00111 m_pFileName = sName;
00112 m_fd = fopen (sName, "rb");
00113 if (m_fd == NULL) return 0;
00114
00115
00116 if (fseek(m_fd, 0, SEEK_END)) {
00117 fprintf(stderr, "Error seeking to end of binary file\n");
00118 return false;
00119 }
00120 m_lImageSize = ftell(m_fd);
00121
00122
00123 m_pImage = new char[m_lImageSize];
00124 if (m_pImage == 0) {
00125 fprintf(stderr, "Could not allocate %ld bytes for program image\n", m_lImageSize);
00126 return false;
00127 }
00128 Elf32_Ehdr* pHeader = (Elf32_Ehdr*)m_pImage;
00129
00130
00131 fseek(m_fd, 0, SEEK_SET);
00132 size_t size = fread(m_pImage, 1, m_lImageSize, m_fd);
00133 if (size != (size_t)m_lImageSize)
00134 fprintf(stderr, "WARNING! Only read %ud of %ld bytes of binary file!\n", size, m_lImageSize);
00135
00136
00137 if (strncmp(m_pImage, "\x7F""ELF", 4) != 0) {
00138 fprintf(stderr, "Incorrect header: %02X %02X %02X %02X\n",
00139 pHeader->e_ident[0], pHeader->e_ident[1], pHeader->e_ident[2],
00140 pHeader->e_ident[3]);
00141 return 0;
00142 }
00143 if ((pHeader->endianness != 1) && (pHeader->endianness != 2)) {
00144 fprintf(stderr, "Unknown endianness %02X\n", pHeader->endianness);
00145 return 0;
00146 }
00147
00148 m_elfEndianness = pHeader->endianness - 1;
00149
00150
00151 i = elfRead4(&pHeader->e_phoff);
00152 if (i) m_pPhdrs = (Elf32_Phdr*)(m_pImage + i);
00153
00154
00155 i = elfRead4(&pHeader->e_shoff);
00156 if (i) m_pShdrs = (Elf32_Shdr*)(m_pImage + i);
00157
00158
00159
00160
00161 i = elfRead2(&pHeader->e_shstrndx);
00162 if (i) m_pStrings = m_pImage + elfRead4(&m_pShdrs[i].sh_offset);
00163
00164 i = 1;
00165 char* pName;
00166
00167
00168 m_iNumSections = elfRead2(&pHeader->e_shnum);
00169
00170
00171 m_pSections = new SectionInfo[m_iNumSections];
00172 if (m_pSections == 0) return false;
00173
00174
00175 m_sh_link = new int[m_iNumSections];
00176 m_sh_info = new int[m_iNumSections];
00177
00178
00179 bool bGotCode = false;
00180 ADDRESS arbitaryLoadAddr = 0x08000000;
00181 for (i=0; i < m_iNumSections; i++) {
00182
00183 Elf32_Shdr* pShdr = m_pShdrs + i;
00184 if ((char*)pShdr > m_pImage + m_lImageSize) {
00185 std::cerr << "section " << i << " header is outside the image size\n";
00186 return false;
00187 }
00188 pName = m_pStrings + elfRead4(&pShdr->sh_name);
00189 if (pName > m_pImage + m_lImageSize) {
00190 std::cerr << "name for section " << i << " is outside the image size\n";
00191 return false;
00192 }
00193 m_pSections[i].pSectionName = pName;
00194 int off = elfRead4(&pShdr->sh_offset);
00195 if (off) m_pSections[i].uHostAddr = (ADDRESS)(m_pImage + off);
00196 m_pSections[i].uNativeAddr = elfRead4(&pShdr->sh_addr);
00197 m_pSections[i].uSectionSize = elfRead4(&pShdr->sh_size);
00198 if (m_pSections[i].uNativeAddr == 0 && strncmp(pName, ".rel", 4)) {
00199 int align = elfRead4(&pShdr->sh_addralign);
00200 if (align > 1) {
00201 if (arbitaryLoadAddr % align)
00202 arbitaryLoadAddr += align - (arbitaryLoadAddr % align);
00203 }
00204 m_pSections[i].uNativeAddr = arbitaryLoadAddr;
00205 arbitaryLoadAddr += m_pSections[i].uSectionSize;
00206 }
00207 m_pSections[i].uType = elfRead4(&pShdr->sh_type);
00208 m_sh_link[i] = elfRead4(&pShdr->sh_link);
00209 m_sh_info[i] = elfRead4(&pShdr->sh_info);
00210 m_pSections[i].uSectionEntrySize = elfRead4(&pShdr->sh_entsize);
00211 if (m_pSections[i].uNativeAddr + m_pSections[i].uSectionSize > next_extern)
00212 first_extern = next_extern = m_pSections[i].uNativeAddr + m_pSections[i].uSectionSize;
00213 if ((elfRead4(&pShdr->sh_flags) & SHF_WRITE) == 0)
00214 m_pSections[i].bReadOnly = true;
00215
00216
00217
00218 if (strcmp(pName, ".bss") == 0)
00219 m_pSections[i].bBss = true;
00220 if (elfRead4(&pShdr->sh_flags) & SHF_EXECINSTR) {
00221 m_pSections[i].bCode = true;
00222 bGotCode = true;
00223 }
00224
00225
00226
00227
00228
00229
00230
00231
00232 if (bGotCode && ((elfRead4(&pShdr->sh_flags) & (SHF_EXECINSTR | SHF_ALLOC)) == SHF_ALLOC) &&
00233 (elfRead4(&pShdr->sh_type) != SHT_NOBITS))
00234 m_pSections[i].bData = true;
00235 }
00236
00237
00238 for (i=0; i < m_iNumSections; i++)
00239 if (m_pSections[i].uNativeAddr == 0 && !strncmp(m_pSections[i].pSectionName, ".rel", 4)) {
00240 m_pSections[i].uNativeAddr = arbitaryLoadAddr;
00241 arbitaryLoadAddr += m_pSections[i].uSectionSize;
00242 }
00243
00244
00245
00246 for (i=1; i < m_iNumSections; ++i) {
00247 unsigned uType = m_pSections[i].uType;
00248 if (uType == SHT_SYMTAB || uType == SHT_DYNSYM)
00249 AddSyms(i);
00250 #if 0 // Ick; bad logic. Done with fake library function pointers now (-2 .. -1024)
00251 if (uType == SHT_REL || uType == SHT_RELA)
00252 AddRelocsAsSyms(i);
00253 #endif
00254 }
00255
00256
00257 PSectionInfo pRel = GetSectionInfoByName(".rela.text");
00258 if (pRel) {
00259 m_bAddend = true;
00260 m_pReloc = (Elf32_Rel*)pRel->uHostAddr;
00261
00262 }
00263 else {
00264 m_bAddend = false;
00265 pRel = GetSectionInfoByName(".rel.text");
00266 if (pRel) {
00267
00268 m_pReloc = (Elf32_Rel*)pRel->uHostAddr;
00269 }
00270 }
00271
00272
00273 PSectionInfo pPlt = GetSectionInfoByName(".plt");
00274 if (pPlt) {
00275 m_uPltMin = pPlt->uNativeAddr;
00276 m_uPltMax = pPlt->uNativeAddr + pPlt->uSectionSize;
00277 }
00278
00279
00280 applyRelocations();
00281
00282 return true;
00283 }
00284
00285
00286 void ElfBinaryFile::UnLoad()
00287 {
00288 if (m_pImage) delete [] m_pImage;
00289 fclose (m_fd);
00290 Init();
00291 }
00292
00293
00294 char* ElfBinaryFile::GetStrPtr(int idx, int offset)
00295 {
00296 if (idx < 0)
00297 {
00298
00299 fprintf(stderr, "Error! GetStrPtr passed index of %d\n", idx);
00300 return "Error!";
00301 }
00302
00303 char* pSym = (char*)m_pSections[idx].uHostAddr;
00304
00305 return pSym + offset;
00306 }
00307
00308
00309
00310
00311
00312 ADDRESS ElfBinaryFile::findRelPltOffset(int i, ADDRESS addrRelPlt, int sizeRelPlt, int numRelPlt, ADDRESS addrPlt) {
00313 int first = i;
00314 if (first >= numRelPlt)
00315 first = numRelPlt-1;
00316 int curr = first;
00317 do {
00318
00319 int* pEntry = (int*)(addrRelPlt + (curr*sizeRelPlt));
00320 int entry = elfRead4(pEntry+1);
00321 int sym = entry >> 8;
00322 if (sym == i) {
00323
00324
00325
00326 return addrPlt + 0x10 * (curr+1);
00327 }
00328 if (--curr < 0)
00329 curr = numRelPlt - 1;
00330 } while (curr != first);
00331 return 0;
00332 }
00333
00334
00335 void ElfBinaryFile::AddSyms(int secIndex) {
00336 int e_type = elfRead2(&((Elf32_Ehdr*)m_pImage)->e_type);
00337 PSectionInfo pSect = &m_pSections[secIndex];
00338
00339 int nSyms = pSect->uSectionSize / pSect->uSectionEntrySize;
00340 m_pSym = (Elf32_Sym*) pSect->uHostAddr;
00341 int strIdx = m_sh_link[secIndex];
00342
00343 PSectionInfo siPlt = GetSectionInfoByName(".plt");
00344 ADDRESS addrPlt = siPlt ? siPlt->uNativeAddr : 0;
00345 PSectionInfo siRelPlt = GetSectionInfoByName(".rel.plt");
00346 int sizeRelPlt = 8;
00347 if (siRelPlt == NULL) {
00348 siRelPlt = GetSectionInfoByName(".rela.plt");
00349 sizeRelPlt = 12;
00350 }
00351 ADDRESS addrRelPlt = 0;
00352 int numRelPlt = 0;
00353 if (siRelPlt) {
00354 addrRelPlt = siRelPlt->uHostAddr;
00355 numRelPlt = sizeRelPlt ? siRelPlt->uSectionSize / sizeRelPlt : 0;
00356 }
00357
00358
00359
00360 for (int i = 1; i < nSyms; i++) {
00361 ADDRESS val = (ADDRESS) elfRead4((int*)&m_pSym[i].st_value);
00362 int name = elfRead4(&m_pSym[i].st_name);
00363 if (name == 0) continue;
00364 std::string str(GetStrPtr(strIdx, name));
00365
00366 unsigned pos;
00367 if ((pos = str.find("@@")) != std::string::npos)
00368 str.erase(pos);
00369 std::map<ADDRESS, std::string>::iterator aa = m_SymTab.find(val);
00370
00371 if (aa == m_SymTab.end() || ELF32_ST_TYPE(m_pSym[i].st_info) == STT_FUNC) {
00372 if (val == 0 && siPlt) {
00373
00374
00375
00376
00377 val = findRelPltOffset(i, addrRelPlt, sizeRelPlt, numRelPlt, addrPlt);
00378 } else if (e_type == E_REL) {
00379 int nsec = elfRead2(&m_pSym[i].st_shndx);
00380 if (nsec >= 0 && nsec < m_iNumSections)
00381 val += GetSectionInfo(nsec)->uNativeAddr;
00382 }
00383
00384 #define ECHO_SYMS 0
00385 #if ECHO_SYMS
00386 std::cerr << "Elf AddSym: about to add " << str << " to address " << std::hex << val << std::dec << "\n";
00387 #endif
00388 m_SymTab[val] = str;
00389 }
00390 }
00391 ADDRESS uMain = GetMainEntryPoint();
00392 if (uMain != NO_ADDRESS && m_SymTab.find(uMain) == m_SymTab.end()) {
00393
00394 std::string sMain("main");
00395 m_SymTab[uMain] = sMain;
00396 }
00397 return;
00398 }
00399
00400 std::vector<ADDRESS> ElfBinaryFile::GetExportedAddresses(bool funcsOnly)
00401 {
00402 std::vector<ADDRESS> exported;
00403
00404 int i;
00405 int secIndex = 0;
00406 for (i=1; i < m_iNumSections; ++i) {
00407 unsigned uType = m_pSections[i].uType;
00408 if (uType == SHT_SYMTAB) {
00409 secIndex = i;
00410 break;
00411 }
00412 }
00413 if (secIndex == 0)
00414 return exported;
00415
00416 int e_type = elfRead2(&((Elf32_Ehdr*)m_pImage)->e_type);
00417 PSectionInfo pSect = &m_pSections[secIndex];
00418
00419 int nSyms = pSect->uSectionSize / pSect->uSectionEntrySize;
00420 m_pSym = (Elf32_Sym*) pSect->uHostAddr;
00421 int strIdx = m_sh_link[secIndex];
00422
00423
00424 for (int i = 1; i < nSyms; i++) {
00425 ADDRESS val = (ADDRESS) elfRead4((int*)&m_pSym[i].st_value);
00426 int name = elfRead4(&m_pSym[i].st_name);
00427 if (name == 0) continue;
00428 std::string str(GetStrPtr(strIdx, name));
00429
00430 unsigned pos;
00431 if ((pos = str.find("@@")) != std::string::npos)
00432 str.erase(pos);
00433 if (ELF32_ST_BIND(m_pSym[i].st_info) == STB_GLOBAL || ELF32_ST_BIND(m_pSym[i].st_info) == STB_WEAK) {
00434 if (funcsOnly == false || ELF32_ST_TYPE(m_pSym[i].st_info) == STT_FUNC) {
00435 if (e_type == E_REL) {
00436 int nsec = elfRead2(&m_pSym[i].st_shndx);
00437 if (nsec >= 0 && nsec < m_iNumSections)
00438 val += GetSectionInfo(nsec)->uNativeAddr;
00439 }
00440 exported.push_back(val);
00441 }
00442 }
00443 }
00444 return exported;
00445
00446 }
00447
00448
00449
00450
00451
00452 void ElfBinaryFile::AddRelocsAsSyms(int relSecIdx) {
00453 PSectionInfo pSect = &m_pSections[relSecIdx];
00454 if (pSect == 0) return;
00455
00456 int nRelocs = pSect->uSectionSize / pSect->uSectionEntrySize;
00457 m_pReloc = (Elf32_Rel*) pSect->uHostAddr;
00458 int symSecIdx = m_sh_link[relSecIdx];
00459 int strSecIdx = m_sh_link[symSecIdx];
00460
00461
00462 for (int i = 1; i < nRelocs; i++) {
00463 ADDRESS val = (ADDRESS) elfRead4((int*)&m_pReloc[i].r_offset);
00464 int symIndex = elfRead4(&m_pReloc[i].r_info) >> 8;
00465 int flags = elfRead4(&m_pReloc[i].r_info);
00466 if ((flags & 0xFF) == R_386_32) {
00467
00468 ADDRESS a = elfRead4((int*)&m_pSym[symIndex].st_value);
00469 if (m_pSym[symIndex].st_info & STT_SECTION)
00470 a = GetSectionInfo(elfRead2(&m_pSym[symIndex].st_shndx))->uNativeAddr;
00471
00472 writeNative4(val, a);
00473 continue;
00474 }
00475 if ((flags & R_386_PC32) == 0)
00476 continue;
00477 if (symIndex == 0) continue;
00478 std::string str(GetStrPtr(strSecIdx, elfRead4(&m_pSym[symIndex].st_name)));
00479
00480 unsigned pos;
00481 if ((pos = str.find("@@")) != std::string::npos)
00482 str.erase(pos);
00483 std::map<ADDRESS, std::string>::iterator it;
00484
00485 for (it = m_SymTab.begin(); it != m_SymTab.end(); it++)
00486 if ((*it).second == str)
00487 break;
00488
00489 if (it == m_SymTab.end()) {
00490 m_SymTab[next_extern] = str;
00491 it = m_SymTab.find(next_extern);
00492 next_extern += 4;
00493 }
00494 writeNative4(val, (*it).first - val - 4);
00495 }
00496 return;
00497 }
00498
00499
00500 const char* ElfBinaryFile::SymbolByAddress(const ADDRESS dwAddr) {
00501 std::map<ADDRESS, std::string>::iterator aa = m_SymTab.find(dwAddr);
00502 if (aa == m_SymTab.end())
00503 return 0;
00504 return (char*)aa->second.c_str();
00505 }
00506
00507 bool ElfBinaryFile::ValueByName(const char* pName, SymValue* pVal, bool bNoTypeOK ) {
00508 int hash, numBucket, numChain, y;
00509 int *pBuckets, *pChains;
00510 int found;
00511 int* pHash;
00512 Elf32_Sym* pSym;
00513 int iStr;
00514 PSectionInfo pSect;
00515
00516 pSect = GetSectionInfoByName(".dynsym");
00517 if (pSect == 0)
00518 {
00519
00520
00521
00522
00523 return SearchValueByName(pName, pVal);
00524 }
00525 pSym = (Elf32_Sym*)pSect->uHostAddr;
00526 if (pSym == 0) return false;
00527 pSect = GetSectionInfoByName(".hash");
00528 if (pSect == 0) return false;
00529 pHash = (int*) pSect->uHostAddr;
00530 iStr = GetSectionIndexByName(".dynstr");
00531
00532
00533 numBucket = elfRead4(&pHash[0]);
00534 numChain = elfRead4(&pHash[1]);
00535 pBuckets = &pHash[2];
00536 pChains = &pBuckets[numBucket];
00537
00538
00539 hash = elf_hash(pName) % numBucket;
00540 y = elfRead4(&pBuckets[hash]);
00541
00542
00543 found = (y != 0);
00544 if (y) {
00545 while (strcmp(pName, GetStrPtr(iStr, elfRead4(&pSym[y].st_name))) != 0) {
00546 y = elfRead4(&pChains[y]);
00547 if (y == 0) {
00548 found = false;
00549 break;
00550 }
00551 }
00552 }
00553
00554
00555 if (found && (bNoTypeOK || (ELF32_ST_TYPE(pSym[y].st_info) != STT_NOTYPE))) {
00556 pVal->uSymAddr = elfRead4((int*)&pSym[y].st_value);
00557 int e_type = elfRead2(&((Elf32_Ehdr*)m_pImage)->e_type);
00558 if (e_type == E_REL) {
00559 int nsec = elfRead2(&pSym[y].st_shndx);
00560 if (nsec >= 0 && nsec < m_iNumSections)
00561 pVal->uSymAddr += GetSectionInfo(nsec)->uNativeAddr;
00562 }
00563 pVal->iSymSize = elfRead4(&pSym[y].st_size);
00564 return true;
00565 }
00566 else {
00567
00568
00569 return SearchValueByName(pName, pVal);
00570 }
00571 }
00572
00573
00574 bool ElfBinaryFile::SearchValueByName(const char* pName, SymValue* pVal, const char* pSectName, const char* pStrName)
00575 {
00576
00577 PSectionInfo pSect, pStrSect;
00578
00579 pSect = GetSectionInfoByName(pSectName);
00580 if (pSect == 0) return false;
00581 pStrSect = GetSectionInfoByName(pStrName);
00582 if (pStrSect == 0) return false;
00583 const char* pStr = (const char*) pStrSect->uHostAddr;
00584
00585 int n = pSect->uSectionSize / pSect->uSectionEntrySize;
00586 Elf32_Sym* pSym = (Elf32_Sym*)pSect->uHostAddr;
00587
00588 for (int i=0; i < n; i++) {
00589 int idx = elfRead4(&pSym[i].st_name);
00590 if (strcmp(pName, pStr+idx) == 0) {
00591
00592 pVal->uSymAddr = elfRead4((int*)&pSym[i].st_value);
00593 int e_type = elfRead2(&((Elf32_Ehdr*)m_pImage)->e_type);
00594 if (e_type == E_REL) {
00595 int nsec = elfRead2(&pSym[i].st_shndx);
00596 if (nsec >= 0 && nsec < m_iNumSections)
00597 pVal->uSymAddr += GetSectionInfo(nsec)->uNativeAddr;
00598 }
00599 pVal->iSymSize = elfRead4( &pSym[i].st_size);
00600 return true;
00601 }
00602 }
00603 return false;
00604 }
00605
00606
00607
00608 bool ElfBinaryFile::SearchValueByName(const char* pName, SymValue* pVal) {
00609 if (SearchValueByName(pName, pVal, ".symtab", ".strtab"))
00610 return true;
00611 return SearchValueByName(pName, pVal, ".dynsym", ".dynstr");
00612 }
00613
00614
00615 ADDRESS ElfBinaryFile::GetAddressByName(const char* pName,
00616 bool bNoTypeOK ) {
00617 SymValue Val;
00618 bool bSuccess = ValueByName(pName, &Val, bNoTypeOK);
00619 if (bSuccess) {
00620 m_iLastSize = Val.iSymSize;
00621 m_uLastAddr = Val.uSymAddr;
00622 return Val.uSymAddr;
00623 }
00624 else return NO_ADDRESS;
00625 }
00626
00627 int ElfBinaryFile::GetSizeByName(const char* pName, bool bNoTypeOK ) {
00628 SymValue Val;
00629 bool bSuccess = ValueByName(pName, &Val, bNoTypeOK);
00630 if (bSuccess) {
00631 m_iLastSize = Val.iSymSize;
00632 m_uLastAddr = Val.uSymAddr;
00633 return Val.iSymSize;
00634 }
00635 else return 0;
00636 }
00637
00638
00639
00640 int ElfBinaryFile::GetDistanceByName(const char* sName, const char* pSectName)
00641 {
00642 int size = GetSizeByName(sName);
00643 if (size) return size;
00644
00645
00646
00647 unsigned value = GetAddressByName(sName);
00648 if (value == 0) return 0;
00649
00650 PSectionInfo pSect;
00651 pSect = GetSectionInfoByName(pSectName);
00652 if (pSect == 0) return 0;
00653
00654 int n = pSect->uSectionSize / pSect->uSectionEntrySize;
00655 Elf32_Sym* pSym = (Elf32_Sym*)pSect->uHostAddr;
00656
00657 unsigned closest = 0xFFFFFFFF;
00658 int idx = -1;
00659 for (int i=0; i < n; i++) {
00660 if ((pSym[i].st_value > value) && (pSym[i].st_value < closest)) {
00661 idx = i;
00662 closest = pSym[i].st_value;
00663 }
00664 }
00665 if (idx == -1) return 0;
00666
00667 pSect = GetSectionInfoByName(".text");
00668 ADDRESS low = pSect->uNativeAddr;
00669 ADDRESS hi = low + pSect->uSectionSize;
00670 if ((value >= low) && (value < hi)) {
00671
00672 if (closest > hi) closest = hi;
00673 }
00674 return closest - value;
00675 }
00676
00677 int ElfBinaryFile::GetDistanceByName(const char* sName) {
00678 int val = GetDistanceByName(sName, ".symtab");
00679 if (val) return val;
00680 return GetDistanceByName(sName, ".dynsym");
00681 }
00682
00683 bool ElfBinaryFile::IsDynamicLinkedProc(ADDRESS uNative) {
00684 if (uNative > (unsigned)-1024 && uNative != (unsigned)-1)
00685 return true;
00686 if (uNative >= first_extern && uNative < next_extern)
00687 return true;
00688 if (m_uPltMin == 0) return false;
00689 return (uNative >= m_uPltMin) && (uNative < m_uPltMax);
00690 }
00691
00692
00693
00694
00695
00696
00697
00698 std::list<SectionInfo*>& ElfBinaryFile::GetEntryPoints(
00699 const char* pEntry ) {
00700 SectionInfo* pSect = GetSectionInfoByName(".text");
00701 ADDRESS uMain = GetAddressByName(pEntry, true);
00702 ADDRESS delta = uMain - pSect->uNativeAddr;
00703 pSect->uNativeAddr += delta;
00704 pSect->uHostAddr += delta;
00705
00706 pSect->uSectionSize -= delta;
00707 m_EntryPoint.push_back(pSect);
00708
00709 pSect = GetSectionInfoByName(".init");
00710 m_EntryPoint.push_back(pSect);
00711 pSect = GetSectionInfoByName(".fini");
00712 m_EntryPoint.push_back(pSect);
00713 return m_EntryPoint;
00714 }
00715
00716
00717
00718
00719
00720
00721 ADDRESS ElfBinaryFile::GetMainEntryPoint() {
00722 return GetAddressByName ("main", true);
00723 }
00724
00725 ADDRESS ElfBinaryFile::GetEntryPoint() {
00726 return (ADDRESS) elfRead4(&((Elf32_Ehdr*)m_pImage)->e_entry);
00727 }
00728
00729
00730 ADDRESS ElfBinaryFile::NativeToHostAddress(ADDRESS uNative) {
00731 if (m_iNumSections == 0) return 0;
00732 return m_pSections[1].uHostAddr - m_pSections[1].uNativeAddr + uNative;
00733 }
00734
00735 ADDRESS ElfBinaryFile::GetRelocatedAddress(ADDRESS uNative) {
00736
00737 return 0;
00738 }
00739
00740 bool ElfBinaryFile::PostLoad(void* handle) {
00741
00742
00743
00744
00745
00746
00747 return false;
00748 }
00749
00750
00751
00752 bool ElfBinaryFile::Open(const char* sName) {
00753 return false;
00754 }
00755
00756
00757 void ElfBinaryFile::Close() {
00758 UnLoad();
00759 }
00760
00761 LOAD_FMT ElfBinaryFile::GetFormat() const {
00762 return LOADFMT_ELF;
00763 }
00764
00765 MACHINE ElfBinaryFile::GetMachine() const {
00766 int machine = elfRead2(&((Elf32_Ehdr*)m_pImage)->e_machine);
00767 if ((machine == EM_SPARC) || (machine == EM_SPARC32PLUS)) return MACHINE_SPARC;
00768 else if (machine == EM_386) return MACHINE_PENTIUM;
00769 else if (machine == EM_PA_RISC) return MACHINE_HPRISC;
00770 else if (machine == EM_68K) return MACHINE_PALM;
00771 else if (machine == EM_PPC) return MACHINE_PPC;
00772 else if (machine == EM_ST20) return MACHINE_ST20;
00773 else if (machine == EM_X86_64) {
00774 std::cerr << "Error: ElfBinaryFile::GetMachine: The AMD x86-64 architecture is not supported yet\n";
00775 return (MACHINE)-1;
00776 }
00777
00778 std::cerr << "Error: ElfBinaryFile::GetMachine: Unsupported machine type: "
00779 << machine << " (0x" << std::hex << machine << ")\n";
00780 std::cerr << "(Please add a description for this type, thanks!)\n";
00781 return (MACHINE)-1;
00782 }
00783
00784 bool ElfBinaryFile::isLibrary() const {
00785 int type = elfRead2(&((Elf32_Ehdr*)m_pImage)->e_type);
00786 return (type == ET_DYN);
00787 }
00788
00789 std::list<const char *> ElfBinaryFile::getDependencyList() {
00790 std::list<const char *> result;
00791 ADDRESS stringtab = NO_ADDRESS;
00792 PSectionInfo dynsect = GetSectionInfoByName(".dynamic");
00793 if( dynsect == NULL )
00794 return result;
00795
00796 Elf32_Dyn *dyn;
00797 for( dyn = (Elf32_Dyn *)dynsect->uHostAddr; dyn->d_tag != DT_NULL; dyn++ ) {
00798 if( dyn->d_tag == DT_STRTAB ) {
00799 stringtab = (ADDRESS)dyn->d_un.d_ptr;
00800 break;
00801 }
00802 }
00803
00804 if( stringtab == NO_ADDRESS )
00805 return result;
00806 stringtab = NativeToHostAddress( stringtab );
00807
00808 for( dyn = (Elf32_Dyn *)dynsect->uHostAddr; dyn->d_tag != DT_NULL; dyn++ ) {
00809 if( dyn->d_tag == DT_NEEDED ) {
00810 const char *need = (char *)stringtab + dyn->d_un.d_val;
00811 if( need != NULL )
00812 result.push_back( need );
00813 }
00814 }
00815 return result;
00816 }
00817
00818 ADDRESS ElfBinaryFile::getImageBase() {
00819 return m_uBaseAddr;
00820 }
00821
00822 size_t ElfBinaryFile::getImageSize() {
00823 return m_uImageSize;
00824 }
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834 ADDRESS* ElfBinaryFile::GetImportStubs(int& numImports) {
00835 ADDRESS a = m_uPltMin;
00836 int n = 0;
00837 std::map<ADDRESS, std::string>::iterator aa = m_SymTab.find(a);
00838 std::map<ADDRESS, std::string>::iterator ff = aa;
00839 bool delDummy = false;
00840 if (aa == m_SymTab.end()) {
00841
00842 delDummy = true;
00843 m_SymTab[a] = std::string();
00844 ff = m_SymTab.find(a);
00845 aa = ff;
00846 aa++;
00847 }
00848 while ((aa != m_SymTab.end()) && (a < m_uPltMax)) {
00849 n++;
00850 a = aa->first;
00851 aa++;
00852 }
00853
00854 m_pImportStubs = new ADDRESS[n];
00855 aa = ff;
00856 a = aa->first;
00857 int i=0;
00858 while ((aa != m_SymTab.end()) && (a < m_uPltMax)) {
00859 m_pImportStubs[i++] = a;
00860 a = aa->first;
00861 aa++;
00862 }
00863 if (delDummy)
00864 m_SymTab.erase(ff);
00865 numImports = n;
00866 return m_pImportStubs;
00867 }
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880 std::map<ADDRESS, const char*>* ElfBinaryFile::GetDynamicGlobalMap() {
00881 std::map<ADDRESS, const char*>* ret = new std::map<ADDRESS, const char*>;
00882 SectionInfo* pSect = GetSectionInfoByName(".rel.bss");
00883 if (pSect == 0)
00884 pSect = GetSectionInfoByName(".rela.bss");
00885 if (pSect == 0) {
00886
00887
00888 return ret;
00889 }
00890 int numEnt = pSect->uSectionSize / pSect->uSectionEntrySize;
00891 SectionInfo* sym = GetSectionInfoByName(".dynsym");
00892 if (sym == 0) {
00893 fprintf(stderr, "Could not find section .dynsym in source binary file");
00894 return ret;
00895 }
00896 Elf32_Sym* pSym = (Elf32_Sym*)sym->uHostAddr;
00897 int idxStr = GetSectionIndexByName(".dynstr");
00898 if (idxStr == -1) {
00899 fprintf(stderr, "Could not find section .dynstr in source binary file");
00900 return ret;
00901 }
00902
00903 unsigned p = pSect->uHostAddr;
00904 for (int i=0; i < numEnt; i++) {
00905
00906 int sym = ELF32_R_SYM(((int*)p)[1]);
00907 int name = pSym[sym].st_name;
00908 const char* s = GetStrPtr(idxStr, name);
00909 ADDRESS val = ((int*)p)[0];
00910 (*ret)[val] = s;
00911 p += pSect->uSectionEntrySize;
00912 }
00913
00914 return ret;
00915 }
00916
00917
00918
00919
00920
00921
00922
00923
00924 int ElfBinaryFile::elfRead2(short* ps) const {
00925 unsigned char* p = (unsigned char*)ps;
00926 if (m_elfEndianness) {
00927
00928 return (int)((p[0] << 8) + p[1]);
00929 } else {
00930
00931 return (int)(p[0] + (p[1] << 8));
00932 }
00933 }
00934 int ElfBinaryFile::elfRead4(int* pi) const{
00935 short* p = (short*)pi;
00936 if (m_elfEndianness) {
00937 return (int)((elfRead2(p) << 16) + elfRead2(p+1));
00938 } else
00939 return (int) (elfRead2(p) + (elfRead2(p+1) << 16));
00940 }
00941
00942 void ElfBinaryFile::elfWrite4(int* pi, int val) {
00943 char* p = (char*)pi;
00944 if (m_elfEndianness) {
00945
00946 *p++ = (char)(val >> 24);
00947 *p++ = (char)(val >> 16);
00948 *p++ = (char)(val >> 8);
00949 *p = (char)val;
00950 } else {
00951 *p++ = (char)val;
00952 *p++ = (char)(val >> 8);
00953 *p++ = (char)(val >> 16);
00954 *p = (char)(val >> 24);
00955 }
00956 }
00957
00958 int ElfBinaryFile::readNative1(ADDRESS nat) {
00959 PSectionInfo si = GetSectionInfoByAddr(nat);
00960 if (si == 0) {
00961 si = GetSectionInfo(0);
00962 }
00963 ADDRESS host = si->uHostAddr - si->uNativeAddr + nat;
00964 return *(char *)host;
00965 }
00966
00967
00968 int ElfBinaryFile::readNative2(ADDRESS nat) {
00969 PSectionInfo si = GetSectionInfoByAddr(nat);
00970 if (si == 0) return 0;
00971 ADDRESS host = si->uHostAddr - si->uNativeAddr + nat;
00972 return elfRead2((short*)host);
00973 }
00974
00975
00976 int ElfBinaryFile::readNative4(ADDRESS nat) {
00977 PSectionInfo si = GetSectionInfoByAddr(nat);
00978 if (si == 0) return 0;
00979 ADDRESS host = si->uHostAddr - si->uNativeAddr + nat;
00980 return elfRead4((int*)host);
00981 }
00982
00983 void ElfBinaryFile::writeNative4(ADDRESS nat, unsigned int n) {
00984 PSectionInfo si = GetSectionInfoByAddr(nat);
00985 if (si == 0) return;
00986 ADDRESS host = si->uHostAddr - si->uNativeAddr + nat;
00987 if (m_elfEndianness) {
00988 *(unsigned char*)host = (n >> 24) & 0xff;
00989 *(unsigned char*)(host+1) = (n >> 16) & 0xff;
00990 *(unsigned char*)(host+2) = (n >> 8) & 0xff;
00991 *(unsigned char*)(host+3) = n & 0xff;
00992 } else {
00993 *(unsigned char*)(host+3) = (n >> 24) & 0xff;
00994 *(unsigned char*)(host+2) = (n >> 16) & 0xff;
00995 *(unsigned char*)(host+1) = (n >> 8) & 0xff;
00996 *(unsigned char*)host = n & 0xff;
00997 }
00998 }
00999
01000
01001 QWord ElfBinaryFile::readNative8(ADDRESS nat) {
01002 int raw[2];
01003 #ifdef WORDS_BIGENDIAN // This tests the host machine
01004 if (m_elfEndianness) {
01005 #else
01006 if (!m_elfEndianness) {
01007 #endif // Balance }
01008
01009 raw[0] = readNative4(nat);
01010 raw[1] = readNative4(nat+4);
01011 } else {
01012
01013 raw[1] = readNative4(nat);
01014 raw[0] = readNative4(nat+4);
01015 }
01016
01017 return *(QWord*)raw;
01018 }
01019
01020
01021 float ElfBinaryFile::readNativeFloat4(ADDRESS nat) {
01022 int raw = readNative4(nat);
01023
01024
01025 return *(float*)&raw;
01026 }
01027
01028
01029 double ElfBinaryFile::readNativeFloat8(ADDRESS nat) {
01030 int raw[2];
01031 #ifdef WORDS_BIGENDIAN // This tests the host machine
01032 if (m_elfEndianness) {
01033 #else
01034 if (!m_elfEndianness) {
01035 #endif // Balance }
01036
01037 raw[0] = readNative4(nat);
01038 raw[1] = readNative4(nat+4);
01039 } else {
01040
01041 raw[1] = readNative4(nat);
01042 raw[0] = readNative4(nat+4);
01043 }
01044
01045 return *(double*)raw;
01046 }
01047
01048
01049
01050
01051 extern "C" {
01052 #ifdef _WIN32
01053 __declspec(dllexport)
01054 #endif
01055 BinaryFile* construct() {
01056 return new ElfBinaryFile;
01057 }
01058 }
01059
01060 void ElfBinaryFile::applyRelocations() {
01061 int nextFakeLibAddr = -2;
01062 if (m_pImage == 0) return;
01063 int machine = elfRead2(&((Elf32_Ehdr*)m_pImage)->e_machine);
01064 int e_type = elfRead2(&((Elf32_Ehdr*)m_pImage)->e_type);
01065 switch (machine) {
01066 case EM_SPARC:
01067 break;
01068 case EM_386: {
01069 for (int i=1; i < m_iNumSections; ++i) {
01070 SectionInfo* ps = &m_pSections[i];
01071 if (ps->uType == SHT_REL) {
01072
01073
01074
01075
01076
01077
01078 int* pReloc = (int*)ps->uHostAddr;
01079 unsigned size = ps->uSectionSize;
01080
01081
01082 ADDRESS destNatOrigin=0, destHostOrigin=0;
01083 if (e_type == E_REL) {
01084 int destSection = m_sh_info[i];
01085 destNatOrigin = m_pSections[destSection].uNativeAddr;
01086 destHostOrigin = m_pSections[destSection].uHostAddr;
01087 }
01088 int symSection = m_sh_link[i];
01089 int strSection = m_sh_link[symSection];
01090 char* pStrSection = (char*)m_pSections[strSection].uHostAddr;
01091 Elf32_Sym* symOrigin = (Elf32_Sym*) m_pSections[symSection].uHostAddr;
01092 for (unsigned u=0; u < size; u+= 2*sizeof(unsigned)) {
01093 unsigned r_offset = elfRead4(pReloc++);
01094 unsigned info = elfRead4(pReloc++);
01095 unsigned char relType = (unsigned char) info;
01096 unsigned symTabIndex = info >> 8;
01097 int* pRelWord;
01098 if (e_type == E_REL)
01099 pRelWord = ((int*)(destHostOrigin + r_offset));
01100 else {
01101 SectionInfo* destSec = GetSectionInfoByAddr(r_offset);
01102 pRelWord = (int*)(destSec->uHostAddr - destSec->uNativeAddr + r_offset);
01103 destNatOrigin = 0;
01104 }
01105 ADDRESS A, S=0, P;
01106 int nsec;
01107 switch (relType) {
01108 case 0:
01109 break;
01110 case 1:
01111 S = elfRead4((int*)&symOrigin[symTabIndex].st_value);
01112 if (e_type == E_REL) {
01113 nsec = elfRead2(&symOrigin[symTabIndex].st_shndx);
01114 if (nsec >= 0 && nsec < m_iNumSections)
01115 S += GetSectionInfo(nsec)->uNativeAddr;
01116 }
01117 A = elfRead4(pRelWord);
01118 elfWrite4(pRelWord, S+A);
01119 break;
01120 case 2:
01121 if (ELF32_ST_TYPE(symOrigin[symTabIndex].st_info) == STT_SECTION) {
01122 nsec = elfRead2(&symOrigin[symTabIndex].st_shndx);
01123 if (nsec >= 0 && nsec < m_iNumSections)
01124 S = GetSectionInfo(nsec)->uNativeAddr;
01125 } else {
01126 S = elfRead4((int*)&symOrigin[symTabIndex].st_value);
01127 if (S == 0) {
01128
01129
01130
01131
01132
01133
01134 int nameOffset = elfRead4((int*)&symOrigin[symTabIndex].st_name);
01135 char* pName = pStrSection + nameOffset;
01136
01137
01138
01139 S = nextFakeLibAddr--;
01140 AddSymbol(S, pName);
01141
01142 } else if (e_type == E_REL) {
01143 nsec = elfRead2(&symOrigin[symTabIndex].st_shndx);
01144 if (nsec >= 0 && nsec < m_iNumSections)
01145 S += GetSectionInfo(nsec)->uNativeAddr;
01146 }
01147 }
01148 A = elfRead4(pRelWord);
01149 P = destNatOrigin + r_offset;
01150 elfWrite4(pRelWord, S+A-P);
01151 break;
01152 case 7:
01153 case 8:
01154 break;
01155 default:
01156
01157 ;
01158 }
01159 }
01160 }
01161 }
01162 }
01163 default:
01164 break;
01165 }
01166 }
01167
01168 bool ElfBinaryFile::IsRelocationAt(ADDRESS uNative)
01169 {
01170
01171 if (m_pImage == 0) return false;
01172 int machine = elfRead2(&((Elf32_Ehdr*)m_pImage)->e_machine);
01173 int e_type = elfRead2(&((Elf32_Ehdr*)m_pImage)->e_type);
01174 switch (machine) {
01175 case EM_SPARC:
01176 break;
01177 case EM_386: {
01178 for (int i=1; i < m_iNumSections; ++i) {
01179 SectionInfo* ps = &m_pSections[i];
01180 if (ps->uType == SHT_REL) {
01181
01182
01183
01184
01185
01186
01187 int* pReloc = (int*)ps->uHostAddr;
01188 unsigned size = ps->uSectionSize;
01189
01190
01191 ADDRESS destNatOrigin=0, destHostOrigin;
01192 if (e_type == E_REL) {
01193 int destSection = m_sh_info[i];
01194 destNatOrigin = m_pSections[destSection].uNativeAddr;
01195 destHostOrigin = m_pSections[destSection].uHostAddr;
01196 }
01197
01198
01199
01200
01201 for (unsigned u=0; u < size; u+= 2*sizeof(unsigned)) {
01202 unsigned r_offset = elfRead4(pReloc++);
01203
01204 pReloc++;
01205
01206
01207 ADDRESS pRelWord;
01208 if (e_type == E_REL)
01209 pRelWord = destNatOrigin + r_offset;
01210 else {
01211 SectionInfo* destSec = GetSectionInfoByAddr(r_offset);
01212 pRelWord = destSec->uNativeAddr + r_offset;
01213 destNatOrigin = 0;
01214 }
01215 if (uNative == pRelWord)
01216 return true;
01217 }
01218 }
01219 }
01220 }
01221 default:
01222 break;
01223 }
01224 return false;
01225 }
01226
01227 const char *ElfBinaryFile::getFilenameSymbolFor(const char *sym)
01228 {
01229 int i;
01230 int secIndex = 0;
01231 for (i=1; i < m_iNumSections; ++i) {
01232 unsigned uType = m_pSections[i].uType;
01233 if (uType == SHT_SYMTAB) {
01234 secIndex = i;
01235 break;
01236 }
01237 }
01238 if (secIndex == 0)
01239 return NULL;
01240
01241
01242 PSectionInfo pSect = &m_pSections[secIndex];
01243
01244 int nSyms = pSect->uSectionSize / pSect->uSectionEntrySize;
01245 m_pSym = (Elf32_Sym*) pSect->uHostAddr;
01246 int strIdx = m_sh_link[secIndex];
01247
01248 std::string filename;
01249
01250
01251 for (int i = 1; i < nSyms; i++) {
01252
01253 int name = elfRead4(&m_pSym[i].st_name);
01254 if (name == 0) continue;
01255 std::string str(GetStrPtr(strIdx, name));
01256
01257 unsigned pos;
01258 if ((pos = str.find("@@")) != std::string::npos)
01259 str.erase(pos);
01260 if (ELF32_ST_TYPE(m_pSym[i].st_info) == STT_FILE) {
01261 filename = str;
01262 continue;
01263 }
01264 if (str == sym) {
01265 if (filename.length())
01266 return strdup(filename.c_str());
01267 return NULL;
01268 }
01269 }
01270 return NULL;
01271 }
01272
01273
01274 void ElfBinaryFile::AddSymbol(ADDRESS uNative, const char *pName)
01275 {
01276 m_SymTab[uNative] = pName;
01277 }
01278
01279 void ElfBinaryFile::dumpSymbols() {
01280 std::map<ADDRESS, std::string>::iterator it;
01281 std::cerr << std::hex;
01282 for (it = m_SymTab.begin(); it != m_SymTab.end(); ++it)
01283 std::cerr << "0x" << it->first << " " << it->second << " ";
01284 std::cerr << std::dec << "\n";
01285 }