aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--binutils/ChangeLog11
-rw-r--r--binutils/doc/binutils.texi6
-rw-r--r--binutils/objdump.c7
-rw-r--r--binutils/readelf.c92
4 files changed, 94 insertions, 22 deletions
diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index 7d0c9a4..db2a7e0 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -1,3 +1,14 @@
+2008-12-04 Nick Clifton <nickc@redhat.com>
+
+ * objdump.c (dump_reloc_set): Append "()" to symbol names which
+ have the BSF_INDIRECT_FUNCTION type.
+ * readelf.c (print_symbol): Fix handling of negative widths.
+ (dump_relocations): Append "()" to symbol names which have the
+ STT_IFUNC type. Display negative offsets as a positive number with
+ a "-" prefix.
+ (get_symbol_type): Return "IFUNC" for STT_IFUNC symbols.
+ * doc/binutils.texi: Document 'i' symbol type.
+
2008-11-26 Jan Kratochvil <jan.kratochvil@redhat.com>
* strings.c (main): New variable `s'. Have string_min parsing
diff --git a/binutils/doc/binutils.texi b/binutils/doc/binutils.texi
index 2e7aa2b..100b0f5 100644
--- a/binutils/doc/binutils.texi
+++ b/binutils/doc/binutils.texi
@@ -2045,8 +2045,10 @@ symbol's name is a message to be displayed if the symbol following the
warning symbol is ever referenced.
@item I
-The symbol is an indirect reference to another symbol (I) or a normal
-symbol (a space).
+@item i
+The symbol is an indirect reference to another symbol (I), a function
+to be evaluated during reloc processing (i) or a normal symbol (a
+space).
@item d
@itemx D
diff --git a/binutils/objdump.c b/binutils/objdump.c
index b1411d9..ac5fa0d 100644
--- a/binutils/objdump.c
+++ b/binutils/objdump.c
@@ -2718,8 +2718,13 @@ dump_reloc_set (bfd *abfd, asection *sec, arelent **relpp, long relcount)
printf (" %-16s ", q->howto->name);
else
printf (" %-16d ", q->howto->type);
+
if (sym_name)
- objdump_print_symname (abfd, NULL, *q->sym_ptr_ptr);
+ {
+ objdump_print_symname (abfd, NULL, *q->sym_ptr_ptr);
+ if ((*q->sym_ptr_ptr)->flags & BSF_INDIRECT_FUNCTION)
+ printf ("() ");
+ }
else
{
if (section_name == NULL)
diff --git a/binutils/readelf.c b/binutils/readelf.c
index 02de84c..8bf0d76 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -414,35 +414,31 @@ print_vma (bfd_vma vma, print_mode mode)
return 0;
}
-/* Display a symbol on stdout. Handles the display of
- non-printing characters.
- If DO_WIDE is not true then format the symbol to be
- at most WIDTH characters, truncating as necessary.
- If WIDTH is negative then format the string to be
- exactly - WIDTH characters, truncating or padding
- as necessary. */
+/* Display a symbol on stdout. Handles the display of non-printing characters.
-static void
+ If DO_WIDE is not true then format the symbol to be at most WIDTH characters,
+ truncating as necessary. If WIDTH is negative then format the string to be
+ exactly - WIDTH characters, truncating or padding as necessary.
+
+ Returns the number of emitted characters. */
+
+static unsigned int
print_symbol (int width, const char *symbol)
{
- const char * format_string;
const char * c;
+ bfd_boolean extra_padding = FALSE;
+ unsigned int num_printed = 0;
if (do_wide)
{
- format_string = "%.*s";
/* Set the width to a very large value. This simplifies the code below. */
width = INT_MAX;
}
else if (width < 0)
{
- format_string = "%-*.*2s";
/* Keep the width positive. This also helps. */
width = - width;
- }
- else
- {
- format_string = "%-.*s";
+ extra_padding = TRUE;
}
while (width)
@@ -464,9 +460,10 @@ print_symbol (int width, const char *symbol)
if (len > width)
len = width;
- printf (format_string, len, symbol);
+ printf ("%.*s", len, symbol);
width -= len;
+ num_printed += len;
}
if (* c == 0 || width == 0)
@@ -482,6 +479,7 @@ print_symbol (int width, const char *symbol)
printf ("^%c", *c + 0x40);
width -= 2;
+ num_printed += 2;
}
else
{
@@ -491,10 +489,20 @@ print_symbol (int width, const char *symbol)
printf ("<0x%.2x>", *c);
width -= 6;
+ num_printed += 6;
}
symbol = c + 1;
}
+
+ if (extra_padding && width > 0)
+ {
+ /* Fill in the remaining spaces. */
+ printf ("%-*s", width, " ");
+ num_printed += 2;
+ }
+
+ return num_printed;
}
static void
@@ -1242,8 +1250,39 @@ dump_relocations (FILE *file,
psym = symtab + symtab_index;
printf (" ");
- print_vma (psym->st_value, LONG_HEX);
- printf (is_32bit_elf ? " " : " ");
+
+ if (ELF_ST_TYPE (psym->st_info) == STT_IFUNC)
+ {
+ const char * name;
+ unsigned int len;
+ unsigned int width = is_32bit_elf ? 8 : 14;
+
+ /* Relocations against 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;
+
+ 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)
{
@@ -1294,7 +1333,14 @@ dump_relocations (FILE *file,
print_symbol (22, strtab + psym->st_name);
if (is_rela)
- printf (" + %lx", (unsigned long) rels[i].r_addend);
+ {
+ long offset = (long) (bfd_signed_vma) rels[i].r_addend;
+
+ if (offset < 0)
+ printf (" - %lx", - offset);
+ else
+ printf (" + %lx", offset);
+ }
}
}
else if (is_rela)
@@ -7019,6 +7065,14 @@ get_symbol_type (unsigned int type)
if (type == STT_HP_STUB)
return "HP_STUB";
}
+ else if (elf_header.e_ident[EI_OSABI] == ELFOSABI_LINUX
+ || elf_header.e_ident[EI_OSABI] == ELFOSABI_HURD
+ /* GNU/Linux is still using the default value 0. */
+ || elf_header.e_ident[EI_OSABI] == ELFOSABI_NONE)
+ {
+ if (type == STT_IFUNC)
+ return "IFUNC";
+ }
snprintf (buff, sizeof (buff), _("<OS specific>: %d"), type);
}