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