diff options
66 files changed, 7775 insertions, 260 deletions
diff --git a/trunk/ChangeLog.cross b/trunk/ChangeLog.cross new file mode 100644 index 0000000..1578fd6 --- /dev/null +++ b/trunk/ChangeLog.cross @@ -0,0 +1,115 @@ +2006-12-01 Mark Hatle <mark.hatle@windriver.com> + + * merge to 20061201 (r151) + * src/arch-arm.c: remove read_une32, write_ne32, buf_write_ne32, + buf_read_une32 + * src/dso-readonly.c: sync to changes in src/dso.c + +2006-08-18 Mark Hatle <mark.hatle@windriver.com> + + * arch-arm.c: remove prelink_conflict_rela + * arch-arm.c: Add big-endian arm support, based on arch-sh.c + +2006-08-17 Mark Hatle <mark.hatle@windriver.com> + + * data.c, dso.c, prelink.h: when using elfutils/libelf, we need + to byte swap only if the type is ELF_T_BYTE. + * dso-readonly.c: add get_data prototype change for byteswapping + * ld-libs.c: add get_data prototype change for byteswapping + +2006-08-10 Mark Hatle <mark.hatle@windriver.com> + + * testsuite/Makefile.in: Allow testsuite to run using cross prelink. + Disable the run-time tests, but keep all basic + prelink testing. + * testsuite/ccx1.sh, testsuite/cycle1.sh, testsuite/cycle2.sh + testsuite/deps1.sh, testsuite/deps2.sh, testuite/functions.sh + testuite/layout1.sh, testuite/layout2.sh, testsuite/movelibs.sh + testsuite/quick1.sh, testsuite/quick2.sh, testsuite/quick3.sh + testsuite/reloc1.sh, testsuite/reloc2.sh, testsuite/reloc3.sh + testsuite/reloc4.sh, testsuite/reloc5.sh, testsuite/reloc6.sh + testsuite/reloc7.sh, testsuite/reloc8.sh, testsuite/reloc9.sh + testsuite/reloc10.sh, testsuite/reloc11.sh, testsuite/shuffle1.sh + testsuite/shuffle2.c, testsuite/shuffle2.sh, testsuite/shuffle3.sh + testsuite/shuffle4.sh, testsuite/shuffle5.sh, testsuite/shuffle6.sh + testsuite/shuffle7.sh, testsuite/shuffle8.sh, testsuite/tls1.sh + testsuite/tls2.sh, testsuite/tls3.sh, testsuite/tls4.sh + testsuite/tls5.sh, testsuite/tls6.sh, testsuite/tls7.sh + testsuite/undo1.sh: ditto + +2006-08-09 Mark Hatle <mark.hatle@windriver.com> + + * execstack.c: add WR versioning + * ld-libs.c: add argp option processing and WR versioning + * main.c: add WR versioning + +2006-08-09 Mark Hatle <mark.hatle@windriver.com> + + * ld-libs.c: Add --root argument to prelink-rtld + +2006-08-09 Mark Hatle <mark.hatle@windriver.com> + + * cross-prelink code merged and upreved + original code from: + MontaVista Software, Inc. + CodeSourcery, LLC. + * Makefile.am: add prelink-rtld, libiberty + * dso-readonly.c: new file based on dso.c + * gather.c: use cross-rtld + * get.c: use cross-rtld + * ld-do-lookup.h: Add ld-do-lookup.h from glibc + * ld-libs.c: add cross-rtld functionality + * ld-libs.h: ditto + * ld-lookup.c: ditto + * ld-lookup64.c: ditto + * main.c: Add rtld option + * prelink.h: add extern rtld variable + +2006-08-09 CodeSourcery, LLC. + + * main.c: if we modified /sbin/init, re-run init + +2006-08-08 CodeSourcery, LLC. + + * arch-arm.c: add ARM EABI support, dynamic_linker_alt + * src/dso.c: STT_ARM_TFUNC support + * src/get.c: ld-linux.so.3 to the list of ldso names + +2006-08-08 CodeSourcery, LLC. + + * gather.c: add new dynamic_linker_alt + * prelink.h: ditto + +2006-08-08 MontaVista Software, Inc. + + * main.c: Add relative sysroot support + +2006-08-08 Montavista Software, Inc. + + * Makefile.am: Add function wrapper support for sysroots + * main.c: add --root option + * cache.c, doit.c, dso.c, execstack.c, gather.c, get.c, + prelink.h, undoall.c, verify.c: Add functional wrappers for sysroot + * wrap-file.c: add function wrapper definitions + +2006-07-28 Alexandre Oliva <aoliva@redhat.com> + + * src/cache.c: Avoid SEGFAULT when sorting cache entries (#197451) + +2006-07-21 MontaVista Software, Inc. + + * prelink.c: add PRELINK_TIMESTAMP support + +2006-07-21 MontaVista Software, Inc. + + * dso.c: Don't adjust reloc for debug info + +2006-06-30 Mark Hatle <mark.hatle@windriver.com> + + * src/elf.h: Make available the elf.h file from glibc 2.3.6 + +2006-06-10 MontaVista Software, Inc. + + * arch-sh.c: Fix R_SH_RELATIVE endian swap problem, + change max page size + diff --git a/trunk/src/Makefile.am b/trunk/src/Makefile.am index 882eeea..6981801 100644 --- a/trunk/src/Makefile.am +++ b/trunk/src/Makefile.am @@ -4,25 +4,31 @@ AUTOMAKE_OPTIONS = 1.4 gnu DEFS = -D_GNU_SOURCE -DHAVE_CONFIG_H -Wall AM_CFLAGS = -Wall -AM_CPPFLAGS = -DSBINDIR='"@sbindir@"' +AM_CPPFLAGS = -DSBINDIR='"@sbindir@"' -DBINDIR='"@bindir@"' INCLUDES = @GELFINCLUDE@ -sbin_PROGRAMS = prelink +sbin_PROGRAMS = prelink prelink-rtld bin_PROGRAMS = execstack arch_SOURCES = arch-i386.c arch-alpha.c arch-ppc.c arch-ppc64.c \ arch-sparc.c arch-sparc64.c arch-x86_64.c arch-mips.c \ arch-s390.c arch-s390x.c arch-arm.c arch-sh.c arch-ia64.c common_SOURCES = checksum.c data.c dso.c dwarf2.c dwarf2.h fptr.c fptr.h \ - hashtab.c hashtab.h mdebug.c prelink.h stabs.c crc32.c + hashtab.c hashtab.h mdebug.c prelink.h stabs.c crc32.c \ + wrap-file.c canonicalize.c prelink_SOURCES = cache.c conflict.c cxx.c doit.c exec.c execle_open.c get.c \ gather.c layout.c main.c prelink.c \ prelinktab.h reloc.c reloc.h space.c undo.c undoall.c \ - verify.c canonicalize.c md5.c md5.h sha.c sha.h \ + verify.c md5.c md5.h sha.c sha.h \ $(common_SOURCES) $(arch_SOURCES) -prelink_LDADD = @LIBGELF@ +prelink_LDADD = @LIBGELF@ -liberty prelink_LDFLAGS = -all-static execstack_SOURCES = execstack.c $(common_SOURCES) $(arch_SOURCES) +prelink_rtld_LDADD = @LIBGELF@ -liberty +prelink_rtld_SOURCES = data.c dso-readonly.c ld-libs.c ld-lookup.c \ + canonicalize.c wrap-file.c ld-lookup64.c +prelink_rtld_LDFLAGS = -all-static + extra_DIST = makecrc.c diff --git a/trunk/src/arch-arm.c b/trunk/src/arch-arm.c index 6641e86..12b8f3d 100644 --- a/trunk/src/arch-arm.c +++ b/trunk/src/arch-arm.c @@ -28,6 +28,12 @@ #include "prelink.h" +#ifndef R_ARM_TLS_DTPMOD32 +#define R_ARM_TLS_DTPMOD32 17 /* ID of module containing symbol */ +#define R_ARM_TLS_DTPOFF32 18 /* Offset in TLS block */ +#define R_ARM_TLS_TPOFF32 19 /* Offset in static TLS block */ +#endif + static int arm_adjust_dyn (DSO *dso, int n, GElf_Dyn *dyn, GElf_Addr start, GElf_Addr adjust) @@ -40,12 +46,12 @@ arm_adjust_dyn (DSO *dso, int n, GElf_Dyn *dyn, GElf_Addr start, if (sec == -1) return 0; - data = read_ule32 (dso, dyn->d_un.d_ptr); + data = read_une32 (dso, dyn->d_un.d_ptr); /* If .got.plt[0] points to _DYNAMIC, it needs to be adjusted. */ if (data == dso->shdr[n].sh_addr && data >= start) - write_le32 (dso, dyn->d_un.d_ptr, data + adjust); + write_ne32 (dso, dyn->d_un.d_ptr, data + adjust); - data = read_ule32 (dso, dyn->d_un.d_ptr + 4); + data = read_une32 (dso, dyn->d_un.d_ptr + 4); /* If .got.plt[1] points to .plt, it needs to be adjusted. */ if (data && data >= start) { @@ -57,7 +63,7 @@ arm_adjust_dyn (DSO *dso, int n, GElf_Dyn *dyn, GElf_Addr start, && strcmp (strptr (dso, dso->ehdr.e_shstrndx, dso->shdr[i].sh_name), ".plt") == 0) { - write_le32 (dso, dyn->d_un.d_ptr + 4, data + adjust); + write_ne32 (dso, dyn->d_un.d_ptr + 4, data + adjust); break; } } @@ -74,9 +80,9 @@ arm_adjust_rel (DSO *dso, GElf_Rel *rel, GElf_Addr start, { case R_ARM_RELATIVE: case R_ARM_JUMP_SLOT: - data = read_ule32 (dso, rel->r_offset); + data = read_une32 (dso, rel->r_offset); if (data >= start) - write_le32 (dso, rel->r_offset, data + adjust); + write_ne32 (dso, rel->r_offset, data + adjust); break; } return 0; @@ -96,13 +102,13 @@ arm_adjust_rela (DSO *dso, GElf_Rela *rela, GElf_Addr start, rela->r_addend += (Elf32_Sword) adjust; /* Write it to the memory location as well. Not necessary, but we can do it. */ - write_le32 (dso, rela->r_offset, rela->r_addend); + write_ne32 (dso, rela->r_offset, rela->r_addend); } break; case R_ARM_JUMP_SLOT: - data = read_ule32 (dso, rela->r_offset); + data = read_une32 (dso, rela->r_offset); if (data >= start) - write_le32 (dso, rela->r_offset, data + adjust); + write_ne32 (dso, rela->r_offset, data + adjust); break; break; } @@ -126,18 +132,18 @@ arm_prelink_rel (struct prelink_info *info, GElf_Rel *rel, GElf_Addr reladdr) { case R_ARM_GLOB_DAT: case R_ARM_JUMP_SLOT: - write_le32 (dso, rel->r_offset, value); + write_ne32 (dso, rel->r_offset, value); break; case R_ARM_ABS32: { - if (read_ule32 (dso, rel->r_offset)) + if (read_une32 (dso, rel->r_offset)) { error (0, 0, "%s: R_ARM_ABS32 relocs with non-zero addend should not be present in prelinked REL sections", dso->filename); return 1; } rel->r_info = GELF_R_INFO (GELF_R_SYM (rel->r_info), R_ARM_GLOB_DAT); - write_le32 (dso, rel->r_offset, value); + write_ne32 (dso, rel->r_offset, value); /* Tell prelink_rel routine *rel has changed. */ return 2; } @@ -151,6 +157,25 @@ arm_prelink_rel (struct prelink_info *info, GElf_Rel *rel, GElf_Addr reladdr) return 0; error (0, 0, "%s: R_ARM_COPY reloc in shared library?", dso->filename); return 1; + case R_ARM_TLS_DTPOFF32: + write_ne32 (dso, rel->r_offset, value); + break; + /* DTPMOD32 and TPOFF32 is impossible to predict in shared libraries + unless prelink sets the rules. */ + case R_ARM_TLS_DTPMOD32: + if (dso->ehdr.e_type == ET_EXEC) + { + error (0, 0, "%s: R_ARM_TLS_DTPMOD32 reloc in executable?", + dso->filename); + return 1; + } + break; + case R_ARM_TLS_TPOFF32: + if (dso->ehdr.e_type == ET_EXEC) + error (0, 0, "%s: R_ARM_TLS_TPOFF32 relocs should not be present in " + "prelinked ET_EXEC REL sections", + dso->filename); + break; default: error (0, 0, "%s: Unknown arm relocation type %d", dso->filename, (int) GELF_R_TYPE (rel->r_info)); @@ -178,10 +203,10 @@ arm_prelink_rela (struct prelink_info *info, GElf_Rela *rela, { case R_ARM_GLOB_DAT: case R_ARM_JUMP_SLOT: - write_le32 (dso, rela->r_offset, value + rela->r_addend); + write_ne32 (dso, rela->r_offset, value + rela->r_addend); break; case R_ARM_ABS32: - write_le32 (dso, rela->r_offset, value + rela->r_addend); + write_ne32 (dso, rela->r_offset, value + rela->r_addend); break; case R_ARM_PC24: val = value + rela->r_addend - rela->r_offset; @@ -192,8 +217,8 @@ arm_prelink_rela (struct prelink_info *info, GElf_Rela *rela, return 1; } val &= 0xffffff; - write_le32 (dso, rela->r_offset, - (read_ule32 (dso, rela->r_offset) & 0xff000000) | val); + write_ne32 (dso, rela->r_offset, + (read_une32 (dso, rela->r_offset) & 0xff000000) | val); break; case R_ARM_COPY: if (dso->ehdr.e_type == ET_EXEC) @@ -201,6 +226,24 @@ arm_prelink_rela (struct prelink_info *info, GElf_Rela *rela, return 0; error (0, 0, "%s: R_ARM_COPY reloc in shared library?", dso->filename); return 1; + case R_ARM_TLS_DTPOFF32: + write_ne32 (dso, rela->r_offset, value + rela->r_addend); + break; + /* DTPMOD32 and TPOFF32 is impossible to predict in shared libraries + unless prelink sets the rules. */ + case R_ARM_TLS_DTPMOD32: + if (dso->ehdr.e_type == ET_EXEC) + { + error (0, 0, "%s: R_ARM_TLS_DTPMOD32 reloc in executable?", + dso->filename); + return 1; + } + break; + case R_ARM_TLS_TPOFF32: + if (dso->ehdr.e_type == ET_EXEC && info->resolvetls) + write_ne32 (dso, rela->r_offset, + value + rela->r_addend + info->resolvetls->offset); + break; default: error (0, 0, "%s: Unknown arm relocation type %d", dso->filename, (int) GELF_R_TYPE (rela->r_info)); @@ -218,7 +261,7 @@ arm_apply_conflict_rela (struct prelink_info *info, GElf_Rela *rela, case R_ARM_GLOB_DAT: case R_ARM_JUMP_SLOT: case R_ARM_ABS32: - buf_write_le32 (buf, rela->r_addend); + buf_write_ne32 (info->dso, buf, rela->r_addend); break; default: abort (); @@ -240,14 +283,14 @@ arm_apply_rel (struct prelink_info *info, GElf_Rel *rel, char *buf) break; case R_ARM_GLOB_DAT: case R_ARM_JUMP_SLOT: - buf_write_le32 (buf, value); + buf_write_ne32 (info->dso, buf, value); break; case R_ARM_ABS32: - buf_write_le32 (buf, value + read_ule32 (info->dso, rel->r_offset)); + buf_write_ne32 (info->dso, buf, value + read_une32 (info->dso, rel->r_offset)); break; case R_ARM_PC24: val = value + rel->r_offset; - value = read_ule32 (info->dso, rel->r_offset) << 8; + value = read_une32 (info->dso, rel->r_offset) << 8; value = ((Elf32_Sword) value) >> 6; val += value; val >>= 2; @@ -257,7 +300,7 @@ arm_apply_rel (struct prelink_info *info, GElf_Rel *rel, char *buf) return 1; } val &= 0xffffff; - buf_write_le32 (buf, (buf_read_ule32 (buf) & 0xff000000) | val); + buf_write_ne32 (info->dso, buf, (buf_read_une32 (info->dso, buf) & 0xff000000) | val); break; case R_ARM_COPY: abort (); @@ -285,7 +328,7 @@ arm_apply_rela (struct prelink_info *info, GElf_Rela *rela, char *buf) case R_ARM_GLOB_DAT: case R_ARM_JUMP_SLOT: case R_ARM_ABS32: - buf_write_le32 (buf, value + rela->r_addend); + buf_write_ne32 (info->dso, buf, value + rela->r_addend); break; case R_ARM_PC24: val = value + rela->r_addend - rela->r_offset; @@ -296,7 +339,7 @@ arm_apply_rela (struct prelink_info *info, GElf_Rela *rela, char *buf) return 1; } val &= 0xffffff; - buf_write_le32 (buf, (buf_read_ule32 (buf) & 0xff000000) | val); + buf_write_ne32 (info->dso, buf, (buf_read_une32 (info->dso, buf) & 0xff000000) | val); break; case R_ARM_COPY: abort (); @@ -315,6 +358,7 @@ arm_prelink_conflict_rel (DSO *dso, struct prelink_info *info, GElf_Rel *rel, { GElf_Addr value; struct prelink_conflict *conflict; + struct prelink_tls *tls; GElf_Rela *ret; if (GELF_R_TYPE (rel->r_info) == R_ARM_RELATIVE @@ -324,8 +368,34 @@ arm_prelink_conflict_rel (DSO *dso, struct prelink_info *info, GElf_Rel *rel, conflict = prelink_conflict (info, GELF_R_SYM (rel->r_info), GELF_R_TYPE (rel->r_info)); if (conflict == NULL) - return 0; - value = conflict_lookup_value (conflict); + { + if (info->curtls == NULL) + return 0; + + switch (GELF_R_TYPE (rel->r_info)) + { + /* Even local DTPMOD and TPOFF relocs need conflicts. */ + case R_ARM_TLS_DTPMOD32: + case R_ARM_TLS_TPOFF32: + break; + + default: + return 0; + } + value = 0; + } + else + { + /* DTPOFF32 wants to see only real conflicts, not lookups + with reloc_class RTYPE_CLASS_TLS. */ + if (GELF_R_TYPE (rel->r_info) == R_ARM_TLS_DTPOFF32 + && conflict->lookup.tls == conflict->conflict.tls + && conflict->lookupval == conflict->conflictval) + return 0; + + value = conflict_lookup_value (conflict); + } + ret = prelink_conflict_add_rela (info); if (ret == NULL) return 1; @@ -345,6 +415,33 @@ arm_prelink_conflict_rel (DSO *dso, struct prelink_info *info, GElf_Rel *rel, case R_ARM_COPY: error (0, 0, "R_ARM_COPY should not be present in shared libraries"); return 1; + case R_ARM_TLS_DTPMOD32: + case R_ARM_TLS_DTPOFF32: + case R_ARM_TLS_TPOFF32: + if (conflict != NULL + && (conflict->reloc_class != RTYPE_CLASS_TLS + || conflict->lookup.tls == NULL)) + { + error (0, 0, "%s: TLS reloc not resolving to STT_TLS symbol", + dso->filename); + return 1; + } + tls = conflict ? conflict->lookup.tls : info->curtls; + ret->r_info = GELF_R_INFO (0, R_ARM_ABS32); + switch (GELF_R_TYPE (rel->r_info)) + { + case R_ARM_TLS_DTPMOD32: + ret->r_addend = tls->modid; + break; + case R_ARM_TLS_DTPOFF32: + ret->r_addend = value; + break; + case R_ARM_TLS_TPOFF32: + ret->r_addend = (value + read_une32 (dso, rel->r_offset) + + tls->offset); + break; + } + break; default: error (0, 0, "%s: Unknown arm relocation type %d", dso->filename, (int) GELF_R_TYPE (rel->r_info)); @@ -359,6 +456,7 @@ arm_prelink_conflict_rela (DSO *dso, struct prelink_info *info, { GElf_Addr value; struct prelink_conflict *conflict; + struct prelink_tls *tls; GElf_Rela *ret; Elf32_Sword val; @@ -368,9 +466,36 @@ arm_prelink_conflict_rela (DSO *dso, struct prelink_info *info, return 0; conflict = prelink_conflict (info, GELF_R_SYM (rela->r_info), GELF_R_TYPE (rela->r_info)); + if (conflict == NULL) - return 0; - value = conflict_lookup_value (conflict); + { + if (info->curtls == NULL) + return 0; + + switch (GELF_R_TYPE (rela->r_info)) + { + /* Even local DTPMOD and TPOFF relocs need conflicts. */ + case R_ARM_TLS_DTPMOD32: + case R_ARM_TLS_TPOFF32: + break; + + default: + return 0; + } + value = 0; + } + else + { + /* DTPOFF32 wants to see only real conflicts, not lookups + with reloc_class RTYPE_CLASS_TLS. */ + if (GELF_R_TYPE (rela->r_info) == R_ARM_TLS_DTPOFF32 + && conflict->lookup.tls == conflict->conflict.tls + && conflict->lookupval == conflict->conflictval) + return 0; + + value = conflict_lookup_value (conflict); + } + ret = prelink_conflict_add_rela (info); if (ret == NULL) return 1; @@ -391,13 +516,39 @@ arm_prelink_conflict_rela (DSO *dso, struct prelink_info *info, error (0, 0, "%s: R_ARM_PC24 overflow", dso->filename); return 1; } - value = read_ule32 (dso, rela->r_offset) & 0xff000000; + value = read_une32 (dso, rela->r_offset) & 0xff000000; ret->r_addend = (Elf32_Sword) (value | (val & 0xffffff)); ret->r_info = GELF_R_INFO (0, R_ARM_ABS32); break; case R_ARM_COPY: error (0, 0, "R_ARM_COPY should not be present in shared libraries"); return 1; + case R_ARM_TLS_DTPMOD32: + case R_ARM_TLS_DTPOFF32: + case R_ARM_TLS_TPOFF32: + if (conflict != NULL + && (conflict->reloc_class != RTYPE_CLASS_TLS + || conflict->lookup.tls == NULL)) + { + error (0, 0, "%s: TLS reloc not resolving to STT_TLS symbol", + dso->filename); + return 1; + } + tls = conflict ? conflict->lookup.tls : info->curtls; + ret->r_info = GELF_R_INFO (0, R_ARM_ABS32); + switch (GELF_R_TYPE (rela->r_info)) + { + case R_ARM_TLS_DTPMOD32: + ret->r_addend = tls->modid; + break; + case R_ARM_TLS_DTPOFF32: + ret->r_addend = value; + break; + case R_ARM_TLS_TPOFF32: + ret->r_addend = value + rela->r_offset + tls->offset; + break; + } + break; default: error (0, 0, "%s: Unknown arm relocation type %d", dso->filename, (int) GELF_R_TYPE (rela->r_info)); @@ -418,14 +569,17 @@ arm_rel_to_rela (DSO *dso, GElf_Rel *rel, GElf_Rela *rela) abort (); case R_ARM_RELATIVE: case R_ARM_ABS32: - rela->r_addend = (Elf32_Sword) read_ule32 (dso, rel->r_offset); + case R_ARM_TLS_TPOFF32: + rela->r_addend = (Elf32_Sword) read_une32 (dso, rel->r_offset); break; case R_ARM_PC24: - rela->r_addend = read_ule32 (dso, rel->r_offset) << 8; + rela->r_addend = read_une32 (dso, rel->r_offset) << 8; rela->r_addend = ((Elf32_Sword) rela->r_addend) >> 6; break; case R_ARM_COPY: case R_ARM_GLOB_DAT: + case R_ARM_TLS_DTPMOD32: + case R_ARM_TLS_DTPOFF32: rela->r_addend = 0; break; } @@ -445,15 +599,18 @@ arm_rela_to_rel (DSO *dso, GElf_Rela *rela, GElf_Rel *rel) abort (); case R_ARM_RELATIVE: case R_ARM_ABS32: - write_le32 (dso, rela->r_offset, rela->r_addend); + case R_ARM_TLS_TPOFF32: + write_ne32 (dso, rela->r_offset, rela->r_addend); break; case R_ARM_PC24: - write_le32 (dso, rela->r_offset, - (read_ule32 (dso, rela->r_offset) & 0xff000000) + write_ne32 (dso, rela->r_offset, + (read_une32 (dso, rela->r_offset) & 0xff000000) | ((rela->r_addend >> 2) & 0xffffff)); break; case R_ARM_GLOB_DAT: - write_le32 (dso, rela->r_offset, 0); + case R_ARM_TLS_DTPMOD32: + case R_ARM_TLS_DTPOFF32: + write_ne32 (dso, rela->r_offset, 0); break; } return 0; @@ -479,7 +636,7 @@ arm_need_rel_to_rela (DSO *dso, int first, int last) switch (ELF32_R_TYPE (rel->r_info)) { case R_ARM_ABS32: - val = read_ule32 (dso, rel->r_offset); + val = read_une32 (dso, rel->r_offset); /* R_ARM_ABS32 with addend 0 can be converted to R_ARM_GLOB_DAT and we don't have to convert to RELA because of that. */ @@ -488,6 +645,14 @@ arm_need_rel_to_rela (DSO *dso, int first, int last) /* FALLTHROUGH */ case R_ARM_PC24: return 1; + case R_ARM_TLS_TPOFF32: + /* In shared libraries TPOFF is changed always into + conflicts, for executables we need to preserve + original addend. */ + if (dso->ehdr.e_type == ET_EXEC) + return 1; + + break; } } } @@ -521,7 +686,7 @@ arm_arch_prelink (struct prelink_info *info) if (i == dso->ehdr.e_shnum) return 0; data = dso->shdr[i].sh_addr; - write_le32 (dso, dso->info[DT_PLTGOT] + 4, data); + write_ne32 (dso, dso->info[DT_PLTGOT] + 4, data); } return 0; @@ -550,9 +715,9 @@ arm_arch_undo_prelink (DSO *dso) if (i == dso->ehdr.e_shnum) return 0; - data = read_ule32 (dso, dso->info[DT_PLTGOT] + 4); + data = read_une32 (dso, dso->info[DT_PLTGOT] + 4); if (data == dso->shdr[i].sh_addr) - write_le32 (dso, dso->info[DT_PLTGOT] + 4, 0); + write_ne32 (dso, dso->info[DT_PLTGOT] + 4, 0); } return 0; @@ -580,17 +745,17 @@ arm_undo_prelink_rel (DSO *dso, GElf_Rel *rel, GElf_Addr reladdr) } else { - Elf32_Addr data = read_ule32 (dso, dso->shdr[sec].sh_addr + 4); + Elf32_Addr data = read_une32 (dso, dso->shdr[sec].sh_addr + 4); assert (rel->r_offset >= dso->shdr[sec].sh_addr + 12); assert (((rel->r_offset - dso->shdr[sec].sh_addr) & 3) == 0); - write_le32 (dso, rel->r_offset, data); + write_ne32 (dso, rel->r_offset, data); } break; case R_ARM_GLOB_DAT: sec = addr_to_sec (dso, rel->r_offset); - write_le32 (dso, rel->r_offset, 0); + write_ne32 (dso, rel->r_offset, 0); if (sec != -1) { if (strcmp (strptr (dso, dso->ehdr.e_shstrndx, @@ -614,6 +779,12 @@ arm_undo_prelink_rel (DSO *dso, GElf_Rel *rel, GElf_Addr reladdr) return 0; error (0, 0, "%s: R_ARM_COPY reloc in shared library?", dso->filename); return 1; + case R_ARM_TLS_DTPMOD32: + case R_ARM_TLS_DTPOFF32: + write_ne32 (dso, rel->r_offset, 0); + break; + case R_ARM_TLS_TPOFF32: + break; default: error (0, 0, "%s: Unknown arm relocation type %d", dso->filename, (int) GELF_R_TYPE (rel->r_info)); @@ -636,6 +807,10 @@ arm_reloc_class (int reloc_type) { case R_ARM_COPY: return RTYPE_CLASS_COPY; case R_ARM_JUMP_SLOT: return RTYPE_CLASS_PLT; + case R_ARM_TLS_DTPMOD32: + case R_ARM_TLS_DTPOFF32: + case R_ARM_TLS_TPOFF32: + return RTYPE_CLASS_TLS; default: return RTYPE_CLASS_VALID; } } @@ -649,6 +824,7 @@ PL_ARCH = { .R_COPY = R_ARM_COPY, .R_RELATIVE = R_ARM_RELATIVE, .dynamic_linker = "/lib/ld-linux.so.2", + .dynamic_linker_alt = "/lib/ld-linux.so.3", .adjust_dyn = arm_adjust_dyn, .adjust_rel = arm_adjust_rel, .adjust_rela = arm_adjust_rela, diff --git a/trunk/src/arch-sh.c b/trunk/src/arch-sh.c index 6b2914a..6ddf5f6 100644 --- a/trunk/src/arch-sh.c +++ b/trunk/src/arch-sh.c @@ -348,7 +348,7 @@ sh_undo_prelink_rela (DSO *dso, GElf_Rela *rela, GElf_Addr relaaddr) break; case R_SH_RELATIVE: if (rela->r_addend) - write_le32 (dso, rela->r_offset, 0); + write_ne32 (dso, rela->r_offset, 0); break; case R_SH_JMP_SLOT: sec = addr_to_sec (dso, rela->r_offset); @@ -440,6 +440,6 @@ PL_ARCH = { even dlopened libraries will get the slots they desire. */ .mmap_base = 0x30000000, .mmap_end = 0x40000000, - .max_page_size = 0x2000, + .max_page_size = 0x10000, .page_size = 0x1000 }; diff --git a/trunk/src/cache.c b/trunk/src/cache.c index b677e22..2a72267 100644 --- a/trunk/src/cache.c +++ b/trunk/src/cache.c @@ -112,8 +112,8 @@ prelink_find_entry (const char *filename, const struct stat64 *stp, if (! stp) { - canon_filename = prelink_canonicalize (filename, &st); - if (canon_filename == NULL && stat64 (filename, &st) < 0) + canon_filename = wrap_prelink_canonicalize (filename, &st); + if (canon_filename == NULL && wrap_stat64 (filename, &st) < 0) { error (0, errno, "Could not stat %s", filename); if (insert) @@ -142,7 +142,7 @@ prelink_find_entry (const char *filename, const struct stat64 *stp, { ent = (struct prelink_entry *) *devino_slot; if (canon_filename == NULL) - canon_filename = prelink_canonicalize (filename, NULL); + canon_filename = wrap_prelink_canonicalize (filename, NULL); if (canon_filename == NULL) { error (0, 0, "Could not canonicalize filename %s", filename); @@ -189,7 +189,7 @@ prelink_find_entry (const char *filename, const struct stat64 *stp, if (canon_filename != NULL) ent->canon_filename = canon_filename; else - ent->canon_filename = prelink_canonicalize (filename, NULL); + ent->canon_filename = wrap_prelink_canonicalize (filename, NULL); if (ent->canon_filename == NULL) { error (0, 0, "Could not canonicalize filename %s", filename); @@ -248,7 +248,7 @@ prelink_load_entry (const char *filename) if (*filename_slot != NULL) return (struct prelink_entry *) *filename_slot; - canon_filename = prelink_canonicalize (filename, &st); + canon_filename = wrap_prelink_canonicalize (filename, &st); if (canon_filename == NULL) goto error_out2; if (strcmp (canon_filename, filename) != 0) @@ -364,7 +364,7 @@ prelink_load_cache (void) size_t cache_size; uint32_t string_start, *dep; - fd = open (prelink_cache, O_RDONLY); + fd = wrap_open (prelink_cache, O_RDONLY); if (fd < 0) return 0; /* The cache does not exist yet. */ @@ -672,7 +672,7 @@ prelink_save_cache (int do_warn) char prelink_cache_tmp [prelink_cache_len + sizeof (".XXXXXX")]; memcpy (mempcpy (prelink_cache_tmp, prelink_cache, prelink_cache_len), ".XXXXXX", sizeof (".XXXXXX")); - fd = mkstemp (prelink_cache_tmp); + fd = wrap_mkstemp (prelink_cache_tmp); if (fd < 0) { error (0, errno, "Could not write prelink cache"); @@ -683,10 +683,10 @@ prelink_save_cache (int do_warn) || write (fd, data, len) != len || fchmod (fd, 0644) || close (fd) - || rename (prelink_cache_tmp, prelink_cache)) + || wrap_rename (prelink_cache_tmp, prelink_cache)) { error (0, errno, "Could not write prelink cache"); - unlink (prelink_cache_tmp); + wrap_unlink (prelink_cache_tmp); return 1; } return 0; diff --git a/trunk/src/data.c b/trunk/src/data.c index 742d6b3..13380da 100644 --- a/trunk/src/data.c +++ b/trunk/src/data.c @@ -22,12 +22,16 @@ uint##nn##_t \ read_u##le##nn (DSO *dso, GElf_Addr addr) \ { \ - unsigned char *data = get_data (dso, addr, NULL); \ + Elf_Type type; \ + unsigned char *data = get_data (dso, addr, NULL, &type); \ \ if (data == NULL) \ return 0; \ \ - return buf_read_u##le##nn (data); \ + if (type == ELF_T_BYTE) \ + return buf_read_u##le##nn (data); \ + else \ + return *(uint##nn##_t *)data; \ } #define WRITE(le,nn) \ @@ -35,12 +39,16 @@ int \ write_##le##nn (DSO *dso, GElf_Addr addr, uint##nn##_t val) \ { \ int sec; \ - unsigned char *data = get_data (dso, addr, &sec); \ + Elf_Type type; \ + unsigned char *data = get_data (dso, addr, &sec, &type); \ \ if (data == NULL) \ return -1; \ \ - buf_write_##le##nn (data, val); \ + if (type == ELF_T_BYTE) \ + buf_write_##le##nn (data, val); \ + else \ + *(uint##nn##_t *)data = val; \ elf_flagscn (dso->scn[sec], ELF_C_SET, ELF_F_DIRTY); \ return 0; \ } @@ -93,7 +101,7 @@ buf_write_ne##nn (DSO *dso, unsigned char *buf, \ WRITENE(nn) BUFWRITENE(nn) unsigned char * -get_data (DSO *dso, GElf_Addr addr, int *secp) +get_data (DSO *dso, GElf_Addr addr, int *secp, Elf_Type *typep) { int sec = addr_to_sec (dso, addr); Elf_Data *data = NULL; @@ -107,8 +115,10 @@ get_data (DSO *dso, GElf_Addr addr, int *secp) addr -= dso->shdr[sec].sh_addr; while ((data = elf_getdata (dso->scn[sec], data)) != NULL) if (data->d_off <= addr && data->d_off + data->d_size > addr) + { + if (typep) *typep = data->d_type; return (unsigned char *) data->d_buf + (addr - data->d_off); - + } return NULL; } diff --git a/trunk/src/doit.c b/trunk/src/doit.c index 31c32fd..2208ece 100644 --- a/trunk/src/doit.c +++ b/trunk/src/doit.c @@ -161,7 +161,7 @@ prelink_ent (struct prelink_entry *ent) { size_t len; - if (lstat64 (hardlink->canon_filename, &st) < 0) + if (wrap_lstat64 (hardlink->canon_filename, &st) < 0) { error (0, 0, "Could not stat %s (former hardlink to %s)", hardlink->canon_filename, ent->canon_filename); @@ -204,19 +204,19 @@ prelink_ent (struct prelink_entry *ent) memcpy (mempcpy (move, hardlink->canon_filename, len), ".#prelink#", sizeof (".#prelink#")); - if (rename (hardlink->canon_filename, move) < 0) + if (wrap_rename (hardlink->canon_filename, move) < 0) { error (0, errno, "Could not hardlink %s to %s", hardlink->canon_filename, ent->canon_filename); continue; } - if (link (ent->canon_filename, hardlink->canon_filename) < 0) + if (wrap_link (ent->canon_filename, hardlink->canon_filename) < 0) { error (0, errno, "Could not hardlink %s to %s", hardlink->canon_filename, ent->canon_filename); - if (rename (move, hardlink->canon_filename) < 0) + if (wrap_rename (move, hardlink->canon_filename) < 0) { error (0, errno, "Could not rename %s back to %s", move, hardlink->canon_filename); @@ -224,7 +224,7 @@ prelink_ent (struct prelink_entry *ent) continue; } - if (unlink (move) < 0) + if (wrap_unlink (move) < 0) { error (0, errno, "Could not unlink %s", move); continue; @@ -232,7 +232,7 @@ prelink_ent (struct prelink_entry *ent) } free (move); - if (! dry_run && stat64 (ent->canon_filename, &st) >= 0) + if (! dry_run && wrap_stat64 (ent->canon_filename, &st) >= 0) { ent->dev = st.st_dev; ent->ino = st.st_ino; diff --git a/trunk/src/dso-readonly.c b/trunk/src/dso-readonly.c new file mode 100644 index 0000000..8ad5865 --- /dev/null +++ b/trunk/src/dso-readonly.c @@ -0,0 +1,1823 @@ +/* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 Red Hat, Inc. + Written by Jakub Jelinek <jakub@redhat.com>, 2001. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <config.h> +#include <assert.h> +#include <errno.h> +#include <error.h> +#include <fcntl.h> +#include <string.h> +#include <sys/stat.h> +#include <sys/time.h> +#include <time.h> +#include <unistd.h> +#include <utime.h> +#include "prelink.h" + +#if defined HAVE_LIBSELINUX && defined HAVE_SELINUX_SELINUX_H +#include <selinux/selinux.h> +#define USE_SELINUX +#endif + +#define RELOCATE_SCN(shf) \ + ((shf) & (SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR)) + +#ifndef ELF_F_PERMISSIVE +# define ELF_F_PERMISSIVE 0 +#endif + +void +read_dynamic (DSO *dso) +{ + int i; + + memset (dso->info, 0, sizeof(dso->info)); + dso->info_set_mask = 0; + for (i = 0; i < dso->ehdr.e_shnum; i++) + if (dso->shdr[i].sh_type == SHT_DYNAMIC) + { + Elf_Data *data = NULL; + Elf_Scn *scn = dso->scn[i]; + GElf_Dyn dyn; + + dso->dynamic = i; + while ((data = elf_getdata (scn, data)) != NULL) + { + int ndx, maxndx; + + maxndx = data->d_size / dso->shdr[i].sh_entsize; + for (ndx = 0; ndx < maxndx; ++ndx) + { + gelfx_getdyn (dso->elf, data, ndx, &dyn); + if (dyn.d_tag == DT_NULL) + break; + else if ((GElf_Xword) dyn.d_tag < DT_NUM) + { + dso->info[dyn.d_tag] = dyn.d_un.d_val; + if (dyn.d_tag < 50) + dso->info_set_mask |= (1ULL << dyn.d_tag); + } + else if (dyn.d_tag == DT_CHECKSUM) + { + dso->info_DT_CHECKSUM = dyn.d_un.d_val; + dso->info_set_mask |= (1ULL << DT_CHECKSUM_BIT); + } + else if (dyn.d_tag == DT_GNU_PRELINKED) + { + dso->info_DT_GNU_PRELINKED = dyn.d_un.d_val; + dso->info_set_mask |= (1ULL << DT_GNU_PRELINKED_BIT); + } + else if (dyn.d_tag == DT_VERDEF) + { + dso->info_DT_VERDEF = dyn.d_un.d_val; + dso->info_set_mask |= (1ULL << DT_VERDEF_BIT); + } + else if (dyn.d_tag == DT_VERNEED) + { + dso->info_DT_VERNEED = dyn.d_un.d_val; + dso->info_set_mask |= (1ULL << DT_VERNEED_BIT); + } + else if (dyn.d_tag == DT_VERSYM) + { + dso->info_DT_VERSYM = dyn.d_un.d_val; + dso->info_set_mask |= (1ULL << DT_VERSYM_BIT); + } + else if (dyn.d_tag == DT_FILTER) + dso->info_set_mask |= (1ULL << DT_FILTER_BIT); + else if (dyn.d_tag == DT_AUXILIARY) + dso->info_set_mask |= (1ULL << DT_AUXILIARY_BIT); + else if (dyn.d_tag == DT_LOPROC) + dso->info_set_mask |= (1ULL << DT_LOPROC_BIT); + else if (dyn.d_tag == DT_GNU_HASH) + { + dso->info_DT_GNU_HASH = dyn.d_un.d_val; + dso->info_set_mask |= (1ULL << DT_GNU_HASH_BIT); + } + if (dso->ehdr.e_machine == EM_MIPS) + { + if (dyn.d_tag == DT_MIPS_LOCAL_GOTNO) + dso->info_DT_MIPS_LOCAL_GOTNO = dyn.d_un.d_val; + else if (dyn.d_tag == DT_MIPS_GOTSYM) + dso->info_DT_MIPS_GOTSYM = dyn.d_un.d_val; + else if (dyn.d_tag == DT_MIPS_SYMTABNO) + dso->info_DT_MIPS_SYMTABNO = dyn.d_un.d_val; + } + } + if (ndx < maxndx) + break; + } + } +} + +int +set_dynamic (DSO *dso, GElf_Word tag, GElf_Addr value, int fatal) +{ + Elf_Data *data; + Elf_Scn *scn; + GElf_Dyn dyn; + int ndx, maxndx; + uint64_t mask = dso->info_set_mask; + + assert (dso->shdr[dso->dynamic].sh_type == SHT_DYNAMIC); + + scn = dso->scn[dso->dynamic]; + + data = elf_getdata (scn, NULL); + assert (elf_getdata (scn, data) == NULL); + + switch (tag) + { + case DT_CHECKSUM: + mask |= (1ULL << DT_CHECKSUM_BIT); break; + case DT_GNU_PRELINKED: + mask |= (1ULL << DT_GNU_PRELINKED_BIT); break; + case DT_VERDEF: + mask |= (1ULL << DT_VERDEF_BIT); break; + case DT_VERNEED: + mask |= (1ULL << DT_VERNEED_BIT); break; + case DT_VERSYM: + mask |= (1ULL << DT_VERSYM_BIT); break; + default: + if (tag < DT_NUM && tag < 50) + mask |= (1ULL << tag); + break; + } + + maxndx = data->d_size / dso->shdr[dso->dynamic].sh_entsize; + for (ndx = 0; ndx < maxndx; ndx++) + { + gelfx_getdyn (dso->elf, data, ndx, &dyn); + if (dyn.d_tag == DT_NULL) + break; + else if (dyn.d_tag == tag) + { + if (dyn.d_un.d_ptr != value) + { + dyn.d_un.d_ptr = value; + gelfx_update_dyn (dso->elf, data, ndx, &dyn); + elf_flagscn (scn, ELF_C_SET, ELF_F_DIRTY); + } + + return 0; + } + } + assert (ndx < maxndx); + + if (ndx + 1 < maxndx) + { + /* DT_NULL is not the last dynamic entry. */ + gelfx_update_dyn (dso->elf, data, ndx + 1, &dyn); + dyn.d_tag = tag; + dyn.d_un.d_ptr = value; + gelfx_update_dyn (dso->elf, data, ndx, &dyn); + dso->info_set_mask = mask; + elf_flagscn (scn, ELF_C_SET, ELF_F_DIRTY); + return 0; + } + + if (fatal) + error (0, 0, "%s: Not enough room to add .dynamic entry", + dso->filename); + return 1; +} + +int +check_dso (DSO *dso) +{ + int i, last = 1; + + /* FIXME: Several routines in prelink and in libelf-0.7.0 too + rely on sh_offset's monotonically increasing. */ + for (i = 2; i < dso->ehdr.e_shnum; ++i) + { + if (dso->shdr[last].sh_offset + + (dso->shdr[last].sh_type == SHT_NOBITS + ? 0 : dso->shdr[last].sh_size) > dso->shdr[i].sh_offset) + { + if (!dso->permissive + || RELOCATE_SCN (dso->shdr[last].sh_flags) + || RELOCATE_SCN (dso->shdr[i].sh_flags)) + { + error (0, 0, "%s: section file offsets not monotonically increasing", + dso->filename); + return 1; + } + } + if (!dso->permissive + || (dso->shdr[i].sh_type != SHT_NOBITS && dso->shdr[i].sh_size != 0)) + last = i; + } + return 0; +} + +DSO * +open_dso (const char *name) +{ + int fd; + + fd = wrap_open (name, O_RDONLY); + if (fd == -1) + { + error (0, errno, "cannot open \"%s\"", name); + return NULL; + } + return fdopen_dso (fd, name); +} + +/* WARNING: If prelink is ever multi-threaded, this will not work + Other alternatives are: + 1) make section_cmp nested function - trampolines + vs. non-exec stack needs to be resolved for it though + 2) make the variable __thread + 3) use locking around the qsort + */ +static DSO *section_cmp_dso; + +static int +section_cmp (const void *A, const void *B) +{ + int *a = (int *) A; + int *b = (int *) B; + DSO *dso = section_cmp_dso; + + if (dso->shdr[*a].sh_offset < dso->shdr[*b].sh_offset) + return -1; + if (dso->shdr[*a].sh_offset > dso->shdr[*b].sh_offset) + return 1; + if (*a < *b) + return -1; + return *a > *b; +} + +DSO * +fdopen_dso (int fd, const char *name) +{ + Elf *elf = NULL; + GElf_Ehdr ehdr; + GElf_Addr last_off; + int i, j, k, last, *sections, *invsections; + DSO *dso = NULL; +#if 0 + struct PLArch *plarch; + extern struct PLArch __start_pl_arch[], __stop_pl_arch[]; +#endif + + elf = elf_begin (fd, ELF_C_READ, NULL); + if (elf == NULL) + { + error (0, 0, "cannot open ELF file: %s (dso_readonly)", elf_errmsg (-1)); + goto error_out; + } + + if (elf_kind (elf) != ELF_K_ELF) + { + error (0, 0, "\"%s\" is not an ELF file", name); + goto error_out; + } + + if (gelf_getehdr (elf, &ehdr) == NULL) + { + error (0, 0, "cannot get the ELF header: %s", + elf_errmsg (-1)); + goto error_out; + } + + if (ehdr.e_type != ET_DYN && ehdr.e_type != ET_EXEC) + { + error (0, 0, "\"%s\" is not a shared library", name); + goto error_out; + } + + if (ehdr.e_shnum == 0) + { + GElf_Phdr phdr; + + /* Check for UPX compressed executables. */ + if (ehdr.e_type == ET_EXEC + && ehdr.e_phnum > 0 + && (gelf_getphdr (elf, 0, &phdr), phdr.p_type == PT_LOAD) + && phdr.p_filesz >= 256 + && phdr.p_filesz <= 4096 + && phdr.p_offset == 0 + && ehdr.e_phoff + ehdr.e_phnum * ehdr.e_phentsize < phdr.p_filesz) + { + char *buf = alloca (phdr.p_filesz); + size_t start = ehdr.e_phoff + ehdr.e_phnum * ehdr.e_phentsize; + + if (pread (fd, buf, phdr.p_filesz, 0) == phdr.p_filesz + && memmem (buf + start, phdr.p_filesz - start, + "UPX!", 4) != NULL) + { + error (0, 0, "\"%s\" is UPX compressed executable", name); + goto error_out; + } + } + error (0, 0, "\"%s\" has no section headers", name); + goto error_out; + } + + /* Allocate DSO structure. Leave place for additional 20 new section + headers. */ + dso = (DSO *) + malloc (sizeof(DSO) + (ehdr.e_shnum + 20) * sizeof(GElf_Shdr) + + (ehdr.e_phnum + 1) * sizeof(GElf_Phdr) + + (ehdr.e_shnum + 20) * sizeof(Elf_Scn *)); + if (!dso) + { + error (0, ENOMEM, "Could not open DSO"); + goto error_out; + } + + elf_flagelf (elf, ELF_C_SET, ELF_F_LAYOUT | ELF_F_PERMISSIVE); + + memset (dso, 0, sizeof(DSO)); + dso->elf = elf; + dso->ehdr = ehdr; + dso->phdr = (GElf_Phdr *) &dso->shdr[ehdr.e_shnum + 20]; + dso->scn = (Elf_Scn **) &dso->phdr[ehdr.e_phnum + 1]; + switch (ehdr.e_ident[EI_CLASS]) + { + case ELFCLASS32: + dso->mask = 0xffffffff; break; + case ELFCLASS64: + dso->mask = 0xffffffffffffffffULL; break; + } + for (i = 0; i < ehdr.e_phnum; ++i) + gelf_getphdr (elf, i, dso->phdr + i); + dso->fd = fd; + + for (i = 0, j = 0; i < ehdr.e_shnum; ++i) + { + dso->scn[i] = elf_getscn (elf, i); + gelfx_getshdr (elf, dso->scn[i], dso->shdr + i); + if ((dso->shdr[i].sh_flags & SHF_ALLOC) && dso->shdr[i].sh_type != SHT_NOBITS) + j = 1; + } + if (j == 0) + { + /* If all ALLOC sections are SHT_NOBITS, then this is a + stripped-to-file debuginfo. Skip it silently. */ + goto error_out; + } + + sections = (int *) alloca (dso->ehdr.e_shnum * sizeof (int) * 2); + sections[0] = 0; + for (i = 1, j = 1, k = dso->ehdr.e_shnum, last = -1; + i < dso->ehdr.e_shnum; ++i) + if (RELOCATE_SCN (dso->shdr[i].sh_flags)) + { + last = i; + sections[j++] = i; + } + else + sections[--k] = i; + assert (j == k); + + section_cmp_dso = dso; + qsort (sections + k, dso->ehdr.e_shnum - k, sizeof (*sections), section_cmp); + invsections = sections + dso->ehdr.e_shnum; + invsections[0] = 0; + for (i = 1, j = 0; i < ehdr.e_shnum; ++i) + { + if (i != sections[i]) + { + j = 1; + dso->scn[i] = elf_getscn (elf, sections[i]); + gelfx_getshdr (elf, dso->scn[i], dso->shdr + i); + } + invsections[sections[i]] = i; + } + +#if 0 + if (j) + { + dso->move = init_section_move (dso); + if (dso->move == NULL) + goto error_out; + memcpy (dso->move->old_to_new, invsections, dso->ehdr.e_shnum * sizeof (int)); + memcpy (dso->move->new_to_old, sections, dso->ehdr.e_shnum * sizeof (int)); + } +#endif + + last_off = 0; + for (i = 1; i < ehdr.e_shnum; ++i) + { + if (dso->shdr[i].sh_link >= ehdr.e_shnum) + { + error (0, 0, "%s: bogus sh_link value %d", name, + dso->shdr[i].sh_link); + goto error_out; + } + dso->shdr[i].sh_link = invsections[dso->shdr[i].sh_link]; + if (dso->shdr[i].sh_type == SHT_REL + || dso->shdr[i].sh_type == SHT_RELA + || (dso->shdr[i].sh_flags & SHF_INFO_LINK)) + { + if (dso->shdr[i].sh_info >= ehdr.e_shnum) + { + error (0, 0, "%s: bogus sh_info value %d", name, + dso->shdr[i].sh_info); + goto error_out; + } + dso->shdr[i].sh_info = invsections[dso->shdr[i].sh_info]; + } + + /* Some linkers mess up sh_offset fields for empty or nobits + sections. */ + if (RELOCATE_SCN (dso->shdr[i].sh_flags) + && (dso->shdr[i].sh_size == 0 + || dso->shdr[i].sh_type == SHT_NOBITS)) + { + for (j = i + 1; j < ehdr.e_shnum; ++j) + if (! RELOCATE_SCN (dso->shdr[j].sh_flags)) + break; + else if (dso->shdr[j].sh_size != 0 + && dso->shdr[j].sh_type != SHT_NOBITS) + break; + dso->shdr[i].sh_offset = (last_off + dso->shdr[i].sh_addralign - 1) + & ~(dso->shdr[i].sh_addralign - 1); + if (j < ehdr.e_shnum + && dso->shdr[i].sh_offset > dso->shdr[j].sh_offset) + { + GElf_Addr k; + + for (k = dso->shdr[i].sh_addralign - 1; k; ) + { + k >>= 1; + dso->shdr[i].sh_offset = (last_off + k) & ~k; + if (dso->shdr[i].sh_offset <= dso->shdr[j].sh_offset) + break; + } + } + last_off = dso->shdr[i].sh_offset; + } + else + last_off = dso->shdr[i].sh_offset + dso->shdr[i].sh_size; + } + dso->ehdr.e_shstrndx = invsections[dso->ehdr.e_shstrndx]; + +#if 0 + for (plarch = __start_pl_arch; plarch < __stop_pl_arch; plarch++) + if (plarch->class == ehdr.e_ident[EI_CLASS] + && (plarch->machine == ehdr.e_machine + || plarch->alternate_machine[0] == ehdr.e_machine + || plarch->alternate_machine[1] == ehdr.e_machine + || plarch->alternate_machine[2] == ehdr.e_machine)) + break; + + if (plarch == __stop_pl_arch || ehdr.e_machine == EM_NONE) + { + error (0, 0, "\"%s\"'s architecture is not supported", name); + goto error_out; + } + + dso->arch = plarch; +#else + dso->arch = NULL; +#endif + + dso->base = ~(GElf_Addr) 0; + dso->align = 0; + dso->end = 0; + for (i = 0; i < dso->ehdr.e_phnum; i++) + if (dso->phdr[i].p_type == PT_LOAD) + { + GElf_Addr base, end; + + if (dso->phdr[i].p_align > dso->align) + dso->align = dso->phdr[i].p_align; + base = dso->phdr[i].p_vaddr & ~(dso->phdr[i].p_align - 1); + end = dso->phdr[i].p_vaddr + dso->phdr[i].p_memsz; + if (base < dso->base) + dso->base = base; + if (end > dso->end) + dso->end = end; + } + + if (dso->base == ~(GElf_Addr) 0) + { + error (0, 0, "%s: cannot find loadable segment", name); + goto error_out; + } + + read_dynamic (dso); + + dso->filename = (const char *) strdup (name); + dso->soname = dso->filename; + if (dso->info[DT_STRTAB] && dso->info[DT_SONAME]) + { + const char *soname; + + soname = get_data (dso, dso->info[DT_STRTAB] + dso->info[DT_SONAME], + NULL, NULL); + if (soname && soname[0] != '\0') + dso->soname = (const char *) strdup (soname); + } + +#if 0 + if (dso->arch->machine == EM_ALPHA + || dso->arch->machine == EM_MIPS) + for (i = 1; i < ehdr.e_shnum; ++i) + { + if ((dso->shdr[i].sh_type == SHT_ALPHA_DEBUG + && dso->arch->machine == EM_ALPHA) + || (dso->shdr[i].sh_type == SHT_MIPS_DEBUG + && dso->arch->machine == EM_MIPS)) + { + const char *name + = strptr (dso, dso->ehdr.e_shstrndx, dso->shdr[i].sh_name); + if (! strcmp (name, ".mdebug")) + dso->mdebug_orig_offset = dso->shdr[i].sh_offset; + break; + } + } +#endif + + return dso; + +error_out: + if (dso) + { + free (dso->move); + if (dso->soname != dso->filename) + free ((char *) dso->soname); + free ((char *) dso->filename); + free (dso); + } + if (elf) + elf_end (elf); + if (fd != -1) + close (fd); + return NULL; +} + +#if 0 + +static int +adjust_symtab_section_indices (DSO *dso, int n, int old_shnum, int *old_to_new) +{ + Elf_Data *data = NULL; + Elf_Scn *scn = dso->scn[n]; + GElf_Sym sym; + int changed = 0, ndx, maxndx; + + while ((data = elf_getdata (scn, data)) != NULL) + { + maxndx = data->d_size / dso->shdr[n].sh_entsize; + for (ndx = 0; ndx < maxndx; ++ndx) + { + gelfx_getsym (dso->elf, data, ndx, &sym); + if (sym.st_shndx > SHN_UNDEF && sym.st_shndx < SHN_LORESERVE) + { + if (sym.st_shndx >= old_shnum + || old_to_new[sym.st_shndx] == -1) + { + if (! sym.st_size && + sym.st_info == ELF32_ST_INFO (STB_LOCAL, STT_SECTION)) + { + sym.st_value = 0; + sym.st_shndx = SHN_UNDEF; + gelfx_update_sym (dso->elf, data, ndx, &sym); + changed = 1; + continue; + } + else + { + if (sym.st_shndx >= old_shnum) + { + error (0, 0, "%s: Symbol section index outside of section numbers", + dso->filename); + return 1; + } + error (0, 0, "%s: Section symbol points into has been removed", + dso->filename); + return 1; + } + } + if (old_to_new[sym.st_shndx] != sym.st_shndx) + { + changed = 1; + sym.st_shndx = old_to_new[sym.st_shndx]; + gelfx_update_sym (dso->elf, data, ndx, &sym); + } + } + } + } + + if (changed) + elf_flagscn (scn, ELF_C_SET, ELF_F_DIRTY); + + return 0; +} + +static int +set_stt_section_values (DSO *dso, int n) +{ + Elf_Data *data; + Elf_Scn *scn = dso->scn[n]; + GElf_Sym sym; + int ndx, maxndx, sec; + char seen[dso->ehdr.e_shnum]; + + memset (seen, 0, dso->ehdr.e_shnum); + data = elf_getdata (scn, NULL); + assert (data != NULL); + assert (elf_getdata (scn, data) == NULL); + assert (data->d_off == 0); + + maxndx = data->d_size / dso->shdr[n].sh_entsize; + gelfx_getsym (dso->elf, data, 0, &sym); + if (sym.st_info != ELF32_ST_INFO (STB_LOCAL, STT_NOTYPE) + || sym.st_size != 0 || sym.st_other != 0 + || sym.st_value != 0 || sym.st_shndx != SHN_UNDEF + || sym.st_name != 0) + return 0; + + for (ndx = 1; ndx < maxndx; ++ndx) + { + gelfx_getsym (dso->elf, data, ndx, &sym); + if (sym.st_info == ELF32_ST_INFO (STB_LOCAL, STT_SECTION) + && sym.st_size == 0 && sym.st_other == 0 + && sym.st_name == 0) + { + if (sym.st_shndx > SHN_UNDEF && sym.st_shndx < SHN_LORESERVE) + { + seen[sym.st_shndx] = 1; + sym.st_value = dso->shdr[sym.st_shndx].sh_addr; + gelfx_update_sym (dso->elf, data, ndx, &sym); + } + } + else + break; + } + + for (ndx = 1, sec = 1; ndx < maxndx; ++ndx) + { + gelfx_getsym (dso->elf, data, ndx, &sym); + if (sym.st_info == ELF32_ST_INFO (STB_LOCAL, STT_SECTION) + && sym.st_size == 0 && sym.st_other == 0 + && sym.st_name == 0) + { + if (sym.st_shndx == SHN_UNDEF) + { + while (sec < dso->ehdr.e_shnum && seen[sec]) + ++sec; + + if (sec >= dso->ehdr.e_shnum) + sym.st_value = 0; + else + sym.st_value = dso->shdr[sec].sh_addr; + sym.st_shndx = sec++; + gelfx_update_sym (dso->elf, data, ndx, &sym); + } + } + else + break; + } + + return 0; +} + +struct section_move * +init_section_move (DSO *dso) +{ + struct section_move *move; + int i; + + move = malloc (sizeof (struct section_move) + + (dso->ehdr.e_shnum * 2 + 20) * sizeof (int)); + if (move == NULL) + { + error (0, ENOMEM, "%s: Could not move sections", dso->filename); + return move; + } + move->old_shnum = dso->ehdr.e_shnum; + move->new_shnum = dso->ehdr.e_shnum; + move->old_to_new = (int *)(move + 1); + move->new_to_old = move->old_to_new + move->new_shnum; + for (i = 0; i < move->new_shnum; i++) + { + move->old_to_new[i] = i; + move->new_to_old[i] = i; + } + return move; +} + +void +add_section (struct section_move *move, int sec) +{ + int i; + + assert (move->new_shnum < move->old_shnum + 20); + assert (sec <= move->new_shnum); + + memmove (move->new_to_old + sec + 1, move->new_to_old + sec, + (move->new_shnum - sec) * sizeof (int)); + ++move->new_shnum; + move->new_to_old[sec] = -1; + for (i = 1; i < move->old_shnum; i++) + if (move->old_to_new[i] >= sec) + ++move->old_to_new[i]; +} + +void +remove_section (struct section_move *move, int sec) +{ + int i; + + assert (sec < move->new_shnum); + + memmove (move->new_to_old + sec, move->new_to_old + sec + 1, + (move->new_shnum - sec - 1) * sizeof (int)); + --move->new_shnum; + for (i = 1; i < move->old_shnum; i++) + if (move->old_to_new[i] == sec) + move->old_to_new[i] = -1; + else if (move->old_to_new[i] > sec) + --move->old_to_new[i]; +} + +int +reopen_dso (DSO *dso, struct section_move *move, const char *temp_base) +{ + char filename[strlen (temp_base ? temp_base : dso->filename) + + sizeof ("/dev/shm/.#prelink#.XXXXXX")]; + int adddel = 0; + int free_move = 0; + Elf *elf = NULL; + GElf_Ehdr ehdr; + char *e_ident; + int fd, i, j; + + if (move == NULL) + { + move = init_section_move (dso); + if (move == NULL) + return 1; + free_move = 1; + } + else + assert (dso->ehdr.e_shnum == move->old_shnum); + + if (temp_base == NULL) + temp_base = dso->filename; + sprintf (filename, "%s.#prelink#.XXXXXX", temp_base); + + fd = wrap_mkstemp (filename); + if (fd == -1) + { + strcpy (filename, "/tmp/#prelink#.XXXXXX"); + fd = wrap_mkstemp (filename); + if (fd == -1) + { + strcpy (filename, "/dev/shm/#prelink#.XXXXXX"); + fd = wrap_mkstemp (filename); + } + if (fd == -1) + { + error (0, errno, "Could not create temporary file %s", filename); + goto error_out; + } + } + + elf = elf_begin (fd, ELF_C_WRITE, NULL); + if (elf == NULL) + { + error (0, 0, "cannot open ELF file: %s (elf_begin failed, dso_readonly)", elf_errmsg (-1)); + goto error_out; + + } + + /* Some gelf_newehdr implementations don't return the resulting + ElfNN_Ehdr, so we have to do it the hard way instead of: + e_ident = (char *) gelf_newehdr (elf, gelf_getclass (dso->elf)); */ + switch (gelf_getclass (dso->elf)) + { + case ELFCLASS32: + e_ident = (char *) elf32_newehdr (elf); + break; + case ELFCLASS64: + e_ident = (char *) elf64_newehdr (elf); + break; + default: + e_ident = NULL; + break; + } + + if (e_ident == NULL + /* This is here just for the gelfx wrapper, so that gelf_update_ehdr + already has the correct ELF class. */ + || memcpy (e_ident, dso->ehdr.e_ident, EI_NIDENT) == NULL + || gelf_update_ehdr (elf, &dso->ehdr) == 0 + || gelf_newphdr (elf, dso->ehdr.e_phnum) == 0) + { + error (0, 0, "Could not create new ELF headers"); + goto error_out; + } + ehdr = dso->ehdr; + elf_flagelf (elf, ELF_C_SET, ELF_F_LAYOUT | ELF_F_PERMISSIVE); + for (i = 0; i < ehdr.e_phnum; ++i) + gelf_update_phdr (elf, i, dso->phdr + i); + + for (i = 1; i < move->new_shnum; ++i) + { + Elf_Scn *scn; + Elf_Data data, *data1, *data2; + + if (move->new_to_old[i] == -1) + { + scn = elf_newscn (elf); + elf_newdata (scn); + } + else + { + j = move->new_to_old[i]; + scn = elf_newscn (elf); + gelfx_update_shdr (elf, scn, &dso->shdr[j]); + if (dso->shdr[j].sh_type == SHT_NOBITS) + { + data1 = elf_getdata (dso->scn[j], NULL); + data2 = elf_newdata (scn); + memcpy (data2, data1, sizeof (*data1)); + } + else + { + data.d_type = ELF_T_NUM; + data1 = NULL; + while ((data1 = elf_getdata (dso->scn[j], data1)) + != NULL) + { + if (data.d_type == ELF_T_NUM) + data = *data1; + else if (data.d_type != data1->d_type + || data.d_version != data1->d_version) + abort (); + else + { + if (data1->d_off < data.d_off) + { + data.d_size += data.d_off - data1->d_off; + data.d_off = data1->d_off; + } + if (data1->d_off + data1->d_size + > data.d_off + data.d_size) + data.d_size = data1->d_off + data1->d_size + - data.d_off; + if (data1->d_align > data.d_align) + data.d_align = data1->d_align; + } + } + if (data.d_type == ELF_T_NUM) + { + assert (dso->shdr[j].sh_size == 0); + continue; + } + if (data.d_size != 0) + { + data.d_buf = calloc (1, data.d_size); + if (data.d_buf == NULL) + { + error (0, ENOMEM, "%s: Could not copy section", + dso->filename); + goto error_out; + } + } + else + data.d_buf = NULL; + data1 = NULL; + while ((data1 = elf_getdata (dso->scn[j], data1)) + != NULL) + memcpy (data.d_buf + data1->d_off - data.d_off, data1->d_buf, + data1->d_size); + data2 = elf_newdata (scn); + memcpy (data2, &data, sizeof (data)); + } + } + } + + ehdr.e_shnum = move->new_shnum; + dso->temp_filename = strdup (filename); + if (dso->temp_filename == NULL) + { + error (0, ENOMEM, "%s: Could not save temporary filename", dso->filename); + goto error_out; + } + dso->elfro = dso->elf; + dso->elf = elf; + dso->fdro = dso->fd; + dso->fd = fd; + dso->ehdr = ehdr; + dso->lastscn = 0; + elf = NULL; + fd = -1; + for (i = 1; i < move->old_shnum; i++) + if (move->old_to_new[i] != i) + { + adddel = 1; + break; + } + if (! adddel) + for (i = 1; i < move->new_shnum; i++) + if (move->new_to_old[i] != i) + { + adddel = 1; + break; + } + + for (i = 1; i < move->new_shnum; i++) + { + dso->scn[i] = elf_getscn (dso->elf, i); + gelfx_getshdr (dso->elf, dso->scn[i], dso->shdr + i); + if (move->new_to_old[i] == -1) + continue; + if (dso->move + && (dso->shdr[i].sh_type == SHT_SYMTAB + || dso->shdr[i].sh_type == SHT_DYNSYM)) + { + if (adjust_symtab_section_indices (dso, i, dso->move->old_shnum, + dso->move->old_to_new)) + goto error_out; + } + if (adddel) + { + if (dso->shdr[i].sh_link) + { + if (dso->shdr[i].sh_link >= move->old_shnum) + { + error (0, 0, "%s: bogus sh_link value %d", dso->filename, + dso->shdr[i].sh_link); + goto error_out; + } + if (move->old_to_new[dso->shdr[i].sh_link] == -1) + { + error (0, 0, "Section sh_link points to has been removed"); + goto error_out; + } + dso->shdr[i].sh_link = move->old_to_new[dso->shdr[i].sh_link]; + } + /* Only some section types use sh_info for section index. */ + if (dso->shdr[i].sh_info + && (dso->shdr[i].sh_type == SHT_REL + || dso->shdr[i].sh_type == SHT_RELA + || (dso->shdr[i].sh_flags & SHF_INFO_LINK))) + { + if (dso->shdr[i].sh_info >= move->old_shnum) + { + error (0, 0, "%s: bogus sh_info value %d", dso->filename, + dso->shdr[i].sh_info); + goto error_out; + } + if (move->old_to_new[dso->shdr[i].sh_info] == -1) + { + error (0, 0, "Section sh_info points to has been removed"); + goto error_out; + } + dso->shdr[i].sh_info = move->old_to_new[dso->shdr[i].sh_info]; + } + if (dso->shdr[i].sh_type == SHT_SYMTAB + || dso->shdr[i].sh_type == SHT_DYNSYM) + { + if (adjust_symtab_section_indices (dso, i, move->old_shnum, + move->old_to_new)) + goto error_out; + } + } + } + + free (dso->move); + dso->move = NULL; + + dso->ehdr.e_shstrndx = move->old_to_new[dso->ehdr.e_shstrndx]; + gelf_update_ehdr (dso->elf, &dso->ehdr); + + read_dynamic (dso); + + /* If shoff does not point after last section, we need to adjust the sections + after it if we added or removed some sections. */ + if (move->old_shnum != move->new_shnum + && adjust_dso_nonalloc (dso, 0, dso->ehdr.e_shoff + 1, + ((long) move->new_shnum - (long) move->old_shnum) + * gelf_fsize (dso->elf, ELF_T_SHDR, 1, + EV_CURRENT))) + goto error_out; + + if (free_move) + free (move); + return 0; + +error_out: + if (free_move) + free (move); + if (elf) + elf_end (elf); + if (fd != -1) + { + wrap_unlink (filename); + close (fd); + } + return 1; +} + +/* Return true if the value of symbol SYM, which belongs to DSO, + should be treated as an address within the DSO, and should + therefore track DSO's relocations. */ + +int +adjust_symbol_p (DSO *dso, GElf_Sym *sym) +{ + if (sym->st_shndx == SHN_ABS + && sym->st_value != 0 + && (GELF_ST_TYPE (sym->st_info) <= STT_FUNC + || (dso->ehdr.e_machine == EM_ARM + && GELF_ST_TYPE (sym->st_info) == STT_ARM_TFUNC))) + /* This is problematic. How do we find out if + we should relocate this? Assume we should. */ + return 1; + + /* If a MIPS object does not define a symbol, but has a lazy binding + stub for it, st_value will point to that stub. Note that unlike + other targets, these stub addresses never participate in symbol + lookup; the stubs can only be called by the object that defines them. + st_values are only used in this way so that the associated GOT entry + can store a Quickstart value without losing the original stub + address. */ + if (dso->ehdr.e_machine == EM_MIPS + && sym->st_shndx == SHN_UNDEF + && sym->st_value != 0) + return 1; + + return (sym->st_shndx > SHN_UNDEF + && sym->st_shndx < dso->ehdr.e_shnum + && ELF32_ST_TYPE (sym->st_info) != STT_TLS + && RELOCATE_SCN (dso->shdr[sym->st_shndx].sh_flags)); +} + +static int +adjust_symtab (DSO *dso, int n, GElf_Addr start, GElf_Addr adjust) +{ + Elf_Data *data = NULL; + Elf_Scn *scn = dso->scn[n]; + GElf_Sym sym; + int ndx, maxndx; + + while ((data = elf_getdata (scn, data)) != NULL) + { + maxndx = data->d_size / dso->shdr[n].sh_entsize; + for (ndx = 0; ndx < maxndx; ++ndx) + { + gelfx_getsym (dso->elf, data, ndx, &sym); + if (adjust_symbol_p (dso, &sym) && sym.st_value >= start) + { + sym.st_value += adjust; + gelfx_update_sym (dso->elf, data, ndx, &sym); + } + } + } + + elf_flagscn (scn, ELF_C_SET, ELF_F_DIRTY); + return 0; +} + +#endif + +int +dso_is_rdwr (DSO *dso) +{ + return dso->elfro != NULL; +} + +#if 0 + +GElf_Addr +adjust_old_to_new (DSO *dso, GElf_Addr addr) +{ + int i; + + if (dso->adjust == NULL) + return addr; /* Fast path. */ + + for (i = 0; i < dso->nadjust; i++) + if (addr >= dso->adjust[i].start) + { + addr += dso->adjust[i].adjust; + assert (dso->ehdr.e_ident[EI_CLASS] != ELFCLASS32 + || addr == (Elf32_Addr) addr); + return addr; + } + + return addr; +} + +GElf_Addr +adjust_new_to_old (DSO *dso, GElf_Addr addr) +{ + int i; + + if (dso->adjust == NULL) + return addr; /* Fast path. */ + + for (i = 0; i < dso->nadjust; i++) + if (addr >= dso->adjust[i].start + dso->adjust[i].adjust) + { + addr -= dso->adjust[i].adjust; + assert (dso->ehdr.e_ident[EI_CLASS] != ELFCLASS32 + || addr == (Elf32_Addr) addr); + return addr; + } + + return addr; +} + +static int +adjust_dynamic (DSO *dso, int n, GElf_Addr start, GElf_Addr adjust) +{ + Elf_Data *data = NULL; + Elf_Scn *scn = dso->scn[n]; + GElf_Dyn dyn; + int ndx, maxndx; + + while ((data = elf_getdata (scn, data)) != NULL) + { + maxndx = data->d_size / dso->shdr[n].sh_entsize; + for (ndx = 0; ndx < maxndx; ++ndx) + { + gelfx_getdyn (dso->elf, data, ndx, &dyn); + if (dso->arch->adjust_dyn (dso, n, &dyn, start, adjust) == 0) + switch (dyn.d_tag) + { + case DT_REL: + case DT_RELA: + /* On some arches DT_REL* may be 0 indicating no relocations + (if DT_REL*SZ is also 0). Don't adjust it in that case. */ + if (dyn.d_un.d_ptr && dyn.d_un.d_ptr >= start) + { + dyn.d_un.d_ptr += adjust; + gelfx_update_dyn (dso->elf, data, ndx, &dyn); + } + break; + default: + if (dyn.d_tag < DT_ADDRRNGLO || dyn.d_tag > DT_ADDRRNGHI) + break; + /* FALLTHROUGH */ + case DT_INIT: + case DT_FINI: + case DT_HASH: + case DT_STRTAB: + case DT_SYMTAB: + case DT_JMPREL: + case DT_INIT_ARRAY: + case DT_FINI_ARRAY: + case DT_PREINIT_ARRAY: + case DT_VERDEF: + case DT_VERNEED: + case DT_VERSYM: + case DT_PLTGOT: + if (dyn.d_un.d_ptr >= start) + { + dyn.d_un.d_ptr += adjust; + gelfx_update_dyn (dso->elf, data, ndx, &dyn); + } + break; + } + else + gelfx_update_dyn (dso->elf, data, ndx, &dyn); + } + } + + elf_flagscn (scn, ELF_C_SET, ELF_F_DIRTY); + + /* Update the cached dynamic info as well. */ + read_dynamic (dso); + return 0; +} + +#endif + +int +addr_to_sec (DSO *dso, GElf_Addr addr) +{ + GElf_Shdr *shdr; + int i; + + shdr = &dso->shdr[dso->lastscn]; + for (i = -1; i < dso->ehdr.e_shnum; shdr = &dso->shdr[++i]) + if (RELOCATE_SCN (shdr->sh_flags) + && shdr->sh_addr <= addr && shdr->sh_addr + shdr->sh_size > addr + && (shdr->sh_type != SHT_NOBITS || (shdr->sh_flags & SHF_TLS) == 0)) + { + if (i != -1) + dso->lastscn = i; + return dso->lastscn; + } + + return -1; +} + +#if 0 + +static int +adjust_rel (DSO *dso, int n, GElf_Addr start, GElf_Addr adjust) +{ + Elf_Data *data = NULL; + Elf_Scn *scn = dso->scn[n]; + GElf_Rel rel; + int sec, ndx, maxndx; + + while ((data = elf_getdata (scn, data)) != NULL) + { + maxndx = data->d_size / dso->shdr[n].sh_entsize; + for (ndx = 0; ndx < maxndx; ++ndx) + { + gelfx_getrel (dso->elf, data, ndx, &rel); + sec = addr_to_sec (dso, rel.r_offset); + if (sec == -1) + continue; + + dso->arch->adjust_rel (dso, &rel, start, adjust); + addr_adjust (rel.r_offset, start, adjust); + gelfx_update_rel (dso->elf, data, ndx, &rel); + } + } + + elf_flagscn (scn, ELF_C_SET, ELF_F_DIRTY); + return 0; +} + +static int +adjust_rela (DSO *dso, int n, GElf_Addr start, GElf_Addr adjust) +{ + Elf_Data *data = NULL; + Elf_Scn *scn = dso->scn[n]; + GElf_Rela rela; + int sec, ndx, maxndx; + + while ((data = elf_getdata (scn, data)) != NULL) + { + maxndx = data->d_size / dso->shdr[n].sh_entsize; + for (ndx = 0; ndx < maxndx; ++ndx) + { + gelfx_getrela (dso->elf, data, ndx, &rela); + sec = addr_to_sec (dso, rela.r_offset); + if (sec == -1) + continue; + + dso->arch->adjust_rela (dso, &rela, start, adjust); + addr_adjust (rela.r_offset, start, adjust); + gelfx_update_rela (dso->elf, data, ndx, &rela); + } + } + + elf_flagscn (scn, ELF_C_SET, ELF_F_DIRTY); + return 0; +} + +int +adjust_nonalloc (DSO *dso, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int first, + GElf_Addr start, GElf_Addr adjust) +{ + int i; + + for (i = 1; i < ehdr->e_shnum; i++) + { + if (RELOCATE_SCN (shdr[i].sh_flags) || shdr[i].sh_type == SHT_NULL) + continue; + + if ((shdr[i].sh_offset > start + || (shdr[i].sh_offset == start && i >= first)) + && (adjust & (shdr[i].sh_addralign - 1))) + adjust = (adjust + shdr[i].sh_addralign - 1) + & ~(shdr[i].sh_addralign - 1); + } + + if (ehdr->e_shoff >= start) + { + GElf_Addr shdralign = gelf_fsize (dso->elf, ELF_T_ADDR, 1, EV_CURRENT); + + if (adjust & (shdralign - 1)) + adjust = (adjust + shdralign - 1) & ~(shdralign - 1); + ehdr->e_shoff += adjust; + } + + for (i = 1; i < ehdr->e_shnum; i++) + { + if (RELOCATE_SCN (shdr[i].sh_flags) || shdr[i].sh_type == SHT_NULL) + continue; + + if (shdr[i].sh_offset > start + || (shdr[i].sh_offset == start && i >= first)) + shdr[i].sh_offset += adjust; + } + return 0; +} + +int +adjust_dso_nonalloc (DSO *dso, int first, GElf_Addr start, GElf_Addr adjust) +{ + return adjust_nonalloc (dso, &dso->ehdr, dso->shdr, first, start, adjust); +} + +/* Add ADJUST to all addresses above START. */ +int +adjust_dso (DSO *dso, GElf_Addr start, GElf_Addr adjust) +{ + int i; + + if (dso->arch->arch_adjust + && dso->arch->arch_adjust (dso, start, adjust)) + return 1; + + if (dso->ehdr.e_entry >= start) + { + dso->ehdr.e_entry += adjust; + gelf_update_ehdr (dso->elf, &dso->ehdr); + elf_flagehdr (dso->elf, ELF_C_SET, ELF_F_DIRTY); + } + + for (i = 0; i < dso->ehdr.e_phnum; i++) + { + /* Leave STACK segment alone, it has + p_vaddr == p_paddr == p_offset == p_filesz == p_memsz == 0. */ + if (dso->phdr[i].p_type == PT_GNU_STACK) + continue; + if (! start) + { + dso->phdr[i].p_vaddr += adjust; + dso->phdr[i].p_paddr += adjust; + } + else if (start <= dso->phdr[i].p_vaddr) + { + dso->phdr[i].p_vaddr += adjust; + dso->phdr[i].p_paddr += adjust; + dso->phdr[i].p_offset += adjust; + } + else if (start < dso->phdr[i].p_vaddr + dso->phdr[i].p_filesz) + { + dso->phdr[i].p_filesz += adjust; + dso->phdr[i].p_memsz += adjust; + } + else if (start < dso->phdr[i].p_vaddr + dso->phdr[i].p_memsz) + dso->phdr[i].p_memsz += adjust; + else + continue; + if (dso->phdr[i].p_type == PT_LOAD + && (dso->phdr[i].p_vaddr - dso->phdr[i].p_offset) + % dso->phdr[i].p_align) + { + error (0, 0, "%s: PT_LOAD %08llx %08llx 0x%x would be not properly aligned", + dso->filename, (long long) dso->phdr[i].p_offset, + (long long) dso->phdr[i].p_vaddr, (int) dso->phdr[i].p_align); + return 1; + } + gelf_update_phdr (dso->elf, i, dso->phdr + i); + } + elf_flagphdr (dso->elf, ELF_C_SET, ELF_F_DIRTY); + + for (i = 1; i < dso->ehdr.e_shnum; i++) + { + const char *name; + + if (dso->arch->adjust_section) + { + int ret = dso->arch->adjust_section (dso, i, start, adjust); + + if (ret == 1) + return 1; + else if (ret) + continue; + } + switch (dso->shdr[i].sh_type) + { + case SHT_PROGBITS: + name = strptr (dso, dso->ehdr.e_shstrndx, dso->shdr[i].sh_name); + if (strcmp (name, ".stab") == 0 + && adjust_stabs (dso, i, start, adjust)) + return 1; + if (strcmp (name, ".debug_info") == 0 + && adjust_dwarf2 (dso, i, start, adjust)) + return 1; + break; + case SHT_HASH: + case SHT_GNU_HASH: + case SHT_NOBITS: + case SHT_STRTAB: + break; + case SHT_SYMTAB: + case SHT_DYNSYM: + if (adjust_symtab (dso, i, start, adjust)) + return 1; + break; + case SHT_DYNAMIC: + if (adjust_dynamic (dso, i, start, adjust)) + return 1; + break; + case SHT_REL: + /* Don't adjust reloc sections for debug info. */ + if (dso->shdr[i].sh_flags & SHF_ALLOC) + if (adjust_rel (dso, i, start, adjust)) + return 1; + break; + case SHT_RELA: + if (dso->shdr[i].sh_flags & SHF_ALLOC) + if (adjust_rela (dso, i, start, adjust)) + return 1; + break; + } + if ((dso->arch->machine == EM_ALPHA + && dso->shdr[i].sh_type == SHT_ALPHA_DEBUG) + || (dso->arch->machine == EM_MIPS + && dso->shdr[i].sh_type == SHT_MIPS_DEBUG)) + if (adjust_mdebug (dso, i, start, adjust)) + return 1; + } + + for (i = 0; i < dso->ehdr.e_shnum; i++) + { + if (RELOCATE_SCN (dso->shdr[i].sh_flags)) + { + if (dso->shdr[i].sh_addr >= start) + { + Elf_Scn *scn = dso->scn[i]; + + dso->shdr[i].sh_addr += adjust; + if (start) + dso->shdr[i].sh_offset += adjust; + gelfx_update_shdr (dso->elf, scn, dso->shdr + i); + elf_flagshdr (scn, ELF_C_SET, ELF_F_DIRTY); + } + } + } + + addr_adjust (dso->base, start, adjust); + addr_adjust (dso->end, start, adjust); + + if (start) + { + start = adjust_new_to_old (dso, start); + for (i = 0; i < dso->nadjust; i++) + if (start < dso->adjust[i].start) + dso->adjust[i].adjust += adjust; + else + break; + if (i < dso->nadjust && start == dso->adjust[i].start) + dso->adjust[i].adjust += adjust; + else + { + dso->adjust = + realloc (dso->adjust, (dso->nadjust + 1) * sizeof (*dso->adjust)); + if (dso->adjust == NULL) + { + error (0, ENOMEM, "Cannot record the list of adjustements being made"); + return 1; + } + memmove (dso->adjust + i + 1, dso->adjust + i, dso->nadjust - i); + dso->adjust[i].start = start; + dso->adjust[i].adjust = adjust; + ++dso->nadjust; + } + } + + return start ? adjust_dso_nonalloc (dso, 0, 0, adjust) : 0; +} + +int +recompute_nonalloc_offsets (DSO *dso) +{ + int i, first_nonalloc, sec_before_shoff = 0; + GElf_Addr last_offset = 0; + GElf_Addr shdralign = gelf_fsize (dso->elf, ELF_T_ADDR, 1, EV_CURRENT); + GElf_Addr shdrsize = gelf_fsize (dso->elf, ELF_T_SHDR, 1, EV_CURRENT) + * dso->ehdr.e_shnum; + + for (i = 1; i < dso->ehdr.e_shnum; ++i) + if (RELOCATE_SCN (dso->shdr[i].sh_flags)) + { + if (dso->shdr[i].sh_type == SHT_NOBITS) + last_offset = dso->shdr[i].sh_offset; + else + last_offset = dso->shdr[i].sh_offset + dso->shdr[i].sh_size; + } + else + break; + + first_nonalloc = i; + if (dso->ehdr.e_shoff < dso->shdr[i].sh_offset) + { + dso->ehdr.e_shoff = (last_offset + shdralign - 1) & ~(shdralign - 1); + last_offset = dso->ehdr.e_shoff + shdrsize; + } + else + for (; i < dso->ehdr.e_shnum; ++i) + if (dso->shdr[i].sh_offset < dso->ehdr.e_shoff + && (i == dso->ehdr.e_shnum - 1 + || dso->shdr[i + 1].sh_offset > dso->ehdr.e_shoff)) + { + sec_before_shoff = i; + break; + } + + for (i = first_nonalloc; i < dso->ehdr.e_shnum; ++i) + { + assert (!RELOCATE_SCN (dso->shdr[i].sh_flags)); + assert (dso->shdr[i].sh_type != SHT_NOBITS); + dso->shdr[i].sh_offset = (last_offset + dso->shdr[i].sh_addralign - 1) + & ~(dso->shdr[i].sh_addralign - 1); + last_offset = dso->shdr[i].sh_offset + dso->shdr[i].sh_size; + if (i == sec_before_shoff) + { + dso->ehdr.e_shoff = (last_offset + shdralign - 1) & ~(shdralign - 1); + last_offset = dso->ehdr.e_shoff + shdrsize; + } + } + + return 0; +} + +int +strtabfind (DSO *dso, int strndx, const char *name) +{ + Elf_Scn *scn; + Elf_Data *data; + const char *p, *q, *r; + size_t len = strlen (name); + + if (dso->shdr[strndx].sh_type != SHT_STRTAB) + return 0; + + scn = dso->scn[strndx]; + data = elf_getdata (scn, NULL); + assert (elf_getdata (scn, data) == NULL); + assert (data->d_off == 0); + assert (data->d_size == dso->shdr[strndx].sh_size); + q = data->d_buf + data->d_size; + for (p = data->d_buf; p < q; p = r + 1) + { + r = strchr (p, '\0'); + if (r - p >= len && memcmp (r - len, name, len) == 0) + return (r - (const char *) data->d_buf) - len; + } + + return 0; +} + +int +shstrtabadd (DSO *dso, const char *name) +{ + Elf_Scn *scn; + Elf_Data *data; + GElf_Addr adjust; + const char *p, *q, *r; + size_t len = strlen (name), align; + int ret; + + scn = dso->scn[dso->ehdr.e_shstrndx]; + data = elf_getdata (scn, NULL); + assert (elf_getdata (scn, data) == NULL); + assert (data->d_off == 0); + assert (data->d_size == dso->shdr[dso->ehdr.e_shstrndx].sh_size); + q = data->d_buf + data->d_size; + for (p = data->d_buf; p < q; p = r + 1) + { + r = strchr (p, '\0'); + if (r - p >= len && memcmp (r - len, name, len) == 0) + return (r - (const char *) data->d_buf) - len; + } + + data->d_buf = realloc (data->d_buf, data->d_size + len + 1); + if (data->d_buf == NULL) + { + error (0, ENOMEM, "Cannot add new section name %s", name); + return 0; + } + + memcpy (data->d_buf + data->d_size, name, len + 1); + ret = data->d_size; + data->d_size += len + 1; + align = gelf_fsize (dso->elf, ELF_T_ADDR, 1, EV_CURRENT); + adjust = (len + 1 + align - 1) & ~(align - 1); + if (adjust_dso_nonalloc (dso, 0, + dso->shdr[dso->ehdr.e_shstrndx].sh_offset + + dso->shdr[dso->ehdr.e_shstrndx].sh_size, + adjust)) + return 0; + dso->shdr[dso->ehdr.e_shstrndx].sh_size += len + 1; + return ret; +} + +int +relocate_dso (DSO *dso, GElf_Addr base) +{ + /* Check if it is already relocated. */ + if (dso->base == base) + return 0; + + if (! dso_is_rdwr (dso)) + { + if (reopen_dso (dso, NULL, NULL)) + return 1; + } + + return adjust_dso (dso, 0, base - dso->base); +} + +#endif + +static int +close_dso_1 (DSO *dso) +{ + if (dso_is_rdwr (dso)) + { + int i; + + for (i = 1; i < dso->ehdr.e_shnum; ++i) + { + Elf_Scn *scn = dso->scn[i]; + Elf_Data *data = NULL; + + while ((data = elf_getdata (scn, data)) != NULL) + { + free (data->d_buf); + data->d_buf = NULL; + } + } + } + + elf_end (dso->elf); + close (dso->fd); + if (dso->elfro) + { + elf_end (dso->elfro); + close (dso->fdro); + } + if (dso->filename != dso->soname) + free ((char *) dso->soname); + free ((char *) dso->filename); + free ((char *) dso->temp_filename); + free (dso->move); + free (dso->adjust); + free (dso->undo.d_buf); + free (dso); + return 0; +} + +int +close_dso (DSO *dso) +{ + int rdwr = dso_is_rdwr (dso); + + if (rdwr && dso->temp_filename != NULL) + wrap_unlink (dso->temp_filename); + close_dso_1 (dso); + return 0; +} + +#if 0 + +int +prepare_write_dso (DSO *dso) +{ + int i; + + if (check_dso (dso) + || (dso->mdebug_orig_offset && finalize_mdebug (dso))) + return 1; + + gelf_update_ehdr (dso->elf, &dso->ehdr); + for (i = 0; i < dso->ehdr.e_phnum; ++i) + gelf_update_phdr (dso->elf, i, dso->phdr + i); + for (i = 0; i < dso->ehdr.e_shnum; ++i) + { + gelfx_update_shdr (dso->elf, dso->scn[i], dso->shdr + i); + if (dso->shdr[i].sh_type == SHT_SYMTAB + || dso->shdr[i].sh_type == SHT_DYNSYM) + set_stt_section_values (dso, i); + } + return 0; +} + +int +write_dso (DSO *dso) +{ + if (prepare_write_dso (dso)) + return 1; + + if (! dso->permissive && ELF_F_PERMISSIVE) + elf_flagelf (dso->elf, ELF_C_CLR, ELF_F_PERMISSIVE); + + if (elf_update (dso->elf, ELF_C_WRITE) == -1) + return 2; + return 0; +} + +int +set_security_context (DSO *dso, const char *temp_name, const char *name) +{ +#ifdef USE_SELINUX + static int selinux_enabled = -1; + if (selinux_enabled == -1) + selinux_enabled = is_selinux_enabled (); + if (selinux_enabled > 0) + { + security_context_t scontext; + if (getfilecon (name, &scontext) < 0) + { + /* If the filesystem doesn't support extended attributes, + the original had no special security context and the + target cannot have one either. */ + if (errno == EOPNOTSUPP) + return 0; + + error (0, errno, "Could not get security context for %s", + name); + return 1; + } + if (setfilecon (temp_name, scontext) < 0) + { + error (0, errno, "Could not set security context for %s", + name); + freecon (scontext); + return 1; + } + freecon (scontext); + } +#endif + return 0; +} + +int +update_dso (DSO *dso, const char *orig_name) +{ + int rdwr = dso_is_rdwr (dso); + + if (rdwr) + { + char *name1, *name2; + struct utimbuf u; + struct stat64 st; + + switch (write_dso (dso)) + { + case 2: + error (0, 0, "Could not write %s: %s", dso->filename, + elf_errmsg (-1)); + /* FALLTHROUGH */ + case 1: + close_dso (dso); + return 1; + case 0: + break; + } + + name1 = strdupa (dso->filename); + name2 = strdupa (dso->temp_filename); + if (fstat64 (dso->fdro, &st) < 0) + { + error (0, errno, "Could not stat %s", dso->filename); + close_dso (dso); + return 1; + } + if (fchown (dso->fd, st.st_uid, st.st_gid) < 0 + || fchmod (dso->fd, st.st_mode & 07777) < 0) + { + error (0, errno, "Could not set %s owner or mode", dso->filename); + close_dso (dso); + return 1; + } + close_dso_1 (dso); + u.actime = time (NULL); + u.modtime = st.st_mtime; + wrap_utime (name2, &u); + + if (set_security_context (dso, name2, orig_name ? orig_name : name1)) + { + wrap_unlink (name2); + return 1; + } + + if (wrap_rename (name2, name1)) + { + wrap_unlink (name2); + error (0, errno, "Could not rename temporary to %s", name1); + return 1; + } + } + else + close_dso_1 (dso); + + return 0; +} + +#endif diff --git a/trunk/src/dso.c b/trunk/src/dso.c index fcefafb..5080ffc 100644 --- a/trunk/src/dso.c +++ b/trunk/src/dso.c @@ -229,7 +229,7 @@ open_dso (const char *name) { int fd; - fd = open (name, O_RDONLY); + fd = wrap_open (name, O_RDONLY); if (fd == -1) { error (0, errno, "cannot open \"%s\"", name); @@ -515,7 +515,7 @@ fdopen_dso (int fd, const char *name) const char *soname; soname = get_data (dso, dso->info[DT_STRTAB] + dso->info[DT_SONAME], - NULL); + NULL, NULL); if (soname && soname[0] != '\0') dso->soname = (const char *) strdup (soname); } @@ -765,15 +765,15 @@ reopen_dso (DSO *dso, struct section_move *move, const char *temp_base) temp_base = dso->filename; sprintf (filename, "%s.#prelink#.XXXXXX", temp_base); - fd = mkstemp (filename); + fd = wrap_mkstemp (filename); if (fd == -1) { strcpy (filename, "/tmp/#prelink#.XXXXXX"); - fd = mkstemp (filename); + fd = wrap_mkstemp (filename); if (fd == -1) { strcpy (filename, "/dev/shm/#prelink#.XXXXXX"); - fd = mkstemp (filename); + fd = wrap_mkstemp (filename); } if (fd == -1) { @@ -1014,7 +1014,7 @@ error_out: elf_end (elf); if (fd != -1) { - unlink (filename); + wrap_unlink (filename); close (fd); } return 1; @@ -1029,7 +1029,9 @@ adjust_symbol_p (DSO *dso, GElf_Sym *sym) { if (sym->st_shndx == SHN_ABS && sym->st_value != 0 - && GELF_ST_TYPE (sym->st_info) <= STT_FUNC) + && (GELF_ST_TYPE (sym->st_info) <= STT_FUNC + || (dso->ehdr.e_machine == EM_ARM + && GELF_ST_TYPE (sym->st_info) == STT_ARM_TFUNC))) /* This is problematic. How do we find out if we should relocate this? Assume we should. */ return 1; @@ -1403,12 +1405,15 @@ adjust_dso (DSO *dso, GElf_Addr start, GElf_Addr adjust) return 1; break; case SHT_REL: - if (adjust_rel (dso, i, start, adjust)) - return 1; + /* Don't adjust reloc sections for debug info. */ + if (dso->shdr[i].sh_flags & SHF_ALLOC) + if (adjust_rel (dso, i, start, adjust)) + return 1; break; case SHT_RELA: - if (adjust_rela (dso, i, start, adjust)) - return 1; + if (dso->shdr[i].sh_flags & SHF_ALLOC) + if (adjust_rela (dso, i, start, adjust)) + return 1; break; } if ((dso->arch->machine == EM_ALPHA @@ -1652,7 +1657,7 @@ close_dso (DSO *dso) int rdwr = dso_is_rdwr (dso); if (rdwr && dso->temp_filename != NULL) - unlink (dso->temp_filename); + wrap_unlink (dso->temp_filename); close_dso_1 (dso); return 0; } @@ -1770,17 +1775,17 @@ update_dso (DSO *dso, const char *orig_name) close_dso_1 (dso); u.actime = time (NULL); u.modtime = st.st_mtime; - utime (name2, &u); + wrap_utime (name2, &u); if (set_security_context (dso, name2, orig_name ? orig_name : name1)) { - unlink (name2); + wrap_unlink (name2); return 1; } - if (rename (name2, name1)) + if (wrap_rename (name2, name1)) { - unlink (name2); + wrap_unlink (name2); error (0, errno, "Could not rename temporary to %s", name1); return 1; } diff --git a/trunk/src/elf.h b/trunk/src/elf.h new file mode 100644 index 0000000..0daff76 --- /dev/null +++ b/trunk/src/elf.h @@ -0,0 +1,2558 @@ +/* This file defines standard ELF types, structures, and macros. + Copyright (C) 1995-2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _ELF_H +#define _ELF_H 1 + +#include <features.h> + +__BEGIN_DECLS + +/* Standard ELF types. */ + +#include <stdint.h> + +/* Type for a 16-bit quantity. */ +typedef uint16_t Elf32_Half; +typedef uint16_t Elf64_Half; + +/* Types for signed and unsigned 32-bit quantities. */ +typedef uint32_t Elf32_Word; +typedef int32_t Elf32_Sword; +typedef uint32_t Elf64_Word; +typedef int32_t Elf64_Sword; + +/* Types for signed and unsigned 64-bit quantities. */ +typedef uint64_t Elf32_Xword; +typedef int64_t Elf32_Sxword; +typedef uint64_t Elf64_Xword; +typedef int64_t Elf64_Sxword; + +/* Type of addresses. */ +typedef uint32_t Elf32_Addr; +typedef uint64_t Elf64_Addr; + +/* Type of file offsets. */ +typedef uint32_t Elf32_Off; +typedef uint64_t Elf64_Off; + +/* Type for section indices, which are 16-bit quantities. */ +typedef uint16_t Elf32_Section; +typedef uint16_t Elf64_Section; + +/* Type for version symbol information. */ +typedef Elf32_Half Elf32_Versym; +typedef Elf64_Half Elf64_Versym; + + +/* The ELF file header. This appears at the start of every ELF file. */ + +#define EI_NIDENT (16) + +typedef struct +{ + unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ + Elf32_Half e_type; /* Object file type */ + Elf32_Half e_machine; /* Architecture */ + Elf32_Word e_version; /* Object file version */ + Elf32_Addr e_entry; /* Entry point virtual address */ + Elf32_Off e_phoff; /* Program header table file offset */ + Elf32_Off e_shoff; /* Section header table file offset */ + Elf32_Word e_flags; /* Processor-specific flags */ + Elf32_Half e_ehsize; /* ELF header size in bytes */ + Elf32_Half e_phentsize; /* Program header table entry size */ + Elf32_Half e_phnum; /* Program header table entry count */ + Elf32_Half e_shentsize; /* Section header table entry size */ + Elf32_Half e_shnum; /* Section header table entry count */ + Elf32_Half e_shstrndx; /* Section header string table index */ +} Elf32_Ehdr; + +typedef struct +{ + unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ + Elf64_Half e_type; /* Object file type */ + Elf64_Half e_machine; /* Architecture */ + Elf64_Word e_version; /* Object file version */ + Elf64_Addr e_entry; /* Entry point virtual address */ + Elf64_Off e_phoff; /* Program header table file offset */ + Elf64_Off e_shoff; /* Section header table file offset */ + Elf64_Word e_flags; /* Processor-specific flags */ + Elf64_Half e_ehsize; /* ELF header size in bytes */ + Elf64_Half e_phentsize; /* Program header table entry size */ + Elf64_Half e_phnum; /* Program header table entry count */ + Elf64_Half e_shentsize; /* Section header table entry size */ + Elf64_Half e_shnum; /* Section header table entry count */ + Elf64_Half e_shstrndx; /* Section header string table index */ +} Elf64_Ehdr; + +/* Fields in the e_ident array. The EI_* macros are indices into the + array. The macros under each EI_* macro are the values the byte + may have. */ + +#define EI_MAG0 0 /* File identification byte 0 index */ +#define ELFMAG0 0x7f /* Magic number byte 0 */ + +#define EI_MAG1 1 /* File identification byte 1 index */ +#define ELFMAG1 'E' /* Magic number byte 1 */ + +#define EI_MAG2 2 /* File identification byte 2 index */ +#define ELFMAG2 'L' /* Magic number byte 2 */ + +#define EI_MAG3 3 /* File identification byte 3 index */ +#define ELFMAG3 'F' /* Magic number byte 3 */ + +/* Conglomeration of the identification bytes, for easy testing as a word. */ +#define ELFMAG "\177ELF" +#define SELFMAG 4 + +#define EI_CLASS 4 /* File class byte index */ +#define ELFCLASSNONE 0 /* Invalid class */ +#define ELFCLASS32 1 /* 32-bit objects */ +#define ELFCLASS64 2 /* 64-bit objects */ +#define ELFCLASSNUM 3 + +#define EI_DATA 5 /* Data encoding byte index */ +#define ELFDATANONE 0 /* Invalid data encoding */ +#define ELFDATA2LSB 1 /* 2's complement, little endian */ +#define ELFDATA2MSB 2 /* 2's complement, big endian */ +#define ELFDATANUM 3 + +#define EI_VERSION 6 /* File version byte index */ + /* Value must be EV_CURRENT */ + +#define EI_OSABI 7 /* OS ABI identification */ +#define ELFOSABI_NONE 0 /* UNIX System V ABI */ +#define ELFOSABI_SYSV 0 /* Alias. */ +#define ELFOSABI_HPUX 1 /* HP-UX */ +#define ELFOSABI_NETBSD 2 /* NetBSD. */ +#define ELFOSABI_LINUX 3 /* Linux. */ +#define ELFOSABI_SOLARIS 6 /* Sun Solaris. */ +#define ELFOSABI_AIX 7 /* IBM AIX. */ +#define ELFOSABI_IRIX 8 /* SGI Irix. */ +#define ELFOSABI_FREEBSD 9 /* FreeBSD. */ +#define ELFOSABI_TRU64 10 /* Compaq TRU64 UNIX. */ +#define ELFOSABI_MODESTO 11 /* Novell Modesto. */ +#define ELFOSABI_OPENBSD 12 /* OpenBSD. */ +#define ELFOSABI_ARM 97 /* ARM */ +#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */ + +#define EI_ABIVERSION 8 /* ABI version */ + +#define EI_PAD 9 /* Byte index of padding bytes */ + +/* Legal values for e_type (object file type). */ + +#define ET_NONE 0 /* No file type */ +#define ET_REL 1 /* Relocatable file */ +#define ET_EXEC 2 /* Executable file */ +#define ET_DYN 3 /* Shared object file */ +#define ET_CORE 4 /* Core file */ +#define ET_NUM 5 /* Number of defined types */ +#define ET_LOOS 0xfe00 /* OS-specific range start */ +#define ET_HIOS 0xfeff /* OS-specific range end */ +#define ET_LOPROC 0xff00 /* Processor-specific range start */ +#define ET_HIPROC 0xffff /* Processor-specific range end */ + +/* Legal values for e_machine (architecture). */ + +#define EM_NONE 0 /* No machine */ +#define EM_M32 1 /* AT&T WE 32100 */ +#define EM_SPARC 2 /* SUN SPARC */ +#define EM_386 3 /* Intel 80386 */ +#define EM_68K 4 /* Motorola m68k family */ +#define EM_88K 5 /* Motorola m88k family */ +#define EM_860 7 /* Intel 80860 */ +#define EM_MIPS 8 /* MIPS R3000 big-endian */ +#define EM_S370 9 /* IBM System/370 */ +#define EM_MIPS_RS3_LE 10 /* MIPS R3000 little-endian */ + +#define EM_PARISC 15 /* HPPA */ +#define EM_VPP500 17 /* Fujitsu VPP500 */ +#define EM_SPARC32PLUS 18 /* Sun's "v8plus" */ +#define EM_960 19 /* Intel 80960 */ +#define EM_PPC 20 /* PowerPC */ +#define EM_PPC64 21 /* PowerPC 64-bit */ +#define EM_S390 22 /* IBM S390 */ + +#define EM_V800 36 /* NEC V800 series */ +#define EM_FR20 37 /* Fujitsu FR20 */ +#define EM_RH32 38 /* TRW RH-32 */ +#define EM_RCE 39 /* Motorola RCE */ +#define EM_ARM 40 /* ARM */ +#define EM_FAKE_ALPHA 41 /* Digital Alpha */ +#define EM_SH 42 /* Hitachi SH */ +#define EM_SPARCV9 43 /* SPARC v9 64-bit */ +#define EM_TRICORE 44 /* Siemens Tricore */ +#define EM_ARC 45 /* Argonaut RISC Core */ +#define EM_H8_300 46 /* Hitachi H8/300 */ +#define EM_H8_300H 47 /* Hitachi H8/300H */ +#define EM_H8S 48 /* Hitachi H8S */ +#define EM_H8_500 49 /* Hitachi H8/500 */ +#define EM_IA_64 50 /* Intel Merced */ +#define EM_MIPS_X 51 /* Stanford MIPS-X */ +#define EM_COLDFIRE 52 /* Motorola Coldfire */ +#define EM_68HC12 53 /* Motorola M68HC12 */ +#define EM_MMA 54 /* Fujitsu MMA Multimedia Accelerator*/ +#define EM_PCP 55 /* Siemens PCP */ +#define EM_NCPU 56 /* Sony nCPU embeeded RISC */ +#define EM_NDR1 57 /* Denso NDR1 microprocessor */ +#define EM_STARCORE 58 /* Motorola Start*Core processor */ +#define EM_ME16 59 /* Toyota ME16 processor */ +#define EM_ST100 60 /* STMicroelectronic ST100 processor */ +#define EM_TINYJ 61 /* Advanced Logic Corp. Tinyj emb.fam*/ +#define EM_X86_64 62 /* AMD x86-64 architecture */ +#define EM_PDSP 63 /* Sony DSP Processor */ + +#define EM_FX66 66 /* Siemens FX66 microcontroller */ +#define EM_ST9PLUS 67 /* STMicroelectronics ST9+ 8/16 mc */ +#define EM_ST7 68 /* STmicroelectronics ST7 8 bit mc */ +#define EM_68HC16 69 /* Motorola MC68HC16 microcontroller */ +#define EM_68HC11 70 /* Motorola MC68HC11 microcontroller */ +#define EM_68HC08 71 /* Motorola MC68HC08 microcontroller */ +#define EM_68HC05 72 /* Motorola MC68HC05 microcontroller */ +#define EM_SVX 73 /* Silicon Graphics SVx */ +#define EM_ST19 74 /* STMicroelectronics ST19 8 bit mc */ +#define EM_VAX 75 /* Digital VAX */ +#define EM_CRIS 76 /* Axis Communications 32-bit embedded processor */ +#define EM_JAVELIN 77 /* Infineon Technologies 32-bit embedded processor */ +#define EM_FIREPATH 78 /* Element 14 64-bit DSP Processor */ +#define EM_ZSP 79 /* LSI Logic 16-bit DSP Processor */ +#define EM_MMIX 80 /* Donald Knuth's educational 64-bit processor */ +#define EM_HUANY 81 /* Harvard University machine-independent object files */ +#define EM_PRISM 82 /* SiTera Prism */ +#define EM_AVR 83 /* Atmel AVR 8-bit microcontroller */ +#define EM_FR30 84 /* Fujitsu FR30 */ +#define EM_D10V 85 /* Mitsubishi D10V */ +#define EM_D30V 86 /* Mitsubishi D30V */ +#define EM_V850 87 /* NEC v850 */ +#define EM_M32R 88 /* Mitsubishi M32R */ +#define EM_MN10300 89 /* Matsushita MN10300 */ +#define EM_MN10200 90 /* Matsushita MN10200 */ +#define EM_PJ 91 /* picoJava */ +#define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor */ +#define EM_ARC_A5 93 /* ARC Cores Tangent-A5 */ +#define EM_XTENSA 94 /* Tensilica Xtensa Architecture */ +#define EM_NUM 95 + +/* If it is necessary to assign new unofficial EM_* values, please + pick large random numbers (0x8523, 0xa7f2, etc.) to minimize the + chances of collision with official or non-GNU unofficial values. */ + +#define EM_ALPHA 0x9026 + +/* Legal values for e_version (version). */ + +#define EV_NONE 0 /* Invalid ELF version */ +#define EV_CURRENT 1 /* Current version */ +#define EV_NUM 2 + +/* Section header. */ + +typedef struct +{ + Elf32_Word sh_name; /* Section name (string tbl index) */ + Elf32_Word sh_type; /* Section type */ + Elf32_Word sh_flags; /* Section flags */ + Elf32_Addr sh_addr; /* Section virtual addr at execution */ + Elf32_Off sh_offset; /* Section file offset */ + Elf32_Word sh_size; /* Section size in bytes */ + Elf32_Word sh_link; /* Link to another section */ + Elf32_Word sh_info; /* Additional section information */ + Elf32_Word sh_addralign; /* Section alignment */ + Elf32_Word sh_entsize; /* Entry size if section holds table */ +} Elf32_Shdr; + +typedef struct +{ + Elf64_Word sh_name; /* Section name (string tbl index) */ + Elf64_Word sh_type; /* Section type */ + Elf64_Xword sh_flags; /* Section flags */ + Elf64_Addr sh_addr; /* Section virtual addr at execution */ + Elf64_Off sh_offset; /* Section file offset */ + Elf64_Xword sh_size; /* Section size in bytes */ + Elf64_Word sh_link; /* Link to another section */ + Elf64_Word sh_info; /* Additional section information */ + Elf64_Xword sh_addralign; /* Section alignment */ + Elf64_Xword sh_entsize; /* Entry size if section holds table */ +} Elf64_Shdr; + +/* Special section indices. */ + +#define SHN_UNDEF 0 /* Undefined section */ +#define SHN_LORESERVE 0xff00 /* Start of reserved indices */ +#define SHN_LOPROC 0xff00 /* Start of processor-specific */ +#define SHN_BEFORE 0xff00 /* Order section before all others + (Solaris). */ +#define SHN_AFTER 0xff01 /* Order section after all others + (Solaris). */ +#define SHN_HIPROC 0xff1f /* End of processor-specific */ +#define SHN_LOOS 0xff20 /* Start of OS-specific */ +#define SHN_HIOS 0xff3f /* End of OS-specific */ +#define SHN_ABS 0xfff1 /* Associated symbol is absolute */ +#define SHN_COMMON 0xfff2 /* Associated symbol is common */ +#define SHN_XINDEX 0xffff /* Index is in extra table. */ +#define SHN_HIRESERVE 0xffff /* End of reserved indices */ + +/* Legal values for sh_type (section type). */ + +#define SHT_NULL 0 /* Section header table entry unused */ +#define SHT_PROGBITS 1 /* Program data */ +#define SHT_SYMTAB 2 /* Symbol table */ +#define SHT_STRTAB 3 /* String table */ +#define SHT_RELA 4 /* Relocation entries with addends */ +#define SHT_HASH 5 /* Symbol hash table */ +#define SHT_DYNAMIC 6 /* Dynamic linking information */ +#define SHT_NOTE 7 /* Notes */ +#define SHT_NOBITS 8 /* Program space with no data (bss) */ +#define SHT_REL 9 /* Relocation entries, no addends */ +#define SHT_SHLIB 10 /* Reserved */ +#define SHT_DYNSYM 11 /* Dynamic linker symbol table */ +#define SHT_INIT_ARRAY 14 /* Array of constructors */ +#define SHT_FINI_ARRAY 15 /* Array of destructors */ +#define SHT_PREINIT_ARRAY 16 /* Array of pre-constructors */ +#define SHT_GROUP 17 /* Section group */ +#define SHT_SYMTAB_SHNDX 18 /* Extended section indeces */ +#define SHT_NUM 19 /* Number of defined types. */ +#define SHT_LOOS 0x60000000 /* Start OS-specific */ +#define SHT_GNU_LIBLIST 0x6ffffff7 /* Prelink library list */ +#define SHT_CHECKSUM 0x6ffffff8 /* Checksum for DSO content. */ +#define SHT_LOSUNW 0x6ffffffa /* Sun-specific low bound. */ +#define SHT_SUNW_move 0x6ffffffa +#define SHT_SUNW_COMDAT 0x6ffffffb +#define SHT_SUNW_syminfo 0x6ffffffc +#define SHT_GNU_verdef 0x6ffffffd /* Version definition section. */ +#define SHT_GNU_verneed 0x6ffffffe /* Version needs section. */ +#define SHT_GNU_versym 0x6fffffff /* Version symbol table. */ +#define SHT_HISUNW 0x6fffffff /* Sun-specific high bound. */ +#define SHT_HIOS 0x6fffffff /* End OS-specific type */ +#define SHT_LOPROC 0x70000000 /* Start of processor-specific */ +#define SHT_HIPROC 0x7fffffff /* End of processor-specific */ +#define SHT_LOUSER 0x80000000 /* Start of application-specific */ +#define SHT_HIUSER 0x8fffffff /* End of application-specific */ + +/* Legal values for sh_flags (section flags). */ + +#define SHF_WRITE (1 << 0) /* Writable */ +#define SHF_ALLOC (1 << 1) /* Occupies memory during execution */ +#define SHF_EXECINSTR (1 << 2) /* Executable */ +#define SHF_MERGE (1 << 4) /* Might be merged */ +#define SHF_STRINGS (1 << 5) /* Contains nul-terminated strings */ +#define SHF_INFO_LINK (1 << 6) /* `sh_info' contains SHT index */ +#define SHF_LINK_ORDER (1 << 7) /* Preserve order after combining */ +#define SHF_OS_NONCONFORMING (1 << 8) /* Non-standard OS specific handling + required */ +#define SHF_GROUP (1 << 9) /* Section is member of a group. */ +#define SHF_TLS (1 << 10) /* Section hold thread-local data. */ +#define SHF_MASKOS 0x0ff00000 /* OS-specific. */ +#define SHF_MASKPROC 0xf0000000 /* Processor-specific */ +#define SHF_ORDERED (1 << 30) /* Special ordering requirement + (Solaris). */ +#define SHF_EXCLUDE (1 << 31) /* Section is excluded unless + referenced or allocated (Solaris).*/ + +/* Section group handling. */ +#define GRP_COMDAT 0x1 /* Mark group as COMDAT. */ + +/* Symbol table entry. */ + +typedef struct +{ + Elf32_Word st_name; /* Symbol name (string tbl index) */ + Elf32_Addr st_value; /* Symbol value */ + Elf32_Word st_size; /* Symbol size */ + unsigned char st_info; /* Symbol type and binding */ + unsigned char st_other; /* Symbol visibility */ + Elf32_Section st_shndx; /* Section index */ +} Elf32_Sym; + +typedef struct +{ + Elf64_Word st_name; /* Symbol name (string tbl index) */ + unsigned char st_info; /* Symbol type and binding */ + unsigned char st_other; /* Symbol visibility */ + Elf64_Section st_shndx; /* Section index */ + Elf64_Addr st_value; /* Symbol value */ + Elf64_Xword st_size; /* Symbol size */ +} Elf64_Sym; + +/* The syminfo section if available contains additional information about + every dynamic symbol. */ + +typedef struct +{ + Elf32_Half si_boundto; /* Direct bindings, symbol bound to */ + Elf32_Half si_flags; /* Per symbol flags */ +} Elf32_Syminfo; + +typedef struct +{ + Elf64_Half si_boundto; /* Direct bindings, symbol bound to */ + Elf64_Half si_flags; /* Per symbol flags */ +} Elf64_Syminfo; + +/* Possible values for si_boundto. */ +#define SYMINFO_BT_SELF 0xffff /* Symbol bound to self */ +#define SYMINFO_BT_PARENT 0xfffe /* Symbol bound to parent */ +#define SYMINFO_BT_LOWRESERVE 0xff00 /* Beginning of reserved entries */ + +/* Possible bitmasks for si_flags. */ +#define SYMINFO_FLG_DIRECT 0x0001 /* Direct bound symbol */ +#define SYMINFO_FLG_PASSTHRU 0x0002 /* Pass-thru symbol for translator */ +#define SYMINFO_FLG_COPY 0x0004 /* Symbol is a copy-reloc */ +#define SYMINFO_FLG_LAZYLOAD 0x0008 /* Symbol bound to object to be lazy + loaded */ +/* Syminfo version values. */ +#define SYMINFO_NONE 0 +#define SYMINFO_CURRENT 1 +#define SYMINFO_NUM 2 + + +/* How to extract and insert information held in the st_info field. */ + +#define ELF32_ST_BIND(val) (((unsigned char) (val)) >> 4) +#define ELF32_ST_TYPE(val) ((val) & 0xf) +#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) + +/* Both Elf32_Sym and Elf64_Sym use the same one-byte st_info field. */ +#define ELF64_ST_BIND(val) ELF32_ST_BIND (val) +#define ELF64_ST_TYPE(val) ELF32_ST_TYPE (val) +#define ELF64_ST_INFO(bind, type) ELF32_ST_INFO ((bind), (type)) + +/* Legal values for ST_BIND subfield of st_info (symbol binding). */ + +#define STB_LOCAL 0 /* Local symbol */ +#define STB_GLOBAL 1 /* Global symbol */ +#define STB_WEAK 2 /* Weak symbol */ +#define STB_NUM 3 /* Number of defined types. */ +#define STB_LOOS 10 /* Start of OS-specific */ +#define STB_HIOS 12 /* End of OS-specific */ +#define STB_LOPROC 13 /* Start of processor-specific */ +#define STB_HIPROC 15 /* End of processor-specific */ + +/* Legal values for ST_TYPE subfield of st_info (symbol type). */ + +#define STT_NOTYPE 0 /* Symbol type is unspecified */ +#define STT_OBJECT 1 /* Symbol is a data object */ +#define STT_FUNC 2 /* Symbol is a code object */ +#define STT_SECTION 3 /* Symbol associated with a section */ +#define STT_FILE 4 /* Symbol's name is file name */ +#define STT_COMMON 5 /* Symbol is a common data object */ +#define STT_TLS 6 /* Symbol is thread-local data object*/ +#define STT_NUM 7 /* Number of defined types. */ +#define STT_LOOS 10 /* Start of OS-specific */ +#define STT_HIOS 12 /* End of OS-specific */ +#define STT_LOPROC 13 /* Start of processor-specific */ +#define STT_HIPROC 15 /* End of processor-specific */ + + +/* Symbol table indices are found in the hash buckets and chain table + of a symbol hash table section. This special index value indicates + the end of a chain, meaning no further symbols are found in that bucket. */ + +#define STN_UNDEF 0 /* End of a chain. */ + + +/* How to extract and insert information held in the st_other field. */ + +#define ELF32_ST_VISIBILITY(o) ((o) & 0x03) + +/* For ELF64 the definitions are the same. */ +#define ELF64_ST_VISIBILITY(o) ELF32_ST_VISIBILITY (o) + +/* Symbol visibility specification encoded in the st_other field. */ +#define STV_DEFAULT 0 /* Default symbol visibility rules */ +#define STV_INTERNAL 1 /* Processor specific hidden class */ +#define STV_HIDDEN 2 /* Sym unavailable in other modules */ +#define STV_PROTECTED 3 /* Not preemptible, not exported */ + + +/* Relocation table entry without addend (in section of type SHT_REL). */ + +typedef struct +{ + Elf32_Addr r_offset; /* Address */ + Elf32_Word r_info; /* Relocation type and symbol index */ +} Elf32_Rel; + +/* I have seen two different definitions of the Elf64_Rel and + Elf64_Rela structures, so we'll leave them out until Novell (or + whoever) gets their act together. */ +/* The following, at least, is used on Sparc v9, MIPS, and Alpha. */ + +typedef struct +{ + Elf64_Addr r_offset; /* Address */ + Elf64_Xword r_info; /* Relocation type and symbol index */ +} Elf64_Rel; + +/* Relocation table entry with addend (in section of type SHT_RELA). */ + +typedef struct +{ + Elf32_Addr r_offset; /* Address */ + Elf32_Word r_info; /* Relocation type and symbol index */ + Elf32_Sword r_addend; /* Addend */ +} Elf32_Rela; + +typedef struct +{ + Elf64_Addr r_offset; /* Address */ + Elf64_Xword r_info; /* Relocation type and symbol index */ + Elf64_Sxword r_addend; /* Addend */ +} Elf64_Rela; + +/* How to extract and insert information held in the r_info field. */ + +#define ELF32_R_SYM(val) ((val) >> 8) +#define ELF32_R_TYPE(val) ((val) & 0xff) +#define ELF32_R_INFO(sym, type) (((sym) << 8) + ((type) & 0xff)) + +#define ELF64_R_SYM(i) ((i) >> 32) +#define ELF64_R_TYPE(i) ((i) & 0xffffffff) +#define ELF64_R_INFO(sym,type) ((((Elf64_Xword) (sym)) << 32) + (type)) + +/* Program segment header. */ + +typedef struct +{ + Elf32_Word p_type; /* Segment type */ + Elf32_Off p_offset; /* Segment file offset */ + Elf32_Addr p_vaddr; /* Segment virtual address */ + Elf32_Addr p_paddr; /* Segment physical address */ + Elf32_Word p_filesz; /* Segment size in file */ + Elf32_Word p_memsz; /* Segment size in memory */ + Elf32_Word p_flags; /* Segment flags */ + Elf32_Word p_align; /* Segment alignment */ +} Elf32_Phdr; + +typedef struct +{ + Elf64_Word p_type; /* Segment type */ + Elf64_Word p_flags; /* Segment flags */ + Elf64_Off p_offset; /* Segment file offset */ + Elf64_Addr p_vaddr; /* Segment virtual address */ + Elf64_Addr p_paddr; /* Segment physical address */ + Elf64_Xword p_filesz; /* Segment size in file */ + Elf64_Xword p_memsz; /* Segment size in memory */ + Elf64_Xword p_align; /* Segment alignment */ +} Elf64_Phdr; + +/* Legal values for p_type (segment type). */ + +#define PT_NULL 0 /* Program header table entry unused */ +#define PT_LOAD 1 /* Loadable program segment */ +#define PT_DYNAMIC 2 /* Dynamic linking information */ +#define PT_INTERP 3 /* Program interpreter */ +#define PT_NOTE 4 /* Auxiliary information */ +#define PT_SHLIB 5 /* Reserved */ +#define PT_PHDR 6 /* Entry for header table itself */ +#define PT_TLS 7 /* Thread-local storage segment */ +#define PT_NUM 8 /* Number of defined types */ +#define PT_LOOS 0x60000000 /* Start of OS-specific */ +#define PT_GNU_EH_FRAME 0x6474e550 /* GCC .eh_frame_hdr segment */ +#define PT_GNU_STACK 0x6474e551 /* Indicates stack executability */ +#define PT_GNU_RELRO 0x6474e552 /* Read-only after relocation */ +#define PT_LOSUNW 0x6ffffffa +#define PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */ +#define PT_SUNWSTACK 0x6ffffffb /* Stack segment */ +#define PT_HISUNW 0x6fffffff +#define PT_HIOS 0x6fffffff /* End of OS-specific */ +#define PT_LOPROC 0x70000000 /* Start of processor-specific */ +#define PT_HIPROC 0x7fffffff /* End of processor-specific */ + +/* Legal values for p_flags (segment flags). */ + +#define PF_X (1 << 0) /* Segment is executable */ +#define PF_W (1 << 1) /* Segment is writable */ +#define PF_R (1 << 2) /* Segment is readable */ +#define PF_MASKOS 0x0ff00000 /* OS-specific */ +#define PF_MASKPROC 0xf0000000 /* Processor-specific */ + +/* Legal values for note segment descriptor types for core files. */ + +#define NT_PRSTATUS 1 /* Contains copy of prstatus struct */ +#define NT_FPREGSET 2 /* Contains copy of fpregset struct */ +#define NT_PRPSINFO 3 /* Contains copy of prpsinfo struct */ +#define NT_PRXREG 4 /* Contains copy of prxregset struct */ +#define NT_TASKSTRUCT 4 /* Contains copy of task structure */ +#define NT_PLATFORM 5 /* String from sysinfo(SI_PLATFORM) */ +#define NT_AUXV 6 /* Contains copy of auxv array */ +#define NT_GWINDOWS 7 /* Contains copy of gwindows struct */ +#define NT_ASRS 8 /* Contains copy of asrset struct */ +#define NT_PSTATUS 10 /* Contains copy of pstatus struct */ +#define NT_PSINFO 13 /* Contains copy of psinfo struct */ +#define NT_PRCRED 14 /* Contains copy of prcred struct */ +#define NT_UTSNAME 15 /* Contains copy of utsname struct */ +#define NT_LWPSTATUS 16 /* Contains copy of lwpstatus struct */ +#define NT_LWPSINFO 17 /* Contains copy of lwpinfo struct */ +#define NT_PRFPXREG 20 /* Contains copy of fprxregset struct*/ + +/* Legal values for the note segment descriptor types for object files. */ + +#define NT_VERSION 1 /* Contains a version string. */ + + +/* Dynamic section entry. */ + +typedef struct +{ + Elf32_Sword d_tag; /* Dynamic entry type */ + union + { + Elf32_Word d_val; /* Integer value */ + Elf32_Addr d_ptr; /* Address value */ + } d_un; +} Elf32_Dyn; + +typedef struct +{ + Elf64_Sxword d_tag; /* Dynamic entry type */ + union + { + Elf64_Xword d_val; /* Integer value */ + Elf64_Addr d_ptr; /* Address value */ + } d_un; +} Elf64_Dyn; + +/* Legal values for d_tag (dynamic entry type). */ + +#define DT_NULL 0 /* Marks end of dynamic section */ +#define DT_NEEDED 1 /* Name of needed library */ +#define DT_PLTRELSZ 2 /* Size in bytes of PLT relocs */ +#define DT_PLTGOT 3 /* Processor defined value */ +#define DT_HASH 4 /* Address of symbol hash table */ +#define DT_STRTAB 5 /* Address of string table */ +#define DT_SYMTAB 6 /* Address of symbol table */ +#define DT_RELA 7 /* Address of Rela relocs */ +#define DT_RELASZ 8 /* Total size of Rela relocs */ +#define DT_RELAENT 9 /* Size of one Rela reloc */ +#define DT_STRSZ 10 /* Size of string table */ +#define DT_SYMENT 11 /* Size of one symbol table entry */ +#define DT_INIT 12 /* Address of init function */ +#define DT_FINI 13 /* Address of termination function */ +#define DT_SONAME 14 /* Name of shared object */ +#define DT_RPATH 15 /* Library search path (deprecated) */ +#define DT_SYMBOLIC 16 /* Start symbol search here */ +#define DT_REL 17 /* Address of Rel relocs */ +#define DT_RELSZ 18 /* Total size of Rel relocs */ +#define DT_RELENT 19 /* Size of one Rel reloc */ +#define DT_PLTREL 20 /* Type of reloc in PLT */ +#define DT_DEBUG 21 /* For debugging; unspecified */ +#define DT_TEXTREL 22 /* Reloc might modify .text */ +#define DT_JMPREL 23 /* Address of PLT relocs */ +#define DT_BIND_NOW 24 /* Process relocations of object */ +#define DT_INIT_ARRAY 25 /* Array with addresses of init fct */ +#define DT_FINI_ARRAY 26 /* Array with addresses of fini fct */ +#define DT_INIT_ARRAYSZ 27 /* Size in bytes of DT_INIT_ARRAY */ +#define DT_FINI_ARRAYSZ 28 /* Size in bytes of DT_FINI_ARRAY */ +#define DT_RUNPATH 29 /* Library search path */ +#define DT_FLAGS 30 /* Flags for the object being loaded */ +#define DT_ENCODING 32 /* Start of encoded range */ +#define DT_PREINIT_ARRAY 32 /* Array with addresses of preinit fct*/ +#define DT_PREINIT_ARRAYSZ 33 /* size in bytes of DT_PREINIT_ARRAY */ +#define DT_NUM 34 /* Number used */ +#define DT_LOOS 0x6000000d /* Start of OS-specific */ +#define DT_HIOS 0x6ffff000 /* End of OS-specific */ +#define DT_LOPROC 0x70000000 /* Start of processor-specific */ +#define DT_HIPROC 0x7fffffff /* End of processor-specific */ +#define DT_PROCNUM DT_MIPS_NUM /* Most used by any processor */ + +/* DT_* entries which fall between DT_VALRNGHI & DT_VALRNGLO use the + Dyn.d_un.d_val field of the Elf*_Dyn structure. This follows Sun's + approach. */ +#define DT_VALRNGLO 0x6ffffd00 +#define DT_GNU_PRELINKED 0x6ffffdf5 /* Prelinking timestamp */ +#define DT_GNU_CONFLICTSZ 0x6ffffdf6 /* Size of conflict section */ +#define DT_GNU_LIBLISTSZ 0x6ffffdf7 /* Size of library list */ +#define DT_CHECKSUM 0x6ffffdf8 +#define DT_PLTPADSZ 0x6ffffdf9 +#define DT_MOVEENT 0x6ffffdfa +#define DT_MOVESZ 0x6ffffdfb +#define DT_FEATURE_1 0x6ffffdfc /* Feature selection (DTF_*). */ +#define DT_POSFLAG_1 0x6ffffdfd /* Flags for DT_* entries, effecting + the following DT_* entry. */ +#define DT_SYMINSZ 0x6ffffdfe /* Size of syminfo table (in bytes) */ +#define DT_SYMINENT 0x6ffffdff /* Entry size of syminfo */ +#define DT_VALRNGHI 0x6ffffdff +#define DT_VALTAGIDX(tag) (DT_VALRNGHI - (tag)) /* Reverse order! */ +#define DT_VALNUM 12 + +/* DT_* entries which fall between DT_ADDRRNGHI & DT_ADDRRNGLO use the + Dyn.d_un.d_ptr field of the Elf*_Dyn structure. + + If any adjustment is made to the ELF object after it has been + built these entries will need to be adjusted. */ +#define DT_ADDRRNGLO 0x6ffffe00 +#define DT_GNU_CONFLICT 0x6ffffef8 /* Start of conflict section */ +#define DT_GNU_LIBLIST 0x6ffffef9 /* Library list */ +#define DT_CONFIG 0x6ffffefa /* Configuration information. */ +#define DT_DEPAUDIT 0x6ffffefb /* Dependency auditing. */ +#define DT_AUDIT 0x6ffffefc /* Object auditing. */ +#define DT_PLTPAD 0x6ffffefd /* PLT padding. */ +#define DT_MOVETAB 0x6ffffefe /* Move table. */ +#define DT_SYMINFO 0x6ffffeff /* Syminfo table. */ +#define DT_ADDRRNGHI 0x6ffffeff +#define DT_ADDRTAGIDX(tag) (DT_ADDRRNGHI - (tag)) /* Reverse order! */ +#define DT_ADDRNUM 10 + +/* The versioning entry types. The next are defined as part of the + GNU extension. */ +#define DT_VERSYM 0x6ffffff0 + +#define DT_RELACOUNT 0x6ffffff9 +#define DT_RELCOUNT 0x6ffffffa + +/* These were chosen by Sun. */ +#define DT_FLAGS_1 0x6ffffffb /* State flags, see DF_1_* below. */ +#define DT_VERDEF 0x6ffffffc /* Address of version definition + table */ +#define DT_VERDEFNUM 0x6ffffffd /* Number of version definitions */ +#define DT_VERNEED 0x6ffffffe /* Address of table with needed + versions */ +#define DT_VERNEEDNUM 0x6fffffff /* Number of needed versions */ +#define DT_VERSIONTAGIDX(tag) (DT_VERNEEDNUM - (tag)) /* Reverse order! */ +#define DT_VERSIONTAGNUM 16 + +/* Sun added these machine-independent extensions in the "processor-specific" + range. Be compatible. */ +#define DT_AUXILIARY 0x7ffffffd /* Shared object to load before self */ +#define DT_FILTER 0x7fffffff /* Shared object to get values from */ +#define DT_EXTRATAGIDX(tag) ((Elf32_Word)-((Elf32_Sword) (tag) <<1>>1)-1) +#define DT_EXTRANUM 3 + +/* Values of `d_un.d_val' in the DT_FLAGS entry. */ +#define DF_ORIGIN 0x00000001 /* Object may use DF_ORIGIN */ +#define DF_SYMBOLIC 0x00000002 /* Symbol resolutions starts here */ +#define DF_TEXTREL 0x00000004 /* Object contains text relocations */ +#define DF_BIND_NOW 0x00000008 /* No lazy binding for this object */ +#define DF_STATIC_TLS 0x00000010 /* Module uses the static TLS model */ + +/* State flags selectable in the `d_un.d_val' element of the DT_FLAGS_1 + entry in the dynamic section. */ +#define DF_1_NOW 0x00000001 /* Set RTLD_NOW for this object. */ +#define DF_1_GLOBAL 0x00000002 /* Set RTLD_GLOBAL for this object. */ +#define DF_1_GROUP 0x00000004 /* Set RTLD_GROUP for this object. */ +#define DF_1_NODELETE 0x00000008 /* Set RTLD_NODELETE for this object.*/ +#define DF_1_LOADFLTR 0x00000010 /* Trigger filtee loading at runtime.*/ +#define DF_1_INITFIRST 0x00000020 /* Set RTLD_INITFIRST for this object*/ +#define DF_1_NOOPEN 0x00000040 /* Set RTLD_NOOPEN for this object. */ +#define DF_1_ORIGIN 0x00000080 /* $ORIGIN must be handled. */ +#define DF_1_DIRECT 0x00000100 /* Direct binding enabled. */ +#define DF_1_TRANS 0x00000200 +#define DF_1_INTERPOSE 0x00000400 /* Object is used to interpose. */ +#define DF_1_NODEFLIB 0x00000800 /* Ignore default lib search path. */ +#define DF_1_NODUMP 0x00001000 /* Object can't be dldump'ed. */ +#define DF_1_CONFALT 0x00002000 /* Configuration alternative created.*/ +#define DF_1_ENDFILTEE 0x00004000 /* Filtee terminates filters search. */ +#define DF_1_DISPRELDNE 0x00008000 /* Disp reloc applied at build time. */ +#define DF_1_DISPRELPND 0x00010000 /* Disp reloc applied at run-time. */ + +/* Flags for the feature selection in DT_FEATURE_1. */ +#define DTF_1_PARINIT 0x00000001 +#define DTF_1_CONFEXP 0x00000002 + +/* Flags in the DT_POSFLAG_1 entry effecting only the next DT_* entry. */ +#define DF_P1_LAZYLOAD 0x00000001 /* Lazyload following object. */ +#define DF_P1_GROUPPERM 0x00000002 /* Symbols from next object are not + generally available. */ + +/* Version definition sections. */ + +typedef struct +{ + Elf32_Half vd_version; /* Version revision */ + Elf32_Half vd_flags; /* Version information */ + Elf32_Half vd_ndx; /* Version Index */ + Elf32_Half vd_cnt; /* Number of associated aux entries */ + Elf32_Word vd_hash; /* Version name hash value */ + Elf32_Word vd_aux; /* Offset in bytes to verdaux array */ + Elf32_Word vd_next; /* Offset in bytes to next verdef + entry */ +} Elf32_Verdef; + +typedef struct +{ + Elf64_Half vd_version; /* Version revision */ + Elf64_Half vd_flags; /* Version information */ + Elf64_Half vd_ndx; /* Version Index */ + Elf64_Half vd_cnt; /* Number of associated aux entries */ + Elf64_Word vd_hash; /* Version name hash value */ + Elf64_Word vd_aux; /* Offset in bytes to verdaux array */ + Elf64_Word vd_next; /* Offset in bytes to next verdef + entry */ +} Elf64_Verdef; + + +/* Legal values for vd_version (version revision). */ +#define VER_DEF_NONE 0 /* No version */ +#define VER_DEF_CURRENT 1 /* Current version */ +#define VER_DEF_NUM 2 /* Given version number */ + +/* Legal values for vd_flags (version information flags). */ +#define VER_FLG_BASE 0x1 /* Version definition of file itself */ +#define VER_FLG_WEAK 0x2 /* Weak version identifier */ + +/* Versym symbol index values. */ +#define VER_NDX_LOCAL 0 /* Symbol is local. */ +#define VER_NDX_GLOBAL 1 /* Symbol is global. */ +#define VER_NDX_LORESERVE 0xff00 /* Beginning of reserved entries. */ +#define VER_NDX_ELIMINATE 0xff01 /* Symbol is to be eliminated. */ + +/* Auxialiary version information. */ + +typedef struct +{ + Elf32_Word vda_name; /* Version or dependency names */ + Elf32_Word vda_next; /* Offset in bytes to next verdaux + entry */ +} Elf32_Verdaux; + +typedef struct +{ + Elf64_Word vda_name; /* Version or dependency names */ + Elf64_Word vda_next; /* Offset in bytes to next verdaux + entry */ +} Elf64_Verdaux; + + +/* Version dependency section. */ + +typedef struct +{ + Elf32_Half vn_version; /* Version of structure */ + Elf32_Half vn_cnt; /* Number of associated aux entries */ + Elf32_Word vn_file; /* Offset of filename for this + dependency */ + Elf32_Word vn_aux; /* Offset in bytes to vernaux array */ + Elf32_Word vn_next; /* Offset in bytes to next verneed + entry */ +} Elf32_Verneed; + +typedef struct +{ + Elf64_Half vn_version; /* Version of structure */ + Elf64_Half vn_cnt; /* Number of associated aux entries */ + Elf64_Word vn_file; /* Offset of filename for this + dependency */ + Elf64_Word vn_aux; /* Offset in bytes to vernaux array */ + Elf64_Word vn_next; /* Offset in bytes to next verneed + entry */ +} Elf64_Verneed; + + +/* Legal values for vn_version (version revision). */ +#define VER_NEED_NONE 0 /* No version */ +#define VER_NEED_CURRENT 1 /* Current version */ +#define VER_NEED_NUM 2 /* Given version number */ + +/* Auxiliary needed version information. */ + +typedef struct +{ + Elf32_Word vna_hash; /* Hash value of dependency name */ + Elf32_Half vna_flags; /* Dependency specific information */ + Elf32_Half vna_other; /* Unused */ + Elf32_Word vna_name; /* Dependency name string offset */ + Elf32_Word vna_next; /* Offset in bytes to next vernaux + entry */ +} Elf32_Vernaux; + +typedef struct +{ + Elf64_Word vna_hash; /* Hash value of dependency name */ + Elf64_Half vna_flags; /* Dependency specific information */ + Elf64_Half vna_other; /* Unused */ + Elf64_Word vna_name; /* Dependency name string offset */ + Elf64_Word vna_next; /* Offset in bytes to next vernaux + entry */ +} Elf64_Vernaux; + + +/* Legal values for vna_flags. */ +#define VER_FLG_WEAK 0x2 /* Weak version identifier */ + + +/* Auxiliary vector. */ + +/* This vector is normally only used by the program interpreter. The + usual definition in an ABI supplement uses the name auxv_t. The + vector is not usually defined in a standard <elf.h> file, but it + can't hurt. We rename it to avoid conflicts. The sizes of these + types are an arrangement between the exec server and the program + interpreter, so we don't fully specify them here. */ + +typedef struct +{ + int a_type; /* Entry type */ + union + { + long int a_val; /* Integer value */ + void *a_ptr; /* Pointer value */ + void (*a_fcn) (void); /* Function pointer value */ + } a_un; +} Elf32_auxv_t; + +typedef struct +{ + long int a_type; /* Entry type */ + union + { + long int a_val; /* Integer value */ + void *a_ptr; /* Pointer value */ + void (*a_fcn) (void); /* Function pointer value */ + } a_un; +} Elf64_auxv_t; + +/* Legal values for a_type (entry type). */ + +#define AT_NULL 0 /* End of vector */ +#define AT_IGNORE 1 /* Entry should be ignored */ +#define AT_EXECFD 2 /* File descriptor of program */ +#define AT_PHDR 3 /* Program headers for program */ +#define AT_PHENT 4 /* Size of program header entry */ +#define AT_PHNUM 5 /* Number of program headers */ +#define AT_PAGESZ 6 /* System page size */ +#define AT_BASE 7 /* Base address of interpreter */ +#define AT_FLAGS 8 /* Flags */ +#define AT_ENTRY 9 /* Entry point of program */ +#define AT_NOTELF 10 /* Program is not ELF */ +#define AT_UID 11 /* Real uid */ +#define AT_EUID 12 /* Effective uid */ +#define AT_GID 13 /* Real gid */ +#define AT_EGID 14 /* Effective gid */ +#define AT_CLKTCK 17 /* Frequency of times() */ + +/* Some more special a_type values describing the hardware. */ +#define AT_PLATFORM 15 /* String identifying platform. */ +#define AT_HWCAP 16 /* Machine dependent hints about + processor capabilities. */ + +/* This entry gives some information about the FPU initialization + performed by the kernel. */ +#define AT_FPUCW 18 /* Used FPU control word. */ + +/* Cache block sizes. */ +#define AT_DCACHEBSIZE 19 /* Data cache block size. */ +#define AT_ICACHEBSIZE 20 /* Instruction cache block size. */ +#define AT_UCACHEBSIZE 21 /* Unified cache block size. */ + +/* A special ignored value for PPC, used by the kernel to control the + interpretation of the AUXV. Must be > 16. */ +#define AT_IGNOREPPC 22 /* Entry should be ignored. */ + +#define AT_SECURE 23 /* Boolean, was exec setuid-like? */ + +/* Pointer to the global system page used for system calls and other + nice things. */ +#define AT_SYSINFO 32 +#define AT_SYSINFO_EHDR 33 + +/* Shapes of the caches. Bits 0-3 contains associativity; bits 4-7 contains + log2 of line size; mask those to get cache size. */ +#define AT_L1I_CACHESHAPE 34 +#define AT_L1D_CACHESHAPE 35 +#define AT_L2_CACHESHAPE 36 +#define AT_L3_CACHESHAPE 37 + +/* Note section contents. Each entry in the note section begins with + a header of a fixed form. */ + +typedef struct +{ + Elf32_Word n_namesz; /* Length of the note's name. */ + Elf32_Word n_descsz; /* Length of the note's descriptor. */ + Elf32_Word n_type; /* Type of the note. */ +} Elf32_Nhdr; + +typedef struct +{ + Elf64_Word n_namesz; /* Length of the note's name. */ + Elf64_Word n_descsz; /* Length of the note's descriptor. */ + Elf64_Word n_type; /* Type of the note. */ +} Elf64_Nhdr; + +/* Known names of notes. */ + +/* Solaris entries in the note section have this name. */ +#define ELF_NOTE_SOLARIS "SUNW Solaris" + +/* Note entries for GNU systems have this name. */ +#define ELF_NOTE_GNU "GNU" + + +/* Defined types of notes for Solaris. */ + +/* Value of descriptor (one word) is desired pagesize for the binary. */ +#define ELF_NOTE_PAGESIZE_HINT 1 + + +/* Defined note types for GNU systems. */ + +/* ABI information. The descriptor consists of words: + word 0: OS descriptor + word 1: major version of the ABI + word 2: minor version of the ABI + word 3: subminor version of the ABI +*/ +#define ELF_NOTE_ABI 1 + +/* Known OSes. These value can appear in word 0 of an ELF_NOTE_ABI + note section entry. */ +#define ELF_NOTE_OS_LINUX 0 +#define ELF_NOTE_OS_GNU 1 +#define ELF_NOTE_OS_SOLARIS2 2 +#define ELF_NOTE_OS_FREEBSD 3 + + +/* Move records. */ +typedef struct +{ + Elf32_Xword m_value; /* Symbol value. */ + Elf32_Word m_info; /* Size and index. */ + Elf32_Word m_poffset; /* Symbol offset. */ + Elf32_Half m_repeat; /* Repeat count. */ + Elf32_Half m_stride; /* Stride info. */ +} Elf32_Move; + +typedef struct +{ + Elf64_Xword m_value; /* Symbol value. */ + Elf64_Xword m_info; /* Size and index. */ + Elf64_Xword m_poffset; /* Symbol offset. */ + Elf64_Half m_repeat; /* Repeat count. */ + Elf64_Half m_stride; /* Stride info. */ +} Elf64_Move; + +/* Macro to construct move records. */ +#define ELF32_M_SYM(info) ((info) >> 8) +#define ELF32_M_SIZE(info) ((unsigned char) (info)) +#define ELF32_M_INFO(sym, size) (((sym) << 8) + (unsigned char) (size)) + +#define ELF64_M_SYM(info) ELF32_M_SYM (info) +#define ELF64_M_SIZE(info) ELF32_M_SIZE (info) +#define ELF64_M_INFO(sym, size) ELF32_M_INFO (sym, size) + + +/* Motorola 68k specific definitions. */ + +/* Values for Elf32_Ehdr.e_flags. */ +#define EF_CPU32 0x00810000 + +/* m68k relocs. */ + +#define R_68K_NONE 0 /* No reloc */ +#define R_68K_32 1 /* Direct 32 bit */ +#define R_68K_16 2 /* Direct 16 bit */ +#define R_68K_8 3 /* Direct 8 bit */ +#define R_68K_PC32 4 /* PC relative 32 bit */ +#define R_68K_PC16 5 /* PC relative 16 bit */ +#define R_68K_PC8 6 /* PC relative 8 bit */ +#define R_68K_GOT32 7 /* 32 bit PC relative GOT entry */ +#define R_68K_GOT16 8 /* 16 bit PC relative GOT entry */ +#define R_68K_GOT8 9 /* 8 bit PC relative GOT entry */ +#define R_68K_GOT32O 10 /* 32 bit GOT offset */ +#define R_68K_GOT16O 11 /* 16 bit GOT offset */ +#define R_68K_GOT8O 12 /* 8 bit GOT offset */ +#define R_68K_PLT32 13 /* 32 bit PC relative PLT address */ +#define R_68K_PLT16 14 /* 16 bit PC relative PLT address */ +#define R_68K_PLT8 15 /* 8 bit PC relative PLT address */ +#define R_68K_PLT32O 16 /* 32 bit PLT offset */ +#define R_68K_PLT16O 17 /* 16 bit PLT offset */ +#define R_68K_PLT8O 18 /* 8 bit PLT offset */ +#define R_68K_COPY 19 /* Copy symbol at runtime */ +#define R_68K_GLOB_DAT 20 /* Create GOT entry */ +#define R_68K_JMP_SLOT 21 /* Create PLT entry */ +#define R_68K_RELATIVE 22 /* Adjust by program base */ +/* Keep this the last entry. */ +#define R_68K_NUM 23 + +/* Intel 80386 specific definitions. */ + +/* i386 relocs. */ + +#define R_386_NONE 0 /* No reloc */ +#define R_386_32 1 /* Direct 32 bit */ +#define R_386_PC32 2 /* PC relative 32 bit */ +#define R_386_GOT32 3 /* 32 bit GOT entry */ +#define R_386_PLT32 4 /* 32 bit PLT address */ +#define R_386_COPY 5 /* Copy symbol at runtime */ +#define R_386_GLOB_DAT 6 /* Create GOT entry */ +#define R_386_JMP_SLOT 7 /* Create PLT entry */ +#define R_386_RELATIVE 8 /* Adjust by program base */ +#define R_386_GOTOFF 9 /* 32 bit offset to GOT */ +#define R_386_GOTPC 10 /* 32 bit PC relative offset to GOT */ +#define R_386_32PLT 11 +#define R_386_TLS_TPOFF 14 /* Offset in static TLS block */ +#define R_386_TLS_IE 15 /* Address of GOT entry for static TLS + block offset */ +#define R_386_TLS_GOTIE 16 /* GOT entry for static TLS block + offset */ +#define R_386_TLS_LE 17 /* Offset relative to static TLS + block */ +#define R_386_TLS_GD 18 /* Direct 32 bit for GNU version of + general dynamic thread local data */ +#define R_386_TLS_LDM 19 /* Direct 32 bit for GNU version of + local dynamic thread local data + in LE code */ +#define R_386_16 20 +#define R_386_PC16 21 +#define R_386_8 22 +#define R_386_PC8 23 +#define R_386_TLS_GD_32 24 /* Direct 32 bit for general dynamic + thread local data */ +#define R_386_TLS_GD_PUSH 25 /* Tag for pushl in GD TLS code */ +#define R_386_TLS_GD_CALL 26 /* Relocation for call to + __tls_get_addr() */ +#define R_386_TLS_GD_POP 27 /* Tag for popl in GD TLS code */ +#define R_386_TLS_LDM_32 28 /* Direct 32 bit for local dynamic + thread local data in LE code */ +#define R_386_TLS_LDM_PUSH 29 /* Tag for pushl in LDM TLS code */ +#define R_386_TLS_LDM_CALL 30 /* Relocation for call to + __tls_get_addr() in LDM code */ +#define R_386_TLS_LDM_POP 31 /* Tag for popl in LDM TLS code */ +#define R_386_TLS_LDO_32 32 /* Offset relative to TLS block */ +#define R_386_TLS_IE_32 33 /* GOT entry for negated static TLS + block offset */ +#define R_386_TLS_LE_32 34 /* Negated offset relative to static + TLS block */ +#define R_386_TLS_DTPMOD32 35 /* ID of module containing symbol */ +#define R_386_TLS_DTPOFF32 36 /* Offset in TLS block */ +#define R_386_TLS_TPOFF32 37 /* Negated offset in static TLS block */ +/* Keep this the last entry. */ +#define R_386_NUM 38 + +/* SUN SPARC specific definitions. */ + +/* Legal values for ST_TYPE subfield of st_info (symbol type). */ + +#define STT_SPARC_REGISTER 13 /* Global register reserved to app. */ + +/* Values for Elf64_Ehdr.e_flags. */ + +#define EF_SPARCV9_MM 3 +#define EF_SPARCV9_TSO 0 +#define EF_SPARCV9_PSO 1 +#define EF_SPARCV9_RMO 2 +#define EF_SPARC_LEDATA 0x800000 /* little endian data */ +#define EF_SPARC_EXT_MASK 0xFFFF00 +#define EF_SPARC_32PLUS 0x000100 /* generic V8+ features */ +#define EF_SPARC_SUN_US1 0x000200 /* Sun UltraSPARC1 extensions */ +#define EF_SPARC_HAL_R1 0x000400 /* HAL R1 extensions */ +#define EF_SPARC_SUN_US3 0x000800 /* Sun UltraSPARCIII extensions */ + +/* SPARC relocs. */ + +#define R_SPARC_NONE 0 /* No reloc */ +#define R_SPARC_8 1 /* Direct 8 bit */ +#define R_SPARC_16 2 /* Direct 16 bit */ +#define R_SPARC_32 3 /* Direct 32 bit */ +#define R_SPARC_DISP8 4 /* PC relative 8 bit */ +#define R_SPARC_DISP16 5 /* PC relative 16 bit */ +#define R_SPARC_DISP32 6 /* PC relative 32 bit */ +#define R_SPARC_WDISP30 7 /* PC relative 30 bit shifted */ +#define R_SPARC_WDISP22 8 /* PC relative 22 bit shifted */ +#define R_SPARC_HI22 9 /* High 22 bit */ +#define R_SPARC_22 10 /* Direct 22 bit */ +#define R_SPARC_13 11 /* Direct 13 bit */ +#define R_SPARC_LO10 12 /* Truncated 10 bit */ +#define R_SPARC_GOT10 13 /* Truncated 10 bit GOT entry */ +#define R_SPARC_GOT13 14 /* 13 bit GOT entry */ +#define R_SPARC_GOT22 15 /* 22 bit GOT entry shifted */ +#define R_SPARC_PC10 16 /* PC relative 10 bit truncated */ +#define R_SPARC_PC22 17 /* PC relative 22 bit shifted */ +#define R_SPARC_WPLT30 18 /* 30 bit PC relative PLT address */ +#define R_SPARC_COPY 19 /* Copy symbol at runtime */ +#define R_SPARC_GLOB_DAT 20 /* Create GOT entry */ +#define R_SPARC_JMP_SLOT 21 /* Create PLT entry */ +#define R_SPARC_RELATIVE 22 /* Adjust by program base */ +#define R_SPARC_UA32 23 /* Direct 32 bit unaligned */ + +/* Additional Sparc64 relocs. */ + +#define R_SPARC_PLT32 24 /* Direct 32 bit ref to PLT entry */ +#define R_SPARC_HIPLT22 25 /* High 22 bit PLT entry */ +#define R_SPARC_LOPLT10 26 /* Truncated 10 bit PLT entry */ +#define R_SPARC_PCPLT32 27 /* PC rel 32 bit ref to PLT entry */ +#define R_SPARC_PCPLT22 28 /* PC rel high 22 bit PLT entry */ +#define R_SPARC_PCPLT10 29 /* PC rel trunc 10 bit PLT entry */ +#define R_SPARC_10 30 /* Direct 10 bit */ +#define R_SPARC_11 31 /* Direct 11 bit */ +#define R_SPARC_64 32 /* Direct 64 bit */ +#define R_SPARC_OLO10 33 /* 10bit with secondary 13bit addend */ +#define R_SPARC_HH22 34 /* Top 22 bits of direct 64 bit */ +#define R_SPARC_HM10 35 /* High middle 10 bits of ... */ +#define R_SPARC_LM22 36 /* Low middle 22 bits of ... */ +#define R_SPARC_PC_HH22 37 /* Top 22 bits of pc rel 64 bit */ +#define R_SPARC_PC_HM10 38 /* High middle 10 bit of ... */ +#define R_SPARC_PC_LM22 39 /* Low miggle 22 bits of ... */ +#define R_SPARC_WDISP16 40 /* PC relative 16 bit shifted */ +#define R_SPARC_WDISP19 41 /* PC relative 19 bit shifted */ +#define R_SPARC_7 43 /* Direct 7 bit */ +#define R_SPARC_5 44 /* Direct 5 bit */ +#define R_SPARC_6 45 /* Direct 6 bit */ +#define R_SPARC_DISP64 46 /* PC relative 64 bit */ +#define R_SPARC_PLT64 47 /* Direct 64 bit ref to PLT entry */ +#define R_SPARC_HIX22 48 /* High 22 bit complemented */ +#define R_SPARC_LOX10 49 /* Truncated 11 bit complemented */ +#define R_SPARC_H44 50 /* Direct high 12 of 44 bit */ +#define R_SPARC_M44 51 /* Direct mid 22 of 44 bit */ +#define R_SPARC_L44 52 /* Direct low 10 of 44 bit */ +#define R_SPARC_REGISTER 53 /* Global register usage */ +#define R_SPARC_UA64 54 /* Direct 64 bit unaligned */ +#define R_SPARC_UA16 55 /* Direct 16 bit unaligned */ +#define R_SPARC_TLS_GD_HI22 56 +#define R_SPARC_TLS_GD_LO10 57 +#define R_SPARC_TLS_GD_ADD 58 +#define R_SPARC_TLS_GD_CALL 59 +#define R_SPARC_TLS_LDM_HI22 60 +#define R_SPARC_TLS_LDM_LO10 61 +#define R_SPARC_TLS_LDM_ADD 62 +#define R_SPARC_TLS_LDM_CALL 63 +#define R_SPARC_TLS_LDO_HIX22 64 +#define R_SPARC_TLS_LDO_LOX10 65 +#define R_SPARC_TLS_LDO_ADD 66 +#define R_SPARC_TLS_IE_HI22 67 +#define R_SPARC_TLS_IE_LO10 68 +#define R_SPARC_TLS_IE_LD 69 +#define R_SPARC_TLS_IE_LDX 70 +#define R_SPARC_TLS_IE_ADD 71 +#define R_SPARC_TLS_LE_HIX22 72 +#define R_SPARC_TLS_LE_LOX10 73 +#define R_SPARC_TLS_DTPMOD32 74 +#define R_SPARC_TLS_DTPMOD64 75 +#define R_SPARC_TLS_DTPOFF32 76 +#define R_SPARC_TLS_DTPOFF64 77 +#define R_SPARC_TLS_TPOFF32 78 +#define R_SPARC_TLS_TPOFF64 79 +/* Keep this the last entry. */ +#define R_SPARC_NUM 80 + +/* For Sparc64, legal values for d_tag of Elf64_Dyn. */ + +#define DT_SPARC_REGISTER 0x70000001 +#define DT_SPARC_NUM 2 + +/* Bits present in AT_HWCAP, primarily for Sparc32. */ + +#define HWCAP_SPARC_FLUSH 1 /* The cpu supports flush insn. */ +#define HWCAP_SPARC_STBAR 2 +#define HWCAP_SPARC_SWAP 4 +#define HWCAP_SPARC_MULDIV 8 +#define HWCAP_SPARC_V9 16 /* The cpu is v9, so v8plus is ok. */ +#define HWCAP_SPARC_ULTRA3 32 + +/* MIPS R3000 specific definitions. */ + +/* Legal values for e_flags field of Elf32_Ehdr. */ + +#define EF_MIPS_NOREORDER 1 /* A .noreorder directive was used */ +#define EF_MIPS_PIC 2 /* Contains PIC code */ +#define EF_MIPS_CPIC 4 /* Uses PIC calling sequence */ +#define EF_MIPS_XGOT 8 +#define EF_MIPS_64BIT_WHIRL 16 +#define EF_MIPS_ABI2 32 +#define EF_MIPS_ABI_ON32 64 +#define EF_MIPS_ARCH 0xf0000000 /* MIPS architecture level */ + +/* Legal values for MIPS architecture level. */ + +#define EF_MIPS_ARCH_1 0x00000000 /* -mips1 code. */ +#define EF_MIPS_ARCH_2 0x10000000 /* -mips2 code. */ +#define EF_MIPS_ARCH_3 0x20000000 /* -mips3 code. */ +#define EF_MIPS_ARCH_4 0x30000000 /* -mips4 code. */ +#define EF_MIPS_ARCH_5 0x40000000 /* -mips5 code. */ +#define EF_MIPS_ARCH_32 0x60000000 /* MIPS32 code. */ +#define EF_MIPS_ARCH_64 0x70000000 /* MIPS64 code. */ + +/* The following are non-official names and should not be used. */ + +#define E_MIPS_ARCH_1 0x00000000 /* -mips1 code. */ +#define E_MIPS_ARCH_2 0x10000000 /* -mips2 code. */ +#define E_MIPS_ARCH_3 0x20000000 /* -mips3 code. */ +#define E_MIPS_ARCH_4 0x30000000 /* -mips4 code. */ +#define E_MIPS_ARCH_5 0x40000000 /* -mips5 code. */ +#define E_MIPS_ARCH_32 0x60000000 /* MIPS32 code. */ +#define E_MIPS_ARCH_64 0x70000000 /* MIPS64 code. */ + +/* Special section indices. */ + +#define SHN_MIPS_ACOMMON 0xff00 /* Allocated common symbols */ +#define SHN_MIPS_TEXT 0xff01 /* Allocated test symbols. */ +#define SHN_MIPS_DATA 0xff02 /* Allocated data symbols. */ +#define SHN_MIPS_SCOMMON 0xff03 /* Small common symbols */ +#define SHN_MIPS_SUNDEFINED 0xff04 /* Small undefined symbols */ + +/* Legal values for sh_type field of Elf32_Shdr. */ + +#define SHT_MIPS_LIBLIST 0x70000000 /* Shared objects used in link */ +#define SHT_MIPS_MSYM 0x70000001 +#define SHT_MIPS_CONFLICT 0x70000002 /* Conflicting symbols */ +#define SHT_MIPS_GPTAB 0x70000003 /* Global data area sizes */ +#define SHT_MIPS_UCODE 0x70000004 /* Reserved for SGI/MIPS compilers */ +#define SHT_MIPS_DEBUG 0x70000005 /* MIPS ECOFF debugging information*/ +#define SHT_MIPS_REGINFO 0x70000006 /* Register usage information */ +#define SHT_MIPS_PACKAGE 0x70000007 +#define SHT_MIPS_PACKSYM 0x70000008 +#define SHT_MIPS_RELD 0x70000009 +#define SHT_MIPS_IFACE 0x7000000b +#define SHT_MIPS_CONTENT 0x7000000c +#define SHT_MIPS_OPTIONS 0x7000000d /* Miscellaneous options. */ +#define SHT_MIPS_SHDR 0x70000010 +#define SHT_MIPS_FDESC 0x70000011 +#define SHT_MIPS_EXTSYM 0x70000012 +#define SHT_MIPS_DENSE 0x70000013 +#define SHT_MIPS_PDESC 0x70000014 +#define SHT_MIPS_LOCSYM 0x70000015 +#define SHT_MIPS_AUXSYM 0x70000016 +#define SHT_MIPS_OPTSYM 0x70000017 +#define SHT_MIPS_LOCSTR 0x70000018 +#define SHT_MIPS_LINE 0x70000019 +#define SHT_MIPS_RFDESC 0x7000001a +#define SHT_MIPS_DELTASYM 0x7000001b +#define SHT_MIPS_DELTAINST 0x7000001c +#define SHT_MIPS_DELTACLASS 0x7000001d +#define SHT_MIPS_DWARF 0x7000001e /* DWARF debugging information. */ +#define SHT_MIPS_DELTADECL 0x7000001f +#define SHT_MIPS_SYMBOL_LIB 0x70000020 +#define SHT_MIPS_EVENTS 0x70000021 /* Event section. */ +#define SHT_MIPS_TRANSLATE 0x70000022 +#define SHT_MIPS_PIXIE 0x70000023 +#define SHT_MIPS_XLATE 0x70000024 +#define SHT_MIPS_XLATE_DEBUG 0x70000025 +#define SHT_MIPS_WHIRL 0x70000026 +#define SHT_MIPS_EH_REGION 0x70000027 +#define SHT_MIPS_XLATE_OLD 0x70000028 +#define SHT_MIPS_PDR_EXCEPTION 0x70000029 + +/* Legal values for sh_flags field of Elf32_Shdr. */ + +#define SHF_MIPS_GPREL 0x10000000 /* Must be part of global data area */ +#define SHF_MIPS_MERGE 0x20000000 +#define SHF_MIPS_ADDR 0x40000000 +#define SHF_MIPS_STRINGS 0x80000000 +#define SHF_MIPS_NOSTRIP 0x08000000 +#define SHF_MIPS_LOCAL 0x04000000 +#define SHF_MIPS_NAMES 0x02000000 +#define SHF_MIPS_NODUPE 0x01000000 + + +/* Symbol tables. */ + +/* MIPS specific values for `st_other'. */ +#define STO_MIPS_DEFAULT 0x0 +#define STO_MIPS_INTERNAL 0x1 +#define STO_MIPS_HIDDEN 0x2 +#define STO_MIPS_PROTECTED 0x3 +#define STO_MIPS_SC_ALIGN_UNUSED 0xff + +/* MIPS specific values for `st_info'. */ +#define STB_MIPS_SPLIT_COMMON 13 + +/* Entries found in sections of type SHT_MIPS_GPTAB. */ + +typedef union +{ + struct + { + Elf32_Word gt_current_g_value; /* -G value used for compilation */ + Elf32_Word gt_unused; /* Not used */ + } gt_header; /* First entry in section */ + struct + { + Elf32_Word gt_g_value; /* If this value were used for -G */ + Elf32_Word gt_bytes; /* This many bytes would be used */ + } gt_entry; /* Subsequent entries in section */ +} Elf32_gptab; + +/* Entry found in sections of type SHT_MIPS_REGINFO. */ + +typedef struct +{ + Elf32_Word ri_gprmask; /* General registers used */ + Elf32_Word ri_cprmask[4]; /* Coprocessor registers used */ + Elf32_Sword ri_gp_value; /* $gp register value */ +} Elf32_RegInfo; + +/* Entries found in sections of type SHT_MIPS_OPTIONS. */ + +typedef struct +{ + unsigned char kind; /* Determines interpretation of the + variable part of descriptor. */ + unsigned char size; /* Size of descriptor, including header. */ + Elf32_Section section; /* Section header index of section affected, + 0 for global options. */ + Elf32_Word info; /* Kind-specific information. */ +} Elf_Options; + +/* Values for `kind' field in Elf_Options. */ + +#define ODK_NULL 0 /* Undefined. */ +#define ODK_REGINFO 1 /* Register usage information. */ +#define ODK_EXCEPTIONS 2 /* Exception processing options. */ +#define ODK_PAD 3 /* Section padding options. */ +#define ODK_HWPATCH 4 /* Hardware workarounds performed */ +#define ODK_FILL 5 /* record the fill value used by the linker. */ +#define ODK_TAGS 6 /* reserve space for desktop tools to write. */ +#define ODK_HWAND 7 /* HW workarounds. 'AND' bits when merging. */ +#define ODK_HWOR 8 /* HW workarounds. 'OR' bits when merging. */ + +/* Values for `info' in Elf_Options for ODK_EXCEPTIONS entries. */ + +#define OEX_FPU_MIN 0x1f /* FPE's which MUST be enabled. */ +#define OEX_FPU_MAX 0x1f00 /* FPE's which MAY be enabled. */ +#define OEX_PAGE0 0x10000 /* page zero must be mapped. */ +#define OEX_SMM 0x20000 /* Force sequential memory mode? */ +#define OEX_FPDBUG 0x40000 /* Force floating point debug mode? */ +#define OEX_PRECISEFP OEX_FPDBUG +#define OEX_DISMISS 0x80000 /* Dismiss invalid address faults? */ + +#define OEX_FPU_INVAL 0x10 +#define OEX_FPU_DIV0 0x08 +#define OEX_FPU_OFLO 0x04 +#define OEX_FPU_UFLO 0x02 +#define OEX_FPU_INEX 0x01 + +/* Masks for `info' in Elf_Options for an ODK_HWPATCH entry. */ + +#define OHW_R4KEOP 0x1 /* R4000 end-of-page patch. */ +#define OHW_R8KPFETCH 0x2 /* may need R8000 prefetch patch. */ +#define OHW_R5KEOP 0x4 /* R5000 end-of-page patch. */ +#define OHW_R5KCVTL 0x8 /* R5000 cvt.[ds].l bug. clean=1. */ + +#define OPAD_PREFIX 0x1 +#define OPAD_POSTFIX 0x2 +#define OPAD_SYMBOL 0x4 + +/* Entry found in `.options' section. */ + +typedef struct +{ + Elf32_Word hwp_flags1; /* Extra flags. */ + Elf32_Word hwp_flags2; /* Extra flags. */ +} Elf_Options_Hw; + +/* Masks for `info' in ElfOptions for ODK_HWAND and ODK_HWOR entries. */ + +#define OHWA0_R4KEOP_CHECKED 0x00000001 +#define OHWA1_R4KEOP_CLEAN 0x00000002 + +/* MIPS relocs. */ + +#define R_MIPS_NONE 0 /* No reloc */ +#define R_MIPS_16 1 /* Direct 16 bit */ +#define R_MIPS_32 2 /* Direct 32 bit */ +#define R_MIPS_REL32 3 /* PC relative 32 bit */ +#define R_MIPS_26 4 /* Direct 26 bit shifted */ +#define R_MIPS_HI16 5 /* High 16 bit */ +#define R_MIPS_LO16 6 /* Low 16 bit */ +#define R_MIPS_GPREL16 7 /* GP relative 16 bit */ +#define R_MIPS_LITERAL 8 /* 16 bit literal entry */ +#define R_MIPS_GOT16 9 /* 16 bit GOT entry */ +#define R_MIPS_PC16 10 /* PC relative 16 bit */ +#define R_MIPS_CALL16 11 /* 16 bit GOT entry for function */ +#define R_MIPS_GPREL32 12 /* GP relative 32 bit */ + +#define R_MIPS_SHIFT5 16 +#define R_MIPS_SHIFT6 17 +#define R_MIPS_64 18 +#define R_MIPS_GOT_DISP 19 +#define R_MIPS_GOT_PAGE 20 +#define R_MIPS_GOT_OFST 21 +#define R_MIPS_GOT_HI16 22 +#define R_MIPS_GOT_LO16 23 +#define R_MIPS_SUB 24 +#define R_MIPS_INSERT_A 25 +#define R_MIPS_INSERT_B 26 +#define R_MIPS_DELETE 27 +#define R_MIPS_HIGHER 28 +#define R_MIPS_HIGHEST 29 +#define R_MIPS_CALL_HI16 30 +#define R_MIPS_CALL_LO16 31 +#define R_MIPS_SCN_DISP 32 +#define R_MIPS_REL16 33 +#define R_MIPS_ADD_IMMEDIATE 34 +#define R_MIPS_PJUMP 35 +#define R_MIPS_RELGOT 36 +#define R_MIPS_JALR 37 +/* Keep this the last entry. */ +#define R_MIPS_NUM 38 + +/* Legal values for p_type field of Elf32_Phdr. */ + +#define PT_MIPS_REGINFO 0x70000000 /* Register usage information */ +#define PT_MIPS_RTPROC 0x70000001 /* Runtime procedure table. */ +#define PT_MIPS_OPTIONS 0x70000002 + +/* Special program header types. */ + +#define PF_MIPS_LOCAL 0x10000000 + +/* Legal values for d_tag field of Elf32_Dyn. */ + +#define DT_MIPS_RLD_VERSION 0x70000001 /* Runtime linker interface version */ +#define DT_MIPS_TIME_STAMP 0x70000002 /* Timestamp */ +#define DT_MIPS_ICHECKSUM 0x70000003 /* Checksum */ +#define DT_MIPS_IVERSION 0x70000004 /* Version string (string tbl index) */ +#define DT_MIPS_FLAGS 0x70000005 /* Flags */ +#define DT_MIPS_BASE_ADDRESS 0x70000006 /* Base address */ +#define DT_MIPS_MSYM 0x70000007 +#define DT_MIPS_CONFLICT 0x70000008 /* Address of CONFLICT section */ +#define DT_MIPS_LIBLIST 0x70000009 /* Address of LIBLIST section */ +#define DT_MIPS_LOCAL_GOTNO 0x7000000a /* Number of local GOT entries */ +#define DT_MIPS_CONFLICTNO 0x7000000b /* Number of CONFLICT entries */ +#define DT_MIPS_LIBLISTNO 0x70000010 /* Number of LIBLIST entries */ +#define DT_MIPS_SYMTABNO 0x70000011 /* Number of DYNSYM entries */ +#define DT_MIPS_UNREFEXTNO 0x70000012 /* First external DYNSYM */ +#define DT_MIPS_GOTSYM 0x70000013 /* First GOT entry in DYNSYM */ +#define DT_MIPS_HIPAGENO 0x70000014 /* Number of GOT page table entries */ +#define DT_MIPS_RLD_MAP 0x70000016 /* Address of run time loader map. */ +#define DT_MIPS_DELTA_CLASS 0x70000017 /* Delta C++ class definition. */ +#define DT_MIPS_DELTA_CLASS_NO 0x70000018 /* Number of entries in + DT_MIPS_DELTA_CLASS. */ +#define DT_MIPS_DELTA_INSTANCE 0x70000019 /* Delta C++ class instances. */ +#define DT_MIPS_DELTA_INSTANCE_NO 0x7000001a /* Number of entries in + DT_MIPS_DELTA_INSTANCE. */ +#define DT_MIPS_DELTA_RELOC 0x7000001b /* Delta relocations. */ +#define DT_MIPS_DELTA_RELOC_NO 0x7000001c /* Number of entries in + DT_MIPS_DELTA_RELOC. */ +#define DT_MIPS_DELTA_SYM 0x7000001d /* Delta symbols that Delta + relocations refer to. */ +#define DT_MIPS_DELTA_SYM_NO 0x7000001e /* Number of entries in + DT_MIPS_DELTA_SYM. */ +#define DT_MIPS_DELTA_CLASSSYM 0x70000020 /* Delta symbols that hold the + class declaration. */ +#define DT_MIPS_DELTA_CLASSSYM_NO 0x70000021 /* Number of entries in + DT_MIPS_DELTA_CLASSSYM. */ +#define DT_MIPS_CXX_FLAGS 0x70000022 /* Flags indicating for C++ flavor. */ +#define DT_MIPS_PIXIE_INIT 0x70000023 +#define DT_MIPS_SYMBOL_LIB 0x70000024 +#define DT_MIPS_LOCALPAGE_GOTIDX 0x70000025 +#define DT_MIPS_LOCAL_GOTIDX 0x70000026 +#define DT_MIPS_HIDDEN_GOTIDX 0x70000027 +#define DT_MIPS_PROTECTED_GOTIDX 0x70000028 +#define DT_MIPS_OPTIONS 0x70000029 /* Address of .options. */ +#define DT_MIPS_INTERFACE 0x7000002a /* Address of .interface. */ +#define DT_MIPS_DYNSTR_ALIGN 0x7000002b +#define DT_MIPS_INTERFACE_SIZE 0x7000002c /* Size of the .interface section. */ +#define DT_MIPS_RLD_TEXT_RESOLVE_ADDR 0x7000002d /* Address of rld_text_rsolve + function stored in GOT. */ +#define DT_MIPS_PERF_SUFFIX 0x7000002e /* Default suffix of dso to be added + by rld on dlopen() calls. */ +#define DT_MIPS_COMPACT_SIZE 0x7000002f /* (O32)Size of compact rel section. */ +#define DT_MIPS_GP_VALUE 0x70000030 /* GP value for aux GOTs. */ +#define DT_MIPS_AUX_DYNAMIC 0x70000031 /* Address of aux .dynamic. */ +#define DT_MIPS_NUM 0x32 + +/* Legal values for DT_MIPS_FLAGS Elf32_Dyn entry. */ + +#define RHF_NONE 0 /* No flags */ +#define RHF_QUICKSTART (1 << 0) /* Use quickstart */ +#define RHF_NOTPOT (1 << 1) /* Hash size not power of 2 */ +#define RHF_NO_LIBRARY_REPLACEMENT (1 << 2) /* Ignore LD_LIBRARY_PATH */ +#define RHF_NO_MOVE (1 << 3) +#define RHF_SGI_ONLY (1 << 4) +#define RHF_GUARANTEE_INIT (1 << 5) +#define RHF_DELTA_C_PLUS_PLUS (1 << 6) +#define RHF_GUARANTEE_START_INIT (1 << 7) +#define RHF_PIXIE (1 << 8) +#define RHF_DEFAULT_DELAY_LOAD (1 << 9) +#define RHF_REQUICKSTART (1 << 10) +#define RHF_REQUICKSTARTED (1 << 11) +#define RHF_CORD (1 << 12) +#define RHF_NO_UNRES_UNDEF (1 << 13) +#define RHF_RLD_ORDER_SAFE (1 << 14) + +/* Entries found in sections of type SHT_MIPS_LIBLIST. */ + +typedef struct +{ + Elf32_Word l_name; /* Name (string table index) */ + Elf32_Word l_time_stamp; /* Timestamp */ + Elf32_Word l_checksum; /* Checksum */ + Elf32_Word l_version; /* Interface version */ + Elf32_Word l_flags; /* Flags */ +} Elf32_Lib; + +typedef struct +{ + Elf64_Word l_name; /* Name (string table index) */ + Elf64_Word l_time_stamp; /* Timestamp */ + Elf64_Word l_checksum; /* Checksum */ + Elf64_Word l_version; /* Interface version */ + Elf64_Word l_flags; /* Flags */ +} Elf64_Lib; + + +/* Legal values for l_flags. */ + +#define LL_NONE 0 +#define LL_EXACT_MATCH (1 << 0) /* Require exact match */ +#define LL_IGNORE_INT_VER (1 << 1) /* Ignore interface version */ +#define LL_REQUIRE_MINOR (1 << 2) +#define LL_EXPORTS (1 << 3) +#define LL_DELAY_LOAD (1 << 4) +#define LL_DELTA (1 << 5) + +/* Entries found in sections of type SHT_MIPS_CONFLICT. */ + +typedef Elf32_Addr Elf32_Conflict; + + +/* HPPA specific definitions. */ + +/* Legal values for e_flags field of Elf32_Ehdr. */ + +#define EF_PARISC_TRAPNIL 0x00010000 /* Trap nil pointer dereference. */ +#define EF_PARISC_EXT 0x00020000 /* Program uses arch. extensions. */ +#define EF_PARISC_LSB 0x00040000 /* Program expects little endian. */ +#define EF_PARISC_WIDE 0x00080000 /* Program expects wide mode. */ +#define EF_PARISC_NO_KABP 0x00100000 /* No kernel assisted branch + prediction. */ +#define EF_PARISC_LAZYSWAP 0x00400000 /* Allow lazy swapping. */ +#define EF_PARISC_ARCH 0x0000ffff /* Architecture version. */ + +/* Defined values for `e_flags & EF_PARISC_ARCH' are: */ + +#define EFA_PARISC_1_0 0x020b /* PA-RISC 1.0 big-endian. */ +#define EFA_PARISC_1_1 0x0210 /* PA-RISC 1.1 big-endian. */ +#define EFA_PARISC_2_0 0x0214 /* PA-RISC 2.0 big-endian. */ + +/* Additional section indeces. */ + +#define SHN_PARISC_ANSI_COMMON 0xff00 /* Section for tenatively declared + symbols in ANSI C. */ +#define SHN_PARISC_HUGE_COMMON 0xff01 /* Common blocks in huge model. */ + +/* Legal values for sh_type field of Elf32_Shdr. */ + +#define SHT_PARISC_EXT 0x70000000 /* Contains product specific ext. */ +#define SHT_PARISC_UNWIND 0x70000001 /* Unwind information. */ +#define SHT_PARISC_DOC 0x70000002 /* Debug info for optimized code. */ + +/* Legal values for sh_flags field of Elf32_Shdr. */ + +#define SHF_PARISC_SHORT 0x20000000 /* Section with short addressing. */ +#define SHF_PARISC_HUGE 0x40000000 /* Section far from gp. */ +#define SHF_PARISC_SBP 0x80000000 /* Static branch prediction code. */ + +/* Legal values for ST_TYPE subfield of st_info (symbol type). */ + +#define STT_PARISC_MILLICODE 13 /* Millicode function entry point. */ + +#define STT_HP_OPAQUE (STT_LOOS + 0x1) +#define STT_HP_STUB (STT_LOOS + 0x2) + +/* HPPA relocs. */ + +#define R_PARISC_NONE 0 /* No reloc. */ +#define R_PARISC_DIR32 1 /* Direct 32-bit reference. */ +#define R_PARISC_DIR21L 2 /* Left 21 bits of eff. address. */ +#define R_PARISC_DIR17R 3 /* Right 17 bits of eff. address. */ +#define R_PARISC_DIR17F 4 /* 17 bits of eff. address. */ +#define R_PARISC_DIR14R 6 /* Right 14 bits of eff. address. */ +#define R_PARISC_PCREL32 9 /* 32-bit rel. address. */ +#define R_PARISC_PCREL21L 10 /* Left 21 bits of rel. address. */ +#define R_PARISC_PCREL17R 11 /* Right 17 bits of rel. address. */ +#define R_PARISC_PCREL17F 12 /* 17 bits of rel. address. */ +#define R_PARISC_PCREL14R 14 /* Right 14 bits of rel. address. */ +#define R_PARISC_DPREL21L 18 /* Left 21 bits of rel. address. */ +#define R_PARISC_DPREL14R 22 /* Right 14 bits of rel. address. */ +#define R_PARISC_GPREL21L 26 /* GP-relative, left 21 bits. */ +#define R_PARISC_GPREL14R 30 /* GP-relative, right 14 bits. */ +#define R_PARISC_LTOFF21L 34 /* LT-relative, left 21 bits. */ +#define R_PARISC_LTOFF14R 38 /* LT-relative, right 14 bits. */ +#define R_PARISC_SECREL32 41 /* 32 bits section rel. address. */ +#define R_PARISC_SEGBASE 48 /* No relocation, set segment base. */ +#define R_PARISC_SEGREL32 49 /* 32 bits segment rel. address. */ +#define R_PARISC_PLTOFF21L 50 /* PLT rel. address, left 21 bits. */ +#define R_PARISC_PLTOFF14R 54 /* PLT rel. address, right 14 bits. */ +#define R_PARISC_LTOFF_FPTR32 57 /* 32 bits LT-rel. function pointer. */ +#define R_PARISC_LTOFF_FPTR21L 58 /* LT-rel. fct ptr, left 21 bits. */ +#define R_PARISC_LTOFF_FPTR14R 62 /* LT-rel. fct ptr, right 14 bits. */ +#define R_PARISC_FPTR64 64 /* 64 bits function address. */ +#define R_PARISC_PLABEL32 65 /* 32 bits function address. */ +#define R_PARISC_PCREL64 72 /* 64 bits PC-rel. address. */ +#define R_PARISC_PCREL22F 74 /* 22 bits PC-rel. address. */ +#define R_PARISC_PCREL14WR 75 /* PC-rel. address, right 14 bits. */ +#define R_PARISC_PCREL14DR 76 /* PC rel. address, right 14 bits. */ +#define R_PARISC_PCREL16F 77 /* 16 bits PC-rel. address. */ +#define R_PARISC_PCREL16WF 78 /* 16 bits PC-rel. address. */ +#define R_PARISC_PCREL16DF 79 /* 16 bits PC-rel. address. */ +#define R_PARISC_DIR64 80 /* 64 bits of eff. address. */ +#define R_PARISC_DIR14WR 83 /* 14 bits of eff. address. */ +#define R_PARISC_DIR14DR 84 /* 14 bits of eff. address. */ +#define R_PARISC_DIR16F 85 /* 16 bits of eff. address. */ +#define R_PARISC_DIR16WF 86 /* 16 bits of eff. address. */ +#define R_PARISC_DIR16DF 87 /* 16 bits of eff. address. */ +#define R_PARISC_GPREL64 88 /* 64 bits of GP-rel. address. */ +#define R_PARISC_GPREL14WR 91 /* GP-rel. address, right 14 bits. */ +#define R_PARISC_GPREL14DR 92 /* GP-rel. address, right 14 bits. */ +#define R_PARISC_GPREL16F 93 /* 16 bits GP-rel. address. */ +#define R_PARISC_GPREL16WF 94 /* 16 bits GP-rel. address. */ +#define R_PARISC_GPREL16DF 95 /* 16 bits GP-rel. address. */ +#define R_PARISC_LTOFF64 96 /* 64 bits LT-rel. address. */ +#define R_PARISC_LTOFF14WR 99 /* LT-rel. address, right 14 bits. */ +#define R_PARISC_LTOFF14DR 100 /* LT-rel. address, right 14 bits. */ +#define R_PARISC_LTOFF16F 101 /* 16 bits LT-rel. address. */ +#define R_PARISC_LTOFF16WF 102 /* 16 bits LT-rel. address. */ +#define R_PARISC_LTOFF16DF 103 /* 16 bits LT-rel. address. */ +#define R_PARISC_SECREL64 104 /* 64 bits section rel. address. */ +#define R_PARISC_SEGREL64 112 /* 64 bits segment rel. address. */ +#define R_PARISC_PLTOFF14WR 115 /* PLT-rel. address, right 14 bits. */ +#define R_PARISC_PLTOFF14DR 116 /* PLT-rel. address, right 14 bits. */ +#define R_PARISC_PLTOFF16F 117 /* 16 bits LT-rel. address. */ +#define R_PARISC_PLTOFF16WF 118 /* 16 bits PLT-rel. address. */ +#define R_PARISC_PLTOFF16DF 119 /* 16 bits PLT-rel. address. */ +#define R_PARISC_LTOFF_FPTR64 120 /* 64 bits LT-rel. function ptr. */ +#define R_PARISC_LTOFF_FPTR14WR 123 /* LT-rel. fct. ptr., right 14 bits. */ +#define R_PARISC_LTOFF_FPTR14DR 124 /* LT-rel. fct. ptr., right 14 bits. */ +#define R_PARISC_LTOFF_FPTR16F 125 /* 16 bits LT-rel. function ptr. */ +#define R_PARISC_LTOFF_FPTR16WF 126 /* 16 bits LT-rel. function ptr. */ +#define R_PARISC_LTOFF_FPTR16DF 127 /* 16 bits LT-rel. function ptr. */ +#define R_PARISC_LORESERVE 128 +#define R_PARISC_COPY 128 /* Copy relocation. */ +#define R_PARISC_IPLT 129 /* Dynamic reloc, imported PLT */ +#define R_PARISC_EPLT 130 /* Dynamic reloc, exported PLT */ +#define R_PARISC_TPREL32 153 /* 32 bits TP-rel. address. */ +#define R_PARISC_TPREL21L 154 /* TP-rel. address, left 21 bits. */ +#define R_PARISC_TPREL14R 158 /* TP-rel. address, right 14 bits. */ +#define R_PARISC_LTOFF_TP21L 162 /* LT-TP-rel. address, left 21 bits. */ +#define R_PARISC_LTOFF_TP14R 166 /* LT-TP-rel. address, right 14 bits.*/ +#define R_PARISC_LTOFF_TP14F 167 /* 14 bits LT-TP-rel. address. */ +#define R_PARISC_TPREL64 216 /* 64 bits TP-rel. address. */ +#define R_PARISC_TPREL14WR 219 /* TP-rel. address, right 14 bits. */ +#define R_PARISC_TPREL14DR 220 /* TP-rel. address, right 14 bits. */ +#define R_PARISC_TPREL16F 221 /* 16 bits TP-rel. address. */ +#define R_PARISC_TPREL16WF 222 /* 16 bits TP-rel. address. */ +#define R_PARISC_TPREL16DF 223 /* 16 bits TP-rel. address. */ +#define R_PARISC_LTOFF_TP64 224 /* 64 bits LT-TP-rel. address. */ +#define R_PARISC_LTOFF_TP14WR 227 /* LT-TP-rel. address, right 14 bits.*/ +#define R_PARISC_LTOFF_TP14DR 228 /* LT-TP-rel. address, right 14 bits.*/ +#define R_PARISC_LTOFF_TP16F 229 /* 16 bits LT-TP-rel. address. */ +#define R_PARISC_LTOFF_TP16WF 230 /* 16 bits LT-TP-rel. address. */ +#define R_PARISC_LTOFF_TP16DF 231 /* 16 bits LT-TP-rel. address. */ +#define R_PARISC_HIRESERVE 255 + +/* Legal values for p_type field of Elf32_Phdr/Elf64_Phdr. */ + +#define PT_HP_TLS (PT_LOOS + 0x0) +#define PT_HP_CORE_NONE (PT_LOOS + 0x1) +#define PT_HP_CORE_VERSION (PT_LOOS + 0x2) +#define PT_HP_CORE_KERNEL (PT_LOOS + 0x3) +#define PT_HP_CORE_COMM (PT_LOOS + 0x4) +#define PT_HP_CORE_PROC (PT_LOOS + 0x5) +#define PT_HP_CORE_LOADABLE (PT_LOOS + 0x6) +#define PT_HP_CORE_STACK (PT_LOOS + 0x7) +#define PT_HP_CORE_SHM (PT_LOOS + 0x8) +#define PT_HP_CORE_MMF (PT_LOOS + 0x9) +#define PT_HP_PARALLEL (PT_LOOS + 0x10) +#define PT_HP_FASTBIND (PT_LOOS + 0x11) +#define PT_HP_OPT_ANNOT (PT_LOOS + 0x12) +#define PT_HP_HSL_ANNOT (PT_LOOS + 0x13) +#define PT_HP_STACK (PT_LOOS + 0x14) + +#define PT_PARISC_ARCHEXT 0x70000000 +#define PT_PARISC_UNWIND 0x70000001 + +/* Legal values for p_flags field of Elf32_Phdr/Elf64_Phdr. */ + +#define PF_PARISC_SBP 0x08000000 + +#define PF_HP_PAGE_SIZE 0x00100000 +#define PF_HP_FAR_SHARED 0x00200000 +#define PF_HP_NEAR_SHARED 0x00400000 +#define PF_HP_CODE 0x01000000 +#define PF_HP_MODIFY 0x02000000 +#define PF_HP_LAZYSWAP 0x04000000 +#define PF_HP_SBP 0x08000000 + + +/* Alpha specific definitions. */ + +/* Legal values for e_flags field of Elf64_Ehdr. */ + +#define EF_ALPHA_32BIT 1 /* All addresses must be < 2GB. */ +#define EF_ALPHA_CANRELAX 2 /* Relocations for relaxing exist. */ + +/* Legal values for sh_type field of Elf64_Shdr. */ + +/* These two are primerily concerned with ECOFF debugging info. */ +#define SHT_ALPHA_DEBUG 0x70000001 +#define SHT_ALPHA_REGINFO 0x70000002 + +/* Legal values for sh_flags field of Elf64_Shdr. */ + +#define SHF_ALPHA_GPREL 0x10000000 + +/* Legal values for st_other field of Elf64_Sym. */ +#define STO_ALPHA_NOPV 0x80 /* No PV required. */ +#define STO_ALPHA_STD_GPLOAD 0x88 /* PV only used for initial ldgp. */ + +/* Alpha relocs. */ + +#define R_ALPHA_NONE 0 /* No reloc */ +#define R_ALPHA_REFLONG 1 /* Direct 32 bit */ +#define R_ALPHA_REFQUAD 2 /* Direct 64 bit */ +#define R_ALPHA_GPREL32 3 /* GP relative 32 bit */ +#define R_ALPHA_LITERAL 4 /* GP relative 16 bit w/optimization */ +#define R_ALPHA_LITUSE 5 /* Optimization hint for LITERAL */ +#define R_ALPHA_GPDISP 6 /* Add displacement to GP */ +#define R_ALPHA_BRADDR 7 /* PC+4 relative 23 bit shifted */ +#define R_ALPHA_HINT 8 /* PC+4 relative 16 bit shifted */ +#define R_ALPHA_SREL16 9 /* PC relative 16 bit */ +#define R_ALPHA_SREL32 10 /* PC relative 32 bit */ +#define R_ALPHA_SREL64 11 /* PC relative 64 bit */ +#define R_ALPHA_GPRELHIGH 17 /* GP relative 32 bit, high 16 bits */ +#define R_ALPHA_GPRELLOW 18 /* GP relative 32 bit, low 16 bits */ +#define R_ALPHA_GPREL16 19 /* GP relative 16 bit */ +#define R_ALPHA_COPY 24 /* Copy symbol at runtime */ +#define R_ALPHA_GLOB_DAT 25 /* Create GOT entry */ +#define R_ALPHA_JMP_SLOT 26 /* Create PLT entry */ +#define R_ALPHA_RELATIVE 27 /* Adjust by program base */ +#define R_ALPHA_TLS_GD_HI 28 +#define R_ALPHA_TLSGD 29 +#define R_ALPHA_TLS_LDM 30 +#define R_ALPHA_DTPMOD64 31 +#define R_ALPHA_GOTDTPREL 32 +#define R_ALPHA_DTPREL64 33 +#define R_ALPHA_DTPRELHI 34 +#define R_ALPHA_DTPRELLO 35 +#define R_ALPHA_DTPREL16 36 +#define R_ALPHA_GOTTPREL 37 +#define R_ALPHA_TPREL64 38 +#define R_ALPHA_TPRELHI 39 +#define R_ALPHA_TPRELLO 40 +#define R_ALPHA_TPREL16 41 +/* Keep this the last entry. */ +#define R_ALPHA_NUM 46 + +/* Magic values of the LITUSE relocation addend. */ +#define LITUSE_ALPHA_ADDR 0 +#define LITUSE_ALPHA_BASE 1 +#define LITUSE_ALPHA_BYTOFF 2 +#define LITUSE_ALPHA_JSR 3 +#define LITUSE_ALPHA_TLS_GD 4 +#define LITUSE_ALPHA_TLS_LDM 5 + + +/* PowerPC specific declarations */ + +/* Values for Elf32/64_Ehdr.e_flags. */ +#define EF_PPC_EMB 0x80000000 /* PowerPC embedded flag */ + +/* Cygnus local bits below */ +#define EF_PPC_RELOCATABLE 0x00010000 /* PowerPC -mrelocatable flag*/ +#define EF_PPC_RELOCATABLE_LIB 0x00008000 /* PowerPC -mrelocatable-lib + flag */ + +/* PowerPC relocations defined by the ABIs */ +#define R_PPC_NONE 0 +#define R_PPC_ADDR32 1 /* 32bit absolute address */ +#define R_PPC_ADDR24 2 /* 26bit address, 2 bits ignored. */ +#define R_PPC_ADDR16 3 /* 16bit absolute address */ +#define R_PPC_ADDR16_LO 4 /* lower 16bit of absolute address */ +#define R_PPC_ADDR16_HI 5 /* high 16bit of absolute address */ +#define R_PPC_ADDR16_HA 6 /* adjusted high 16bit */ +#define R_PPC_ADDR14 7 /* 16bit address, 2 bits ignored */ +#define R_PPC_ADDR14_BRTAKEN 8 +#define R_PPC_ADDR14_BRNTAKEN 9 +#define R_PPC_REL24 10 /* PC relative 26 bit */ +#define R_PPC_REL14 11 /* PC relative 16 bit */ +#define R_PPC_REL14_BRTAKEN 12 +#define R_PPC_REL14_BRNTAKEN 13 +#define R_PPC_GOT16 14 +#define R_PPC_GOT16_LO 15 +#define R_PPC_GOT16_HI 16 +#define R_PPC_GOT16_HA 17 +#define R_PPC_PLTREL24 18 +#define R_PPC_COPY 19 +#define R_PPC_GLOB_DAT 20 +#define R_PPC_JMP_SLOT 21 +#define R_PPC_RELATIVE 22 +#define R_PPC_LOCAL24PC 23 +#define R_PPC_UADDR32 24 +#define R_PPC_UADDR16 25 +#define R_PPC_REL32 26 +#define R_PPC_PLT32 27 +#define R_PPC_PLTREL32 28 +#define R_PPC_PLT16_LO 29 +#define R_PPC_PLT16_HI 30 +#define R_PPC_PLT16_HA 31 +#define R_PPC_SDAREL16 32 +#define R_PPC_SECTOFF 33 +#define R_PPC_SECTOFF_LO 34 +#define R_PPC_SECTOFF_HI 35 +#define R_PPC_SECTOFF_HA 36 + +/* PowerPC relocations defined for the TLS access ABI. */ +#define R_PPC_TLS 67 /* none (sym+add)@tls */ +#define R_PPC_DTPMOD32 68 /* word32 (sym+add)@dtpmod */ +#define R_PPC_TPREL16 69 /* half16* (sym+add)@tprel */ +#define R_PPC_TPREL16_LO 70 /* half16 (sym+add)@tprel@l */ +#define R_PPC_TPREL16_HI 71 /* half16 (sym+add)@tprel@h */ +#define R_PPC_TPREL16_HA 72 /* half16 (sym+add)@tprel@ha */ +#define R_PPC_TPREL32 73 /* word32 (sym+add)@tprel */ +#define R_PPC_DTPREL16 74 /* half16* (sym+add)@dtprel */ +#define R_PPC_DTPREL16_LO 75 /* half16 (sym+add)@dtprel@l */ +#define R_PPC_DTPREL16_HI 76 /* half16 (sym+add)@dtprel@h */ +#define R_PPC_DTPREL16_HA 77 /* half16 (sym+add)@dtprel@ha */ +#define R_PPC_DTPREL32 78 /* word32 (sym+add)@dtprel */ +#define R_PPC_GOT_TLSGD16 79 /* half16* (sym+add)@got@tlsgd */ +#define R_PPC_GOT_TLSGD16_LO 80 /* half16 (sym+add)@got@tlsgd@l */ +#define R_PPC_GOT_TLSGD16_HI 81 /* half16 (sym+add)@got@tlsgd@h */ +#define R_PPC_GOT_TLSGD16_HA 82 /* half16 (sym+add)@got@tlsgd@ha */ +#define R_PPC_GOT_TLSLD16 83 /* half16* (sym+add)@got@tlsld */ +#define R_PPC_GOT_TLSLD16_LO 84 /* half16 (sym+add)@got@tlsld@l */ +#define R_PPC_GOT_TLSLD16_HI 85 /* half16 (sym+add)@got@tlsld@h */ +#define R_PPC_GOT_TLSLD16_HA 86 /* half16 (sym+add)@got@tlsld@ha */ +#define R_PPC_GOT_TPREL16 87 /* half16* (sym+add)@got@tprel */ +#define R_PPC_GOT_TPREL16_LO 88 /* half16 (sym+add)@got@tprel@l */ +#define R_PPC_GOT_TPREL16_HI 89 /* half16 (sym+add)@got@tprel@h */ +#define R_PPC_GOT_TPREL16_HA 90 /* half16 (sym+add)@got@tprel@ha */ +#define R_PPC_GOT_DTPREL16 91 /* half16* (sym+add)@got@dtprel */ +#define R_PPC_GOT_DTPREL16_LO 92 /* half16* (sym+add)@got@dtprel@l */ +#define R_PPC_GOT_DTPREL16_HI 93 /* half16* (sym+add)@got@dtprel@h */ +#define R_PPC_GOT_DTPREL16_HA 94 /* half16* (sym+add)@got@dtprel@ha */ + +/* Keep this the last entry. */ +#define R_PPC_NUM 95 + +/* The remaining relocs are from the Embedded ELF ABI, and are not + in the SVR4 ELF ABI. */ +#define R_PPC_EMB_NADDR32 101 +#define R_PPC_EMB_NADDR16 102 +#define R_PPC_EMB_NADDR16_LO 103 +#define R_PPC_EMB_NADDR16_HI 104 +#define R_PPC_EMB_NADDR16_HA 105 +#define R_PPC_EMB_SDAI16 106 +#define R_PPC_EMB_SDA2I16 107 +#define R_PPC_EMB_SDA2REL 108 +#define R_PPC_EMB_SDA21 109 /* 16 bit offset in SDA */ +#define R_PPC_EMB_MRKREF 110 +#define R_PPC_EMB_RELSEC16 111 +#define R_PPC_EMB_RELST_LO 112 +#define R_PPC_EMB_RELST_HI 113 +#define R_PPC_EMB_RELST_HA 114 +#define R_PPC_EMB_BIT_FLD 115 +#define R_PPC_EMB_RELSDA 116 /* 16 bit relative offset in SDA */ + +/* Diab tool relocations. */ +#define R_PPC_DIAB_SDA21_LO 180 /* like EMB_SDA21, but lower 16 bit */ +#define R_PPC_DIAB_SDA21_HI 181 /* like EMB_SDA21, but high 16 bit */ +#define R_PPC_DIAB_SDA21_HA 182 /* like EMB_SDA21, adjusted high 16 */ +#define R_PPC_DIAB_RELSDA_LO 183 /* like EMB_RELSDA, but lower 16 bit */ +#define R_PPC_DIAB_RELSDA_HI 184 /* like EMB_RELSDA, but high 16 bit */ +#define R_PPC_DIAB_RELSDA_HA 185 /* like EMB_RELSDA, adjusted high 16 */ + +/* This is a phony reloc to handle any old fashioned TOC16 references + that may still be in object files. */ +#define R_PPC_TOC16 255 + + +/* PowerPC64 relocations defined by the ABIs */ +#define R_PPC64_NONE R_PPC_NONE +#define R_PPC64_ADDR32 R_PPC_ADDR32 /* 32bit absolute address */ +#define R_PPC64_ADDR24 R_PPC_ADDR24 /* 26bit address, word aligned */ +#define R_PPC64_ADDR16 R_PPC_ADDR16 /* 16bit absolute address */ +#define R_PPC64_ADDR16_LO R_PPC_ADDR16_LO /* lower 16bits of address */ +#define R_PPC64_ADDR16_HI R_PPC_ADDR16_HI /* high 16bits of address. */ +#define R_PPC64_ADDR16_HA R_PPC_ADDR16_HA /* adjusted high 16bits. */ +#define R_PPC64_ADDR14 R_PPC_ADDR14 /* 16bit address, word aligned */ +#define R_PPC64_ADDR14_BRTAKEN R_PPC_ADDR14_BRTAKEN +#define R_PPC64_ADDR14_BRNTAKEN R_PPC_ADDR14_BRNTAKEN +#define R_PPC64_REL24 R_PPC_REL24 /* PC-rel. 26 bit, word aligned */ +#define R_PPC64_REL14 R_PPC_REL14 /* PC relative 16 bit */ +#define R_PPC64_REL14_BRTAKEN R_PPC_REL14_BRTAKEN +#define R_PPC64_REL14_BRNTAKEN R_PPC_REL14_BRNTAKEN +#define R_PPC64_GOT16 R_PPC_GOT16 +#define R_PPC64_GOT16_LO R_PPC_GOT16_LO +#define R_PPC64_GOT16_HI R_PPC_GOT16_HI +#define R_PPC64_GOT16_HA R_PPC_GOT16_HA + +#define R_PPC64_COPY R_PPC_COPY +#define R_PPC64_GLOB_DAT R_PPC_GLOB_DAT +#define R_PPC64_JMP_SLOT R_PPC_JMP_SLOT +#define R_PPC64_RELATIVE R_PPC_RELATIVE + +#define R_PPC64_UADDR32 R_PPC_UADDR32 +#define R_PPC64_UADDR16 R_PPC_UADDR16 +#define R_PPC64_REL32 R_PPC_REL32 +#define R_PPC64_PLT32 R_PPC_PLT32 +#define R_PPC64_PLTREL32 R_PPC_PLTREL32 +#define R_PPC64_PLT16_LO R_PPC_PLT16_LO +#define R_PPC64_PLT16_HI R_PPC_PLT16_HI +#define R_PPC64_PLT16_HA R_PPC_PLT16_HA + +#define R_PPC64_SECTOFF R_PPC_SECTOFF +#define R_PPC64_SECTOFF_LO R_PPC_SECTOFF_LO +#define R_PPC64_SECTOFF_HI R_PPC_SECTOFF_HI +#define R_PPC64_SECTOFF_HA R_PPC_SECTOFF_HA +#define R_PPC64_ADDR30 37 /* word30 (S + A - P) >> 2 */ +#define R_PPC64_ADDR64 38 /* doubleword64 S + A */ +#define R_PPC64_ADDR16_HIGHER 39 /* half16 #higher(S + A) */ +#define R_PPC64_ADDR16_HIGHERA 40 /* half16 #highera(S + A) */ +#define R_PPC64_ADDR16_HIGHEST 41 /* half16 #highest(S + A) */ +#define R_PPC64_ADDR16_HIGHESTA 42 /* half16 #highesta(S + A) */ +#define R_PPC64_UADDR64 43 /* doubleword64 S + A */ +#define R_PPC64_REL64 44 /* doubleword64 S + A - P */ +#define R_PPC64_PLT64 45 /* doubleword64 L + A */ +#define R_PPC64_PLTREL64 46 /* doubleword64 L + A - P */ +#define R_PPC64_TOC16 47 /* half16* S + A - .TOC */ +#define R_PPC64_TOC16_LO 48 /* half16 #lo(S + A - .TOC.) */ +#define R_PPC64_TOC16_HI 49 /* half16 #hi(S + A - .TOC.) */ +#define R_PPC64_TOC16_HA 50 /* half16 #ha(S + A - .TOC.) */ +#define R_PPC64_TOC 51 /* doubleword64 .TOC */ +#define R_PPC64_PLTGOT16 52 /* half16* M + A */ +#define R_PPC64_PLTGOT16_LO 53 /* half16 #lo(M + A) */ +#define R_PPC64_PLTGOT16_HI 54 /* half16 #hi(M + A) */ +#define R_PPC64_PLTGOT16_HA 55 /* half16 #ha(M + A) */ + +#define R_PPC64_ADDR16_DS 56 /* half16ds* (S + A) >> 2 */ +#define R_PPC64_ADDR16_LO_DS 57 /* half16ds #lo(S + A) >> 2 */ +#define R_PPC64_GOT16_DS 58 /* half16ds* (G + A) >> 2 */ +#define R_PPC64_GOT16_LO_DS 59 /* half16ds #lo(G + A) >> 2 */ +#define R_PPC64_PLT16_LO_DS 60 /* half16ds #lo(L + A) >> 2 */ +#define R_PPC64_SECTOFF_DS 61 /* half16ds* (R + A) >> 2 */ +#define R_PPC64_SECTOFF_LO_DS 62 /* half16ds #lo(R + A) >> 2 */ +#define R_PPC64_TOC16_DS 63 /* half16ds* (S + A - .TOC.) >> 2 */ +#define R_PPC64_TOC16_LO_DS 64 /* half16ds #lo(S + A - .TOC.) >> 2 */ +#define R_PPC64_PLTGOT16_DS 65 /* half16ds* (M + A) >> 2 */ +#define R_PPC64_PLTGOT16_LO_DS 66 /* half16ds #lo(M + A) >> 2 */ + +/* PowerPC64 relocations defined for the TLS access ABI. */ +#define R_PPC64_TLS 67 /* none (sym+add)@tls */ +#define R_PPC64_DTPMOD64 68 /* doubleword64 (sym+add)@dtpmod */ +#define R_PPC64_TPREL16 69 /* half16* (sym+add)@tprel */ +#define R_PPC64_TPREL16_LO 70 /* half16 (sym+add)@tprel@l */ +#define R_PPC64_TPREL16_HI 71 /* half16 (sym+add)@tprel@h */ +#define R_PPC64_TPREL16_HA 72 /* half16 (sym+add)@tprel@ha */ +#define R_PPC64_TPREL64 73 /* doubleword64 (sym+add)@tprel */ +#define R_PPC64_DTPREL16 74 /* half16* (sym+add)@dtprel */ +#define R_PPC64_DTPREL16_LO 75 /* half16 (sym+add)@dtprel@l */ +#define R_PPC64_DTPREL16_HI 76 /* half16 (sym+add)@dtprel@h */ +#define R_PPC64_DTPREL16_HA 77 /* half16 (sym+add)@dtprel@ha */ +#define R_PPC64_DTPREL64 78 /* doubleword64 (sym+add)@dtprel */ +#define R_PPC64_GOT_TLSGD16 79 /* half16* (sym+add)@got@tlsgd */ +#define R_PPC64_GOT_TLSGD16_LO 80 /* half16 (sym+add)@got@tlsgd@l */ +#define R_PPC64_GOT_TLSGD16_HI 81 /* half16 (sym+add)@got@tlsgd@h */ +#define R_PPC64_GOT_TLSGD16_HA 82 /* half16 (sym+add)@got@tlsgd@ha */ +#define R_PPC64_GOT_TLSLD16 83 /* half16* (sym+add)@got@tlsld */ +#define R_PPC64_GOT_TLSLD16_LO 84 /* half16 (sym+add)@got@tlsld@l */ +#define R_PPC64_GOT_TLSLD16_HI 85 /* half16 (sym+add)@got@tlsld@h */ +#define R_PPC64_GOT_TLSLD16_HA 86 /* half16 (sym+add)@got@tlsld@ha */ +#define R_PPC64_GOT_TPREL16_DS 87 /* half16ds* (sym+add)@got@tprel */ +#define R_PPC64_GOT_TPREL16_LO_DS 88 /* half16ds (sym+add)@got@tprel@l */ +#define R_PPC64_GOT_TPREL16_HI 89 /* half16 (sym+add)@got@tprel@h */ +#define R_PPC64_GOT_TPREL16_HA 90 /* half16 (sym+add)@got@tprel@ha */ +#define R_PPC64_GOT_DTPREL16_DS 91 /* half16ds* (sym+add)@got@dtprel */ +#define R_PPC64_GOT_DTPREL16_LO_DS 92 /* half16ds (sym+add)@got@dtprel@l */ +#define R_PPC64_GOT_DTPREL16_HI 93 /* half16 (sym+add)@got@dtprel@h */ +#define R_PPC64_GOT_DTPREL16_HA 94 /* half16 (sym+add)@got@dtprel@ha */ +#define R_PPC64_TPREL16_DS 95 /* half16ds* (sym+add)@tprel */ +#define R_PPC64_TPREL16_LO_DS 96 /* half16ds (sym+add)@tprel@l */ +#define R_PPC64_TPREL16_HIGHER 97 /* half16 (sym+add)@tprel@higher */ +#define R_PPC64_TPREL16_HIGHERA 98 /* half16 (sym+add)@tprel@highera */ +#define R_PPC64_TPREL16_HIGHEST 99 /* half16 (sym+add)@tprel@highest */ +#define R_PPC64_TPREL16_HIGHESTA 100 /* half16 (sym+add)@tprel@highesta */ +#define R_PPC64_DTPREL16_DS 101 /* half16ds* (sym+add)@dtprel */ +#define R_PPC64_DTPREL16_LO_DS 102 /* half16ds (sym+add)@dtprel@l */ +#define R_PPC64_DTPREL16_HIGHER 103 /* half16 (sym+add)@dtprel@higher */ +#define R_PPC64_DTPREL16_HIGHERA 104 /* half16 (sym+add)@dtprel@highera */ +#define R_PPC64_DTPREL16_HIGHEST 105 /* half16 (sym+add)@dtprel@highest */ +#define R_PPC64_DTPREL16_HIGHESTA 106 /* half16 (sym+add)@dtprel@highesta */ + +/* Keep this the last entry. */ +#define R_PPC64_NUM 107 + +/* PowerPC64 specific values for the Dyn d_tag field. */ +#define DT_PPC64_GLINK (DT_LOPROC + 0) +#define DT_PPC64_OPD (DT_LOPROC + 1) +#define DT_PPC64_OPDSZ (DT_LOPROC + 2) +#define DT_PPC64_NUM 3 + + +/* ARM specific declarations */ + +/* Processor specific flags for the ELF header e_flags field. */ +#define EF_ARM_RELEXEC 0x01 +#define EF_ARM_HASENTRY 0x02 +#define EF_ARM_INTERWORK 0x04 +#define EF_ARM_APCS_26 0x08 +#define EF_ARM_APCS_FLOAT 0x10 +#define EF_ARM_PIC 0x20 +#define EF_ARM_ALIGN8 0x40 /* 8-bit structure alignment is in use */ +#define EF_ARM_NEW_ABI 0x80 +#define EF_ARM_OLD_ABI 0x100 + +/* Other constants defined in the ARM ELF spec. version B-01. */ +/* NB. These conflict with values defined above. */ +#define EF_ARM_SYMSARESORTED 0x04 +#define EF_ARM_DYNSYMSUSESEGIDX 0x08 +#define EF_ARM_MAPSYMSFIRST 0x10 +#define EF_ARM_EABIMASK 0XFF000000 + +#define EF_ARM_EABI_VERSION(flags) ((flags) & EF_ARM_EABIMASK) +#define EF_ARM_EABI_UNKNOWN 0x00000000 +#define EF_ARM_EABI_VER1 0x01000000 +#define EF_ARM_EABI_VER2 0x02000000 + +/* Additional symbol types for Thumb */ +#define STT_ARM_TFUNC 0xd + +/* ARM-specific values for sh_flags */ +#define SHF_ARM_ENTRYSECT 0x10000000 /* Section contains an entry point */ +#define SHF_ARM_COMDEF 0x80000000 /* Section may be multiply defined + in the input to a link step */ + +/* ARM-specific program header flags */ +#define PF_ARM_SB 0x10000000 /* Segment contains the location + addressed by the static base */ + +/* ARM relocs. */ +#define R_ARM_NONE 0 /* No reloc */ +#define R_ARM_PC24 1 /* PC relative 26 bit branch */ +#define R_ARM_ABS32 2 /* Direct 32 bit */ +#define R_ARM_REL32 3 /* PC relative 32 bit */ +#define R_ARM_PC13 4 +#define R_ARM_ABS16 5 /* Direct 16 bit */ +#define R_ARM_ABS12 6 /* Direct 12 bit */ +#define R_ARM_THM_ABS5 7 +#define R_ARM_ABS8 8 /* Direct 8 bit */ +#define R_ARM_SBREL32 9 +#define R_ARM_THM_PC22 10 +#define R_ARM_THM_PC8 11 +#define R_ARM_AMP_VCALL9 12 +#define R_ARM_SWI24 13 +#define R_ARM_THM_SWI8 14 +#define R_ARM_XPC25 15 +#define R_ARM_THM_XPC22 16 +#define R_ARM_COPY 20 /* Copy symbol at runtime */ +#define R_ARM_GLOB_DAT 21 /* Create GOT entry */ +#define R_ARM_JUMP_SLOT 22 /* Create PLT entry */ +#define R_ARM_RELATIVE 23 /* Adjust by program base */ +#define R_ARM_GOTOFF 24 /* 32 bit offset to GOT */ +#define R_ARM_GOTPC 25 /* 32 bit PC relative offset to GOT */ +#define R_ARM_GOT32 26 /* 32 bit GOT entry */ +#define R_ARM_PLT32 27 /* 32 bit PLT address */ +#define R_ARM_ALU_PCREL_7_0 32 +#define R_ARM_ALU_PCREL_15_8 33 +#define R_ARM_ALU_PCREL_23_15 34 +#define R_ARM_LDR_SBREL_11_0 35 +#define R_ARM_ALU_SBREL_19_12 36 +#define R_ARM_ALU_SBREL_27_20 37 +#define R_ARM_GNU_VTENTRY 100 +#define R_ARM_GNU_VTINHERIT 101 +#define R_ARM_THM_PC11 102 /* thumb unconditional branch */ +#define R_ARM_THM_PC9 103 /* thumb conditional branch */ +#define R_ARM_RXPC25 249 +#define R_ARM_RSBREL32 250 +#define R_ARM_THM_RPC22 251 +#define R_ARM_RREL32 252 +#define R_ARM_RABS22 253 +#define R_ARM_RPC24 254 +#define R_ARM_RBASE 255 +/* Keep this the last entry. */ +#define R_ARM_NUM 256 + +/* IA-64 specific declarations. */ + +/* Processor specific flags for the Ehdr e_flags field. */ +#define EF_IA_64_MASKOS 0x0000000f /* os-specific flags */ +#define EF_IA_64_ABI64 0x00000010 /* 64-bit ABI */ +#define EF_IA_64_ARCH 0xff000000 /* arch. version mask */ + +/* Processor specific values for the Phdr p_type field. */ +#define PT_IA_64_ARCHEXT (PT_LOPROC + 0) /* arch extension bits */ +#define PT_IA_64_UNWIND (PT_LOPROC + 1) /* ia64 unwind bits */ +#define PT_IA_64_HP_OPT_ANOT (PT_LOOS + 0x12) +#define PT_IA_64_HP_HSL_ANOT (PT_LOOS + 0x13) +#define PT_IA_64_HP_STACK (PT_LOOS + 0x14) + +/* Processor specific flags for the Phdr p_flags field. */ +#define PF_IA_64_NORECOV 0x80000000 /* spec insns w/o recovery */ + +/* Processor specific values for the Shdr sh_type field. */ +#define SHT_IA_64_EXT (SHT_LOPROC + 0) /* extension bits */ +#define SHT_IA_64_UNWIND (SHT_LOPROC + 1) /* unwind bits */ + +/* Processor specific flags for the Shdr sh_flags field. */ +#define SHF_IA_64_SHORT 0x10000000 /* section near gp */ +#define SHF_IA_64_NORECOV 0x20000000 /* spec insns w/o recovery */ + +/* Processor specific values for the Dyn d_tag field. */ +#define DT_IA_64_PLT_RESERVE (DT_LOPROC + 0) +#define DT_IA_64_NUM 1 + +/* IA-64 relocations. */ +#define R_IA64_NONE 0x00 /* none */ +#define R_IA64_IMM14 0x21 /* symbol + addend, add imm14 */ +#define R_IA64_IMM22 0x22 /* symbol + addend, add imm22 */ +#define R_IA64_IMM64 0x23 /* symbol + addend, mov imm64 */ +#define R_IA64_DIR32MSB 0x24 /* symbol + addend, data4 MSB */ +#define R_IA64_DIR32LSB 0x25 /* symbol + addend, data4 LSB */ +#define R_IA64_DIR64MSB 0x26 /* symbol + addend, data8 MSB */ +#define R_IA64_DIR64LSB 0x27 /* symbol + addend, data8 LSB */ +#define R_IA64_GPREL22 0x2a /* @gprel(sym + add), add imm22 */ +#define R_IA64_GPREL64I 0x2b /* @gprel(sym + add), mov imm64 */ +#define R_IA64_GPREL32MSB 0x2c /* @gprel(sym + add), data4 MSB */ +#define R_IA64_GPREL32LSB 0x2d /* @gprel(sym + add), data4 LSB */ +#define R_IA64_GPREL64MSB 0x2e /* @gprel(sym + add), data8 MSB */ +#define R_IA64_GPREL64LSB 0x2f /* @gprel(sym + add), data8 LSB */ +#define R_IA64_LTOFF22 0x32 /* @ltoff(sym + add), add imm22 */ +#define R_IA64_LTOFF64I 0x33 /* @ltoff(sym + add), mov imm64 */ +#define R_IA64_PLTOFF22 0x3a /* @pltoff(sym + add), add imm22 */ +#define R_IA64_PLTOFF64I 0x3b /* @pltoff(sym + add), mov imm64 */ +#define R_IA64_PLTOFF64MSB 0x3e /* @pltoff(sym + add), data8 MSB */ +#define R_IA64_PLTOFF64LSB 0x3f /* @pltoff(sym + add), data8 LSB */ +#define R_IA64_FPTR64I 0x43 /* @fptr(sym + add), mov imm64 */ +#define R_IA64_FPTR32MSB 0x44 /* @fptr(sym + add), data4 MSB */ +#define R_IA64_FPTR32LSB 0x45 /* @fptr(sym + add), data4 LSB */ +#define R_IA64_FPTR64MSB 0x46 /* @fptr(sym + add), data8 MSB */ +#define R_IA64_FPTR64LSB 0x47 /* @fptr(sym + add), data8 LSB */ +#define R_IA64_PCREL60B 0x48 /* @pcrel(sym + add), brl */ +#define R_IA64_PCREL21B 0x49 /* @pcrel(sym + add), ptb, call */ +#define R_IA64_PCREL21M 0x4a /* @pcrel(sym + add), chk.s */ +#define R_IA64_PCREL21F 0x4b /* @pcrel(sym + add), fchkf */ +#define R_IA64_PCREL32MSB 0x4c /* @pcrel(sym + add), data4 MSB */ +#define R_IA64_PCREL32LSB 0x4d /* @pcrel(sym + add), data4 LSB */ +#define R_IA64_PCREL64MSB 0x4e /* @pcrel(sym + add), data8 MSB */ +#define R_IA64_PCREL64LSB 0x4f /* @pcrel(sym + add), data8 LSB */ +#define R_IA64_LTOFF_FPTR22 0x52 /* @ltoff(@fptr(s+a)), imm22 */ +#define R_IA64_LTOFF_FPTR64I 0x53 /* @ltoff(@fptr(s+a)), imm64 */ +#define R_IA64_LTOFF_FPTR32MSB 0x54 /* @ltoff(@fptr(s+a)), data4 MSB */ +#define R_IA64_LTOFF_FPTR32LSB 0x55 /* @ltoff(@fptr(s+a)), data4 LSB */ +#define R_IA64_LTOFF_FPTR64MSB 0x56 /* @ltoff(@fptr(s+a)), data8 MSB */ +#define R_IA64_LTOFF_FPTR64LSB 0x57 /* @ltoff(@fptr(s+a)), data8 LSB */ +#define R_IA64_SEGREL32MSB 0x5c /* @segrel(sym + add), data4 MSB */ +#define R_IA64_SEGREL32LSB 0x5d /* @segrel(sym + add), data4 LSB */ +#define R_IA64_SEGREL64MSB 0x5e /* @segrel(sym + add), data8 MSB */ +#define R_IA64_SEGREL64LSB 0x5f /* @segrel(sym + add), data8 LSB */ +#define R_IA64_SECREL32MSB 0x64 /* @secrel(sym + add), data4 MSB */ +#define R_IA64_SECREL32LSB 0x65 /* @secrel(sym + add), data4 LSB */ +#define R_IA64_SECREL64MSB 0x66 /* @secrel(sym + add), data8 MSB */ +#define R_IA64_SECREL64LSB 0x67 /* @secrel(sym + add), data8 LSB */ +#define R_IA64_REL32MSB 0x6c /* data 4 + REL */ +#define R_IA64_REL32LSB 0x6d /* data 4 + REL */ +#define R_IA64_REL64MSB 0x6e /* data 8 + REL */ +#define R_IA64_REL64LSB 0x6f /* data 8 + REL */ +#define R_IA64_LTV32MSB 0x74 /* symbol + addend, data4 MSB */ +#define R_IA64_LTV32LSB 0x75 /* symbol + addend, data4 LSB */ +#define R_IA64_LTV64MSB 0x76 /* symbol + addend, data8 MSB */ +#define R_IA64_LTV64LSB 0x77 /* symbol + addend, data8 LSB */ +#define R_IA64_PCREL21BI 0x79 /* @pcrel(sym + add), 21bit inst */ +#define R_IA64_PCREL22 0x7a /* @pcrel(sym + add), 22bit inst */ +#define R_IA64_PCREL64I 0x7b /* @pcrel(sym + add), 64bit inst */ +#define R_IA64_IPLTMSB 0x80 /* dynamic reloc, imported PLT, MSB */ +#define R_IA64_IPLTLSB 0x81 /* dynamic reloc, imported PLT, LSB */ +#define R_IA64_COPY 0x84 /* copy relocation */ +#define R_IA64_SUB 0x85 /* Addend and symbol difference */ +#define R_IA64_LTOFF22X 0x86 /* LTOFF22, relaxable. */ +#define R_IA64_LDXMOV 0x87 /* Use of LTOFF22X. */ +#define R_IA64_TPREL14 0x91 /* @tprel(sym + add), imm14 */ +#define R_IA64_TPREL22 0x92 /* @tprel(sym + add), imm22 */ +#define R_IA64_TPREL64I 0x93 /* @tprel(sym + add), imm64 */ +#define R_IA64_TPREL64MSB 0x96 /* @tprel(sym + add), data8 MSB */ +#define R_IA64_TPREL64LSB 0x97 /* @tprel(sym + add), data8 LSB */ +#define R_IA64_LTOFF_TPREL22 0x9a /* @ltoff(@tprel(s+a)), imm2 */ +#define R_IA64_DTPMOD64MSB 0xa6 /* @dtpmod(sym + add), data8 MSB */ +#define R_IA64_DTPMOD64LSB 0xa7 /* @dtpmod(sym + add), data8 LSB */ +#define R_IA64_LTOFF_DTPMOD22 0xaa /* @ltoff(@dtpmod(sym + add)), imm22 */ +#define R_IA64_DTPREL14 0xb1 /* @dtprel(sym + add), imm14 */ +#define R_IA64_DTPREL22 0xb2 /* @dtprel(sym + add), imm22 */ +#define R_IA64_DTPREL64I 0xb3 /* @dtprel(sym + add), imm64 */ +#define R_IA64_DTPREL32MSB 0xb4 /* @dtprel(sym + add), data4 MSB */ +#define R_IA64_DTPREL32LSB 0xb5 /* @dtprel(sym + add), data4 LSB */ +#define R_IA64_DTPREL64MSB 0xb6 /* @dtprel(sym + add), data8 MSB */ +#define R_IA64_DTPREL64LSB 0xb7 /* @dtprel(sym + add), data8 LSB */ +#define R_IA64_LTOFF_DTPREL22 0xba /* @ltoff(@dtprel(s+a)), imm22 */ + +/* SH specific declarations */ + +/* SH relocs. */ +#define R_SH_NONE 0 +#define R_SH_DIR32 1 +#define R_SH_REL32 2 +#define R_SH_DIR8WPN 3 +#define R_SH_IND12W 4 +#define R_SH_DIR8WPL 5 +#define R_SH_DIR8WPZ 6 +#define R_SH_DIR8BP 7 +#define R_SH_DIR8W 8 +#define R_SH_DIR8L 9 +#define R_SH_SWITCH16 25 +#define R_SH_SWITCH32 26 +#define R_SH_USES 27 +#define R_SH_COUNT 28 +#define R_SH_ALIGN 29 +#define R_SH_CODE 30 +#define R_SH_DATA 31 +#define R_SH_LABEL 32 +#define R_SH_SWITCH8 33 +#define R_SH_GNU_VTINHERIT 34 +#define R_SH_GNU_VTENTRY 35 +#define R_SH_TLS_GD_32 144 +#define R_SH_TLS_LD_32 145 +#define R_SH_TLS_LDO_32 146 +#define R_SH_TLS_IE_32 147 +#define R_SH_TLS_LE_32 148 +#define R_SH_TLS_DTPMOD32 149 +#define R_SH_TLS_DTPOFF32 150 +#define R_SH_TLS_TPOFF32 151 +#define R_SH_GOT32 160 +#define R_SH_PLT32 161 +#define R_SH_COPY 162 +#define R_SH_GLOB_DAT 163 +#define R_SH_JMP_SLOT 164 +#define R_SH_RELATIVE 165 +#define R_SH_GOTOFF 166 +#define R_SH_GOTPC 167 +/* Keep this the last entry. */ +#define R_SH_NUM 256 + +/* Additional s390 relocs */ + +#define R_390_NONE 0 /* No reloc. */ +#define R_390_8 1 /* Direct 8 bit. */ +#define R_390_12 2 /* Direct 12 bit. */ +#define R_390_16 3 /* Direct 16 bit. */ +#define R_390_32 4 /* Direct 32 bit. */ +#define R_390_PC32 5 /* PC relative 32 bit. */ +#define R_390_GOT12 6 /* 12 bit GOT offset. */ +#define R_390_GOT32 7 /* 32 bit GOT offset. */ +#define R_390_PLT32 8 /* 32 bit PC relative PLT address. */ +#define R_390_COPY 9 /* Copy symbol at runtime. */ +#define R_390_GLOB_DAT 10 /* Create GOT entry. */ +#define R_390_JMP_SLOT 11 /* Create PLT entry. */ +#define R_390_RELATIVE 12 /* Adjust by program base. */ +#define R_390_GOTOFF32 13 /* 32 bit offset to GOT. */ +#define R_390_GOTPC 14 /* 32 bit PC relative offset to GOT. */ +#define R_390_GOT16 15 /* 16 bit GOT offset. */ +#define R_390_PC16 16 /* PC relative 16 bit. */ +#define R_390_PC16DBL 17 /* PC relative 16 bit shifted by 1. */ +#define R_390_PLT16DBL 18 /* 16 bit PC rel. PLT shifted by 1. */ +#define R_390_PC32DBL 19 /* PC relative 32 bit shifted by 1. */ +#define R_390_PLT32DBL 20 /* 32 bit PC rel. PLT shifted by 1. */ +#define R_390_GOTPCDBL 21 /* 32 bit PC rel. GOT shifted by 1. */ +#define R_390_64 22 /* Direct 64 bit. */ +#define R_390_PC64 23 /* PC relative 64 bit. */ +#define R_390_GOT64 24 /* 64 bit GOT offset. */ +#define R_390_PLT64 25 /* 64 bit PC relative PLT address. */ +#define R_390_GOTENT 26 /* 32 bit PC rel. to GOT entry >> 1. */ +#define R_390_GOTOFF16 27 /* 16 bit offset to GOT. */ +#define R_390_GOTOFF64 28 /* 64 bit offset to GOT. */ +#define R_390_GOTPLT12 29 /* 12 bit offset to jump slot. */ +#define R_390_GOTPLT16 30 /* 16 bit offset to jump slot. */ +#define R_390_GOTPLT32 31 /* 32 bit offset to jump slot. */ +#define R_390_GOTPLT64 32 /* 64 bit offset to jump slot. */ +#define R_390_GOTPLTENT 33 /* 32 bit rel. offset to jump slot. */ +#define R_390_PLTOFF16 34 /* 16 bit offset from GOT to PLT. */ +#define R_390_PLTOFF32 35 /* 32 bit offset from GOT to PLT. */ +#define R_390_PLTOFF64 36 /* 16 bit offset from GOT to PLT. */ +#define R_390_TLS_LOAD 37 /* Tag for load insn in TLS code. */ +#define R_390_TLS_GDCALL 38 /* Tag for function call in general + dynamic TLS code. */ +#define R_390_TLS_LDCALL 39 /* Tag for function call in local + dynamic TLS code. */ +#define R_390_TLS_GD32 40 /* Direct 32 bit for general dynamic + thread local data. */ +#define R_390_TLS_GD64 41 /* Direct 64 bit for general dynamic + thread local data. */ +#define R_390_TLS_GOTIE12 42 /* 12 bit GOT offset for static TLS + block offset. */ +#define R_390_TLS_GOTIE32 43 /* 32 bit GOT offset for static TLS + block offset. */ +#define R_390_TLS_GOTIE64 44 /* 64 bit GOT offset for static TLS + block offset. */ +#define R_390_TLS_LDM32 45 /* Direct 32 bit for local dynamic + thread local data in LE code. */ +#define R_390_TLS_LDM64 46 /* Direct 64 bit for local dynamic + thread local data in LE code. */ +#define R_390_TLS_IE32 47 /* 32 bit address of GOT entry for + negated static TLS block offset. */ +#define R_390_TLS_IE64 48 /* 64 bit address of GOT entry for + negated static TLS block offset. */ +#define R_390_TLS_IEENT 49 /* 32 bit rel. offset to GOT entry for + negated static TLS block offset. */ +#define R_390_TLS_LE32 50 /* 32 bit negated offset relative to + static TLS block. */ +#define R_390_TLS_LE64 51 /* 64 bit negated offset relative to + static TLS block. */ +#define R_390_TLS_LDO32 52 /* 32 bit offset relative to TLS + block. */ +#define R_390_TLS_LDO64 53 /* 64 bit offset relative to TLS + block. */ +#define R_390_TLS_DTPMOD 54 /* ID of module containing symbol. */ +#define R_390_TLS_DTPOFF 55 /* Offset in TLS block. */ +#define R_390_TLS_TPOFF 56 /* Negated offset in static TLS + block. */ +#define R_390_20 57 /* Direct 20 bit. */ +#define R_390_GOT20 58 /* 20 bit GOT offset. */ +#define R_390_GOTPLT20 59 /* 20 bit offset to jump slot. */ +#define R_390_TLS_GOTIE20 60 /* 20 bit GOT offset for static TLS + block offset. */ +/* Keep this the last entry. */ +#define R_390_NUM 61 + + +/* CRIS relocations. */ +#define R_CRIS_NONE 0 +#define R_CRIS_8 1 +#define R_CRIS_16 2 +#define R_CRIS_32 3 +#define R_CRIS_8_PCREL 4 +#define R_CRIS_16_PCREL 5 +#define R_CRIS_32_PCREL 6 +#define R_CRIS_GNU_VTINHERIT 7 +#define R_CRIS_GNU_VTENTRY 8 +#define R_CRIS_COPY 9 +#define R_CRIS_GLOB_DAT 10 +#define R_CRIS_JUMP_SLOT 11 +#define R_CRIS_RELATIVE 12 +#define R_CRIS_16_GOT 13 +#define R_CRIS_32_GOT 14 +#define R_CRIS_16_GOTPLT 15 +#define R_CRIS_32_GOTPLT 16 +#define R_CRIS_32_GOTREL 17 +#define R_CRIS_32_PLT_GOTREL 18 +#define R_CRIS_32_PLT_PCREL 19 + +#define R_CRIS_NUM 20 + + +/* AMD x86-64 relocations. */ +#define R_X86_64_NONE 0 /* No reloc */ +#define R_X86_64_64 1 /* Direct 64 bit */ +#define R_X86_64_PC32 2 /* PC relative 32 bit signed */ +#define R_X86_64_GOT32 3 /* 32 bit GOT entry */ +#define R_X86_64_PLT32 4 /* 32 bit PLT address */ +#define R_X86_64_COPY 5 /* Copy symbol at runtime */ +#define R_X86_64_GLOB_DAT 6 /* Create GOT entry */ +#define R_X86_64_JUMP_SLOT 7 /* Create PLT entry */ +#define R_X86_64_RELATIVE 8 /* Adjust by program base */ +#define R_X86_64_GOTPCREL 9 /* 32 bit signed PC relative + offset to GOT */ +#define R_X86_64_32 10 /* Direct 32 bit zero extended */ +#define R_X86_64_32S 11 /* Direct 32 bit sign extended */ +#define R_X86_64_16 12 /* Direct 16 bit zero extended */ +#define R_X86_64_PC16 13 /* 16 bit sign extended pc relative */ +#define R_X86_64_8 14 /* Direct 8 bit sign extended */ +#define R_X86_64_PC8 15 /* 8 bit sign extended pc relative */ +#define R_X86_64_DTPMOD64 16 /* ID of module containing symbol */ +#define R_X86_64_DTPOFF64 17 /* Offset in module's TLS block */ +#define R_X86_64_TPOFF64 18 /* Offset in initial TLS block */ +#define R_X86_64_TLSGD 19 /* 32 bit signed PC relative offset + to two GOT entries for GD symbol */ +#define R_X86_64_TLSLD 20 /* 32 bit signed PC relative offset + to two GOT entries for LD symbol */ +#define R_X86_64_DTPOFF32 21 /* Offset in TLS block */ +#define R_X86_64_GOTTPOFF 22 /* 32 bit signed PC relative offset + to GOT entry for IE symbol */ +#define R_X86_64_TPOFF32 23 /* Offset in initial TLS block */ + +#define R_X86_64_NUM 24 + + +/* AM33 relocations. */ +#define R_MN10300_NONE 0 /* No reloc. */ +#define R_MN10300_32 1 /* Direct 32 bit. */ +#define R_MN10300_16 2 /* Direct 16 bit. */ +#define R_MN10300_8 3 /* Direct 8 bit. */ +#define R_MN10300_PCREL32 4 /* PC-relative 32-bit. */ +#define R_MN10300_PCREL16 5 /* PC-relative 16-bit signed. */ +#define R_MN10300_PCREL8 6 /* PC-relative 8-bit signed. */ +#define R_MN10300_GNU_VTINHERIT 7 /* Ancient C++ vtable garbage... */ +#define R_MN10300_GNU_VTENTRY 8 /* ... collection annotation. */ +#define R_MN10300_24 9 /* Direct 24 bit. */ +#define R_MN10300_GOTPC32 10 /* 32-bit PCrel offset to GOT. */ +#define R_MN10300_GOTPC16 11 /* 16-bit PCrel offset to GOT. */ +#define R_MN10300_GOTOFF32 12 /* 32-bit offset from GOT. */ +#define R_MN10300_GOTOFF24 13 /* 24-bit offset from GOT. */ +#define R_MN10300_GOTOFF16 14 /* 16-bit offset from GOT. */ +#define R_MN10300_PLT32 15 /* 32-bit PCrel to PLT entry. */ +#define R_MN10300_PLT16 16 /* 16-bit PCrel to PLT entry. */ +#define R_MN10300_GOT32 17 /* 32-bit offset to GOT entry. */ +#define R_MN10300_GOT24 18 /* 24-bit offset to GOT entry. */ +#define R_MN10300_GOT16 19 /* 16-bit offset to GOT entry. */ +#define R_MN10300_COPY 20 /* Copy symbol at runtime. */ +#define R_MN10300_GLOB_DAT 21 /* Create GOT entry. */ +#define R_MN10300_JMP_SLOT 22 /* Create PLT entry. */ +#define R_MN10300_RELATIVE 23 /* Adjust by program base. */ + +#define R_MN10300_NUM 24 + + +/* M32R relocs. */ +#define R_M32R_NONE 0 /* No reloc. */ +#define R_M32R_16 1 /* Direct 16 bit. */ +#define R_M32R_32 2 /* Direct 32 bit. */ +#define R_M32R_24 3 /* Direct 24 bit. */ +#define R_M32R_10_PCREL 4 /* PC relative 10 bit shifted. */ +#define R_M32R_18_PCREL 5 /* PC relative 18 bit shifted. */ +#define R_M32R_26_PCREL 6 /* PC relative 26 bit shifted. */ +#define R_M32R_HI16_ULO 7 /* High 16 bit with unsigned low. */ +#define R_M32R_HI16_SLO 8 /* High 16 bit with signed low. */ +#define R_M32R_LO16 9 /* Low 16 bit. */ +#define R_M32R_SDA16 10 /* 16 bit offset in SDA. */ +#define R_M32R_GNU_VTINHERIT 11 +#define R_M32R_GNU_VTENTRY 12 +/* M32R relocs use SHT_RELA. */ +#define R_M32R_16_RELA 33 /* Direct 16 bit. */ +#define R_M32R_32_RELA 34 /* Direct 32 bit. */ +#define R_M32R_24_RELA 35 /* Direct 24 bit. */ +#define R_M32R_10_PCREL_RELA 36 /* PC relative 10 bit shifted. */ +#define R_M32R_18_PCREL_RELA 37 /* PC relative 18 bit shifted. */ +#define R_M32R_26_PCREL_RELA 38 /* PC relative 26 bit shifted. */ +#define R_M32R_HI16_ULO_RELA 39 /* High 16 bit with unsigned low */ +#define R_M32R_HI16_SLO_RELA 40 /* High 16 bit with signed low */ +#define R_M32R_LO16_RELA 41 /* Low 16 bit */ +#define R_M32R_SDA16_RELA 42 /* 16 bit offset in SDA */ +#define R_M32R_RELA_GNU_VTINHERIT 43 +#define R_M32R_RELA_GNU_VTENTRY 44 + +#define R_M32R_GOT24 48 /* 24 bit GOT entry */ +#define R_M32R_26_PLTREL 49 /* 26 bit PC relative to PLT shifted */ +#define R_M32R_COPY 50 /* Copy symbol at runtime */ +#define R_M32R_GLOB_DAT 51 /* Create GOT entry */ +#define R_M32R_JMP_SLOT 52 /* Create PLT entry */ +#define R_M32R_RELATIVE 53 /* Adjust by program base */ +#define R_M32R_GOTOFF 54 /* 24 bit offset to GOT */ +#define R_M32R_GOTPC24 55 /* 24 bit PC relative offset to GOT */ +#define R_M32R_GOT16_HI_ULO 56 /* High 16 bit GOT entry with unsigned + low */ +#define R_M32R_GOT16_HI_SLO 57 /* High 16 bit GOT entry with signed + low */ +#define R_M32R_GOT16_LO 58 /* Low 16 bit GOT entry */ +#define R_M32R_GOTPC_HI_ULO 59 /* High 16 bit PC relative offset to + GOT with unsigned low */ +#define R_M32R_GOTPC_HI_SLO 60 /* High 16 bit PC relative offset to + GOT with signed low */ +#define R_M32R_GOTPC_LO 61 /* Low 16 bit PC relative offset to + GOT */ +#define R_M32R_GOTOFF_HI_ULO 62 /* High 16 bit offset to GOT + with unsigned low */ +#define R_M32R_GOTOFF_HI_SLO 63 /* High 16 bit offset to GOT + with signed low */ +#define R_M32R_GOTOFF_LO 64 /* Low 16 bit offset to GOT */ +#define R_M32R_NUM 256 /* Keep this the last entry. */ + + +__END_DECLS + +#endif /* elf.h */ diff --git a/trunk/src/execstack.c b/trunk/src/execstack.c index 1e50aad..f38fead 100644 --- a/trunk/src/execstack.c +++ b/trunk/src/execstack.c @@ -32,9 +32,9 @@ int set; int execflag; -const char *argp_program_version = "execstack 1.0"; +const char *argp_program_version = "execstack 1.0 (20061201) Wind River"; -const char *argp_program_bug_address = "<jakub@redhat.com>"; +const char *argp_program_bug_address = "<support@windriver.com>"; static char argp_doc[] = "execstack -- program to query or set executable stack flag"; @@ -107,7 +107,7 @@ execstack_make_rdwr (DSO *dso, int flag) header we've created. */ sprintf (filename, "%s.#execstack#.XXXXXX", dso->filename); - fd = mkstemp (filename); + fd = wrap_mkstemp (filename); if (fd == -1) { error (0, 0, "%s: Cannot create temporary file", @@ -183,7 +183,7 @@ execstack_make_rdwr (DSO *dso, int flag) ndso->filename = p; p = NULL; - unlink (filename); + wrap_unlink (filename); close (fd); fd = -1; close_dso (dso); @@ -195,7 +195,7 @@ error_out: close_dso (ndso); if (fd != -1) { - unlink (filename); + wrap_unlink (filename); close (fd); } close_dso (dso); diff --git a/trunk/src/gather.c b/trunk/src/gather.c index a3d0870..9219fdf 100644 --- a/trunk/src/gather.c +++ b/trunk/src/gather.c @@ -61,8 +61,8 @@ gather_deps (DSO *dso, struct prelink_entry *ent) { int i, j, seen = 0; FILE *f = NULL; - const char *argv[5]; - const char *envp[4]; + const char *argv[6]; + const char *envp[5]; char *line = NULL, *p, *q = NULL; const char **depends = NULL; size_t ndepends = 0, ndepends_alloced = 0; @@ -143,11 +143,6 @@ gather_deps (DSO *dso, struct prelink_entry *ent) i = 0; argv[i++] = dl; - if (ld_library_path) - { - argv[i++] = "--library-path"; - argv[i++] = ld_library_path; - } if (strchr (ent->filename, '/') != NULL) ent_filename = ent->filename; else @@ -158,13 +153,55 @@ gather_deps (DSO *dso, struct prelink_entry *ent) memcpy (tp + 2, ent->filename, flen + 1); ent_filename = tp; } - argv[i++] = ent_filename; - argv[i] = NULL; - envp[0] = "LD_TRACE_LOADED_OBJECTS=1"; - envp[1] = "LD_TRACE_PRELINKING=1"; - envp[2] = "LD_WARN="; - envp[3] = NULL; - f = execve_open (dl, (char * const *)argv, (char * const *)envp); + + if (prelink_rtld == NULL) + { + i = 0; + argv[i++] = dl; + if (ld_library_path) + { + argv[i++] = "--library-path"; + argv[i++] = ld_library_path; + } + argv[i++] = ent_filename; + argv[i] = NULL; + envp[0] = "LD_TRACE_LOADED_OBJECTS=1"; + envp[1] = "LD_TRACE_PRELINKING=1"; + envp[2] = "LD_WARN="; + envp[3] = NULL; + f = execve_open (dl, (char * const *)argv, (char * const *)envp); + } + else + { + char *path; + i = 0; + argv[i++] = prelink_rtld; + if (ld_library_path) + { + argv[i++] = "--library-path"; + argv[i++] = ld_library_path; + } + argv[i++] = "--target-paths"; + argv[i++] = ent_filename; + argv[i] = NULL; + envp[0] = "RTLD_TRACE_PRELINKING=1"; + envp[1] = "LD_WARN="; + path = alloca (sizeof "PATH=" + strlen (getenv ("PATH"))); + sprintf (path, "PATH=%s", getenv ("PATH")); + envp[2] = path; + + if (sysroot) + { + envp[3] = alloca (sizeof "PRELINK_SYSROOT=" + strlen (sysroot)); + sprintf ((char *) envp[3], "PRELINK_SYSROOT=%s", sysroot); + envp[4] = NULL; + } + else + envp[3] = NULL; + + f = execve_open (prelink_rtld, (char * const *)argv, (char * const *)envp); + } + if (f == NULL) goto error_out; @@ -183,8 +220,8 @@ gather_deps (DSO *dso, struct prelink_entry *ent) q = strstr (p, " ("); if (q == NULL && strcmp (p, " => not found") == 0) { - error (0, 0, "%s: Could not find one of the dependencies", - ent->filename); + error (0, 0, "%s: Could not find one of the dependencies: %s", + ent->filename, line); goto error_out; } } @@ -551,7 +588,9 @@ make_unprelinkable: } dl = dynamic_linker ?: dso->arch->dynamic_linker; - if (strcmp (dl, data->d_buf) != 0) + if (strcmp (dl, data->d_buf) != 0 + && (dynamic_linker != NULL || dso->arch->dynamic_linker_alt == NULL + || strcmp (dso->arch->dynamic_linker_alt, data->d_buf) != 0)) { error (0, 0, "%s: Using %s, not %s as dynamic linker", dso->filename, (char *) data->d_buf, dl); @@ -587,7 +626,7 @@ add_dir_to_dirlist (const char *name, dev_t dev, int flags) struct prelink_dir *dir; size_t len; - canon_name = prelink_canonicalize (name, NULL); + canon_name = wrap_prelink_canonicalize (name, NULL); if (canon_name == NULL) { if (! all && implicit) @@ -693,7 +732,7 @@ gather_func (const char *name, const struct stat64 *st, int type, if (st->st_size < sizeof (e_ident)) return FTW_CONTINUE; - fd = open (name, O_RDONLY); + fd = wrap_open (name, O_RDONLY); if (fd == -1) return FTW_CONTINUE; @@ -891,7 +930,7 @@ gather_binlib (const char *name, const struct stat64 *st) return 0; } - fd = open (name, O_RDONLY); + fd = wrap_open (name, O_RDONLY); if (fd == -1) { error (0, errno, "Could not open %s", name); @@ -979,7 +1018,7 @@ gather_object (const char *name, int deref, int onefs) { struct stat64 st; - if (stat64 (name, &st) < 0) + if (wrap_stat64 (name, &st) < 0) { if (implicit) return 0; @@ -1002,7 +1041,7 @@ gather_object (const char *name, int deref, int onefs) if (!all && implicit && ! deref) return 0; ++implicit; - ret = nftw64 (name, gather_func, 20, flags | FTW_ACTIONRETVAL); + ret = wrap_nftw64 (name, gather_func, 20, flags | FTW_ACTIONRETVAL); --implicit; #ifndef HAVE_FTW_ACTIONRETVAL free (blacklist_dir); @@ -1226,7 +1265,7 @@ add_to_blacklist (const char *name, int deref, int onefs) return 0; } - canon_name = prelink_canonicalize (name, NULL); + canon_name = wrap_prelink_canonicalize (name, NULL); if (canon_name == NULL) { if (implicit) diff --git a/trunk/src/get.c b/trunk/src/get.c index 9912a92..0ae418b 100644 --- a/trunk/src/get.c +++ b/trunk/src/get.c @@ -30,6 +30,7 @@ int is_ldso_soname (const char *soname) { if (! strcmp (soname, "ld-linux.so.2") + || ! strcmp (soname, "ld-linux.so.3") || ! strcmp (soname, "ld.so.1") || ! strcmp (soname, "ld-linux-ia64.so.2") || ! strcmp (soname, "ld-linux-x86-64.so.2") @@ -144,7 +145,7 @@ prelink_record_relocations (struct prelink_info *info, FILE *f, { struct stat64 st; - if (stat64 (filename, &st) < 0) + if (wrap_stat64 (filename, &st) < 0) { error (0, errno, "%s: Could not stat %s", info->ent->filename, filename); @@ -561,7 +562,7 @@ prelink_get_relocations (struct prelink_info *info) { FILE *f; DSO *dso = info->dso; - const char *argv[5]; + const char *argv[6]; const char *envp[4]; int i, ret, status; char *p; @@ -590,13 +591,6 @@ prelink_get_relocations (struct prelink_info *info) / info->symtab_entsize; info->symbols = calloc (sizeof (struct prelink_symbol), info->symbol_count); - i = 0; - argv[i++] = dl; - if (ld_library_path) - { - argv[i++] = "--library-path"; - argv[i++] = ld_library_path; - } if (strchr (info->ent->filename, '/') != NULL) ent_filename = info->ent->filename; else @@ -607,17 +601,56 @@ prelink_get_relocations (struct prelink_info *info) memcpy (p + 2, info->ent->filename, flen + 1); ent_filename = p; } - argv[i++] = ent_filename; - argv[i] = NULL; - envp[0] = "LD_TRACE_LOADED_OBJECTS=1"; - envp[1] = "LD_BIND_NOW=1"; - p = alloca (sizeof "LD_TRACE_PRELINKING=" + strlen (info->ent->filename)); - strcpy (stpcpy (p, "LD_TRACE_PRELINKING="), info->ent->filename); - envp[2] = p; - envp[3] = NULL; - - ret = 2; - f = execve_open (dl, (char * const *)argv, (char * const *)envp); + if (prelink_rtld == NULL) + { + i = 0; + argv[i++] = dl; + if (ld_library_path) + { + argv[i++] = "--library-path"; + argv[i++] = ld_library_path; + } + argv[i++] = ent_filename; + argv[i] = NULL; + envp[0] = "LD_TRACE_LOADED_OBJECTS=1"; + envp[1] = "LD_BIND_NOW=1"; + p = alloca (sizeof "LD_TRACE_PRELINKING=" + strlen (info->ent->filename)); + strcpy (stpcpy (p, "LD_TRACE_PRELINKING="), info->ent->filename); + envp[2] = p; + envp[3] = NULL; + ret = 2; + f = execve_open (dl, (char * const *)argv, (char * const *)envp); + } + else + { + i = 0; + argv[i++] = prelink_rtld; + if (ld_library_path) + { + argv[i++] = "--library-path"; + argv[i++] = ld_library_path; + } + argv[i++] = "--target-paths"; + argv[i++] = ent_filename; + argv[i] = NULL; + p = alloca (sizeof "RTLD_TRACE_PRELINKING=" + strlen (info->ent->filename)); + strcpy (stpcpy (p, "RTLD_TRACE_PRELINKING="), info->ent->filename); + envp[0] = p; + p = alloca (sizeof "PATH=" + strlen (getenv ("PATH"))); + sprintf (p, "PATH=%s", getenv ("PATH")); + envp[1] = p; + envp[2] = NULL; + if (sysroot) + { + p = alloca (sizeof "PRELINK_SYSROOT=" + strlen (sysroot)); + sprintf (p, "PRELINK_SYSROOT=%s", sysroot); + envp[2] = p; + envp[3] = NULL; + } + ret = 2; + f = execve_open (prelink_rtld, (char * const *)argv, (char * const *)envp); + } + if (f == NULL) { error (0, errno, "%s: Could not trace symbol resolving", diff --git a/trunk/src/ld-do-lookup.h b/trunk/src/ld-do-lookup.h new file mode 100644 index 0000000..62a1280 --- /dev/null +++ b/trunk/src/ld-do-lookup.h @@ -0,0 +1,225 @@ +/* Look up a symbol in the loaded objects. + Copyright (C) 1995,96,97,98,99,2000,2001,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if VERSIONED +# define FCT do_lookup_versioned +# define ARG const struct r_found_version *const version +#else +# define FCT do_lookup +# define ARG int flags +#endif + +/* Inner part of the lookup functions. We return a value > 0 if we + found the symbol, the value 0 if nothing is found and < 0 if + something bad happened. */ +static inline int +FCT (const char *undef_name, unsigned long int hash, const ElfW(Sym) *ref, + struct sym_val *result, struct r_scope_elem *scope, size_t i, ARG, + struct ldlibs_link_map *skip, int type_class, int machine) +{ + struct ldlibs_link_map **list = scope->r_list; + size_t n = scope->r_nlist; + struct ldlibs_link_map *map; + + do + { + const ElfW(Sym) *symtab; + const char *strtab; + const ElfW(Half) *verstab; + Elf_Symndx symidx; + const ElfW(Sym) *sym; +#if ! VERSIONED + int num_versions = 0; + const ElfW(Sym) *versioned_sym = NULL; +#endif + + map = list[i]; + + /* Here come the extra test needed for `_dl_lookup_symbol_skip'. */ + if (skip != NULL && map == skip) + continue; + + /* Don't search the executable when resolving a copy reloc. */ + if ((type_class & ELF_RTYPE_CLASS_COPY) && map->l_type == lt_executable) + continue; + + /* Print some debugging info if wanted. */ + if (__builtin_expect (GL(dl_debug_mask) & DL_DEBUG_SYMBOLS, 0)) + INTUSE(_dl_debug_printf) ("symbol=%s; lookup in file=%s\n", + undef_name, (map->l_name[0] + ? map->l_name : rtld_progname)); + + symtab = (const void *) D_PTR (map, l_info[DT_SYMTAB]); + strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]); + verstab = map->l_versyms; + + /* Search the appropriate hash bucket in this object's symbol table + for a definition for the same symbol name. */ + for (symidx = map->l_buckets[hash % map->l_nbuckets]; + symidx != STN_UNDEF; + symidx = map->l_chain[symidx]) + { + sym = &symtab[symidx]; + + assert (ELF_RTYPE_CLASS_PLT == 1); + if ((sym->st_value == 0 /* No value. */ +#ifdef USE_TLS + && ELFW(ST_TYPE) (sym->st_info) != STT_TLS +#endif + ) + || (type_class & (sym->st_shndx == SHN_UNDEF))) + continue; + + if (ELFW(ST_TYPE) (sym->st_info) > STT_FUNC + && (machine != EM_ARM + || ELFW(ST_TYPE) (sym->st_info) != STT_ARM_TFUNC) +#ifdef USE_TLS + && ELFW(ST_TYPE) (sym->st_info) != STT_TLS +#endif + ) + /* Ignore all but STT_NOTYPE, STT_OBJECT and STT_FUNC + entries (and STT_TLS if TLS is supported) since these + are no code/data definitions. */ + continue; + + if (sym != ref && strcmp (strtab + sym->st_name, undef_name)) + /* Not the symbol we are looking for. */ + continue; + +#if VERSIONED + if (__builtin_expect (verstab == NULL, 0)) + { + /* We need a versioned symbol but haven't found any. If + this is the object which is referenced in the verneed + entry it is a bug in the library since a symbol must + not simply disappear. + + It would also be a bug in the object since it means that + the list of required versions is incomplete and so the + tests in dl-version.c haven't found a problem.*/ + assert (version->filename == NULL + || ! _dl_soname_match_p (version->filename, map)); + + /* Otherwise we accept the symbol. */ + } + else + { + /* We can match the version information or use the + default one if it is not hidden. */ + ElfW(Half) ndx = verstab[symidx] & 0x7fff; + if ((map->l_versions[ndx].hash != version->hash + || strcmp (map->l_versions[ndx].name, version->name)) + && (version->hidden || map->l_versions[ndx].hash + || (verstab[symidx] & 0x8000))) + /* It's not the version we want. */ + continue; + } +#else + /* No specific version is selected. There are two ways we + can got here: + + - a binary which does not include versioning information + is loaded + + - dlsym() instead of dlvsym() is used to get a symbol which + might exist in more than one form + + If the library does not provide symbol version + information there is no problem at at: we simply use the + symbol if it is defined. + + These two lookups need to be handled differently if the + library defines versions. In the case of the old + unversioned application the oldest (default) version + should be used. In case of a dlsym() call the latest and + public interface should be returned. */ + if (verstab != NULL) + { + if ((verstab[symidx] & 0x7fff) + >= ((flags & DL_LOOKUP_RETURN_NEWEST) ? 2 : 3)) + { + /* Don't accept hidden symbols. */ + if ((verstab[symidx] & 0x8000) == 0 && num_versions++ == 0) + /* No version so far. */ + versioned_sym = sym; + + continue; + } + } +#endif + + /* There cannot be another entry for this symbol so stop here. */ + goto found_it; + } + + /* If we have seen exactly one versioned symbol while we are + looking for an unversioned symbol and the version is not the + default version we still accept this symbol since there are + no possible ambiguities. */ +#if VERSIONED + sym = NULL; +#else + sym = num_versions == 1 ? versioned_sym : NULL; +#endif + + if (sym != NULL) + { + found_it: + switch (ELFW(ST_BIND) (sym->st_info)) + { + case STB_WEAK: + /* Weak definition. Use this value if we don't find another. */ + if (__builtin_expect (GL(dl_dynamic_weak), 0)) + { + if (! result->s) + { + result->s = sym; + result->m = map; + } + break; + } + /* FALLTHROUGH */ + case STB_GLOBAL: + /* Global definition. Just what we need. */ + result->s = sym; + result->m = map; + return 1; + default: + /* Local symbols are ignored. */ + break; + } + } + +#if VERSIONED + /* If this current map is the one mentioned in the verneed entry + and we have not found a weak entry, it is a bug. */ + if (symidx == STN_UNDEF && version->filename != NULL + && __builtin_expect (_dl_soname_match_p (version->filename, map), 0)) + return -1; +#endif + } + while (++i < n); + + /* We have not found anything until now. */ + return 0; +} + +#undef FCT +#undef ARG +#undef VERSIONED diff --git a/trunk/src/ld-libs.c b/trunk/src/ld-libs.c new file mode 100644 index 0000000..b169cde --- /dev/null +++ b/trunk/src/ld-libs.c @@ -0,0 +1,1371 @@ +/* Copyright (C) 2003 MontaVista Software, Inc. + Written by Daniel Jacobowitz <drow@mvista.com>, 2003 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <config.h> +#include <assert.h> +#include <ctype.h> +#include <errno.h> +#include <error.h> +#include <argp.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/stat.h> +#include <unistd.h> + +#include "prelinktab.h" +#include "reloc.h" + +#include "ld-libs.h" + +struct search_path +{ + int maxlen, count, allocated; + char **dirs; +}; + +struct search_path ld_dirs, ld_library_search_path; +int host_paths; + +void string_to_path (struct search_path *path, const char *string); + +const char *argp_program_version = "prelink-rtld 1.0 (20061201) Wind River Linux"; + +const char *argp_program_bug_address = "<support@windriver.com>"; + +static char argp_doc[] = "prelink-rtld -- program to simulate the runtime linker"; + +#define OPT_SYSROOT 0x8c +#define OPT_LIBRARY_PATH 0x8e +#define OPT_TARGET_PATHS 0x8f + +static struct argp_option options[] = { + {"library-path", OPT_LIBRARY_PATH, "LIBRARY_PATH", 0, "Set library search path to LIBRARY_PATH" }, + {"root", OPT_SYSROOT, "ROOT_PATH", 0, "Prefix all paths with ROOT_PATH" }, + {"target-paths", OPT_TARGET_PATHS, 0, 0, "Specified paths are based on ROOT_PATH" }, + { 0 } +}; + +static error_t +parse_opt (int key, char *arg, struct argp_state *state) +{ + switch (key) + { + case OPT_SYSROOT: + sysroot = arg; + break; + case OPT_LIBRARY_PATH: + string_to_path(&ld_library_search_path, arg); + break; + case OPT_TARGET_PATHS: + host_paths = 0; + break; + default: + return ARGP_ERR_UNKNOWN; + } + return 0; +} + +#ifndef PT_TLS +#define PT_TLS 7 /* Thread-local storage segment */ +#endif + +#ifndef R_ARM_TLS_DTPMOD32 +#define R_ARM_TLS_DTPMOD32 17 /* ID of module containing symbol */ +#define R_ARM_TLS_DTPOFF32 18 /* Offset in TLS block */ +#define R_ARM_TLS_TPOFF32 19 /* Offset in static TLS block */ +#endif + +/* This function returns the same constants expected by glibc's + symbol lookup routines. This is slightly different from the + equivalent routines in prelink. It should return PLT for any + relocation where an undefined symbol in the application should + be ignored: typically, this means any jump slot or TLS relocations, + but not copy relocations. Don't return the prelinker's + RTYPE_CLASS_TLS. */ +int +reloc_type_class (int type, int machine) +{ + switch (machine) + { + case EM_386: + switch (type) + { + case R_386_COPY: return ELF_RTYPE_CLASS_COPY; + case R_386_JMP_SLOT: + case R_386_TLS_DTPMOD32: + case R_386_TLS_DTPOFF32: + case R_386_TLS_TPOFF32: + case R_386_TLS_TPOFF: + return ELF_RTYPE_CLASS_PLT; + default: return 0; + } + + case EM_X86_64: + switch (type) + { + case R_X86_64_COPY: return ELF_RTYPE_CLASS_COPY; + case R_X86_64_JUMP_SLOT: + case R_X86_64_DTPMOD64: + case R_X86_64_DTPOFF64: + case R_X86_64_TPOFF64: + case R_X86_64_DTPOFF32: + case R_X86_64_TPOFF32: + return ELF_RTYPE_CLASS_PLT; + default: return 0; + } + + case EM_ARM: + switch (type) + { + case R_ARM_COPY: return ELF_RTYPE_CLASS_COPY; + case R_ARM_JUMP_SLOT: + case R_ARM_TLS_DTPMOD32: + case R_ARM_TLS_DTPOFF32: + case R_ARM_TLS_TPOFF32: + return ELF_RTYPE_CLASS_PLT; + default: return 0; + } + + case EM_SH: + switch (type) + { + case R_SH_COPY: return ELF_RTYPE_CLASS_COPY; + case R_SH_JMP_SLOT: return ELF_RTYPE_CLASS_PLT; + default: return 0; + } + + case EM_PPC: + switch (type) + { + case R_PPC_COPY: return ELF_RTYPE_CLASS_COPY; + case R_PPC_JMP_SLOT: return ELF_RTYPE_CLASS_PLT; + default: + if (type >= R_PPC_DTPMOD32 && type <= R_PPC_DTPREL32) + return ELF_RTYPE_CLASS_PLT; + return 0; + } + + case EM_PPC64: + switch (type) + { + case R_PPC64_COPY: return ELF_RTYPE_CLASS_COPY; + case R_PPC64_ADDR24: return ELF_RTYPE_CLASS_PLT; + default: + if (type >= R_PPC64_DTPMOD64 && type <= R_PPC64_TPREL16_HIGHESTA) + return ELF_RTYPE_CLASS_PLT; + return 0; + } + + default: + printf ("Unknown architecture!\n"); + exit (1); + return 0; + } +} + +int +is_ldso_soname (const char *soname) +{ + if (! strcmp (soname, "ld-linux.so.2") + || ! strcmp (soname, "ld-linux.so.3") + || ! strcmp (soname, "ld.so.1") + || ! strcmp (soname, "ld-linux-ia64.so.2") + || ! strcmp (soname, "ld-linux-x86-64.so.2") + || ! strcmp (soname, "ld64.so.1")) + return 1; + return 0; +} + + +struct needed_list +{ + struct dso_list *ent; + struct needed_list *next; +}; + +struct dso_list +{ + DSO *dso; + struct ldlibs_link_map *map; + struct dso_list *next, *prev; + struct needed_list *needed, *needed_tail; + const char *name; + struct dso_list *loader; + const char *canon_filename; +}; + +static int dso_open_error = 0; + +static void +free_needed (struct needed_list *p) +{ + struct needed_list *old_p = p; + while (old_p) + { + old_p = p->next; + free (p); + p = old_p; + } +} + +static struct dso_list * +in_dso_list (struct dso_list *dso_list, const char *soname, const char *filename) +{ + while (dso_list != NULL) + { + if (dso_list->dso != NULL) + { + if (strcmp (dso_list->dso->soname, soname) == 0) + return dso_list; + } + + if (strcmp (dso_list->name, soname) == 0) + return dso_list; + + if (filename && dso_list->canon_filename + && strcmp (dso_list->canon_filename, filename) == 0) + return dso_list; + + dso_list = dso_list->next; + } + return NULL; +} + +static int +in_needed_list (struct needed_list *needed_list, const char *soname) +{ + while (needed_list != NULL) + { + if (needed_list->ent->dso != NULL + && strcmp (needed_list->ent->dso->soname, soname) == 0) + return 1; + needed_list = needed_list->next; + } + return 0; +} + + +/****/ + +void +add_dir (struct search_path *path, const char *dir, int dirlen) +{ + if (path->allocated == 0) + { + path->allocated = 5; + path->dirs = malloc (sizeof (char *) * 5); + } + else if (path->count == path->allocated) + { + path->allocated *= 2; + path->dirs = realloc (path->dirs, sizeof (char *) * path->allocated); + } + path->dirs[path->count] = malloc (dirlen + 1); + memcpy (path->dirs[path->count], dir, dirlen); + path->dirs[path->count++][dirlen] = 0; + + if (path->maxlen < dirlen) + path->maxlen = dirlen; +} + +void +free_path (struct search_path *path) +{ + if (path->allocated) + { + int i; + for (i = 0; i < path->count; i++) + free (path->dirs[i]); + free (path->dirs); + } +} + +void +load_ld_so_conf (int use_64bit) +{ + int fd; + FILE *conf; + char buf[1024]; + + memset (&ld_dirs, 0, sizeof (ld_dirs)); + + /* Only use the correct machine, to prevent mismatches if we + have both /lib/ld.so and /lib64/ld.so on x86-64. */ + if (use_64bit) + { + add_dir (&ld_dirs, "/lib64/tls", strlen ("/lib64/tls")); + add_dir (&ld_dirs, "/lib64", strlen ("/lib64")); + add_dir (&ld_dirs, "/usr/lib64/tls", strlen ("/usr/lib64/tls")); + add_dir (&ld_dirs, "/usr/lib64", strlen ("/usr/lib64")); + } + else + { + add_dir (&ld_dirs, "/lib/tls", strlen ("/lib/tls")); + add_dir (&ld_dirs, "/lib", strlen ("/lib")); + add_dir (&ld_dirs, "/usr/lib/tls", strlen ("/usr/lib/tls")); + add_dir (&ld_dirs, "/usr/lib", strlen ("/usr/lib")); + } + + fd = wrap_open ("/etc/ld.so.conf", O_RDONLY); + if (fd == -1) + return; + conf = fdopen (fd, "r"); + while (fgets (buf, 1024, conf) != NULL) + { + int len; + char *p; + + p = strchr (buf, '#'); + if (p) + *p = 0; + len = strlen (buf); + while (isspace (buf[len - 1])) + buf[--len] = 0; + + add_dir (&ld_dirs, buf, len); + } + fclose (conf); +} + +void +string_to_path (struct search_path *path, const char *string) +{ + const char *start, *end, *end_tmp; + + start = string; + while (1) { + end = start; + while (*end && *end != ':' && *end != ';') + end ++; + + /* Eliminate any trailing '/' characters, but be sure to leave a + leading slash if someeone wants / in their RPATH. */ + end_tmp = end; + while (end_tmp > start + 1 && end_tmp[-1] == '/') + end_tmp --; + + add_dir (path, start, end_tmp - start); + + if (*end == 0) + break; + + /* Skip the separator. */ + start = end + 1; + } +} + +char * +find_lib_in_path (struct search_path *path, const char *soname, + int elfclass) +{ + char *ret; + int i; + + ret = malloc (strlen (soname) + 2 + path->maxlen); + + for (i = 0; i < path->count; i++) + { + sprintf (ret, "%s/%s", path->dirs[i], soname); + if (wrap_access (ret, F_OK) == 0) + { + /* Skip 32-bit libraries when looking for 64-bit. */ + DSO *dso = open_dso (ret); + + if (dso == NULL) + continue; + + if (gelf_getclass (dso->elf) != elfclass) + { + close_dso (dso); + continue; + } + + close_dso (dso); + return ret; + } + } + + free (ret); + return NULL; +} + +char * +find_lib_by_soname (const char *soname, struct dso_list *loader, + int elfclass) +{ + char *ret; + + if (strchr (soname, '/')) + return strdup (soname); + + if (loader->dso->info[DT_RUNPATH] == 0) + { + /* Search DT_RPATH all the way up. */ + struct dso_list *loader_p = loader; + while (loader_p) + { + if (loader_p->dso->info[DT_RPATH]) + { + struct search_path r_path; + const char *rpath = get_data (loader_p->dso, + loader_p->dso->info[DT_STRTAB] + + loader_p->dso->info[DT_RPATH], + NULL, NULL); + memset (&r_path, 0, sizeof (r_path)); + string_to_path (&r_path, rpath); + ret = find_lib_in_path (&r_path, soname, elfclass); + free_path (&r_path); + if (ret) + return ret; + } + loader_p = loader_p->loader; + } + } + + ret = find_lib_in_path (&ld_library_search_path, soname, elfclass); + if (ret) + return ret; + + if (loader->dso->info[DT_RUNPATH]) + { + struct search_path r_path; + const char *rpath = get_data (loader->dso, + loader->dso->info[DT_STRTAB] + + loader->dso->info[DT_RUNPATH], + NULL, NULL); + memset (&r_path, 0, sizeof (r_path)); + string_to_path (&r_path, rpath); + ret = find_lib_in_path (&r_path, soname, elfclass); + free_path (&r_path); + if (ret) + return ret; + } + + ret = find_lib_in_path (&ld_dirs, soname, elfclass); + if (ret) + return ret; + + return NULL; +} + +static struct dso_list * +load_dsos (DSO *dso) +{ + struct dso_list *dso_list, *dso_list_tail, *cur_dso_ent, *new_dso_ent; + + dso_list = malloc (sizeof (struct dso_list)); + dso_list->dso = dso; + dso_list->next = NULL; + dso_list->prev = NULL; + dso_list->needed = NULL; + dso_list->name = dso->filename; + dso_list->loader = NULL; + dso_list->canon_filename = wrap_prelink_canonicalize (dso->filename, NULL); + + cur_dso_ent = dso_list_tail = dso_list; + + while (cur_dso_ent != NULL) + { + DSO *cur_dso, *new_dso; + Elf_Scn *scn; + Elf_Data *data; + GElf_Dyn dyn; + + cur_dso = cur_dso_ent->dso; + if (cur_dso == NULL) + { + cur_dso_ent = cur_dso_ent->next; + continue; + } + + scn = cur_dso->scn[cur_dso->dynamic]; + data = NULL; + while ((data = elf_getdata (scn, data)) != NULL) + { + int ndx, maxndx; + maxndx = data->d_size / cur_dso->shdr[cur_dso->dynamic].sh_entsize; + for (ndx = 0; ndx < maxndx; ++ndx) + { + gelfx_getdyn (cur_dso->elf, data, ndx, &dyn); + if (dyn.d_tag == DT_NULL) + break; + if (dyn.d_tag == DT_NEEDED) + { + char *new_name=NULL, *new_canon_name=NULL; + const char *soname = get_data (cur_dso, + cur_dso->info[DT_STRTAB] + + dyn.d_un.d_val, + NULL, NULL); + new_dso_ent = in_dso_list (dso_list, soname, NULL); + if (new_dso_ent == NULL) + { + new_name = find_lib_by_soname (soname, cur_dso_ent, + gelf_getclass (dso->elf)); + if (new_name == 0 || wrap_access (new_name, R_OK) < 0) + { + dso_open_error ++; + + new_dso_ent = malloc (sizeof (struct dso_list)); + dso_list_tail->next = new_dso_ent; + dso_list_tail->next->prev = dso_list_tail; + dso_list_tail = dso_list_tail->next; + dso_list_tail->next = NULL; + dso_list_tail->dso = NULL; + dso_list_tail->needed = NULL; + dso_list_tail->name = soname; + dso_list_tail->loader = NULL; + dso_list_tail->canon_filename = soname; + + continue; + } + + /* See if the filename we found has already been + opened (possibly under a different SONAME via + some symlink). */ + new_canon_name = wrap_prelink_canonicalize (new_name, NULL); + if (new_canon_name == NULL) + new_canon_name = strdup (new_name); + new_dso_ent = in_dso_list (dso_list, soname, new_canon_name); + } + else if (new_dso_ent->dso == NULL) + continue; + + if (new_dso_ent == NULL) + { + new_dso = open_dso (new_name); + free (new_name); + new_dso_ent = malloc (sizeof (struct dso_list)); + dso_list_tail->next = new_dso_ent; + dso_list_tail->next->prev = dso_list_tail; + dso_list_tail = dso_list_tail->next; + dso_list_tail->next = NULL; + dso_list_tail->dso = new_dso; + dso_list_tail->needed = NULL; + dso_list_tail->loader = cur_dso_ent; + dso_list_tail->canon_filename = new_canon_name; + + if (is_ldso_soname (new_dso->soname)) + dso_list_tail->name = new_dso->filename; + else if (strcmp (new_dso->soname, new_dso->filename) == 0) + /* new_dso->soname might be a full path if the library + had no SONAME. Use the original SONAME instead. */ + dso_list_tail->name = soname; + else + /* Use the new SONAME if possible, in case some library + links to this one using an incorrect SONAME. */ + dso_list_tail->name = new_dso->soname; + } + + if (!cur_dso_ent->needed) + { + cur_dso_ent->needed = malloc (sizeof (struct needed_list)); + cur_dso_ent->needed_tail = cur_dso_ent->needed; + cur_dso_ent->needed_tail->ent = new_dso_ent; + cur_dso_ent->needed_tail->next = NULL; + } + else if (!in_needed_list (cur_dso_ent->needed, soname)) + { + cur_dso_ent->needed_tail->next = malloc (sizeof (struct needed_list)); + cur_dso_ent->needed_tail = cur_dso_ent->needed_tail->next; + cur_dso_ent->needed_tail->ent = new_dso_ent; + cur_dso_ent->needed_tail->next = NULL; + } + + continue; + } + if (dyn.d_tag == DT_FILTER || dyn.d_tag == DT_AUXILIARY) + { + // big fat warning; + } + } + } + cur_dso_ent = cur_dso_ent->next; + } + return dso_list; +} + +static void +get_version_info (DSO *dso, struct ldlibs_link_map *map) +{ + int i; + Elf_Data *data; + int ndx_high; + const char *strtab = map->l_info[DT_STRTAB]; + + /* Fortunately, 32-bit and 64-bit ELF use the same Verneed and Verdef + structures, so this function will work for either. */ + + Elf64_Verneed *verneed; + Elf64_Verdef *verdef; + + map->l_versyms = NULL; + + if (dso->info_set_mask & (1ULL << DT_VERNEED_BIT)) + { + i = addr_to_sec (dso, dso->info_DT_VERNEED); + data = elf_getdata (dso->scn[i], NULL); + verneed = data->d_buf; + } + else + verneed = NULL; + + if (dso->info_set_mask & (1ULL << DT_VERDEF_BIT)) + { + i = addr_to_sec (dso, dso->info_DT_VERDEF); + data = elf_getdata (dso->scn[i], NULL); + verdef = data->d_buf; + } + else + verdef = NULL; + + ndx_high = 0; + if (verneed) + { + Elf64_Verneed *ent = verneed; + Elf64_Vernaux *aux; + while (1) + { + aux = (Elf64_Vernaux *) ((char *) ent + ent->vn_aux); + while (1) + { + if ((unsigned int) (aux->vna_other & 0x7fff) > ndx_high) + ndx_high = aux->vna_other & 0x7fff; + + if (aux->vna_next == 0) + break; + aux = (Elf64_Vernaux *) ((char *) aux + aux->vna_next); + } + + if (ent->vn_next == 0) + break; + ent = (Elf64_Verneed *) ((char *) ent + ent->vn_next); + } + } + + if (verdef) + { + Elf64_Verdef *ent = verdef; + while (1) + { + if ((unsigned int) (ent->vd_ndx & 0x7fff) > ndx_high) + ndx_high = ent->vd_ndx & 0x7fff; + + if (ent->vd_next == 0) + break; + ent = (Elf64_Verdef *) ((char *) ent + ent->vd_next); + } + } + + if (ndx_high) + { + map->l_versions = (struct r_found_version *) + calloc (ndx_high + 1, sizeof (struct r_found_version)); + map->l_nversions = ndx_high + 1; + + i = addr_to_sec (dso, dso->info_DT_VERSYM); + data = elf_getdata (dso->scn[i], NULL); + map->l_versyms = data->d_buf; + + if (verneed) + { + Elf64_Verneed *ent = verneed; + + while (1) + { + Elf64_Vernaux *aux; + aux = (Elf64_Vernaux *) ((char *) ent + ent->vn_aux); + while (1) + { + Elf64_Half ndx = aux->vna_other & 0x7fff; + map->l_versions[ndx].hash = aux->vna_hash; + map->l_versions[ndx].hidden = aux->vna_other & 0x8000; + map->l_versions[ndx].name = &strtab[aux->vna_name]; + map->l_versions[ndx].filename = &strtab[ent->vn_file]; + + if (aux->vna_next == 0) + break; + aux = (Elf64_Vernaux *) ((char *) aux + aux->vna_next); + } + + if (ent->vn_next == 0) + break; + ent = (Elf64_Verneed *) ((char *) ent + ent->vn_next); + } + } + + if (verdef) + { + Elf64_Verdef *ent = verdef; + Elf64_Verdaux *aux; + while (1) + { + aux = (Elf64_Verdaux *) ((char *) ent + ent->vd_aux); + + if ((ent->vd_flags & VER_FLG_BASE) == 0) + { + /* The name of the base version should not be + available for matching a versioned symbol. */ + Elf64_Half ndx = ent->vd_ndx & 0x7fff; + map->l_versions[ndx].hash = ent->vd_hash; + map->l_versions[ndx].name = &strtab[aux->vda_name]; + map->l_versions[ndx].filename = NULL; + } + + if (ent->vd_next == 0) + break; + ent = (Elf64_Verdef *) ((char *) ent + ent->vd_next); + } + } + } +} + +const char *rtld_progname; + +static Elf64_Addr load_addr = 0xdead0000; + +static void +create_ldlibs_link_map (struct dso_list *cur_dso_ent) +{ + struct ldlibs_link_map *map = malloc (sizeof (struct ldlibs_link_map)); + DSO *dso = cur_dso_ent->dso; + int i; + Elf_Data *data; + Elf_Symndx *hash; + + memset (map, 0, sizeof (*map)); + cur_dso_ent->map = map; + + if (is_ldso_soname (cur_dso_ent->dso->soname)) + { + map->l_name = dso->filename; + rtld_progname = dso->filename; + } + else + map->l_name = dso->soname; + map->l_soname = dso->soname; + map->filename = dso->filename; + + if (dso->ehdr.e_type == ET_EXEC) + map->l_type = lt_executable; + else + map->l_type = lt_library; + + /* FIXME: gelfify, endianness issues */ + /* and leaks? */ + i = addr_to_sec (dso, dso->info[DT_SYMTAB]); + data = elf_getdata (dso->scn[i], NULL); + map->l_info[DT_SYMTAB] = data->d_buf; + + i = addr_to_sec (dso, dso->info[DT_STRTAB]); + data = elf_getdata (dso->scn[i], NULL); + map->l_info[DT_STRTAB] = data->d_buf; + + i = addr_to_sec (dso, dso->info[DT_HASH]); + data = elf_getdata (dso->scn[i], NULL); + hash = data->d_buf; + map->l_nbuckets = *hash; + map->l_buckets = hash + 2; + map->l_chain = hash + 2 + map->l_nbuckets; + + get_version_info (dso, map); + + map->l_map_start = load_addr; + load_addr += 0x1000; + + map->sym_base = dso->info[DT_SYMTAB] - dso->base; + + for (i = 0; i < dso->ehdr.e_phnum; ++i) + if (dso->phdr[i].p_type == PT_TLS) + { + map->l_tls_blocksize = dso->phdr[i].p_memsz; + map->l_tls_align = dso->phdr[i].p_align; + if (map->l_tls_align == 0) + map->l_tls_firstbyte_offset = 0; + else + map->l_tls_firstbyte_offset = dso->phdr[i].p_vaddr & (map->l_tls_align - 1); + break; + } +} + +struct +{ + void *symptr; + int rtypeclass; +} cache; + +void +do_rel_section (DSO *dso, struct ldlibs_link_map *map, + struct r_scope_elem *scope, + int tag, int section) +{ + Elf_Data *data; + int ndx, maxndx, sym, type; + struct r_found_version *ver; + int rtypeclass; + void *symptr; + const char *name; + Elf64_Word st_name; + + data = elf_getdata (dso->scn[section], NULL); + maxndx = data->d_size / dso->shdr[section].sh_entsize; + for (ndx = 0; ndx < maxndx; ndx++) + { + if (tag == DT_REL) + { + GElf_Rel rel; + gelfx_getrel (dso->elf, data, ndx, &rel); + sym = GELF_R_SYM (rel.r_info); + type = GELF_R_TYPE (rel.r_info); + } + else + { + GElf_Rela rela; + gelfx_getrela (dso->elf, data, ndx, &rela); + sym = GELF_R_SYM (rela.r_info); + type = GELF_R_TYPE (rela.r_info); + } + if (sym == 0) + continue; + if (map->l_versyms) + { + int vernum = map->l_versyms[sym] & 0x7fff; + ver = &map->l_versions[vernum]; + } + else + ver = NULL; + + rtypeclass = reloc_type_class (type, dso->ehdr.e_machine); + + if (gelf_getclass (dso->elf) == ELFCLASS32) + { + Elf32_Sym *sym32 = &((Elf32_Sym *)map->l_info[DT_SYMTAB])[sym]; + + if (ELF32_ST_BIND (sym32->st_info) == STB_LOCAL) + continue; + symptr = sym32; + st_name = sym32->st_name; + } + else + { + Elf64_Sym *sym64 = &((Elf64_Sym *)map->l_info[DT_SYMTAB])[sym]; + + if (ELF64_ST_BIND (sym64->st_info) == STB_LOCAL) + continue; + symptr = sym64; + st_name = sym64->st_name; + } + + if (cache.symptr == symptr && cache.rtypeclass == rtypeclass) + continue; + cache.symptr = symptr; + cache.rtypeclass = rtypeclass; + + name = ((const char *)map->l_info[DT_STRTAB]) + st_name; + + if (gelf_getclass (dso->elf) == ELFCLASS32) + { + if (ver && ver->hash) + rtld_lookup_symbol_versioned (name, symptr, scope, ver, rtypeclass, map, + dso->ehdr.e_machine); + else + rtld_lookup_symbol (name, symptr, scope, rtypeclass, map, dso->ehdr.e_machine); + } + else + { + if (ver && ver->hash) + rtld_lookup_symbol_versioned64 (name, symptr, scope, ver, rtypeclass, map, + dso->ehdr.e_machine); + else + rtld_lookup_symbol64 (name, symptr, scope, rtypeclass, map, dso->ehdr.e_machine); + } + } +} + +void +do_relocs (DSO *dso, struct ldlibs_link_map *map, struct r_scope_elem *scope, int tag) +{ + GElf_Addr rel_start, rel_end; + GElf_Addr pltrel_start, pltrel_end; + int first, last; + + /* Load the DT_REL or DT_RELA section. */ + if (dso->info[tag] != 0) + { + rel_start = dso->info[tag]; + rel_end = rel_start + dso->info[tag == DT_REL ? DT_RELSZ : DT_RELASZ]; + first = addr_to_sec (dso, rel_start); + last = addr_to_sec (dso, rel_end - 1); + while (first <= last) + do_rel_section (dso, map, scope, tag, first++); + + /* If the DT_JMPREL relocs are of the same type and not included, + load them too. Assume they overlap completely or not at all, + and are in at most a single section. They also need to be adjacent. */ + if (dso->info[DT_PLTREL] == tag) + { + pltrel_start = dso->info[DT_JMPREL]; + pltrel_end = pltrel_start + dso->info[DT_PLTRELSZ]; + if (pltrel_start < rel_start || pltrel_start >= rel_end) + do_rel_section (dso, map, scope, tag, addr_to_sec (dso, pltrel_start)); + } + } + else if (dso->info[DT_PLTREL] == tag) + do_rel_section (dso, map, scope, tag, addr_to_sec (dso, dso->info[DT_JMPREL])); +} + +void +handle_relocs (DSO *dso, struct dso_list *dso_list) +{ + struct dso_list *ldso, *tail; + + /* do them all last to first. + skip the dynamic linker; then do it last + in glibc this is conditional on the opencount; but every binary + should be linked to libc and thereby have an opencount for ld.so... + besides, that's the only way it would get on our dso list. */ + + tail = dso_list; + while (tail->next) + tail = tail->next; + + ldso = NULL; + while (tail) + { + if (is_ldso_soname (tail->dso->soname)) + ldso = tail; + else + { + /* Load the symbols and relocations. */ + do_relocs (tail->dso, tail->map, dso_list->map->l_local_scope, DT_REL); + do_relocs (tail->dso, tail->map, dso_list->map->l_local_scope, DT_RELA); + } + tail = tail->prev; + } + + if (ldso) + { + do_relocs (ldso->dso, ldso->map, dso_list->map->l_local_scope, DT_REL); + do_relocs (ldso->dso, ldso->map, dso_list->map->l_local_scope, DT_RELA); + } +} + +void +add_to_scope (struct r_scope_elem *scope, struct dso_list *ent) +{ + struct needed_list *n; + int i; + + for (i = 0; i < scope->r_nlist; i++) + if (scope->r_list[i] == ent->map) + return; + + scope->r_list[scope->r_nlist++] = ent->map; + n = ent->needed; + while (n) + { + add_to_scope (scope, n->ent); + n = n->next; + } +} + +void +build_local_scope (struct dso_list *ent, int max) +{ + ent->map->l_local_scope = malloc (sizeof (struct r_scope_elem)); + ent->map->l_local_scope->r_list = malloc (sizeof (struct ldlibs_link_map *) * max); + ent->map->l_local_scope->r_nlist = 0; + add_to_scope (ent->map->l_local_scope, ent); +} + +/* Assign TLS offsets for every loaded library. This code is taken + almost directly from glibc! */ + +#define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y)) + +static void +determine_tlsoffsets (int e_machine, struct r_scope_elem *search_list) +{ + uint64_t freetop = 0; + uint64_t freebottom = 0; + uint64_t offset; + uint64_t modid = 1; + int i; + + /* This comes from each architecture's ABI. If TLS_TCB_AT_TP, then + set offset to -1; if TLS_DTV_AT_TP, then set offset to + TLS_TCB_SIZE. */ + switch (e_machine) + { + case EM_X86_64: + offset = -1; + break; + + case EM_386: + offset = -1; + break; + + case EM_SH: + offset = 8; + break; + + case EM_PPC: + offset = 0; + break; + + case EM_PPC64: + offset = 0; + break; + + case EM_ARM: + offset = 8; + break; + + default: + /* Hope there's no TLS! */ + for (i = 0; i < search_list->r_nlist; i++) + { + struct ldlibs_link_map *map = search_list->r_list[i]; + + if (map->l_tls_blocksize > 0) + error (1, 0, "TLS encountered on an unsupported architecture"); + } + + return; + } + + /* Loop over the loaded DSOs. We use the symbol search order; this + should be the same as glibc's ordering, which traverses l_next. + It's somewhat important that we use both the same ordering to + assign module IDs and the same algorithm to assign offsets, + because the prelinker will resolve all relocations using these + offsets... and then glibc will recalculate them. Future dynamic + relocations in any loaded modules will use glibc's values. Also + if we take too much space here, glibc won't allocate enough + static TLS area to hold it. */ + + if (offset == (uint64_t) -1) + { + /* We simply start with zero. */ + offset = 0; + + for (i = 0; i < search_list->r_nlist; i++) + { + struct ldlibs_link_map *map = search_list->r_list[i]; + uint64_t firstbyte = (-map->l_tls_firstbyte_offset + & (map->l_tls_align - 1)); + uint64_t off; + + if (map->l_tls_blocksize == 0) + continue; + map->l_tls_modid = modid++; + + if (freebottom - freetop >= map->l_tls_blocksize) + { + off = roundup (freetop + map->l_tls_blocksize + - firstbyte, map->l_tls_align) + + firstbyte; + if (off <= freebottom) + { + freetop = off; + + map->l_tls_offset = off; + continue; + } + } + + off = roundup (offset + map->l_tls_blocksize - firstbyte, + map->l_tls_align) + firstbyte; + if (off > offset + map->l_tls_blocksize + + (freebottom - freetop)) + { + freetop = offset; + freebottom = off - map->l_tls_blocksize; + } + offset = off; + + map->l_tls_offset = off; + } + } + else + { + for (i = 0; i < search_list->r_nlist; i++) + { + struct ldlibs_link_map *map = search_list->r_list[i]; + uint64_t firstbyte = (-map->l_tls_firstbyte_offset + & (map->l_tls_align - 1)); + uint64_t off; + + if (map->l_tls_blocksize == 0) + continue; + map->l_tls_modid = modid++; + + if (map->l_tls_blocksize <= freetop - freebottom) + { + off = roundup (freebottom, map->l_tls_align); + if (off - freebottom < firstbyte) + off += map->l_tls_align; + if (off + map->l_tls_blocksize - firstbyte <= freetop) + { + map->l_tls_offset = off - firstbyte; + freebottom = (off + map->l_tls_blocksize + - firstbyte); + continue; + } + } + + off = roundup (offset, map->l_tls_align); + if (off - offset < firstbyte) + off += map->l_tls_align; + + map->l_tls_offset = off - firstbyte; + if (off - firstbyte - offset > freetop - freebottom) + { + freebottom = offset; + freetop = off - firstbyte; + } + + offset = off + map->l_tls_blocksize - firstbyte; + } + } +} + +static struct argp argp = { options, parse_opt, "[FILES]", argp_doc }; + +struct ldlibs_link_map *requested_map; + +static void process_one_dso (DSO *dso, int host_paths); + +int +main(int argc, char **argv) +{ + int remaining; + int multiple = 0; + host_paths = 1; + + sysroot = getenv ("PRELINK_SYSROOT"); +#ifdef DEFAULT_SYSROOT + if (sysroot == NULL) + { + extern char *make_relative_prefix (const char *, const char *, const char *); + sysroot = make_relative_prefix (argv[0], BINDIR, DEFAULT_SYSROOT); + } +#endif + + elf_version (EV_CURRENT); + + argp_parse (&argp, argc, argv, 0, &remaining, 0); + + if (sysroot) + sysroot = prelink_canonicalize (sysroot, NULL); + + if (remaining == argc) + error (1, 0, "missing file arguments\nTry `%s: --help' for more information.", argv[0]); + + if ((argc-remaining) >= 2) + multiple = 1; + + while (remaining < argc) + { + DSO *dso = NULL; + int i, fd; + + if (host_paths) + fd = open (argv[remaining], O_RDONLY); + else + fd = wrap_open (argv[remaining], O_RDONLY); + + if (fd >= 0) + dso = fdopen_dso (fd, argv[remaining]); + + if (dso == NULL) + error (1, errno, "Could not open %s", argv[remaining]); + + load_ld_so_conf (gelf_getclass (dso->elf) == ELFCLASS64); + + if (multiple) + printf ("%s:\n", argv[remaining]); + + for (i = 0; i < dso->ehdr.e_phnum; ++i) + if (dso->phdr[i].p_type == PT_INTERP) + break; + + /* If there are no PT_INTERP segments, it is statically linked. */ + if (dso->ehdr.e_type == ET_EXEC && i == dso->ehdr.e_phnum) + printf ("\tnot a dynamic executable\n"); + else + process_one_dso (dso, host_paths); + + remaining++; + } + + return 0; +} + +static void +process_one_dso (DSO *dso, int host_paths) +{ + struct dso_list *dso_list, *cur_dso_ent, *old_dso_ent; + const char *req = getenv ("RTLD_TRACE_PRELINKING"); + int i, flag; + int process_relocs = 0; + + /* Close enough. Really it's if LD_WARN is "" and RTLD_TRACE_PRELINKING. */ + if (getenv ("LD_WARN") == 0 && req != NULL) + process_relocs = 1; + + dso_list = load_dsos (dso); + + cur_dso_ent = dso_list; + i = 0; + while (cur_dso_ent) + { + if (cur_dso_ent->dso) + { + create_ldlibs_link_map (cur_dso_ent); + if (req && strcmp (req, cur_dso_ent->dso->filename) == 0) + requested_map = cur_dso_ent->map; + i++; + } + cur_dso_ent = cur_dso_ent->next; + } + dso_list->map->l_local_scope = malloc (sizeof (struct r_scope_elem)); + dso_list->map->l_local_scope->r_list = malloc (sizeof (struct ldlibs_link_map *) * i); + dso_list->map->l_local_scope->r_nlist = i; + cur_dso_ent = dso_list; + i = 0; + while (cur_dso_ent) + { + if (cur_dso_ent->dso) + { + dso_list->map->l_local_scope->r_list[i] = cur_dso_ent->map; + if (cur_dso_ent != dso_list) + build_local_scope (cur_dso_ent, dso_list->map->l_local_scope->r_nlist); + + i++; + } + cur_dso_ent = cur_dso_ent->next; + } + + determine_tlsoffsets (dso->ehdr.e_machine, dso_list->map->l_local_scope); + + cur_dso_ent = dso_list; + flag = 0; + /* In ldd mode, do not show the application. Note that we do show it + in list-loaded-objects RTLD_TRACE_PRELINK mode. */ + if (req == NULL && cur_dso_ent) + cur_dso_ent = cur_dso_ent->next; + while (cur_dso_ent) + { + char *filename; + + if (host_paths && sysroot && cur_dso_ent->dso) + { + const char *rooted_filename; + + if (cur_dso_ent->dso->filename[0] == '/') + rooted_filename = cur_dso_ent->dso->filename; + else + rooted_filename = wrap_prelink_canonicalize (cur_dso_ent->dso->filename, NULL); + + /* This covers the odd case where we have a sysroot set, + * but the item isn't in the sysroot! + */ + if (rooted_filename == NULL) + filename = strdup (cur_dso_ent->dso->filename); + else + { + filename = malloc (strlen (rooted_filename) + strlen (sysroot) + 1); + strcpy (filename, sysroot); + strcat (filename, rooted_filename); + } + } + else if (cur_dso_ent->dso) + filename = strdup (cur_dso_ent->dso->filename); + else + filename = NULL; + + /* The difference between the two numbers must be dso->base, + and the first number must be unique. */ + if (cur_dso_ent->dso == NULL) + printf ("\t%s => not found\n", cur_dso_ent->name); + else if (gelf_getclass (cur_dso_ent->dso->elf) == ELFCLASS32) + { + if (process_relocs) + { + printf ("\t%s => %s (0x%08x, 0x%08x)", + cur_dso_ent->name, filename, + (uint32_t) cur_dso_ent->map->l_map_start, + (uint32_t) (cur_dso_ent->map->l_map_start - cur_dso_ent->dso->base)); + if (cur_dso_ent->map->l_tls_modid) + printf (" TLS(0x%x, 0x%08x)", + (uint32_t) cur_dso_ent->map->l_tls_modid, + (uint32_t) cur_dso_ent->map->l_tls_offset); + printf ("\n"); + } + else + printf ("\t%s => %s (0x%08x)\n", + cur_dso_ent->name, filename, + (uint32_t) cur_dso_ent->map->l_map_start); + } + else + { + if (process_relocs) + { + printf ("\t%s => %s (0x%016" HOST_LONG_LONG_FORMAT + "x, 0x%016" HOST_LONG_LONG_FORMAT "x)", + cur_dso_ent->name, filename, + (unsigned long long) cur_dso_ent->map->l_map_start, + (unsigned long long) (cur_dso_ent->map->l_map_start - cur_dso_ent->dso->base)); + if (cur_dso_ent->map->l_tls_modid) + printf (" TLS(0x%x, 0x%016" HOST_LONG_LONG_FORMAT "x)", + (uint32_t) cur_dso_ent->map->l_tls_modid, + (unsigned long long) cur_dso_ent->map->l_tls_offset); + printf ("\n"); + } + else + printf ("\t%s => %s (0x%08x)\n", + cur_dso_ent->name, filename, + (uint32_t) cur_dso_ent->map->l_map_start); + } + + if (filename) + free (filename); + + cur_dso_ent = cur_dso_ent->next; + flag = 1; + } + + if (dso_open_error) + exit (1); + + if (process_relocs) + handle_relocs (dso_list->dso, dso_list); + + cur_dso_ent = dso_list; + while (cur_dso_ent) + { + if (cur_dso_ent->dso) + close_dso (cur_dso_ent->dso); + old_dso_ent = cur_dso_ent; + cur_dso_ent = cur_dso_ent->next; + if (old_dso_ent->needed) + free_needed (old_dso_ent->needed); + free (old_dso_ent); + } +} diff --git a/trunk/src/ld-libs.h b/trunk/src/ld-libs.h new file mode 100644 index 0000000..48dd555 --- /dev/null +++ b/trunk/src/ld-libs.h @@ -0,0 +1,113 @@ +#ifndef _LD_LIBS_H +#define _LD_LIBS_H + +#if !defined (__linux__) +#define DT_VERSIONTAGNUM 16 +#endif + +struct ldlibs_link_map; + +struct r_scope_elem +{ + struct ldlibs_link_map **r_list; + unsigned int r_nlist; +}; + +struct r_found_version + { + const char *name; + Elf64_Word hash; + + int hidden; + const char *filename; + }; + +/* The size of entries in .hash. Only Alpha and 64-bit S/390 use 64-bit + entries; those are not currently supported. */ +typedef uint32_t Elf_Symndx; + +struct ldlibs_link_map + { + const char *l_name; + struct r_scope_elem *l_local_scope; + enum { lt_executable, lt_library, lt_loaded } l_type; + void *l_info[DT_NUM + DT_VERSIONTAGNUM]; + + /* Symbol hash table. */ + Elf_Symndx l_nbuckets; + const Elf_Symndx *l_buckets, *l_chain; + + unsigned int l_nversions; + struct r_found_version *l_versions; + + /* Pointer to the version information if available. Fortunately, 32-bit + and 64-bit ELF use the same Versym type. */ + Elf64_Versym *l_versyms; + + /* for _dl_soname_match_p */ + const char *l_soname; + + Elf64_Addr l_map_start; + + Elf64_Addr sym_base; + const char *filename; + + /* For TLS. From the object file. */ + uint64_t l_tls_blocksize; + uint64_t l_tls_align; + uint64_t l_tls_firstbyte_offset; + + /* For TLS. Computed. */ + uint64_t l_tls_modid; + uint64_t l_tls_offset; + }; + +#define ELF_RTYPE_CLASS_COPY 2 +#define ELF_RTYPE_CLASS_PLT 1 + +#define GL(X) _ ## X +#define INTUSE(X) X + +#define D_PTR(MAP,MEM) MAP->MEM +#define VERSYMIDX(tag) DT_NUM + DT_VERSIONTAGIDX (tag) + +extern int _dl_debug_mask; +#define DL_DEBUG_SYMBOLS 0 +#define DL_LOOKUP_RETURN_NEWEST 0 +#define _dl_dynamic_weak 0 +extern const char *rtld_progname; +#define _dl_debug_printf printf + + +#define USE_TLS + +#ifndef rtld_lookup_symbol +void rtld_lookup_symbol (const char *name, const Elf32_Sym *sym, + struct r_scope_elem *scope, int rtypeclass, + struct ldlibs_link_map *undef_map, int machine); +void rtld_lookup_symbol_versioned (const char *name, const Elf32_Sym *sym, + struct r_scope_elem *scope, + struct r_found_version *version, int rtypeclass, + struct ldlibs_link_map *undef_map, int machine); +#endif + +void rtld_lookup_symbol64 (const char *name, const Elf64_Sym *sym, + struct r_scope_elem *scope, int rtypeclass, + struct ldlibs_link_map *undef_map, int machine); +void rtld_lookup_symbol_versioned64 (const char *name, const Elf64_Sym *sym, + struct r_scope_elem *scope, + struct r_found_version *version, int rtypeclass, + struct ldlibs_link_map *undef_map, int machine); + +extern struct ldlibs_link_map *requested_map; + +#define __builtin_expect(a,b) (a) + +#if defined(__MINGW32__) +# define HOST_LONG_LONG_FORMAT "I64" +#else +# define HOST_LONG_LONG_FORMAT "ll" +#endif + +#endif + diff --git a/trunk/src/ld-lookup.c b/trunk/src/ld-lookup.c new file mode 100644 index 0000000..69b6bd1 --- /dev/null +++ b/trunk/src/ld-lookup.c @@ -0,0 +1,214 @@ +/* Copyright (C) 2003 MontaVista Software, Inc. + Written by Daniel Jacobowitz <drow@mvista.com>, 2003 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <config.h> +#include <assert.h> +#include <errno.h> +#include <error.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/stat.h> +#include <unistd.h> + +#include "prelinktab.h" +#include "reloc.h" + +#include "ld-libs.h" + +#ifndef ElfW +/* Default to 32-bit. */ +#define ElfW(x) Elf32_##x +#define ELFW(x) ELF32_##x +#endif + +static int _dl_soname_match_p (const char *name, struct ldlibs_link_map *map); + +struct sym_val +{ + const ElfW(Sym) *s; + struct ldlibs_link_map *m; +}; + +#include "ld-do-lookup.h" +#define VERSIONED 1 +#include "ld-do-lookup.h" +#undef VERSIONED + +static unsigned long +rtld_elf_hash (const char *name) +{ + const unsigned char *str = (const unsigned char *) name; + unsigned long int hash, hi; + hash = *str++; + while (*str != '\0') + { + hash = (hash << 4) + *str++; + hi = hash & 0xf0000000; + hash ^= hi; + hash ^= hi >> 24; + } + return hash & 0xffffffff; +} + +static int +_dl_soname_match_p (const char *name, struct ldlibs_link_map *map) +{ + if (strcmp (name, map->l_name) == 0) + return 1; + if (strcmp (name, map->l_soname) == 0) + return 1; + return 0; +} + +#if 0 +void +rtld_lookup_symbol (const char *name, const ElfW(Sym) *sym, + struct r_scope_elem *scope, int rtypeclass, + struct ldlibs_link_map *undef_map, int machine) +{ + int ret; + struct sym_val result; + + result.s = NULL; + ret = do_lookup (name, rtld_elf_hash (name), sym, + &result, scope, 0, 0, NULL, rtypeclass); + if (ret > 0) + printf ("name %s /%d\n", name, rtypeclass); +#if 0 + printf ("name %s ret %d", name, ret); + if (result.s) + printf (" result sym 0x%08x (in %s)", result.s->st_value, result.m->l_name); + printf ("\n"); +#endif +} +#endif + +void +rtld_lookup_symbol (const char *name, const ElfW(Sym) *sym, + struct r_scope_elem *scope, + int rtypeclass, + struct ldlibs_link_map *undef_map, int machine) +{ + rtld_lookup_symbol_versioned (name, sym, scope, NULL, rtypeclass, undef_map, machine); +} + +void +rtld_lookup_symbol_versioned (const char *name, const ElfW(Sym) *sym, + struct r_scope_elem *scope, + struct r_found_version *version, int rtypeclass, + struct ldlibs_link_map *undef_map, int machine) +{ + int ret; + int conflict = 0; + int sym_offset; + struct sym_val result, result2; + unsigned int value1, value2; + + result.s = NULL; + result.m = NULL; + result2.s = NULL; + result2.m = NULL; + if (version) + ret = do_lookup_versioned (name, rtld_elf_hash (name), sym, + &result, scope, 0, version, NULL, rtypeclass, + machine); + else + ret = do_lookup (name, rtld_elf_hash (name), sym, + &result, scope, 0, 0, NULL, rtypeclass, + machine); + + if (result.s == NULL && ELFW(ST_BIND) (sym->st_info) != STB_WEAK) + printf ("undefined symbol: %s\t(%s)\n", name, undef_map->filename); + + if (ret <= 0) + return; + + /* Don't do conflict checking for references in the executable. */ + if (undef_map->l_local_scope != scope) + { + result2.s = NULL; + result2.m = NULL; + if (version) + ret = do_lookup_versioned (name, rtld_elf_hash (name), sym, + &result2, undef_map->l_local_scope, 0, version, + NULL, rtypeclass, machine); + else + ret = do_lookup (name, rtld_elf_hash (name), sym, + &result2, undef_map->l_local_scope, 0, 0, + NULL, rtypeclass, machine); + + if (result2.s != result.s + || result2.m != result.m) + conflict = 1; + } + + if (result.s && ELFW(ST_TYPE) (result.s->st_info) == STT_TLS) + rtypeclass = 4; + + /* Print out information for the requested object, all conflicts, and all TLS. */ + if (!conflict + && rtypeclass != 4 + && requested_map + && requested_map != undef_map) + return; + + /* FIXME: Careful with this if we change the size of symbols when reading in! */ + sym_offset = ((char *)sym) - ((char *)undef_map->l_info[DT_SYMTAB]); + sym_offset += undef_map->sym_base; + + value1 = 0; + if (machine == EM_ARM && result.s + && ELFW(ST_TYPE) (result.s->st_info) == STT_ARM_TFUNC) + value1 = 1; + + value2 = 0; + if (machine == EM_ARM && conflict && result2.s + && ELFW(ST_TYPE) (result2.s->st_info) == STT_ARM_TFUNC) + value2 = 1; + +#if defined(rtld_lookup_symbol) /* 64-bit */ + printf ("%s 0x%016" HOST_LONG_LONG_FORMAT "x " + "0x%016" HOST_LONG_LONG_FORMAT "x " + "-> 0x%016" HOST_LONG_LONG_FORMAT "x " + "0x%016" HOST_LONG_LONG_FORMAT "x ", + conflict ? "conflict" : "lookup", + (unsigned long long) undef_map->l_map_start, + (unsigned long long) sym_offset, + (unsigned long long) (result.s ? result.m->l_map_start : 0), + (unsigned long long) (result.s ? result.s->st_value | value1 : 0)); + if (conflict) + printf ("x 0x%016" HOST_LONG_LONG_FORMAT "x " + "0x%016" HOST_LONG_LONG_FORMAT "x ", + (unsigned long long) (result2.s ? result2.m->l_map_start : 0), + (unsigned long long) (result2.s ? result2.s->st_value | value2 : 0)); +#else + printf ("%s 0x%08x 0x%08x -> 0x%08x 0x%08x ", + conflict ? "conflict" : "lookup", + (uint32_t) undef_map->l_map_start, + (uint32_t) sym_offset, + (uint32_t) (result.s ? result.m->l_map_start : 0), + (uint32_t) (result.s ? result.s->st_value | value1 : 0)); + if (conflict) + printf ("x 0x%08x 0x%08x ", + (uint32_t) (result2.s ? result2.m->l_map_start : 0), + (uint32_t) (result2.s ? result2.s->st_value | value2 : 0)); +#endif + printf ("/%x %s\n", rtypeclass, name); +} + diff --git a/trunk/src/ld-lookup64.c b/trunk/src/ld-lookup64.c new file mode 100644 index 0000000..7e35334 --- /dev/null +++ b/trunk/src/ld-lookup64.c @@ -0,0 +1,24 @@ +/* Copyright (C) 2003 MontaVista Software, Inc. + Written by Daniel Jacobowitz <drow@mvista.com>, 2003 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#define ElfW(x) Elf64_ ## x +#define ELFW(x) ELF64_ ## x + +#define rtld_lookup_symbol rtld_lookup_symbol64 +#define rtld_lookup_symbol_versioned rtld_lookup_symbol_versioned64 + +#include "ld-lookup.c" diff --git a/trunk/src/main.c b/trunk/src/main.c index 9c8b082..631da44 100644 --- a/trunk/src/main.c +++ b/trunk/src/main.c @@ -58,10 +58,12 @@ const char *ld_library_path; const char *prelink_conf = PRELINK_CONF; const char *prelink_cache = PRELINK_CACHE; const char *undo_output; +int noreexecinit; +time_t initctime; -const char *argp_program_version = "prelink 1.0"; +const char *argp_program_version = "prelink 1.0 (20061201) Wind River Linux"; -const char *argp_program_bug_address = "<jakub@redhat.com>"; +const char *argp_program_bug_address = "<support@windriver.com>"; static char argp_doc[] = "prelink -- program to relocate and prelink ELF shared libraries and programs"; @@ -77,6 +79,8 @@ static char argp_doc[] = "prelink -- program to relocate and prelink ELF shared #define OPT_MD5 0x89 #define OPT_SHA 0x8a #define OPT_COMPUTE_CHECKSUM 0x8b +#define OPT_SYSROOT 0x8c +#define OPT_RTLD 0x8d static struct argp_option options[] = { {"all", 'a', 0, 0, "Prelink all binaries" }, @@ -94,6 +98,7 @@ static struct argp_option options[] = { {"quick", 'q', 0, 0, "Quick scan" }, {"random", 'R', 0, 0, "Choose random base for libraries" }, {"reloc-only", 'r', "BASE_ADDRESS", 0, "Relocate library to given address, don't prelink" }, + {"root", OPT_SYSROOT, "ROOT_PATH", 0, "Prefix all paths with ROOT_PATH" }, {"undo", 'u', 0, 0, "Undo prelink" }, {"verbose", 'v', 0, 0, "Produce verbose output" }, {"verify", 'y', 0, 0, "Verify file consistency by undoing and redoing prelink and printing original to standard output" }, @@ -111,6 +116,8 @@ static struct argp_option options[] = { {"mmap-region-end", OPT_MMAP_REG_END, "BASE_ADDRESS", OPTION_HIDDEN, "" }, {"seed", OPT_SEED, "SEED", OPTION_HIDDEN, "" }, {"compute-checksum", OPT_COMPUTE_CHECKSUM, 0, OPTION_HIDDEN, "" }, + {"rtld", OPT_RTLD, "RTLD", OPTION_HIDDEN, "" }, + {"init", 'i', 0, 0, "Do not re-execute init" }, { 0 } }; @@ -222,14 +229,39 @@ parse_opt (int key, char *arg, struct argp_state *state) case OPT_COMPUTE_CHECKSUM: compute_checksum = 1; break; + case OPT_SYSROOT: + sysroot = arg; + break; + case OPT_RTLD: + prelink_rtld = arg; + break; + case 'i': + noreexecinit=1; + break; default: return ARGP_ERR_UNKNOWN; } return 0; } +time_t get_ctime(const char *file) { + struct stat st; + if(stat(file,&st) == 0) + return st.st_ctime; + return 0; +} + +void checkinit() { + if(initctime != get_ctime("/sbin/init")) { + printf("Executing /sbin/init U\n"); + system("/sbin/init U"); + } +} + static struct argp argp = { options, parse_opt, "[FILES]", argp_doc }; +const char *prelink_rtld = NULL; + int main (int argc, char *argv[]) { @@ -237,9 +269,7 @@ main (int argc, char *argv[]) setlocale (LC_ALL, ""); - /* Set the default for exec_shield. */ - if (! access ("/proc/sys/kernel/exec-shield", F_OK)) - exec_shield = 1; + exec_shield = 2; prelink_init_cache (); @@ -247,6 +277,11 @@ main (int argc, char *argv[]) argp_parse (&argp, argc, argv, 0, &remaining, 0); + if(!noreexecinit) { + initctime = get_ctime("/sbin/init"); + atexit(checkinit); + } + if (ld_library_path == NULL) ld_library_path = getenv ("LD_LIBRARY_PATH"); @@ -261,6 +296,43 @@ main (int argc, char *argv[]) if ((undo || verify) && quick) error (EXIT_FAILURE, 0, "--undo and --quick options are incompatible"); + /* Set the default for exec_shield. */ + if (exec_shield == 2) + { + if (sysroot == NULL && ! access ("/proc/sys/kernel/exec-shield", F_OK)) + exec_shield = 1; + else + exec_shield = 0; + } + +#ifdef DEFAULT_SYSROOT + if (sysroot == NULL) + { + extern char *make_relative_prefix (const char *, const char *, const char *); + sysroot = make_relative_prefix (argv[0], BINDIR, DEFAULT_SYSROOT); + } +#endif + + if (sysroot) + { + sysroot = prelink_canonicalize (sysroot, NULL); + if (sysroot == NULL) + error (EXIT_FAILURE, 0, "Could not canonicalize --root argument"); + asprintf ((char **) &prelink_conf, "%s%s", sysroot, prelink_conf); + } + + if (prelink_rtld == NULL) + { + extern char *make_relative_prefix (const char *, const char *, const char *); + const char *path = make_relative_prefix (argv[0], BINDIR, BINDIR); + if (strchr (argv[0], '/')) + asprintf ((char **) &prelink_rtld, "%s-rtld", argv[0]); + else + asprintf ((char **) &prelink_rtld, "%s/%s-rtld", path, argv[0]); + } + else if (prelink_rtld[0] == 0) + prelink_rtld = NULL; + if (print_cache) { prelink_load_cache (); diff --git a/trunk/src/prelink.c b/trunk/src/prelink.c index 7586c9b..1a2260e 100644 --- a/trunk/src/prelink.c +++ b/trunk/src/prelink.c @@ -793,7 +793,9 @@ prelink_set_timestamp (struct prelink_info *info) DSO *dso = info->dso; if (! verify) - info->ent->timestamp = (GElf_Word) time (NULL); + info->ent->timestamp = getenv ("PRELINK_TIMESTAMP") ? + atoi (getenv ("PRELINK_TIMESTAMP")) + : (GElf_Word) time (NULL); dso->info_DT_GNU_PRELINKED = info->ent->timestamp; if (prelink_set_checksum (dso)) return 1; diff --git a/trunk/src/prelink.h b/trunk/src/prelink.h index 5aedaf6..0118602 100644 --- a/trunk/src/prelink.h +++ b/trunk/src/prelink.h @@ -21,10 +21,12 @@ #include <elf.h> #include <libelf.h> #include <gelfx.h> +#include <ftw.h> #include <stdint.h> #include <stdlib.h> #include <stdio.h> #include <sys/stat.h> +#include <utime.h> #ifndef DT_GNU_LIBLIST #define DT_GNU_LIBLIST 0x6ffffef9 @@ -150,6 +152,7 @@ struct PLArch int alternate_machine[3]; int max_reloc_size; const char *dynamic_linker; + const char *dynamic_linker_alt; int R_COPY; int R_JMP_SLOT; int R_RELATIVE; @@ -260,7 +263,7 @@ struct data_iterator { GElf_Addr sec_offset; }; -unsigned char * get_data (DSO *dso, GElf_Addr addr, int *scnp); +unsigned char * get_data (DSO *dso, GElf_Addr addr, int *scnp, Elf_Type *typep); #define READWRITEPROTO(le,nn) \ uint##nn##_t buf_read_u##le##nn (unsigned char *data); \ uint##nn##_t read_u##le##nn (DSO *dso, GElf_Addr addr); \ @@ -504,4 +507,21 @@ extern int quick; extern long long seed; extern GElf_Addr mmap_reg_start, mmap_reg_end; +extern const char *sysroot; + +char *wrap_prelink_canonicalize (const char *name, struct stat64 *stp); +int wrap_lstat64 (const char *file, struct stat64 *buf); +int wrap_stat64 (const char *file, struct stat64 *buf); +int wrap_open (const char *file, int mode, ...); +int wrap_access (const char *file, int mode); +int wrap_rename (const char *old, const char *new); +int wrap_link (const char *old, const char *new); +int wrap_nftw64 (const char *dir, __nftw64_func_t func, + int descriptors, int flag); +int wrap_utime (const char *file, struct utimbuf *file_times); +int wrap_mkstemp (char *filename); +int wrap_unlink (const char *filename); + +extern const char *prelink_rtld; + #endif /* PRELINK_H */ diff --git a/trunk/src/undoall.c b/trunk/src/undoall.c index 4ce4670..90e9240 100644 --- a/trunk/src/undoall.c +++ b/trunk/src/undoall.c @@ -88,7 +88,7 @@ undo_one (void **p, void *info) { size_t len; - if (lstat64 (hardlink->canon_filename, &st) < 0) + if (wrap_lstat64 (hardlink->canon_filename, &st) < 0) { error (0, 0, "Could not stat %s (former hardlink to %s)", hardlink->canon_filename, ent->canon_filename); @@ -128,19 +128,19 @@ undo_one (void **p, void *info) memcpy (mempcpy (move, hardlink->canon_filename, len), ".#prelink#", sizeof (".#prelink#")); - if (rename (hardlink->canon_filename, move) < 0) + if (wrap_rename (hardlink->canon_filename, move) < 0) { error (0, errno, "Could not hardlink %s to %s", hardlink->canon_filename, ent->canon_filename); continue; } - if (link (ent->canon_filename, hardlink->canon_filename) < 0) + if (wrap_link (ent->canon_filename, hardlink->canon_filename) < 0) { error (0, errno, "Could not hardlink %s to %s", hardlink->canon_filename, ent->canon_filename); - if (rename (move, hardlink->canon_filename) < 0) + if (wrap_rename (move, hardlink->canon_filename) < 0) { error (0, errno, "Could not rename %s back to %s", move, hardlink->canon_filename); @@ -148,7 +148,7 @@ undo_one (void **p, void *info) continue; } - if (unlink (move) < 0) + if (wrap_unlink (move) < 0) { error (0, errno, "Could not unlink %s", move); continue; diff --git a/trunk/src/verify.c b/trunk/src/verify.c index 7945ced..8acecfb 100644 --- a/trunk/src/verify.c +++ b/trunk/src/verify.c @@ -193,7 +193,7 @@ prelink_verify (const char *filename) size_t count; char *p, *q; - if (stat64 (filename, &st) < 0) + if (wrap_stat64 (filename, &st) < 0) error (EXIT_FAILURE, errno, "Couldn't stat %s", filename); dso = open_dso (filename); @@ -266,7 +266,7 @@ prelink_verify (const char *filename) break; } - fd = open (dso->temp_filename, O_RDONLY); + fd = wrap_open (dso->temp_filename, O_RDONLY); if (fd < 0) { error (0, errno, "Could not verify %s", filename); @@ -432,7 +432,7 @@ failure: not_prelinked: if (dso) close_dso (dso); - fd = open (filename, O_RDONLY); + fd = wrap_open (filename, O_RDONLY); if (fd < 0) error (EXIT_FAILURE, errno, "Couldn't open %s", filename); if (handle_verify (fd, filename)) diff --git a/trunk/src/wrap-file.c b/trunk/src/wrap-file.c new file mode 100644 index 0000000..c631458 --- /dev/null +++ b/trunk/src/wrap-file.c @@ -0,0 +1,536 @@ +/* Copyright (C) 2003 MontaVista Software, Inc. + Written by Daniel Jacobowitz <drow@mvista.com>, 2003. + + The chroot_canon function is copied from the GNU C Library, + elf/chroot-canon.c, also licensed under the GPL: + Copyright (C) 1996,1997,1998,1999,2000,2001 Free Software Foundation, Inc. + [and then further modified.] + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <config.h> +#include <assert.h> +#include <errno.h> +#include <error.h> +#include <fcntl.h> +#include <ftw.h> +#include <stdarg.h> +#include <stddef.h> +#include <string.h> +#include <sys/stat.h> +#include <sys/time.h> +#include <time.h> +#include <unistd.h> +#include <utime.h> +#include "prelink.h" + +#ifndef PATH_MAX +#define PATH_MAX 1024 +#endif + +#ifndef MAXSYMLINKS +#define MAXSYMLINKS 20 +#endif + +/* Return the canonical absolute name of file NAME as if chroot(CHROOT) was + done first. A canonical name does not contain any `.', `..' components + nor any repeated path separators ('/') or symlinks. All path components + must exist and NAME must be absolute filename. The result is malloc'd. + The returned name includes the CHROOT prefix. + + If ALLOW_LAST_LINK, then symlinks in the last component won't be + resolved. */ + +static char * +chroot_canon_filename (const char * chroot, const char *name, int allow_last_link, struct stat64 *stp) +{ + char *rpath, *dest, *extra_buf = NULL; + char *rpath_root; + const char *start, *end, *rpath_limit; + long int path_max; + int num_links = 0; + int stp_initialized = 0; + size_t chroot_len = 0; + + if (name == NULL) + { + errno = EINVAL; + return NULL; + } + + if (name[0] == '\0') + { + errno = ENOENT; + return NULL; + } + + if (chroot == NULL) + { + errno = EINVAL; + return NULL; + } + + chroot_len = strlen (chroot); + +#ifdef PATH_MAX + path_max = PATH_MAX; +#else + path_max = pathconf (name, _PC_PATH_MAX); + if (path_max <= 0) + path_max = 1024; +#endif + + rpath = malloc (chroot_len + path_max); + if (rpath == NULL) + return NULL; + rpath_limit = rpath + chroot_len + path_max; + + rpath_root = (char *) mempcpy (rpath, chroot, chroot_len) - 1; + if (*rpath_root != '/') + *++rpath_root = '/'; + dest = rpath_root + 1; + + for (start = end = name; *start; start = end) + { + int n; + + /* Skip sequence of multiple path-separators. */ + while (*start == '/') + ++start; + + /* Find end of path component. */ + for (end = start; *end && *end != '/'; ++end) + /* Nothing. */; + + if (end - start == 0) + break; + else if (end - start == 1 && start[0] == '.') + /* nothing */; + else if (end - start == 2 && start[0] == '.' && start[1] == '.') + { + /* Back up to previous component, ignore if at root already. */ + if (dest > rpath_root + 1) + while ((--dest)[-1] != '/'); + stp_initialized = 0; + } + else + { + size_t new_size; + + if (dest[-1] != '/') + *dest++ = '/'; + + if (dest + (end - start) >= rpath_limit) + { + ptrdiff_t dest_offset = dest - rpath; + char *new_rpath; + + new_size = rpath_limit - rpath; + if (end - start + 1 > path_max) + new_size += end - start + 1; + else + new_size += path_max; + new_rpath = (char *) realloc (rpath, new_size); + if (new_rpath == NULL) + goto error; + rpath = new_rpath; + rpath_limit = rpath + new_size; + + dest = rpath + dest_offset; + } + + dest = mempcpy (dest, start, end - start); + *dest = '\0'; + + if (lstat64 (rpath, stp) < 0) + goto error; + + stp_initialized = 1; + + if (allow_last_link && *end == '\0') + goto done; + + if (S_ISLNK (stp->st_mode)) + { + char *buf = alloca (path_max); + size_t len; + + if (++num_links > MAXSYMLINKS) + { + errno = ELOOP; + goto error; + } + + n = readlink (rpath, buf, path_max); + if (n < 0) + goto error; + buf[n] = '\0'; + + if (!extra_buf) + extra_buf = alloca (path_max); + + len = strlen (end); + if ((long int) (n + len) >= path_max) + { + errno = ENAMETOOLONG; + goto error; + } + + /* Careful here, end may be a pointer into extra_buf... */ + memmove (&extra_buf[n], end, len + 1); + name = end = memcpy (extra_buf, buf, n); + + if (buf[0] == '/') + dest = rpath_root + 1; /* It's an absolute symlink */ + else + /* Back up to previous component, ignore if at root already: */ + if (dest > rpath_root + 1) + while ((--dest)[-1] != '/'); + } + else if (!S_ISDIR (stp->st_mode) && *end != '\0') + { + errno = ENOTDIR; + goto error; + } + } + } +done: + if (dest > rpath_root + 1 && dest[-1] == '/') + --dest; + *dest = '\0'; + + if (!stp_initialized && lstat64 (rpath, stp) < 0) + goto error; + + if (dest + 1 - rpath <= (rpath_limit - rpath) / 2) + { + char *new_rpath = realloc (rpath, dest + 1 - rpath); + + if (new_rpath != NULL) + return new_rpath; + } + return rpath; + +error: + free (rpath); + return NULL; +} + + +const char *sysroot; + +static char * +sysroot_file_name (const char *name, int allow_last_link, struct stat64 *stp) +{ + char *ret; + struct stat64 st; + + if (sysroot == NULL || name == NULL) + return (char *) name; + + if (name[0] != '/') + { + char *tmpname = malloc (strlen (name) + 2); + strcpy (tmpname, "/"); + strcat (tmpname, name); + ret = chroot_canon_filename (sysroot, tmpname, allow_last_link, stp ? stp : &st); + free (tmpname); + } + else + ret = chroot_canon_filename (sysroot, name, allow_last_link, stp ? stp : &st); + + if (ret == NULL) + { + char *ret_root; + + ret = malloc(strlen(sysroot) + strlen(name) + 1); + ret_root = mempcpy(ret, sysroot, strlen(sysroot)); + ret_root = mempcpy(ret_root, name, strlen(name)); + *ret_root='\0'; + } + return ret; +} + +static char * +unsysroot_file_name (const char *name) +{ + if (name == NULL) + return (char *)name; + + if (sysroot) + { + int sysroot_len = strlen (sysroot); + if (strncmp (name, sysroot, sysroot_len) == 0) + { + if (name[sysroot_len] == '/') + return strdup (name + sysroot_len); + else if (name[sysroot_len] == 0) + return strdup ("/"); + } + } + return (char *)name; +} + +char * +wrap_prelink_canonicalize (const char *name, struct stat64 *stp) +{ + if (sysroot) + { + struct stat64 st; + char *tmpname; + char *ret; + + /* Use chroot_canon_filename because we want a NULL return if it doesn't exist! */ + tmpname = chroot_canon_filename (sysroot, name, 0, stp ? stp : &st); + + if (tmpname == NULL) + return NULL; + + ret = unsysroot_file_name (tmpname); + + if (ret == tmpname) + ret = strdup (ret); + + if (tmpname != name) + free (tmpname); + + return ret; + } + else + return prelink_canonicalize(name, stp); +} + +int +wrap_lstat64 (const char *file, struct stat64 *buf) +{ + char *tmpname = sysroot_file_name (file, 1, NULL); + int ret; + + if (tmpname == NULL) + return -1; + + ret = lstat64 (tmpname, buf); + + if (tmpname != file) + free (tmpname); + return ret; +} + +int +wrap_stat64 (const char *file, struct stat64 *buf) +{ + char* file_copy; + char *tmpname; + int ret; + int len; + + tmpname = sysroot_file_name (file, 0, NULL); + + if (tmpname == NULL) + return -1; + + file_copy = strdup (tmpname); + + if (tmpname != file) + free (tmpname); + + if (file_copy == NULL) + return -1; + + len = strlen (file_copy); + if (file_copy[len - 1] == '/') + file_copy[len - 1] = '\0'; + + ret = stat64 (file_copy, buf); + + free (file_copy); + + return ret; +} + +int +wrap_rename (const char *old, const char *new) +{ + char *tmpold = sysroot_file_name (old, 1, NULL); + char *tmpnew; + int ret; + + if (tmpold == NULL) + return -1; + + tmpnew = sysroot_file_name (new, 1, NULL); + if (tmpnew == NULL) + return -1; + + ret = rename (tmpold, tmpnew); + + if (tmpold != old) + free (tmpold); + if (tmpnew != new) + free (tmpnew); + return ret; +} + +int +wrap_open (const char *name, int mode, ...) +{ + char *tmpname = sysroot_file_name (name, 0, NULL); + int ret; + + if (tmpname == NULL) + return -1; + + if (mode & O_CREAT) + { + va_list va; + int flags; + va_start (va, mode); + flags = va_arg (va, int); + va_end (va); + ret = open (tmpname, mode, flags); + } + else + ret = open (tmpname, mode); + + if (tmpname != name) + free (tmpname); + return ret; +} + +int +wrap_access (const char *name, int mode) +{ + char *tmpname = sysroot_file_name (name, 0, NULL); + int ret; + + if (tmpname == NULL) + return -1; + + ret = access (tmpname, mode); + + if (tmpname != name) + free (tmpname); + return ret; +} + +int +wrap_link (const char *old, const char *new) +{ + char *tmpold = sysroot_file_name (old, 1, NULL); + char *tmpnew; + int ret; + + if (tmpold == NULL) + return -1; + + tmpnew = sysroot_file_name (new, 1, NULL); + if (tmpnew == NULL) + return -1; + + ret = link (tmpold, tmpnew); + + if (tmpold != old) + free (tmpold); + if (tmpnew != new) + free (tmpnew); + return ret; +} + +/* Note that this isn't recursive safe, since nftw64 doesn't + pass an opaque object around to use. But that fits our needs + for now. */ + +static __nftw64_func_t nftw64_cur_func; + +static int +wrap_nftw64_func (const char *filename, const struct stat64 *status, + int flag, struct FTW *info) +{ + char *tmpname = unsysroot_file_name (filename); + int ret = nftw64_cur_func (tmpname, status, flag, info); + + if (tmpname != filename) + free (tmpname); + return ret; +} + +int +wrap_nftw64 (const char *dir, __nftw64_func_t func, + int descriptors, int flag) +{ + char *tmpdir = sysroot_file_name (dir, 1, NULL); + int ret; + + if (tmpdir == NULL) + return -1; + + nftw64_cur_func = func; + ret = nftw64 (tmpdir, wrap_nftw64_func, descriptors, flag); + + if (tmpdir != dir) + free (tmpdir); + return ret; +} + +int +wrap_utime (const char *file, struct utimbuf *file_times) +{ + char *tmpname = sysroot_file_name (file, 0, NULL); + int ret; + + if (tmpname == NULL) + return -1; + + ret = utime (tmpname, file_times); + + if (tmpname != file) + free (tmpname); + return ret; +} + +int +wrap_mkstemp (char *filename) +{ + char *tmpname = sysroot_file_name (filename, 1, NULL); + int ret; + + if (tmpname == NULL) + return -1; + + ret = mkstemp (tmpname); + + if (tmpname != filename) + { + strcpy (filename, tmpname + strlen (sysroot)); + free (tmpname); + } + return ret; +} + +int +wrap_unlink (const char *filename) +{ + char *tmpname = sysroot_file_name (filename, 1, NULL); + int ret; + + if (tmpname == NULL) + return -1; + + ret = unlink (tmpname); + + if (tmpname != filename) + free (tmpname); + return ret; +} diff --git a/trunk/testsuite/Makefile.in b/trunk/testsuite/Makefile.in index 53feb82..205f6e3 100644 --- a/trunk/testsuite/Makefile.in +++ b/trunk/testsuite/Makefile.in @@ -161,7 +161,9 @@ check-TESTS: $(TESTS) if test -f ./$$tst; then dir=./; \ elif test -f $$tst; then dir=; \ else dir="$(srcdir)/"; fi; \ - if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \ + $(TESTS_ENVIRONMENT) $${dir}$$tst; \ + ret=$$?; \ + if test $$ret -eq 0; then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ *" $$tst "*) \ @@ -173,16 +175,16 @@ check-TESTS: $(TESTS) echo "PASS: $$tst"; \ ;; \ esac; \ - elif test $$? -ne 77; then \ + elif test $$ret -ne 77; then \ all=`expr $$all + 1`; \ case " $(XFAIL_TESTS) " in \ *" $$tst "*) \ xfail=`expr $$xfail + 1`; \ - echo "XFAIL: $$tst"; \ + echo "XFAIL: $$tst ($$ret)"; \ ;; \ *) \ failed=`expr $$failed + 1`; \ - echo "FAIL: $$tst"; \ + echo "FAIL: $$tst ($$ret)"; \ ;; \ esac; \ fi; \ diff --git a/trunk/testsuite/cxx1.sh b/trunk/testsuite/cxx1.sh index a48cc65..81428c2 100755 --- a/trunk/testsuite/cxx1.sh +++ b/trunk/testsuite/cxx1.sh @@ -11,7 +11,9 @@ savelibs echo $PRELINK -vvvv ${PRELINK_OPTS--vm} ./cxx1 > cxx1.log $PRELINK -vvvv ${PRELINK_OPTS--vm} ./cxx1 >> cxx1.log 2>&1 || exit 1 grep ^`echo $PRELINK | sed 's/ .*$/: /'` cxx1.log | grep -q -v 'C++ conflict' && exit 2 -LD_LIBRARY_PATH=. ./cxx1 || exit 3 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./cxx1 || exit 3 +fi readelf -a ./cxx1 >> cxx1.log 2>&1 || exit 4 # So that it is not prelinked again chmod -x ./cxx1 diff --git a/trunk/testsuite/cycle1.sh b/trunk/testsuite/cycle1.sh index 3dc7f93..caf7864 100755 --- a/trunk/testsuite/cycle1.sh +++ b/trunk/testsuite/cycle1.sh @@ -18,6 +18,8 @@ grep -v 'has a dependency cycle' cycle1.log \ | grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` && exit 2 grep -q "^`echo $PRELINK | sed 's/ .*$/: .*has a dependency cycle/'`" \ cycle1.log || exit 3 -LD_LIBRARY_PATH=. ./cycle1 || exit 4 +if [ "x$CROSS" = "x" ] ; then + LD_LIBRARY_PATH=. ./cycle1 || exit 4 +fi # So that it is not prelinked again chmod -x ./cycle1 diff --git a/trunk/testsuite/cycle2.sh b/trunk/testsuite/cycle2.sh index 0b99a5d..a160a3a 100755 --- a/trunk/testsuite/cycle2.sh +++ b/trunk/testsuite/cycle2.sh @@ -21,6 +21,8 @@ grep -v 'has a dependency cycle' cycle2.log \ | grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` && exit 2 grep -q "^`echo $PRELINK | sed 's/ .*$/: .*has a dependency cycle/'`" \ cycle2.log || exit 3 -LD_LIBRARY_PATH=. ./cycle2 || exit 4 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./cycle2 || exit 4 +fi # So that it is not prelinked again chmod -x ./cycle2 diff --git a/trunk/testsuite/deps1.sh b/trunk/testsuite/deps1.sh index c345c07..96395fa 100755 --- a/trunk/testsuite/deps1.sh +++ b/trunk/testsuite/deps1.sh @@ -41,7 +41,9 @@ chmod 644 `ls $BINS | sed 's|$|.orig|'` echo $PRELINK ${PRELINK_OPTS--v} -avvvvv > deps1.log $PRELINK ${PRELINK_OPTS--v} -avvvvv > deps1.tree/etc/log1 2>&1 || exit 1 cat deps1.tree/etc/log1 >> deps1.log -LD_LIBRARY_PATH=deps1.tree/lib deps1.tree/usr/bin/bin1 || exit 2 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=deps1.tree/lib deps1.tree/usr/bin/bin1 || exit 2 +fi readelf -d deps1.tree/{usr,opt}/lib/lib1.so 2>&1 | grep CHECKSUM >> deps1.log || exit 3 readelf -A deps1.tree/usr/lib/lib1.so >> deps1.log 2>&1 || exit 4 readelf -A deps1.tree/opt/lib/lib1.so >> deps1.log 2>&1 || exit 5 diff --git a/trunk/testsuite/deps2.sh b/trunk/testsuite/deps2.sh index 636023c..4838f9b 100755 --- a/trunk/testsuite/deps2.sh +++ b/trunk/testsuite/deps2.sh @@ -41,7 +41,9 @@ chmod 644 `ls $BINS | sed 's|$|.orig|'` echo $PRELINK ${PRELINK_OPTS--v} -avvvvv > deps2.log $PRELINK ${PRELINK_OPTS--v} -avvvvv > deps2.tree/etc/log1 2>&1 || exit 1 cat deps2.tree/etc/log1 >> deps2.log -LD_LIBRARY_PATH=deps2.tree/lib deps2.tree/usr/bin/bin1 || exit 2 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=deps2.tree/lib deps2.tree/usr/bin/bin1 || exit 2 +fi readelf -d deps2.tree/{usr,opt}/lib/lib1.so 2>&1 | grep CHECKSUM >> deps2.log || exit 3 readelf -A deps2.tree/usr/lib/lib1.so >> deps2.log 2>&1 || exit 4 readelf -A deps2.tree/opt/lib/lib1.so >> deps2.log 2>&1 || exit 5 diff --git a/trunk/testsuite/functions.sh b/trunk/testsuite/functions.sh index 85bf875..c351fd1 100755 --- a/trunk/testsuite/functions.sh +++ b/trunk/testsuite/functions.sh @@ -4,6 +4,9 @@ CCLINK=${CCLINK:-${CC} -Wl,--dynamic-linker=`echo ./ld*.so.*[0-9]`} CXX="${CXX:-g++} ${LINKOPTS}" CXXLINK=${CXXLINK:-${CXX} -Wl,--dynamic-linker=`echo ./ld*.so.*[0-9]`} PRELINK=${PRELINK:-../src/prelink -c ./prelink.conf -C ./prelink.cache --ld-library-path=. --dynamic-linker=`echo ./ld*.so.*[0-9]`} +LDD=${LDD:-../src/prelink-rtld} +STRIP=${STRIP:-strip} +HOST_CC=${HOST_CC:-$CC} srcdir=${srcdir:-`dirname $0`} savelibs() { for i in $LIBS $BINS; do cp -p $i $i.orig; done diff --git a/trunk/testsuite/layout1.sh b/trunk/testsuite/layout1.sh index ee751ab..e217dea 100755 --- a/trunk/testsuite/layout1.sh +++ b/trunk/testsuite/layout1.sh @@ -15,7 +15,9 @@ savelibs echo $PRELINK ${PRELINK_OPTS--vR} ./layout1 > layout1.log $PRELINK ${PRELINK_OPTS--vR} ./layout1 >> layout1.log 2>&1 || exit 1 grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` layout1.log && exit 2 -LD_LIBRARY_PATH=. ./layout1 || exit 3 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./layout1 || exit 3 +fi readelf -a ./layout1 >> layout1.log 2>&1 || exit 4 # So that it is not prelinked again chmod -x ./layout1 diff --git a/trunk/testsuite/layout2.sh b/trunk/testsuite/layout2.sh index 7d8504b..2307a42 100755 --- a/trunk/testsuite/layout2.sh +++ b/trunk/testsuite/layout2.sh @@ -14,7 +14,9 @@ savelibs echo $PRELINK ${PRELINK_OPTS--vR} ./layout2 > layout2.log $PRELINK ${PRELINK_OPTS--vR} ./layout2 >> layout2.log 2>&1 || exit 1 grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` layout2.log && exit 2 -LD_LIBRARY_PATH=. ./layout2 || exit 3 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./layout2 || exit 3 +fi readelf -a ./layout2 >> layout2.log 2>&1 || exit 4 # So that it is not prelinked again chmod -x ./layout2 diff --git a/trunk/testsuite/movelibs.sh b/trunk/testsuite/movelibs.sh index 4357ee8..010e0e7 100755 --- a/trunk/testsuite/movelibs.sh +++ b/trunk/testsuite/movelibs.sh @@ -5,7 +5,7 @@ echo 'int main() { }' > movelibs.C $CXX -o movelibs movelibs.C > syslib.list > syslnk.list -for i in `LD_TRACE_PRELINKING=1 LD_WARN= LD_TRACE_LOADED_OBJECTS=1 ./movelibs \ +for i in `RTLD_TRACE_PRELINKING=1 LD_WARN= $LDD ./movelibs \ | awk '$1 !~ /^\.\/movelibs/ { print $3 } '`; do k=`basename $i` if [ -L $i ]; then diff --git a/trunk/testsuite/quick1.sh b/trunk/testsuite/quick1.sh index 8974146..f3f80a8 100755 --- a/trunk/testsuite/quick1.sh +++ b/trunk/testsuite/quick1.sh @@ -111,12 +111,24 @@ cat quick1.tree/etc/log3 >> quick1.log echo $PRELINK ${PRELINK_OPTS--vm} -aqvvvvv >> quick1.log $PRELINK ${PRELINK_OPTS--vm} -aqvvvvv > quick1.tree/etc/log4 2>&1 || exit 4 cat quick1.tree/etc/log4 >> quick1.log -LD_LIBRARY_PATH=quick1.tree/lib:quick1.tree/usr/lib quick1.tree/usr/bin/bin1 || exit 5 -LD_LIBRARY_PATH=quick1.tree/lib:quick1.tree/usr/lib quick1.tree/usr/bin/bin2 || exit 6 -LD_LIBRARY_PATH=quick1.tree/lib:quick1.tree/usr/lib quick1.tree/usr/bin/bin3 || exit 7 -LD_LIBRARY_PATH=quick1.tree/lib:quick1.tree/usr/lib quick1.tree/usr/bin/bin4 || exit 8 -LD_LIBRARY_PATH=quick1.tree/lib:quick1.tree/usr/lib quick1.tree/usr/bin/bin5 || exit 9 -LD_LIBRARY_PATH=quick1.tree/lib:quick1.tree/usr/lib quick1.tree/usr/bin/bin6 || exit 10 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=quick1.tree/lib:quick1.tree/usr/lib quick1.tree/usr/bin/bin1 || exit 5 +fi +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=quick1.tree/lib:quick1.tree/usr/lib quick1.tree/usr/bin/bin2 || exit 6 +fi +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=quick1.tree/lib:quick1.tree/usr/lib quick1.tree/usr/bin/bin3 || exit 7 +fi +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=quick1.tree/lib:quick1.tree/usr/lib quick1.tree/usr/bin/bin4 || exit 8 +fi +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=quick1.tree/lib:quick1.tree/usr/lib quick1.tree/usr/bin/bin5 || exit 9 +fi +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=quick1.tree/lib:quick1.tree/usr/lib quick1.tree/usr/bin/bin6 || exit 10 +fi readelf -a quick1.tree/usr/bin/bin1 >> quick1.log 2>&1 || exit 11 readelf -a quick1.tree/usr/bin/bin3 >> quick1.log 2>&1 || exit 12 readelf -a quick1.tree/usr/bin/bin4 >> quick1.log 2>&1 || exit 13 @@ -140,12 +152,24 @@ done echo $PRELINK ${PRELINK_OPTS--vm} -aqvvvvv >> quick1.log $PRELINK ${PRELINK_OPTS--vm} -aqvvvvv > quick1.tree/etc/log5 2>&1 || exit 17 cat quick1.tree/etc/log5 >> quick1.log -LD_LIBRARY_PATH=quick1.tree/lib:quick1.tree/usr/lib quick1.tree/usr/bin/bin1 || exit 18 -LD_LIBRARY_PATH=quick1.tree/lib:quick1.tree/usr/lib quick1.tree/usr/bin/bin2 || exit 19 -LD_LIBRARY_PATH=quick1.tree/lib:quick1.tree/usr/lib quick1.tree/usr/bin/bin3 || exit 20 -LD_LIBRARY_PATH=quick1.tree/lib:quick1.tree/usr/lib quick1.tree/usr/bin/bin4 || exit 21 -LD_LIBRARY_PATH=quick1.tree/lib:quick1.tree/usr/lib quick1.tree/usr/bin/bin5 || exit 22 -LD_LIBRARY_PATH=quick1.tree/lib:quick1.tree/usr/lib quick1.tree/usr/bin/bin6 || exit 23 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=quick1.tree/lib:quick1.tree/usr/lib quick1.tree/usr/bin/bin1 || exit 18 +fi +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=quick1.tree/lib:quick1.tree/usr/lib quick1.tree/usr/bin/bin2 || exit 19 +fi +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=quick1.tree/lib:quick1.tree/usr/lib quick1.tree/usr/bin/bin3 || exit 20 +fi +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=quick1.tree/lib:quick1.tree/usr/lib quick1.tree/usr/bin/bin4 || exit 21 +fi +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=quick1.tree/lib:quick1.tree/usr/lib quick1.tree/usr/bin/bin5 || exit 22 +fi +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=quick1.tree/lib:quick1.tree/usr/lib quick1.tree/usr/bin/bin6 || exit 23 +fi readelf -a quick1.tree/usr/bin/bin1 >> quick1.log 2>&1 || exit 24 readelf -a quick1.tree/usr/bin/bin3 >> quick1.log 2>&1 || exit 25 readelf -a quick1.tree/usr/bin/bin4 >> quick1.log 2>&1 || exit 26 diff --git a/trunk/testsuite/quick2.sh b/trunk/testsuite/quick2.sh index 131795e..87138ae 100755 --- a/trunk/testsuite/quick2.sh +++ b/trunk/testsuite/quick2.sh @@ -112,8 +112,18 @@ echo is present in prelink.conf. exit 0 EOF chmod 755 quick2.tree/usr/bin/bin11.script -echo 'int main () { return 0; }' \ +if [ `$CC -dumpmachine | sed "s/-.*-.*-.*//"` = "arm" ]; then + cat > quick2.tree/usr/bin/bin12 << EOF +#!/bin/sh +echo -pie -fPIE is not supported on our ARM architectures +echo this script will serve to disable that part of the test. +exit 0 +EOF +chmod 0755 quick2.tree/usr/bin/bin12 +else + echo 'int main () { return 0; }' \ | $CCLINK -o quick2.tree/usr/bin/bin12 -pie -fPIE -xc - -xnone +fi cat > quick2.tree/etc/prelink.conf <<EOF -b *.sh -b *.py @@ -173,12 +183,24 @@ grep -q 'Could not prelink .*bin5 because its dependency .*lib7.so could not be echo $PRELINK ${PRELINK_OPTS--vm} -aqvvvvv >> quick2.log $PRELINK ${PRELINK_OPTS--vm} -aqvvvvv > quick2.tree/etc/log4 2>&1 || exit 4 cat quick2.tree/etc/log4 >> quick2.log -LD_LIBRARY_PATH=quick2.tree/lib:quick2.tree/usr/lib quick2.tree/usr/bin/bin1 || exit 5 -LD_LIBRARY_PATH=quick2.tree/lib:quick2.tree/usr/lib quick2.tree/usr/bin/bin2 || exit 6 -LD_LIBRARY_PATH=quick2.tree/lib:quick2.tree/usr/lib quick2.tree/usr/bin/bin3 || exit 7 -LD_LIBRARY_PATH=quick2.tree/lib:quick2.tree/usr/lib quick2.tree/usr/bin/bin4 || exit 8 -LD_LIBRARY_PATH=quick2.tree/lib:quick2.tree/usr/lib quick2.tree/usr/bin/bin5 || exit 9 -LD_LIBRARY_PATH=quick2.tree/lib:quick2.tree/usr/lib quick2.tree/usr/bin/bin6 || exit 10 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=quick2.tree/lib:quick2.tree/usr/lib quick2.tree/usr/bin/bin1 || exit 5 +fi +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=quick2.tree/lib:quick2.tree/usr/lib quick2.tree/usr/bin/bin2 || exit 6 +fi +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=quick2.tree/lib:quick2.tree/usr/lib quick2.tree/usr/bin/bin3 || exit 7 +fi +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=quick2.tree/lib:quick2.tree/usr/lib quick2.tree/usr/bin/bin4 || exit 8 +fi +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=quick2.tree/lib:quick2.tree/usr/lib quick2.tree/usr/bin/bin5 || exit 9 +fi +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=quick2.tree/lib:quick2.tree/usr/lib quick2.tree/usr/bin/bin6 || exit 10 +fi readelf -a quick2.tree/usr/bin/bin1 >> quick2.log 2>&1 || exit 11 readelf -a quick2.tree/usr/bin/bin3 >> quick2.log 2>&1 || exit 12 readelf -a quick2.tree/usr/bin/bin4 >> quick2.log 2>&1 || exit 13 @@ -201,12 +223,24 @@ done echo $PRELINK ${PRELINK_OPTS--vm} -aqvvvvv >> quick2.log $PRELINK ${PRELINK_OPTS--vm} -aqvvvvv > quick2.tree/etc/log5 2>&1 || exit 17 cat quick2.tree/etc/log5 >> quick2.log -LD_LIBRARY_PATH=quick2.tree/lib:quick2.tree/usr/lib quick2.tree/usr/bin/bin1 || exit 18 -LD_LIBRARY_PATH=quick2.tree/lib:quick2.tree/usr/lib quick2.tree/usr/bin/bin2 || exit 19 -LD_LIBRARY_PATH=quick2.tree/lib:quick2.tree/usr/lib quick2.tree/usr/bin/bin3 || exit 20 -LD_LIBRARY_PATH=quick2.tree/lib:quick2.tree/usr/lib quick2.tree/usr/bin/bin4 || exit 21 -LD_LIBRARY_PATH=quick2.tree/lib:quick2.tree/usr/lib quick2.tree/usr/bin/bin5 || exit 22 -LD_LIBRARY_PATH=quick2.tree/lib:quick2.tree/usr/lib quick2.tree/usr/bin/bin6 || exit 23 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=quick2.tree/lib:quick2.tree/usr/lib quick2.tree/usr/bin/bin1 || exit 18 +fi +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=quick2.tree/lib:quick2.tree/usr/lib quick2.tree/usr/bin/bin2 || exit 19 +fi +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=quick2.tree/lib:quick2.tree/usr/lib quick2.tree/usr/bin/bin3 || exit 20 +fi +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=quick2.tree/lib:quick2.tree/usr/lib quick2.tree/usr/bin/bin4 || exit 21 +fi +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=quick2.tree/lib:quick2.tree/usr/lib quick2.tree/usr/bin/bin5 || exit 22 +fi +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=quick2.tree/lib:quick2.tree/usr/lib quick2.tree/usr/bin/bin6 || exit 23 +fi readelf -a quick2.tree/usr/bin/bin1 >> quick2.log 2>&1 || exit 24 readelf -a quick2.tree/usr/bin/bin3 >> quick2.log 2>&1 || exit 25 readelf -a quick2.tree/usr/bin/bin4 >> quick2.log 2>&1 || exit 26 diff --git a/trunk/testsuite/quick3.sh b/trunk/testsuite/quick3.sh index 00d2aad..0562e52 100755 --- a/trunk/testsuite/quick3.sh +++ b/trunk/testsuite/quick3.sh @@ -72,7 +72,9 @@ sleep 3s echo $PRELINK ${PRELINK_OPTS--vm} -aqvvvvv >> quick3.log $PRELINK ${PRELINK_OPTS--vm} -aqvvvvv > quick3.tree/etc/log3 2>&1 || exit 3 cat quick3.tree/etc/log3 >> quick3.log -LD_LIBRARY_PATH=quick3.tree/lib:quick3.tree/usr/lib quick3.tree/usr/bin/bin1 || exit 4 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=quick3.tree/lib:quick3.tree/usr/lib quick3.tree/usr/bin/bin1 || exit 4 +fi LIBS="quick3.tree/usr/lib/lib1.so quick3.tree/usr/lib/lib2.so.0" echo $PRELINK ${PRELINK_OPTS--vm} -aqvvvvv >> quick3.log $PRELINK ${PRELINK_OPTS--vm} -aqvvvvv > quick3.tree/etc/log4 2>&1 || exit 5 diff --git a/trunk/testsuite/reloc1.sh b/trunk/testsuite/reloc1.sh index 124ab96..ade05c9 100755 --- a/trunk/testsuite/reloc1.sh +++ b/trunk/testsuite/reloc1.sh @@ -11,7 +11,9 @@ savelibs echo $PRELINK ${PRELINK_OPTS--vm} ./reloc1 > reloc1.log $PRELINK ${PRELINK_OPTS--vm} ./reloc1 >> reloc1.log 2>&1 || exit 1 grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` reloc1.log && exit 2 -LD_LIBRARY_PATH=. ./reloc1 || exit 3 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./reloc1 || exit 3 +fi readelf -a ./reloc1 >> reloc1.log 2>&1 || exit 4 # So that it is not prelinked again chmod -x ./reloc1 diff --git a/trunk/testsuite/reloc10.sh b/trunk/testsuite/reloc10.sh index 94a4e69..66dd438 100755 --- a/trunk/testsuite/reloc10.sh +++ b/trunk/testsuite/reloc10.sh @@ -14,7 +14,9 @@ savelibs echo $PRELINK ${PRELINK_OPTS--vm} ./reloc10 > reloc10.log $PRELINK ${PRELINK_OPTS--vm} ./reloc10 >> reloc10.log 2>&1 || exit 1 grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` reloc10.log && exit 2 -LD_LIBRARY_PATH=. ./reloc10 || exit 3 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./reloc10 || exit 3 +fi readelf -a ./reloc10 >> reloc10.log 2>&1 || exit 4 # So that it is not prelinked again chmod -x ./reloc10 diff --git a/trunk/testsuite/reloc11.sh b/trunk/testsuite/reloc11.sh index 5d3f4f1..ab0cbee 100755 --- a/trunk/testsuite/reloc11.sh +++ b/trunk/testsuite/reloc11.sh @@ -12,7 +12,9 @@ savelibs echo $PRELINK ${PRELINK_OPTS--vm} ./reloc11 > reloc11.log $PRELINK ${PRELINK_OPTS--vm} ./reloc11 >> reloc11.log 2>&1 || exit 1 grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` reloc11.log && exit 2 -LD_LIBRARY_PATH=. ./reloc11 || exit 3 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./reloc11 || exit 3 +fi readelf -a ./reloc11 >> reloc11.log 2>&1 || exit 4 # So that it is not prelinked again chmod -x ./reloc11 diff --git a/trunk/testsuite/reloc2.sh b/trunk/testsuite/reloc2.sh index c8dee4e..4d180c6 100755 --- a/trunk/testsuite/reloc2.sh +++ b/trunk/testsuite/reloc2.sh @@ -12,12 +12,14 @@ $CC -shared $SHFLAGS -O2 -o reloc2lib2.so $srcdir/reloc2lib2.c \ BINS="reloc2" LIBS="reloc2lib1.so reloc2lib2.so" $CCLINK -o reloc2 $srcdir/reloc2.c -Wl,--rpath-link,. reloc2lib2.so -strip -R .comment $BINS $LIBS +$STRIP -R .comment $BINS $LIBS savelibs echo $PRELINK ${PRELINK_OPTS--vm} ./reloc2 > reloc2.log $PRELINK ${PRELINK_OPTS--vm} ./reloc2 >> reloc2.log 2>&1 || exit 1 grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` reloc2.log && exit 2 -LD_LIBRARY_PATH=. ./reloc2 || exit 3 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./reloc2 || exit 3 +fi readelf -a ./reloc2 >> reloc2.log 2>&1 || exit 4 # So that it is not prelinked again chmod -x ./reloc2 diff --git a/trunk/testsuite/reloc3.sh b/trunk/testsuite/reloc3.sh index 66e1bca..acf0497 100755 --- a/trunk/testsuite/reloc3.sh +++ b/trunk/testsuite/reloc3.sh @@ -7,12 +7,14 @@ $CC -shared -O2 -fpic -o reloc3lib2.so $srcdir/reloc1lib2.c reloc3lib1.so BINS="reloc3" LIBS="reloc3lib1.so reloc3lib2.so" $CCLINK -o reloc3 $srcdir/reloc3.c -Wl,--rpath-link,. reloc3lib2.so -strip -g $BINS $LIBS +$STRIP -g $BINS $LIBS savelibs echo $PRELINK ${PRELINK_OPTS--vm} ./reloc3 > reloc3.log $PRELINK ${PRELINK_OPTS--vm} ./reloc3 >> reloc3.log 2>&1 || exit 1 grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` reloc3.log && exit 2 -LD_LIBRARY_PATH=. ./reloc3 >> reloc3.log || exit 3 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./reloc3 >> reloc3.log || exit 3 +fi readelf -a ./reloc3 >> reloc3.log 2>&1 || exit 4 # So that it is not prelinked again chmod -x ./reloc3 diff --git a/trunk/testsuite/reloc4.sh b/trunk/testsuite/reloc4.sh index 6fd733d..c20f8b5 100755 --- a/trunk/testsuite/reloc4.sh +++ b/trunk/testsuite/reloc4.sh @@ -4,10 +4,10 @@ [ -z "$CHECK_ME_HARDER" ] && exit 77 rm -f reloc4 reloc4lib*.so reloc4.log rm -f prelink.cache -$CC -O2 -o reloc4lib1.tmp $srcdir/reloc4lib1.c -$CC -O2 -o reloc4lib2.tmp $srcdir/reloc4lib2.c -$CC -O2 -o reloc4lib3.tmp $srcdir/reloc4lib3.c -$CC -O2 -o reloc4.tmp $srcdir/reloc4.c +$HOST_CC -O2 -o reloc4lib1.tmp $srcdir/reloc4lib1.c +$HOST_CC -O2 -o reloc4lib2.tmp $srcdir/reloc4lib2.c +$HOST_CC -O2 -o reloc4lib3.tmp $srcdir/reloc4lib3.c +$HOST_CC -O2 -o reloc4.tmp $srcdir/reloc4.c ./reloc4lib1.tmp > reloc4lib1.tmp.c ./reloc4lib2.tmp > reloc4lib2.tmp.c ./reloc4lib3.tmp > reloc4lib3.tmp.c @@ -27,7 +27,9 @@ rm -f reloc4*.tmp reloc4*.tmp.c echo $PRELINK ${PRELINK_OPTS--vm} ./reloc4 > reloc4.log $PRELINK ${PRELINK_OPTS--vm} ./reloc4 >> reloc4.log 2>&1 || exit 1 grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` reloc4.log && exit 2 -LD_LIBRARY_PATH=. ./reloc4 || exit 3 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./reloc4 || exit 3 +fi readelf -a ./reloc4 >> reloc4.log 2>&1 || exit 4 # So that it is not prelinked again chmod -x ./reloc4 diff --git a/trunk/testsuite/reloc5.c b/trunk/testsuite/reloc5.c index 68e67b6..b174bcf 100644 --- a/trunk/testsuite/reloc5.c +++ b/trunk/testsuite/reloc5.c @@ -14,7 +14,11 @@ int main (void) printf (" for (x = 0; x < 16384; ++x)\n"); printf (" if (testzero[x]) abort ();\n"); printf (" exit (0);\n}\n\n"); + printf ("#ifdef __arm__\n"); + printf ("asm (\".section nonalloced,\\\"aw\\\",%%nobits\\n\\t\"\n"); + printf ("#else\n"); printf ("asm (\".section nonalloced,\\\"aw\\\",@nobits\\n\\t\"\n"); + printf ("#endif\n"); printf (" \".globl testzero\\n\\t\"\n"); printf (" \"testzero: .skip 16384\");\n"); } diff --git a/trunk/testsuite/reloc5.sh b/trunk/testsuite/reloc5.sh index 16d2b7a..f543f69 100755 --- a/trunk/testsuite/reloc5.sh +++ b/trunk/testsuite/reloc5.sh @@ -4,7 +4,7 @@ [ -z "$CHECK_ME_HARDER" ] && exit 77 rm -f reloc5 reloc5.log rm -f prelink.cache -$CC -O2 -o reloc5.tmp $srcdir/reloc5.c +$HOST_CC -O2 -o reloc5.tmp $srcdir/reloc5.c ./reloc5.tmp > reloc5.tmp.c BINS="reloc5" $CCLINK -o reloc5 reloc5.tmp.c -Wl,--rpath-link,. reloc4lib3.so @@ -13,7 +13,9 @@ rm -f reloc5*.tmp reloc5*.tmp.c echo $PRELINK ${PRELINK_OPTS--vm} ./reloc5 > reloc5.log $PRELINK ${PRELINK_OPTS--vm} ./reloc5 >> reloc5.log 2>&1 || exit 1 grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` reloc5.log && exit 2 -LD_LIBRARY_PATH=. ./reloc5 || exit 3 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./reloc5 || exit 3 +fi readelf -a ./reloc5 >> reloc5.log 2>&1 || exit 4 # So that it is not prelinked again chmod -x ./reloc5 diff --git a/trunk/testsuite/reloc6.sh b/trunk/testsuite/reloc6.sh index 0ddd8d8..7f72936 100755 --- a/trunk/testsuite/reloc6.sh +++ b/trunk/testsuite/reloc6.sh @@ -9,15 +9,27 @@ $CCLINK -o reloc6.nop $srcdir/reloc3.c -Wl,--rpath-link,. reloc6lib2.so echo $PRELINK ${PRELINK_OPTS--vm} ./reloc6 > reloc6.log $PRELINK ${PRELINK_OPTS--vm} ./reloc6 >> reloc6.log 2>&1 || exit 1 grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` reloc6.log && exit 2 -LD_LIBRARY_PATH=. ./reloc6 >> reloc6.log || exit 3 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./reloc6 >> reloc6.log || exit 3 +fi readelf -a ./reloc6 >> reloc6.log 2>&1 || exit 4 -LD_LIBRARY_PATH=. ./reloc6.nop >> reloc6.log || exit 5 -LD_LIBRARY_PATH=. LD_BIND_NOW=1 ./reloc6.nop >> reloc6.log || exit 6 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./reloc6.nop >> reloc6.log || exit 5 +fi +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. LD_BIND_NOW=1 ./reloc6.nop >> reloc6.log || exit 6 +fi mv -f reloc6lib2.so reloc6lib2.so.p $CC -shared -O2 -fpic -o reloc6lib2.so $srcdir/reloc1lib2.c reloc6lib1.so -LD_LIBRARY_PATH=. ./reloc6 >> reloc6.log || exit 7 -LD_LIBRARY_PATH=. ./reloc6.nop >> reloc6.log || exit 8 -LD_LIBRARY_PATH=. LD_BIND_NOW=1 ./reloc6.nop >> reloc6.log || exit 9 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./reloc6 >> reloc6.log || exit 7 +fi +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./reloc6.nop >> reloc6.log || exit 8 +fi +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. LD_BIND_NOW=1 ./reloc6.nop >> reloc6.log || exit 9 +fi mv -f reloc6lib2.so reloc6lib2.so.nop mv -f reloc6lib2.so.p reloc6lib2.so # So that it is not prelinked again diff --git a/trunk/testsuite/reloc7.sh b/trunk/testsuite/reloc7.sh index 640ca78..edbbcbf 100755 --- a/trunk/testsuite/reloc7.sh +++ b/trunk/testsuite/reloc7.sh @@ -11,7 +11,9 @@ savelibs echo $PRELINK ${PRELINK_OPTS--vm} ./reloc7 > reloc7.log $PRELINK ${PRELINK_OPTS--vm} ./reloc7 >> reloc7.log 2>&1 || exit 1 grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` reloc7.log && exit 2 -LD_LIBRARY_PATH=. ./reloc7 >> reloc7.log || exit 3 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./reloc7 >> reloc7.log || exit 3 +fi readelf -a ./reloc7 >> reloc7.log 2>&1 || exit 4 # So that it is not prelinked again chmod -x ./reloc7 diff --git a/trunk/testsuite/reloc8.sh b/trunk/testsuite/reloc8.sh index ea0a89e..9f5e1fb 100755 --- a/trunk/testsuite/reloc8.sh +++ b/trunk/testsuite/reloc8.sh @@ -1,7 +1,9 @@ #!/bin/bash . `dirname $0`/functions.sh # Disable this test under SELinux -test -x /usr/sbin/getenforce -a "`/usr/sbin/getenforce`" = Enforcing && exit 77 +if [ "x$CROSS" = "x" ]; then + test -x /usr/sbin/getenforce -a "`/usr/sbin/getenforce`" = Enforcing && exit 77 +fi rm -f reloc8 reloc8lib*.so reloc8.log rm -f prelink.cache NOCOPYRELOC=-Wl,-z,nocopyreloc @@ -17,7 +19,9 @@ savelibs echo $PRELINK ${PRELINK_OPTS--vm} ./reloc8 > reloc8.log $PRELINK ${PRELINK_OPTS--vm} ./reloc8 >> reloc8.log 2>&1 || exit 1 grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` reloc8.log && exit 2 -LD_LIBRARY_PATH=. ./reloc8 >> reloc8.log || exit 3 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./reloc8 >> reloc8.log || exit 3 +fi readelf -a ./reloc8 >> reloc8.log 2>&1 || exit 4 # So that it is not prelinked again chmod -x ./reloc8 diff --git a/trunk/testsuite/reloc9.sh b/trunk/testsuite/reloc9.sh index 41fe578..d3a449c 100755 --- a/trunk/testsuite/reloc9.sh +++ b/trunk/testsuite/reloc9.sh @@ -1,7 +1,9 @@ #!/bin/bash . `dirname $0`/functions.sh # Disable this test under SELinux -test -x /usr/sbin/getenforce -a "`/usr/sbin/getenforce`" = Enforcing && exit 77 +if [ "x$CROSS" = "x" ]; then + test -x /usr/sbin/getenforce -a "`/usr/sbin/getenforce`" = Enforcing && exit 77 +fi rm -f reloc9 reloc9lib*.so reloc9.log rm -f prelink.cache NOCOPYRELOC=-Wl,-z,nocopyreloc @@ -17,7 +19,9 @@ savelibs echo $PRELINK ${PRELINK_OPTS--vm} ./reloc9 > reloc9.log $PRELINK ${PRELINK_OPTS--vm} ./reloc9 >> reloc9.log 2>&1 || exit 1 grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` reloc9.log && exit 2 -LD_LIBRARY_PATH=. ./reloc9 >> reloc9.log || exit 3 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./reloc9 >> reloc9.log || exit 3 +fi readelf -a ./reloc9 >> reloc9.log 2>&1 || exit 4 # So that it is not prelinked again chmod -x ./reloc9 diff --git a/trunk/testsuite/shuffle1.sh b/trunk/testsuite/shuffle1.sh index 7798d9e..4553d2e 100755 --- a/trunk/testsuite/shuffle1.sh +++ b/trunk/testsuite/shuffle1.sh @@ -15,7 +15,9 @@ savelibs echo $PRELINK ${PRELINK_OPTS--vm} ./shuffle1 > shuffle1.log $PRELINK ${PRELINK_OPTS--vm} ./shuffle1 >> shuffle1.log 2>&1 || exit 1 grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` shuffle1.log && exit 2 -LD_LIBRARY_PATH=. ./shuffle1 || exit 3 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./shuffle1 || exit 3 +fi readelf -a ./shuffle1 >> shuffle1.log 2>&1 || exit 4 # So that it is not prelinked again chmod -x ./shuffle1 diff --git a/trunk/testsuite/shuffle2.c b/trunk/testsuite/shuffle2.c index c5e8488..c9f03ce 100644 --- a/trunk/testsuite/shuffle2.c +++ b/trunk/testsuite/shuffle2.c @@ -16,6 +16,12 @@ int main() exit (0); } +#ifdef __arm__ +asm (".section nonalloced,\"aw\",%nobits\n\t" + ".globl testzero\n\t" + "testzero: .skip 16384"); +#else asm (".section nonalloced,\"aw\",@nobits\n\t" ".globl testzero\n\t" "testzero: .skip 16384"); +#endif diff --git a/trunk/testsuite/shuffle2.sh b/trunk/testsuite/shuffle2.sh index fcfbfb1..fdaf03e 100755 --- a/trunk/testsuite/shuffle2.sh +++ b/trunk/testsuite/shuffle2.sh @@ -1,9 +1,11 @@ #!/bin/bash . `dirname $0`/functions.sh # Kernels before 2.4.10 are known not to work -case "`uname -r`" in +if [ "x$CROSS" = "x" ]; then + case "`uname -r`" in [01].*|2.[0-3].*|2.4.[0-9]|2.4.[0-9][^0-9]*) exit 77;; -esac + esac +fi rm -f shuffle2 shuffle2lib*.so shuffle2.log shuffle2.lds $CC -shared -O2 -fpic -o shuffle2lib1.so $srcdir/reloc1lib1.c $CC -shared -O2 -fpic -o shuffle2lib2.so $srcdir/reloc1lib2.c shuffle2lib1.so @@ -18,7 +20,9 @@ savelibs echo $PRELINK ${PRELINK_OPTS--vm} ./shuffle2 > shuffle2.log $PRELINK ${PRELINK_OPTS--vm} ./shuffle2 >> shuffle2.log 2>&1 || exit 1 grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` shuffle2.log && exit 2 -LD_LIBRARY_PATH=. ./shuffle2 || exit 3 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./shuffle2 || exit 3 +fi readelf -a ./shuffle2 >> shuffle2.log 2>&1 || exit 4 # So that it is not prelinked again chmod -x ./shuffle2 diff --git a/trunk/testsuite/shuffle3.sh b/trunk/testsuite/shuffle3.sh index d731102..989bfcb 100755 --- a/trunk/testsuite/shuffle3.sh +++ b/trunk/testsuite/shuffle3.sh @@ -1,9 +1,11 @@ #!/bin/bash . `dirname $0`/functions.sh # Kernels before 2.4.10 are known not to work -case "`uname -r`" in +if [ "x$CROSS" = "x" ]; then + case "`uname -r`" in [01].*|2.[0-3].*|2.4.[0-9]|2.4.[0-9][^0-9]*) exit 77;; -esac + esac +fi rm -f shuffle3 shuffle3lib*.so shuffle3.log shuffle3.lds rm -f prelink.cache $CC -shared -O2 -fpic -o shuffle3lib1.so $srcdir/reloc1lib1.c @@ -19,7 +21,9 @@ savelibs echo $PRELINK ${PRELINK_OPTS--vm} ./shuffle3 > shuffle3.log $PRELINK ${PRELINK_OPTS--vm} ./shuffle3 >> shuffle3.log 2>&1 || exit 1 grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` shuffle3.log && exit 2 -LD_LIBRARY_PATH=. ./shuffle3 || exit 3 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./shuffle3 || exit 3 +fi readelf -a ./shuffle3 >> shuffle3.log 2>&1 || exit 4 # So that it is not prelinked again chmod -x ./shuffle3 diff --git a/trunk/testsuite/shuffle4.sh b/trunk/testsuite/shuffle4.sh index 127e224..781431c 100755 --- a/trunk/testsuite/shuffle4.sh +++ b/trunk/testsuite/shuffle4.sh @@ -1,9 +1,11 @@ #!/bin/bash . `dirname $0`/functions.sh # Kernels before 2.4.10 are known not to work -case "`uname -r`" in +if [ "x$CROSS" = "x" ]; then + case "`uname -r`" in [01].*|2.[0-3].*|2.4.[0-9]|2.4.[0-9][^0-9]*) exit 77;; -esac + esac +fi rm -f shuffle4 shuffle4.log BINS="shuffle4" $CCLINK -o shuffle4 $srcdir/shuffle2.c -Wl,--rpath-link,. shuffle3lib2.so @@ -11,7 +13,9 @@ savelibs echo $PRELINK ${PRELINK_OPTS--vm} ./shuffle4 > shuffle4.log $PRELINK ${PRELINK_OPTS--vm} ./shuffle4 >> shuffle4.log 2>&1 || exit 1 grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` shuffle4.log && exit 2 -LD_LIBRARY_PATH=. ./shuffle4 || exit 3 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./shuffle4 || exit 3 +fi readelf -a ./shuffle4 >> shuffle4.log 2>&1 || exit 4 # So that it is not prelinked again chmod -x ./shuffle4 diff --git a/trunk/testsuite/shuffle5.sh b/trunk/testsuite/shuffle5.sh index ce09d46..db722e8 100755 --- a/trunk/testsuite/shuffle5.sh +++ b/trunk/testsuite/shuffle5.sh @@ -15,7 +15,9 @@ savelibs echo $PRELINK ${PRELINK_OPTS--vm} ./shuffle5 > shuffle5.log $PRELINK ${PRELINK_OPTS--vm} ./shuffle5 >> shuffle5.log 2>&1 || exit 1 grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` shuffle5.log && exit 2 -LD_LIBRARY_PATH=. ./shuffle5 || exit 3 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./shuffle5 || exit 3 +fi readelf -a ./shuffle5 >> shuffle5.log 2>&1 || exit 4 # So that it is not prelinked again chmod -x ./shuffle5 diff --git a/trunk/testsuite/shuffle6.sh b/trunk/testsuite/shuffle6.sh index 3eec2ff..eb28d62 100755 --- a/trunk/testsuite/shuffle6.sh +++ b/trunk/testsuite/shuffle6.sh @@ -15,7 +15,9 @@ savelibs echo $PRELINK ${PRELINK_OPTS--vm} ./shuffle6 > shuffle6.log $PRELINK ${PRELINK_OPTS--vm} ./shuffle6 >> shuffle6.log 2>&1 || exit 1 grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` shuffle6.log && exit 2 -LD_LIBRARY_PATH=. ./shuffle6 || exit 3 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./shuffle6 || exit 3 +fi readelf -a ./shuffle6 >> shuffle6.log 2>&1 || exit 4 comparelibs >> shuffle6.log 2>&1 || exit 5 for l in shuffle6lib{1,2}.so{,.orig}; do mv -f $l $l.first; done @@ -26,7 +28,9 @@ for l in shuffle6lib{1,2}.so; do cp -p $l $l.orig; done echo $PRELINK ${PRELINK_OPTS--vm} ./shuffle6 >> shuffle6.log $PRELINK ${PRELINK_OPTS--vm} ./shuffle6 >> shuffle6.log 2>&1 || exit 6 grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` shuffle6.log && exit 7 -LD_LIBRARY_PATH=. ./shuffle6 || exit 8 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./shuffle6 || exit 8 +fi readelf -a ./shuffle6 >> shuffle6.log 2>&1 || exit 9 # So that it is not prelinked again chmod -x ./shuffle6 diff --git a/trunk/testsuite/shuffle7.sh b/trunk/testsuite/shuffle7.sh index 23c3c60..c6449c8 100755 --- a/trunk/testsuite/shuffle7.sh +++ b/trunk/testsuite/shuffle7.sh @@ -16,7 +16,9 @@ savelibs echo $PRELINK ${PRELINK_OPTS--vm} ./shuffle7 > shuffle7.log $PRELINK ${PRELINK_OPTS--vm} ./shuffle7 >> shuffle7.log 2>&1 || exit 1 grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` shuffle7.log && exit 2 -LD_LIBRARY_PATH=. ./shuffle7 || exit 3 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./shuffle7 || exit 3 +fi readelf -a ./shuffle7 >> shuffle7.log 2>&1 || exit 4 comparelibs >> shuffle7.log 2>&1 || exit 5 for l in shuffle7lib{1,2}.so{,.orig}; do mv -f $l $l.first; done @@ -27,7 +29,9 @@ for l in shuffle7lib{1,2}.so; do cp -p $l $l.orig; done echo $PRELINK ${PRELINK_OPTS--vm} ./shuffle7 >> shuffle7.log $PRELINK ${PRELINK_OPTS--vm} ./shuffle7 >> shuffle7.log 2>&1 || exit 6 grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` shuffle7.log && exit 7 -LD_LIBRARY_PATH=. ./shuffle7 || exit 8 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./shuffle7 || exit 8 +fi readelf -a ./shuffle7 >> shuffle7.log 2>&1 || exit 9 comparelibs >> shuffle7.log 2>&1 || exit 10 for l in shuffle7lib{1,2}.so{,.orig}; do mv -f $l $l.second; done @@ -36,7 +40,9 @@ for l in shuffle7lib{1,2}.so{,.orig}; do cp -p $l.first $l; done echo $PRELINK ${PRELINK_OPTS--vm} ./shuffle7 >> shuffle7.log $PRELINK ${PRELINK_OPTS--vm} ./shuffle7 >> shuffle7.log 2>&1 || exit 11 grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` shuffle7.log && exit 12 -LD_LIBRARY_PATH=. ./shuffle7 || exit 13 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./shuffle7 || exit 13 +fi readelf -a ./shuffle7 >> shuffle7.log 2>&1 || exit 14 comparelibs >> shuffle7.log 2>&1 || exit 15 cmp -s shuffle7{,.first} || exit 16 diff --git a/trunk/testsuite/shuffle8.sh b/trunk/testsuite/shuffle8.sh index d0768a4..51dcc4c 100755 --- a/trunk/testsuite/shuffle8.sh +++ b/trunk/testsuite/shuffle8.sh @@ -7,12 +7,14 @@ $CC -shared -O2 -fpic -o shuffle8lib2.so $srcdir/reloc1lib2.c shuffle8lib1.so BINS="shuffle8" LIBS="shuffle8lib1.so shuffle8lib2.so" $CCLINK -o shuffle8 $srcdir/shuffle8.c -Wl,--rpath-link,. shuffle8lib2.so -strip -R .comment shuffle8 +$STRIP -R .comment shuffle8 savelibs echo $PRELINK ${PRELINK_OPTS--vm} ./shuffle8 > shuffle8.log $PRELINK ${PRELINK_OPTS--vm} ./shuffle8 >> shuffle8.log 2>&1 || exit 1 grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` shuffle8.log && exit 2 -LD_LIBRARY_PATH=. ./shuffle8 || exit 3 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./shuffle8 || exit 3 +fi readelf -a ./shuffle8 >> shuffle8.log 2>&1 || exit 4 # So that it is not prelinked again chmod -x ./shuffle8 diff --git a/trunk/testsuite/tls1.sh b/trunk/testsuite/tls1.sh index 0fb4986..f3d2113 100755 --- a/trunk/testsuite/tls1.sh +++ b/trunk/testsuite/tls1.sh @@ -2,9 +2,9 @@ . `dirname $0`/functions.sh # First check if __thread is supported by ld.so/gcc/ld/as: rm -f tlstest -echo '__thread int a; int main (void) { return a; }' \ - | $CC -xc - -o tlstest > /dev/null 2>&1 || exit 77 -( ./tlstest || { rm -f tlstest; exit 77; } ) 2>/dev/null || exit 77 +#echo '__thread int a; int main (void) { return a; }' \ +# | $CC -xc - -o tlstest > /dev/null 2>&1 || exit 77 +#( ./tlstest || { rm -f tlstest; exit 77; } ) 2>/dev/null || exit 77 rm -f tls1 tls1lib*.so tls1.log rm -f prelink.cache $CC -shared -O2 -fpic -o tls1lib1.so $srcdir/tls1lib1.c @@ -16,7 +16,9 @@ savelibs echo $PRELINK ${PRELINK_OPTS--vm} ./tls1 > tls1.log $PRELINK ${PRELINK_OPTS--vm} ./tls1 >> tls1.log 2>&1 || exit 1 grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` tls1.log && exit 2 -LD_LIBRARY_PATH=. ./tls1 || exit 3 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./tls1 || exit 3 +fi readelf -a ./tls1 >> tls1.log 2>&1 || exit 4 # So that it is not prelinked again chmod -x ./tls1 diff --git a/trunk/testsuite/tls2.sh b/trunk/testsuite/tls2.sh index bf9e1eb..4b515b0 100755 --- a/trunk/testsuite/tls2.sh +++ b/trunk/testsuite/tls2.sh @@ -2,9 +2,9 @@ . `dirname $0`/functions.sh # First check if __thread is supported by ld.so/gcc/ld/as: rm -f tlstest -echo '__thread int a; int main (void) { return a; }' \ - | $CC -xc - -o tlstest > /dev/null 2>&1 || exit 77 -( ./tlstest || { rm -f tlstest; exit 77; } ) 2>/dev/null || exit 77 +#echo '__thread int a; int main (void) { return a; }' \ +# | $CC -xc - -o tlstest > /dev/null 2>&1 || exit 77 +#( ./tlstest || { rm -f tlstest; exit 77; } ) 2>/dev/null || exit 77 rm -f tls2 tls2lib*.so tls2.log rm -f prelink.cache $CC -shared -O2 -fpic -o tls2lib1.so $srcdir/tls2lib1.c @@ -17,7 +17,9 @@ echo $PRELINK ${PRELINK_OPTS--vm} ./tls2 > tls2.log $PRELINK ${PRELINK_OPTS--vm} ./tls2 >> tls2.log 2>&1 || exit 1 grep -v 'has undefined non-weak symbols' tls2.log \ | grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` && exit 2 -LD_LIBRARY_PATH=. ./tls2 || exit 3 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./tls2 || exit 3 +fi readelf -a ./tls2 >> tls2.log 2>&1 || exit 4 # So that it is not prelinked again chmod -x ./tls2 diff --git a/trunk/testsuite/tls3.sh b/trunk/testsuite/tls3.sh index 966eb1f..e7270e9 100755 --- a/trunk/testsuite/tls3.sh +++ b/trunk/testsuite/tls3.sh @@ -2,9 +2,9 @@ . `dirname $0`/functions.sh # First check if __thread is supported by ld.so/gcc/ld/as: rm -f tlstest -echo '__thread int a; int main (void) { return a; }' \ - | $CC -xc - -o tlstest > /dev/null 2>&1 || exit 77 -( ./tlstest || { rm -f tlstest; exit 77; } ) 2>/dev/null || exit 77 +#echo '__thread int a; int main (void) { return a; }' \ +# | $CC -xc - -o tlstest > /dev/null 2>&1 || exit 77 +#( ./tlstest || { rm -f tlstest; exit 77; } ) 2>/dev/null || exit 77 SHFLAGS= case "`uname -m`" in ia64|ppc*|x86_64|alpha*|s390*|mips*) SHFLAGS=-fpic;; # Does not support non-pic shared libs @@ -21,7 +21,9 @@ savelibs echo $PRELINK ${PRELINK_OPTS--vm} ./tls3 > tls3.log $PRELINK ${PRELINK_OPTS--vm} ./tls3 >> tls3.log 2>&1 || exit 1 grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` tls3.log && exit 2 -LD_LIBRARY_PATH=. ./tls3 || exit 3 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./tls3 || exit 3 +fi readelf -a ./tls3 >> tls3.log 2>&1 || exit 4 # So that it is not prelinked again chmod -x ./tls3 diff --git a/trunk/testsuite/tls4.sh b/trunk/testsuite/tls4.sh index 556a6d5..e6bdde2 100755 --- a/trunk/testsuite/tls4.sh +++ b/trunk/testsuite/tls4.sh @@ -2,9 +2,9 @@ . `dirname $0`/functions.sh # First check if __thread is supported by ld.so/gcc/ld/as: rm -f tlstest -echo '__thread int a; int main (void) { return a; }' \ - | $CC -xc - -o tlstest > /dev/null 2>&1 || exit 77 -( ./tlstest || { rm -f tlstest; exit 77; } ) 2>/dev/null || exit 77 +#echo '__thread int a; int main (void) { return a; }' \ +# | $CC -xc - -o tlstest > /dev/null 2>&1 || exit 77 +#( ./tlstest || { rm -f tlstest; exit 77; } ) 2>/dev/null || exit 77 rm -f tls4 tls4lib*.so tls4.log rm -f prelink.cache $CC -shared -O2 -fpic -o tls4lib1.so $srcdir/tls4lib1.c @@ -17,7 +17,9 @@ savelibs echo $PRELINK ${PRELINK_OPTS--vm} ./tls4 > tls4.log $PRELINK ${PRELINK_OPTS--vm} ./tls4 >> tls4.log 2>&1 || exit 1 grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` tls4.log && exit 2 -LD_LIBRARY_PATH=. ./tls4 || exit 3 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./tls4 || exit 3 +fi readelf -a ./tls4 >> tls4.log 2>&1 || exit 4 # So that it is not prelinked again chmod -x ./tls4 diff --git a/trunk/testsuite/tls5.sh b/trunk/testsuite/tls5.sh index dbc0470..68ec82f 100755 --- a/trunk/testsuite/tls5.sh +++ b/trunk/testsuite/tls5.sh @@ -2,9 +2,9 @@ . `dirname $0`/functions.sh # First check if __thread is supported by ld.so/gcc/ld/as: rm -f tlstest -echo '__thread int a; int main (void) { return a; }' \ - | $CC -xc - -o tlstest > /dev/null 2>&1 || exit 77 -( ./tlstest || { rm -f tlstest; exit 77; } ) 2>/dev/null || exit 77 +#echo '__thread int a; int main (void) { return a; }' \ +# | $CC -xc - -o tlstest > /dev/null 2>&1 || exit 77 +#( ./tlstest || { rm -f tlstest; exit 77; } ) 2>/dev/null || exit 77 rm -f tls5 tls5lib*.so tls5.log rm -f prelink.cache echo 'int tls5;' | $CC -shared -O2 -fpic -xc - -o tls5lib3.so @@ -18,12 +18,16 @@ savelibs echo $PRELINK ${PRELINK_OPTS--vm} ./tls5 > tls5.log $PRELINK ${PRELINK_OPTS--vm} ./tls5 >> tls5.log 2>&1 || exit 1 grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` tls5.log && exit 2 -LD_LIBRARY_PATH=. ./tls5 || exit 3 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./tls5 || exit 3 +fi $PRELINK -u tls5lib3.so || exit 4 echo $PRELINK ${PRELINK_OPTS--vm} ./tls5 >> tls5.log $PRELINK ${PRELINK_OPTS--vm} ./tls5 >> tls5.log 2>&1 || exit 5 grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` tls5.log && exit 6 -LD_LIBRARY_PATH=. ./tls5 || exit 7 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./tls5 || exit 7 +fi readelf -a ./tls5 >> tls5.log 2>&1 || exit 8 # So that it is not prelinked again chmod -x ./tls5 diff --git a/trunk/testsuite/tls6.sh b/trunk/testsuite/tls6.sh index 2d854d9..60ae492 100755 --- a/trunk/testsuite/tls6.sh +++ b/trunk/testsuite/tls6.sh @@ -2,9 +2,9 @@ . `dirname $0`/functions.sh # First check if __thread is supported by ld.so/gcc/ld/as: rm -f tlstest -echo '__thread int a; int main (void) { return a; }' \ - | $CC -xc - -o tlstest > /dev/null 2>&1 || exit 77 -( ./tlstest || { rm -f tlstest; exit 77; } ) 2>/dev/null || exit 77 +#echo '__thread int a; int main (void) { return a; }' \ +# | $CC -xc - -o tlstest > /dev/null 2>&1 || exit 77 +#( ./tlstest || { rm -f tlstest; exit 77; } ) 2>/dev/null || exit 77 rm -f tls6 tls6lib*.so tls6.log rm -f prelink.cache echo 'int tls6;' | $CC -shared -O2 -fpic -xc - -o tls6lib3.so @@ -19,13 +19,17 @@ echo $PRELINK ${PRELINK_OPTS--vm} ./tls6 > tls6.log $PRELINK ${PRELINK_OPTS--vm} ./tls6 >> tls6.log 2>&1 || exit 1 grep -v 'has undefined non-weak symbols' tls6.log \ | grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` && exit 2 -LD_LIBRARY_PATH=. ./tls6 || exit 3 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./tls6 || exit 3 +fi $PRELINK -u tls6lib3.so || exit 4 echo $PRELINK ${PRELINK_OPTS--vm} ./tls6 >> tls6.log $PRELINK ${PRELINK_OPTS--vm} ./tls6 >> tls6.log 2>&1 || exit 5 grep -v 'has undefined non-weak symbols' tls6.log \ | grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` && exit 6 -LD_LIBRARY_PATH=. ./tls6 || exit 7 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./tls6 || exit 7 +fi readelf -a ./tls6 >> tls6.log 2>&1 || exit 8 # So that it is not prelinked again chmod -x ./tls6 diff --git a/trunk/testsuite/tls7.sh b/trunk/testsuite/tls7.sh index ab93719..216a379 100755 --- a/trunk/testsuite/tls7.sh +++ b/trunk/testsuite/tls7.sh @@ -2,9 +2,9 @@ . `dirname $0`/functions.sh # First check if __thread is supported by ld.so/gcc/ld/as: rm -f tlstest -echo '__thread int a; int main (void) { return a; }' \ - | $CC -xc - -o tlstest > /dev/null 2>&1 || exit 77 -( ./tlstest || { rm -f tlstest; exit 77; } ) 2>/dev/null || exit 77 +#echo '__thread int a; int main (void) { return a; }' \ +# | $CC -xc - -o tlstest > /dev/null 2>&1 || exit 77 +#( ./tlstest || { rm -f tlstest; exit 77; } ) 2>/dev/null || exit 77 rm -f tls7 tls7.log rm -f prelink.cache BINS="tls7" @@ -14,7 +14,9 @@ savelibs echo $PRELINK ${PRELINK_OPTS--vm} ./tls7 > tls7.log $PRELINK ${PRELINK_OPTS--vm} ./tls7 >> tls7.log 2>&1 || exit 1 grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` tls7.log && exit 2 -LD_LIBRARY_PATH=. ./tls7 || exit 3 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./tls7 || exit 3 +fi readelf -a ./tls7 >> tls7.log 2>&1 || exit 4 # So that it is not prelinked again chmod -x ./tls7 diff --git a/trunk/testsuite/undo1.sh b/trunk/testsuite/undo1.sh index d8436a5..ed61b6b 100755 --- a/trunk/testsuite/undo1.sh +++ b/trunk/testsuite/undo1.sh @@ -11,7 +11,9 @@ savelibs echo $PRELINK ${PRELINK_OPTS--vm} ./undo1 > undo1.log $PRELINK ${PRELINK_OPTS--vm} ./undo1 >> undo1.log 2>&1 || exit 1 grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` undo1.log && exit 2 -LD_LIBRARY_PATH=. ./undo1 || exit 3 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./undo1 || exit 3 +fi readelf -a ./undo1 >> undo1.log 2>&1 || exit 4 # So that it is not prelinked again chmod -x ./undo1 |