+
+ for (n = new_file_h->e_shnum - 1; n; n--)
+ {
+ ElfW(Shdr) section = NEW_SECTION_H (n);
+ caddr_t reloc, end;
+ ElfW(Addr) addr, offset;
+ int target;
+
+ switch (section.sh_type)
+ {
+ default:
+ break;
+ case SHT_REL:
+ case SHT_RELA:
+ /* This code handles two different size structs, but there should
+ be no harm in that provided that r_offset is always the first
+ member. */
+ for (reloc = old_base + section.sh_offset,
+ end = reloc + section.sh_size;
+ reloc < end;
+ reloc += section.sh_entsize)
+ {
+ addr = ((ElfW(Rel) *) reloc)->r_offset;
+#ifdef __alpha__
+ /* The Alpha ELF binutils currently have a bug that
+ sometimes results in relocs that contain all
+ zeroes. Work around this for now... */
+ if (addr == 0)
+ continue;
+#endif
+ for (nn = 0; nn < n_unreloc_sections; nn++)
+ {
+ target = unreloc_sections[nn];
+ if (NEW_SECTION_H (target).sh_addr <= addr
+ && addr < (NEW_SECTION_H (target).sh_addr +
+ NEW_SECTION_H (target).sh_size))
+ {
+ offset = (NEW_SECTION_H (target).sh_addr -
+ NEW_SECTION_H (target).sh_offset);
+ memcpy (new_base + addr - offset,
+ old_base + addr - offset,
+ sizeof (ElfW(Addr)));
+#ifdef DEBUG
+ fprintf (stderr, "unrelocate: [%08lx] <= %08lx\n",
+ (long) addr,
+ (long) *((long *) (new_base + addr - offset)));
+#endif
+ break;
+ }
+ }
+ }
+ break;
+ }