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
00035
00036
00037 #include <algorithm>
00038 #include "Symtab.h"
00039 #include "emitElf.h"
00040 #include "emitElfStatic.h"
00041 #include "debug.h"
00042
00043
00044 #include "common/h/pathName.h"
00045
00046 #if defined(os_freebsd)
00047 #include "common/h/freebsdKludges.h"
00048 #endif
00049
00050 #if defined(os_linux)
00051 #include "common/h/linuxKludges.h"
00052 #endif
00053
00054 extern void symtab_log_perror(const char *msg);
00055 using namespace Dyninst;
00056 using namespace Dyninst::SymtabAPI;
00057 using namespace std;
00058
00059 extern const char *pdelf_get_shnames(Elf_X *elf);
00060 extern const char *STRTAB_NAME;
00061 extern const char *SYMTAB_NAME;
00062 extern const char *INTERP_NAME;
00063
00064
00065 extern void setSymtabError(SymtabError new_err);
00066 extern void symtab_log_perror(const char *msg);
00067
00068 struct sortByIndex
00069 {
00070 bool operator ()(Symbol * lhs, Symbol* rhs) {
00071 return lhs->getIndex() < rhs->getIndex();
00072 }
00073 };
00074
00075
00076 typedef struct
00077 {
00078 void *d_buf;
00079 Elf_Type d_type;
00080 unsigned int d_version;
00081 size_t d_size;
00082 off64_t d_off;
00083 size_t d_align;
00084 } Elf_Data64;
00085
00086 static bool libelfso0Flag;
00087 static bool libelfso1Flag;
00088 static int libelfso1version_major;
00089 static int libelfso1version_minor;
00090
00091 static void setVersion(){
00092 libelfso0Flag = false;
00093 libelfso1Flag = false;
00094 libelfso1version_major = 0;
00095 libelfso1version_minor = 0;
00096 #if defined(os_linux) || defined(os_freebsd)
00097 unsigned nEntries;
00098 map_entries *maps = getVMMaps(getpid(), nEntries);
00099 for (unsigned i=0; i< nEntries; i++){
00100 if (!strstr(maps[i].path, "libelf"))
00101 continue;
00102 std::string real_file = resolve_file_path(maps[i].path);
00103 const char *libelf_start = strstr(real_file.c_str(), "libelf");
00104 int num_read, major, minor;
00105 num_read = sscanf(libelf_start, "libelf-%d.%d.so", &major, &minor);
00106 if (num_read == 2) {
00107 libelfso1Flag = true;
00108 libelfso1version_major = major;
00109 libelfso1version_minor = minor;
00110 }
00111 else {
00112 libelfso0Flag = true;
00113 }
00114 }
00115 if (libelfso0Flag && libelfso1Flag) {
00116 fprintf(stderr, "WARNING: SymtabAPI is linked with libelf.so.0 and "
00117 "libelf.so.1! SymtabAPI likely going to be unable to read "
00118 "and write elf files!\n");
00119 }
00120
00121 #if defined(os_freebsd)
00122 if( libelfso1Flag ) {
00123 fprintf(stderr, "WARNING: SymtabAPI on FreeBSD is known to function "
00124 "incorrectly when linked with libelf.so.1\n");
00125 }
00126 #endif
00127 #endif
00128 }
00129
00130 bool emitElf::hasPHdrSectionBug()
00131 {
00132 if (movePHdrsFirst)
00133 return false;
00134 if (!libelfso1Flag)
00135 return false;
00136 return (libelfso1version_major == 0 && libelfso1version_minor <= 137);
00137 }
00138
00139 bool emitElf::cannotRelocatePhdrs()
00140 {
00141 #if defined(bug_phdrs_first_page)
00142 return true;
00143 #else
00144 return false;
00145 #endif
00146 }
00147
00148 unsigned int elfHash(const char *name)
00149 {
00150 unsigned int h = 0, g;
00151
00152 while (*name) {
00153 h = (h << 4) + *name++;
00154 if ((g = h & 0xf0000000))
00155 h ^= g >> 24;
00156 h &= ~g;
00157 }
00158 return h;
00159 }
00160
00161 static int elfSymType(Symbol *sym)
00162 {
00163 switch (sym->getType()) {
00164 case Symbol::ST_MODULE: return STT_FILE;
00165 case Symbol::ST_SECTION: return STT_SECTION;
00166 case Symbol::ST_OBJECT: return STT_OBJECT;
00167 case Symbol::ST_FUNCTION: return STT_FUNC;
00168 case Symbol::ST_TLS: return STT_TLS;
00169 case Symbol::ST_NOTYPE : return STT_NOTYPE;
00170 case Symbol::ST_UNKNOWN: return sym->getInternalType();
00171 case Symbol::ST_INDIRECT: return STT_GNU_IFUNC;
00172 default: return STT_SECTION;
00173 }
00174 }
00175
00176 static int elfSymBind(Symbol::SymbolLinkage sLinkage)
00177 {
00178 switch (sLinkage) {
00179 case Symbol::SL_LOCAL: return STB_LOCAL;
00180 case Symbol::SL_WEAK: return STB_WEAK;
00181 case Symbol::SL_GLOBAL: return STB_GLOBAL;
00182 default: return STB_LOPROC;
00183 }
00184 }
00185
00186 static int elfSymVisibility(Symbol::SymbolVisibility sVisibility)
00187 {
00188 switch (sVisibility) {
00189 case Symbol::SV_DEFAULT: return STV_DEFAULT;
00190 case Symbol::SV_INTERNAL: return STV_INTERNAL;
00191 case Symbol::SV_HIDDEN: return STV_HIDDEN;
00192 case Symbol::SV_PROTECTED: return STV_PROTECTED;
00193 default: return STV_DEFAULT;
00194 }
00195 }
00196
00197 emitElf::emitElf(Elf_X *oldElfHandle_, bool isStripped_, Object *obj_, void (*err_func)(const char *)) :
00198 oldElfHandle(oldElfHandle_),
00199 phdrs_scn(NULL),
00200 isStripped(isStripped_),
00201 object(obj_),
00202 err_func_(err_func)
00203 {
00204 firstNewLoadSec = NULL;
00205 textData = NULL;
00206 symStrData = NULL;
00207 symTabData = NULL;
00208 dynsymData = NULL;
00209 dynStrData = NULL;
00210 hashData = NULL;
00211 rodata = NULL;
00212
00213 linkedStaticData = NULL;
00214 hasRewrittenTLS = false;
00215 TLSExists = false;
00216 newTLSData = NULL;
00217
00218 oldElf = oldElfHandle->e_elfp();
00219 curVersionNum = 2;
00220 setVersion();
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233 createNewPhdr = true; BSSExpandFlag = false; replaceNOTE = false;
00234
00235 bool isBlueGeneP = obj_->isBlueGeneP();
00236 bool hasNoteSection = obj_->hasNoteSection();
00237
00238
00239 if(isBlueGeneP){
00240 createNewPhdr = false;
00241 if(hasNoteSection) {
00242 replaceNOTE = true;
00243 } else {
00244 BSSExpandFlag = true;
00245 }
00246 }
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256 movePHdrsFirst = createNewPhdr && object && object->getLoadAddress();
00257
00258
00259
00260
00261
00262
00263
00264 library_adjust = 0;
00265 if( cannotRelocatePhdrs() && !movePHdrsFirst ) {
00266 movePHdrsFirst = true;
00267 library_adjust = getpagesize();
00268 }
00269 }
00270
00271 bool emitElf::createElfSymbol(Symbol *symbol, unsigned strIndex, vector<Elf32_Sym *> &symbols, bool dynSymFlag)
00272 {
00273 Elf32_Sym *sym = new Elf32_Sym();
00274 sym->st_name = strIndex;
00275
00276 sym->st_value = symbol->getOffset();
00277 if (symbol->getOffset())
00278 sym->st_value = symbol->getOffset() + library_adjust;
00279 sym->st_size = symbol->getSize();
00280 sym->st_other = ELF32_ST_VISIBILITY(elfSymVisibility(symbol->getVisibility()));
00281 sym->st_info = (unsigned char) ELF32_ST_INFO(elfSymBind(symbol->getLinkage()), elfSymType (symbol));
00282
00283 if (symbol->getRegion())
00284 {
00285 #if defined(os_freebsd)
00286 sym->st_shndx = (Elf32_Half) symbol->getRegion()->getRegionNumber();
00287 #else
00288 sym->st_shndx = (Elf32_Section) symbol->getRegion()->getRegionNumber();
00289 #endif
00290 }
00291 else if (symbol->isAbsolute())
00292 {
00293 sym->st_shndx = SHN_ABS;
00294 }
00295 else
00296 {
00297 sym->st_shndx = 0;
00298 }
00299
00300 symbols.push_back(sym);
00301
00302 if (dynSymFlag)
00303 {
00304
00305
00306 char msg[2048];
00307 char *mpos = msg;
00308 msg[0] = '\0';
00309 string fileName;
00310
00311 if (!symbol->getVersionFileName(fileName))
00312 {
00313
00314 vector<string> *vers;
00315 if (!symbol->getVersions(vers))
00316 {
00317 if (symbol->getLinkage() == Symbol::SL_GLOBAL)
00318 {
00319 versionSymTable.push_back(1);
00320 mpos += sprintf(mpos, " global\n");
00321 }
00322 else
00323 {
00324 versionSymTable.push_back(0);
00325 mpos += sprintf(mpos, " local\n");
00326 }
00327 }
00328 else
00329 {
00330 if (vers->size() > 0)
00331 {
00332
00333 mpos += sprintf(mpos, "verdef: symbol=%s version=%s ", symbol->getMangledName().c_str(), (*vers)[0].c_str());
00334 if (verdefEntries.find((*vers)[0]) != verdefEntries.end())
00335 {
00336 unsigned short index = verdefEntries[(*vers)[0]];
00337 if (symbol->getVersionHidden()) index += 0x8000;
00338 versionSymTable.push_back(index);
00339 }
00340 else
00341 {
00342 unsigned short index = curVersionNum;
00343 if (symbol->getVersionHidden()) index += 0x8000;
00344 versionSymTable.push_back(index);
00345
00346 verdefEntries[(*vers)[0]] = curVersionNum;
00347 curVersionNum++;
00348 }
00349 }
00350
00351 for (unsigned i=0; i< vers->size(); i++)
00352 {
00353 mpos += sprintf(mpos, " {%s}", (*vers)[i].c_str());
00354 if (versionNames.find((*vers)[i]) == versionNames.end())
00355 {
00356 versionNames[(*vers)[i]] = 0;
00357 }
00358
00359 if (find( verdauxEntries[verdefEntries[(*vers)[0]]].begin(),
00360 verdauxEntries[verdefEntries[(*vers)[0]]].end(),
00361 (*vers)[i]) == verdauxEntries[verdefEntries[(*vers)[0]]].end())
00362 {
00363 verdauxEntries[verdefEntries[(*vers)[0]]].push_back((*vers)[i]);
00364 }
00365 }
00366 mpos += sprintf(mpos, "\n");
00367 }
00368 }
00369 else
00370 {
00371
00372 mpos += sprintf(mpos, "need: symbol=%s filename=%s\n",
00373 symbol->getMangledName().c_str(), fileName.c_str());
00374
00375 vector<string> *vers;
00376
00377 if (!symbol->getVersions(vers) || (vers && vers->size() != 1))
00378 {
00379
00380 if (fileName != "")
00381 {
00382
00383 if (!symbol->getReferringSymbol()->getSymtab()->isExec()) {
00384 if (find(unversionedNeededEntries.begin(),
00385 unversionedNeededEntries.end(),
00386 fileName) == unversionedNeededEntries.end())
00387 {
00388 mpos += sprintf(mpos, " new unversioned: %s\n", fileName.c_str());
00389 unversionedNeededEntries.push_back(fileName);
00390 }
00391 }
00392
00393 if (symbol->getLinkage() == Symbol::SL_GLOBAL) {
00394 mpos += sprintf(mpos, " global (w/ filename)\n");
00395 versionSymTable.push_back(1);
00396 }
00397 else {
00398 mpos += sprintf(mpos, " local (w/ filename)\n");
00399 versionSymTable.push_back(0);
00400 }
00401 }
00402 }
00403 else
00404 {
00405 if (!vers)
00406 {
00407 fprintf(stderr, "%s[%d]: weird inconsistency here... getVersions returned NULL\n",
00408 FILE__, __LINE__);
00409 }
00410 else
00411 {
00412
00413
00414
00415 if (versionNames.find((*vers)[0]) == versionNames.end())
00416 {
00417 mpos += sprintf(mpos, " new version name: %s\n", (*vers)[0].c_str());
00418 versionNames[(*vers)[0]] = 0;
00419 }
00420
00421 if (verneedEntries.find(fileName) != verneedEntries.end())
00422 {
00423 if (verneedEntries[fileName].find((*vers)[0]) != verneedEntries[fileName].end())
00424 {
00425 mpos += sprintf(mpos, " vernum: %d\n", verneedEntries[fileName][(*vers)[0]]);
00426 versionSymTable.push_back((unsigned short) verneedEntries[fileName][(*vers)[0]]);
00427 }
00428 else
00429 {
00430 mpos += sprintf(mpos, " new entry #%d: %s [%s]\n",
00431 curVersionNum, (*vers)[0].c_str(), fileName.c_str());
00432 versionSymTable.push_back((unsigned short) curVersionNum);
00433 verneedEntries[fileName][(*vers)[0]] = curVersionNum;
00434 curVersionNum++;
00435 }
00436 }
00437 else
00438 {
00439 mpos += sprintf(mpos, " new entry #%d: %s [%s]\n",
00440 curVersionNum, (*vers)[0].c_str(), fileName.c_str());
00441 versionSymTable.push_back((unsigned short) curVersionNum);
00442 verneedEntries[fileName][(*vers)[0]] = curVersionNum;
00443 curVersionNum++;
00444 }
00445 }
00446 }
00447 }
00448 #ifdef BINEDIT_DEBUG
00449 printf("%s", msg);
00450 #endif
00451 }
00452
00453 return true;
00454 }
00455
00456
00457 void emitElf::findSegmentEnds()
00458 {
00459 Elf32_Phdr *tmp = elf32_getphdr(oldElf);
00460
00461
00462
00463 dataSegEnd = 0;
00464 for(unsigned i=0;i<oldEhdr->e_phnum;i++)
00465 {
00466 if(tmp->p_type == PT_LOAD)
00467 {
00468 if (dataSegEnd < tmp->p_vaddr+tmp->p_memsz)
00469 dataSegEnd = tmp->p_vaddr+tmp->p_memsz;
00470 }else if( PT_TLS == tmp->p_type ) {
00471 TLSExists = true;
00472 }
00473 tmp++;
00474 }
00475 }
00476
00477
00478
00479 void emitElf::renameSection(const std::string &oldStr, const std::string &newStr, bool renameAll) {
00480 assert(oldStr.length() == newStr.length());
00481 for (unsigned k = 0; k < secNames.size(); k++) {
00482 if (secNames[k] == oldStr) {
00483 secNames[k].replace(0, oldStr.length(), newStr);
00484 if (!renameAll)
00485 break;
00486 }
00487 }
00488 }
00489
00490 bool emitElf::driver(Symtab *obj, string fName){
00491 int newfd;
00492 Region *foundSec = NULL;
00493 unsigned pgSize = getpagesize();
00494
00495 string strtmpl = fName + "XXXXXX";
00496 char buf[strtmpl.length() + 1];
00497 strncpy(buf, strtmpl.c_str(), strtmpl.length()+1);
00498
00499 newfd = mkstemp(buf);
00500
00501 if (newfd == -1) {
00502 log_elferror(err_func_, "error opening file to write symbols");
00503 return false;
00504 }
00505 strtmpl = buf;
00506
00507 fchmod(newfd, S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP);
00508 rewrite_printf("Emitting to temporary file %s\n", buf);
00509
00510 #if 0
00511
00512 if((newfd = (open(fName.c_str(), O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP)))==-1){
00513 log_elferror(err_func_, "error opening file to write symbols");
00514 return false;
00515 }
00516 #endif
00517
00518 if((newElf = elf_begin(newfd, ELF_C_WRITE, NULL)) == NULL){
00519 log_elferror(err_func_, "NEWELF_BEGIN_FAIL");
00520 fflush(stdout);
00521 return false;
00522 }
00523
00524
00525 secNames.push_back("");
00526 secNameIndex = 1;
00527
00528 loadSecTotalSize = 0;
00529 unsigned NOBITStotalsize = 0;
00530 int dirtySecsChange = 0;
00531 unsigned extraAlignSize = 0;
00532
00533
00534 const char *shnames = pdelf_get_shnames(oldElfHandle);
00535 if (shnames == NULL) {
00536 log_elferror(err_func_, ".shstrtab section");
00537 return false;
00538 }
00539
00540
00541 newEhdr = elf32_newehdr(newElf);
00542 if(!newEhdr){
00543 log_elferror(err_func_, "newEhdr failed\n");
00544 return false;
00545 }
00546 oldEhdr = elf32_getehdr(oldElf);
00547 memcpy(newEhdr, oldEhdr, sizeof(Elf32_Ehdr));
00548
00549 newEhdr->e_shnum = (Elf32_Half) (newEhdr->e_shnum + newSecs.size());
00550
00551
00552 findSegmentEnds();
00553 unsigned insertPoint = oldEhdr->e_shnum;
00554 unsigned insertPointOffset = 0;
00555 unsigned NOBITSstartPoint = oldEhdr->e_shnum;
00556
00557 if(movePHdrsFirst)
00558 {
00559 newEhdr->e_phoff = sizeof(Elf32_Ehdr);
00560 }
00561
00562
00563 elf_flagelf(newElf,ELF_C_SET,ELF_F_LAYOUT);
00564
00565 Elf_Scn *scn = NULL, *newscn = NULL;
00566 Elf_Data *newdata = NULL, *olddata = NULL;
00567 Elf32_Shdr *newshdr = NULL, *shdr = NULL;
00568 dyn_hash_map<unsigned, unsigned> secLinkMapping;
00569 dyn_hash_map<unsigned, unsigned> secInfoMapping;
00570 dyn_hash_map<unsigned, unsigned> changeMapping;
00571 dyn_hash_map<std::string, unsigned> newNameIndexMapping;
00572 dyn_hash_map<unsigned, std::string> oldIndexNameMapping;
00573
00574 bool createdLoadableSections = false;
00575 unsigned scncount;
00576 unsigned sectionNumber = 0;
00577
00578 bool startMovingSections = false;
00579 for (scncount = 0; (scn = elf_nextscn(oldElf, scn)); scncount++) {
00580
00581 shdr = elf32_getshdr(scn);
00582
00583
00584 const char *name = &shnames[shdr->sh_name];
00585 bool result = obj->findRegion(foundSec, shdr->sh_addr, shdr->sh_size);
00586
00587
00588
00589 if (!result || foundSec->isDirty()) {
00590 result = obj->findRegion(foundSec, name);
00591 }
00592
00593
00594 if(!strcmp(name, ".shstrtab"))
00595 continue;
00596
00597 sectionNumber++;
00598 changeMapping[sectionNumber] = 0;
00599 oldIndexNameMapping[scncount+1] = string(name);
00600 newNameIndexMapping[string(name)] = sectionNumber;
00601
00602 newscn = elf_newscn(newElf);
00603 newshdr = elf32_getshdr(newscn);
00604 newdata = elf_newdata(newscn);
00605 olddata = elf_getdata(scn,NULL);
00606 memcpy(newshdr, shdr, sizeof(Elf32_Shdr));
00607 memcpy(newdata,olddata, sizeof(Elf_Data));
00608
00609
00610 secNames.push_back(name);
00611 newshdr->sh_name = secNameIndex;
00612 secNameIndex += strlen(name) + 1;
00613
00614 if (newshdr->sh_addr) {
00615 newshdr->sh_addr += library_adjust;
00616 }
00617
00618 if(foundSec->isDirty())
00619 {
00620
00621
00622 newdata->d_buf = (char *)malloc(foundSec->getDiskSize());
00623 memcpy(newdata->d_buf, foundSec->getPtrToRawData(), foundSec->getDiskSize());
00624 newdata->d_size = foundSec->getDiskSize();
00625 newshdr->sh_size = foundSec->getDiskSize();
00626
00627 }
00628 else if(olddata->d_buf)
00629 {
00630
00631 newdata->d_buf = (char *)malloc(olddata->d_size);
00632 memcpy(newdata->d_buf, olddata->d_buf, olddata->d_size);
00633 }
00634
00635 if (newshdr->sh_entsize && (newshdr->sh_size % newshdr->sh_entsize != 0))
00636 {
00637 newshdr->sh_entsize = 0x0;
00638 }
00639
00640 if(BSSExpandFlag) {
00641
00642 if(scncount > NOBITSstartPoint)
00643 newshdr->sh_offset += NOBITStotalsize;
00644
00645
00646 if(shdr->sh_type == SHT_NOBITS)
00647 {
00648 newshdr->sh_type = SHT_PROGBITS;
00649 newdata->d_buf = (char *)malloc(shdr->sh_size);
00650 memset(newdata->d_buf, '\0', shdr->sh_size);
00651 newdata->d_size = shdr->sh_size;
00652 if(NOBITSstartPoint == oldEhdr->e_shnum)
00653 NOBITSstartPoint = scncount;
00654 NOBITStotalsize += shdr->sh_size;
00655 }
00656 }
00657
00658 std::vector <std::vector <unsigned long> > moveSecAddrRange = obj->getObject()->getMoveSecAddrRange();
00659
00660 for (unsigned i = 0 ; i != moveSecAddrRange.size(); i++) {
00661 if ( (moveSecAddrRange[i][0] == shdr->sh_addr) ||
00662 (shdr->sh_addr >= moveSecAddrRange[i][0] && shdr->sh_addr < moveSecAddrRange[i][1]) )
00663 {
00664 newshdr->sh_type = SHT_PROGBITS;
00665 changeMapping[sectionNumber] = 1;
00666 string newName = ".o";
00667 newName.append(name, 2, strlen(name));
00668 renameSection((string)name, newName, false);
00669 }
00670 }
00671
00672 if((obj->getObject()->getStrtabAddr() != 0 &&
00673 obj->getObject()->getStrtabAddr() == shdr->sh_addr) ||
00674 !strcmp(name, STRTAB_NAME))
00675 {
00676 symStrData = newdata;
00677 updateSymbols(symTabData, symStrData, loadSecTotalSize);
00678 }
00679
00680
00681 if((obj->getObject()->getSymtabAddr() != 0 &&
00682 obj->getObject()->getSymtabAddr() == shdr->sh_addr) ||
00683 !strcmp(name, SYMTAB_NAME) ){
00684 newshdr->sh_link = secNames.size();
00685 changeMapping[sectionNumber] = 1;
00686 symTabData = newdata;
00687 }
00688
00689
00690 if(obj->getObject()->getTextAddr() != 0 &&
00691 obj->getObject()->getTextAddr() == shdr->sh_addr){
00692 textData = newdata;
00693 }
00694
00695 if(obj->getObject()->getDynamicAddr() != 0 &&
00696 obj->getObject()->getDynamicAddr() == shdr->sh_addr){
00697 dynData = newdata;
00698 dynSegOff = newshdr->sh_offset;
00699 dynSegAddr = newshdr->sh_addr;
00700
00701 newshdr->sh_type = SHT_PROGBITS;
00702 changeMapping[sectionNumber] = 1;
00703 string newName = ".o";
00704 newName.append(name, 2, strlen(name));
00705 renameSection((string)name, newName, false);
00706
00707 }
00708
00709
00710 if( hasRewrittenTLS && foundSec->isTLS()
00711 && foundSec->getRegionType() == Region::RT_DATA )
00712 {
00713
00714 newshdr->sh_flags &= ~SHF_TLS;
00715
00716 string newName = ".o";
00717 newName.append(name, 2, strlen(name));
00718 renameSection((string)name, newName, false);
00719 }
00720
00721
00722 if(movePHdrsFirst) {
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733 if( newshdr->sh_offset > 0 ) {
00734 if( startMovingSections || obj->isStaticBinary()
00735 || obj->getObjectType() == obj_SharedLib ) newshdr->sh_offset += pgSize;
00736 else if( createNewPhdr ) newshdr->sh_offset += oldEhdr->e_phentsize;
00737 }
00738 }
00739
00740 if(scncount > insertPoint && newshdr->sh_offset >= insertPointOffset )
00741 newshdr->sh_offset += loadSecTotalSize;
00742
00743 if (newshdr->sh_offset > 0 )
00744 newshdr->sh_offset += dirtySecsChange;
00745
00746 if (BSSExpandFlag) {
00747 if( newshdr->sh_offset > 0 ) {
00748 newshdr->sh_offset += extraAlignSize;
00749 }
00750 }else if (newshdr->sh_offset >= insertPointOffset ) {
00751 newshdr->sh_offset += extraAlignSize;
00752 }
00753
00754 if(foundSec->isDirty())
00755 dirtySecsChange += newshdr->sh_size - shdr->sh_size;
00756
00757 if(BSSExpandFlag && newshdr->sh_addr) {
00758 unsigned newOff = newshdr->sh_offset - (newshdr->sh_offset & (pgSize-1)) + (newshdr->sh_addr & (pgSize-1));
00759 if(newOff < newshdr->sh_offset)
00760 newOff += pgSize;
00761 extraAlignSize += newOff - newshdr->sh_offset;
00762 newshdr->sh_offset = newOff;
00763 }
00764
00765 secLinkMapping[sectionNumber] = shdr->sh_link;
00766 secInfoMapping[sectionNumber] = shdr->sh_info;
00767
00768 rewrite_printf("section %s addr = %lx off = %lx size = %lx\n",
00769 name, newshdr->sh_addr, newshdr->sh_offset, newshdr->sh_size);
00770
00771
00772 if (shdr->sh_addr+shdr->sh_size == dataSegEnd && !createdLoadableSections) {
00773 createdLoadableSections = true;
00774 insertPoint = scncount;
00775 if( SHT_NOBITS == shdr->sh_type ) {
00776 insertPointOffset = shdr->sh_offset;
00777 }else{
00778 insertPointOffset = shdr->sh_offset + shdr->sh_size;
00779 }
00780
00781 if(!createLoadableSections(obj,newshdr, extraAlignSize,
00782 newNameIndexMapping, sectionNumber))
00783 return false;
00784 if (createNewPhdr && !movePHdrsFirst) {
00785 sectionNumber++;
00786 createNewPhdrRegion(newNameIndexMapping);
00787 }
00788
00789
00790 updateSymbols(dynsymData, dynStrData, loadSecTotalSize);
00791 }
00792
00793 if ( 0 > elf_update(newElf, ELF_C_NULL))
00794 {
00795 fprintf(stderr, "%s[%d]: elf_update failed: %d, %s\n", FILE__, __LINE__, elf_errno(), elf_errmsg(elf_errno()));
00796 return false;
00797 }
00798
00799 if(!strcmp(name, INTERP_NAME)) {
00800 startMovingSections = true;
00801 }
00802 }
00803
00804
00805 if(!createNonLoadableSections(newshdr))
00806 return false;
00807
00808 if ( 0 > elf_update(newElf, ELF_C_NULL))
00809 {
00810 fprintf(stderr, "%s[%d]: elf_update failed: %d, %s\n", FILE__, __LINE__, elf_errno(), elf_errmsg(elf_errno()));
00811 return false;
00812 }
00813
00814
00815 addSectionHeaderTable(newshdr);
00816
00817
00818 scn = NULL;
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853 for (scncount = 0; (scn = elf_nextscn(newElf, scn)); scncount++){
00854 shdr = elf32_getshdr(scn);
00855
00856 if (changeMapping[scncount+1] == 0 && secLinkMapping[scncount+1] != 0) {
00857 unsigned linkIndex = secLinkMapping[scncount+1];
00858 string secName = oldIndexNameMapping[linkIndex];
00859 unsigned newLinkIndex = newNameIndexMapping[secName];
00860 shdr->sh_link = newLinkIndex;
00861 }
00862
00863 if (changeMapping[scncount+1] == 0 && secInfoMapping[scncount+1] != 0) {
00864
00865
00866
00867 if (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA) {
00868 unsigned infoIndex = secInfoMapping[scncount+1];
00869 string secName = oldIndexNameMapping[infoIndex];
00870 unsigned newInfoIndex = newNameIndexMapping[secName];
00871 shdr->sh_info = newInfoIndex;
00872 }
00873 }
00874
00875 }
00876
00877 newEhdr->e_shstrndx = (Elf32_Half) scncount;
00878
00879
00880 newEhdr->e_shoff =shdr->sh_offset+shdr->sh_size;
00881 if (newEhdr->e_shoff % 8)
00882 newEhdr->e_shoff += 8 - (newEhdr->e_shoff % 8);
00883
00884
00885 oldPhdr = elf32_getphdr(oldElf);
00886 fixPhdrs(extraAlignSize);
00887
00888
00889 if (elf_update(newElf, ELF_C_WRITE) < 0){
00890 int err;
00891 if ((err = elf_errno()) != 0)
00892 {
00893 const char *msg = elf_errmsg(err);
00894
00895 fprintf(stderr, "Error: Unable to write ELF file: %s\n", msg);
00896 }
00897 log_elferror(err_func_, "elf_update failed");
00898 return false;
00899 }
00900 elf_end(newElf);
00901 if (hasPHdrSectionBug()) {
00902 unsigned long ehdr_off = (unsigned long) &(((Elf32_Ehdr *) 0x0)->e_phoff);
00903 lseek(newfd, ehdr_off, SEEK_SET);
00904 Elf32_Off offset = (Elf32_Off) phdr_offset;
00905 write(newfd, &offset, sizeof(Elf32_Off));
00906 }
00907 close(newfd);
00908
00909 if (::rename(strtmpl.c_str(), fName.c_str())) {
00910 return false;
00911 }
00912
00913 return true;
00914 }
00915
00916 void emitElf::createNewPhdrRegion(dyn_hash_map<std::string, unsigned> &newNameIndexMapping)
00917 {
00918 assert(!movePHdrsFirst);
00919
00920 unsigned phdr_size = oldEhdr->e_phnum*oldEhdr->e_phentsize;
00921 if (createNewPhdr)
00922 phdr_size += oldEhdr->e_phentsize;
00923
00924 unsigned align = 0;
00925 if (currEndOffset % 8)
00926 align = 8 - (currEndOffset % 8);
00927
00928 newEhdr->e_phoff = currEndOffset + align;
00929 phdr_offset = newEhdr->e_phoff;
00930
00931 Address endaddr = currEndAddress;
00932 currEndAddress += phdr_size + align;
00933 currEndOffset += phdr_size + align;
00934 loadSecTotalSize += phdr_size + align;
00935
00936
00937
00938
00939
00940 phdrs_scn = elf_newscn(newElf);
00941 Elf32_Shdr *newshdr = elf32_getshdr(phdrs_scn);
00942 const char *newname = ".dynphdrs";
00943
00944 secNames.push_back(newname);
00945 newNameIndexMapping[newname] = secNames.size() - 1;
00946 newshdr->sh_name = secNameIndex;
00947 secNameIndex += strlen(newname) + 1;
00948 newshdr->sh_flags = SHF_ALLOC;
00949 newshdr->sh_type = SHT_PROGBITS;
00950 newshdr->sh_offset = newEhdr->e_phoff;
00951 newshdr->sh_addr = endaddr + align;
00952 newshdr->sh_size = phdr_size;
00953 newshdr->sh_link = SHN_UNDEF;
00954 newshdr->sh_info = 0;
00955 newshdr->sh_addralign = 4;
00956 newshdr->sh_entsize = newEhdr->e_phentsize;
00957 phdrSegOff = newshdr->sh_offset;
00958 phdrSegAddr = newshdr->sh_addr;
00959
00960 }
00961
00962 void emitElf::fixPhdrs(unsigned &extraAlignSize)
00963 {
00964 unsigned pgSize = getpagesize();
00965 Elf32_Phdr *old = oldPhdr;
00966
00967 newEhdr->e_phnum = oldEhdr->e_phnum;
00968 newEhdr->e_phentsize = oldEhdr->e_phentsize;
00969 if(createNewPhdr) {
00970 newEhdr->e_phnum++;
00971 if( hasRewrittenTLS && !TLSExists ) newEhdr->e_phnum++;
00972 }
00973 bool added_new_sec = false;
00974 bool replaced = false;
00975
00976 if (!hasPHdrSectionBug())
00977 newPhdr = elf32_newphdr(newElf,newEhdr->e_phnum);
00978 else {
00979 newPhdr = (Elf32_Phdr *) malloc(sizeof(Elf32_Phdr) * newEhdr->e_phnum);
00980 }
00981 void *phdr_data = (void *) newPhdr;
00982
00983 Elf32_Phdr newSeg;
00984 for(unsigned i=0;i<oldEhdr->e_phnum;i++)
00985 {
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999 Elf32_Phdr * insert_phdr = NULL;
01000 if(createNewPhdr && !added_new_sec && firstNewLoadSec) {
01001 if(i+1 == oldEhdr->e_phnum) {
01002
01003 insert_phdr = newPhdr+1;
01004 }
01005 else if(old->p_type == PT_LOAD && (old+1)->p_type != PT_LOAD) {
01006
01007 insert_phdr = newPhdr+1;
01008 }
01009 else if(old->p_type != PT_LOAD &&
01010 (old+1)->p_type == PT_LOAD &&
01011 newSegmentStart < (old+1)->p_vaddr)
01012 {
01013
01014
01015 insert_phdr = newPhdr+1;
01016 }
01017 else if(old->p_type == PT_LOAD &&
01018 (old+1)->p_type == PT_LOAD &&
01019 newSegmentStart >= old->p_vaddr &&
01020 newSegmentStart < (old+1)->p_vaddr)
01021 {
01022
01023 insert_phdr = newPhdr+1;
01024 }
01025 else if(i == 0 &&
01026 old->p_type == PT_LOAD &&
01027 newSegmentStart < old->p_vaddr)
01028 {
01029
01030 insert_phdr = newPhdr;
01031 newPhdr++;
01032 }
01033 }
01034
01035 if(insert_phdr)
01036 {
01037 newSeg.p_type = PT_LOAD;
01038 newSeg.p_offset = firstNewLoadSec->sh_offset;
01039 newSeg.p_vaddr = newSegmentStart;
01040 newSeg.p_paddr = newSeg.p_vaddr;
01041 newSeg.p_filesz = loadSecTotalSize - (newSegmentStart - firstNewLoadSec->sh_addr);
01042 newSeg.p_memsz = (currEndAddress - firstNewLoadSec->sh_addr) - (newSegmentStart - firstNewLoadSec->sh_addr);
01043 newSeg.p_flags = PF_R+PF_W+PF_X;
01044 newSeg.p_align = pgSize;
01045 memcpy(insert_phdr, &newSeg, oldEhdr->e_phentsize);
01046 added_new_sec = true;
01047 #ifdef BINEDIT_DEBUG
01048 fprintf(stderr, "Added New program header : offset 0x%lx,addr 0x%lx\n", newPhdr->p_offset, newPhdr->p_vaddr);
01049 #endif
01050 }
01051
01052 memcpy(newPhdr, old, oldEhdr->e_phentsize);
01053
01054
01055 if(old->p_type == PT_DYNAMIC){
01056 newPhdr->p_vaddr = dynSegAddr;
01057 newPhdr->p_paddr = dynSegAddr;
01058 newPhdr->p_offset = dynSegOff;
01059 newPhdr->p_memsz = dynSegSize;
01060 newPhdr->p_filesz = newPhdr->p_memsz;
01061 }
01062 else if(old->p_type == PT_PHDR){
01063 if(createNewPhdr && !movePHdrsFirst)
01064 newPhdr->p_vaddr = phdrSegAddr;
01065 else if (createNewPhdr && movePHdrsFirst)
01066 newPhdr->p_vaddr = old->p_vaddr - pgSize;
01067 else
01068 newPhdr->p_vaddr = old->p_vaddr;
01069 newPhdr->p_paddr = newPhdr->p_vaddr;
01070 newPhdr->p_filesz = sizeof(Elf32_Phdr) * newEhdr->e_phnum;
01071 newPhdr->p_memsz = newPhdr->p_filesz;
01072 }else if( hasRewrittenTLS && old->p_type == PT_TLS) {
01073 newPhdr->p_offset = newTLSData->sh_offset;
01074 newPhdr->p_vaddr = newTLSData->sh_addr;
01075 newPhdr->p_paddr = newTLSData->sh_addr;
01076 newPhdr->p_filesz = newTLSData->sh_size;
01077 newPhdr->p_memsz = newTLSData->sh_size + old->p_memsz - old->p_filesz;
01078 newPhdr->p_align = newTLSData->sh_addralign;
01079 }else if (old->p_type == PT_LOAD) {
01080 if(!createNewPhdr && newPhdr->p_align > pgSize) {
01081 newPhdr->p_align = pgSize;
01082 }
01083 if(BSSExpandFlag) {
01084 if(old->p_flags == 6 || old->p_flags == 7)
01085 {
01086 newPhdr->p_memsz += loadSecTotalSize + extraAlignSize;
01087 newPhdr->p_filesz = newPhdr->p_memsz;
01088 newPhdr->p_flags = 7;
01089 }
01090 }
01091
01092 if(movePHdrsFirst) {
01093 if (!old->p_offset) {
01094 if (newPhdr->p_vaddr)
01095 newPhdr->p_vaddr = old->p_vaddr - pgSize;
01096 newPhdr->p_paddr = newPhdr->p_vaddr;
01097 newPhdr->p_filesz += pgSize;
01098 newPhdr->p_memsz = newPhdr->p_filesz;
01099 }
01100 else {
01101 newPhdr->p_offset += pgSize;
01102 }
01103 if (newPhdr->p_vaddr) {
01104 newPhdr->p_vaddr += library_adjust;
01105 newPhdr->p_paddr += library_adjust;
01106 }
01107 }
01108 }else if (replaceNOTE && old->p_type == PT_NOTE && !replaced) {
01109 replaced = true;
01110 newPhdr->p_type = PT_LOAD;
01111 newPhdr->p_offset = firstNewLoadSec->sh_offset;
01112 newPhdr->p_vaddr = newSegmentStart;
01113 newPhdr->p_paddr = newPhdr->p_vaddr;
01114 newPhdr->p_filesz = loadSecTotalSize - (newSegmentStart - firstNewLoadSec->sh_addr);
01115 newPhdr->p_memsz = (currEndAddress - firstNewLoadSec->sh_addr) - (newSegmentStart - firstNewLoadSec->sh_addr);
01116 newPhdr->p_flags = PF_R+PF_W+PF_X;
01117 newPhdr->p_align = pgSize;
01118 }
01119 else if (old->p_type == PT_INTERP && movePHdrsFirst
01120 && old->p_offset && newEhdr->e_phnum > oldEhdr->e_phnum)
01121 {
01122 newPhdr->p_offset +=
01123 oldEhdr->e_phentsize*(newEhdr->e_phnum-oldEhdr->e_phnum);
01124 }
01125 else if (movePHdrsFirst && old->p_offset) {
01126 newPhdr->p_offset += pgSize;
01127 if (newPhdr->p_vaddr) {
01128 newPhdr->p_vaddr += library_adjust;
01129 newPhdr->p_paddr += library_adjust;
01130 }
01131 }
01132
01133 rewrite_printf("Existing program header: type %u, offset 0x%lx, addr 0x%lx\n",
01134 newPhdr->p_type, newPhdr->p_offset, newPhdr->p_vaddr);
01135
01136 newPhdr++;
01137 if(insert_phdr)
01138 newPhdr++;
01139
01140 old++;
01141 }
01142
01143 if( hasRewrittenTLS && !TLSExists ) {
01144 newPhdr->p_type = PT_TLS;
01145 newPhdr->p_offset = newTLSData->sh_offset;
01146 newPhdr->p_vaddr = newTLSData->sh_addr;
01147 newPhdr->p_filesz = newTLSData->sh_size;
01148 newPhdr->p_memsz = newTLSData->sh_size;
01149 newPhdr->p_align = newTLSData->sh_addralign;
01150 }
01151
01152 if (!phdrs_scn)
01153 return;
01154
01155
01156
01157 Elf_Data *data = elf_newdata(phdrs_scn);
01158 size_t total_size = newEhdr->e_phnum * newEhdr->e_phentsize;
01159 data->d_buf = malloc(total_size);
01160 memcpy(data->d_buf, phdr_data, total_size);
01161 data->d_size = total_size;
01162 data->d_align = 0;
01163 data->d_off = 0;
01164 data->d_type = ELF_T_BYTE;
01165 data->d_version = 1;
01166 }
01167
01168 #if !defined(DT_GNU_HASH)
01169 #define DT_GNU_HASH 0x6ffffef5
01170 #endif
01171 #if !defined(DT_GNU_CONFLICT)
01172 #define DT_GNU_CONFLICT 0x6ffffef8
01173 #endif
01174
01175
01176 void emitElf::updateDynamic(unsigned tag, Elf32_Addr val){
01177 if(dynamicSecData.find(tag) == dynamicSecData.end()) {
01178 rewrite_printf("%s[%d]: updateDynamic cannot find tag %d in section data\n",
01179 FILE__, __LINE__, tag);
01180 return;
01181 }
01182
01183 switch(dynamicSecData[tag][0]->d_tag){
01184 case DT_STRSZ:
01185 case DT_RELSZ:
01186 case DT_RELASZ:
01187 dynamicSecData[tag][0]->d_un.d_val = val;
01188 break;
01189 case DT_HASH:
01190 case DT_GNU_HASH:
01191 case DT_SYMTAB:
01192 case DT_STRTAB:
01193 case DT_REL:
01194 case DT_RELA:
01195 case DT_VERSYM:
01196 case DT_JMPREL:
01197 dynamicSecData[tag][0]->d_un.d_ptr = val;
01198 break;
01199 case DT_VERNEED:
01200 dynamicSecData[tag][0]->d_un.d_ptr = val;
01201 dynamicSecData[DT_VERNEEDNUM][0]->d_un.d_val = verneednum;
01202 break;
01203 case DT_VERDEF:
01204 dynamicSecData[tag][0]->d_un.d_ptr = val;
01205 dynamicSecData[DT_VERDEFNUM][0]->d_un.d_val = verdefnum;
01206 break;
01207 }
01208 }
01209
01210
01211
01212
01213 void emitElf::updateSymbols(Elf_Data* symtabData,Elf_Data* strData, unsigned long loadSecsSize){
01214 unsigned pgSize = (unsigned)getpagesize();
01215 if( symtabData && strData && loadSecsSize){
01216 Elf32_Sym *symPtr=(Elf32_Sym*)symtabData->d_buf;
01217 for(unsigned int i=0;i< symtabData->d_size/(sizeof(Elf32_Sym));i++,symPtr++){
01218 if(!(strcmp("_end", (char*) strData->d_buf + symPtr->st_name))){
01219 if( newSegmentStart >= symPtr->st_value ) {
01220 symPtr->st_value += ((newSegmentStart - symPtr->st_value) + loadSecsSize);
01221
01222
01223 symPtr->st_value = (symPtr->st_value & ~(pgSize-1)) + pgSize;
01224 }
01225 }
01226 if(!(strcmp("_END_", (char*) strData->d_buf + symPtr->st_name))){
01227 if( newSegmentStart > symPtr->st_value ) {
01228 symPtr->st_value += (newSegmentStart - symPtr->st_value) + loadSecsSize;
01229
01230
01231 symPtr->st_value = (symPtr->st_value & ~(pgSize-1)) + pgSize;
01232 }
01233 }
01234 }
01235 }
01236 }
01237
01238 bool emitElf::createLoadableSections(Symtab*obj, Elf32_Shdr* &shdr, unsigned &extraAlignSize, dyn_hash_map<std::string, unsigned> &newNameIndexMapping, unsigned §ionNumber)
01239 {
01240 Elf_Scn *newscn;
01241 Elf_Data *newdata = NULL;
01242 Elf_Data64 *newdata64 = NULL;
01243 Elf32_Shdr *newshdr;
01244 std::vector<Elf32_Shdr *> updateDynLinkShdr;
01245 std::vector<Elf32_Shdr *> updateStrLinkShdr;
01246 firstNewLoadSec = NULL;
01247 unsigned pgSize = getpagesize();
01248 unsigned strtabIndex = 0;
01249 unsigned dynsymIndex = 0;
01250 Elf32_Shdr *prevshdr = NULL;
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260 Address zstart = emitElfUtils::orderLoadableSections(obj,newSecs);
01261
01262 for(unsigned i=0; i < newSecs.size(); i++)
01263 {
01264 if(!newSecs[i]->isLoadable()) {
01265 nonLoadableSecs.push_back(newSecs[i]);
01266 continue;
01267 }
01268 secNames.push_back(newSecs[i]->getRegionName());
01269 newNameIndexMapping[newSecs[i]->getRegionName()] = secNames.size() -1;
01270 sectionNumber++;
01271
01272 if((newscn = elf_newscn(newElf)) == NULL)
01273 {
01274 log_elferror(err_func_, "unable to create new function");
01275 return false;
01276 }
01277 if ((newdata = elf_newdata(newscn)) == NULL)
01278 {
01279 log_elferror(err_func_, "unable to create section data");
01280 return false;
01281 }
01282 memset(newdata, 0, sizeof(Elf_Data));
01283 if(!libelfso0Flag) {
01284 newdata64 = (Elf_Data64 *)malloc(sizeof(Elf_Data64));
01285 memset(newdata64, 0, sizeof(Elf_Data64));
01286 }
01287
01288
01289 newshdr = elf32_getshdr(newscn);
01290 newshdr->sh_name = secNameIndex;
01291 newshdr->sh_flags = 0;
01292 newshdr->sh_type = SHT_PROGBITS;
01293 switch(newSecs[i]->getRegionType()){
01294 case Region::RT_TEXTDATA:
01295 newshdr->sh_flags = SHF_EXECINSTR | SHF_ALLOC | SHF_WRITE;
01296 break;
01297 case Region::RT_TEXT:
01298 newshdr->sh_flags = SHF_EXECINSTR | SHF_ALLOC;
01299 break;
01300 case Region::RT_BSS:
01301 newshdr->sh_type = SHT_NOBITS;
01302 case Region::RT_DATA:
01303 newshdr->sh_flags = SHF_WRITE | SHF_ALLOC;
01304 break;
01305 default:
01306 break;
01307 }
01308
01309 if(shdr->sh_type == SHT_NOBITS) {
01310 newshdr->sh_offset = shdr->sh_offset;
01311 }else if( !firstNewLoadSec || !newSecs[i]->getDiskOffset() ) {
01312 newshdr->sh_offset = shdr->sh_offset+shdr->sh_size;
01313 }else{
01314
01315
01316 newshdr->sh_offset = firstNewLoadSec->sh_offset +
01317 (newSecs[i]->getDiskOffset() - firstNewLoadSec->sh_addr);
01318
01319
01320 loadSecTotalSize += newshdr->sh_offset - (shdr->sh_offset+shdr->sh_size);
01321 }
01322
01323 if(newSecs[i]->getDiskOffset())
01324 newshdr->sh_addr = newSecs[i]->getDiskOffset() + library_adjust;
01325 else if(!prevshdr) {
01326 newshdr->sh_addr = zstart + library_adjust;
01327 }
01328 else{
01329 newshdr->sh_addr = prevshdr->sh_addr+ prevshdr->sh_size;
01330 }
01331
01332 newshdr->sh_link = SHN_UNDEF;
01333 newshdr->sh_info = 0;
01334 newshdr->sh_addralign = newSecs[i]->getMemAlignment();
01335 newshdr->sh_entsize = 0;
01336
01337
01338 if( newSecs[i]->isTLS() ) {
01339 newTLSData = newshdr;
01340 newshdr->sh_flags |= SHF_TLS;
01341 }
01342
01343 if(newSecs[i]->getRegionType() == Region::RT_REL ||
01344 newSecs[i]->getRegionType() == Region::RT_PLTREL)
01345 {
01346 newshdr->sh_type = SHT_REL;
01347 newshdr->sh_flags = SHF_ALLOC;
01348 newshdr->sh_entsize = sizeof(Elf32_Rel);
01349 updateDynLinkShdr.push_back(newshdr);
01350 if(!libelfso0Flag) {
01351 newdata64->d_type = ELF_T_REL;
01352 newdata64->d_align = 4;
01353 }
01354 else {
01355 newdata->d_type = ELF_T_REL;
01356 newdata->d_align = 4;
01357 }
01358 if (newSecs[i]->getRegionType() == Region::RT_REL)
01359 updateDynamic(DT_REL, newshdr->sh_addr);
01360 else if (newSecs[i]->getRegionType() == Region::RT_PLTREL)
01361 updateDynamic(DT_JMPREL, newshdr->sh_addr);
01362 }
01363 else if(newSecs[i]->getRegionType() == Region::RT_RELA ||
01364 newSecs[i]->getRegionType() == Region::RT_PLTRELA)
01365 {
01366 newshdr->sh_type = SHT_RELA;
01367 newshdr->sh_flags = SHF_ALLOC;
01368 newshdr->sh_entsize = sizeof(Elf32_Rela);
01369 updateDynLinkShdr.push_back(newshdr);
01370 newdata->d_type = ELF_T_RELA;
01371 newdata->d_align = 4;
01372 if (newSecs[i]->getRegionType() == Region::RT_RELA)
01373 updateDynamic(DT_RELA, newshdr->sh_addr);
01374 else if(newSecs[i]->getRegionType() == Region::RT_PLTRELA)
01375 updateDynamic(DT_JMPREL, newshdr->sh_addr);
01376 }
01377 else if(newSecs[i]->getRegionType() == Region::RT_STRTAB)
01378 {
01379 newshdr->sh_type = SHT_STRTAB;
01380 newshdr->sh_entsize = 0;
01381 if(!libelfso0Flag) {
01382 newdata64->d_type = ELF_T_BYTE;
01383 newdata64->d_align = 1;
01384 }
01385 else {
01386 newdata->d_type = ELF_T_BYTE;
01387 newdata->d_align = 1;
01388 dynStrData = newdata;
01389 }
01390 newshdr->sh_link = SHN_UNDEF;
01391 newshdr->sh_flags= SHF_ALLOC;
01392 strtabIndex = secNames.size()-1;
01393 newshdr->sh_addralign = 1;
01394 updateDynamic(DT_STRTAB, newshdr->sh_addr);
01395 updateDynamic(DT_STRSZ, newSecs[i]->getDiskSize());
01396 }
01397 else if(newSecs[i]->getRegionType() == Region::RT_SYMTAB)
01398 {
01399 newshdr->sh_type = SHT_DYNSYM;
01400 newshdr->sh_entsize = sizeof(Elf32_Sym);
01401 if(!libelfso0Flag) {
01402 newdata64->d_type = ELF_T_SYM;
01403 newdata64->d_align = 4;
01404 }
01405 else {
01406 newdata->d_type = ELF_T_SYM;
01407 newdata->d_align = 4;
01408 dynsymData = newdata;
01409 }
01410 newshdr->sh_link = secNames.size();
01411 newshdr->sh_flags = SHF_ALLOC ;
01412 newshdr->sh_info = 1;
01413 dynsymIndex = secNames.size()-1;
01414 updateDynamic(DT_SYMTAB, newshdr->sh_addr);
01415 }
01416 else if(newSecs[i]->getRegionType() == Region::RT_DYNAMIC)
01417 {
01418 newshdr->sh_entsize = sizeof(Elf32_Dyn);
01419 newshdr->sh_type = SHT_DYNAMIC;
01420 if(!libelfso0Flag) {
01421 newdata64->d_type = ELF_T_DYN;
01422 newdata64->d_align = 4;
01423 }
01424 else {
01425 newdata->d_type = ELF_T_DYN;
01426 newdata->d_align = 4;
01427 }
01428 updateStrLinkShdr.push_back(newshdr);
01429 newshdr->sh_flags= SHF_ALLOC | SHF_WRITE;
01430 dynSegOff = newshdr->sh_offset;
01431 dynSegAddr = newshdr->sh_addr;
01432 dynSegSize = newSecs[i]->getDiskSize();
01433 }
01434 else if(newSecs[i]->getRegionType() == Region::RT_HASH)
01435 {
01436 newshdr->sh_entsize = sizeof(Elf32_Word);
01437 newshdr->sh_type = SHT_HASH;
01438 if(!libelfso0Flag) {
01439 newdata64->d_type = ELF_T_WORD;
01440 newdata64->d_align = 4;
01441 } else {
01442 newdata->d_type = ELF_T_WORD;
01443 newdata->d_align = 4;
01444 }
01445 updateDynLinkShdr.push_back(newshdr);
01446 newshdr->sh_flags= SHF_ALLOC;
01447 newshdr->sh_info = 0;
01448 updateDynamic(DT_HASH, newshdr->sh_addr);
01449 }
01450 else if(newSecs[i]->getRegionType() == Region::RT_SYMVERSIONS)
01451 {
01452 newshdr->sh_type = SHT_GNU_versym;
01453 newshdr->sh_entsize = sizeof(Elf32_Half);
01454 newshdr->sh_addralign = 2;
01455 if(!libelfso0Flag) {
01456 newdata64->d_type = ELF_T_HALF;
01457 newdata64->d_align = 2;
01458 }
01459 else {
01460 newdata->d_type = ELF_T_HALF;
01461 newdata->d_align = 2;
01462 }
01463 updateDynLinkShdr.push_back(newshdr);
01464 newshdr->sh_flags = SHF_ALLOC ;
01465 updateDynamic(DT_VERSYM, newshdr->sh_addr);
01466 }
01467 else if(newSecs[i]->getRegionType() == Region::RT_SYMVERNEEDED)
01468 {
01469 newshdr->sh_type = SHT_GNU_verneed;
01470 newshdr->sh_entsize = 0;
01471 newshdr->sh_addralign = 4;
01472 if(!libelfso0Flag) {
01473 newdata64->d_type = ELF_T_VNEED;
01474 newdata64->d_align = 4;
01475 }
01476 else {
01477 newdata->d_type = ELF_T_VNEED;
01478 newdata->d_align = 4;
01479 }
01480 updateStrLinkShdr.push_back(newshdr);
01481 newshdr->sh_flags = SHF_ALLOC ;
01482 newshdr->sh_info = verneednum;
01483 updateDynamic(DT_VERNEED, newshdr->sh_addr);
01484 }
01485 else if(newSecs[i]->getRegionType() == Region::RT_SYMVERDEF)
01486 {
01487 newshdr->sh_type = SHT_GNU_verdef;
01488 newshdr->sh_entsize = 0;
01489 if(!libelfso0Flag) {
01490 newdata64->d_type = ELF_T_VDEF;
01491 newdata64->d_align = 4;
01492 }
01493 else {
01494 newdata->d_type = ELF_T_VDEF;
01495 newdata->d_align = 4;
01496 }
01497 updateStrLinkShdr.push_back(newshdr);
01498 newshdr->sh_flags = SHF_ALLOC ;
01499 newshdr->sh_info = verdefnum;
01500 updateDynamic(DT_VERDEF, newshdr->sh_addr);
01501 }
01502
01503
01504 if(!firstNewLoadSec)
01505 {
01506 Offset newoff = newshdr->sh_offset - (newshdr->sh_offset & (pgSize-1)) + (newshdr->sh_addr & (pgSize-1));
01507 if(newoff < newshdr->sh_offset)
01508 newoff += pgSize;
01509 extraAlignSize += newoff - newshdr->sh_offset;
01510 newshdr->sh_offset = newoff;
01511
01512
01513
01514
01515 if (!createNewPhdr && replaceNOTE) {
01516 Offset newaddr = newshdr->sh_addr - (newshdr->sh_addr & (0x100000-1));
01517 if(newaddr < newshdr->sh_addr)
01518 newaddr += 0x100000;
01519 newshdr->sh_addr = newaddr;
01520 }
01521 newSegmentStart = newshdr->sh_addr;
01522 }
01523
01524
01525 if(!libelfso0Flag) {
01526 newdata64->d_buf = malloc(newSecs[i]->getDiskSize());
01527 memcpy(newdata64->d_buf, newSecs[i]->getPtrToRawData(), newSecs[i]->getDiskSize());
01528 newdata64->d_off = 0;
01529 newdata64->d_version = 1;
01530 newdata64->d_size = newSecs[i]->getDiskSize();
01531 if (!newdata64->d_align)
01532 newdata64->d_align = newshdr->sh_addralign;
01533 newshdr->sh_size = newdata64->d_size;
01534 memcpy(newdata, newdata64, sizeof(Elf_Data));
01535 }
01536 else {
01537 newdata->d_buf = malloc(newSecs[i]->getDiskSize());
01538 memcpy(newdata->d_buf, newSecs[i]->getPtrToRawData(), newSecs[i]->getDiskSize());
01539 newdata->d_off = 0;
01540 newdata->d_version = 1;
01541 newdata->d_size = newSecs[i]->getDiskSize();
01542 if (!newdata->d_align)
01543 newdata->d_align = newshdr->sh_addralign;
01544 newshdr->sh_size = newdata->d_size;
01545 }
01546
01547 if( newshdr->sh_type == SHT_NOBITS ) {
01548 currEndOffset = newshdr->sh_offset;
01549 }else{
01550 loadSecTotalSize += newshdr->sh_size;
01551 currEndOffset = newshdr->sh_offset + newshdr->sh_size;
01552 }
01553 currEndAddress = newshdr->sh_addr + newshdr->sh_size;
01554
01555 rewrite_printf("new section %s addr = %lx off = %lx size = %lx\n",
01556 newSecs[i]->getRegionName().c_str(), newshdr->sh_addr, newshdr->sh_offset,
01557 newshdr->sh_size);
01558
01559 if (0 > elf_update(newElf, ELF_C_NULL))
01560 {
01561 fprintf(stderr, "%s[%d]: elf_update failed: %d, %s\n", FILE__, __LINE__, errno, elf_errmsg(elf_errno()));
01562 return false;
01563 }
01564
01565 shdr = newshdr;
01566 if(!firstNewLoadSec)
01567 firstNewLoadSec = shdr;
01568 secNameIndex += newSecs[i]->getRegionName().size() + 1;
01569 prevshdr = newshdr;
01570 }
01571
01572 for(unsigned i=0; i < updateDynLinkShdr.size(); i++) {
01573 newshdr = updateDynLinkShdr[i];
01574 newshdr->sh_link = dynsymIndex;
01575 }
01576
01577 for(unsigned i=0; i < updateStrLinkShdr.size(); i++) {
01578 newshdr = updateStrLinkShdr[i];
01579 newshdr->sh_link = strtabIndex;
01580 }
01581
01582
01583 return true;
01584 }
01585
01586 bool emitElf::addSectionHeaderTable(Elf32_Shdr *shdr) {
01587 Elf_Scn *newscn;
01588 Elf_Data *newdata = NULL;
01589 Elf_Data64 *newdata64 = NULL;
01590 Elf32_Shdr *newshdr;
01591
01592 if((newscn = elf_newscn(newElf)) == NULL)
01593 {
01594 log_elferror(err_func_, "unable to create new function");
01595 return false;
01596 }
01597 if ((newdata = elf_newdata(newscn)) == NULL)
01598 {
01599 log_elferror(err_func_, "unable to create section data");
01600 return false;
01601 }
01602 if(!libelfso0Flag)
01603 newdata64 = (Elf_Data64 *) malloc(sizeof(Elf_Data64));
01604
01605
01606 newshdr = elf32_getshdr(newscn);
01607 newshdr->sh_name = secNameIndex;
01608 secNames.push_back(".shstrtab");
01609 secNameIndex += 10;
01610 newshdr->sh_type = SHT_STRTAB;
01611 newshdr->sh_entsize = 1;
01612 newshdr->sh_link = SHN_UNDEF;
01613 newshdr->sh_flags= 0;
01614
01615 newshdr->sh_offset = shdr->sh_offset+shdr->sh_size;
01616 newshdr->sh_addr = 0;
01617 newshdr->sh_info = 0;
01618 newshdr->sh_addralign = 4;
01619
01620 char *ptr;
01621
01622 if(!libelfso0Flag){
01623 newdata64->d_buf = (char *)malloc(secNameIndex);
01624 ptr = (char *)newdata64->d_buf;
01625 }
01626 else{
01627 newdata->d_buf = (char *)malloc(secNameIndex);
01628 ptr = (char *)newdata->d_buf;
01629 }
01630 for(unsigned i=0;i<secNames.size(); i++)
01631 {
01632 memcpy(ptr, secNames[i].c_str(), secNames[i].length());
01633 memcpy(ptr+secNames[i].length(), "\0", 1);
01634 ptr += secNames[i].length()+1;
01635 }
01636
01637 if(!libelfso0Flag){
01638 newdata64->d_type = ELF_T_BYTE;
01639 newdata64->d_size = secNameIndex;
01640 newdata64->d_align = 4;
01641 newdata64->d_version = 1;
01642 newdata64->d_off = 0;
01643 newshdr->sh_size = newdata64->d_size;
01644 memcpy(newdata, newdata64, sizeof(Elf_Data));
01645 }
01646 else {
01647 newdata->d_type = ELF_T_BYTE;
01648 newdata->d_size = secNameIndex;
01649 newdata->d_align = 4;
01650 newdata->d_version = 1;
01651 newdata->d_off = 0;
01652 newshdr->sh_size = newdata->d_size;
01653 }
01654
01655
01656
01657
01658 return true;
01659 }
01660
01661 bool emitElf::createNonLoadableSections(Elf32_Shdr *&shdr)
01662 {
01663 Elf_Scn *newscn;
01664 Elf_Data *newdata = NULL;
01665 Elf_Data64 *newdata64 = NULL;
01666 Elf32_Shdr *newshdr;
01667
01668 Elf32_Shdr *prevshdr = shdr;
01669
01670 for(unsigned i = 0; i < nonLoadableSecs.size(); i++)
01671 {
01672 secNames.push_back(nonLoadableSecs[i]->getRegionName());
01673
01674 if((newscn = elf_newscn(newElf)) == NULL)
01675 {
01676 log_elferror(err_func_, "unable to create new function");
01677 return false;
01678 }
01679 if ((newdata = elf_newdata(newscn)) == NULL)
01680 {
01681 log_elferror(err_func_, "unable to create section data");
01682 return false;
01683 }
01684 newdata64 = (Elf_Data64 *)malloc(sizeof(Elf_Data64));
01685
01686
01687 newshdr = elf32_getshdr(newscn);
01688 newshdr->sh_name = secNameIndex;
01689 secNameIndex += nonLoadableSecs[i]->getRegionName().length() + 1;
01690 if(nonLoadableSecs[i]->getRegionType() == Region::RT_TEXT)
01691 {
01692 newshdr->sh_type = SHT_PROGBITS;
01693 newshdr->sh_flags = SHF_EXECINSTR | SHF_WRITE;
01694 newshdr->sh_entsize = 1;
01695 if(!libelfso0Flag)
01696 newdata64->d_type = ELF_T_BYTE;
01697 else
01698 newdata->d_type = ELF_T_BYTE;
01699 }
01700 else if(nonLoadableSecs[i]->getRegionType() == Region::RT_DATA)
01701 {
01702 newshdr->sh_type = SHT_PROGBITS;
01703 newshdr->sh_flags = SHF_WRITE;
01704 newshdr->sh_entsize = 1;
01705 if(!libelfso0Flag)
01706 newdata64->d_type = ELF_T_BYTE;
01707 else
01708 newdata->d_type = ELF_T_BYTE;
01709 }
01710 else if(nonLoadableSecs[i]->getRegionType() == Region::RT_REL)
01711 {
01712 newshdr->sh_type = SHT_REL;
01713 newshdr->sh_flags = SHF_WRITE;
01714 newshdr->sh_entsize = sizeof(Elf32_Rel);
01715 if(!libelfso0Flag)
01716 newdata64->d_type = ELF_T_BYTE;
01717 else
01718 newdata->d_type = ELF_T_BYTE;
01719 }
01720 else if(nonLoadableSecs[i]->getRegionType() == Region::RT_RELA)
01721 {
01722 newshdr->sh_type = SHT_RELA;
01723 newshdr->sh_flags = SHF_WRITE;
01724 newshdr->sh_entsize = sizeof(Elf32_Rela);
01725 if(!libelfso0Flag)
01726 newdata64->d_type = ELF_T_BYTE;
01727 else
01728 newdata->d_type = ELF_T_BYTE;
01729 }
01730
01731 else if(nonLoadableSecs[i]->getRegionType() == Region::RT_SYMTAB)
01732 {
01733 newshdr->sh_type = SHT_SYMTAB;
01734 newshdr->sh_entsize = sizeof(Elf32_Sym);
01735 if(!libelfso0Flag)
01736 newdata64->d_type = ELF_T_SYM;
01737 else
01738 newdata->d_type = ELF_T_SYM;
01739
01740 newshdr->sh_link = secNames.size();
01741 newshdr->sh_flags= 0;
01742 }
01743 else if(nonLoadableSecs[i]->getRegionType() == Region::RT_STRTAB)
01744 {
01745 newshdr->sh_type = SHT_STRTAB;
01746 newshdr->sh_entsize = 0;
01747 if(!libelfso0Flag)
01748 newdata64->d_type = ELF_T_BYTE;
01749 else
01750 newdata->d_type = ELF_T_BYTE;
01751 newshdr->sh_link = SHN_UNDEF;
01752 newshdr->sh_flags= 0;
01753 }
01754
01755
01756
01757
01758
01759
01760
01761
01762
01763
01764
01765
01766 if( prevshdr->sh_type == SHT_NOBITS ) {
01767 newshdr->sh_offset = prevshdr->sh_offset;
01768 }else{
01769 newshdr->sh_offset = prevshdr->sh_offset+prevshdr->sh_size;
01770 }
01771 if (newshdr->sh_offset < currEndOffset) {
01772 newshdr->sh_offset = currEndOffset;
01773 }
01774 newshdr->sh_addr = 0;
01775 newshdr->sh_info = 0;
01776 newshdr->sh_addralign = 4;
01777
01778
01779 if(!libelfso0Flag) {
01780 newdata64->d_buf = nonLoadableSecs[i]->getPtrToRawData();
01781 newdata64->d_size = nonLoadableSecs[i]->getDiskSize();
01782 newshdr->sh_size = newdata64->d_size;
01783 newdata64->d_align = 4;
01784 newdata64->d_off = 0;
01785 newdata64->d_version = 1;
01786 memcpy(newdata, newdata64, sizeof(Elf_Data));
01787 }
01788 else{
01789 newdata->d_buf = nonLoadableSecs[i]->getPtrToRawData();
01790 newdata->d_size = nonLoadableSecs[i]->getDiskSize();
01791 newshdr->sh_size = newdata->d_size;
01792 newdata->d_align = 4;
01793 newdata->d_off = 0;
01794 newdata->d_version = 1;
01795 }
01796
01797 currEndOffset = newshdr->sh_offset + newshdr->sh_size;
01798
01799
01800
01801
01802 prevshdr = newshdr;
01803 }
01804 shdr = prevshdr;
01805 return true;
01806 }
01807
01808
01809
01810
01811
01812
01813
01814 bool emitElf::createSymbolTables(Symtab *obj, vector<Symbol *>&allSymbols)
01815 {
01816 unsigned i;
01817
01818
01819 std::vector<Elf32_Sym *> symbols;
01820
01821
01822 std::vector<Elf32_Sym *> dynsymbols;
01823
01824 unsigned symbolNamesLength = 1, dynsymbolNamesLength = 1;
01825 dyn_hash_map<string, unsigned> dynSymNameMapping;
01826 std::vector<std::string> symbolStrs, dynsymbolStrs;
01827 std::vector<Symbol *> dynsymVector;
01828 std::vector<Symbol *> allDynSymbols;
01829 std::vector<Symbol *> allSymSymbols;
01830
01831 dyn_hash_map<int, Region*> secTagRegionMapping = obj->getObject()->getTagRegionMapping();
01832
01833 Region *sec;
01834 dyn_hash_map<int, Region*>::const_iterator foundRegion;
01835 foundRegion = secTagRegionMapping.find(DT_STRTAB);
01836 if ((foundRegion != secTagRegionMapping.end()) && (foundRegion->second != NULL)) {
01837
01838 sec = foundRegion->second;
01839 olddynStrData = (char *)(sec->getPtrToRawData());
01840 olddynStrSize = sec->getDiskSize();
01841 dynsymbolNamesLength = olddynStrSize+1;
01842 }
01843
01844
01845 vector<string> &elibs = obj->getObject()->deps_;
01846 for (std::vector<std::string>::iterator iter = elibs.begin();
01847 iter != elibs.end(); ++iter) {
01848 addDTNeeded(*iter);
01849 }
01850
01851
01852 set<string> &plibs = obj->getObject()->prereq_libs;
01853 for (set<string>::iterator i = plibs.begin(); i != plibs.end(); i++) {
01854 addDTNeeded(*i);
01855 }
01856 new_dynamic_entries = obj->getObject()->new_dynamic_entries;
01857 Object *object = obj->getObject();
01858
01859 Elf32_Sym *sym = new Elf32_Sym();
01860 symbolStrs.push_back("");
01861
01862
01863 sym->st_name = 0;
01864 sym->st_value = 0;
01865 sym->st_size = 0;
01866 sym->st_other = 0;
01867 sym->st_info = (unsigned char) ELF32_ST_INFO(STB_LOCAL, STT_NOTYPE);
01868 sym->st_shndx = SHN_UNDEF;
01869
01870 symbols.push_back(sym);
01871 if (!obj->isStaticBinary()) {
01872 dynsymbols.push_back(sym);
01873 dynsymVector.push_back(Symbol::magicEmitElfSymbol());
01874 versionSymTable.push_back(0);
01875 }
01876
01877 for(i=0; i<allSymbols.size();i++) {
01878 if(allSymbols[i]->isInSymtab()) {
01879 allSymSymbols.push_back(allSymbols[i]);
01880 }
01881 if (!obj->isStaticBinary()) {
01882 if(allSymbols[i]->isInDynSymtab()) {
01883 allDynSymbols.push_back(allSymbols[i]);
01884 }
01885 }
01886 }
01887
01888 int max_index = -1;
01889 for(i = 0; i < allDynSymbols.size();i++) {
01890 if (max_index < allDynSymbols[i]->getIndex())
01891 max_index = allDynSymbols[i]->getIndex();
01892 }
01893 for(i=0; i<allDynSymbols.size(); i++) {
01894 if (allDynSymbols[i]->getIndex() == -1) {
01895 max_index++;
01896 allDynSymbols[i]->setIndex(max_index);
01897 }
01898
01899 if (allDynSymbols[i]->getStrIndex() == -1) {
01900
01901 dynsymbolStrs.push_back( allDynSymbols[i]->getMangledName().c_str());
01902 allDynSymbols[i]->setStrIndex(dynsymbolNamesLength);
01903 dynsymbolNamesLength += allDynSymbols[i]->getMangledName().length() + 1;
01904 }
01905
01906 }
01907
01908 std::sort(allDynSymbols.begin(), allDynSymbols.end(), sortByIndex());
01909
01910 max_index = -1;
01911 for(i = 0; i < allSymSymbols.size();i++) {
01912 if (max_index < allSymSymbols[i]->getIndex())
01913 max_index = allSymSymbols[i]->getIndex();
01914 }
01915
01916 for(i=0; i<allSymSymbols.size(); i++) {
01917 if (allSymSymbols[i]->getIndex() == -1) {
01918 max_index++;
01919 allSymSymbols[i]->setIndex(max_index);
01920 }
01921 }
01922
01923 std::sort(allSymSymbols.begin(), allSymSymbols.end(), sortByIndex());
01924
01925
01926
01927
01928
01929
01930
01931
01932
01933
01934
01935 for(i=0; i<allSymSymbols.size();i++) {
01936
01937 createElfSymbol(allSymSymbols[i], symbolNamesLength, symbols);
01938 symbolStrs.push_back(allSymSymbols[i]->getMangledName());
01939 symbolNamesLength += allSymSymbols[i]->getMangledName().length()+1;
01940 }
01941 for(i=0; i<allDynSymbols.size();i++) {
01942 createElfSymbol(allDynSymbols[i], allDynSymbols[i]->getStrIndex(), dynsymbols, true);
01943 dynSymNameMapping[allDynSymbols[i]->getMangledName().c_str()] = allDynSymbols[i]->getIndex();
01944 dynsymVector.push_back(allDynSymbols[i]);
01945 }
01946
01947
01948 Elf32_Sym *syms = (Elf32_Sym *)malloc(symbols.size()* sizeof(Elf32_Sym));
01949 for(i=0;i<symbols.size();i++)
01950 syms[i] = *(symbols[i]);
01951
01952 char *str = (char *)malloc(symbolNamesLength);
01953 unsigned cur=0;
01954 for(i=0;i<symbolStrs.size();i++)
01955 {
01956 strcpy(&str[cur],symbolStrs[i].c_str());
01957 cur+=symbolStrs[i].length()+1;
01958 }
01959
01960 if(!isStripped)
01961 {
01962 Region *sec;
01963 if (obj->findRegion(sec,".symtab")) {
01964 sec->setPtrToRawData(syms, symbols.size()*sizeof(Elf32_Sym));
01965 }
01966 else {
01967 obj->addRegion(0, syms, symbols.size()*sizeof(Elf32_Sym), ".symtab", Region::RT_SYMTAB);
01968 }
01969 }
01970 else
01971 obj->addRegion(0, syms, symbols.size()*sizeof(Elf32_Sym), ".symtab", Region::RT_SYMTAB);
01972
01973
01974 if(!isStripped)
01975 {
01976 Region *sec;
01977 if (obj->findRegion(sec,".strtab")) {
01978 sec->setPtrToRawData(str, symbolNamesLength);
01979 }
01980 else {
01981 obj->addRegion(0, str, symbolNamesLength , ".strtab", Region::RT_STRTAB);
01982 }
01983 }
01984 else
01985 obj->addRegion(0, str, symbolNamesLength , ".strtab", Region::RT_STRTAB);
01986
01987 if(!obj->getAllNewRegions(newSecs))
01988 log_elferror(err_func_, "No new sections to add");
01989
01990 if(dynsymbols.size() == 1)
01991 return true;
01992
01993 if (!obj->isStaticBinary()) {
01994
01995 Elf32_Sym *dynsyms = (Elf32_Sym *)malloc(dynsymbols.size()* sizeof(Elf32_Sym));
01996 for(i=0;i<dynsymbols.size();i++)
01997 dynsyms[i] = *(dynsymbols[i]);
01998
01999 Elf32_Half *symVers;
02000 char *verneedSecData, *verdefSecData;
02001 unsigned verneedSecSize = 0, verdefSecSize = 0;
02002
02003 createSymbolVersions(obj, symVers, verneedSecData, verneedSecSize, verdefSecData, verdefSecSize, dynsymbolNamesLength, dynsymbolStrs);
02004
02005 Elf32_Word *hashsecData;
02006 unsigned hashsecSize = 0;
02007 createHashSection(obj, hashsecData, hashsecSize, dynsymVector);
02008 if(hashsecSize) {
02009 string name;
02010 if (secTagRegionMapping.find(DT_HASH) != secTagRegionMapping.end()) {
02011 name = secTagRegionMapping[DT_HASH]->getRegionName();
02012 obj->addRegion(0, hashsecData, hashsecSize*sizeof(Elf32_Word), name, Region::RT_HASH, true);
02013 } else if (secTagRegionMapping.find(0x6ffffef5) != secTagRegionMapping.end()) {
02014 name = secTagRegionMapping[0x6ffffef5]->getRegionName();
02015 obj->addRegion(0, hashsecData, hashsecSize*sizeof(Elf32_Word), name, Region::RT_HASH, true);
02016 } else {
02017 name = ".hash";
02018 obj->addRegion(0, hashsecData, hashsecSize*sizeof(Elf32_Word), name, Region::RT_HASH, true);
02019 }
02020 }
02021
02022 Elf32_Dyn *dynsecData;
02023 unsigned dynsecSize = 0;
02024 if(obj->findRegion(sec, ".dynamic")) {
02025
02026
02027 if( !object->hasReldyn() && !object->hasReladyn() ) {
02028 if( object->getRelType() == Region::RT_REL ) {
02029 new_dynamic_entries.push_back(make_pair(DT_REL,0));
02030 new_dynamic_entries.push_back(make_pair(DT_RELSZ,0));
02031 }else if( object->getRelType() == Region::RT_RELA ) {
02032 new_dynamic_entries.push_back(make_pair(DT_RELA,0));
02033 new_dynamic_entries.push_back(make_pair(DT_RELASZ,0));
02034 }else{
02035 assert(!"Relocation type not set to known RT_REL or RT_RELA.");
02036 }
02037 }
02038
02039 createDynamicSection(sec->getPtrToRawData(), sec->getDiskSize(), dynsecData, dynsecSize, dynsymbolNamesLength, dynsymbolStrs);
02040 }
02041
02042
02043
02044 if(!dynsymbolNamesLength)
02045 return true;
02046
02047 char *dynstr = (char *)malloc(dynsymbolNamesLength);
02048 memcpy((void *)dynstr, (void *)olddynStrData, olddynStrSize);
02049 cur = olddynStrSize+1;
02050 for(i=0;i<dynsymbolStrs.size();i++)
02051 {
02052 strcpy(&dynstr[cur],dynsymbolStrs[i].c_str());
02053 cur+=dynsymbolStrs[i].length()+1;
02054 if ( dynSymNameMapping.find(dynsymbolStrs[i]) == dynSymNameMapping.end()) {
02055 dynSymNameMapping[dynsymbolStrs[i]] = allDynSymbols.size()+i;
02056 }
02057 }
02058
02059 string name;
02060 if (secTagRegionMapping.find(DT_SYMTAB) != secTagRegionMapping.end()) {
02061 name = secTagRegionMapping[DT_SYMTAB]->getRegionName();
02062 } else {
02063 name = ".dynsym";
02064 }
02065 obj->addRegion(0, dynsyms, dynsymbols.size()*sizeof(Elf32_Sym), name, Region::RT_SYMTAB, true);
02066
02067 if (secTagRegionMapping.find(DT_STRTAB) != secTagRegionMapping.end()) {
02068 name = secTagRegionMapping[DT_STRTAB]->getRegionName();
02069 } else {
02070 name = ".dynstr";
02071 }
02072 obj->addRegion(0, dynstr, dynsymbolNamesLength , name, Region::RT_STRTAB, true);
02073
02074
02075 if (secTagRegionMapping.find(DT_VERSYM) != secTagRegionMapping.end()) {
02076 name = secTagRegionMapping[DT_VERSYM]->getRegionName();
02077 } else {
02078 name = ".gnu.version";
02079 }
02080 obj->addRegion(0, symVers, versionSymTable.size() * sizeof(Elf32_Half), name, Region::RT_SYMVERSIONS, true);
02081
02082 if(verneedSecSize) {
02083 if (secTagRegionMapping.find(DT_VERNEED) != secTagRegionMapping.end()) {
02084 name = secTagRegionMapping[DT_VERNEED]->getRegionName();
02085 } else {
02086 name = ".gnu.version_r";
02087 }
02088 obj->addRegion(0, verneedSecData, verneedSecSize, name, Region::RT_SYMVERNEEDED, true);
02089 }
02090
02091 if(verdefSecSize) {
02092 obj->addRegion(0, verdefSecData, verdefSecSize, ".gnu.version_d", Region::RT_SYMVERDEF, true);
02093 }
02094
02095
02096
02097 bool has_plt = object->hasRelaplt() || object->hasRelplt();
02098 bool has_dyn = object->hasReladyn() || object->hasReldyn();
02099 if (!has_plt) {
02100 createRelocationSections(obj, object->getDynRelocs(), true, dynSymNameMapping);
02101 }
02102 else if (!has_dyn) {
02103 createRelocationSections(obj, object->getPLTRelocs(), false, dynSymNameMapping);
02104 createRelocationSections(obj, object->getDynRelocs(), true, dynSymNameMapping);
02105 }
02106 else if (object->getRelPLTAddr() < object->getRelDynAddr()) {
02107 createRelocationSections(obj, object->getPLTRelocs(), false, dynSymNameMapping);
02108 createRelocationSections(obj, object->getDynRelocs(), true, dynSymNameMapping);
02109 }
02110 else {
02111 createRelocationSections(obj, object->getDynRelocs(), true, dynSymNameMapping);
02112 createRelocationSections(obj, object->getPLTRelocs(), false, dynSymNameMapping);
02113 }
02114
02115
02116 if(dynsecSize)
02117 obj->addRegion(0, dynsecData, dynsecSize*sizeof(Elf64_Dyn), ".dynamic", Region::RT_DYNAMIC, true);
02118 }else{
02119
02120 vector<Region *> newRegs;
02121 obj->getAllNewRegions(newRegs);
02122 if( newRegs.size() ) {
02123
02124 emitElfStatic linker(obj->getAddressWidth(), isStripped);
02125
02126 emitElfStatic::StaticLinkError err;
02127 std::string errMsg;
02128 linkedStaticData = linker.linkStatic(obj, err, errMsg);
02129 if ( !linkedStaticData ) {
02130 std::string linkStaticError =
02131 std::string("Failed to link to static library code into the binary: ") +
02132 emitElfStatic::printStaticLinkError(err) + std::string(" = ")
02133 + errMsg;
02134 setSymtabError(Emit_Error);
02135 symtab_log_perror(linkStaticError.c_str());
02136 return false;
02137 }
02138
02139 hasRewrittenTLS = linker.hasRewrittenTLS();
02140
02141
02142 obj->getAllNewRegions(newRegs);
02143
02144 Offset lastRegionAddr = 0, lastRegionSize = 0;
02145 vector<Region *>::iterator newRegIter;
02146 for(newRegIter = newRegs.begin(); newRegIter != newRegs.end();
02147 ++newRegIter)
02148 {
02149 if( (*newRegIter)->getDiskOffset() > lastRegionAddr ) {
02150 lastRegionAddr = (*newRegIter)->getDiskOffset();
02151
02152 lastRegionSize = (*newRegIter)->getDiskSize();
02153 }
02154 }
02155
02156 if( !emitElfUtils::updateHeapVariables(obj, lastRegionAddr + lastRegionSize) ) {
02157 return false;
02158 }
02159 }
02160 }
02161
02162 if(!obj->getAllNewRegions(newSecs))
02163 log_elferror(err_func_, "No new sections to add");
02164
02165 return true;
02166 }
02167
02168 void emitElf::createRelocationSections(Symtab *obj, std::vector<relocationEntry> &relocation_table, bool isDynRelocs, dyn_hash_map<std::string, unsigned> &dynSymNameMapping) {
02169 vector<relocationEntry> newRels;
02170 if(isDynRelocs && newSecs.size()) {
02171 std::vector<Region *>::iterator i;
02172 for (i = newSecs.begin(); i != newSecs.end(); i++) {
02173 std::copy((*i)->getRelocations().begin(),
02174 (*i)->getRelocations().end(),
02175 std::back_inserter(newRels));
02176 }
02177 }
02178
02179 unsigned i,j,k,l,m;
02180
02181 Elf32_Rel *rels = (Elf32_Rel *)malloc(sizeof(Elf32_Rel) * (relocation_table.size()+newRels.size()));
02182 Elf32_Rela *relas = (Elf32_Rela *)malloc(sizeof(Elf32_Rela) * (relocation_table.size()+newRels.size()));
02183 j=0; k=0; l=0; m=0;
02184
02185 for(i=0; i<relocation_table.size(); i++)
02186 {
02187 if (relocation_table[i].regionType() == Region::RT_REL) {
02188 if( library_adjust && !isDynRelocs) {
02189
02190
02191
02192
02193
02194 emitElfUtils::updateRelocation(obj, relocation_table[i], library_adjust);
02195 }
02196
02197 rels[j].r_offset = relocation_table[i].rel_addr() + library_adjust;
02198
02199 unsigned long sym_offset = 0;
02200 std::string sym_name = relocation_table[i].name();
02201 if (!sym_name.empty()) {
02202 dyn_hash_map<string, unsigned int>::iterator n = dynSymNameMapping.find(sym_name);
02203 if (n != dynSymNameMapping.end())
02204 sym_offset = n->second;
02205 else {
02206 Symbol *sym = relocation_table[i].getDynSym();
02207 if (sym)
02208 sym_offset = sym->getIndex();
02209 }
02210 }
02211
02212 if (sym_offset) {
02213 rels[j].r_info = ELF32_R_INFO(sym_offset, relocation_table[i].getRelType());
02214 } else {
02215 rels[j].r_info = ELF32_R_INFO(STN_UNDEF, relocation_table[i].getRelType());
02216 }
02217 j++;
02218 } else {
02219 relas[k].r_offset = relocation_table[i].rel_addr() + library_adjust;
02220 relas[k].r_addend = relocation_table[i].addend();
02221 if (relas[k].r_addend)
02222 relas[k].r_addend += library_adjust;
02223 unsigned long sym_offset = 0;
02224 std::string sym_name = relocation_table[i].name();
02225 if (!sym_name.empty()) {
02226 dyn_hash_map<string, unsigned int>::iterator n = dynSymNameMapping.find(sym_name);
02227 if (n != dynSymNameMapping.end())
02228 sym_offset = n->second;
02229 else {
02230 Symbol *sym = relocation_table[i].getDynSym();
02231 if (sym)
02232 sym_offset = sym->getIndex();
02233 }
02234 }
02235
02236 if (sym_offset) {
02237 relas[k].r_info = ELF32_R_INFO(sym_offset, relocation_table[i].getRelType());
02238 } else {
02239 relas[k].r_info = ELF32_R_INFO(STN_UNDEF, relocation_table[i].getRelType());
02240 }
02241 k++;
02242 }
02243 }
02244 for(i=0;i<newRels.size();i++)
02245 {
02246 if (newRels[i].regionType() == Region::RT_REL) {
02247 rels[j].r_offset = newRels[i].rel_addr() + library_adjust;
02248 if(dynSymNameMapping.find(newRels[i].name()) != dynSymNameMapping.end()) {
02249 rels[j].r_info = ELF32_R_INFO(dynSymNameMapping[newRels[i].name()],
02250 relocationEntry::getGlobalRelType(obj->getAddressWidth()));
02251 } else {
02252 rels[j].r_info = ELF32_R_INFO(STN_UNDEF,
02253 relocationEntry::getGlobalRelType(obj->getAddressWidth()));
02254 }
02255 j++;
02256 l++;
02257 } else {
02258 relas[k].r_offset = newRels[i].rel_addr();
02259 relas[k].r_addend = newRels[i].addend();
02260 if( relas[k].r_addend ) relas[k].r_addend += library_adjust;
02261 if(dynSymNameMapping.find(newRels[i].name()) != dynSymNameMapping.end()) {
02262 relas[k].r_info = ELF32_R_INFO(dynSymNameMapping[newRels[i].name()],
02263 relocationEntry::getGlobalRelType(obj->getAddressWidth()));
02264 } else {
02265 relas[k].r_info = ELF32_R_INFO(STN_UNDEF,
02266 relocationEntry::getGlobalRelType(obj->getAddressWidth()));
02267 }
02268 k++;
02269 m++;
02270 }
02271 }
02272
02273 dyn_hash_map<int, Region*> secTagRegionMapping = obj->getObject()->getTagRegionMapping();
02274 int reloc_size, old_reloc_size, dynamic_reloc_size;
02275 const char *new_name;
02276 Region::RegionType rtype;
02277 int dtype;
02278 int dsize_type;
02279 void *buffer = NULL;
02280
02281 reloc_size = j*sizeof(Elf32_Rel)+k*sizeof(Elf32_Rela);
02282 if (!reloc_size)
02283 return;
02284
02285 if ( isDynRelocs
02286 && object->getRelType() == Region::RT_REL )
02287 {
02288 new_name = ".rel.dyn";
02289 dtype = DT_REL;
02290 rtype = Region::RT_REL;
02291 dsize_type = DT_RELSZ;
02292 buffer = rels;
02293 }
02294
02295 if ( isDynRelocs
02296 && object->getRelType() == Region::RT_RELA )
02297 {
02298 new_name = ".rela.dyn";
02299 dtype = DT_RELA;
02300 rtype = Region::RT_RELA;
02301 dsize_type = DT_RELASZ;
02302 buffer = relas;
02303 }
02304
02305 if ( !isDynRelocs
02306 && (obj->hasRelplt() ||
02307 object->getRelType() == Region::RT_REL) )
02308 {
02309 new_name = ".rel.plt";
02310 dtype = DT_JMPREL;
02311 rtype = Region::RT_PLTREL;
02312 dsize_type = DT_PLTRELSZ;
02313 buffer = rels;
02314 }
02315
02316 if ( !isDynRelocs
02317 && (obj->hasRelaplt() ||
02318 object->getRelType() == Region::RT_RELA ) )
02319 {
02320 new_name = ".rela.plt";
02321 dtype = DT_JMPREL;
02322 rtype = Region::RT_PLTRELA;
02323 dsize_type = DT_PLTRELSZ;
02324 buffer = relas;
02325 }
02326
02327
02328
02329
02330
02331
02332 old_reloc_size = dynamicSecData[dsize_type][0]->d_un.d_val;
02333 dynamic_reloc_size = old_reloc_size+ l*sizeof(Elf32_Rel)+ m*sizeof(Elf32_Rela);
02334
02335 string name;
02336 if (secTagRegionMapping.find(dtype) != secTagRegionMapping.end())
02337 name = secTagRegionMapping[dtype]->getRegionName();
02338 else
02339 name = std::string(new_name);
02340 obj->addRegion(0, buffer, reloc_size, name, rtype, true);
02341 updateDynamic(dsize_type, dynamic_reloc_size);
02342
02343 }
02344
02345 void emitElf::createSymbolVersions(Symtab *obj, Elf32_Half *&symVers, char*&verneedSecData, unsigned &verneedSecSize, char
02346 *&verdefSecData, unsigned &verdefSecSize, unsigned &dynSymbolNamesLength, vector<string> &dynStrs){
02347
02348
02349 map<string, unsigned>::iterator iter = versionNames.begin();
02350 for(;iter!=versionNames.end();iter++){
02351 iter->second = dynSymbolNamesLength;
02352 dynStrs.push_back(iter->first);
02353 dynSymbolNamesLength+= iter->first.size()+1;
02354 }
02355
02356
02357 symVers = (Elf32_Half *)malloc(versionSymTable.size() * sizeof(Elf32_Half));
02358 for(unsigned i=0; i<versionSymTable.size(); i++)
02359 symVers[i] = versionSymTable[i];
02360
02361
02362 verneedSecSize = 0;
02363 map<string, map<string, unsigned> >::iterator it = verneedEntries.begin();
02364 for(; it != verneedEntries.end(); it++)
02365 verneedSecSize += sizeof(Elf32_Verneed) + sizeof(Elf32_Vernaux) * it->second.size();
02366
02367 verneedSecData = (char *)malloc(verneedSecSize);
02368 unsigned curpos = 0;
02369 verneednum = 0;
02370 std::vector<std::string>::iterator dit;
02371 for(dit = unversionedNeededEntries.begin(); dit != unversionedNeededEntries.end(); dit++) {
02372
02373 std::string name = obj->getDynLibSubstitution(*dit);
02374
02375 if (!(obj->name() == name)) {
02376 versionNames[name] = dynSymbolNamesLength;
02377 dynStrs.push_back(name);
02378 dynSymbolNamesLength+= (name).size()+1;
02379 addDTNeeded(name);
02380 }
02381 }
02382 for(it = verneedEntries.begin(); it != verneedEntries.end(); it++){
02383
02384 Elf32_Verneed *verneed = (Elf32_Verneed *)(void*)(verneedSecData+curpos);
02385 verneed->vn_version = 1;
02386 verneed->vn_cnt = (Elf32_Half) it->second.size();
02387 verneed->vn_file = dynSymbolNamesLength;
02388 versionNames[it->first] = dynSymbolNamesLength;
02389 dynStrs.push_back(it->first);
02390 dynSymbolNamesLength+= it->first.size()+1;
02391 addDTNeeded(it->first);
02392 verneed->vn_aux = sizeof(Elf32_Verneed);
02393 verneed->vn_next = sizeof(Elf32_Verneed) + it->second.size()*sizeof(Elf32_Vernaux);
02394 if(curpos + verneed->vn_next == verneedSecSize)
02395 verneed->vn_next = 0;
02396 verneednum++;
02397 int i = 0;
02398 for(iter = it->second.begin(); iter!= it->second.end(); iter++){
02399
02400 Elf32_Vernaux *vernaux = (Elf32_Vernaux *)(void*)(verneedSecData + curpos + verneed->vn_aux + i*sizeof(Elf32_Vernaux));
02401 vernaux->vna_hash = elfHash(iter->first.c_str());
02402 vernaux->vna_flags = 0;
02403 vernaux->vna_other = (Elf32_Half) iter->second;
02404 vernaux->vna_name = versionNames[iter->first];
02405 if(i == verneed->vn_cnt-1)
02406 vernaux->vna_next = 0;
02407 else
02408 vernaux->vna_next = sizeof(Elf32_Vernaux);
02409 i++;
02410 }
02411
02412 curpos += verneed->vn_next;
02413 }
02414
02415
02416 verdefSecSize = 0;
02417 for(iter = verdefEntries.begin(); iter != verdefEntries.end(); iter++)
02418 verdefSecSize += sizeof(Elf32_Verdef) + sizeof(Elf32_Verdaux) * verdauxEntries[iter->second].size();
02419
02420 verdefSecData = (char *)malloc(verdefSecSize);
02421 curpos = 0;
02422 verdefnum = 0;
02423 for(iter = verdefEntries.begin(); iter != verdefEntries.end(); iter++){
02424
02425 Elf32_Verdef *verdef = (Elf32_Verdef *)(void*)(verdefSecData+curpos);
02426 verdef->vd_version = 1;
02427
02428 verdef->vd_flags = 0;
02429 verdef->vd_ndx = (Elf32_Half) iter->second;
02430 verdef->vd_cnt = (Elf32_Half) verdauxEntries[iter->second].size();
02431 verdef->vd_hash = elfHash(iter->first.c_str());
02432 verdef->vd_aux = sizeof(Elf32_Verdef);
02433 verdef->vd_next = sizeof(Elf32_Verdef) + verdauxEntries[iter->second].size()*sizeof(Elf32_Verdaux);
02434 if(curpos + verdef->vd_next == verdefSecSize)
02435 verdef->vd_next = 0;
02436 verdefnum++;
02437 for(unsigned i = 0; i< verdauxEntries[iter->second].size(); i++){
02438
02439 Elf32_Verdaux *verdaux = (Elf32_Verdaux *)(void*)(verdefSecData + curpos +verdef->vd_aux + i*sizeof(Elf32_Verdaux));
02440 verdaux->vda_name = versionNames[verdauxEntries[iter->second][i]];
02441 if(i == (unsigned) verdef->vd_cnt-1)
02442 verdaux->vda_next = 0;
02443 else
02444 verdaux->vda_next = sizeof(Elf32_Verdaux);
02445 }
02446
02447 curpos += verdef->vd_next;
02448 }
02449 return;
02450 }
02451
02452 void emitElf::createHashSection(Symtab *obj, Elf32_Word *&hashsecData, unsigned &hashsecSize, vector<Symbol *>&dynSymbols)
02453 {
02454
02455
02456 std::vector<unsigned> originalHashEntries;
02457 unsigned dynsymSize = obj->getObject()->getDynsymSize();
02458
02459 Elf_Scn *scn = NULL;
02460 Elf32_Shdr *shdr = NULL;
02461 for (unsigned scncount = 0; (scn = elf_nextscn(oldElf, scn)); scncount++) {
02462 shdr = elf32_getshdr(scn);
02463 if(obj->getObject()->getElfHashAddr() != 0 &&
02464 obj->getObject()->getElfHashAddr() == shdr->sh_addr){
02465 Elf_Data *hashData = elf_getdata(scn,NULL);
02466 Elf32_Word *oldHashSec = (Elf32_Word *) hashData->d_buf;
02467 unsigned original_nbuckets, original_nchains;
02468 original_nbuckets = oldHashSec[0];
02469 original_nchains = oldHashSec[1];
02470 for (unsigned i = 0; i < original_nbuckets+original_nchains; i++) {
02471 if ( oldHashSec[2+i] != 0) {
02472 originalHashEntries.push_back( oldHashSec[2+i]);
02473
02474 }
02475 }
02476 }
02477
02478 if(obj->getObject()->getGnuHashAddr() != 0 &&
02479 obj->getObject()->getGnuHashAddr() == shdr->sh_addr){
02480 Elf_Data *hashData = elf_getdata(scn,NULL);
02481 Elf32_Word *oldHashSec = (Elf32_Word *) hashData->d_buf;
02482 unsigned symndx = oldHashSec[1];
02483 if (dynsymSize != 0)
02484 for (unsigned i = symndx; i < dynsymSize ; i++) {
02485 originalHashEntries.push_back(i);
02486
02487 }
02488 }
02489 }
02490
02491 vector<Symbol *>::iterator iter;
02492 dyn_hash_map<unsigned, unsigned> lastHash;
02493 unsigned nbuckets = (unsigned)dynSymbols.size()*2/3;
02494 if (nbuckets % 2 == 0)
02495 nbuckets--;
02496 if (nbuckets < 1)
02497 nbuckets = 1;
02498 unsigned nchains = (unsigned)dynSymbols.size();
02499 hashsecSize = 2 + nbuckets + nchains;
02500 hashsecData = (Elf32_Word *)malloc(hashsecSize*sizeof(Elf32_Word));
02501 unsigned i=0, key;
02502 for (i=0; i<hashsecSize; i++) {
02503 hashsecData[i] = STN_UNDEF;
02504 }
02505 hashsecData[0] = (Elf32_Word)nbuckets;
02506 hashsecData[1] = (Elf32_Word)nchains;
02507 i = 0;
02508 for (iter = dynSymbols.begin(); iter != dynSymbols.end(); iter++, i++) {
02509 if((*iter)->getMangledName().empty()) continue;
02510 unsigned index = (*iter)->getIndex();
02511 if ((find(originalHashEntries.begin(),originalHashEntries.end(),index) == originalHashEntries.end()) &&
02512 (index < obj->getObject()->getDynsymSize())) {
02513 continue;
02514 }
02515 key = elfHash((*iter)->getMangledName().c_str()) % nbuckets;
02516 if (lastHash.find(key) != lastHash.end()) {
02517 hashsecData[2+nbuckets+lastHash[key]] = i;
02518
02519 }
02520 else {
02521 hashsecData[2+key] = i;
02522
02523 }
02524 lastHash[key] = i;
02525 hashsecData[2+nbuckets+i] = STN_UNDEF;
02526 }
02527 }
02528
02529 void emitElf::createDynamicSection(void *dynData, unsigned size, Elf32_Dyn *&dynsecData, unsigned &dynsecSize, unsigned &dynSymbolNamesLength, std::vector<std::string> &dynStrs) {
02530 dynamicSecData.clear();
02531 Elf32_Dyn *dyns = (Elf32_Dyn *)dynData;
02532 unsigned count = size/sizeof(Elf32_Dyn);
02533 vector<string> &libs_rmd = object->libsRMd();
02534 dynsecSize = 2*(count + DT_NEEDEDEntries.size() + new_dynamic_entries.size());
02535 dynsecData = (Elf32_Dyn *)malloc(dynsecSize*sizeof(Elf32_Dyn));
02536 unsigned curpos = 0;
02537 string rpathstr;
02538 for(unsigned i = 0; i< DT_NEEDEDEntries.size(); i++){
02539 dynsecData[curpos].d_tag = DT_NEEDED;
02540 dynStrs.push_back(DT_NEEDEDEntries[i]);
02541 dynsecData[curpos].d_un.d_val = dynSymbolNamesLength;
02542 dynSymbolNamesLength += DT_NEEDEDEntries[i].size()+1;
02543 dynamicSecData[DT_NEEDED].push_back(dynsecData+curpos);
02544 curpos++;
02545 }
02546 for (unsigned i = 0; i<new_dynamic_entries.size(); i++) {
02547 long name = new_dynamic_entries[i].first;
02548 long value = new_dynamic_entries[i].second;
02549 dynsecData[curpos].d_tag = name;
02550 dynsecData[curpos].d_un.d_val = value;
02551 dynamicSecData[name].push_back(dynsecData+curpos);
02552 curpos++;
02553 }
02554
02555
02556 bool foundHashSection = false;
02557
02558 for(unsigned i = 0; i< count;i++){
02559 switch(dyns[i].d_tag){
02560 case DT_NULL:
02561 break;
02562 case 0x6ffffef5:
02563 if (!foundHashSection) {
02564 dynsecData[curpos].d_tag = DT_HASH;
02565 dynsecData[curpos].d_un.d_ptr =dyns[i].d_un.d_ptr ;
02566 dynamicSecData[DT_HASH].push_back(dynsecData+curpos);
02567 curpos++;
02568 foundHashSection = true;
02569 }
02570 break;
02571 case DT_HASH:
02572 if (!foundHashSection) {
02573 dynsecData[curpos].d_tag = dyns[i].d_tag;
02574 dynsecData[curpos].d_un.d_ptr =dyns[i].d_un.d_ptr ;
02575 dynamicSecData[dyns[i].d_tag].push_back(dynsecData+curpos);
02576 curpos++;
02577 foundHashSection = true;
02578 }
02579
02580 break;
02581 case DT_NEEDED:
02582 rpathstr = &olddynStrData[dyns[i].d_un.d_val];
02583 if(find(DT_NEEDEDEntries.begin(), DT_NEEDEDEntries.end(), rpathstr) != DT_NEEDEDEntries.end()) {
02584 break;
02585 }
02586 if (find(libs_rmd.begin(), libs_rmd.end(), rpathstr) != libs_rmd.end())
02587 break;
02588 dynsecData[curpos].d_tag = dyns[i].d_tag;
02589 dynsecData[curpos].d_un.d_val = dynSymbolNamesLength;
02590 dynStrs.push_back(rpathstr);
02591 dynSymbolNamesLength += rpathstr.size() + 1;
02592 dynamicSecData[dyns[i].d_tag].push_back(dynsecData+curpos);
02593 curpos++;
02594 break;
02595 case DT_RPATH:
02596 case DT_RUNPATH:
02597 dynsecData[curpos].d_tag = dyns[i].d_tag;
02598 dynsecData[curpos].d_un.d_val = dynSymbolNamesLength;
02599 rpathstr = &olddynStrData[dyns[i].d_un.d_val];
02600 dynStrs.push_back(rpathstr);
02601 dynSymbolNamesLength += rpathstr.size() + 1;
02602 dynamicSecData[dyns[i].d_tag].push_back(dynsecData+curpos);
02603 curpos++;
02604 break;
02605 case DT_INIT:
02606 case DT_FINI:
02607 case DT_GNU_CONFLICT:
02608 case DT_JMPREL:
02609 case DT_PLTGOT:
02610
02611
02612
02613
02614
02615
02616 memcpy(dynsecData+curpos, dyns+i, sizeof(Elf64_Dyn));
02617 dynsecData[curpos].d_un.d_ptr += library_adjust;
02618 dynamicSecData[dyns[i].d_tag].push_back(dynsecData+curpos);
02619 curpos++;
02620 break;
02621 default:
02622 memcpy(dynsecData+curpos, dyns+i, sizeof(Elf32_Dyn));
02623 dynamicSecData[dyns[i].d_tag].push_back(dynsecData+curpos);
02624 curpos++;
02625 break;
02626 }
02627 }
02628 dynsecData[curpos].d_tag = DT_NULL;
02629 dynsecData[curpos].d_un.d_val = 0;
02630 curpos++;
02631 dynsecSize = curpos+1;
02632 }
02633
02634 void emitElf::log_elferror(void (*err_func)(const char *), const char* msg) {
02635 const char* err = elf_errmsg(elf_errno());
02636 err = err ? err: "(bad elf error)";
02637 string str = string(err)+string(msg);
02638 err_func(str.c_str());
02639 }
02640
02641 void emitElf::addDTNeeded(string s)
02642 {
02643 if (find(DT_NEEDEDEntries.begin(), DT_NEEDEDEntries.end(), s) != DT_NEEDEDEntries.end())
02644 return;
02645 vector<string> &libs_rmd = object->libsRMd();
02646 if (find(libs_rmd.begin(), libs_rmd.end(), s) != libs_rmd.end())
02647 return;
02648 DT_NEEDEDEntries.push_back(s);
02649 }