Bug 771569 - Move elfhack sections before .rel{,a}.dyn to work around glibc 2.16 bug. r=froydnj a=akeybl
--- a/build/unix/elfhack/elfhack.cpp
+++ b/build/unix/elfhack/elfhack.cpp
@@ -470,29 +470,30 @@ int do_relocation_section(Elf *elf, unsi
}
}
if (relhack_entry.r_offset)
relhack->push_back(relhack_entry);
// Last entry must be NULL
relhack_entry.r_offset = relhack_entry.r_info = 0;
relhack->push_back(relhack_entry);
- relhackcode->insertAfter(section);
+ unsigned int old_end = section->getOffset() + section->getSize();
+
+ relhackcode->insertBefore(section);
relhack->insertAfter(relhackcode);
- unsigned int old_end = section->getOffset() + section->getSize();
section->rels.assign(new_rels.begin(), new_rels.end());
section->shrink(new_rels.size() * section->getEntSize());
ElfLocation *init = new ElfLocation(relhackcode, relhackcode->getEntryPoint());
dyn->setValueForType(DT_INIT, init);
// TODO: adjust the value according to the remaining number of relative relocations
if (dyn->getValueForType(Rel_Type::d_tag_count))
dyn->setValueForType(Rel_Type::d_tag_count, new ElfPlainValue(0));
- if (relhack->getOffset() + relhack->getSize() >= old_end) {
+ if (section->getOffset() + section->getSize() >= old_end) {
fprintf(stderr, "No gain. Skipping\n");
return -1;
}
return 0;
}
static inline int backup_file(const char *name)
{
--- a/build/unix/elfhack/elfxx.h
+++ b/build/unix/elfhack/elfxx.h
@@ -388,16 +388,33 @@ public:
} else
next = NULL;
if (next != NULL)
next->previous = this;
if (dirty)
markDirty();
}
+ void insertBefore(ElfSection *section, bool dirty = true) {
+ if (previous != NULL)
+ previous->next = next;
+ if (next != NULL)
+ next->previous = previous;
+ next = section;
+ if (section != NULL) {
+ previous = section->previous;
+ section->previous = this;
+ } else
+ previous = NULL;
+ if (previous != NULL)
+ previous->next = this;
+ if (dirty)
+ markDirty();
+ }
+
void markDirty() {
if (link != NULL)
shdr.sh_link = -1;
if (info.index)
shdr.sh_info = -1;
shdr.sh_offset = -1;
if (isRelocatable())
shdr.sh_addr = -1;