aboutsummaryrefslogtreecommitdiff
path: root/binutils
diff options
context:
space:
mode:
Diffstat (limited to 'binutils')
-rw-r--r--binutils/ChangeLog6
-rw-r--r--binutils/readelf.c39
2 files changed, 43 insertions, 2 deletions
diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index 800e76a..268d75e 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -1,3 +1,9 @@
+2009-04-30 Nick Clifton <nickc@redhat.com>
+
+ * readelf.c (dump_relocations): Display a relocation against an
+ ifunc symbol as if it were a function invocation.
+ (get_symbol_type): Handle STT_GNU_IFUNC.
+
2009-04-29 Anthony Green <green@moxielogic.com>
* NEWS: Tweak verilog support description.
diff --git a/binutils/readelf.c b/binutils/readelf.c
index a7e7b05..30bcf66 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -1238,9 +1238,38 @@ dump_relocations (FILE * file,
printf (" ");
- print_vma (psym->st_value, LONG_HEX);
+ if (ELF_ST_TYPE (psym->st_info) == STT_GNU_IFUNC)
+ {
+ const char * name;
+ unsigned int len;
+ unsigned int width = is_32bit_elf ? 8 : 14;
+
+ /* Relocations against GNU_IFUNC symbols do not use the value
+ of the symbol as the address to relocate against. Instead
+ they invoke the function named by the symbol and use its
+ result as the address for relocation.
+
+ To indicate this to the user, do not display the value of
+ the symbol in the "Symbols's Value" field. Instead show
+ its name followed by () as a hint that the symbol is
+ invoked. */
+
+ if (strtab == NULL
+ || psym->st_name == 0
+ || psym->st_name >= strtablen)
+ name = "??";
+ else
+ name = strtab + psym->st_name;
- printf (is_32bit_elf ? " " : " ");
+ len = print_symbol (width, name);
+ printf ("()%-*s", len <= width ? (width + 1) - len : 1, " ");
+ }
+ else
+ {
+ print_vma (psym->st_value, LONG_HEX);
+
+ printf (is_32bit_elf ? " " : " ");
+ }
if (psym->st_name == 0)
{
@@ -6913,6 +6942,12 @@ get_symbol_type (unsigned int type)
return "HP_STUB";
}
+ if (type == STT_GNU_IFUNC
+ && (elf_header.e_ident[EI_OSABI] == ELFOSABI_LINUX
+ /* GNU/Linux is still using the default value 0. */
+ || elf_header.e_ident[EI_OSABI] == ELFOSABI_NONE))
+ return "IFUNC";
+
snprintf (buff, sizeof (buff), _("<OS specific>: %d"), type);
}
else