aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--trunk/ChangeLog.cross458
-rw-r--r--trunk/configure.in44
-rw-r--r--trunk/doc/prelink.89
-rw-r--r--trunk/src/Makefile.am31
-rw-r--r--trunk/src/arch-alpha.c2
-rw-r--r--trunk/src/arch-arm.c9
-rw-r--r--trunk/src/arch-cris.c2
-rw-r--r--trunk/src/arch-i386.c2
-rw-r--r--trunk/src/arch-ia64.c2
-rw-r--r--trunk/src/arch-mips.c666
-rw-r--r--trunk/src/arch-ppc.c2
-rw-r--r--trunk/src/arch-ppc64.c2
-rw-r--r--trunk/src/arch-s390.c2
-rw-r--r--trunk/src/arch-s390x.c2
-rw-r--r--trunk/src/arch-sh.c6
-rw-r--r--trunk/src/arch-sparc.c2
-rw-r--r--trunk/src/arch-sparc64.c2
-rw-r--r--trunk/src/arch-x86_64.c2
-rw-r--r--trunk/src/cache.c11
-rw-r--r--trunk/src/canonicalize.c87
-rw-r--r--trunk/src/conflict.c31
-rw-r--r--trunk/src/cxx.c12
-rw-r--r--trunk/src/data.c26
-rw-r--r--trunk/src/doit.c12
-rw-r--r--trunk/src/dso-readonly.c1832
-rw-r--r--trunk/src/dso.c55
-rw-r--r--trunk/src/elf.h2581
-rw-r--r--trunk/src/execle_open.c3
-rw-r--r--trunk/src/execstack.c36
-rw-r--r--trunk/src/gather.c209
-rw-r--r--trunk/src/get.c73
-rw-r--r--trunk/src/layout.c7
-rw-r--r--trunk/src/ld-do-lookup.h232
-rw-r--r--trunk/src/ld-libs.c1512
-rw-r--r--trunk/src/ld-libs.h115
-rw-r--r--trunk/src/ld-lookup.c298
-rw-r--r--trunk/src/ld-lookup64.c24
-rw-r--r--trunk/src/main.c82
-rw-r--r--trunk/src/prelink.c5
-rw-r--r--trunk/src/prelink.h58
-rw-r--r--trunk/src/reloc-info.c215
-rw-r--r--trunk/src/reloc-info.h35
-rw-r--r--trunk/src/space.c361
-rw-r--r--trunk/src/undoall.c10
-rw-r--r--trunk/src/verify.c27
-rw-r--r--trunk/src/wrap-file.c317
-rw-r--r--trunk/testsuite/Makefile.in10
-rwxr-xr-xtrunk/testsuite/cxx1.sh4
-rwxr-xr-xtrunk/testsuite/cycle1.sh4
-rwxr-xr-xtrunk/testsuite/cycle2.sh4
-rwxr-xr-xtrunk/testsuite/deps1.sh4
-rwxr-xr-xtrunk/testsuite/deps2.sh4
-rwxr-xr-xtrunk/testsuite/functions.sh3
-rwxr-xr-xtrunk/testsuite/layout1.sh4
-rwxr-xr-xtrunk/testsuite/layout2.sh4
-rwxr-xr-xtrunk/testsuite/movelibs.sh2
-rwxr-xr-xtrunk/testsuite/quick1.sh48
-rwxr-xr-xtrunk/testsuite/quick2.sh60
-rwxr-xr-xtrunk/testsuite/quick3.sh4
-rwxr-xr-xtrunk/testsuite/reloc1.sh4
-rwxr-xr-xtrunk/testsuite/reloc10.sh4
-rwxr-xr-xtrunk/testsuite/reloc11.sh4
-rwxr-xr-xtrunk/testsuite/reloc2.sh6
-rwxr-xr-xtrunk/testsuite/reloc3.sh6
-rwxr-xr-xtrunk/testsuite/reloc4.sh12
-rw-r--r--trunk/testsuite/reloc5.c4
-rwxr-xr-xtrunk/testsuite/reloc5.sh6
-rwxr-xr-xtrunk/testsuite/reloc6.sh24
-rwxr-xr-xtrunk/testsuite/reloc7.sh4
-rwxr-xr-xtrunk/testsuite/reloc8.sh8
-rwxr-xr-xtrunk/testsuite/reloc9.sh8
-rwxr-xr-xtrunk/testsuite/shuffle1.sh4
-rw-r--r--trunk/testsuite/shuffle2.c7
-rwxr-xr-xtrunk/testsuite/shuffle2.sh10
-rwxr-xr-xtrunk/testsuite/shuffle3.sh10
-rwxr-xr-xtrunk/testsuite/shuffle4.sh10
-rwxr-xr-xtrunk/testsuite/shuffle5.sh4
-rwxr-xr-xtrunk/testsuite/shuffle6.sh8
-rwxr-xr-xtrunk/testsuite/shuffle7.sh12
-rwxr-xr-xtrunk/testsuite/shuffle8.sh6
-rwxr-xr-xtrunk/testsuite/tls1.sh10
-rwxr-xr-xtrunk/testsuite/tls2.sh10
-rwxr-xr-xtrunk/testsuite/tls3.sh10
-rwxr-xr-xtrunk/testsuite/tls4.sh10
-rwxr-xr-xtrunk/testsuite/tls5.sh14
-rwxr-xr-xtrunk/testsuite/tls6.sh14
-rwxr-xr-xtrunk/testsuite/tls7.sh10
-rwxr-xr-xtrunk/testsuite/undo1.sh4
88 files changed, 9273 insertions, 636 deletions
diff --git a/trunk/ChangeLog.cross b/trunk/ChangeLog.cross
new file mode 100644
index 0000000..6a4acf6
--- /dev/null
+++ b/trunk/ChangeLog.cross
@@ -0,0 +1,458 @@
+2009-09-01 Maciej W. Rozycki <macro@codesourcery.com>
+
+ Issue #5273
+ * src/arch-mips.c (mips_prelink_reloc): Resolve
+ R_MIPS_TLS_DTPMOD32 and R_MIPS_TLS_DTPMOD64 relocations in
+ executables.
+
+2009-04-27 Maciej W. Rozycki <macro@codesourcery.com>
+ Issue #5165
+ * src/ld-libs.c (load_ld_so_conf): Fix a buffer overrun. Don't
+ record empty paths.
+
+
+2009-04-23 Maciej W. Rozycki <macro@codesourcery.com>
+
+ Issue #5165
+ * src/ld-lookup.c (rtld_elf_hash): Handle an initial NULL
+ character correctly. Reformat for consistency with
+ rtld_elf_gnu_hash()
+
+2009-04-23 Maciej W. Rozycki <macro@codesourcery.com>
+
+ Issue #5165
+ * src/ld-do-lookup.h (FCT): Remove the hash argument and
+ calculate the value within the function. Call
+ do_lookup_get_first() and do_lookup_get_next() to iterate over
+ symbols.
+ * src/prelink.h (dynamic_info_is_set): Convert macro to a
+ function. Return 1 for success rather than the bit set.
+ * src/ld-libs.h (ldlibs_link_map): Add l_gnu_hash, l_maskword64,
+ l_nmaskwords, l_shift and l_maskwords members.
+ * src/ld-libs.c (create_ldlibs_link_map): Handle the GNU hash.
+ * src/ld-lookup.c (rtld_elf_gnu_hash): New function.
+ (rtld_elf_any_hash): Likewise.
+ (rtld_elf_hash): Move above "ld-do-lookup.h" inclusions.
+ (do_lookup_get_first, do_lookup_get_next): New functions.
+ (rtld_lookup_symbol): Remove hash calculation.
+ (rtld_lookup_symbol_versioned): Likewise.
+
+2009-04-23 Maciej W. Rozycki <macro@codesourcery.com>
+
+ Issue #5165
+ * src/execle_open.c (execve_open): Add missing pid
+ initialisation.
+
+2010-06-15 Mark Hatle <mark.hatle@windriver.com>
+ * Merge to upstream r174
+ * src/arch-mips.c, src/conflict.c, src/cxx.c, src/main.c, src/verify.c:
+ fix items missed in the merge
+ * Resync dso-readonly.c from dso.c
+
+2010-06-14 Mark Hatle <mark.hatle@windriver.com>
+
+ * Integrate prelinker/cross-prelinking patches
+
+ 2009-08-06 Joseph Myers <joseph@codesourcery.com>
+
+ * src/dwarf2.c (dwarf2_write_le64, dwarf2_write_be64): Shift by 56
+ not 58 for MSB.
+
+ 2009-03-19 Joseph Myers <joseph@codesourcery.com>
+
+ Issue #4626
+ * src/cache.c, src/dso-readonly.c, src/dso.c, src/execstack.c,
+ src/gather.c, src/layout.c, src/mapfile.c, src/verify.c: fsync
+ file descriptors before closing them.
+
+ 2008-09-23 Joseph Myers <joseph@codesourcery.com>
+
+ * src/arch-arm.c (arm_prelink_conflict_rela): Correct
+ R_ARM_TLS_TPOFF32 handling.
+
+ 2008-09-18 Joseph Myers <joseph@codesourcery.com>
+
+ * src/ld-libs.c (reloc_type_class, determine_tlsoffsets): Handle
+ SPARC.
+ * src/arch-sparc64.c (sparc64_prelink_rela,
+ sparc64_prelink_conflict_rela, sparc64_undo_prelink_rela,
+ sparc64_reloc_class): Handle TLS relocations.
+ (PL_ARCH(sparc64)): Update mmap_base and mmap_end for
+ TASK_UNMAPPED_BASE change to 0xfffff80100000000.
+
+ 2008-10-02 Maciej W. Rozycki <macro@codesourcery.com>
+
+ * src/arch-mips.c (mips_prelink_reloc): Do not complain about
+ TLS_DTPMOD32 or TLS_DTPMOD64 relocations found in executables.
+
+ 2008-09-03 Maciej W. Rozycki <macro@codesourcery.com>
+
+ * src/prelink.h (Elf64_Byte): New definition.
+ (R_MIPS_TLS_DTPMOD64): New macro.
+ (R_MIPS_TLS_DTPREL64): Likewise.
+ (R_MIPS_TLS_TPREL64): Likewise.
+ (RSS_UNDEF): Likewise.
+ (PL_ARCH): Use plarch_##F as the name of the struct in all
+ variants.
+ * src/reloc-info.c: New file.
+ * src/reloc-info.h: Likewise.
+ * src/arch-mips.c (mips_buf_read_addr): New function.
+ (mips_buf_write_addr): Likewise.
+ (mips_arch_adjust): Replace calls to buf_read_une32() and
+ buf_write_ne32() with ones to mips_buf_read_addr() and
+ mips_buf_write_addr() respectively.
+ (mips_read_addend): Rename to...
+ (mips_read_32bit_addend): ... this.
+ (mips_write_addend): Rename to...
+ (mips_write_32bit_addend): ... this.
+ (mips_read_64bit_addend): New function.
+ (mips_write_64bit_addend): Likewise.
+ (mips_adjust_reloc): Handle 64-bit REL relocations. Use
+ reloc_r_sym() and reloc_r_type() in place of GELF_R_SYM() and
+ GELF_R_TYPE() respectively.
+ (mips_prelink_64bit_reloc): New function.
+ (mips_prelink_reloc): Handle 64-bit REL and GLOB_DAT relocations.
+ Handle TLS_DTPMOD64, TLS_DTPREL64 and TLS_TPREL64 relocations.
+ Use reloc_r_sym() and reloc_r_type().
+ (mips_prelink_rel): Handle 64-bit REL relocations. Use
+ reloc_r_sym(), reloc_r_type() and reloc_r_info_ext() (replacing
+ GELF_R_INFO()).
+ (mips_prelink_conflict_reloc): Handle 64-bit REL relocations.
+ Handle TLS_DTPMOD64, TLS_DTPREL64 and TLS_TPREL64 relocations.
+ Use reloc_r_sym(), reloc_r_type() and reloc_r_info_ext().
+ (mips_arch_prelink_conflict): Use mips_buf_read_addr(). Use
+ reloc_r_info_ext().
+ (mips_apply_conflict_rela): Handle 64-bit REL relocations. Use
+ reloc_r_type(). Use mips_buf_read_addr() and
+ mips_buf_write_addr().
+ (mips_apply_reloc): Handle 64-bit REL relocations. Use
+ reloc_r_sym() and reloc_r_type().
+ (mips_rel_to_rela): Handle 64-bit REL relocations. Handle
+ TLS_DTPMOD64, TLS_DTPREL64 and TLS_TPREL64 relocations. Use
+ reloc_r_sym() and reloc_r_type().
+ (mips_rela_to_rel): Handle 64-bit REL and GLOB_DAT relocations.
+ Handle TLS_DTPMOD64, TLS_DTPREL64 and TLS_TPREL64 relocations.
+ Use reloc_r_sym() and reloc_r_type().
+ (mips_need_rel_to_rela): Use data obtained with gelfx_getshdr() to
+ determine the size of a relocation entry. Use gelfx_getrel() to
+ retrieve them. Handle 64-bit REL relocations. Handle
+ TLS_DTPMOD64, TLS_DTPREL64 and TLS_TPREL64 relocations. Use
+ reloc_r_sym() and reloc_r_type() instead of ELF32_R_SYM() and
+ ELF32_R_TYPE() respectively.
+ (mips_reloc_class): Handle TLS_DTPMOD64, TLS_DTPREL64 and
+ TLS_TPREL64 relocations.
+ (mips_arch_prelink): Use mips_buf_read_addr() and
+ mips_buf_write_addr().
+ (mips_arch_undo_prelink): Likewise.
+ (mips_undo_prelink_rel): Handle 64-bit GLOB_DAT relocations. Use
+ reloc_r_sym(), reloc_r_type() and reloc_r_info_ext().
+ (mips64): New PL_ARCH.
+ * src/prelink.c (prelink_prepare): Handle SHT_MIPS_OPTIONS.
+ * src/conflict.c (conflict_rela_cmp_dso): New variable.
+ (conflict_rela_cmp): Use conflict_rela_cmp_dso and reloc_r_sym().
+ (get_relocated_mem): Use reloc_r_type().
+ (prelink_add_copy_rel): Use reloc_r_sym() and reloc_r_type().
+ (prelink_build_conflicts): Use reloc_r_sym(), reloc_r_type() and
+ reloc_r_info(). Pass dso to conflict_rela_cmp() through
+ conflict_rela_cmp_dso.
+ (prelink_find_copy_rela): Use reloc_r_type().
+ * src/cxx.c (remove_redundant_cxx_conflicts): Use reloc_r_sym(),
+ reloc_r_type() and reloc_r_info().
+ * src/ld-libs.c (do_rel_section): Use reloc_r_sym() and
+ reloc_r_type().
+ * src/Makefile.am (common_SOURCES): Add reloc-info.c and
+ reloc-info.h.
+ (prelink_rtld_SOURCES): Likewise.
+ * src/Makefile.in: Regenerate.
+ * configure.in: Check for the Elf64_Byte type. Require autoconf
+ 2.50.
+ * configure: Regenerate.
+
+ 2008-09-03 Maciej W. Rozycki <macro@codesourcery.com>
+
+ * src/arch-mips.c (mips_undo_prelink_rel): Fix formatting.
+
+ 2008-09-03 Maciej W. Rozycki <macro@codesourcery.com>
+
+ * src/arch-mips.c (mips_init_local_got_iterator): Use ELF_T_ADDR
+ to determine the width of GOT entries.
+ (mips_init_global_got_iterator): Likewise.
+
+ 2008-09-03 Maciej W. Rozycki <macro@codesourcery.com>
+
+ * src/data.c (buf_read_une##nn): Fix the width of the data
+ transfer used.
+
+ 2008-03-06 Daniel Jacobowitz <dan@codesourcery.com>
+
+ * src/ld-do-lookup.h: Check for STO_MIPS_PLT on MIPS.
+ * src/ld-libs.c (reloc_type_class): Handle copy and PLT relocs.
+ * src/prelink.h (R_MIPS_TLS_DTPMOD32, R_MIPS_TLS_DTPREL32)
+ (R_MIPS_TLS_TPREL32, R_MIPS_GLOB_DAT): Remove duplicate definitions.
+ (R_MIPS_COPY, R_MIPS_JUMP_SLOT, STO_MIPS_PLT, DT_MIPS_PLTGOT)
+ (DT_MIPS_PLTNO, DT_MIPS_RWPLT): Define.
+ (DSO): Add info_DT_MIPS_PLTGOT.
+ * src/arch-mips.c (mips_prelink_reloc): Handle R_MIPS_JUMP_SLOT and
+ R_MIPS_COPY.
+ (mips_prelink_conflict_reloc): Handle R_MIPS_COPY.
+ (mips_apply_conflict_rela): Handle R_MIPS_JUMP_SLOT.
+ (mips_apply_reloc): Handle R_MIPS_JUMP_SLOT and R_MIPS_COPY.
+ (mips_rel_to_rela, mips_rela_to_rel): Handle R_MIPS_COPY.
+ (mips_need_rel_to_rela): Handle R_MIPS_COPY and R_MIPS_JUMP_SLOT.
+ Correct error message.
+ (mips_reloc_class): Handle R_MIPS_COPY and R_MIPS_JUMP_SLOT. Use
+ RTYPE_CLASS_VALID by default.
+ (mips_arch_prelink): Save .plt in gotplt[1].
+ (mips_arch_undo_prelink): Clear gotplt[1].
+ (mips_undo_prelink_rel): Undo R_MIPS_JUMP_SLOT relocations.
+ (PL_ARCH): Set R_COPY and R_JMP_SLOT.
+ * src/dso.c (read_dynamic): Save DT_MIPS_PLTGOT.
+ * src/dso-readonly.c (read_dynamic): ditto
+
+ 2007-07-09 Daniel Jacobowitz <dan@codesourcery.com>
+
+ Issue #1816
+ * src/wrap-file.c (chroot_canon): Delete.
+ (sysroot_file_name): Use canon_filename.
+ (unsysroot_file_name): Make global.
+ (wrap_canonicalize_file_name): Delete.
+ * src/ld-libs.c (load_dsos): Use prelink_canonicalize.
+ * src/canonicalize.c (canon_filename): Make global. Add chroot,
+ allow_last_link, allow_missing arguments. Handle links inside
+ a chroot. Handle canonicalizing the current directory. Remove
+ debugging output.
+ (prelink_canonicalize): Update. Use unsysroot_file_name.
+ * src/prelink.h (wrap_canonicalize_file_name): Delete prototype.
+
+ 2007-03-02 Sandra Loosemore <sandra@codesourcery.com>
+
+ * doc/prelink.8: Copy edit. Add entry for --root option. Update
+ list of unsupported systems.
+
+ 2007-02-16 Daniel Jacobowitz <dan@codesourcery.com>
+
+ * src/prelink.h (sysroot_file_name): Declare.
+ * src/ld-libs.c (load_dsos): Take host_paths argument. Do not attempt
+ to canonicalize host filenames within the sysroot. Always set
+ canon_filename.
+ (process_one_dso): Update call to load_dsos. Do not redo call to
+ wrap_canonicalize_file_name.
+
+ 2006-11-30 Mark Shinwell <shinwell@codesourcery.com>
+
+ * configure.in: Recognize --with-pkgversion and ---with-bugurl.
+ * src/Makefile.am: Pass package version and bug URL through
+ AM_CFLAGS, together with the new EXECSTACK_PROG.
+ * src/main.c: Use PKGVERSION and REPORT_BUGS_TO.
+ * src/execstack.c: Likewise. Also use EXECSTACK_PROG.
+
+ Mark Hatle <mark.hatle@windriver.com>
+ * src/ld-libs.c: Use PRELINK_RTLD_PROG, PKGVERSION and REPORT_BUGS_TO
+ * src/execstack.c: Use EXECSTACK_PROG in (argp_doc)
+
+ 2006-11-30 Mark Shinwell <shinwell@codesourcery.com>
+
+ * wrap-file.c (wrap_stat_body): New.
+ (wrap_lstat64, wrap_stat64): Use wrap_stat_body.
+
+ 2006-11-28 Mark Shinwell <shinwell@codesourcery.com>
+
+ * src/layout.c (layout_libs): Add assertion to check for buffer
+ overflow.
+ * src/ld-libs.c (find_lib_in_path): Add "machine" argument.
+ Skip libraries whose ELF machine type field does not match
+ that argument.
+ (find_lib_by_soname): Add "machine" argument. Pass it to
+ find_lib_in_path.
+ (load_dsos): Determine machine type of input DSO. Pass it
+ to find_lib_by_soname.
+
+ 2006-11-28 Mark Shinwell <shinwell@codesourcery.com>
+
+ * src/gather.c (maybe_pie): New.
+ (gather_func): Use it.
+
+ 2006-11-28 Mark Shinwell <shinwell@codesourcery.com>
+
+ * src/canonicalize.c: Add prelink.h include directive.
+ Use wrap_readlink and wrap_lstat64.
+ * src/prelink.h: Declare wrap_readlink.
+ * src/wrap-file.c (wrap_readlink): New.
+
+ 2006-10-13 Daniel Jacobowitz <dan@codesourcery.com>
+
+ * src/execle_open.c (execve_open): Add an error message if execve
+ fails.
+
+ 2006-10-03 Richard Sandiford <richard@codesourcery.com>
+
+ * configure.in (AC_CANONICAL_HOST): Remove in favour of...
+ (AC_CANONICAL_SYSTEM): ...this new directive.
+ (AC_ARG_PROGRAM): New directive.
+ * src/Makefile.am (AM_CFLAGS): Define PRELINK_PROG, PRELINK_RTLD_PROG
+ and EXEEXT.
+ (execstack_LDADD): Add -liberty.
+ * src/execstack.c (program_path, prelink_path): New variables.
+ (execstack_make_rdwr): Initialize prelink_path if it has not
+ been set yet. Use make_relative_prefix, PRELINK_PROG and EXEEXT
+ to get the full pathname of the prelink executable. Pass this path
+ to execl() as the name of executable file.
+ (main): Initialize program_path.
+ * src/main.c (argp_program_version, argp_doc): Use PRELINK_PROG as
+ the program name.
+ (main): Handle empty --rtld= arguments first. Always use
+ make_relative_prefix to work out the path of the defalt rtld
+ executable. Also use PRELINK_RTLD and EXEEXT for this purpose.
+
+2010-06-14 Mark Hatle <mark.hatle@windriver.com>
+ * configure.in: Add option to disable selinux
+ * src/Makefile.am: Stop static linking
+
+2007-08-08 Mark Hatle <mark.hatle@windriver.com>
+
+ * src/arch-mips.c: add /lib32/ld.so.1 as an alternative 32-bit linker
+ * src/ld-libs.c: add a check for MIPS n32, and adjust ld_dirs as
+ necessary
+
+2007-10-11 Richard Sandiford <richard@codesourcery.com>
+
+ * src/space.c (find_readonly_space): If a new PT_LOAD header is needed,
+ first try removing a PT_NULL header.
+
+2006-12-04 Mark Hatle <mark.hatle@windriver.com>
+
+ * Merge code from:
+
+ Richard Sandiford <richard@codesourcery.com>
+ * src/ld-libs.c (reloc_type_class): Handle EM_MIPS.
+ (do_mips_global_relocs): New function.
+ (handle_relocs_in_entry): Call it.
+ (determine_tlsoffsets): Handle EM_MIPS.
+
+ Richard Sandiford <richard@codesourcery.com>
+
+ * src/ld-libs.c (do_reloc): New function, split out from
+ do_rel_section. Take the symbol and relocation type as arguments.
+ (do_rel_section): Call it.
+ (handle_relocs_in_entry): New function.
+ (handle_relocs): Call it.
+
+2006-12-04 Mark Hatle <mark.hatle@windriver.com>
+
+ * src/elf.h: Update to the latest version of elf.h for MIPS prelink
+
+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/configure.in b/trunk/configure.in
index 396f3ac..5998659 100644
--- a/trunk/configure.in
+++ b/trunk/configure.in
@@ -1,8 +1,9 @@
dnl Process this file with autoconf to produce a configure script. -*-m4-*-
AC_INIT(src/prelink.c)
AM_CONFIG_HEADER(config.h)
-AC_PREREQ(2.13) dnl Minimum Autoconf version required.
-AC_CANONICAL_HOST
+AC_PREREQ(2.50) dnl Minimum Autoconf version required.
+AC_CANONICAL_SYSTEM
+AC_ARG_PROGRAM
AM_INIT_AUTOMAKE([prelink], [0.0])
@@ -69,6 +70,16 @@ if test "x$ac_cv_ftw_actionretval" = xyes; then
fi
dnl SELinux checks
+AC_ARG_ENABLE(selinux,
+ AS_HELP_STRING([--disable-selinux],
+ [Disable selinux support in the prelinker]),
+ [ enable_selinux="$enableval" ],
+ [ enable_selinux="yes" ])
+
+if test "x$enable_selinux" != "no"; then
+ ac_cv_lib_selinux_is_selinux_enabled=disabled
+fi
+
AC_CHECK_LIB(selinux,is_selinux_enabled)
AC_CHECK_HEADERS(selinux/selinux.h)
@@ -82,6 +93,35 @@ fi
AC_LIBELF_SXWORD
+dnl Elf64_Byte is specific to the 64-bit MIPS psABI and may not be defined.
+AC_CHECK_TYPES([Elf64_Byte], [], [], [#include <libelf.h>])
+
+# Package version.
+AC_ARG_WITH(pkgversion,
+ AS_HELP_STRING([--with-pkgversion=PKG],
+ [Add PKG to the version string]),
+ [case "$withval" in
+ yes) AC_MSG_ERROR([package version not specified]) ;;
+ no) PKGVERSION= ;;
+ *) PKGVERSION=" ($withval)" ;;
+ esac],
+ PKGVERSION=
+)
+AC_SUBST(PKGVERSION)
+
+# The location to which bugs should be reported.
+AC_ARG_WITH(bugurl,
+ AS_HELP_STRING([--with-bugurl=URL],
+ [Direct users to URL to report a bug]),
+ [case "$withval" in
+ yes) AC_MSG_ERROR([bug URL not specified]) ;;
+ no) REPORT_BUGS_TO="" ;;
+ *) REPORT_BUGS_TO="<URL:$withval>" ;;
+ esac],
+ REPORT_BUGS_TO="<jakub@redhat.com>"
+)
+AC_SUBST(REPORT_BUGS_TO)
+
AC_OUTPUT([Makefile
src/Makefile
gelfx/Makefile
diff --git a/trunk/doc/prelink.8 b/trunk/doc/prelink.8
index e5a0062..f6b9c7c 100644
--- a/trunk/doc/prelink.8
+++ b/trunk/doc/prelink.8
@@ -147,6 +147,13 @@ walking directory hierarchies.
When processing command line directory arguments, limit directory tree walk
to a single file system.
.TP
+.B \-\-root=PATHNAME
+In a cross-compilation environment, this specifies the path to the root of
+the target's file system. All other pathnames processed by
+.B prelink
+are relative to this root, including the name of the configuration file
+as well as its contents and pathnames supplied on the command line.
+.TP
.B \-u \-\-undo
Revert binaries and libraries to their original content before they were
prelinked.
@@ -304,6 +311,6 @@ are ignored).
.SH BUGS
.LP
.B prelink
-Some architectures, including IA-64 and HPPA, are not yet supported.
+Some architectures, including HPPA, are not yet supported.
.SH AUTHORS
Jakub Jelinek <jakub@redhat.com>.
diff --git a/trunk/src/Makefile.am b/trunk/src/Makefile.am
index d2265aa..387b6ef 100644
--- a/trunk/src/Makefile.am
+++ b/trunk/src/Makefile.am
@@ -2,27 +2,46 @@
AUTOMAKE_OPTIONS = 1.4 gnu
+PKGVERSION = "\"@PKGVERSION@\""
+REPORT_BUGS_TO = "\"@REPORT_BUGS_TO@\""
+
DEFS = -D_GNU_SOURCE -DHAVE_CONFIG_H -Wall -Wno-pointer-sign
AM_CFLAGS = -Wall -Wno-pointer-sign
-AM_CPPFLAGS = -DSBINDIR='"@sbindir@"'
+AM_CPPFLAGS = -DSBINDIR='"@sbindir@"' -DBINDIR='"@bindir@"' \
+ -DEXECSTACK_PROG="\"`echo execstack | sed '$(transform)'`\"" \
+ -DPRELINK_PROG="\"`echo prelink | sed '$(transform)'`\"" \
+ -DPRELINK_RTLD_PROG="\"`echo prelink-rtld | \
+ sed '$(transform)'`\"" \
+ -DEXEEXT='"$(EXEEXT)"' \
+ -DPKGVERSION=$(PKGVERSION) \
+ -DREPORT_BUGS_TO=$(REPORT_BUGS_TO)
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 reloc-info.c reloc-info.h
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_LDFLAGS = -all-static
+prelink_LDADD = @LIBGELF@ -liberty
+prelink_LDFLAGS =
execstack_SOURCES = execstack.c $(common_SOURCES) $(arch_SOURCES)
+execstack_LDADD = -liberty
+execstack_LDFLAGS =
+
+prelink_rtld_SOURCES = data.c dso-readonly.c ld-libs.c ld-lookup.c \
+ canonicalize.c wrap-file.c ld-lookup64.c \
+ reloc-info.c reloc-info.h
+prelink_rtld_LDADD = @LIBGELF@ -liberty
+prelink_rtld_LDFLAGS =
extra_DIST = makecrc.c
diff --git a/trunk/src/arch-alpha.c b/trunk/src/arch-alpha.c
index b326b0b..7802a3e 100644
--- a/trunk/src/arch-alpha.c
+++ b/trunk/src/arch-alpha.c
@@ -466,7 +466,7 @@ alpha_reloc_class (int reloc_type)
}
}
-PL_ARCH = {
+PL_ARCH(alpha) = {
.name = "Alpha",
.class = ELFCLASS64,
.machine = EM_ALPHA,
diff --git a/trunk/src/arch-arm.c b/trunk/src/arch-arm.c
index 47fde9b..ba53929 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)
@@ -823,7 +829,7 @@ arm_reloc_class (int reloc_type)
}
}
-PL_ARCH = {
+PL_ARCH(arm) = {
.name = "ARM",
.class = ELFCLASS32,
.machine = EM_ARM,
@@ -833,6 +839,7 @@ PL_ARCH = {
.R_RELATIVE = R_ARM_RELATIVE,
.rtype_class_valid = RTYPE_CLASS_VALID,
.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-cris.c b/trunk/src/arch-cris.c
index d70260a..3272779 100644
--- a/trunk/src/arch-cris.c
+++ b/trunk/src/arch-cris.c
@@ -374,7 +374,7 @@ cris_reloc_class (int reloc_type)
}
}
-PL_ARCH = {
+PL_ARCH(cris) = {
.name = "CRIS",
.class = ELFCLASS32,
.machine = EM_CRIS,
diff --git a/trunk/src/arch-i386.c b/trunk/src/arch-i386.c
index 67b12b5..5661dcb 100644
--- a/trunk/src/arch-i386.c
+++ b/trunk/src/arch-i386.c
@@ -1083,7 +1083,7 @@ i386_layout_libs_post (struct layout_libs *l)
return 0;
}
-PL_ARCH = {
+PL_ARCH(i386) = {
.name = "i386",
.class = ELFCLASS32,
.machine = EM_386,
diff --git a/trunk/src/arch-ia64.c b/trunk/src/arch-ia64.c
index 2573d69..6039115 100644
--- a/trunk/src/arch-ia64.c
+++ b/trunk/src/arch-ia64.c
@@ -492,7 +492,7 @@ ia64_reloc_class (int reloc_type)
}
}
-PL_ARCH = {
+PL_ARCH(ia64) = {
.name = "IA-64",
.class = ELFCLASS64,
.machine = EM_IA_64,
diff --git a/trunk/src/arch-mips.c b/trunk/src/arch-mips.c
index 3e39f03..25fdacc 100644
--- a/trunk/src/arch-mips.c
+++ b/trunk/src/arch-mips.c
@@ -1,5 +1,6 @@
-/* Copyright (C) 2006 CodeSourcery
+/* Copyright (C) 2006, 2008 CodeSourcery.
Written by Richard Sandiford <richard@codesourcery.com>, 2006
+ Updated by Maciej W. Rozycki <macro@codesourcery.com>, 2008.
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
@@ -90,6 +91,7 @@
#include "prelink.h"
#include "layout.h"
+#include "reloc-info.h"
/* The thread pointer points 0x7000 past the first static TLS block. */
#define TLS_TP_OFFSET 0x7000
@@ -124,6 +126,28 @@ struct mips_local_got_iterator {
struct data_iterator got_iterator;
};
+/* Read native-endian address-type data. */
+
+static uint64_t
+mips_buf_read_addr (DSO *dso, unsigned char *data)
+{
+ if (dso->ehdr.e_ident[EI_CLASS] == ELFCLASS64)
+ return buf_read_une64 (dso, data);
+ else
+ return buf_read_une32 (dso, data);
+}
+
+/* Write native-endian address-type data. */
+
+static void
+mips_buf_write_addr (DSO *dso, unsigned char *data, uint64_t val)
+{
+ if (dso->ehdr.e_ident[EI_CLASS] == ELFCLASS64)
+ buf_write_ne64 (dso, data, val);
+ else
+ buf_write_ne32 (dso, data, val);
+}
+
/* Set up LGI to iterate over DSO's local GOT. The caller should use
mips_get_local_got_entry to read the first entry. */
@@ -131,7 +155,7 @@ static inline void
mips_init_local_got_iterator (struct mips_local_got_iterator *lgi, DSO *dso)
{
lgi->dso = dso;
- lgi->entry_size = gelf_fsize (dso->elf, ELF_T_WORD, 1, EV_CURRENT);
+ lgi->entry_size = gelf_fsize (dso->elf, ELF_T_ADDR, 1, EV_CURRENT);
lgi->got_index = RESERVED_GOTNO - 1;
lgi->failed = 0;
init_data_iterator (&lgi->got_iterator, dso,
@@ -199,7 +223,7 @@ mips_init_global_got_iterator (struct mips_global_got_iterator *ggi, DSO *dso)
GElf_Word sym_size;
ggi->dso = dso;
- ggi->entry_size = gelf_fsize (dso->elf, ELF_T_WORD, 1, EV_CURRENT);
+ ggi->entry_size = gelf_fsize (dso->elf, ELF_T_ADDR, 1, EV_CURRENT);
ggi->got_addr = (dso->info[DT_PLTGOT]
+ (dso->info_DT_MIPS_LOCAL_GOTNO - 1) * ggi->entry_size);
ggi->sym_index = dso->info_DT_MIPS_GOTSYM - 1;
@@ -252,8 +276,8 @@ mips_arch_adjust (DSO *dso, GElf_Addr start, GElf_Addr adjust)
mips_init_local_got_iterator (&lgi, dso);
while (mips_get_local_got_entry (&lgi))
{
- value = buf_read_une32 (dso, lgi.got_entry);
- buf_write_ne32 (dso, lgi.got_entry, value + adjust);
+ value = mips_buf_read_addr (dso, lgi.got_entry);
+ mips_buf_write_addr (dso, lgi.got_entry, value + adjust);
}
/* Adjust every global GOT entry. Referring to the table above:
@@ -269,13 +293,13 @@ mips_arch_adjust (DSO *dso, GElf_Addr start, GElf_Addr adjust)
mips_init_global_got_iterator (&ggi, dso);
while (mips_get_global_got_entry (&ggi))
{
- value = buf_read_une32 (dso, ggi.got_entry);
+ value = mips_buf_read_addr (dso, ggi.got_entry);
if (ggi.sym.st_shndx != SHN_COMMON
&& value >= start
&& (value == ggi.sym.st_value
? adjust_symbol_p (dso, &ggi.sym)
: ggi.sym.st_shndx != SHN_UNDEF))
- buf_write_ne32 (dso, ggi.got_entry, value + adjust);
+ mips_buf_write_addr (dso, ggi.got_entry, value + adjust);
}
return lgi.failed || ggi.failed;
@@ -325,16 +349,16 @@ mips_adjust_dyn (DSO *dso, int n, GElf_Dyn *dyn, GElf_Addr start,
address R_OFFSET. */
static inline uint32_t
-mips_read_addend (DSO *dso, GElf_Addr r_offset, GElf_Rela *rela)
+mips_read_32bit_addend (DSO *dso, GElf_Addr r_offset, GElf_Rela *rela)
{
return rela ? rela->r_addend : read_une32 (dso, r_offset);
}
-/* Like mips_read_addend, but change the addend to VALUE. */
+/* Like mips_read_32bit_addend, but change the addend to VALUE. */
static inline void
-mips_write_addend (DSO *dso, GElf_Addr r_offset, GElf_Rela *rela,
- uint32_t value)
+mips_write_32bit_addend (DSO *dso, GElf_Addr r_offset, GElf_Rela *rela,
+ uint32_t value)
{
if (rela)
rela->r_addend = (int32_t) value;
@@ -342,6 +366,26 @@ mips_write_addend (DSO *dso, GElf_Addr r_offset, GElf_Rela *rela,
write_ne32 (dso, r_offset, value);
}
+/* Like mips_read_32bit_addend, but 64-bit. */
+
+static inline uint64_t
+mips_read_64bit_addend (DSO *dso, GElf_Addr r_offset, GElf_Rela *rela)
+{
+ return rela ? rela->r_addend : read_une64 (dso, r_offset);
+}
+
+/* Like mips_read_64bit_addend, but change the addend to VALUE. */
+
+static inline void
+mips_write_64bit_addend (DSO *dso, GElf_Addr r_offset, GElf_Rela *rela,
+ uint64_t value)
+{
+ if (rela)
+ rela->r_addend = value;
+ else
+ write_ne64 (dso, r_offset, value);
+}
+
/* There is a relocation of type R_INFO against address R_OFFSET in DSO.
Adjust it so that virtual addresses >= START are increased by ADJUST
If the relocation is in a RELA section, RELA points to the relocation,
@@ -354,9 +398,9 @@ mips_adjust_reloc (DSO *dso, GElf_Addr r_offset, GElf_Xword r_info,
GElf_Addr value;
GElf_Word r_sym;
- if (GELF_R_TYPE (r_info) == R_MIPS_REL32)
+ if (reloc_r_type (dso, r_info) == R_MIPS_REL32)
{
- r_sym = GELF_R_SYM (r_info);
+ r_sym = reloc_r_sym (dso, r_info);
if (r_sym < dso->info_DT_MIPS_GOTSYM)
{
/* glibc's dynamic linker adds the symbol's st_value and the
@@ -388,8 +432,18 @@ mips_adjust_reloc (DSO *dso, GElf_Addr r_offset, GElf_Xword r_info,
" relocs against local symbols", dso->filename);
return 1;
}
- value = mips_read_addend (dso, r_offset, rela);
- mips_write_addend (dso, r_offset, rela, value + adjust);
+ if (reloc_r_type2 (dso, r_info) == R_MIPS_64)
+ {
+ assert (reloc_r_type3 (dso, r_info) == R_MIPS_NONE);
+ assert (reloc_r_ssym (dso, r_info) == RSS_UNDEF);
+ value = mips_read_64bit_addend (dso, r_offset, rela);
+ mips_write_64bit_addend (dso, r_offset, rela, value + adjust);
+ }
+ else
+ {
+ value = mips_read_32bit_addend (dso, r_offset, rela);
+ mips_write_32bit_addend (dso, r_offset, rela, value + adjust);
+ }
}
}
return 0;
@@ -418,6 +472,13 @@ mips_prelink_32bit_reloc (DSO *dso, GElf_Rela *rela, GElf_Addr value)
write_ne32 (dso, rela->r_offset, value + rela->r_addend);
}
+static void
+mips_prelink_64bit_reloc (DSO *dso, GElf_Rela *rela, GElf_Addr value)
+{
+ assert (rela != NULL);
+ write_ne64 (dso, rela->r_offset, value + rela->r_addend);
+}
+
/* There is a relocation of type R_INFO against address R_OFFSET in DSO.
Prelink the relocation field, using INFO to look up symbol values.
If the relocation is in a RELA section, RELA points to the relocation,
@@ -433,8 +494,8 @@ mips_prelink_reloc (struct prelink_info *info, GElf_Addr r_offset,
int r_type;
dso = info->dso;
- r_sym = GELF_R_SYM (r_info);
- r_type = GELF_R_TYPE (r_info);
+ r_sym = reloc_r_sym (dso, r_info);
+ r_type = reloc_r_type (dso, r_info);
switch (r_type)
{
case R_MIPS_NONE:
@@ -443,47 +504,87 @@ mips_prelink_reloc (struct prelink_info *info, GElf_Addr r_offset,
case R_MIPS_REL32:
/* An in-place R_MIPS_REL32 relocation against symbol 0 needs no
adjustment. */
- if (rela != NULL || GELF_R_SYM (r_info) != 0)
+ if (rela != NULL || r_sym != 0)
{
value = info->resolve (info, r_sym, r_type);
- mips_prelink_32bit_reloc (dso, rela, value);
+ if (reloc_r_type2 (dso, r_info) == R_MIPS_64)
+ {
+ assert (reloc_r_type3 (dso, r_info) == R_MIPS_NONE);
+ assert (reloc_r_ssym (dso, r_info) == RSS_UNDEF);
+ mips_prelink_64bit_reloc (dso, rela, value);
+ }
+ else
+ mips_prelink_32bit_reloc (dso, rela, value);
}
break;
case R_MIPS_GLOB_DAT:
+ if (reloc_r_type2 (dso, r_info) == R_MIPS_64)
+ {
+ assert (reloc_r_type3 (dso, r_info) == R_MIPS_NONE);
+ assert (reloc_r_ssym (dso, r_info) == RSS_UNDEF);
+ write_ne64 (dso, r_offset, info->resolve (info, r_sym, r_type));
+ }
+ else
+ write_ne32 (dso, r_offset, info->resolve (info, r_sym, r_type));
+ break;
+
+ case R_MIPS_JUMP_SLOT:
write_ne32 (dso, r_offset, info->resolve (info, r_sym, r_type));
break;
case R_MIPS_TLS_DTPMOD32:
+ case R_MIPS_TLS_DTPMOD64:
+ /* Relocations in a shared library will be resolved using a conflict.
+ We need not change the relocation field here. */
if (dso->ehdr.e_type == ET_EXEC)
{
- error (0, 0, "%s: R_MIPS_TLS_DTPMOD32 reloc in executable?",
- dso->filename);
- return 1;
+ struct prelink_tls *tls = info->symbols[r_sym].u.tls;
+
+ if (tls == NULL)
+ break;
+ value = tls->modid;
+ if (r_type == R_MIPS_TLS_DTPMOD32)
+ mips_prelink_32bit_reloc (dso, rela, value);
+ else
+ mips_prelink_64bit_reloc (dso, rela, value);
}
- /* These relocations will be resolved using a conflict. We need
- not change the field value here. */
break;
case R_MIPS_TLS_DTPREL32:
+ case R_MIPS_TLS_DTPREL64:
value = info->resolve (info, r_sym, r_type);
- mips_prelink_32bit_reloc (dso, rela, value - TLS_DTV_OFFSET);
+ if (r_type == R_MIPS_TLS_DTPREL32)
+ mips_prelink_32bit_reloc (dso, rela, value - TLS_DTV_OFFSET);
+ else
+ mips_prelink_64bit_reloc (dso, rela, value - TLS_DTV_OFFSET);
break;
case R_MIPS_TLS_TPREL32:
+ case R_MIPS_TLS_TPREL64:
/* Relocations in a shared library will be resolved using a conflict.
We need not change the relocation field here. */
if (dso->ehdr.e_type == ET_EXEC)
{
value = info->resolve (info, r_sym, r_type);
value += info->resolvetls->offset - TLS_TP_OFFSET;
- mips_prelink_32bit_reloc (dso, rela, value);
+ if (r_type == R_MIPS_TLS_TPREL32)
+ mips_prelink_32bit_reloc (dso, rela, value);
+ else
+ mips_prelink_64bit_reloc (dso, rela, value);
}
break;
+ case R_MIPS_COPY:
+ if (dso->ehdr.e_type == ET_EXEC)
+ /* COPY relocs are handled specially in generic code. */
+ return 0;
+ error (0, 0, "%s: R_MIPS_COPY reloc in shared library?", dso->filename);
+ return 1;
+
default:
error (0, 0, "%s: Unknown MIPS relocation type %d",
- dso->filename, (int) GELF_R_TYPE (r_info));
+ dso->filename, (int) reloc_r_type (dso, r_info));
return 1;
}
return 0;
@@ -492,20 +593,41 @@ mips_prelink_reloc (struct prelink_info *info, GElf_Addr r_offset,
static int
mips_prelink_rel (struct prelink_info *info, GElf_Rel *rel, GElf_Addr reladdr)
{
+ GElf_Xword r_info;
+ GElf_Word r_sym;
+ int r_type;
DSO *dso;
/* Convert R_MIPS_REL32 relocations against global symbols into
R_MIPS_GLOB_DAT if the addend is zero. */
dso = info->dso;
- if (GELF_R_TYPE (rel->r_info) == R_MIPS_REL32
- && GELF_R_SYM (rel->r_info) >= dso->info_DT_MIPS_GOTSYM
- && read_une32 (dso, rel->r_offset) == 0)
+ r_sym = reloc_r_sym (dso, rel->r_info);
+ r_type = reloc_r_type (dso, rel->r_info);
+ if (r_type == R_MIPS_REL32 && r_sym >= dso->info_DT_MIPS_GOTSYM)
{
- rel->r_info = GELF_R_INFO (GELF_R_SYM (rel->r_info), R_MIPS_GLOB_DAT);
- write_ne32 (dso, rel->r_offset,
- info->resolve (info, GELF_R_SYM (rel->r_info),
- GELF_R_TYPE (rel->r_info)));
- return 2;
+ r_type = R_MIPS_GLOB_DAT;
+ r_info = reloc_r_info_ext (dso, r_sym, reloc_r_ssym (dso, rel->r_info),
+ r_type,
+ reloc_r_type2 (dso, rel->r_info),
+ reloc_r_type3 (dso, rel->r_info));
+ if (reloc_r_type2 (dso, rel->r_info) == R_MIPS_64)
+ {
+ assert (reloc_r_type3 (dso, rel->r_info) == R_MIPS_NONE);
+ assert (reloc_r_ssym (dso, rel->r_info) == RSS_UNDEF);
+ if (read_une64 (dso, rel->r_offset) == 0)
+ {
+ rel->r_info = r_info;
+ write_ne64 (dso, rel->r_offset,
+ info->resolve (info, r_sym, r_type));
+ return 2;
+ }
+ }
+ else if (read_une32 (dso, rel->r_offset) == 0)
+ {
+ rel->r_info = r_info;
+ write_ne32 (dso, rel->r_offset, info->resolve (info, r_sym, r_type));
+ return 2;
+ }
}
return mips_prelink_reloc (info, rel->r_offset, rel->r_info, NULL);
}
@@ -552,18 +674,23 @@ mips_prelink_conflict_reloc (DSO *dso, struct prelink_info *info,
struct prelink_conflict *conflict;
struct prelink_tls *tls = NULL;
GElf_Rela *entry;
+ GElf_Word r_sym;
+ int r_type;
if (info->dso == dso)
return 0;
- conflict = prelink_conflict (info, GELF_R_SYM (r_info),
- GELF_R_TYPE (r_info));
+ r_sym = reloc_r_sym (dso, r_info);
+ r_type = reloc_r_type (dso, r_info);
+ conflict = prelink_conflict (info, r_sym, r_type);
if (conflict == NULL)
{
- switch (GELF_R_TYPE (r_info))
+ switch (r_type)
{
case R_MIPS_TLS_DTPMOD32:
+ case R_MIPS_TLS_DTPMOD64:
case R_MIPS_TLS_TPREL32:
+ case R_MIPS_TLS_TPREL64:
tls = info->curtls;
if (tls == NULL)
return 0;
@@ -584,10 +711,11 @@ mips_prelink_conflict_reloc (DSO *dso, struct prelink_info *info,
}
else
{
- /* DTPREL32 relocations just involve the symbol value; no other
- TLS information is needed. Ignore conflicts created from a
- lookup of type RTYPE_CLASS_TLS if no real conflict exists. */
- if (GELF_R_TYPE (r_info) == R_MIPS_TLS_DTPREL32
+ /* DTPREL32/DTPREL64 relocations just involve the symbol value;
+ no other TLS information is needed. Ignore conflicts created
+ from a lookup of type RTYPE_CLASS_TLS if no real conflict
+ exists. */
+ if ((r_type == R_MIPS_TLS_DTPREL32 || r_type == R_MIPS_TLS_DTPREL64)
&& conflict->lookup.tls == conflict->conflict.tls
&& conflict->lookupval == conflict->conflictval)
return 0;
@@ -596,44 +724,67 @@ mips_prelink_conflict_reloc (DSO *dso, struct prelink_info *info,
}
/* VALUE now contains the final symbol value. Change it to the
value we want to store at R_OFFSET. */
- switch (GELF_R_TYPE (r_info))
+ switch (r_type)
{
case R_MIPS_REL32:
- value += mips_read_addend (dso, r_offset, rela);
+ if (reloc_r_type2 (dso, r_info) == R_MIPS_64)
+ {
+ assert (reloc_r_type3 (dso, r_info) == R_MIPS_NONE);
+ assert (reloc_r_ssym (dso, r_info) == RSS_UNDEF);
+ value += mips_read_64bit_addend (dso, r_offset, rela);
+ }
+ else
+ value += mips_read_32bit_addend (dso, r_offset, rela);
break;
case R_MIPS_GLOB_DAT:
break;
+ case R_MIPS_COPY:
+ error (0, 0, "R_MIPS_COPY should not be present in shared libraries");
+ return 1;
+
case R_MIPS_TLS_DTPMOD32:
+ case R_MIPS_TLS_DTPMOD64:
if (conflict != NULL && mips_get_tls (dso, conflict, &tls) == 1)
return 1;
value = tls->modid;
break;
case R_MIPS_TLS_DTPREL32:
- value += mips_read_addend (dso, r_offset, rela) - TLS_DTV_OFFSET;
+ value += mips_read_32bit_addend (dso, r_offset, rela) - TLS_DTV_OFFSET;
+ break;
+ case R_MIPS_TLS_DTPREL64:
+ value += mips_read_64bit_addend (dso, r_offset, rela) - TLS_DTV_OFFSET;
break;
case R_MIPS_TLS_TPREL32:
+ case R_MIPS_TLS_TPREL64:
if (conflict != NULL && mips_get_tls (dso, conflict, &tls) == 1)
return 1;
- value += (mips_read_addend (dso, r_offset, rela)
- + tls->offset - TLS_TP_OFFSET);
+ if (r_type == R_MIPS_TLS_TPREL32)
+ value += mips_read_32bit_addend (dso, r_offset, rela);
+ else
+ value += mips_read_64bit_addend (dso, r_offset, rela);
+ value += tls->offset - TLS_TP_OFFSET;
break;
default:
error (0, 0, "%s: Unknown MIPS relocation type %d", dso->filename,
- (int) GELF_R_TYPE (r_info));
+ r_type);
return 1;
}
/* Create and initialize a conflict entry. */
entry = prelink_conflict_add_rela (info);
if (entry == NULL)
return 1;
- entry->r_addend = (int32_t) value;
entry->r_offset = r_offset;
- entry->r_info = GELF_R_INFO (0, R_MIPS_REL32);
+ entry->r_info = reloc_r_info_ext (dso, 0, RSS_UNDEF,
+ R_MIPS_REL32, R_MIPS_64, R_MIPS_NONE);
+ if (reloc_r_type2 (dso, entry->r_info) == R_MIPS_64)
+ entry->r_addend = value;
+ else
+ entry->r_addend = (int32_t) value;
return 0;
}
@@ -678,14 +829,19 @@ mips_arch_prelink_conflict (DSO *dso, struct prelink_info *info)
value = ggi.sym.st_value;
else
continue;
- if (buf_read_une32 (dso, ggi.got_entry) != value)
+ if (mips_buf_read_addr (dso, ggi.got_entry) != value)
{
entry = prelink_conflict_add_rela (info);
if (entry == NULL)
return 1;
- entry->r_addend = (int32_t) value;
entry->r_offset = ggi.got_addr;
- entry->r_info = GELF_R_INFO (0, R_MIPS_REL32);
+ entry->r_info = reloc_r_info_ext (dso, 0, RSS_UNDEF,
+ R_MIPS_REL32, R_MIPS_64,
+ R_MIPS_NONE);
+ if (reloc_r_type2 (dso, entry->r_info) == R_MIPS_64)
+ entry->r_addend = value;
+ else
+ entry->r_addend = (int32_t) value;
}
}
@@ -696,9 +852,23 @@ static int
mips_apply_conflict_rela (struct prelink_info *info, GElf_Rela *rela,
char *buf, GElf_Addr dest_addr)
{
- switch (GELF_R_TYPE (rela->r_info))
+ DSO *dso;
+
+ dso = info->dso;
+ switch (reloc_r_type (dso, rela->r_info))
{
case R_MIPS_REL32:
+ if (reloc_r_type2 (dso, rela->r_info) == R_MIPS_64)
+ {
+ assert (reloc_r_ssym (dso, rela->r_info) == RSS_UNDEF);
+ assert (reloc_r_type3 (dso, rela->r_info) == R_MIPS_NONE);
+ buf_write_ne64 (info->dso, buf, rela->r_addend);
+ }
+ else
+ buf_write_ne32 (info->dso, buf, rela->r_addend);
+ break;
+
+ case R_MIPS_JUMP_SLOT:
buf_write_ne32 (info->dso, buf, rela->r_addend);
break;
@@ -720,26 +890,42 @@ mips_apply_adjustment (DSO *dso, GElf_Rela *rela, char *buf,
if (rela)
adjustment += rela->r_addend;
else
- adjustment += buf_read_une32 (dso, buf);
- buf_write_ne32 (dso, buf, adjustment);
+ adjustment += mips_buf_read_addr (dso, buf);
+ mips_buf_write_addr (dso, buf, adjustment);
}
static int
mips_apply_reloc (struct prelink_info *info, GElf_Xword r_info,
GElf_Rela *rela, char *buf)
{
+ GElf_Addr value;
+ GElf_Word r_sym;
+ int r_type;
DSO *dso;
dso = info->dso;
- switch (GELF_R_TYPE (r_info))
+ r_sym = reloc_r_sym (dso, r_info);
+ r_type = reloc_r_type (dso, r_info);
+ value = info->resolve (info, r_sym, r_type);
+ switch (r_type)
{
case R_MIPS_NONE:
break;
+ case R_MIPS_JUMP_SLOT:
+ buf_write_ne32 (info->dso, buf, value);
+ break;
+
+ case R_MIPS_COPY:
+ abort ();
+
case R_MIPS_REL32:
- mips_apply_adjustment (dso, rela, buf,
- info->resolve (info, GELF_R_SYM (r_info),
- GELF_R_TYPE (r_info)));
+ if (reloc_r_type2 (dso, r_info) == R_MIPS_64)
+ {
+ assert (reloc_r_type3 (dso, r_info) == R_MIPS_NONE);
+ assert (reloc_r_ssym (dso, r_info) == RSS_UNDEF);
+ }
+ mips_apply_adjustment (dso, rela, buf, value);
break;
default:
@@ -763,27 +949,50 @@ mips_apply_rela (struct prelink_info *info, GElf_Rela *rela, char *buf)
static int
mips_rel_to_rela (DSO *dso, GElf_Rel *rel, GElf_Rela *rela)
{
+ GElf_Word r_sym;
+ int r_type;
+
+ r_sym = reloc_r_sym (dso, rel->r_info);
+ r_type = reloc_r_type (dso, rel->r_info);
rela->r_offset = rel->r_offset;
rela->r_info = rel->r_info;
- switch (GELF_R_TYPE (rel->r_info))
+ switch (r_type)
{
case R_MIPS_REL32:
+ /* This relocation has an in-place addend. */
+ if (reloc_r_type2 (dso, rel->r_info) == R_MIPS_64)
+ {
+ assert (reloc_r_type3 (dso, rel->r_info) == R_MIPS_NONE);
+ assert (reloc_r_ssym (dso, rel->r_info) == RSS_UNDEF);
+ rela->r_addend = read_une64 (dso, rel->r_offset);
+ }
+ else
+ rela->r_addend = (int32_t) read_une32 (dso, rel->r_offset);
+ break;
+
case R_MIPS_TLS_DTPREL32:
case R_MIPS_TLS_TPREL32:
/* These relocations have an in-place addend. */
rela->r_addend = (int32_t) read_une32 (dso, rel->r_offset);
break;
+ case R_MIPS_TLS_DTPREL64:
+ case R_MIPS_TLS_TPREL64:
+ /* These relocations have an in-place addend. */
+ rela->r_addend = read_une64 (dso, rel->r_offset);
+ break;
case R_MIPS_NONE:
+ case R_MIPS_COPY:
case R_MIPS_GLOB_DAT:
case R_MIPS_TLS_DTPMOD32:
+ case R_MIPS_TLS_DTPMOD64:
/* These relocations have no addend. */
rela->r_addend = 0;
break;
default:
error (0, 0, "%s: Unknown MIPS relocation type %d", dso->filename,
- (int) GELF_R_TYPE (rel->r_info));
+ r_type);
return 1;
}
return 0;
@@ -792,29 +1001,60 @@ mips_rel_to_rela (DSO *dso, GElf_Rel *rel, GElf_Rela *rela)
static int
mips_rela_to_rel (DSO *dso, GElf_Rela *rela, GElf_Rel *rel)
{
+ GElf_Sxword r_addend;
+ GElf_Word r_sym;
+ int r_type;
+
+ r_sym = reloc_r_sym (dso, rela->r_info);
+ r_type = reloc_r_type (dso, rela->r_info);
+ r_addend = rela->r_addend;
rel->r_offset = rela->r_offset;
rel->r_info = rela->r_info;
- switch (GELF_R_TYPE (rela->r_info))
+ switch (r_type)
{
case R_MIPS_NONE:
+ case R_MIPS_COPY:
break;
+ case R_MIPS_GLOB_DAT:
+ /* This relocation has no addend. */
+ r_addend = 0;
+ /* FALLTHROUGH */
case R_MIPS_REL32:
+ /* This relocation has an in-place addend. */
+ if (reloc_r_type2 (dso, rel->r_info) == R_MIPS_64)
+ {
+ assert (reloc_r_type3 (dso, rel->r_info) == R_MIPS_NONE);
+ assert (reloc_r_ssym (dso, rel->r_info) == RSS_UNDEF);
+ write_ne64 (dso, rela->r_offset, rela->r_addend);
+ }
+ else
+ write_ne32 (dso, rela->r_offset, rela->r_addend);
+ break;
+
+ case R_MIPS_TLS_DTPMOD32:
+ /* This relocation has no addend. */
+ r_addend = 0;
+ /* FALLTHROUGH */
case R_MIPS_TLS_DTPREL32:
case R_MIPS_TLS_TPREL32:
/* These relocations have an in-place addend. */
write_ne32 (dso, rela->r_offset, rela->r_addend);
break;
-
- case R_MIPS_GLOB_DAT:
- case R_MIPS_TLS_DTPMOD32:
- /* These relocations have no addend. */
- write_ne32 (dso, rela->r_offset, 0);
+ case R_MIPS_TLS_DTPMOD64:
+ /* This relocation has no addend. */
+ r_addend = 0;
+ /* FALLTHROUGH */
+ case R_MIPS_TLS_DTPREL64:
+ case R_MIPS_TLS_TPREL64:
+ /* These relocations have an in-place addend. */
+ write_ne64 (dso, rela->r_offset, rela->r_addend);
+ break;
break;
default:
error (0, 0, "%s: Unknown MIPS relocation type %d", dso->filename,
- (int) GELF_R_TYPE (rela->r_info));
+ r_type);
return 1;
}
return 0;
@@ -825,64 +1065,91 @@ mips_need_rel_to_rela (DSO *dso, int first, int last)
{
Elf_Data *data;
Elf_Scn *scn;
- Elf32_Rel *rel, *relend;
+ GElf_Shdr shdr;
+ GElf_Rel rel;
+ GElf_Word r_sym;
+ int r_type;
+ int count;
+ int i;
int n;
for (n = first; n <= last; n++)
{
data = NULL;
scn = dso->scn[n];
+ gelfx_getshdr (dso->elf, scn, &shdr);
while ((data = elf_getdata (scn, data)) != NULL)
{
- rel = (Elf32_Rel *) data->d_buf;
- relend = rel + data->d_size / sizeof (Elf32_Rel);
- for (; rel < relend; rel++)
- switch (ELF32_R_TYPE (rel->r_info))
- {
- case R_MIPS_NONE:
- break;
-
- case R_MIPS_REL32:
- /* The SVR4 definition was designed to allow exactly the
- sort of prelinking we want to do here, in combination
- with Quickstart. Unfortunately, glibc's definition
- makes it impossible for relocations against anything
- other than the null symbol. We get around this for
- zero addends by using a R_MIPS_GLOB_DAT relocation
- instead, where R_MIPS_GLOB_DAT is a GNU extension
- added specifically for this purpose. */
- if (ELF32_R_SYM (rel->r_info) != 0
- && (ELF32_R_SYM (rel->r_info) < dso->info_DT_MIPS_GOTSYM
- || read_une32 (dso, rel->r_offset) != 0))
+ count = data->d_size / shdr.sh_entsize;
+ for (i = 0; i < count; i++)
+ {
+ gelfx_getrel (dso->elf, data, i, &rel);
+ r_type = reloc_r_type (dso, rel.r_info);
+ r_sym = reloc_r_sym (dso, rel.r_info);
+ switch (r_type)
+ {
+ case R_MIPS_NONE:
+ case R_MIPS_COPY:
+ case R_MIPS_JUMP_SLOT:
+ break;
+
+ case R_MIPS_REL32:
+ /* The SVR4 definition was designed to allow exactly the
+ sort of prelinking we want to do here, in combination
+ with Quickstart. Unfortunately, glibc's definition
+ makes it impossible for relocations against anything
+ other than the null symbol. We get around this for
+ zero addends by using a R_MIPS_GLOB_DAT relocation
+ instead, where R_MIPS_GLOB_DAT is a GNU extension
+ added specifically for this purpose. */
+ if (r_sym != 0)
+ {
+ if (r_sym < dso->info_DT_MIPS_GOTSYM)
+ return 1;
+ if (reloc_r_type2 (dso, rel.r_info) == R_MIPS_64)
+ {
+ assert (reloc_r_type3 (dso, rel.r_info)
+ == R_MIPS_NONE);
+ assert (reloc_r_ssym (dso, rel.r_info)
+ == RSS_UNDEF);
+ if (read_une64 (dso, rel.r_offset) != 0)
+ return 1;
+ }
+ else if (read_une32 (dso, rel.r_offset) != 0)
+ return 1;
+ }
+ break;
+
+ case R_MIPS_GLOB_DAT:
+ /* This relocation has no addend. */
+ break;
+
+ case R_MIPS_TLS_DTPMOD32:
+ case R_MIPS_TLS_DTPMOD64:
+ /* The relocation will be resolved using a conflict. */
+ break;
+
+ case R_MIPS_TLS_DTPREL32:
+ case R_MIPS_TLS_DTPREL64:
+ /* We can prelink these fields, and the addend is relative
+ to the symbol value. A RELA entry is needed. */
return 1;
- break;
-
- case R_MIPS_GLOB_DAT:
- /* This relocation has no addend. */
- break;
-
- case R_MIPS_TLS_DTPMOD32:
- /* The relocation will be resolved using a conflict. */
- break;
-
- case R_MIPS_TLS_DTPREL32:
- /* We can prelink these fields, and the addend is relative
- to the symbol value. A RELA entry is needed. */
- return 1;
-
- case R_MIPS_TLS_TPREL32:
- /* Relocations in shared libraries will be resolved by a
- conflict. Relocations in executables will not, and the
- addend is relative to the symbol value. */
- if (dso->ehdr.e_type == ET_EXEC)
+
+ case R_MIPS_TLS_TPREL32:
+ case R_MIPS_TLS_TPREL64:
+ /* Relocations in shared libraries will be resolved by a
+ conflict. Relocations in executables will not, and the
+ addend is relative to the symbol value. */
+ if (dso->ehdr.e_type == ET_EXEC)
+ return 1;
+ break;
+
+ default:
+ error (0, 0, "%s: Unknown MIPS relocation type %d",
+ dso->filename, r_type);
return 1;
- break;
-
- default:
- error (0, 0, "%s: Unknown MIPS relocation type %d",
- dso->filename, (int) GELF_R_TYPE (rel->r_info));
- return 1;
- }
+ }
+ }
}
}
return 0;
@@ -899,14 +1166,19 @@ mips_reloc_class (int reloc_type)
{
switch (reloc_type)
{
+ case R_MIPS_COPY:
+ return RTYPE_CLASS_COPY;
+ case R_MIPS_JUMP_SLOT:
+ return RTYPE_CLASS_PLT;
case R_MIPS_TLS_DTPMOD32:
+ case R_MIPS_TLS_DTPMOD64:
case R_MIPS_TLS_DTPREL32:
+ case R_MIPS_TLS_DTPREL64:
case R_MIPS_TLS_TPREL32:
+ case R_MIPS_TLS_TPREL64:
return RTYPE_CLASS_TLS;
default:
- /* MIPS lazy resolution stubs are local to the containing object,
- so SHN_UNDEF symbols never participate in symbol lookup. */
- return RTYPE_CLASS_PLT;
+ return RTYPE_CLASS_VALID;
}
}
@@ -916,8 +1188,33 @@ mips_arch_prelink (struct prelink_info *info)
struct mips_global_got_iterator ggi;
DSO *dso;
GElf_Addr value;
+ int i;
dso = info->dso;
+
+ if (dso->info_DT_MIPS_PLTGOT)
+ {
+ /* Write address of .plt into gotplt[1]. This is in each
+ normal gotplt entry unless prelinking. */
+ int sec = addr_to_sec (dso, dso->info_DT_MIPS_PLTGOT);
+ Elf32_Addr data;
+
+ if (sec == -1)
+ return 1;
+
+ for (i = 1; i < dso->ehdr.e_shnum; i++)
+ if (dso->shdr[i].sh_type == SHT_PROGBITS
+ && ! strcmp (strptr (dso, dso->ehdr.e_shstrndx,
+ dso->shdr[i].sh_name),
+ ".plt"))
+ break;
+
+ if (i == dso->ehdr.e_shnum)
+ return 0;
+ data = dso->shdr[i].sh_addr;
+ write_ne32 (dso, dso->info_DT_MIPS_PLTGOT + 4, data);
+ }
+
if (dso->info[DT_PLTGOT] == 0)
return 0;
@@ -929,7 +1226,7 @@ mips_arch_prelink (struct prelink_info *info)
value = info->resolve (info, ggi.sym_index, R_MIPS_REL32);
if (ggi.sym.st_shndx == SHN_UNDEF
|| ggi.sym.st_shndx == SHN_COMMON)
- buf_write_ne32 (dso, ggi.got_entry, value);
+ mips_buf_write_addr (dso, ggi.got_entry, value);
else
{
/* Type E and F in the table above. We cannot install Quickstart
@@ -947,7 +1244,7 @@ mips_arch_prelink (struct prelink_info *info)
code will cope correctly with malformed type F entries in
shared libraries, so we only complain about executables here. */
if (dso->ehdr.e_type == ET_EXEC
- && value != buf_read_une32 (dso, ggi.got_entry))
+ && value != mips_buf_read_addr (dso, ggi.got_entry))
{
error (0, 0, "%s: The global GOT entries for defined symbols"
" do not match their st_values\n", dso->filename);
@@ -962,6 +1259,30 @@ static int
mips_arch_undo_prelink (DSO *dso)
{
struct mips_global_got_iterator ggi;
+ int i;
+
+ if (dso->info_DT_MIPS_PLTGOT)
+ {
+ /* Clear gotplt[1] if it contains the address of .plt. */
+ int sec = addr_to_sec (dso, dso->info_DT_MIPS_PLTGOT);
+ Elf32_Addr data;
+
+ if (sec == -1)
+ return 1;
+
+ for (i = 1; i < dso->ehdr.e_shnum; i++)
+ if (dso->shdr[i].sh_type == SHT_PROGBITS
+ && ! strcmp (strptr (dso, dso->ehdr.e_shstrndx,
+ dso->shdr[i].sh_name),
+ ".plt"))
+ break;
+
+ if (i == dso->ehdr.e_shnum)
+ return 0;
+ data = read_une32 (dso, dso->info_DT_MIPS_PLTGOT + 4);
+ if (data == dso->shdr[i].sh_addr)
+ write_ne32 (dso, dso->info_DT_MIPS_PLTGOT + 4, 0);
+ }
if (dso->info[DT_PLTGOT] == 0)
return 0;
@@ -970,41 +1291,79 @@ mips_arch_undo_prelink (DSO *dso)
while (mips_get_global_got_entry (&ggi))
if (ggi.sym.st_shndx == SHN_UNDEF)
/* Types A-C in the table above. */
- buf_write_ne32 (dso, ggi.got_entry, ggi.sym.st_value);
+ mips_buf_write_addr (dso, ggi.got_entry, ggi.sym.st_value);
else if (ggi.sym.st_shndx == SHN_COMMON)
/* Type D in the table above. */
- buf_write_ne32 (dso, ggi.got_entry, 0);
+ mips_buf_write_addr (dso, ggi.got_entry, 0);
return ggi.failed;
}
static int
mips_undo_prelink_rel (DSO *dso, GElf_Rel *rel, GElf_Addr reladdr)
{
+ int sec;
+ const char *name;
+ GElf_Word r_sym;
+ int r_type;
+
/* Convert R_MIPS_GLOB_DAT relocations back into R_MIPS_REL32
relocations. Ideally we'd have some mechanism for recording
these changes in the undo section, but in the absence of that,
it's better to assume that the original relocation was
R_MIPS_REL32; R_MIPS_GLOB_DAT was added specifically for the
prelinker and shouldn't be used in non-prelinked binaries. */
- if (GELF_R_TYPE (rel->r_info) == R_MIPS_GLOB_DAT)
+ r_sym = reloc_r_sym (dso, rel->r_info);
+ r_type = reloc_r_type (dso, rel->r_info);
+ if (r_type == R_MIPS_GLOB_DAT)
{
- write_ne32 (dso, rel->r_offset, 0);
- rel->r_info = GELF_R_INFO (GELF_R_SYM (rel->r_info), R_MIPS_REL32);
+ if (reloc_r_type2 (dso, rel->r_info) == R_MIPS_64)
+ {
+ assert (reloc_r_type3 (dso, rel->r_info) == R_MIPS_NONE);
+ assert (reloc_r_ssym (dso, rel->r_info) == RSS_UNDEF);
+ write_ne64 (dso, rel->r_offset, 0);
+ }
+ else
+ write_ne32 (dso, rel->r_offset, 0);
+ rel->r_info = reloc_r_info_ext (dso,
+ r_sym, reloc_r_ssym (dso, rel->r_info),
+ R_MIPS_REL32,
+ reloc_r_type2 (dso, rel->r_info),
+ reloc_r_type3 (dso, rel->r_info));
return 2;
}
+ else if (r_type == R_MIPS_JUMP_SLOT)
+ {
+ sec = addr_to_sec (dso, rel->r_offset);
+ name = strptr (dso, dso->ehdr.e_shstrndx, dso->shdr[sec].sh_name);
+ if (sec == -1 || strcmp (name, ".got.plt"))
+ {
+ error (0, 0,
+ "%s: R_MIPS_JUMP_SLOT not pointing into .got.plt section",
+ dso->filename);
+ return 1;
+ }
+ else
+ {
+ Elf32_Addr data = read_une32 (dso, dso->shdr[sec].sh_addr + 4);
+
+ assert (rel->r_offset >= dso->shdr[sec].sh_addr + 8);
+ assert (((rel->r_offset - dso->shdr[sec].sh_addr) & 3) == 0);
+ write_ne32 (dso, rel->r_offset, data);
+ }
+ }
+
return 0;
}
-PL_ARCH = {
+PL_ARCH(mips) = {
.name = "MIPS",
.class = ELFCLASS32,
.machine = EM_MIPS,
.max_reloc_size = 4,
.dynamic_linker = "/lib/ld.so.1",
- /* MIPS does not use COPY relocs or jump slots. Pick a value outside
- the ELF32_R_TYPE range. */
- .R_COPY = ~0U,
- .R_JMP_SLOT = ~0U,
+ .dynamic_linker_alt = "/lib32/ld.so.1",
+ .R_COPY = R_MIPS_COPY,
+ .R_JMP_SLOT = R_MIPS_JUMP_SLOT,
/* R_MIPS_REL32 relocations against symbol 0 do act as relative relocs,
but those against other symbols don't. */
.R_RELATIVE = ~0U,
@@ -1039,3 +1398,46 @@ PL_ARCH = {
.max_page_size = 0x10000,
.page_size = 0x1000
};
+
+PL_ARCH(mips64) = {
+ .name = "MIPS64",
+ .class = ELFCLASS64,
+ .machine = EM_MIPS,
+ .max_reloc_size = 8,
+ .dynamic_linker = "/lib/ld.so.1",
+ .dynamic_linker_alt = "/lib64/ld.so.1",
+ .R_COPY = R_MIPS_COPY,
+ .R_JMP_SLOT = R_MIPS_JUMP_SLOT,
+ /* R_MIPS_REL32 relocations against symbol 0 do act as relative relocs,
+ but those against other symbols don't. */
+ .R_RELATIVE = ~0U,
+ .arch_adjust = mips_arch_adjust,
+ .adjust_dyn = mips_adjust_dyn,
+ .adjust_rel = mips_adjust_rel,
+ .adjust_rela = mips_adjust_rela,
+ .prelink_rel = mips_prelink_rel,
+ .prelink_rela = mips_prelink_rela,
+ .prelink_conflict_rel = mips_prelink_conflict_rel,
+ .prelink_conflict_rela = mips_prelink_conflict_rela,
+ .arch_prelink_conflict = mips_arch_prelink_conflict,
+ .apply_conflict_rela = mips_apply_conflict_rela,
+ .apply_rel = mips_apply_rel,
+ .apply_rela = mips_apply_rela,
+ .rel_to_rela = mips_rel_to_rela,
+ .rela_to_rel = mips_rela_to_rel,
+ .need_rel_to_rela = mips_need_rel_to_rela,
+ .reloc_size = mips_reloc_size,
+ .reloc_class = mips_reloc_class,
+ .arch_prelink = mips_arch_prelink,
+ .arch_undo_prelink = mips_arch_undo_prelink,
+ .undo_prelink_rel = mips_undo_prelink_rel,
+ /* Although TASK_UNMAPPED_BASE is 0x5555556000, we leave some
+ area so that mmap of /etc/ld.so.cache and ld.so's malloc
+ does not take some library's VA slot.
+ Also, if this guard area isn't too small, typically
+ even dlopened libraries will get the slots they desire. */
+ .mmap_base = 0x5800000000LL,
+ .mmap_end = 0x9800000000LL,
+ .max_page_size = 0x10000,
+ .page_size = 0x1000
+};
diff --git a/trunk/src/arch-ppc.c b/trunk/src/arch-ppc.c
index b209c7a..ad3961e 100644
--- a/trunk/src/arch-ppc.c
+++ b/trunk/src/arch-ppc.c
@@ -1147,7 +1147,7 @@ ppc_layout_libs_post (struct layout_libs *l)
return 0;
}
-PL_ARCH = {
+PL_ARCH(ppc) = {
.name = "PowerPC",
.class = ELFCLASS32,
.machine = EM_PPC,
diff --git a/trunk/src/arch-ppc64.c b/trunk/src/arch-ppc64.c
index 351fab1..a764b99 100644
--- a/trunk/src/arch-ppc64.c
+++ b/trunk/src/arch-ppc64.c
@@ -859,7 +859,7 @@ ppc64_free_opd (struct prelink_entry *ent)
return 0;
}
-PL_ARCH = {
+PL_ARCH(ppc64) = {
.name = "PowerPC",
.class = ELFCLASS64,
.machine = EM_PPC64,
diff --git a/trunk/src/arch-s390.c b/trunk/src/arch-s390.c
index 829392e..fd076b1 100644
--- a/trunk/src/arch-s390.c
+++ b/trunk/src/arch-s390.c
@@ -567,7 +567,7 @@ s390_reloc_class (int reloc_type)
}
}
-PL_ARCH = {
+PL_ARCH(s390) = {
.name = "S390",
.class = ELFCLASS32,
.machine = EM_S390,
diff --git a/trunk/src/arch-s390x.c b/trunk/src/arch-s390x.c
index a0321ef..8676fff 100644
--- a/trunk/src/arch-s390x.c
+++ b/trunk/src/arch-s390x.c
@@ -597,7 +597,7 @@ s390x_reloc_class (int reloc_type)
}
}
-PL_ARCH = {
+PL_ARCH(s390x) = {
.name = "S390",
.class = ELFCLASS64,
.machine = EM_S390,
diff --git a/trunk/src/arch-sh.c b/trunk/src/arch-sh.c
index 095ed58..1b11312 100644
--- a/trunk/src/arch-sh.c
+++ b/trunk/src/arch-sh.c
@@ -355,7 +355,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);
@@ -413,7 +413,7 @@ sh_reloc_class (int reloc_type)
}
}
-PL_ARCH = {
+PL_ARCH(sh) = {
.name = "SuperH",
.class = ELFCLASS32,
.machine = EM_SH,
@@ -448,6 +448,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/arch-sparc.c b/trunk/src/arch-sparc.c
index 7a3c8db..e016a79 100644
--- a/trunk/src/arch-sparc.c
+++ b/trunk/src/arch-sparc.c
@@ -606,7 +606,7 @@ sparc_reloc_class (int reloc_type)
}
}
-PL_ARCH = {
+PL_ARCH(sparc) = {
.name = "SPARC",
.class = ELFCLASS32,
.machine = EM_SPARC,
diff --git a/trunk/src/arch-sparc64.c b/trunk/src/arch-sparc64.c
index 63e107f..aee4601 100644
--- a/trunk/src/arch-sparc64.c
+++ b/trunk/src/arch-sparc64.c
@@ -806,7 +806,7 @@ sparc64_reloc_class (int reloc_type)
}
}
-PL_ARCH = {
+PL_ARCH(sparc64) = {
.name = "SPARC",
.class = ELFCLASS64,
.machine = EM_SPARCV9,
diff --git a/trunk/src/arch-x86_64.c b/trunk/src/arch-x86_64.c
index 3c760ed..3830f84 100644
--- a/trunk/src/arch-x86_64.c
+++ b/trunk/src/arch-x86_64.c
@@ -523,7 +523,7 @@ x86_64_reloc_class (int reloc_type)
}
}
-PL_ARCH = {
+PL_ARCH(x86_64) = {
.name = "x86-64",
.class = ELFCLASS64,
.machine = EM_X86_64,
diff --git a/trunk/src/cache.c b/trunk/src/cache.c
index b677e22..4c6bffd 100644
--- a/trunk/src/cache.c
+++ b/trunk/src/cache.c
@@ -113,7 +113,7 @@ 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)
+ if (canon_filename == NULL && wrap_stat64 (filename, &st) < 0)
{
error (0, errno, "Could not stat %s", filename);
if (insert)
@@ -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");
@@ -682,11 +682,12 @@ prelink_save_cache (int do_warn)
if (write (fd, &cache, sizeof (cache)) != sizeof (cache)
|| write (fd, data, len) != len
|| fchmod (fd, 0644)
+ || fsync (fd)
|| 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/canonicalize.c b/trunk/src/canonicalize.c
index 79df44e..717e991 100644
--- a/trunk/src/canonicalize.c
+++ b/trunk/src/canonicalize.c
@@ -28,6 +28,7 @@
#include <stddef.h>
#include "hashtab.h"
+#include "prelink.h"
htab_t prelink_dirname_htab;
@@ -72,14 +73,17 @@ dirname_eq (const void *p, const void *q)
separators ('/') or symlinks. All path components must exist.
The result is malloc'd. */
-static char *
-canon_filename (const char *name, int nested, struct stat64 *stp)
+char *
+canon_filename (const char *name, int nested, struct stat64 *stp,
+ const char *chroot, int allow_last_link,
+ int allow_missing)
{
- char *rpath, *dest, *extra_buf = NULL;
+ char *rpath, *dest, *extra_buf = NULL, *rpath_root;
const char *start, *end, *rpath_limit;
long int path_max;
int num_links = 0;
int stp_initialized = 0;
+ int chroot_len;
if (name == NULL)
{
@@ -92,6 +96,9 @@ canon_filename (const char *name, int nested, struct stat64 *stp)
errno = ENOENT;
return NULL;
}
+ chroot_len = strlen (chroot);
+ if (chroot_len > 0 && chroot[chroot_len - 1] == '/')
+ chroot_len--;
#ifdef PATH_MAX
path_max = PATH_MAX;
@@ -101,7 +108,7 @@ canon_filename (const char *name, int nested, struct stat64 *stp)
path_max = 1024;
#endif
- rpath = malloc (path_max);
+ rpath = malloc (path_max + chroot_len + 1);
if (rpath == NULL)
return NULL;
rpath_limit = rpath + path_max;
@@ -113,12 +120,32 @@ canon_filename (const char *name, int nested, struct stat64 *stp)
rpath[0] = '\0';
goto error;
}
- dest = strchr (rpath, '\0');
+ if (chroot_len > 0)
+ {
+ struct stat64 st;
+ char *cwd = canon_filename (rpath, 1, &st, chroot, 0, 0);
+ if (cwd == NULL)
+ goto error;
+ if (memcmp (cwd, chroot, chroot_len) != 0)
+ goto error;
+ strcpy (rpath, cwd);
+ free (cwd);
+ rpath_root = rpath + chroot_len;
+ }
+ else
+ rpath_root = rpath;
+
+ dest = strchr (rpath_root, '\0');
}
else
{
- rpath[0] = '/';
- dest = rpath + 1;
+ if (chroot_len > 0)
+ rpath_root = (char *) mempcpy (rpath, chroot, chroot_len);
+ else
+ rpath_root = rpath;
+
+ rpath_root[0] = '/';
+ dest = rpath_root + 1;
if (!nested)
{
@@ -151,7 +178,8 @@ canon_filename (const char *name, int nested, struct stat64 *stp)
ep->dirname_len = e.dirname_len;
memcpy (dirname, name, ep->dirname_len);
dirname[ep->dirname_len] = '\0';
- ep->canon_dirname = canon_filename (ep->dirname, 1, &st);
+ ep->canon_dirname = canon_filename (ep->dirname, 1, &st,
+ chroot, 0, 0);
if (ep->canon_dirname == NULL || !S_ISDIR (st.st_mode))
free (ep);
else
@@ -168,10 +196,11 @@ canon_filename (const char *name, int nested, struct stat64 *stp)
if (rpath + ep->canon_dirname_len + 1 >= rpath_limit)
{
- size_t new_size;
+ size_t new_size, root_size;
char *new_rpath;
new_size = rpath_limit - rpath;
+ root_size = rpath_root - rpath;
if (ep->canon_dirname_len + 1 > path_max)
new_size += ep->canon_dirname_len + 1;
else
@@ -181,6 +210,7 @@ canon_filename (const char *name, int nested, struct stat64 *stp)
goto error;
rpath = new_rpath;
rpath_limit = rpath + new_size;
+ rpath_root = rpath + root_size;
}
dest = mempcpy (rpath, ep->canon_dirname, ep->canon_dirname_len);
*dest = '\0';
@@ -208,7 +238,7 @@ canon_filename (const char *name, int nested, struct stat64 *stp)
else if (end - start == 2 && start[0] == '.' && start[1] == '.')
{
/* Back up to previous component, ignore if at root already. */
- if (dest > rpath + 1)
+ if (dest > rpath_root + 1)
while ((--dest)[-1] != '/');
stp_initialized = 0;
}
@@ -222,6 +252,7 @@ canon_filename (const char *name, int nested, struct stat64 *stp)
if (dest + (end - start) >= rpath_limit)
{
ptrdiff_t dest_offset = dest - rpath;
+ size_t root_size = rpath_root - rpath;
char *new_rpath;
new_size = rpath_limit - rpath;
@@ -234,6 +265,7 @@ canon_filename (const char *name, int nested, struct stat64 *stp)
goto error;
rpath = new_rpath;
rpath_limit = rpath + new_size;
+ rpath_root = rpath + root_size;
dest = rpath + dest_offset;
}
@@ -241,8 +273,15 @@ canon_filename (const char *name, int nested, struct stat64 *stp)
dest = mempcpy (dest, start, end - start);
*dest = '\0';
+ if (allow_last_link && *end == '\0')
+ break;
+
if (lstat64 (rpath, stp) < 0)
- goto error;
+ {
+ if (allow_missing && *end == '\0')
+ break;
+ goto error;
+ }
stp_initialized = 1;
@@ -259,7 +298,11 @@ canon_filename (const char *name, int nested, struct stat64 *stp)
n = readlink (rpath, buf, path_max);
if (n < 0)
- goto error;
+ {
+ if (allow_missing && *end == '\0')
+ break;
+ goto error;
+ }
buf[n] = '\0';
if (!extra_buf)
@@ -277,10 +320,10 @@ canon_filename (const char *name, int nested, struct stat64 *stp)
name = end = memcpy (extra_buf, buf, n);
if (buf[0] == '/')
- dest = rpath + 1; /* It's an absolute symlink */
+ dest = rpath_root + 1; /* It's an absolute symlink */
else
/* Back up to previous component, ignore if at root already: */
- if (dest > rpath + 1)
+ if (dest > rpath_root + 1)
while ((--dest)[-1] != '/');
}
else if (!S_ISDIR (stp->st_mode) && *end != '\0')
@@ -294,7 +337,8 @@ canon_filename (const char *name, int nested, struct stat64 *stp)
--dest;
*dest = '\0';
- if (!stp_initialized && lstat64 (rpath, stp) < 0)
+ if (!stp_initialized && !allow_missing && !allow_last_link
+ && lstat64 (rpath, stp) < 0)
goto error;
if (dest + 1 - rpath <= (rpath_limit - rpath) / 2)
@@ -311,9 +355,20 @@ error:
return NULL;
}
+char *unsysroot_file_name (const char *name);
+
char *
prelink_canonicalize (const char *name, struct stat64 *stp)
{
struct stat64 st;
- return canon_filename (name, 0, stp ? stp : &st);
+ char *canon, *final;
+
+ canon = canon_filename (name, 0, stp ? stp : &st,
+ sysroot ? sysroot : "", 0, 0);
+ if (canon == NULL)
+ return NULL;
+ final = unsysroot_file_name (canon);
+ if (final != canon)
+ free (canon);
+ return final;
}
diff --git a/trunk/src/conflict.c b/trunk/src/conflict.c
index 9c936ce..a1fb1ec 100644
--- a/trunk/src/conflict.c
+++ b/trunk/src/conflict.c
@@ -1,5 +1,7 @@
/* Copyright (C) 2001, 2002, 2003, 2004, 2007, 2009 Red Hat, Inc.
+ Copyright (C) 2008 CodeSourcery.
Written by Jakub Jelinek <jakub@redhat.com>, 2001.
+ Updated by Maciej W. Rozycki <macro@codesourcery.com>, 2008.
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
@@ -25,6 +27,7 @@
#include <unistd.h>
#include "prelink.h"
#include "reloc.h"
+#include "reloc-info.h"
struct prelink_conflict *
prelink_conflict (struct prelink_info *info, GElf_Word r_sym,
@@ -143,7 +146,7 @@ prelink_add_copy_rel (DSO *dso, int n, GElf_Rel *rel, struct copy_relocs *cr)
Elf_Scn *scn = dso->scn[symsec];
GElf_Sym sym;
size_t entsize = dso->shdr[symsec].sh_entsize;
- off_t off = GELF_R_SYM (rel->r_info) * entsize;
+ off_t off = reloc_r_sym (dso, rel->r_info) * entsize;
while ((data = elf_getdata (scn, data)) != NULL)
{
@@ -199,7 +202,7 @@ prelink_find_copy_rel (DSO *dso, int n, struct copy_relocs *cr)
if (sec == -1)
continue;
- if (GELF_R_TYPE (rel.r_info) == dso->arch->R_COPY
+ if (reloc_r_type (dso, rel.r_info) == dso->arch->R_COPY
&& prelink_add_copy_rel (dso, n, &rel, cr))
return 1;
}
@@ -228,7 +231,7 @@ prelink_find_copy_rela (DSO *dso, int n, struct copy_relocs *cr)
if (sec == -1)
continue;
- if (GELF_R_TYPE (u.rela.r_info) == dso->arch->R_COPY)
+ if (reloc_r_type (dso, u.rela.r_info) == dso->arch->R_COPY)
{
if (u.rela.r_addend != 0)
{
@@ -257,15 +260,18 @@ rela_cmp (const void *A, const void *B)
return 0;
}
+static DSO *conflict_rela_cmp_dso;
+
static int
conflict_rela_cmp (const void *A, const void *B)
{
+ DSO *dso = conflict_rela_cmp_dso;
GElf_Rela *a = (GElf_Rela *)A;
GElf_Rela *b = (GElf_Rela *)B;
- if (GELF_R_SYM (a->r_info) < GELF_R_SYM (b->r_info))
+ if (reloc_r_sym (dso, a->r_info) < reloc_r_sym (dso, b->r_info))
return -1;
- if (GELF_R_SYM (a->r_info) > GELF_R_SYM (b->r_info))
+ if (reloc_r_sym (dso, a->r_info) > reloc_r_sym (dso, b->r_info))
return 1;
if (a->r_offset < b->r_offset)
return -1;
@@ -330,7 +336,7 @@ get_relocated_mem (struct prelink_info *info, DSO *dso, GElf_Addr addr,
<= addr)
continue;
- reloc_type = GELF_R_TYPE (info->conflict_rela[j].r_info);
+ reloc_type = reloc_r_type (dso, info->conflict_rela[j].r_info);
reloc_size = dso->arch->reloc_size (reloc_type);
if (info->conflict_rela[j].r_offset + reloc_size <= addr)
continue;
@@ -414,7 +420,7 @@ get_relocated_mem (struct prelink_info *info, DSO *dso, GElf_Addr addr,
if (u.rel.r_offset + dso->arch->max_reloc_size <= addr)
continue;
- reloc_type = GELF_R_TYPE (u.rel.r_info);
+ reloc_type = reloc_r_type (dso, u.rel.r_info);
reloc_size = dso->arch->reloc_size (reloc_type);
if (u.rel.r_offset + reloc_size <= addr)
continue;
@@ -605,7 +611,8 @@ prelink_build_conflicts (struct prelink_info *info)
/* Record library's position in search scope into R_SYM field. */
for (j = first_conflict; j < info->conflict_rela_size; ++j)
info->conflict_rela[j].r_info
- = GELF_R_INFO (i, GELF_R_TYPE (info->conflict_rela[j].r_info));
+ = reloc_r_info (dso, i,
+ reloc_r_type (dso, info->conflict_rela[j].r_info));
if (dynamic_info_is_set (dso, DT_TEXTREL)
&& info->conflict_rela_size > first_conflict)
@@ -737,11 +744,11 @@ prelink_build_conflicts (struct prelink_info *info)
int j, reloc_class;
reloc_class
- = dso->arch->reloc_class (GELF_R_TYPE (cr.rela[i].r_info));
+ = dso->arch->reloc_class (reloc_r_type (dso, cr.rela[i].r_info));
assert (reloc_class != RTYPE_CLASS_TLS);
- for (s = & info->symbols[GELF_R_SYM (cr.rela[i].r_info)]; s;
+ for (s = & info->symbols[reloc_r_sym (dso, cr.rela[i].r_info)]; s;
s = s->next)
if (s->reloc_class == reloc_class)
break;
@@ -790,13 +797,15 @@ prelink_build_conflicts (struct prelink_info *info)
if (info->conflict_rela_size)
{
+ conflict_rela_cmp_dso = dso;
qsort (info->conflict_rela, info->conflict_rela_size, sizeof (GElf_Rela),
conflict_rela_cmp);
/* Now make sure all conflict RELA's are against absolute 0 symbol. */
for (i = 0; i < info->conflict_rela_size; ++i)
info->conflict_rela[i].r_info
- = GELF_R_INFO (0, GELF_R_TYPE (info->conflict_rela[i].r_info));
+ = reloc_r_info (dso, 0,
+ reloc_r_type (dso, info->conflict_rela[i].r_info));
if (enable_cxx_optimizations && remove_redundant_cxx_conflicts (info))
goto error_out;
diff --git a/trunk/src/cxx.c b/trunk/src/cxx.c
index 9a20b3c..4391ebe 100644
--- a/trunk/src/cxx.c
+++ b/trunk/src/cxx.c
@@ -26,6 +26,7 @@
#include <unistd.h>
#include <sys/wait.h>
#include "prelink.h"
+#include "reloc-info.h"
static struct
{
@@ -338,10 +339,10 @@ remove_redundant_cxx_conflicts (struct prelink_info *info)
{
size_t cidx;
- reloc_type = GELF_R_TYPE (info->conflict_rela[i].r_info);
+ reloc_type = reloc_r_type (info->dso, info->conflict_rela[i].r_info);
reloc_size = info->dso->arch->reloc_size (reloc_type);
- if (GELF_R_SYM (info->conflict_rela[i].r_info) != 0)
+ if (reloc_r_sym (info->dso, info->conflict_rela[i].r_info) != 0)
continue;
if (state
@@ -471,7 +472,8 @@ remove_noref:
(int) (info->conflict_rela[i].r_offset - fcs1.sym.st_value));
info->conflict_rela[i].r_info =
- GELF_R_INFO (1, GELF_R_TYPE (info->conflict_rela[i].r_info));
+ reloc_r_info (info->dso, 1,
+ reloc_r_type (info->dso, info->conflict_rela[i].r_info));
++removed;
continue;
@@ -608,7 +610,7 @@ pltref_remove:
- fcs1.sym.st_value));
info->conflict_rela[i].r_info =
- GELF_R_INFO (1, GELF_R_TYPE (info->conflict_rela[i].r_info));
+ reloc_r_info (info->dso, 1, reloc_r_type (info->dso, info->conflict_rela[i].r_info));
++removed;
goto pltref_check_done;
}
@@ -622,7 +624,7 @@ pltref_check_done:
if (removed)
{
for (i = 0, j = 0; i < info->conflict_rela_size; ++i)
- if (GELF_R_SYM (info->conflict_rela[i].r_info) == 0)
+ if (reloc_r_sym (info->dso, info->conflict_rela[i].r_info) == 0)
{
if (i != j)
info->conflict_rela[j] = info->conflict_rela[i];
diff --git a/trunk/src/data.c b/trunk/src/data.c
index 742d6b3..751f96f 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; \
}
@@ -50,9 +58,9 @@ uint##nn##_t \
buf_read_une##nn (DSO *dso, unsigned char *buf) \
{ \
if (dso->ehdr.e_ident[EI_DATA] == ELFDATA2LSB) \
- return buf_read_ule32 (buf); \
+ return buf_read_ule##nn (buf); \
else \
- return buf_read_ube32 (buf); \
+ return buf_read_ube##nn (buf); \
}
#define READUNE(nn) \
@@ -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 a289dd7..c94fc53 100644
--- a/trunk/src/doit.c
+++ b/trunk/src/doit.c
@@ -145,7 +145,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);
@@ -188,19 +188,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);
@@ -208,7 +208,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;
@@ -216,7 +216,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..f780e9a
--- /dev/null
+++ b/trunk/src/dso-readonly.c
@@ -0,0 +1,1832 @@
+/* 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;
+ else if (dyn.d_tag == DT_MIPS_PLTGOT)
+ dso->info_DT_MIPS_PLTGOT = 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)
+ {
+ fsync (fd);
+ 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
+ {
+ memset (&data, 0, sizeof data);
+ 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);
+ fsync (fd);
+ 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);
+ fsync (dso->fd);
+ close (dso->fd);
+ if (dso->elfro)
+ {
+ elf_end (dso->elfro);
+ fsync (dso->fdro);
+ 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 afafe64..8ad93d3 100644
--- a/trunk/src/dso.c
+++ b/trunk/src/dso.c
@@ -115,6 +115,8 @@ read_dynamic (DSO *dso)
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;
+ else if (dyn.d_tag == DT_MIPS_PLTGOT)
+ dso->info_DT_MIPS_PLTGOT = dyn.d_un.d_val;
}
}
if (ndx < maxndx)
@@ -229,7 +231,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 +517,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);
}
@@ -551,7 +553,10 @@ error_out:
if (elf)
elf_end (elf);
if (fd != -1)
- close (fd);
+ {
+ fsync (fd);
+ close (fd);
+ }
return NULL;
}
@@ -765,15 +770,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)
{
@@ -1015,7 +1020,8 @@ error_out:
elf_end (elf);
if (fd != -1)
{
- unlink (filename);
+ wrap_unlink (filename);
+ fsync (fd);
close (fd);
}
return 1;
@@ -1030,7 +1036,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;
@@ -1404,12 +1412,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
@@ -1630,10 +1641,12 @@ close_dso_1 (DSO *dso)
}
elf_end (dso->elf);
+ fsync (dso->fd);
close (dso->fd);
if (dso->elfro)
{
elf_end (dso->elfro);
+ fsync (dso->fdro);
close (dso->fdro);
}
if (dso->filename != dso->soname)
@@ -1653,7 +1666,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;
}
@@ -1778,19 +1791,19 @@ 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 (name2, orig_name ? orig_name : name1,
orig_name != NULL))
{
if (fdin != -1)
close (fdin);
- unlink (name2);
+ wrap_unlink (name2);
return 1;
}
if ((orig_name != NULL && strcmp (name1, "-") == 0)
- || rename (name2, name1))
+ || wrap_rename (name2, name1))
{
if (fdin != -1)
{
@@ -1800,7 +1813,7 @@ update_dso (DSO *dso, const char *orig_name)
if (strcmp (name1, "-") == 0)
fdout = 1;
else
- fdout = open (name1, O_WRONLY | O_CREAT, 0600);
+ fdout = wrap_open (name1, O_WRONLY | O_CREAT, 0600);
if (fdout != -1
&& fstat64 (fdin, &stt) >= 0
&& send_file (fdout, fdin, &off, stt.st_size) == stt.st_size)
@@ -1811,10 +1824,10 @@ update_dso (DSO *dso, const char *orig_name)
if (strcmp (name1, "-") != 0)
{
set_security_context (name1, name1, 1);
- utime (name1, &u);
+ wrap_utime (name1, &u);
close (fdout);
}
- unlink (name2);
+ wrap_unlink (name2);
return 0;
}
else if (fdout != -1)
@@ -1826,12 +1839,12 @@ update_dso (DSO *dso, const char *orig_name)
else
err = errno;
close (fdin);
- unlink (name2);
+ wrap_unlink (name2);
error (0, err, "Could not rename nor copy temporary to %s",
name1);
return 1;
}
- 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..67e762a
--- /dev/null
+++ b/trunk/src/elf.h
@@ -0,0 +1,2581 @@
+/* This file defines standard ELF types, structures, and macros.
+ Copyright (C) 1995-2003, 2004, 2005 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_ARM_EXIDX (PT_LOPROC + 1) /* .ARM.exidx segment */
+#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
+#define R_MIPS_TLS_DTPMOD32 38 /* Module number 32 bit */
+#define R_MIPS_TLS_DTPREL32 39 /* Module-relative offset 32 bit */
+#define R_MIPS_TLS_DTPMOD64 40 /* Module number 64 bit */
+#define R_MIPS_TLS_DTPREL64 41 /* Module-relative offset 64 bit */
+#define R_MIPS_TLS_GD 42 /* 16 bit GOT offset for GD */
+#define R_MIPS_TLS_LDM 43 /* 16 bit GOT offset for LDM */
+#define R_MIPS_TLS_DTPREL_HI16 44 /* Module-relative offset, high 16 bits */
+#define R_MIPS_TLS_DTPREL_LO16 45 /* Module-relative offset, low 16 bits */
+#define R_MIPS_TLS_GOTTPREL 46 /* 16 bit GOT offset for IE */
+#define R_MIPS_TLS_TPREL32 47 /* TP-relative offset, 32 bit */
+#define R_MIPS_TLS_TPREL64 48 /* TP-relative offset, 64 bit */
+#define R_MIPS_TLS_TPREL_HI16 49 /* TP-relative offset, high 16 bits */
+#define R_MIPS_TLS_TPREL_LO16 50 /* TP-relative offset, low 16 bits */
+#define R_MIPS_GLOB_DAT 51
+/* Keep this the last entry. */
+#define R_MIPS_NUM 52
+
+/* 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_TLS_DTPMOD32 17
+#define R_ARM_TLS_DTPOFF32 18
+#define R_ARM_TLS_TPOFF32 19
+#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_TLS_GD32 104
+#define R_ARM_TLS_LDM32 105
+#define R_ARM_TLS_LDO32 106
+#define R_ARM_TLS_IE32 107
+#define R_ARM_TLS_LE32 108
+#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/execle_open.c b/trunk/src/execle_open.c
index 52872aa..2ee5cbc 100644
--- a/trunk/src/execle_open.c
+++ b/trunk/src/execle_open.c
@@ -50,7 +50,7 @@ execve_open (const char *path, char *const argv[], char *const envp[])
return NULL;
}
- switch (vfork ())
+ switch (pid = vfork ())
{
case -1:
error (0, errno, "Could not run %s", path);
@@ -64,6 +64,7 @@ execve_open (const char *path, char *const argv[], char *const envp[])
}
dup2 (1, 2);
execve (path, argv, envp);
+ error (0, errno, "Could not run %s", path);
_exit (127);
}
diff --git a/trunk/src/execstack.c b/trunk/src/execstack.c
index 2f503ba..dda6bc7 100644
--- a/trunk/src/execstack.c
+++ b/trunk/src/execstack.c
@@ -32,11 +32,11 @@
int set;
int execflag;
-const char *argp_program_version = "execstack 1.0";
+const char *argp_program_version = EXECSTACK_PROG PKGVERSION " 1.0";
-const char *argp_program_bug_address = "<jakub@redhat.com>";
+const char *argp_program_bug_address = REPORT_BUGS_TO;
-static char argp_doc[] = "execstack -- program to query or set executable stack flag";
+static char argp_doc[] = EXECSTACK_PROG " -- program to query or set executable stack flag";
static struct argp_option options[] = {
{"set-execstack", 's', 0, 0, "Set executable stack flag bit" },
@@ -47,6 +47,13 @@ static struct argp_option options[] = {
{ 0 }
};
+/* The cached value of argv[0]. */
+const char *program_path;
+
+/* The full pathname of the prelink tool, or NULL if it hasn't been
+ computed yet. */
+const char *prelink_path;
+
static error_t
parse_opt (int key, char *arg, struct argp_state *state)
{
@@ -90,6 +97,8 @@ execstack_make_rdwr (DSO *dso, int flag)
DSO *ndso = NULL;
char *p = NULL;
char filename[strlen (dso->filename) + sizeof ".#execstack#.XXXXXX"];
+ extern char *make_relative_prefix (const char *, const char *, const char *);
+ char *dirname;
for (i = 0; i < dso->ehdr.e_shnum; ++i)
{
@@ -107,7 +116,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",
@@ -123,13 +132,18 @@ execstack_make_rdwr (DSO *dso, int flag)
goto error_out;
}
+ if (prelink_path == NULL)
+ {
+ dirname = make_relative_prefix (program_path, BINDIR, SBINDIR);
+ asprintf (&prelink_path, "%s/%s", dirname, PRELINK_PROG EXEEXT);
+ free (dirname);
+ }
+
pid = vfork ();
if (pid == 0)
{
close (fd);
- execlp ("prelink", "prelink", "-u", "-o", filename,
- dso->filename, NULL);
- execl (SBINDIR "/prelink", "prelink", "-u", "-o", filename,
+ execl (prelink_path, prelink_path, "-u", "-o", filename,
dso->filename, NULL);
_exit (-1);
}
@@ -183,7 +197,8 @@ execstack_make_rdwr (DSO *dso, int flag)
ndso->filename = p;
p = NULL;
- unlink (filename);
+ wrap_unlink (filename);
+ fsync (fd);
close (fd);
fd = -1;
close_dso (dso);
@@ -195,7 +210,8 @@ error_out:
close_dso (ndso);
if (fd != -1)
{
- unlink (filename);
+ wrap_unlink (filename);
+ fsync (fd);
close (fd);
}
close_dso (dso);
@@ -400,6 +416,8 @@ main (int argc, char *argv[])
{
int remaining, failures = 0;
+ program_path = argv[0];
+
setlocale (LC_ALL, "");
argp_parse (&argp, argc, argv, 0, &remaining, 0);
diff --git a/trunk/src/gather.c b/trunk/src/gather.c
index 2752e4b..16ed21b 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);
@@ -634,6 +673,77 @@ add_dir_to_dirlist (const char *name, dev_t dev, int flags)
return 0;
}
+/* Determine if a buffer holding an ELF header and program header
+ table may be that of a position-independent executable. */
+static int
+maybe_pie (unsigned char *e_ident, int big_endian, int sixty_four)
+{
+ uint16_t num_phdrs;
+ uint16_t phdr;
+ size_t p_type_offset;
+ size_t phnum_offset;
+ unsigned char *phdr_table;
+ unsigned char *this_phdr;
+
+ if (sixty_four)
+ {
+ uint64_t phdr_offset;
+
+ p_type_offset = offsetof (Elf64_Phdr, p_type);
+ phnum_offset = offsetof (Elf64_Ehdr, e_phnum);
+ if (big_endian)
+ phdr_offset = buf_read_ube64 (&e_ident [offsetof (Elf64_Ehdr,
+ e_phoff)]);
+ else
+ phdr_offset = buf_read_ule64 (&e_ident [offsetof (Elf64_Ehdr,
+ e_phoff)]);
+ phdr_table = e_ident + phdr_offset;
+ }
+ else
+ {
+ uint32_t phdr_offset;
+
+ p_type_offset = offsetof (Elf32_Phdr, p_type);
+ phnum_offset = offsetof (Elf32_Ehdr, e_phnum);
+ if (big_endian)
+ phdr_offset = buf_read_ube32 (&e_ident [offsetof (Elf32_Ehdr,
+ e_phoff)]);
+ else
+ phdr_offset = buf_read_ule32 (&e_ident [offsetof (Elf32_Ehdr,
+ e_phoff)]);
+ phdr_table = e_ident + phdr_offset;
+ }
+
+ this_phdr = phdr_table;
+
+ if (big_endian)
+ num_phdrs = buf_read_ube16 (&e_ident [phnum_offset]);
+ else
+ num_phdrs = buf_read_ule16 (&e_ident [phnum_offset]);
+
+ for (phdr = 0; phdr < num_phdrs; phdr++)
+ {
+ unsigned char *p_type_start = this_phdr + p_type_offset;
+ uint32_t p_type;
+
+ if (big_endian)
+ p_type = buf_read_ube32 (p_type_start);
+ else
+ p_type = buf_read_ule32 (p_type_start);
+
+ if (p_type == PT_PHDR)
+ return 1;
+
+ /* Any PT_PHDR entry must come before any PT_LOAD entry. */
+ if (p_type == PT_LOAD)
+ return 0;
+
+ this_phdr += sixty_four ? sizeof (Elf64_Phdr) : sizeof (Elf32_Phdr);
+ }
+
+ return 0;
+}
+
static int
gather_func (const char *name, const struct stat64 *st, int type,
struct FTW *ftwp)
@@ -693,13 +803,14 @@ 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;
if (read (fd, e_ident, sizeof (e_ident)) != sizeof (e_ident))
{
close_it:
+ fsync (fd);
close (fd);
return FTW_CONTINUE;
}
@@ -718,6 +829,7 @@ make_unprelinkable:
ent->type = ET_UNPRELINKABLE;
}
}
+ fsync (fd);
close (fd);
return FTW_CONTINUE;
}
@@ -733,17 +845,7 @@ make_unprelinkable:
goto make_unprelinkable;
else if (e_ident [EI_CLASS] == ELFCLASS32)
{
- if (e_ident [offsetof (Elf32_Ehdr, e_phoff)]
- == sizeof (Elf32_Ehdr)
- && memcmp (e_ident + offsetof (Elf32_Ehdr, e_phoff) + 1,
- "\0\0\0", 3) == 0
- && (e_ident [offsetof (Elf32_Ehdr, e_phnum)]
- || e_ident [offsetof (Elf32_Ehdr, e_phnum) + 1])
- && e_ident [sizeof (Elf32_Ehdr)
- + offsetof (Elf32_Phdr, p_type)] == PT_PHDR
- && memcmp (e_ident + sizeof (Elf32_Ehdr)
- + offsetof (Elf32_Phdr, p_type) + 1,
- "\0\0\0", 3) == 0)
+ if (maybe_pie (e_ident, 0, 0))
{
maybe_pie:
dso = fdopen_dso (fd, name);
@@ -760,17 +862,7 @@ maybe_pie:
}
else if (e_ident [EI_CLASS] == ELFCLASS64)
{
- if (e_ident [offsetof (Elf64_Ehdr, e_phoff)]
- == sizeof (Elf64_Ehdr)
- && memcmp (e_ident + offsetof (Elf64_Ehdr, e_phoff) + 1,
- "\0\0\0\0\0\0\0", 7) == 0
- && (e_ident [offsetof (Elf64_Ehdr, e_phnum)]
- || e_ident [offsetof (Elf64_Ehdr, e_phnum) + 1])
- && e_ident [sizeof (Elf64_Ehdr)
- + offsetof (Elf64_Phdr, p_type)] == PT_PHDR
- && memcmp (e_ident + sizeof (Elf64_Ehdr)
- + offsetof (Elf64_Phdr, p_type) + 1,
- "\0\0\0", 3) == 0)
+ if (maybe_pie (e_ident, 0, 1))
goto maybe_pie;
goto close_it;
}
@@ -787,35 +879,13 @@ maybe_pie:
goto make_unprelinkable;
else if (e_ident [EI_CLASS] == ELFCLASS32)
{
- if (e_ident [offsetof (Elf32_Ehdr, e_phoff) + 3]
- == sizeof (Elf32_Ehdr)
- && memcmp (e_ident + offsetof (Elf32_Ehdr, e_phoff),
- "\0\0\0", 3) == 0
- && (e_ident [offsetof (Elf32_Ehdr, e_phnum)]
- || e_ident [offsetof (Elf32_Ehdr, e_phnum) + 1])
- && e_ident [sizeof (Elf32_Ehdr)
- + offsetof (Elf32_Phdr, p_type) + 3]
- == PT_PHDR
- && memcmp (e_ident + sizeof (Elf32_Ehdr)
- + offsetof (Elf32_Phdr, p_type),
- "\0\0\0", 3) == 0)
+ if (maybe_pie (e_ident, 1, 0))
goto maybe_pie;
goto close_it;
}
else if (e_ident [EI_CLASS] == ELFCLASS64)
{
- if (e_ident [offsetof (Elf64_Ehdr, e_phoff) + 7]
- == sizeof (Elf64_Ehdr)
- && memcmp (e_ident + offsetof (Elf64_Ehdr, e_phoff),
- "\0\0\0\0\0\0\0", 7) == 0
- && (e_ident [offsetof (Elf64_Ehdr, e_phnum)]
- || e_ident [offsetof (Elf64_Ehdr, e_phnum) + 1])
- && e_ident [sizeof (Elf64_Ehdr)
- + offsetof (Elf64_Phdr, p_type) + 3]
- == PT_PHDR
- && memcmp (e_ident + sizeof (Elf64_Ehdr)
- + offsetof (Elf64_Phdr, p_type),
- "\0\0\0", 3) == 0)
+ if (maybe_pie (e_ident, 1, 1))
goto maybe_pie;
goto close_it;
}
@@ -891,7 +961,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);
@@ -901,6 +971,7 @@ gather_binlib (const char *name, const struct stat64 *st)
if (read (fd, e_ident, sizeof (e_ident)) != sizeof (e_ident))
{
error (0, errno, "Could not read ELF header from %s", name);
+ fsync (fd);
close (fd);
return 1;
}
@@ -910,6 +981,7 @@ gather_binlib (const char *name, const struct stat64 *st)
if (memcmp (e_ident, ELFMAG, SELFMAG) != 0)
{
error (0, 0, "%s is not an ELF object", name);
+ fsync (fd);
close (fd);
return 1;
}
@@ -934,6 +1006,7 @@ gather_binlib (const char *name, const struct stat64 *st)
{
unsupported_type:
error (0, 0, "%s is neither ELF executable nor ELF shared library", name);
+ fsync (fd);
close (fd);
return 1;
}
@@ -979,7 +1052,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 +1075,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;
if (ret < 0)
error (0, errno, "Failed searching %s", name);
@@ -1265,7 +1338,7 @@ add_to_blacklist (const char *name, int deref, int onefs)
size_t len;
struct stat64 st;
- if (stat64 (name, &st) < 0)
+ if (wrap_stat64 (name, &st) < 0)
{
if (implicit)
return 0;
diff --git a/trunk/src/get.c b/trunk/src/get.c
index fe32deb..001bb1e 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")
@@ -165,7 +166,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);
@@ -638,7 +639,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;
@@ -667,13 +668,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
@@ -684,17 +678,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/layout.c b/trunk/src/layout.c
index 9292425..de98e1f 100644
--- a/trunk/src/layout.c
+++ b/trunk/src/layout.c
@@ -23,6 +23,7 @@
#include <string.h>
#include <time.h>
#include <unistd.h>
+#include <assert.h>
#include "prelinktab.h"
#include "layout.h"
@@ -298,7 +299,10 @@ layout_libs (void)
for (j = 0, k = 0; j < l.binlibs[i]->ndepends; ++j)
if (l.binlibs[i]->depends[j]->type == ET_DYN
&& l.binlibs[i]->depends[j]->done)
- deps[k++] = l.binlibs[i]->depends[j];
+ {
+ assert (k < l.nlibs);
+ deps[k++] = l.binlibs[i]->depends[j];
+ }
if (k)
{
qsort (deps, k, sizeof (struct prelink_entry *), deps_cmp);
@@ -381,6 +385,7 @@ layout_libs (void)
mmap_start += mmap_base;
}
+ fsync (fd);
close (fd);
}
diff --git a/trunk/src/ld-do-lookup.h b/trunk/src/ld-do-lookup.h
new file mode 100644
index 0000000..2d359d7
--- /dev/null
+++ b/trunk/src/ld-do-lookup.h
@@ -0,0 +1,232 @@
+/* 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, 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
+ {
+ unsigned long int hash;
+ const ElfW(Sym) *symtab;
+ const char *strtab;
+ const ElfW(Half) *verstab;
+ Elf_Symndx symidx;
+ const ElfW(Sym) *sym;
+ int gnu_hash;
+#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;
+ gnu_hash = map->l_gnu_hash;
+ hash = rtld_elf_any_hash (undef_name, gnu_hash);
+
+ /* Search the appropriate hash bucket in this object's symbol table
+ for a definition for the same symbol name. */
+ for (symidx = do_lookup_get_first (map, hash, gnu_hash);
+ symidx != STN_UNDEF;
+ symidx = do_lookup_get_next (symidx, map, hash, gnu_hash))
+ {
+ 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
+ )
+ || (machine == EM_MIPS
+ && sym->st_shndx == SHN_UNDEF
+ && !(sym->st_other & STO_MIPS_PLT))
+ || (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..fe758b8
--- /dev/null
+++ b/trunk/src/ld-libs.c
@@ -0,0 +1,1512 @@
+/* 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 "reloc-info.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_PROG PKGVERSION " 1.0";
+
+const char *argp_program_bug_address = REPORT_BUGS_TO;
+
+static char argp_doc[] = PRELINK_RTLD_PROG " -- 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;
+ }
+
+ case EM_MIPS:
+ switch (type)
+ {
+ case R_MIPS_COPY:
+ return ELF_RTYPE_CLASS_COPY;
+ case R_MIPS_JUMP_SLOT:
+ case R_MIPS_TLS_DTPMOD32:
+ case R_MIPS_TLS_DTPREL32:
+ case R_MIPS_TLS_TPREL32:
+ return ELF_RTYPE_CLASS_PLT;
+ default:
+ return 0;
+ }
+
+ case EM_SPARC:
+ case EM_SPARC32PLUS:
+ switch (type)
+ {
+ case R_SPARC_COPY:
+ return ELF_RTYPE_CLASS_COPY;
+ case R_SPARC_JMP_SLOT:
+ case R_SPARC_TLS_DTPMOD32:
+ case R_SPARC_TLS_DTPOFF32:
+ case R_SPARC_TLS_TPOFF32:
+ case R_SPARC_TLS_LE_HIX22:
+ case R_SPARC_TLS_LE_LOX10:
+ return ELF_RTYPE_CLASS_PLT;
+ default:
+ return 0;
+ }
+
+ case EM_SPARCV9:
+ switch (type)
+ {
+ case R_SPARC_COPY:
+ return ELF_RTYPE_CLASS_COPY;
+ case R_SPARC_JMP_SLOT:
+ case R_SPARC_TLS_DTPMOD64:
+ case R_SPARC_TLS_DTPOFF64:
+ case R_SPARC_TLS_TPOFF64:
+ case R_SPARC_TLS_LE_HIX22:
+ case R_SPARC_TLS_LE_LOX10:
+ return ELF_RTYPE_CLASS_PLT;
+ default:
+ 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 use_mipsn32)
+{
+ 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 if (use_mipsn32)
+ {
+ add_dir (&ld_dirs, "/lib32/tls", strlen ("/lib32/tls"));
+ add_dir (&ld_dirs, "/lib32", strlen ("/lib32"));
+ add_dir (&ld_dirs, "/usr/lib32/tls", strlen ("/usr/lib32/tls"));
+ add_dir (&ld_dirs, "/usr/lib32", strlen ("/usr/lib32"));
+ }
+ 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 (len > 0 && isspace (buf[len - 1]))
+ buf[--len] = 0;
+
+ if (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, int machine)
+{
+ char *ret;
+ int i;
+ int alt_machine;
+
+ switch (machine)
+ {
+ case EM_SPARC:
+ alt_machine = EM_SPARC32PLUS;
+ break;
+ case EM_SPARC32PLUS:
+ alt_machine = EM_SPARC;
+ break;
+ default:
+ alt_machine = machine;
+ break;
+ }
+
+ 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)
+ {
+ DSO *dso = open_dso (ret);
+ int dso_class = gelf_getclass (dso->elf);
+ int dso_machine = (dso_class == ELFCLASS32) ?
+ elf32_getehdr (dso->elf)->e_machine :
+ elf64_getehdr (dso->elf)->e_machine;
+
+ if (dso == NULL)
+ continue;
+
+ /* Skip 32-bit libraries when looking for 64-bit. Also
+ skip libraries for alternative machines. */
+ if (gelf_getclass (dso->elf) != elfclass
+ || (dso_machine != machine && dso_machine != alt_machine))
+ {
+ 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, int machine)
+{
+ 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, machine);
+ free_path (&r_path);
+ if (ret)
+ return ret;
+ }
+ loader_p = loader_p->loader;
+ }
+ }
+
+ ret = find_lib_in_path (&ld_library_search_path, soname, elfclass, machine);
+ 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, machine);
+ free_path (&r_path);
+ if (ret)
+ return ret;
+ }
+
+ ret = find_lib_in_path (&ld_dirs, soname, elfclass, machine);
+ if (ret)
+ return ret;
+
+ return NULL;
+}
+
+static struct dso_list *
+load_dsos (DSO *dso, int host_paths)
+{
+ struct dso_list *dso_list, *dso_list_tail, *cur_dso_ent, *new_dso_ent;
+ struct stat64 st;
+
+ 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;
+
+ if (host_paths)
+ dso_list->canon_filename = canonicalize_file_name (dso->filename);
+ else
+ dso_list->canon_filename = prelink_canonicalize (dso->filename, &st);
+
+ if (dso_list->canon_filename == NULL)
+ dso_list->canon_filename = strdup (dso->filename);
+
+ 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)
+ {
+ int machine;
+ int class = gelf_getclass (dso->elf);
+ machine = (class == ELFCLASS32) ?
+ elf32_getehdr (dso->elf)->e_machine :
+ elf64_getehdr (dso->elf)->e_machine;
+ new_name = find_lib_by_soname (soname, cur_dso_ent,
+ class, machine);
+ 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 = 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;
+
+ map->l_gnu_hash = dynamic_info_is_set (dso, DT_GNU_HASH_BIT);
+ if (map->l_gnu_hash)
+ i = addr_to_sec (dso, dso->info_DT_GNU_HASH);
+ else
+ i = addr_to_sec (dso, dso->info[DT_HASH]);
+ data = elf_getdata (dso->scn[i], NULL);
+ hash = data->d_buf;
+ map->l_nbuckets = hash[0];
+ if (map->l_gnu_hash)
+ {
+ map->l_nmaskwords = hash[2];
+ map->l_maskword64 = gelf_getclass (dso->elf) == ELFCLASS64;
+ map->l_shift = hash[3];
+ map->l_maskwords = hash + 4;
+ map->l_buckets = hash + 4 + (map->l_nmaskwords << map->l_maskword64);
+ map->l_chain = map->l_buckets + map->l_nbuckets - hash[1];
+ }
+ else
+ {
+ map->l_buckets = hash + 2;
+ map->l_chain = map->l_buckets + 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_reloc (DSO *dso, struct ldlibs_link_map *map, struct r_scope_elem *scope,
+ GElf_Word sym, GElf_Word type)
+{
+ struct r_found_version *ver;
+ int rtypeclass;
+ void *symptr;
+ const char *name;
+ Elf64_Word st_name;
+
+ 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)
+ return;
+ 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)
+ return;
+ symptr = sym64;
+ st_name = sym64->st_name;
+ }
+
+ if (cache.symptr == symptr && cache.rtypeclass == rtypeclass)
+ return;
+ 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_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;
+
+ 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 = reloc_r_sym (dso, rel.r_info);
+ type = reloc_r_type (dso, rel.r_info);
+ }
+ else
+ {
+ GElf_Rela rela;
+ gelfx_getrela (dso->elf, data, ndx, &rela);
+ sym = reloc_r_sym (dso, rela.r_info);
+ type = reloc_r_type (dso, rela.r_info);
+ }
+ if (sym != 0)
+ do_reloc (dso, map, scope, sym, type);
+ }
+}
+
+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]));
+}
+
+/* MIPS GOTs are not handled by normal relocations. Instead, entry X
+ in the global GOT is associated with symbol DT_MIPS_GOTSYM + X.
+ For the purposes of symbol lookup and conflict resolution, we need
+ to act as though entry X had a dynamic relocation against symbol
+ DT_MIPS_GOTSYM + X. */
+
+void
+do_mips_global_got_relocs (DSO *dso, struct ldlibs_link_map *map,
+ struct r_scope_elem *scope)
+{
+ GElf_Word i;
+
+ for (i = dso->info_DT_MIPS_GOTSYM; i < dso->info_DT_MIPS_SYMTABNO; i++)
+ do_reloc (dso, map, scope, i, R_MIPS_REL32);
+}
+
+void
+handle_relocs_in_entry (struct dso_list *entry, struct dso_list *dso_list)
+{
+ GElf_Word i;
+
+ do_relocs (entry->dso, entry->map, dso_list->map->l_local_scope, DT_REL);
+ do_relocs (entry->dso, entry->map, dso_list->map->l_local_scope, DT_RELA);
+ if (entry->dso->ehdr.e_machine == EM_MIPS)
+ do_mips_global_got_relocs (entry->dso, entry->map,
+ dso_list->map->l_local_scope);
+}
+
+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
+ handle_relocs_in_entry (tail, dso_list);
+ tail = tail->prev;
+ }
+
+ if (ldso)
+ handle_relocs_in_entry (ldso, dso_list);
+}
+
+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;
+
+ case EM_MIPS:
+ offset = 0;
+ break;
+
+ case EM_SPARC:
+ case EM_SPARC32PLUS:
+ offset = -1;
+ break;
+
+ case EM_SPARCV9:
+ offset = -1;
+ 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 = canonicalize_file_name (sysroot);
+
+ 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,
+ ( dso->ehdr.e_machine == EM_MIPS) && ( dso->ehdr.e_flags & EF_MIPS_ABI2 ) );
+
+ 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, host_paths);
+
+ 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 = cur_dso_ent->canon_filename;
+
+ 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..d69c7cd
--- /dev/null
+++ b/trunk/src/ld-libs.h
@@ -0,0 +1,115 @@
+#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. */
+ int l_gnu_hash, l_maskword64;
+ Elf_Symndx l_nbuckets, l_nmaskwords, l_shift;
+ const void *l_maskwords;
+ 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..5128dbb
--- /dev/null
+++ b/trunk/src/ld-lookup.c
@@ -0,0 +1,298 @@
+/* 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;
+};
+
+static unsigned long
+rtld_elf_hash (const char *name)
+{
+ const unsigned char *str = (const unsigned char *) name;
+ unsigned long int hash = 0;
+ unsigned long int hi;
+
+ while (*str != '\0')
+ {
+ hash = (hash << 4) + *str++;
+ hi = hash & 0xf0000000;
+ hash ^= hi;
+ hash ^= hi >> 24;
+ }
+ return hash & 0xffffffff;
+}
+
+static unsigned long
+rtld_elf_gnu_hash (const char *name)
+{
+ const unsigned char *str = (const unsigned char *) name;
+ unsigned long int hash = 5381;
+
+ while (*str != '\0')
+ hash = (hash << 5) + hash + *str++;
+ return hash & 0xffffffff;
+}
+
+static inline unsigned long
+rtld_elf_any_hash (const char *name, int gnu_hash)
+{
+ return gnu_hash ? rtld_elf_gnu_hash (name) : rtld_elf_hash (name);
+}
+
+static inline Elf_Symndx
+do_lookup_get_first (struct ldlibs_link_map *map,
+ unsigned long int hash, int gnu_hash)
+{
+ Elf_Symndx symidx = STN_UNDEF;
+
+ if (gnu_hash)
+ {
+ Elf_Symndx bucket;
+ int match;
+
+ if (map->l_maskword64)
+ {
+ const Elf64_Xword *const masks = map->l_maskwords;
+ const Elf64_Xword mask = masks[(hash / 64) % map->l_nmaskwords];
+ const Elf64_Xword set = ((1ULL << (hash % 64))
+ | (1ULL << ((hash >> map->l_shift) % 64)));
+
+ match = (mask & set) == set;
+ }
+ else
+ {
+ const Elf32_Word *const masks = map->l_maskwords;
+ const Elf32_Word mask = masks[(hash / 32) % map->l_nmaskwords];
+ const Elf32_Word set = ((1UL << (hash % 32))
+ | (1UL << ((hash >> map->l_shift) % 32)));
+
+ match = (mask & set) == set;
+ }
+
+ if (match
+ && (bucket = map->l_buckets[hash % map->l_nbuckets]) != STN_UNDEF)
+ do
+ if (((map->l_chain[bucket] ^ hash) & ~1UL) == 0)
+ {
+ symidx = bucket;
+ break;
+ }
+ while ((map->l_chain[bucket++] & 1) == 0);
+ }
+ else
+ symidx = map->l_buckets[hash % map->l_nbuckets];
+
+ return symidx;
+}
+
+static inline Elf_Symndx
+do_lookup_get_next (Elf_Symndx osymidx, struct ldlibs_link_map *map,
+ unsigned long int hash, int gnu_hash)
+{
+ Elf_Symndx symidx = STN_UNDEF;
+
+ if (gnu_hash)
+ {
+ Elf_Symndx bucket = osymidx;
+
+ while ((map->l_chain[bucket++] & 1) == 0)
+ if (((map->l_chain[bucket] ^ hash) & ~1UL) == 0)
+ {
+ symidx = bucket;
+ break;
+ }
+ }
+ else
+ symidx = map->l_chain[osymidx];
+
+ return symidx;
+}
+
+#include "ld-do-lookup.h"
+#define VERSIONED 1
+#include "ld-do-lookup.h"
+#undef VERSIONED
+
+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, 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, sym, &result, scope, 0, version, NULL,
+ rtypeclass, machine);
+ else
+ ret = do_lookup (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, sym, &result2,
+ undef_map->l_local_scope, 0, version, NULL,
+ rtypeclass, machine);
+ else
+ ret = do_lookup (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 144ce84..4678ba4 100644
--- a/trunk/src/main.c
+++ b/trunk/src/main.c
@@ -58,12 +58,14 @@ 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_PROG PKGVERSION " 1.0";
-const char *argp_program_bug_address = "<jakub@redhat.com>";
+const char *argp_program_bug_address = REPORT_BUGS_TO;
-static char argp_doc[] = "prelink -- program to relocate and prelink ELF shared libraries and programs";
+static char argp_doc[] = PRELINK_PROG " -- program to relocate and prelink ELF shared libraries and programs";
#define OPT_DYNAMIC_LINKER 0x80
#define OPT_LD_LIBRARY_PATH 0x81
@@ -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,41 @@ 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 = canonicalize_file_name (sysroot);
+ 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 && prelink_rtld[0] == 0)
+ prelink_rtld = NULL;
+ else
+ 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);
+ asprintf ((char **) &prelink_rtld, "%s/%s", path,
+ PRELINK_RTLD_PROG EXEEXT);
+ }
+
if (print_cache)
{
prelink_load_cache ();
diff --git a/trunk/src/prelink.c b/trunk/src/prelink.c
index 0d113b7..0798811 100644
--- a/trunk/src/prelink.c
+++ b/trunk/src/prelink.c
@@ -440,6 +440,7 @@ prelink_prepare (DSO *dso)
break;
case SHT_DYNAMIC:
case SHT_MIPS_REGINFO:
+ case SHT_MIPS_OPTIONS:
/* The same applies to these sections on MIPS. The convention
is to put .dynamic and .reginfo near the beginning of the
read-only segment, before the program text. No relocations
@@ -793,7 +794,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 8849539..741f0a4 100644
--- a/trunk/src/prelink.h
+++ b/trunk/src/prelink.h
@@ -1,6 +1,8 @@
/* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010
Red Hat, Inc.
+ Copyright (C) 2008 CodeSourcery.
Written by Jakub Jelinek <jakub@redhat.com>, 2001.
+ Updated by Maciej W. Rozycki <macro@codesourcery.com>, 2008.
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
@@ -22,10 +24,16 @@
#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 HAVE_ELF64_BYTE
+typedef uint8_t Elf64_Byte;
+#endif
#ifndef DT_GNU_LIBLIST
#define DT_GNU_LIBLIST 0x6ffffef9
@@ -75,10 +83,28 @@
#define R_MIPS_TLS_TPREL32 47
#endif
+#ifndef R_MIPS_TLS_DTPMOD64
+#define R_MIPS_TLS_DTPMOD64 40
+#define R_MIPS_TLS_DTPREL64 41
+#define R_MIPS_TLS_TPREL64 48
+#endif
+
#ifndef R_MIPS_GLOB_DAT
#define R_MIPS_GLOB_DAT 51
#endif
+#ifndef R_MIPS_COPY
+#define R_MIPS_COPY 126
+#define R_MIPS_JUMP_SLOT 127
+#define STO_MIPS_PLT 0x8
+#define DT_MIPS_PLTGOT 0x70000032
+#define DT_MIPS_RWPLT 0x70000034
+#endif
+
+#ifndef RSS_UNDEF
+#define RSS_UNDEF 0
+#endif
+
#ifndef R_ARM_TLS_DTPMOD32
#define R_ARM_TLS_DTPMOD32 17
#define R_ARM_TLS_DTPOFF32 18
@@ -137,6 +163,7 @@ typedef struct
GElf_Addr info_DT_MIPS_LOCAL_GOTNO;
GElf_Addr info_DT_MIPS_GOTSYM;
GElf_Addr info_DT_MIPS_SYMTABNO;
+ GElf_Addr info_DT_MIPS_PLTGOT;
#define DT_GNU_PRELINKED_BIT 50
#define DT_CHECKSUM_BIT 51
#define DT_VERNEED_BIT 52
@@ -162,7 +189,11 @@ typedef struct
GElf_Shdr shdr[0];
} DSO;
-#define dynamic_info_is_set(dso,bit) ((dso)->info_set_mask & (1ULL << (bit)))
+static inline int
+dynamic_info_is_set (DSO *dso, int bit)
+{
+ return ((dso)->info_set_mask & (1ULL << (bit))) != 0;
+}
struct layout_libs;
@@ -174,6 +205,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;
@@ -285,7 +317,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); \
@@ -311,8 +343,8 @@ unsigned char *get_data_from_iterator (struct data_iterator *it,
GElf_Addr size);
int get_sym_from_iterator (struct data_iterator *it, GElf_Sym *sym);
-#define PL_ARCH \
-static struct PLArch plarch __attribute__((section("pl_arch"),used))
+#define PL_ARCH(F) \
+static struct PLArch plarch_##F __attribute__((section("pl_arch"),used))
#define addr_adjust(addr, start, adjust) \
do { \
@@ -541,4 +573,22 @@ extern int quick;
extern long long seed;
extern GElf_Addr mmap_reg_start, mmap_reg_end;
+extern const char *sysroot;
+
+int wrap_readlink (const char *path, char *buf, int len);
+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);
+char *sysroot_file_name (const char *name, int allow_last_link);
+
+extern const char *prelink_rtld;
+
#endif /* PRELINK_H */
diff --git a/trunk/src/reloc-info.c b/trunk/src/reloc-info.c
new file mode 100644
index 0000000..4ce333c
--- /dev/null
+++ b/trunk/src/reloc-info.c
@@ -0,0 +1,215 @@
+/* Copyright (C) 2008 CodeSourcery
+ Written by Maciej W. Rozycki <macro@codesourcery.com>, 2008.
+
+ 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 "prelink.h"
+#include "reloc-info.h"
+
+/* A structure to lay out generic relocation information
+ * in a way specific to 64-bit MIPS. */
+union mips64_r_info
+{
+ /* Generic r_info interpretation. */
+ Elf64_Xword r_info;
+
+ /* 64-bit MIPS r_info interpretation. */
+ struct
+ {
+ /* Symbol index for the first relocation. */
+ Elf64_Word r_sym;
+
+ /* Special symbol for the second relocation. */
+ Elf64_Byte r_ssym;
+
+ /* Third relocation. */
+ Elf64_Byte r_type3;
+
+ /* Second relocation. */
+ Elf64_Byte r_type2;
+
+ /* First relocation. */
+ Elf64_Byte r_type;
+ }
+ s_info;
+};
+
+/* Extract the symbol index from 64-bit MIPS reloc info. */
+
+static GElf_Xword
+mips64_r_sym (DSO *dso, GElf_Xword r_info)
+{
+ union mips64_r_info mips64_r_info;
+
+ buf_write_ne64 (dso, (unsigned char *) &mips64_r_info.r_info, r_info);
+ return buf_read_une32 (dso, (unsigned char *) &mips64_r_info.s_info.r_sym);
+}
+
+/* Extract the special symbol index from 64-bit MIPS reloc info. */
+
+static GElf_Xword
+mips64_r_ssym (DSO *dso, GElf_Xword r_info)
+{
+ union mips64_r_info mips64_r_info;
+
+ buf_write_ne64 (dso, (unsigned char *) &mips64_r_info.r_info, r_info);
+ return mips64_r_info.s_info.r_ssym;
+}
+
+/* Extract the first reloc type from 64-bit MIPS reloc info. */
+
+static GElf_Xword
+mips64_r_type (DSO *dso, GElf_Xword r_info)
+{
+ union mips64_r_info mips64_r_info;
+
+ buf_write_ne64 (dso, (unsigned char *) &mips64_r_info.r_info, r_info);
+ return mips64_r_info.s_info.r_type;
+}
+
+/* Extract the second reloc type from 64-bit MIPS reloc info. */
+
+static GElf_Xword
+mips64_r_type2 (DSO *dso, GElf_Xword r_info)
+{
+ union mips64_r_info mips64_r_info;
+
+ buf_write_ne64 (dso, (unsigned char *) &mips64_r_info.r_info, r_info);
+ return mips64_r_info.s_info.r_type2;
+}
+
+/* Extract the third reloc type from 64-bit MIPS reloc info. */
+
+static GElf_Xword
+mips64_r_type3 (DSO *dso, GElf_Xword r_info)
+{
+ union mips64_r_info mips64_r_info;
+
+ buf_write_ne64 (dso, (unsigned char *) &mips64_r_info.r_info, r_info);
+ return mips64_r_info.s_info.r_type3;
+}
+
+/* Construct 64-bit MIPS reloc info from symbol indices and reloc types. */
+
+static GElf_Xword
+mips64_r_info_ext (DSO *dso, GElf_Word r_sym, Elf64_Byte r_ssym,
+ Elf64_Byte r_type, Elf64_Byte r_type2, Elf64_Byte r_type3)
+{
+ union mips64_r_info mips64_r_info;
+
+ buf_write_ne32 (dso, (unsigned char *) &mips64_r_info.s_info.r_sym, r_sym);
+ mips64_r_info.s_info.r_ssym = r_ssym;
+ mips64_r_info.s_info.r_type = r_type;
+ mips64_r_info.s_info.r_type2 = r_type2;
+ mips64_r_info.s_info.r_type3 = r_type3;
+ return buf_read_une64 (dso, (unsigned char *) &mips64_r_info.r_info);
+}
+
+
+/* Extract the symbol index from reloc info. */
+
+GElf_Xword
+reloc_r_sym (DSO *dso, GElf_Xword r_info)
+{
+ if (dso->ehdr.e_ident[EI_CLASS] == ELFCLASS64
+ && dso->ehdr.e_machine == EM_MIPS)
+ return mips64_r_sym (dso, r_info);
+ else
+ return GELF_R_SYM (r_info);
+}
+
+/* Extract the special symbol index from reloc info. */
+
+GElf_Xword
+reloc_r_ssym (DSO *dso, GElf_Xword r_info)
+{
+ if (dso->ehdr.e_ident[EI_CLASS] == ELFCLASS64
+ && dso->ehdr.e_machine == EM_MIPS)
+ return mips64_r_ssym (dso, r_info);
+ else
+ return RSS_UNDEF;
+}
+
+/* Extract the first reloc type from reloc info. */
+
+GElf_Xword
+reloc_r_type (DSO *dso, GElf_Xword r_info)
+{
+ if (dso->ehdr.e_ident[EI_CLASS] == ELFCLASS64
+ && dso->ehdr.e_machine == EM_MIPS)
+ return mips64_r_type (dso, r_info);
+ else
+ return GELF_R_TYPE (r_info);
+}
+
+/* Extract the second reloc type from reloc info. */
+
+GElf_Xword
+reloc_r_type2 (DSO *dso, GElf_Xword r_info)
+{
+ if (dso->ehdr.e_ident[EI_CLASS] == ELFCLASS64
+ && dso->ehdr.e_machine == EM_MIPS)
+ return mips64_r_type2 (dso, r_info);
+ else
+ return 0;
+}
+
+/* Extract the third reloc type from reloc info. */
+
+GElf_Xword
+reloc_r_type3 (DSO *dso, GElf_Xword r_info)
+{
+ if (dso->ehdr.e_ident[EI_CLASS] == ELFCLASS64
+ && dso->ehdr.e_machine == EM_MIPS)
+ return mips64_r_type3 (dso, r_info);
+ else
+ return 0;
+}
+
+/* Construct reloc info from symbol index and reloc type. */
+
+GElf_Xword
+reloc_r_info (DSO *dso, GElf_Word r_sym, GElf_Word r_type)
+{
+ if (dso->ehdr.e_ident[EI_CLASS] == ELFCLASS64
+ && dso->ehdr.e_machine == EM_MIPS)
+ switch (r_type)
+ {
+ case R_MIPS_REL32:
+ case R_MIPS_GLOB_DAT:
+ return mips64_r_info_ext (dso, r_sym, RSS_UNDEF,
+ r_type, R_MIPS_64, R_MIPS_NONE);
+ default:
+ return mips64_r_info_ext (dso, r_sym, RSS_UNDEF,
+ r_type, R_MIPS_NONE, R_MIPS_NONE);
+ }
+ else
+ return GELF_R_INFO (r_sym, r_type);
+}
+
+/* Construct reloc info from symbol index and reloc type. */
+
+GElf_Xword
+reloc_r_info_ext (DSO *dso, GElf_Word r_sym, Elf64_Byte r_ssym,
+ Elf64_Byte r_type, Elf64_Byte r_type2, Elf64_Byte r_type3)
+{
+ if (dso->ehdr.e_ident[EI_CLASS] == ELFCLASS64
+ && dso->ehdr.e_machine == EM_MIPS)
+ return mips64_r_info_ext (dso, r_sym, r_ssym, r_type, r_type2, r_type3);
+ else
+ return GELF_R_INFO (r_sym, r_type);
+}
diff --git a/trunk/src/reloc-info.h b/trunk/src/reloc-info.h
new file mode 100644
index 0000000..a8f8b7c
--- /dev/null
+++ b/trunk/src/reloc-info.h
@@ -0,0 +1,35 @@
+/* Copyright (C) 2008 CodeSourcery
+ Written by Maciej W. Rozycki <macro@codesourcery.com>, 2008.
+
+ 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. */
+
+#ifndef RELOC_INFO_H
+#define RELOC_INFO_H
+
+#include "prelink.h"
+
+/* Reloc info primitives. */
+GElf_Xword reloc_r_sym (DSO *dso, GElf_Xword r_info);
+GElf_Xword reloc_r_ssym (DSO *dso, GElf_Xword r_info);
+GElf_Xword reloc_r_type (DSO *dso, GElf_Xword r_info);
+GElf_Xword reloc_r_type2 (DSO *dso, GElf_Xword r_info);
+GElf_Xword reloc_r_type3 (DSO *dso, GElf_Xword r_info);
+
+GElf_Xword reloc_r_info (DSO *dso, GElf_Word r_sym, GElf_Word r_type);
+GElf_Xword reloc_r_info_ext (DSO *dso, GElf_Word r_sym, Elf64_Byte r_ssym,
+ Elf64_Byte r_type, Elf64_Byte r_type2,
+ Elf64_Byte r_type3);
+
+#endif /* RELOC_INFO_H */
diff --git a/trunk/src/space.c b/trunk/src/space.c
index f92348e..4bd4760 100644
--- a/trunk/src/space.c
+++ b/trunk/src/space.c
@@ -504,206 +504,219 @@ find_readonly_space (DSO *dso, GElf_Shdr *add, GElf_Ehdr *ehdr,
}
/* We have to create new PT_LOAD if at all possible. */
- addr = ehdr->e_phoff + (ehdr->e_phnum + 1) * ehdr->e_phentsize;
- for (j = 1; j < ehdr->e_shnum; ++j)
+ for (j = 0; j < ehdr->e_phnum; ++j)
+ if (phdr[j].p_type == PT_NULL)
+ break;
+
+ if (j < ehdr->e_phnum)
+ {
+ memmove (phdr, &phdr[j + 1],
+ (ehdr->e_phnum - j - 1) * sizeof (GElf_Phdr));
+ ehdr->e_phnum--;
+ }
+ else
{
- if (addr > shdr[j].sh_offset)
+ addr = ehdr->e_phoff + (ehdr->e_phnum + 1) * ehdr->e_phentsize;
+ for (j = 1; j < ehdr->e_shnum; ++j)
{
- GElf_Addr start, addstart, endaddr, *old_addr;
- GElf_Addr minsize = ~(GElf_Addr) 0;
- int movesec = -1, last, k, e;
-
- if (ehdr->e_phoff < phdr[i].p_offset
- || ehdr->e_phoff + (ehdr->e_phnum + 1) * ehdr->e_phentsize
- > phdr[i].p_offset + phdr[i].p_filesz
- || ! readonly_is_movable (dso, ehdr, shdr, j)
- || shdr[j].sh_addr >= phdr[i].p_vaddr + phdr[i].p_filesz)
+ if (addr > shdr[j].sh_offset)
{
- error (0, 0, "%s: No space in ELF segment table to add new ELF segment",
- dso->filename);
- return 0;
- }
+ GElf_Addr start, addstart, endaddr, *old_addr;
+ GElf_Addr minsize = ~(GElf_Addr) 0;
+ int movesec = -1, last, k, e;
+
+ if (ehdr->e_phoff < phdr[i].p_offset
+ || ehdr->e_phoff + (ehdr->e_phnum + 1) * ehdr->e_phentsize
+ > phdr[i].p_offset + phdr[i].p_filesz
+ || ! readonly_is_movable (dso, ehdr, shdr, j)
+ || shdr[j].sh_addr >= phdr[i].p_vaddr + phdr[i].p_filesz)
+ {
+ error (0, 0, "%s: No space in ELF segment table to add new ELF segment",
+ dso->filename);
+ return 0;
+ }
- start = phdr[i].p_vaddr - phdr[i].p_offset + ehdr->e_phoff
- + (ehdr->e_phnum + 1) * ehdr->e_phentsize;
- for (last = 1; last < ehdr->e_shnum; ++last)
- if (! readonly_is_movable (dso, ehdr, shdr, last)
- || shdr[last].sh_addr >= phdr[i].p_vaddr + phdr[i].p_filesz)
- break;
- for (j = 1; j < last; ++j)
- {
- addstart = (start + add->sh_addralign - 1)
- & ~(add->sh_addralign - 1);
- start = (start + shdr[j].sh_addralign - 1)
- & ~(shdr[j].sh_addralign - 1);
- endaddr = -1;
- if (j + 1 < ehdr->e_shnum)
- endaddr = shdr[j + 1].sh_addr;
- if (phdr[i].p_vaddr + phdr[i].p_filesz < endaddr)
- endaddr = phdr[i].p_vaddr + phdr[i].p_filesz;
-
- switch (shdr[j].sh_type)
+ start = phdr[i].p_vaddr - phdr[i].p_offset + ehdr->e_phoff
+ + (ehdr->e_phnum + 1) * ehdr->e_phentsize;
+ for (last = 1; last < ehdr->e_shnum; ++last)
+ if (! readonly_is_movable (dso, ehdr, shdr, last)
+ || shdr[last].sh_addr >= phdr[i].p_vaddr + phdr[i].p_filesz)
+ break;
+ for (j = 1; j < last; ++j)
{
- case SHT_HASH:
- case SHT_GNU_HASH:
- case SHT_DYNSYM:
- case SHT_STRTAB:
- case SHT_GNU_verdef:
- case SHT_GNU_verneed:
- case SHT_GNU_versym:
- case SHT_GNU_LIBLIST:
- if (endaddr >= start
- && endaddr - start < minsize)
- {
- minsize = endaddr - start;
- movesec = j;
- }
- if (endaddr > addstart
- && endaddr - addstart > add->sh_size
- && endaddr - addstart - add->sh_size
- < minsize)
+ addstart = (start + add->sh_addralign - 1)
+ & ~(add->sh_addralign - 1);
+ start = (start + shdr[j].sh_addralign - 1)
+ & ~(shdr[j].sh_addralign - 1);
+ endaddr = -1;
+ if (j + 1 < ehdr->e_shnum)
+ endaddr = shdr[j + 1].sh_addr;
+ if (phdr[i].p_vaddr + phdr[i].p_filesz < endaddr)
+ endaddr = phdr[i].p_vaddr + phdr[i].p_filesz;
+
+ switch (shdr[j].sh_type)
{
- minsize = endaddr - addstart - add->sh_size;
- movesec = j;
- }
- break;
- case SHT_REL:
- case SHT_RELA:
- case SHT_NOTE:
- /* Don't allow inserting in between reloc sections
- if they are adjacent. Similarly for adjacent
- note sections. */
- if (j + 1 < ehdr->e_shnum)
- {
- if (shdr[j].sh_type == SHT_NOTE)
+ case SHT_HASH:
+ case SHT_GNU_HASH:
+ case SHT_DYNSYM:
+ case SHT_STRTAB:
+ case SHT_GNU_verdef:
+ case SHT_GNU_verneed:
+ case SHT_GNU_versym:
+ case SHT_GNU_LIBLIST:
+ if (endaddr >= start
+ && endaddr - start < minsize)
+ {
+ minsize = endaddr - start;
+ movesec = j;
+ }
+ if (endaddr > addstart
+ && endaddr - addstart > add->sh_size
+ && endaddr - addstart - add->sh_size
+ < minsize)
+ {
+ minsize = endaddr - addstart - add->sh_size;
+ movesec = j;
+ }
+ break;
+ case SHT_REL:
+ case SHT_RELA:
+ case SHT_NOTE:
+ /* Don't allow inserting in between reloc sections
+ if they are adjacent. Similarly for adjacent
+ note sections. */
+ if (j + 1 < ehdr->e_shnum)
{
- if (shdr[j + 1].sh_type != SHT_NOTE)
+ if (shdr[j].sh_type == SHT_NOTE)
+ {
+ if (shdr[j + 1].sh_type != SHT_NOTE)
+ break;
+ }
+ else if (shdr[j + 1].sh_type != SHT_REL
+ && shdr[j + 1].sh_type != SHT_RELA)
+ {
+ break;
+ }
+
+ if ((shdr[j].sh_addr
+ + ((shdr[j].sh_size + 3) & -4))
+ != shdr[j + 1].sh_addr)
break;
- }
- else if (shdr[j + 1].sh_type != SHT_REL
- && shdr[j + 1].sh_type != SHT_RELA)
- {
- break;
- }
- if ((shdr[j].sh_addr
- + ((shdr[j].sh_size + 3) & -4))
- != shdr[j + 1].sh_addr)
- break;
+ start += shdr[j].sh_size;
+ continue;
+ }
+ break;
+ }
- start += shdr[j].sh_size;
- continue;
- }
- break;
+ if (start + shdr[j].sh_size <= endaddr)
+ {
+ movesec = j + 1;
+ break;
+ }
+ start += shdr[j].sh_size;
}
- if (start + shdr[j].sh_size <= endaddr)
+ if (movesec == -1)
{
- movesec = j + 1;
- break;
+ error (0, 0, "%s: No space in ELF segment table to add new ELF segment",
+ dso->filename);
+ return 0;
}
- start += shdr[j].sh_size;
- }
- if (movesec == -1)
- {
- error (0, 0, "%s: No space in ELF segment table to add new ELF segment",
- dso->filename);
- return 0;
- }
-
- start = phdr[i].p_vaddr - phdr[i].p_offset + ehdr->e_phoff
- + (ehdr->e_phnum + 1) * ehdr->e_phentsize;
- old_addr = (GElf_Addr *) alloca (movesec * sizeof (GElf_Addr));
- for (k = 1; k < movesec; ++k)
- {
- start = (start + shdr[k].sh_addralign - 1)
- & ~(shdr[k].sh_addralign - 1);
- old_addr[k] = shdr[k].sh_addr;
- shdr[k].sh_addr = start;
- shdr[k].sh_offset = start + phdr[i].p_offset
- - phdr[i].p_vaddr;
- start += shdr[k].sh_size;
- }
-
- for (e = 0; e < ehdr->e_phnum; ++e)
- if (phdr[e].p_type != PT_LOAD
- && phdr[e].p_type != PT_GNU_STACK)
+ start = phdr[i].p_vaddr - phdr[i].p_offset + ehdr->e_phoff
+ + (ehdr->e_phnum + 1) * ehdr->e_phentsize;
+ old_addr = (GElf_Addr *) alloca (movesec * sizeof (GElf_Addr));
for (k = 1; k < movesec; ++k)
- if (old_addr[k] == phdr[e].p_vaddr)
- {
- if (phdr[e].p_filesz != shdr[k].sh_size
- || phdr[e].p_memsz != shdr[k].sh_size)
+ {
+ start = (start + shdr[k].sh_addralign - 1)
+ & ~(shdr[k].sh_addralign - 1);
+ old_addr[k] = shdr[k].sh_addr;
+ shdr[k].sh_addr = start;
+ shdr[k].sh_offset = start + phdr[i].p_offset
+ - phdr[i].p_vaddr;
+ start += shdr[k].sh_size;
+ }
+
+ for (e = 0; e < ehdr->e_phnum; ++e)
+ if (phdr[e].p_type != PT_LOAD
+ && phdr[e].p_type != PT_GNU_STACK)
+ for (k = 1; k < movesec; ++k)
+ if (old_addr[k] == phdr[e].p_vaddr)
{
- int k1 = -1;
- if (phdr[e].p_type == PT_NOTE
- && shdr[k].sh_type == SHT_NOTE
- && phdr[e].p_filesz == phdr[e].p_memsz)
+ if (phdr[e].p_filesz != shdr[k].sh_size
+ || phdr[e].p_memsz != shdr[k].sh_size)
{
- k1 = k;
- while (k1 < movesec)
+ int k1 = -1;
+ if (phdr[e].p_type == PT_NOTE
+ && shdr[k].sh_type == SHT_NOTE
+ && phdr[e].p_filesz == phdr[e].p_memsz)
{
- if (shdr[k1].sh_type != SHT_NOTE
- || shdr[k1].sh_addr - old_addr[k1]
- != shdr[k].sh_addr - old_addr[k]
- || old_addr[k1] + shdr[k1].sh_size
- > phdr[e].p_vaddr + phdr[e].p_filesz)
+ k1 = k;
+ while (k1 < movesec)
{
- k1 = -1;
- break;
+ if (shdr[k1].sh_type != SHT_NOTE
+ || shdr[k1].sh_addr - old_addr[k1]
+ != shdr[k].sh_addr - old_addr[k]
+ || old_addr[k1] + shdr[k1].sh_size
+ > phdr[e].p_vaddr + phdr[e].p_filesz)
+ {
+ k1 = -1;
+ break;
+ }
+ if (old_addr[k1] + shdr[k1].sh_size
+ == phdr[e].p_vaddr + phdr[e].p_filesz)
+ break;
+ ++k1;
}
- if (old_addr[k1] + shdr[k1].sh_size
- == phdr[e].p_vaddr + phdr[e].p_filesz)
- break;
- ++k1;
+ if (k1 == movesec)
+ k1 = -1;
+ }
+ if (k1 == -1)
+ {
+ error (0, 0, "%s: Non-PT_LOAD segment spanning more than one section",
+ dso->filename);
+ return 0;
}
- if (k1 == movesec)
- k1 = -1;
- }
- if (k1 == -1)
- {
- error (0, 0, "%s: Non-PT_LOAD segment spanning more than one section",
- dso->filename);
- return 0;
}
+ phdr[e].p_vaddr += shdr[k].sh_addr - old_addr[k];
+ phdr[e].p_paddr += shdr[k].sh_addr - old_addr[k];
+ phdr[e].p_offset += shdr[k].sh_addr - old_addr[k];
+ break;
}
- phdr[e].p_vaddr += shdr[k].sh_addr - old_addr[k];
- phdr[e].p_paddr += shdr[k].sh_addr - old_addr[k];
- phdr[e].p_offset += shdr[k].sh_addr - old_addr[k];
- break;
- }
-
- if (j < last)
- /* Now continue as if there was place for a new PT_LOAD
- in ElfW(Phdr) table initially. */
- break;
- else
- {
- GElf_Shdr moveshdr;
- int newidx, ret, movedidx, oldidx;
-
- moveshdr = shdr[movesec];
- newidx = remove_readonly_section (ehdr, shdr, movesec, adjust);
- oldidx = adjust->move->new_to_old[movesec];
- remove_section (adjust->move, movesec);
- ret = find_readonly_space (dso, add, ehdr, phdr, shdr, adjust);
- if (ret == 0)
- return 0;
- movedidx = find_readonly_space (dso, &moveshdr, ehdr, phdr,
- shdr, adjust);
- if (movedidx == 0)
- return 0;
- if (newidx != -1)
- adjust->new[newidx] = movedidx;
- add_section (adjust->move, movedidx);
- if (oldidx != -1)
+
+ if (j < last)
+ /* Now continue as if there was place for a new PT_LOAD
+ in ElfW(Phdr) table initially. */
+ break;
+ else
{
- adjust->move->old_to_new[oldidx] = movedidx;
- adjust->move->new_to_old[movedidx] = oldidx;
+ GElf_Shdr moveshdr;
+ int newidx, ret, movedidx, oldidx;
+
+ moveshdr = shdr[movesec];
+ newidx = remove_readonly_section (ehdr, shdr, movesec, adjust);
+ oldidx = adjust->move->new_to_old[movesec];
+ remove_section (adjust->move, movesec);
+ ret = find_readonly_space (dso, add, ehdr, phdr, shdr, adjust);
+ if (ret == 0)
+ return 0;
+ movedidx = find_readonly_space (dso, &moveshdr, ehdr, phdr,
+ shdr, adjust);
+ if (movedidx == 0)
+ return 0;
+ if (newidx != -1)
+ adjust->new[newidx] = movedidx;
+ add_section (adjust->move, movedidx);
+ if (oldidx != -1)
+ {
+ adjust->move->old_to_new[oldidx] = movedidx;
+ adjust->move->new_to_old[movedidx] = oldidx;
+ }
+ if (movedidx <= ret)
+ ++ret;
+ return ret;
}
- if (movedidx <= ret)
- ++ret;
- return ret;
}
}
}
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 15cbd0e..d9f4d7d 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);
@@ -269,7 +269,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);
@@ -304,7 +304,7 @@ prelink_verify (const char *filename)
if (prelink (dso2, ent))
goto failure_unlink;
- unlink (ent->filename);
+ wrap_unlink (ent->filename);
if (write_dso (dso2))
goto failure;
@@ -412,6 +412,9 @@ prelink_verify (const char *filename)
if (handle_verify (fdundone, filename))
goto failure;
+ fsync (fd);
+ fsync (fdorig);
+ fsync (fdundone);
close (fd);
close (fdorig);
close (fdundone);
@@ -421,11 +424,20 @@ failure_unlink:
unlink (ent->filename);
failure:
if (fd != -1)
- close (fd);
+ {
+ fsync (fd);
+ close (fd);
+ }
if (fdorig != -1)
- close (fdorig);
+ {
+ fsync (fdorig);
+ close (fdorig);
+ }
if (fdundone != -1)
- close (fdundone);
+ {
+ fsync (fdundone);
+ close (fdundone);
+ }
if (dso)
close_dso (dso);
if (dso2)
@@ -435,11 +447,12 @@ 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))
return EXIT_FAILURE;
+ fsync (fd);
close (fd);
return 0;
}
diff --git a/trunk/src/wrap-file.c b/trunk/src/wrap-file.c
new file mode 100644
index 0000000..20f4a13
--- /dev/null
+++ b/trunk/src/wrap-file.c
@@ -0,0 +1,317 @@
+/* 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 <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
+
+extern char *canon_filename (const char *name, int nested, struct stat64 *stp,
+ const char *chroot, int allow_last_link,
+ int allow_missing);
+
+const char *sysroot;
+
+char *
+sysroot_file_name (const char *name, int allow_last_link)
+{
+ struct stat64 st;
+ char *ret;
+
+ if (sysroot == NULL)
+ return (char *) name;
+
+ ret = canon_filename (name, 0, &st, sysroot, allow_last_link, 1);
+
+ if (ret == NULL)
+ /* That will have set errno. */
+ return NULL;
+
+ return ret;
+}
+
+char *
+unsysroot_file_name (const 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;
+}
+
+static int
+wrap_stat_body (const char *file, struct stat64 *buf, int lstat)
+{
+ char* file_copy;
+ char *tmpname;
+ int ret;
+ int len;
+
+ tmpname = sysroot_file_name (file, lstat);
+
+ 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 (len && (file_copy[len - 1] == '/' || file_copy[len - 1] == '\\'))
+ file_copy[len - 1] = '\0';
+
+ ret = lstat ? lstat64 (file_copy, buf) : stat64 (file_copy, buf);
+
+ free (file_copy);
+
+ return ret;
+}
+
+int
+wrap_lstat64 (const char *file, struct stat64 *buf)
+{
+ return wrap_stat_body (file, buf, 1);
+}
+
+int
+wrap_stat64 (const char *file, struct stat64 *buf)
+{
+ return wrap_stat_body (file, buf, 0);
+}
+
+int
+wrap_rename (const char *old, const char *new)
+{
+ char *tmpold = sysroot_file_name (old, 1);
+ char *tmpnew;
+ int ret;
+
+ if (tmpold == NULL)
+ return -1;
+
+ tmpnew = sysroot_file_name (new, 1);
+ 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);
+ 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);
+ 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);
+ char *tmpnew;
+ int ret;
+
+ if (tmpold == NULL)
+ return -1;
+
+ tmpnew = sysroot_file_name (new, 1);
+ 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);
+ 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);
+ 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);
+ 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);
+ int ret;
+
+ if (tmpname == NULL)
+ return -1;
+
+ ret = unlink (tmpname);
+
+ if (tmpname != filename)
+ free (tmpname);
+ return ret;
+}
+
+int
+wrap_readlink (const char *path, char *buf, int len)
+{
+ char *tmpname = sysroot_file_name (path, 1);
+ int ret;
+
+ if (tmpname == NULL)
+ return -1;
+
+ ret = readlink (tmpname, buf, len);
+
+ if (tmpname != path)
+ free (tmpname);
+ return ret;
+}
+
diff --git a/trunk/testsuite/Makefile.in b/trunk/testsuite/Makefile.in
index 30eeeb5..395899f 100644
--- a/trunk/testsuite/Makefile.in
+++ b/trunk/testsuite/Makefile.in
@@ -162,7 +162,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 "*) \
@@ -174,16 +176,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 c99f198..33f876d 100755
--- a/trunk/testsuite/cxx1.sh
+++ b/trunk/testsuite/cxx1.sh
@@ -12,7 +12,9 @@ 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
[ $( grep ^`echo $PRELINK | sed 's/ .*$/: /'` cxx1.log | grep 'Removing C++ conflict' | wc -l ) -ge 5 ] || exit 3
-LD_LIBRARY_PATH=. ./cxx1 || exit 4
+if [ "x$CROSS" = "x" ]; then
+ LD_LIBRARY_PATH=. ./cxx1 || exit 4
+fi
readelf -a ./cxx1 >> cxx1.log 2>&1 || exit 5
# 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 b999786..1d64941 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
-c quick2.tree/etc/prelink.conf.d/*.conf
@@ -177,12 +187,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
@@ -205,12 +227,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 42bb63f..2a75717 100755
--- a/trunk/testsuite/reloc2.sh
+++ b/trunk/testsuite/reloc2.sh
@@ -19,12 +19,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 4bc8cff..2caaf64 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\\t\"\n");
printf (" \".previous\");\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 9820d12..af3aa26 100755
--- a/trunk/testsuite/reloc8.sh
+++ b/trunk/testsuite/reloc8.sh
@@ -1,11 +1,13 @@
#!/bin/bash
. `dirname $0`/functions.sh
# Disable this test under SELinux
-if test -x /usr/sbin/getenforce; then
+if [ "x$CROSS" = "x" ]; then
+ if test -x /usr/sbin/getenforce; then
case "`/usr/sbin/getenforce 2>/dev/null`" in
Permissive|Disabled) ;;
*) exit 77 ;;
esac
+ fi
fi
rm -f reloc8 reloc8lib*.so reloc8.log
rm -f prelink.cache
@@ -22,7 +24,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 a835f89..8c48fa7 100755
--- a/trunk/testsuite/reloc9.sh
+++ b/trunk/testsuite/reloc9.sh
@@ -1,11 +1,13 @@
#!/bin/bash
. `dirname $0`/functions.sh
# Disable this test under SELinux
-if test -x /usr/sbin/getenforce; then
+if [ "x$CROSS" = "x" ]; then
+ if test -x /usr/sbin/getenforce; then
case "`/usr/sbin/getenforce 2>/dev/null`" in
Permissive|Disabled) ;;
*) exit 77 ;;
esac
+ fi
fi
rm -f reloc9 reloc9lib*.so reloc9.log
rm -f prelink.cache
@@ -22,7 +24,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 4d761d4..ed1af21 100644
--- a/trunk/testsuite/shuffle2.c
+++ b/trunk/testsuite/shuffle2.c
@@ -16,7 +16,14 @@ int main()
exit (0);
}
+#ifdef __arm__
+asm (".section nonalloced,\"aw\",%nobits\n\t"
+ ".globl testzero\n\t"
+ "testzero: .skip 16384\n\t"
+ ".previous");
+#else
asm (".section nonalloced,\"aw\",@nobits\n\t"
".globl testzero\n\t"
"testzero: .skip 16384\n\t"
".previous");
+#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 00dde00..6bb1f95 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*|arm*) SHFLAGS=-fpic;; # Does not support non-pic shared libs
@@ -28,7 +28,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