@@ -1274,13 +1274,13 @@ void ElfFile<ElfFileParamNames>::replaceNeeded(map<string, string>& libs)
12741274
12751275 // technically, the string referred by d_val could be used otherwise, too (although unlikely)
12761276 // we'll therefore add a new string
1277- debug (" resizing .dynstr ..." );
1277+ debug (" resizing .dynstr ...\n " );
12781278
12791279 string & newDynStr = replaceSection (" .dynstr" ,
12801280 rdi (shdrDynStr.sh_size ) + replacement.size () + 1 + dynStrAddedBytes);
12811281 setSubstr (newDynStr, rdi (shdrDynStr.sh_size ) + dynStrAddedBytes, replacement + ' \0 ' );
12821282
1283- dyn->d_un .d_val = shdrDynStr.sh_size + dynStrAddedBytes;
1283+ wri ( dyn->d_un .d_val , rdi ( shdrDynStr.sh_size ) + dynStrAddedBytes) ;
12841284
12851285 dynStrAddedBytes += replacement.size () + 1 ;
12861286
@@ -1299,23 +1299,46 @@ void ElfFile<ElfFileParamNames>::replaceNeeded(map<string, string>& libs)
12991299 // be replaced.
13001300
13011301 if (verNeedNum) {
1302- Elf_Shdr & shdrVersionR = findSection3 (" .gnu.version_r" );
1303- // The filename strings in the .gnu.version_r aren't necessarily in
1304- // .dynstr -- we have to look at ->sh_link to find the section with
1305- // the strings in it.
1306- Elf_Shdr & shdrVersionRStrings = *shdrs[rdi (shdrVersionR->sh_link )];
1302+ Elf_Shdr & shdrVersionR = findSection (" .gnu.version_r" );
1303+ // The filename strings in the .gnu.version_r are different from the
1304+ // ones in .dynamic: instead of being in .dynstr, they're in some
1305+ // arbitrary section and we have to look in ->sh_link to figure out
1306+ // which one.
1307+ Elf_Shdr & shdrVersionRStrings = shdrs[rdi (shdrVersionR.sh_link )];
1308+ // this is where we find the actual filename strings
1309+ char * verStrTab = (char *) contents + rdi (shdrVersionRStrings.sh_offset );
1310+ // and we also need the name of the section containing the strings, so
1311+ // that we can pass it to replaceSection
1312+ string versionRStringsSName = getSectionName (shdrVersionRStrings);
1313+
1314+ debug (" found .gnu.version_r with %i entries, strings in %s\n " , verNeedNum, versionRStringsSName.c_str ());
1315+
1316+ unsigned int verStrAddedBytes = 0 ;
13071317
13081318 Elf_Verneed * need = (Elf_Verneed *) (contents + rdi (shdrVersionR.sh_offset ));
13091319 while (verNeedNum > 0 ) {
1320+ char * file = verStrTab + rdi (need->vn_file );
1321+ if (libs.find (file) != libs.end ()) {
1322+ const string & replacement = libs[file];
13101323
1311- // XX check need->vn_file, which is an offset into the
1312- // shdrVersionRStrings section
1313- // if if matches one of the entries in `libs`, then use
1314- // replaceSection logic like that above to add the new string to
1315- // this section and change vn_file
1324+ debug (" replacing .gnu.version_r entry `%s' with `%s'\n " , file, replacement.c_str ());
1325+ debug (" resizing string section %s ...\n " , versionRStringsSName.c_str ());
13161326
1317- need = (Elf_Verneed *) (contents + rdi (need->vn_next ));
1318- verNeedNum--;
1327+ string & newVerDynStr = replaceSection (versionRStringsSName,
1328+ rdi (shdrVersionRStrings.sh_size ) + replacement.size () + 1 + verStrAddedBytes);
1329+ setSubstr (newVerDynStr, rdi (shdrVersionRStrings.sh_size ) + verStrAddedBytes, replacement + ' \0 ' );
1330+
1331+ wri (need->vn_file , rdi (shdrVersionRStrings.sh_size ) + verStrAddedBytes);
1332+
1333+ verStrAddedBytes += replacement.size () + 1 ;
1334+
1335+ changed = true ;
1336+ } else {
1337+ debug (" keeping .gnu.version_r entry `%s'\n " , file);
1338+ }
1339+ // the Elf_Verneed structures form a linked list, so jump to next entry
1340+ need = (Elf_Verneed *) (contents + rdi (shdrVersionR.sh_offset ) + rdi (need->vn_next ));
1341+ --verNeedNum;
13191342 }
13201343 }
13211344}
0 commit comments