aboutsummaryrefslogtreecommitdiffstats
path: root/trunk
diff options
context:
space:
mode:
Diffstat (limited to 'trunk')
-rw-r--r--trunk/ChangeLog109
-rw-r--r--trunk/m4/libelf.m43
-rw-r--r--trunk/src/arch-ppc.c54
-rw-r--r--trunk/src/arch-ppc64.c63
-rw-r--r--trunk/src/arch-s390.c116
-rw-r--r--trunk/src/arch-x86_64.c1
-rw-r--r--trunk/src/dso.c68
-rw-r--r--trunk/src/dwarf2.c310
-rw-r--r--trunk/src/dwarf2.h37
-rw-r--r--trunk/src/execstack.c8
-rw-r--r--trunk/src/prelink.h12
-rw-r--r--trunk/src/undo.c13
-rw-r--r--trunk/src/verify.c10
-rw-r--r--trunk/testsuite/ifunc.h34
-rwxr-xr-xtrunk/testsuite/reloc2.sh7
-rwxr-xr-xtrunk/testsuite/reloc8.sh9
-rwxr-xr-xtrunk/testsuite/reloc9.sh9
-rwxr-xr-xtrunk/testsuite/tls3.sh7
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