This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: COMMITTED: Add support for STT_IFUNC
- From: Nick Clifton <nickc at redhat dot com>
- To: Hans-Peter Nilsson <hans-peter dot nilsson at axis dot com>
- Cc: binutils at sourceware dot org
- Date: Thu, 04 Dec 2008 08:05:19 +0000
- Subject: Re: COMMITTED: Add support for STT_IFUNC
- References: <200812031536.mB3FaCwh015899@ignucius.se.axis.com>
Hi Hans-Peter, (and others who noticed this problem)
My autotester complains; it looks like this introduces a test
failure for cris-axis-elf:
That would be because old bozo brain here forgot to check in the changes
in the binutils directory. I have now applied the attached patch to fix
this problem.
Cheers
Nick
binutils/ChangeLog
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.
Index: binutils/objdump.c
===================================================================
RCS file: /cvs/src/src/binutils/objdump.c,v
retrieving revision 1.148
diff -c -3 -p -r1.148 objdump.c
*** binutils/objdump.c 14 Nov 2008 14:56:51 -0000 1.148
--- binutils/objdump.c 4 Dec 2008 07:58:12 -0000
*************** dump_reloc_set (bfd *abfd, asection *sec
*** 2718,2725 ****
printf (" %-16s ", q->howto->name);
else
printf (" %-16d ", q->howto->type);
if (sym_name)
! objdump_print_symname (abfd, NULL, *q->sym_ptr_ptr);
else
{
if (section_name == NULL)
--- 2718,2730 ----
printf (" %-16s ", q->howto->name);
else
printf (" %-16d ", q->howto->type);
+
if (sym_name)
! {
! objdump_print_symname (abfd, NULL, *q->sym_ptr_ptr);
! if ((*q->sym_ptr_ptr)->flags & BSF_INDIRECT_FUNCTION)
! printf ("() ");
! }
else
{
if (section_name == NULL)
Index: binutils/readelf.c
===================================================================
RCS file: /cvs/src/src/binutils/readelf.c,v
retrieving revision 1.430
diff -c -3 -p -r1.430 readelf.c
*** binutils/readelf.c 18 Nov 2008 15:45:03 -0000 1.430
--- binutils/readelf.c 4 Dec 2008 07:58:14 -0000
*************** print_vma (bfd_vma vma, print_mode mode)
*** 414,448 ****
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. */
! static void
print_symbol (int width, const char *symbol)
{
- const char * format_string;
const char * c;
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";
}
while (width)
--- 414,444 ----
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.
!
! Returns the number of emitted characters. */
!
! static unsigned int
print_symbol (int width, const char *symbol)
{
const char * c;
+ bfd_boolean extra_padding = FALSE;
+ unsigned int num_printed = 0;
if (do_wide)
{
/* Set the width to a very large value. This simplifies the code below. */
width = INT_MAX;
}
else if (width < 0)
{
/* Keep the width positive. This also helps. */
width = - width;
! extra_padding = TRUE;
}
while (width)
*************** print_symbol (int width, const char *sym
*** 464,472 ****
if (len > width)
len = width;
! printf (format_string, len, symbol);
width -= len;
}
if (* c == 0 || width == 0)
--- 460,469 ----
if (len > width)
len = width;
! printf ("%.*s", len, symbol);
width -= len;
+ num_printed += len;
}
if (* c == 0 || width == 0)
*************** print_symbol (int width, const char *sym
*** 482,487 ****
--- 479,485 ----
printf ("^%c", *c + 0x40);
width -= 2;
+ num_printed += 2;
}
else
{
*************** print_symbol (int width, const char *sym
*** 491,500 ****
--- 489,508 ----
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
*************** dump_relocations (FILE *file,
*** 1242,1249 ****
psym = symtab + symtab_index;
printf (" ");
! print_vma (psym->st_value, LONG_HEX);
! printf (is_32bit_elf ? " " : " ");
if (psym->st_name == 0)
{
--- 1250,1288 ----
psym = symtab + symtab_index;
printf (" ");
!
! 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)
{
*************** dump_relocations (FILE *file,
*** 1294,1300 ****
print_symbol (22, strtab + psym->st_name);
if (is_rela)
! printf (" + %lx", (unsigned long) rels[i].r_addend);
}
}
else if (is_rela)
--- 1333,1346 ----
print_symbol (22, strtab + psym->st_name);
if (is_rela)
! {
! long offset = (long) (bfd_signed_vma) rels[i].r_addend;
!
! if (offset < 0)
! printf (" - %lx", - offset);
! else
! printf (" + %lx", offset);
! }
}
}
else if (is_rela)
*************** get_symbol_type (unsigned int type)
*** 7019,7024 ****
--- 7065,7078 ----
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);
}
Index: binutils/doc/binutils.texi
===================================================================
RCS file: /cvs/src/src/binutils/doc/binutils.texi,v
retrieving revision 1.132
diff -c -3 -p -r1.132 binutils.texi
*** binutils/doc/binutils.texi 19 Nov 2008 16:22:47 -0000 1.132
--- binutils/doc/binutils.texi 4 Dec 2008 07:58:16 -0000
*************** symbol's name is a message to be display
*** 2045,2052 ****
warning symbol is ever referenced.
@item I
! The symbol is an indirect reference to another symbol (I) or a normal
! symbol (a space).
@item d
@itemx D
--- 2045,2054 ----
warning symbol is ever referenced.
@item I
! @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