diff options
-rw-r--r-- | trunk/ChangeLog | 109 | ||||
-rw-r--r-- | trunk/m4/libelf.m4 | 3 | ||||
-rw-r--r-- | trunk/src/arch-ppc.c | 54 | ||||
-rw-r--r-- | trunk/src/arch-ppc64.c | 63 | ||||
-rw-r--r-- | trunk/src/arch-s390.c | 116 | ||||
-rw-r--r-- | trunk/src/arch-x86_64.c | 1 | ||||
-rw-r--r-- | trunk/src/dso.c | 68 | ||||
-rw-r--r-- | trunk/src/dwarf2.c | 310 | ||||
-rw-r--r-- | trunk/src/dwarf2.h | 37 | ||||
-rw-r--r-- | trunk/src/execstack.c | 8 | ||||
-rw-r--r-- | trunk/src/prelink.h | 12 | ||||
-rw-r--r-- | trunk/src/undo.c | 13 | ||||
-rw-r--r-- | trunk/src/verify.c | 10 | ||||
-rw-r--r-- | trunk/testsuite/ifunc.h | 34 | ||||
-rwxr-xr-x | trunk/testsuite/reloc2.sh | 7 | ||||
-rwxr-xr-x | trunk/testsuite/reloc8.sh | 9 | ||||
-rwxr-xr-x | trunk/testsuite/reloc9.sh | 9 | ||||
-rwxr-xr-x | trunk/testsuite/tls3.sh | 7 |
18 files changed, 673 insertions, 197 deletions
diff --git a/trunk/ChangeLog b/trunk/ChangeLog index a5c0c5e..df5308b 100644 --- a/trunk/ChangeLog +++ b/trunk/ChangeLog @@ -1,3 +1,112 @@ +2010-04-13 Jakub Jelinek <jakub@redhat.com> + + * testsuite/reloc8.sh: Don't use -Wl,-z,nocopyreloc on + sparc64. + * testsuite/reloc9.sh: Likewise. + + * src/dwarf2.c (DEBUG_TYPES): Define. + (debug_sections): Add .debug_types entry. + (read_abbrev): Handle new DWARF4 forms. + (adjust_attributes): DW_AT_segment can be a loclistptr. + DW_AT_byte_size, DW_AT_bit_offset, DW_AT_bit_size, + DW_AT_string_length, DW_AT_lower_bound, DW_AT_return_addr, + DW_AT_bit_stride, DW_AT_upper_bound, DW_AT_count, + DW_AT_segment, DW_AT_static_link, DW_AT_use_location, + DW_AT_allocated, DW_AT_associated, DW_AT_data_location + and DW_AT_byte_stride can be exprloc. Handle new DWARF4 forms. + (adjust_dwarf2_line): Handle adjusting DWARF4 .debug_line + sections. + (adjust_dwarf2_frame): Handle adjusting DWARF4 .debug_frame + section. + (adjust_dwarf2_info): New function, moved from adjust_dwarf2. + Handle DWARF4 .debug_info and handle .debug_types too. + (adjust_dwarf2): Call it for .debug_info and .debug_types + sections. + * src/dwarf2.h (DW_TAG_type_unit, DW_TAG_rvalue_reference_type, + DW_TAG_template_alias, DW_FORM_sec_offset, DW_FORM_exprloc, + DW_FORM_flag_present, DW_FORM_ref_sig8, DW_AT_bit_stride, + DW_AT_byte_stride, DW_AT_description, DW_AT_binary_scale, + DW_AT_decimal_scale, DW_AT_small, DW_AT_decimal_sign, + DW_AT_digit_count, DW_AT_picture_string, DW_AT_mutable, + DW_AT_threads_scaled, DW_AT_explicit, DW_AT_object_pointer, + DW_AT_endianity, DW_AT_elemental, DW_AT_pure, DW_AT_recursive, + DW_AT_signature, DW_AT_main_subprogram, DW_AT_data_bit_offset, + DW_AT_const_expr, DW_AT_enum_class, DW_AT_linkage_name, + DW_LNS_set_prologue_end, DW_LNS_set_epilogue_begin, + DW_LNS_set_isa, DW_LNE_set_discriminator, DW_LANG_Python): Define. + + * src/prelink.h (send_file): New prototype. + * src/execstack.c (send_file): New dummy function. + * src/verify.c (send_file): No longer static. Don't loop forever + if write or read return 0. + * src/undo.c (prelink_undo): If undo_output is -, use /tmp/undo + instead of - as temp file prefix. + * src/dso.c (set_security_context): Drop unused dso argument, add + ignore_errors argument. If it is non-zero, don't error if + setfilecon failed. + (update_dso): If orig_name is non-NULL, don't error if fchown or + fchmod fails. If rename fails or name1 is - and orig_name is + non-NULL, copy the temporary file to name1 (or to stdout if + name1 is -) instead of failing. + +2010-01-06 Jakub Jelinek <jakub@redhat.com> + + * src/arch-s390.c (s390_prelink_conflict_rela) <case R_390_PC32DBL>: + Ensure negative addends are sign-extended to 64-bits, instead of + zero-extended. + +2010-01-05 Jakub Jelinek <jakub@redhat.com> + + * src/arch-s390.c (s390_prelink_rela, s390_apply_rela, + s390_prelink_conflict_rela, s390_prelink_conflict_rela, + s390_undo_prelink_rela, s390_reloc_size): Handle + R_390_{PC32DBL,16,PC16,PC16DBL,8} relocs. + +2009-12-16 Jakub Jelinek <jakub@redhat.com> + + * testsuite/reloc2.sh: Don't assume textrel works if getenforce + exists, but doesn't print Permissive or Disabled. + * testsuite/reloc8.sh: Likewise. + * testsuite/reloc9.sh: Likewise. + * testsuite/tls3.sh: Likewise. + +2009-11-03 Jakub Jelinek <jakub@redhat.com> + + * src/arch-x86_64.c (x86_64_reloc_size): Handle R_X86_64_IRELATIVE. + + * src/prelink.h (R_PPC_IRELATIVE, R_PPC64_IRELATIVE, + R_PPC64_JMP_IREL): Define if not defined. + * src/undo.c (undo_sections, prelink_undo): Allow .iplt section to + change from SHT_NOBITS to SHT_PROGBITS. + * src/arch-ppc.c (ppc_adjust_rela, ppc_prelink_rela, + ppc_apply_conflict_rela, ppc_undo_prelink_rela): Handle + R_PPC_IRELATIVE. + (ppc_prelink_conflict_rela): Handle R_PPC_IRELATIVE and + conflict->ifunc conflicts. + * src/arch-ppc64.c (ppc64_adjust_rela, ppc64_prelink_rela, + ppc64_undo_prelink_rela): Handle R_PPC64_IRELATIVE and + R_PPC64_JMP_IREL. + (ppc64_apply_conflict_rela, ppc64_reloc_size): Handle + R_PPC64_IRELATIVE. + (ppc64_prelink_conflict_rela): Handle R_PPC64_IRELATIVE, + R_PPC64_JMP_IREL and conflict->ifunc conflicts. + * testsuite/ifunc.h (IFUNC_ASM): Add powerpc definition. + (IFUNC_DECL): Define. + (IFUNC): Use IFUNC_DECL. + +2009-10-19 Joseph Myers <joseph@codesourcery.com> + + * src/conflict.c (prelink_build_conflicts): Use >= not > to + determine whether a relocation points outside the first bss + section. + + * m4/libelf.m4: Resync with version of code in aclocal.m4. + +2009-09-25 Jakub Jelinek <jakub@redhat.com> + + * src/dwarf2.c (adjust_location_list) <case DW_OP_implicit_value>: Add + missing break statement. + 2009-08-06 Joseph Myers <joseph@codesourcery.com> * src/dwarf2.c (dwarf2_write_le64, dwarf2_write_be64): Shift by 56 diff --git a/trunk/m4/libelf.m4 b/trunk/m4/libelf.m4 index 7e80a5d..1156e34 100644 --- a/trunk/m4/libelf.m4 +++ b/trunk/m4/libelf.m4 @@ -73,7 +73,8 @@ int main (void) Elf64_Addr val; Elf_Scn *scn; - fd = open ("conflibelftest", O_RDWR | O_CREAT | O_EXCL); if (fd == -1) exit (1); + fd = open ("conflibelftest", O_RDWR | O_CREAT | O_EXCL, 0600); + if (fd == -1) exit (1); unlink ("conflibelftest"); if (write (fd, sparc64_elf, sizeof(sparc64_elf)) != sizeof(sparc64_elf)) exit (1); diff --git a/trunk/src/arch-ppc.c b/trunk/src/arch-ppc.c index 99dbea5..ad3961e 100644 --- a/trunk/src/arch-ppc.c +++ b/trunk/src/arch-ppc.c @@ -126,7 +126,8 @@ static int ppc_adjust_rela (DSO *dso, GElf_Rela *rela, GElf_Addr start, GElf_Addr adjust) { - if (GELF_R_TYPE (rela->r_info) == R_PPC_RELATIVE) + if (GELF_R_TYPE (rela->r_info) == R_PPC_RELATIVE + || GELF_R_TYPE (rela->r_info) == R_PPC_IRELATIVE) { if ((Elf32_Word) rela->r_addend >= start) rela->r_addend += (Elf32_Sword) adjust; @@ -206,7 +207,8 @@ ppc_prelink_rela (struct prelink_info *info, GElf_Rela *rela, DSO *dso = info->dso; GElf_Addr value; - if (GELF_R_TYPE (rela->r_info) == R_PPC_NONE) + if (GELF_R_TYPE (rela->r_info) == R_PPC_NONE + || GELF_R_TYPE (rela->r_info) == R_PPC_IRELATIVE) return 0; else if (GELF_R_TYPE (rela->r_info) == R_PPC_RELATIVE) { @@ -332,6 +334,7 @@ static int ppc_apply_conflict_rela (struct prelink_info *info, GElf_Rela *rela, char *buf, GElf_Addr dest_addr) { + GElf_Rela *ret; switch (GELF_R_TYPE (rela->r_info)) { case R_PPC_ADDR32: @@ -342,6 +345,16 @@ ppc_apply_conflict_rela (struct prelink_info *info, GElf_Rela *rela, case R_PPC_UADDR16: buf_write_be16 (buf, rela->r_addend); break; + case R_PPC_IRELATIVE: + if (dest_addr == 0) + return 5; + ret = prelink_conflict_add_rela (info); + if (ret == NULL) + return 1; + ret->r_offset = dest_addr; + ret->r_info = GELF_R_INFO (0, R_PPC_IRELATIVE); + ret->r_addend = rela->r_addend; + break; default: abort (); } @@ -435,16 +448,13 @@ ppc_prelink_conflict_rela (DSO *dso, struct prelink_info *info, int r_type; if (GELF_R_TYPE (rela->r_info) == R_PPC_RELATIVE - || GELF_R_TYPE (rela->r_info) == R_PPC_NONE - || info->dso == dso) + || GELF_R_TYPE (rela->r_info) == R_PPC_NONE) /* Fast path: nothing to do. */ return 0; conflict = prelink_conflict (info, GELF_R_SYM (rela->r_info), GELF_R_TYPE (rela->r_info)); if (conflict == NULL) { - if (info->curtls == NULL) - return 0; switch (GELF_R_TYPE (rela->r_info)) { /* Even local DTPMOD and TPREL relocs need conflicts. */ @@ -454,18 +464,19 @@ ppc_prelink_conflict_rela (DSO *dso, struct prelink_info *info, case R_PPC_TPREL16_LO: case R_PPC_TPREL16_HI: case R_PPC_TPREL16_HA: + if (info->curtls == NULL || info->dso == dso) + return 0; + break; + /* Similarly IRELATIVE relocations always need conflicts. */ + case R_PPC_IRELATIVE: break; default: return 0; } value = 0; } - else if (conflict->ifunc) - { - error (0, 0, "%s: STT_GNU_IFUNC not handled on PowerPC yet", - dso->filename); - return 1; - } + else if (info->dso == dso && !conflict->ifunc) + return 0; else { /* DTPREL wants to see only real conflicts, not lookups @@ -494,13 +505,19 @@ ppc_prelink_conflict_rela (DSO *dso, struct prelink_info *info, { case R_PPC_GLOB_DAT: r_type = R_PPC_ADDR32; - break; case R_PPC_ADDR32: case R_PPC_UADDR32: + case R_PPC_IRELATIVE: + if (conflict != NULL && conflict->ifunc) + r_type = R_PPC_IRELATIVE; break; case R_PPC_JMP_SLOT: if (dynamic_info_is_set (dso, DT_PPC_GOT_BIT)) - r_type = R_PPC_ADDR32; + { + r_type = R_PPC_ADDR32; + if (conflict != NULL && conflict->ifunc) + r_type = R_PPC_IRELATIVE; + } break; case R_PPC_ADDR16_HA: value += 0x8000; @@ -606,6 +623,12 @@ ppc_prelink_conflict_rela (DSO *dso, struct prelink_info *info, r_type); return 1; } + if (conflict != NULL && conflict->ifunc && r_type != R_PPC_IRELATIVE) + { + error (0, 0, "%s: relocation %d against IFUNC symbol", dso->filename, + (int) GELF_R_TYPE (rela->r_info)); + return 1; + } ret->r_info = GELF_R_INFO (0, r_type); ret->r_addend = (Elf32_Sword) value; return 0; @@ -777,6 +800,9 @@ ppc_undo_prelink_rela (DSO *dso, GElf_Rela *rela, GElf_Addr relaaddr) otherwise .plt section will be unprelinked in ppc_arch_undo_prelink. */ return 0; + case R_PPC_IRELATIVE: + /* .iplt section will become SHT_NOBITS. */ + return 0; case R_PPC_ADDR16: case R_PPC_UADDR16: case R_PPC_ADDR16_LO: diff --git a/trunk/src/arch-ppc64.c b/trunk/src/arch-ppc64.c index 6f9f644..a764b99 100644 --- a/trunk/src/arch-ppc64.c +++ b/trunk/src/arch-ppc64.c @@ -83,7 +83,8 @@ static int ppc64_adjust_rela (DSO *dso, GElf_Rela *rela, GElf_Addr start, GElf_Addr adjust) { - if (GELF_R_TYPE (rela->r_info) == R_PPC64_RELATIVE) + if (GELF_R_TYPE (rela->r_info) == R_PPC64_RELATIVE + || GELF_R_TYPE (rela->r_info) == R_PPC64_IRELATIVE) { GElf_Addr val = read_ube64 (dso, rela->r_offset); @@ -92,6 +93,11 @@ ppc64_adjust_rela (DSO *dso, GElf_Rela *rela, GElf_Addr start, if (rela->r_addend >= start) rela->r_addend += adjust; } + else if (GELF_R_TYPE (rela->r_info) == R_PPC64_JMP_IREL) + { + if (rela->r_addend >= start) + rela->r_addend += adjust; + } return 0; } @@ -162,7 +168,9 @@ ppc64_prelink_rela (struct prelink_info *info, GElf_Rela *rela, DSO *dso = info->dso; GElf_Addr value; - if (GELF_R_TYPE (rela->r_info) == R_PPC64_NONE) + if (GELF_R_TYPE (rela->r_info) == R_PPC64_NONE + || GELF_R_TYPE (rela->r_info) == R_PPC64_IRELATIVE + || GELF_R_TYPE (rela->r_info) == R_PPC64_JMP_IREL) return 0; else if (GELF_R_TYPE (rela->r_info) == R_PPC64_RELATIVE) { @@ -308,6 +316,7 @@ static int ppc64_apply_conflict_rela (struct prelink_info *info, GElf_Rela *rela, char *buf, GElf_Addr dest_addr) { + GElf_Rela *ret; switch (GELF_R_TYPE (rela->r_info)) { case R_PPC64_ADDR64: @@ -322,6 +331,16 @@ ppc64_apply_conflict_rela (struct prelink_info *info, GElf_Rela *rela, case R_PPC64_UADDR16: buf_write_be16 (buf, rela->r_addend); break; + case R_PPC64_IRELATIVE: + if (dest_addr == 0) + return 5; + ret = prelink_conflict_add_rela (info); + if (ret == NULL) + return 1; + ret->r_offset = dest_addr; + ret->r_info = GELF_R_INFO (0, R_PPC64_IRELATIVE); + ret->r_addend = rela->r_addend; + break; default: abort (); } @@ -439,16 +458,13 @@ ppc64_prelink_conflict_rela (DSO *dso, struct prelink_info *info, int r_type; if (GELF_R_TYPE (rela->r_info) == R_PPC64_RELATIVE - || GELF_R_TYPE (rela->r_info) == R_PPC64_NONE - || info->dso == dso) + || GELF_R_TYPE (rela->r_info) == R_PPC64_NONE) /* Fast path: nothing to do. */ return 0; conflict = prelink_conflict (info, GELF_R_SYM (rela->r_info), GELF_R_TYPE (rela->r_info)); if (conflict == NULL) { - if (info->curtls == NULL) - return 0; switch (GELF_R_TYPE (rela->r_info)) { /* Even local DTPMOD and TPREL relocs need conflicts. */ @@ -458,18 +474,20 @@ ppc64_prelink_conflict_rela (DSO *dso, struct prelink_info *info, case R_PPC64_TPREL16_LO: case R_PPC64_TPREL16_HI: case R_PPC64_TPREL16_HA: + if (info->curtls == NULL || info->dso == dso) + return 0; + break; + /* Similarly IRELATIVE relocations always need conflicts. */ + case R_PPC64_IRELATIVE: + case R_PPC64_JMP_IREL: break; default: return 0; } value = 0; } - else if (conflict->ifunc) - { - error (0, 0, "%s: STT_GNU_IFUNC not handled on PowerPC64 yet", - dso->filename); - return 1; - } + else if (info->dso == dso && !conflict->ifunc) + return 0; else { /* DTPREL wants to see only real conflicts, not lookups @@ -498,10 +516,17 @@ ppc64_prelink_conflict_rela (DSO *dso, struct prelink_info *info, { case R_PPC64_GLOB_DAT: r_type = R_PPC64_ADDR64; - break; case R_PPC64_ADDR64: case R_PPC64_UADDR64: + if (conflict != NULL && conflict->ifunc) + r_type = R_PPC64_IRELATIVE; + break; + case R_PPC64_IRELATIVE: + case R_PPC64_JMP_IREL: + break; case R_PPC64_JMP_SLOT: + if (conflict != NULL && conflict->ifunc) + r_type = R_PPC64_JMP_IREL; break; case R_PPC64_ADDR32: case R_PPC64_UADDR32: @@ -640,6 +665,13 @@ ppc64_prelink_conflict_rela (DSO *dso, struct prelink_info *info, r_type); return 1; } + if (conflict != NULL && conflict->ifunc + && r_type != R_PPC64_IRELATIVE && r_type != R_PPC64_JMP_IREL) + { + error (0, 0, "%s: relocation %d against IFUNC symbol", dso->filename, + (int) GELF_R_TYPE (rela->r_info)); + return 1; + } ret->r_info = GELF_R_INFO (0, r_type); ret->r_addend = value; return 0; @@ -668,8 +700,12 @@ ppc64_undo_prelink_rela (DSO *dso, GElf_Rela *rela, GElf_Addr relaaddr) case R_PPC64_JMP_SLOT: /* .plt section will become SHT_NOBITS. */ return 0; + case R_PPC64_JMP_IREL: + /* .iplt section will become SHT_NOBITS. */ + return 0; case R_PPC64_RELATIVE: case R_PPC64_ADDR64: + case R_PPC64_IRELATIVE: write_be64 (dso, rela->r_offset, rela->r_addend); break; case R_PPC64_GLOB_DAT: @@ -766,6 +802,7 @@ ppc64_reloc_size (int reloc_type) case R_PPC64_DTPMOD64: case R_PPC64_DTPREL64: case R_PPC64_TPREL64: + case R_PPC64_IRELATIVE: return 8; default: break; diff --git a/trunk/src/arch-s390.c b/trunk/src/arch-s390.c index 7907e83..fd076b1 100644 --- a/trunk/src/arch-s390.c +++ b/trunk/src/arch-s390.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001, 2002, 2003, 2004, 2009 Red Hat, Inc. +/* Copyright (C) 2001, 2002, 2003, 2004, 2009, 2010 Red Hat, Inc. Written by Jakub Jelinek <jakub@redhat.com>, 2001. This program is free software; you can redistribute it and/or modify @@ -122,20 +122,40 @@ s390_prelink_rela (struct prelink_info *info, GElf_Rela *rela, } value = info->resolve (info, GELF_R_SYM (rela->r_info), GELF_R_TYPE (rela->r_info)); + value += rela->r_addend; switch (GELF_R_TYPE (rela->r_info)) { case R_390_GLOB_DAT: case R_390_JMP_SLOT: - write_be32 (dso, rela->r_offset, value); + write_be32 (dso, rela->r_offset, value - rela->r_addend); break; case R_390_32: - write_be32 (dso, rela->r_offset, value + rela->r_addend); + write_be32 (dso, rela->r_offset, value); break; case R_390_PC32: - write_be32 (dso, rela->r_offset, value + rela->r_addend - rela->r_offset); + write_be32 (dso, rela->r_offset, value - rela->r_offset); + break; + case R_390_PC32DBL: + case R_390_PLT32DBL: + write_be32 (dso, rela->r_offset, + ((Elf32_Sword) (value - rela->r_offset)) >> 1); + break; + case R_390_16: + write_be16 (dso, rela->r_offset, value); + break; + case R_390_PC16: + write_be16 (dso, rela->r_offset, value - rela->r_offset); + break; + case R_390_PC16DBL: + case R_390_PLT16DBL: + write_be16 (dso, rela->r_offset, + ((int16_t) (value - rela->r_offset)) >> 1); + break; + case R_390_8: + write_8 (dso, rela->r_offset, value); break; case R_390_TLS_DTPOFF: - write_be32 (dso, rela->r_offset, value + rela->r_addend); + write_be32 (dso, rela->r_offset, value); break; /* DTPMOD and TPOFF is impossible to predict in shared libraries unless prelink sets the rules. */ @@ -150,7 +170,7 @@ s390_prelink_rela (struct prelink_info *info, GElf_Rela *rela, case R_390_TLS_TPOFF: if (dso->ehdr.e_type == ET_EXEC && info->resolvetls) write_be32 (dso, rela->r_offset, - value + rela->r_addend - info->resolvetls->offset); + value - info->resolvetls->offset); break; case R_390_COPY: if (dso->ehdr.e_type == ET_EXEC) @@ -175,6 +195,12 @@ s390_apply_conflict_rela (struct prelink_info *info, GElf_Rela *rela, case R_390_32: buf_write_be32 (buf, rela->r_addend); break; + case R_390_16: + buf_write_be16 (buf, rela->r_addend); + break; + case R_390_8: + buf_write_8 (buf, rela->r_addend); + break; default: abort (); } @@ -195,19 +221,37 @@ s390_apply_rela (struct prelink_info *info, GElf_Rela *rela, char *buf) value = info->resolve (info, GELF_R_SYM (rela->r_info), GELF_R_TYPE (rela->r_info)); + value += rela->r_addend; switch (GELF_R_TYPE (rela->r_info)) { case R_390_NONE: break; case R_390_GLOB_DAT: case R_390_JMP_SLOT: - buf_write_be32 (buf, value); + buf_write_be32 (buf, value - rela->r_addend); break; case R_390_32: - buf_write_be32 (buf, value + rela->r_addend); + buf_write_be32 (buf, value); break; case R_390_PC32: - buf_write_be32 (buf, value + rela->r_addend - rela->r_offset); + buf_write_be32 (buf, value - rela->r_offset); + break; + case R_390_PC32DBL: + case R_390_PLT32DBL: + buf_write_be32 (buf, ((Elf32_Sword) (value - rela->r_offset)) >> 1); + break; + case R_390_16: + buf_write_be16 (buf, value); + break; + case R_390_PC16: + buf_write_be16 (buf, value - rela->r_offset); + break; + case R_390_PC16DBL: + case R_390_PLT16DBL: + buf_write_be16 (buf, ((int16_t) (value - rela->r_offset)) >> 1); + break; + case R_390_8: + buf_write_8 (buf, value); break; case R_390_COPY: abort (); @@ -281,17 +325,37 @@ s390_prelink_conflict_rela (DSO *dso, struct prelink_info *info, return 1; ret->r_offset = rela->r_offset; ret->r_info = GELF_R_INFO (0, R_390_32); + value += rela->r_addend; switch (GELF_R_TYPE (rela->r_info)) { case R_390_GLOB_DAT: case R_390_JMP_SLOT: - ret->r_addend = (Elf32_Sword) value; + ret->r_addend = (Elf32_Sword) (value - rela->r_addend); break; case R_390_32: - ret->r_addend = (Elf32_Sword) (value + rela->r_addend); + ret->r_addend = (Elf32_Sword) value; break; case R_390_PC32: - ret->r_addend = (Elf32_Sword) (value + rela->r_addend - rela->r_offset); + ret->r_addend = (Elf32_Sword) (value - rela->r_offset); + break; + case R_390_PC32DBL: + case R_390_PLT32DBL: + ret->r_addend = ((Elf32_Sword) (value - rela->r_offset)) >> 1; + break; + case R_390_PC16: + value -= rela->r_offset; + case R_390_16: + ret->r_addend = (Elf32_Half) value; + ret->r_info = GELF_R_INFO (0, R_390_16); + break; + case R_390_PC16DBL: + case R_390_PLT16DBL: + ret->r_addend = (Elf32_Half) (((int16_t) (value - rela->r_offset)) >> 1); + ret->r_info = GELF_R_INFO (0, R_390_16); + break; + case R_390_8: + ret->r_addend = value & 0xff; + ret->r_info = GELF_R_INFO (0, R_390_8); break; case R_390_COPY: error (0, 0, "R_390_COPY should not be present in shared libraries"); @@ -314,10 +378,10 @@ s390_prelink_conflict_rela (DSO *dso, struct prelink_info *info, ret->r_addend = tls->modid; break; case R_390_TLS_DTPOFF: - ret->r_addend = value + rela->r_addend; + ret->r_addend = value; break; case R_390_TLS_TPOFF: - ret->r_addend = value + rela->r_addend - tls->offset; + ret->r_addend = value - tls->offset; break; } break; @@ -441,11 +505,22 @@ s390_undo_prelink_rela (DSO *dso, GElf_Rela *rela, GElf_Addr relaaddr) case R_390_GLOB_DAT: case R_390_32: case R_390_PC32: + case R_390_PC32DBL: + case R_390_PLT32DBL: case R_390_TLS_DTPMOD: case R_390_TLS_DTPOFF: case R_390_TLS_TPOFF: write_be32 (dso, rela->r_offset, 0); break; + case R_390_16: + case R_390_PC16: + case R_390_PC16DBL: + case R_390_PLT16DBL: + write_be16 (dso, rela->r_offset, 0); + break; + case R_390_8: + write_8 (dso, rela->r_offset, 0); + break; case R_390_COPY: if (dso->ehdr.e_type == ET_EXEC) /* COPY relocs are handled specially in generic code. */ @@ -463,7 +538,18 @@ s390_undo_prelink_rela (DSO *dso, GElf_Rela *rela, GElf_Addr relaaddr) static int s390_reloc_size (int reloc_type) { - return 4; + switch (reloc_type) + { + case R_390_16: + case R_390_PC16: + case R_390_PC16DBL: + case R_390_PLT16DBL: + return 2; + case R_390_8: + return 1; + default: + return 4; + } } static int diff --git a/trunk/src/arch-x86_64.c b/trunk/src/arch-x86_64.c index 83286e9..3830f84 100644 --- a/trunk/src/arch-x86_64.c +++ b/trunk/src/arch-x86_64.c @@ -501,6 +501,7 @@ x86_64_reloc_size (int reloc_type) case R_X86_64_GLOB_DAT: case R_X86_64_JUMP_SLOT: case R_X86_64_64: + case R_X86_64_IRELATIVE: return 8; default: return 4; diff --git a/trunk/src/dso.c b/trunk/src/dso.c index b3b6ee3..8ad93d3 100644 --- a/trunk/src/dso.c +++ b/trunk/src/dso.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 Red Hat, Inc. +/* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2010 Red Hat, Inc. Written by Jakub Jelinek <jakub@redhat.com>, 2001. This program is free software; you can redistribute it and/or modify @@ -1707,8 +1707,9 @@ write_dso (DSO *dso) return 0; } -int -set_security_context (DSO *dso, const char *temp_name, const char *name) +static int +set_security_context (const char *temp_name, const char *name, + int ignore_errors) { #ifdef USE_SELINUX static int selinux_enabled = -1; @@ -1729,7 +1730,7 @@ set_security_context (DSO *dso, const char *temp_name, const char *name) name); return 1; } - if (setfilecon (temp_name, scontext) < 0) + if (setfilecon (temp_name, scontext) < 0 && !ignore_errors) { error (0, errno, "Could not set security context for %s", name); @@ -1752,6 +1753,7 @@ update_dso (DSO *dso, const char *orig_name) char *name1, *name2; struct utimbuf u; struct stat64 st; + int fdin, fdout; switch (write_dso (dso)) { @@ -1774,30 +1776,80 @@ update_dso (DSO *dso, const char *orig_name) close_dso (dso); return 1; } - if (fchown (dso->fd, st.st_uid, st.st_gid) < 0 - || fchmod (dso->fd, st.st_mode & 07777) < 0) + if ((fchown (dso->fd, st.st_uid, st.st_gid) < 0 + || fchmod (dso->fd, st.st_mode & 07777) < 0) + && orig_name == NULL) { error (0, errno, "Could not set %s owner or mode", dso->filename); close_dso (dso); return 1; } + if (orig_name != NULL) + fdin = dup (dso->fd); + else + fdin = -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)) + if (set_security_context (name2, orig_name ? orig_name : name1, + orig_name != NULL)) { + if (fdin != -1) + close (fdin); wrap_unlink (name2); return 1; } - if (wrap_rename (name2, name1)) + if ((orig_name != NULL && strcmp (name1, "-") == 0) + || wrap_rename (name2, name1)) { + if (fdin != -1) + { + struct stat64 stt; + off_t off = 0; + int err; + if (strcmp (name1, "-") == 0) + fdout = 1; + else + 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) + { + close (fdin); + if (fchown (fdout, st.st_uid, st.st_gid) >= 0) + fchmod (fdout, st.st_mode & 07777); + if (strcmp (name1, "-") != 0) + { + set_security_context (name1, name1, 1); + wrap_utime (name1, &u); + close (fdout); + } + wrap_unlink (name2); + return 0; + } + else if (fdout != -1) + { + err = errno; + if (strcmp (name1, "-") == 0) + close (fdout); + } + else + err = errno; + close (fdin); + wrap_unlink (name2); + error (0, err, "Could not rename nor copy temporary to %s", + name1); + return 1; + } wrap_unlink (name2); error (0, errno, "Could not rename temporary to %s", name1); return 1; } + if (fdin != -1) + close (fdin); } else close_dso_1 (dso); diff --git a/trunk/src/dwarf2.c b/trunk/src/dwarf2.c index e831a18..802d9ad 100644 --- a/trunk/src/dwarf2.c +++ b/trunk/src/dwarf2.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001, 2002, 2003, 2005, 2006, 2009 Red Hat, Inc. +/* Copyright (C) 2001, 2002, 2003, 2005, 2006, 2009, 2010 Red Hat, Inc. Written by Jakub Jelinek <jakub@redhat.com>, 2001. This program is free software; you can redistribute it and/or modify @@ -161,6 +161,7 @@ static struct #define DEBUG_STR 8 #define DEBUG_FRAME 9 #define DEBUG_RANGES 10 +#define DEBUG_TYPES 11 { ".debug_info", NULL, 0, 0 }, { ".debug_abbrev", NULL, 0, 0 }, { ".debug_line", NULL, 0, 0 }, @@ -172,6 +173,7 @@ static struct { ".debug_str", NULL, 0, 0 }, { ".debug_frame", NULL, 0, 0 }, { ".debug_ranges", NULL, 0, 0 }, + { ".debug_types", NULL, 0, 0 }, { NULL, NULL, 0 } }; @@ -271,7 +273,8 @@ no_memory: goto no_memory; } form = read_uleb128 (ptr); - if (form == 2 || form > DW_FORM_indirect) + if (form == 2 + || (form > DW_FORM_flag_present && form != DW_FORM_ref_sig8)) { error (0, 0, "%s: Unknown DWARF DW_FORM_%d", dso->filename, form); htab_delete (h); @@ -392,6 +395,7 @@ adjust_location_list (DSO *dso, unsigned char *ptr, size_t len, uint32_t len = read_uleb128 (ptr); ptr += len; } + break; default: error (0, 0, "%s: Unknown DWARF DW_OP_%d", dso->filename, op); return 1; @@ -537,11 +541,12 @@ adjust_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, case DW_AT_return_addr: case DW_AT_data_member_location: case DW_AT_frame_base: + case DW_AT_segment: case DW_AT_static_link: case DW_AT_use_location: case DW_AT_vtable_elem_location: case DW_AT_ranges: - if (form == DW_FORM_data4) + if (form == DW_FORM_data4 || form == DW_FORM_sec_offset) addr = read_32 (ptr), ptr -= 4; else if (form == DW_FORM_data8) addr = read_64 (ptr), ptr -= 8; @@ -586,6 +591,8 @@ adjust_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, if (addr >= start && addr_to_sec (dso, addr) != -1) write_ptr (ptr - ptr_size, addr + adjust); break; + case DW_FORM_flag_present: + break; case DW_FORM_ref1: case DW_FORM_flag: case DW_FORM_data1: @@ -597,10 +604,12 @@ adjust_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, break; case DW_FORM_ref4: case DW_FORM_data4: + case DW_FORM_sec_offset: ptr += 4; break; case DW_FORM_ref8: case DW_FORM_data8: + case DW_FORM_ref_sig8: ptr += 8; break; case DW_FORM_sdata: @@ -639,6 +648,10 @@ adjust_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, form = DW_FORM_block1; assert (len < UINT_MAX); break; + case DW_FORM_exprloc: + len = read_uleb128 (ptr); + assert (len < UINT_MAX); + break; default: error (0, 0, "%s: Unknown DWARF DW_FORM_%d", dso->filename, form); @@ -653,11 +666,27 @@ adjust_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, case DW_AT_location: case DW_AT_data_member_location: case DW_AT_vtable_elem_location: + case DW_AT_byte_size: + case DW_AT_bit_offset: + case DW_AT_bit_size: + case DW_AT_string_length: + case DW_AT_lower_bound: + case DW_AT_return_addr: + case DW_AT_bit_stride: + case DW_AT_upper_bound: + case DW_AT_count: + case DW_AT_segment: + case DW_AT_static_link: + case DW_AT_use_location: + case DW_AT_allocated: + case DW_AT_associated: + case DW_AT_data_location: + case DW_AT_byte_stride: if (adjust_location_list (dso, ptr, len, start, adjust)) return NULL; break; default: - if (t->attr[i].attr <= DW_AT_call_line + if (t->attr[i].attr <= DW_AT_linkage_name || (t->attr[i].attr >= DW_AT_MIPS_fde && t->attr[i].attr <= DW_AT_MIPS_has_inlines) || (t->attr[i].attr >= DW_AT_sf_names @@ -669,6 +698,12 @@ adjust_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, } ptr += len; } + else if (form == DW_FORM_exprloc) + { + if (adjust_location_list (dso, ptr, len, start, adjust)) + return NULL; + ptr += len; + } break; } @@ -706,7 +741,7 @@ adjust_dwarf2_line (DSO *dso, GElf_Addr start, GElf_Addr adjust) } value = read_16 (ptr); - if (value != 2 && value != 3) + if (value != 2 && value != 3 && value != 4) { error (0, 0, "%s: DWARF version %d unhandled", dso->filename, value); @@ -722,8 +757,8 @@ adjust_dwarf2_line (DSO *dso, GElf_Addr start, GElf_Addr adjust) return 1; } - opcode_base = ptr[4]; - opcode_lengths = ptr + 4; + opcode_base = ptr[4 + (value >= 4)]; + opcode_lengths = ptr + 4 + (value >= 4); ptr = endprol; while (ptr < endcu) @@ -731,7 +766,7 @@ adjust_dwarf2_line (DSO *dso, GElf_Addr start, GElf_Addr adjust) op = *ptr++; if (op >= opcode_base) continue; - if (op == 0) + if (op == DW_LNS_extended_op) { unsigned int len = read_uleb128 (ptr); @@ -746,6 +781,7 @@ adjust_dwarf2_line (DSO *dso, GElf_Addr start, GElf_Addr adjust) break; case DW_LNE_end_sequence: case DW_LNE_define_file: + case DW_LNE_set_discriminator: default: ptr += len - 1; break; @@ -855,7 +891,7 @@ adjust_dwarf2_frame (DSO *dso, GElf_Addr start, GElf_Addr adjust) { /* CIE. */ uint32_t version = *ptr++; - if (version != 1 && version != 3) + if (version != 1 && version != 3 && version != 4) { error (0, 0, "%s: unhandled .debug_frame version %d", dso->filename, version); @@ -868,6 +904,22 @@ adjust_dwarf2_frame (DSO *dso, GElf_Addr start, GElf_Addr adjust) return 1; } ptr++; /* Skip augmentation. */ + if (version >= 4) + { + if (ptr[0] != ptr_size) + { + error (0, 0, "%s: .debug_frame unhandled pointer size %d", + dso->filename, ptr[0]); + return 1; + } + if (ptr[1] != 0) + { + error (0, 0, "%s: .debug_frame unhandled non-zero segment size", + dso->filename); + return 1; + } + ptr += 2; + } read_uleb128 (ptr); /* Skip code_alignment factor. */ read_uleb128 (ptr); /* Skip data_alignment factor. */ if (version >= 3) @@ -958,13 +1010,132 @@ adjust_dwarf2_frame (DSO *dso, GElf_Addr start, GElf_Addr adjust) return 0; } +static int +adjust_dwarf2_info (DSO *dso, GElf_Addr start, GElf_Addr adjust, int type) +{ + unsigned char *ptr, *endcu, *endsec; + uint32_t value; + htab_t abbrev; + struct abbrev_tag tag, *t; + struct cu_data cu; + + memset (&cu, 0, sizeof(cu)); + ptr = debug_sections[type].data; + endsec = ptr + debug_sections[type].size; + while (ptr < endsec) + { + if (ptr + 11 > endsec) + { + error (0, 0, "%s: .debug_info CU header too small", dso->filename); + return 1; + } + + endcu = ptr + 4; + endcu += read_32 (ptr); + if (endcu == ptr + 0xffffffff) + { + error (0, 0, "%s: 64-bit DWARF not supported", dso->filename); + return 1; + } + + if (endcu > endsec) + { + error (0, 0, "%s: .debug_info too small", dso->filename); + return 1; + } + + value = read_16 (ptr); + if (value != 2 && value != 3 && value != 4) + { + error (0, 0, "%s: DWARF version %d unhandled", dso->filename, value); + return 1; + } + cu.cu_version = value; + + value = read_32 (ptr); + if (value >= debug_sections[DEBUG_ABBREV].size) + { + if (debug_sections[DEBUG_ABBREV].data == NULL) + error (0, 0, "%s: .debug_abbrev not present", dso->filename); + else + error (0, 0, "%s: DWARF CU abbrev offset too large", + dso->filename); + return 1; + } + + if (ptr_size == 0) + { + ptr_size = read_1 (ptr); + if (ptr_size == 4) + { + do_read_ptr = do_read_32_64; + write_ptr = write_32; + } + else if (ptr_size == 8) + { + do_read_ptr = do_read_64; + write_ptr = write_64; + } + else + { + error (0, 0, "%s: Invalid DWARF pointer size %d", + dso->filename, ptr_size); + return 1; + } + } + else if (read_1 (ptr) != ptr_size) + { + error (0, 0, "%s: DWARF pointer size differs between CUs", + dso->filename); + return 1; + } + + abbrev = read_abbrev (dso, debug_sections[DEBUG_ABBREV].data + value); + if (abbrev == NULL) + return 1; + + cu.cu_entry_pc = ~ (GElf_Addr) 0; + cu.cu_low_pc = ~ (GElf_Addr) 0; + + if (type == DEBUG_TYPES) + { + ptr += 8; /* Skip type_signature. */ + ptr += 4; /* Skip type_offset. */ + } + + while (ptr < endcu) + { + tag.entry = read_uleb128 (ptr); + if (tag.entry == 0) + continue; + t = htab_find_with_hash (abbrev, &tag, tag.entry); + if (t == NULL) + { + error (0, 0, "%s: Could not find DWARF abbreviation %d", + dso->filename, tag.entry); + htab_delete (abbrev); + return 1; + } + + ptr = adjust_attributes (dso, ptr, t, &cu, start, adjust); + if (ptr == NULL) + { + htab_delete (abbrev); + return 1; + } + } + + htab_delete (abbrev); + } + return 0; +} + int adjust_dwarf2 (DSO *dso, int n, GElf_Addr start, GElf_Addr adjust) { Elf_Data *data; Elf_Scn *scn; int i, j; - struct cu_data cu; for (i = 0; debug_sections[i].name; ++i) { @@ -974,7 +1145,6 @@ adjust_dwarf2 (DSO *dso, int n, GElf_Addr start, GElf_Addr adjust) } ptr_size = 0; - memset (&cu, 0, sizeof(cu)); for (i = 1; i < dso->ehdr.e_shnum; ++i) if (! (dso->shdr[i].sh_flags & (SHF_ALLOC | SHF_WRITE | SHF_EXECINSTR)) && dso->shdr[i].sh_size) @@ -1010,6 +1180,7 @@ adjust_dwarf2 (DSO *dso, int n, GElf_Addr start, GElf_Addr adjust) { error (0, 0, "%s: Unknown debugging section %s", dso->filename, name); + return 1; } } } @@ -1038,118 +1209,13 @@ adjust_dwarf2 (DSO *dso, int n, GElf_Addr start, GElf_Addr adjust) return 1; } - if (debug_sections[DEBUG_INFO].data != NULL) - { - unsigned char *ptr, *endcu, *endsec; - uint32_t value; - htab_t abbrev; - struct abbrev_tag tag, *t; - - ptr = debug_sections[DEBUG_INFO].data; - endsec = ptr + debug_sections[DEBUG_INFO].size; - while (ptr < endsec) - { - if (ptr + 11 > endsec) - { - error (0, 0, "%s: .debug_info CU header too small", - dso->filename); - return 1; - } - - endcu = ptr + 4; - endcu += read_32 (ptr); - if (endcu == ptr + 0xffffffff) - { - error (0, 0, "%s: 64-bit DWARF not supported", dso->filename); - return 1; - } - - if (endcu > endsec) - { - error (0, 0, "%s: .debug_info too small", dso->filename); - return 1; - } - - value = read_16 (ptr); - if (value != 2 && value != 3) - { - error (0, 0, "%s: DWARF version %d unhandled", dso->filename, - value); - return 1; - } - cu.cu_version = value; - - value = read_32 (ptr); - if (value >= debug_sections[DEBUG_ABBREV].size) - { - if (debug_sections[DEBUG_ABBREV].data == NULL) - error (0, 0, "%s: .debug_abbrev not present", dso->filename); - else - error (0, 0, "%s: DWARF CU abbrev offset too large", - dso->filename); - return 1; - } - - if (ptr_size == 0) - { - ptr_size = read_1 (ptr); - if (ptr_size == 4) - { - do_read_ptr = do_read_32_64; - write_ptr = write_32; - } - else if (ptr_size == 8) - { - do_read_ptr = do_read_64; - write_ptr = write_64; - } - else - { - error (0, 0, "%s: Invalid DWARF pointer size %d", - dso->filename, ptr_size); - return 1; - } - } - else if (read_1 (ptr) != ptr_size) - { - error (0, 0, "%s: DWARF pointer size differs between CUs", - dso->filename); - return 1; - } - - abbrev = read_abbrev (dso, - debug_sections[DEBUG_ABBREV].data + value); - if (abbrev == NULL) - return 1; - - cu.cu_entry_pc = ~ (GElf_Addr) 0; - cu.cu_low_pc = ~ (GElf_Addr) 0; - - while (ptr < endcu) - { - tag.entry = read_uleb128 (ptr); - if (tag.entry == 0) - continue; - t = htab_find_with_hash (abbrev, &tag, tag.entry); - if (t == NULL) - { - error (0, 0, "%s: Could not find DWARF abbreviation %d", - dso->filename, tag.entry); - htab_delete (abbrev); - return 1; - } - - ptr = adjust_attributes (dso, ptr, t, &cu, start, adjust); - if (ptr == NULL) - { - htab_delete (abbrev); - return 1; - } - } + if (debug_sections[DEBUG_INFO].data != NULL + && adjust_dwarf2_info (dso, start, adjust, DEBUG_INFO)) + return 1; - htab_delete (abbrev); - } - } + if (debug_sections[DEBUG_TYPES].data != NULL + && adjust_dwarf2_info (dso, start, adjust, DEBUG_TYPES)) + return 1; if (ptr_size == 0) /* Should not happen. */ diff --git a/trunk/src/dwarf2.h b/trunk/src/dwarf2.h index 143a00b..7870c28 100644 --- a/trunk/src/dwarf2.h +++ b/trunk/src/dwarf2.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2001, 2002, 2009 Red Hat, Inc. +/* Copyright (C) 2001, 2002, 2009, 2010 Red Hat, Inc. Written by Jakub Jelinek <jakub@redhat.com>, 2001. This program is free software; you can redistribute it and/or modify @@ -73,6 +73,9 @@ #define DW_TAG_imported_unit 0x3d #define DW_TAG_condition 0x3f #define DW_TAG_shared_type 0x40 +#define DW_TAG_type_unit 0x41 +#define DW_TAG_rvalue_reference_type 0x42 +#define DW_TAG_template_alias 0x43 #define DW_TAG_MIPS_loop 0x4081 #define DW_TAG_format_label 0x4101 #define DW_TAG_function_template 0x4102 @@ -106,6 +109,10 @@ #define DW_FORM_ref8 0x14 #define DW_FORM_ref_udata 0x15 #define DW_FORM_indirect 0x16 +#define DW_FORM_sec_offset 0x17 +#define DW_FORM_exprloc 0x18 +#define DW_FORM_flag_present 0x19 +#define DW_FORM_ref_sig8 0x20 #define DW_AT_sibling 0x01 #define DW_AT_location 0x02 @@ -139,6 +146,7 @@ #define DW_AT_return_addr 0x2a #define DW_AT_start_scope 0x2c #define DW_AT_stride_size 0x2e +#define DW_AT_bit_stride 0x2e #define DW_AT_upper_bound 0x2f #define DW_AT_abstract_origin 0x31 #define DW_AT_accessibility 0x32 @@ -173,6 +181,7 @@ #define DW_AT_associated 0x4f #define DW_AT_data_location 0x50 #define DW_AT_stride 0x51 +#define DW_AT_byte_stride 0x51 #define DW_AT_entry_pc 0x52 #define DW_AT_use_UTF8 0x53 #define DW_AT_extension 0x54 @@ -181,6 +190,27 @@ #define DW_AT_call_column 0x57 #define DW_AT_call_file 0x58 #define DW_AT_call_line 0x59 +#define DW_AT_description 0x5a +#define DW_AT_binary_scale 0x5b +#define DW_AT_decimal_scale 0x5c +#define DW_AT_small 0x5d +#define DW_AT_decimal_sign 0x5e +#define DW_AT_digit_count 0x5f +#define DW_AT_picture_string 0x60 +#define DW_AT_mutable 0x61 +#define DW_AT_threads_scaled 0x62 +#define DW_AT_explicit 0x63 +#define DW_AT_object_pointer 0x64 +#define DW_AT_endianity 0x65 +#define DW_AT_elemental 0x66 +#define DW_AT_pure 0x67 +#define DW_AT_recursive 0x68 +#define DW_AT_signature 0x69 +#define DW_AT_main_subprogram 0x6a +#define DW_AT_data_bit_offset 0x6b +#define DW_AT_const_expr 0x6c +#define DW_AT_enum_class 0x6d +#define DW_AT_linkage_name 0x6e #define DW_AT_MIPS_fde 0x2001 #define DW_AT_MIPS_loop_begin 0x2002 #define DW_AT_MIPS_tail_loop_begin 0x2003 @@ -424,10 +454,14 @@ #define DW_LNS_set_basic_block 0x7 #define DW_LNS_const_add_pc 0x8 #define DW_LNS_fixed_advance_pc 0x9 +#define DW_LNS_set_prologue_end 0xa +#define DW_LNS_set_epilogue_begin 0xb +#define DW_LNS_set_isa 0xc #define DW_LNE_end_sequence 0x1 #define DW_LNE_set_address 0x2 #define DW_LNE_define_file 0x3 +#define DW_LNE_set_discriminator 0x4 #define DW_CFA_advance_loc 0x40 #define DW_CFA_offset 0x80 @@ -491,6 +525,7 @@ #define DW_LANG_ObjC_plus_plus 0x0011 #define DW_LANG_UPC 0x0012 #define DW_LANG_D 0x0013 +#define DW_LANG_Python 0x0014 #define DW_LANG_Mips_Assembler 0x8001 #define DW_LANG_lo_user 0x8000 #define DW_LANG_hi_user 0xffff diff --git a/trunk/src/execstack.c b/trunk/src/execstack.c index b75c5bd..dda6bc7 100644 --- a/trunk/src/execstack.c +++ b/trunk/src/execstack.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2003, 2005 Red Hat, Inc. +/* Copyright (C) 2003, 2005, 2010 Red Hat, Inc. Written by Jakub Jelinek <jakub@redhat.com>, 2003. This program is free software; you can redistribute it and/or modify @@ -472,6 +472,12 @@ prelink_conflict_add_rela (struct prelink_info *info) abort (); } +ssize_t +send_file (int outfd, int infd, off_t *poff, size_t count) +{ + abort (); +} + GElf_Addr mmap_reg_start; GElf_Addr mmap_reg_end; int exec_shield; diff --git a/trunk/src/prelink.h b/trunk/src/prelink.h index 117d266..741f0a4 100644 --- a/trunk/src/prelink.h +++ b/trunk/src/prelink.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009 +/* 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. @@ -119,6 +119,15 @@ typedef uint8_t Elf64_Byte; #define R_X86_64_IRELATIVE 37 #endif +#ifndef R_PPC_IRELATIVE +#define R_PPC_IRELATIVE 248 +#endif + +#ifndef R_PPC64_JMP_IREL +#define R_PPC64_JMP_IREL 247 +#define R_PPC64_IRELATIVE 248 +#endif + struct prelink_entry; struct prelink_info; struct PLArch; @@ -517,6 +526,7 @@ int is_ldso_soname (const char *soname); int prelink_undo (DSO *dso); int prelink_verify (const char *filename); +ssize_t send_file (int outfd, int infd, off_t *poff, size_t count); int gather_object (const char *dir, int deref, int onefs); int read_config (const char *config); diff --git a/trunk/src/undo.c b/trunk/src/undo.c index f9b0bd3..4d1332c 100644 --- a/trunk/src/undo.c +++ b/trunk/src/undo.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001, 2002, 2003, 2005 Red Hat, Inc. +/* Copyright (C) 2001, 2002, 2003, 2005, 2010 Red Hat, Inc. Written by Jakub Jelinek <jakub@redhat.com>, 2001. This program is free software; you can redistribute it and/or modify @@ -406,7 +406,7 @@ undo_sections (DSO *dso, int undo, struct section_move *move, if (! strcmp (name, ".bss") || ! strcmp (name, ".sbss") - || (! strcmp (name, ".plt") + || ((! strcmp (name, ".plt") || ! strcmp (name, ".iplt")) && dso->shdr[i].sh_type == SHT_PROGBITS)) { int is_plt = ! strcmp (name, ".plt"); @@ -500,7 +500,8 @@ prelink_undo (DSO *dso) if (undo == dso->ehdr.e_shnum) { if (undo_output) - return reopen_dso (dso, NULL, undo_output); + return reopen_dso (dso, NULL, strcmp (undo_output, "-") == 0 + ? "/tmp/undo" : undo_output); error (0, 0, "%s does not have .gnu.prelink_undo section", dso->filename); return 1; } @@ -516,7 +517,8 @@ prelink_undo (DSO *dso) if (undo_sections (dso, undo, move, &rinfo, &ehdr, phdr, shdr)) goto error_out; - if (reopen_dso (dso, move, undo_output)) + if (reopen_dso (dso, move, (undo_output && strcmp (undo_output, "-") == 0) + ? "/tmp/undo" : undo_output)) goto error_out; if (find_reloc_sections (dso, &rinfo)) @@ -621,7 +623,8 @@ prelink_undo (DSO *dso) { assert (strcmp (name, ".bss") == 0 || strcmp (name, ".sbss") == 0 - || strcmp (name, ".plt") == 0); + || strcmp (name, ".plt") == 0 + || strcmp (name, ".iplt") == 0); scn = dso->scn[i]; d = elf_getdata (scn, NULL); assert (d != NULL && elf_getdata (scn, d) == NULL); diff --git a/trunk/src/verify.c b/trunk/src/verify.c index 6ba406d..d9f4d7d 100644 --- a/trunk/src/verify.c +++ b/trunk/src/verify.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2006, 2007 Red Hat, Inc. +/* Copyright (C) 2002, 2003, 2006, 2007, 2010 Red Hat, Inc. Written by Jakub Jelinek <jakub@redhat.com>, 2002. This program is free software; you can redistribute it and/or modify @@ -30,7 +30,7 @@ #include "md5.h" #include "sha.h" -static ssize_t +ssize_t send_file (int outfd, int infd, off_t *poff, size_t count) { char buf[65536], *b, *p, *q; @@ -45,7 +45,7 @@ send_file (int outfd, int infd, off_t *poff, size_t count) while (p != q) { n = TEMP_FAILURE_RETRY (write (outfd, p, q - p)); - if (n < 0) + if (n <= 0) { munmap (b, count); return -1; @@ -66,7 +66,7 @@ send_file (int outfd, int infd, off_t *poff, size_t count) while (p != q) { n = TEMP_FAILURE_RETRY (read (infd, p, q - p)); - if (n < 0) + if (n <= 0) return -1; p += n; } @@ -74,7 +74,7 @@ send_file (int outfd, int infd, off_t *poff, size_t count) while (p != q) { n = TEMP_FAILURE_RETRY (write (outfd, p, q - p)); - if (n < 0) + if (n <= 0) return -1; p += n; } diff --git a/trunk/testsuite/ifunc.h b/trunk/testsuite/ifunc.h index 3593396..036444b 100644 --- a/trunk/testsuite/ifunc.h +++ b/trunk/testsuite/ifunc.h @@ -16,18 +16,42 @@ # else # define IFUNC_ASM(fn) "\tmovl $" fn ", %eax\n\tret\n" # endif +#elif defined __powerpc__ +# define IFUNC_ASM(fn) "\tmflr 12\n\tbcl 20,31,1f\n" \ + "\t1:mflr 3\n\tmtlr 12\n\taddis 3,3, " fn \ + "-1b@ha\n\taddi 3,3," fn "-1b@l\n\tblr\n" +# if defined __powerpc64__ +# define IFUNC_DECL(name, hidden, fn1, fn2) \ +asm (".text\n" \ + "\t.globl " #name "\n" \ + "\t" hidden " " #name "\n" \ + "\t.type " #name ", @gnu_indirect_function\n" \ + "\t.section .opd,\"aw\"\n" \ + "\t.align 3\n" \ + #name ":\n" \ + "\t.quad .L." #name ",.TOC.@tocbase,0\n" \ + "\t.previous\n" \ + ".L." #name ":\n" \ + IFUNC_ASM (PICK (fn1, fn2)) \ + "\t.size " #name ", .-" #name "\n") +# endif #else # error Architecture not supported #endif -#define IFUNC(name, hidden, fn1, fn2) \ -extern __typeof (fn1) fn1 __attribute__((used)); \ -extern __typeof (fn2) fn2 __attribute__((used)); \ -extern __typeof (fn1) name; \ -asm (".globl " #name "\n" \ +#ifndef IFUNC_DECL +#define IFUNC_DECL(name, hidden, fn1, fn2) \ +asm (".text\n" \ + "\t.globl " #name "\n" \ "\t" hidden " " #name "\n" \ "\t.type " #name ", @gnu_indirect_function\n" \ #name ":\n" \ IFUNC_ASM (PICK (fn1, fn2)) \ "\t.size " #name ", .-" #name "\n") +#endif +#define IFUNC(name, hidden, fn1, fn2) \ +extern __typeof (fn1) fn1 __attribute__((used)); \ +extern __typeof (fn2) fn2 __attribute__((used)); \ +extern __typeof (fn1) name; \ +IFUNC_DECL (name, hidden, fn1, fn2) #define IFUNC_LOCAL(name, fn1, fn2) IFUNC(name, ".hidden", fn1, fn2) #define IFUNC_GLOBAL(name, fn1, fn2) IFUNC(name, ".globl", fn1, fn2) diff --git a/trunk/testsuite/reloc2.sh b/trunk/testsuite/reloc2.sh index 0ab76cd..2a75717 100755 --- a/trunk/testsuite/reloc2.sh +++ b/trunk/testsuite/reloc2.sh @@ -6,7 +6,12 @@ case "`uname -m`" in s390*) if file reloc1lib1.so | grep -q 64-bit; then SHFLAGS=-fpic; fi;; esac # Disable this test under SELinux if textrel -test -z "$SHFLAGS" -a -x /usr/sbin/getenforce -a "`/usr/sbin/getenforce`" = Enforcing && exit 77 +if test -z "$SHFLAGS" -a -x /usr/sbin/getenforce; then + case "`/usr/sbin/getenforce 2>/dev/null`" in + Permissive|Disabled) ;; + *) exit 77 ;; + esac +fi rm -f reloc2 reloc2lib*.so reloc2.log $CC -shared $SHFLAGS -O2 -o reloc2lib1.so $srcdir/reloc2lib1.c $CC -shared $SHFLAGS -O2 -o reloc2lib2.so $srcdir/reloc2lib2.c \ diff --git a/trunk/testsuite/reloc8.sh b/trunk/testsuite/reloc8.sh index 9f5e1fb..af3aa26 100755 --- a/trunk/testsuite/reloc8.sh +++ b/trunk/testsuite/reloc8.sh @@ -2,13 +2,18 @@ . `dirname $0`/functions.sh # Disable this test under SELinux if [ "x$CROSS" = "x" ]; then - test -x /usr/sbin/getenforce -a "`/usr/sbin/getenforce`" = Enforcing && exit 77 + 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 NOCOPYRELOC=-Wl,-z,nocopyreloc case "`uname -m`" in - x86_64|s390*) if file reloc1lib1.so | grep -q 64-bit; then NOCOPYRELOC=; fi;; + x86_64|s390*|sparc*) if file reloc1lib1.so | grep -q 64-bit; then NOCOPYRELOC=; fi;; esac $CC -shared -O2 -Wl,-z,nocombreloc -fpic -o reloc8lib1.so $srcdir/reloc3lib1.c $CC -shared -O2 -Wl,-z,nocombreloc -fpic -o reloc8lib2.so $srcdir/reloc1lib2.c reloc8lib1.so diff --git a/trunk/testsuite/reloc9.sh b/trunk/testsuite/reloc9.sh index d3a449c..8c48fa7 100755 --- a/trunk/testsuite/reloc9.sh +++ b/trunk/testsuite/reloc9.sh @@ -2,13 +2,18 @@ . `dirname $0`/functions.sh # Disable this test under SELinux if [ "x$CROSS" = "x" ]; then - test -x /usr/sbin/getenforce -a "`/usr/sbin/getenforce`" = Enforcing && exit 77 + 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 NOCOPYRELOC=-Wl,-z,nocopyreloc case "`uname -m`" in - x86_64|s390*) if file reloc1lib1.so | grep -q 64-bit; then NOCOPYRELOC=; fi;; + x86_64|s390*|sparc*) if file reloc1lib1.so | grep -q 64-bit; then NOCOPYRELOC=; fi;; esac $CC -shared -O2 -Wl,-z,nocombreloc -fpic -o reloc9lib1.so $srcdir/reloc3lib1.c $CC -shared -O2 -Wl,-z,nocombreloc -fpic -o reloc9lib2.so $srcdir/reloc1lib2.c reloc9lib1.so diff --git a/trunk/testsuite/tls3.sh b/trunk/testsuite/tls3.sh index 8d015d9..6bb1f95 100755 --- a/trunk/testsuite/tls3.sh +++ b/trunk/testsuite/tls3.sh @@ -10,7 +10,12 @@ case "`uname -m`" in ia64|ppc*|x86_64|alpha*|s390*|mips*|arm*) SHFLAGS=-fpic;; # Does not support non-pic shared libs esac # Disable this test under SELinux if textrel -test -z "$SHFLAGS" -a -x /usr/sbin/getenforce -a "`/usr/sbin/getenforce`" = Enforcing && exit 77 +if test -z "$SHFLAGS" -a -x /usr/sbin/getenforce; then + case "`/usr/sbin/getenforce 2>/dev/null`" in + Permissive|Disabled) ;; + *) exit 77 ;; + esac +fi rm -f tls3 tls3lib*.so tls3.log rm -f prelink.cache $CC -shared -O2 -fpic -o tls3lib1.so $srcdir/tls1lib1.c |