diff options
-rw-r--r-- | binutils/ChangeLog | 11 | ||||
-rw-r--r-- | binutils/doc/binutils.texi | 6 | ||||
-rw-r--r-- | binutils/objdump.c | 7 | ||||
-rw-r--r-- | binutils/readelf.c | 92 |
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); } |