Add support for v3 binary annotation notes.
I am checking in the attached patch which updates the binutils support for version 3 binary annotation notes. (Version 3 adds an end address to the ranges covered by the notes, so that it is possible to detect gaps in the coverage). This patch also stops the note merging feature of objcopy from executing if the notes have relocations against them. This makes the code simpler, and prevents the problems with architectures which have unusual relocation management issues. * objcopy.c (objcopy_internal_note): New structure. (gap_exists): New function. (is_open_note): New function. (is_func_note): New function. (is_64bit): New function. (merge_gnu_build_notes): Handle v3 notes. Do not merge if there are relocations against the notes. * readelf.c (get_note_type): Use short names for build attribute notes. (print_symbol_for_build_attribute): Rename to get_symbol_for_build_attribute. Returns the found symbol rather than printing it. (print_gnu_build_attribute_description): Maintain address ranges for function notes as well as global notes. Handle v3 notes. (print_gnu_build_attribute_name): Use more space for printing the name in wide mode. * testsuite/binutils-all/note-2-32.s: Use .dc.l instead of .word. Eliminate symbol references in order to remove the need for relocations. * testsuite/binutils-all/note-2-64.s: Likewise. * testsuite/binutils-all/note-3-32.s: Add a size to the note_1 symbol. * testsuite/binutils-all/note-3-64.s: Likewise. * testsuite/binutils-all/mips/mips-note-2r-n32.d: Update expected output. * testsuite/binutils-all/mips/mips-note-2r-n64.d: Likewise. * testsuite/binutils-all/mips/mips-note-2r.d: Likewise. * testsuite/binutils-all/note-2-32.d: Likewise. * testsuite/binutils-all/note-2-64.d: Likewise. * testsuite/binutils-all/note-3-32.d: Likewise. * testsuite/binutils-all/note-3-64.d: Likewise. * testsuite/binutils-all/note-4-64.s: New test. Checks v3 notes. * testsuite/binutils-all/note-4-32.s: New test. * testsuite/binutils-all/note-4-64.d: New test result file. * testsuite/binutils-all/note-4-32.d: New test result file.
This commit is contained in:
parent
9f757bf7fc
commit
6f156d7a4a
19 changed files with 745 additions and 282 deletions
|
@ -16594,9 +16594,9 @@ get_note_type (Filedata * filedata, unsigned e_type)
|
|||
case NT_ARCH:
|
||||
return _("NT_ARCH (architecture)");
|
||||
case NT_GNU_BUILD_ATTRIBUTE_OPEN:
|
||||
return _("NT_GNU_BUILD_ATTRIBUTE_OPEN");
|
||||
return _("OPEN");
|
||||
case NT_GNU_BUILD_ATTRIBUTE_FUNC:
|
||||
return _("NT_GNU_BUILD_ATTRIBUTE_FUNC");
|
||||
return _("func");
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -17416,13 +17416,16 @@ print_ia64_vms_note (Elf_Internal_Note * pnote)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/* Print the name of the symbol associated with a build attribute
|
||||
that is attached to address OFFSET. */
|
||||
/* Find the symbol associated with a build attribute that is attached
|
||||
to address OFFSET. If PNAME is non-NULL then store the name of
|
||||
the symbol (if found) in the provided pointer, Returns NULL if a
|
||||
symbol could not be found. */
|
||||
|
||||
static bfd_boolean
|
||||
print_symbol_for_build_attribute (Filedata * filedata,
|
||||
unsigned long offset,
|
||||
bfd_boolean is_open_attr)
|
||||
static Elf_Internal_Sym *
|
||||
get_symbol_for_build_attribute (Filedata * filedata,
|
||||
unsigned long offset,
|
||||
bfd_boolean is_open_attr,
|
||||
const char ** pname)
|
||||
{
|
||||
static Filedata * saved_filedata = NULL;
|
||||
static char * strtab;
|
||||
|
@ -17461,10 +17464,7 @@ print_symbol_for_build_attribute (Filedata * filedata,
|
|||
}
|
||||
|
||||
if (symtab == NULL || strtab == NULL)
|
||||
{
|
||||
printf ("\n");
|
||||
return FALSE;
|
||||
}
|
||||
return NULL;
|
||||
|
||||
/* Find a symbol whose value matches offset. */
|
||||
for (sym = symtab; sym < symtab + nsyms; sym ++)
|
||||
|
@ -17484,14 +17484,15 @@ print_symbol_for_build_attribute (Filedata * filedata,
|
|||
FUNC symbols entirely. */
|
||||
switch (ELF_ST_TYPE (sym->st_info))
|
||||
{
|
||||
case STT_OBJECT:
|
||||
case STT_FILE:
|
||||
saved_sym = sym;
|
||||
/* We can stop searching now. */
|
||||
sym = symtab + nsyms;
|
||||
continue;
|
||||
|
||||
case STT_OBJECT:
|
||||
saved_sym = sym;
|
||||
if (sym->st_size)
|
||||
{
|
||||
/* If the symbol has a size associated
|
||||
with it then we can stop searching. */
|
||||
sym = symtab + nsyms;
|
||||
}
|
||||
continue;
|
||||
|
||||
case STT_FUNC:
|
||||
|
@ -17529,55 +17530,118 @@ print_symbol_for_build_attribute (Filedata * filedata,
|
|||
}
|
||||
}
|
||||
|
||||
printf (" (%s: %s)\n",
|
||||
is_open_attr ? _("file") : _("func"),
|
||||
saved_sym ? strtab + saved_sym->st_name : _("<no symbol found>)"));
|
||||
return TRUE;
|
||||
if (saved_sym && pname)
|
||||
* pname = strtab + saved_sym->st_name;
|
||||
|
||||
return saved_sym;
|
||||
}
|
||||
|
||||
static bfd_boolean
|
||||
print_gnu_build_attribute_description (Elf_Internal_Note * pnote,
|
||||
Filedata * filedata)
|
||||
{
|
||||
static unsigned long global_offset = 0;
|
||||
unsigned long offset;
|
||||
unsigned int desc_size = is_32bit_elf ? 4 : 8;
|
||||
bfd_boolean is_open_attr = pnote->type == NT_GNU_BUILD_ATTRIBUTE_OPEN;
|
||||
static unsigned long global_offset = 0;
|
||||
static unsigned long global_end = 0;
|
||||
static unsigned long func_offset = 0;
|
||||
static unsigned long func_end = 0;
|
||||
|
||||
if (pnote->descsz == 0)
|
||||
Elf_Internal_Sym * sym;
|
||||
const char * name;
|
||||
unsigned long start;
|
||||
unsigned long end;
|
||||
bfd_boolean is_open_attr = pnote->type == NT_GNU_BUILD_ATTRIBUTE_OPEN;
|
||||
|
||||
switch (pnote->descsz)
|
||||
{
|
||||
case 0:
|
||||
/* A zero-length description means that the range of
|
||||
the previous note of the same type should be used. */
|
||||
if (is_open_attr)
|
||||
{
|
||||
printf (_(" Applies from offset %#lx\n"), global_offset);
|
||||
return TRUE;
|
||||
if (global_end > global_offset)
|
||||
printf (_(" Applies to region from %#lx to %#lx\n"),
|
||||
global_offset, global_end);
|
||||
else
|
||||
printf (_(" Applies to region from %#lx\n"), global_offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf (_(" Applies to func at %#lx"), global_offset);
|
||||
return print_symbol_for_build_attribute (filedata, global_offset, is_open_attr);
|
||||
if (func_end > func_offset)
|
||||
printf (_(" Applies to region from %#lx to %#lx\n"), func_offset, func_end);
|
||||
else
|
||||
printf (_(" Applies to region from %#lx\n"), func_offset);
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
|
||||
if (pnote->descsz != desc_size)
|
||||
{
|
||||
case 4:
|
||||
start = byte_get ((unsigned char *) pnote->descdata, 4);
|
||||
end = 0;
|
||||
break;
|
||||
|
||||
case 8:
|
||||
if (is_32bit_elf)
|
||||
{
|
||||
/* FIXME: We should check that version 3+ notes are being used here... */
|
||||
start = byte_get ((unsigned char *) pnote->descdata, 4);
|
||||
end = byte_get ((unsigned char *) pnote->descdata + 4, 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
start = byte_get ((unsigned char *) pnote->descdata, 8);
|
||||
end = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 16:
|
||||
start = byte_get ((unsigned char *) pnote->descdata, 8);
|
||||
end = byte_get ((unsigned char *) pnote->descdata + 8, 8);
|
||||
break;
|
||||
|
||||
default:
|
||||
error (_(" <invalid description size: %lx>\n"), pnote->descsz);
|
||||
printf (_(" <invalid descsz>"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
offset = byte_get ((unsigned char *) pnote->descdata, desc_size);
|
||||
name = NULL;
|
||||
sym = get_symbol_for_build_attribute (filedata, start, is_open_attr, & name);
|
||||
|
||||
if (end == 0 && sym != NULL && sym->st_size > 0)
|
||||
end = start + sym->st_size;
|
||||
|
||||
if (is_open_attr)
|
||||
{
|
||||
printf (_(" Applies from offset %#lx"), offset);
|
||||
global_offset = offset;
|
||||
/* FIXME: Need to properly allow for section alignment. 16 is just the alignment used on x86_64. */
|
||||
if (global_end > 0 && start > BFD_ALIGN (global_end, 16))
|
||||
warn (_("Gap in build notes detected from %#lx to %#lx\n"),
|
||||
global_end + 1, start - 1);
|
||||
|
||||
printf (_(" Applies to region from %#lx"), start);
|
||||
global_offset = start;
|
||||
|
||||
if (end)
|
||||
{
|
||||
printf (_(" to %#lx"), end);
|
||||
global_end = end;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf (_(" Applies to func at %#lx"), offset);
|
||||
printf (_(" Applies to region from %#lx"), start);
|
||||
func_offset = start;
|
||||
|
||||
if (end)
|
||||
{
|
||||
printf (_(" to %#lx"), end);
|
||||
func_end = end;
|
||||
}
|
||||
}
|
||||
|
||||
return print_symbol_for_build_attribute (filedata, offset, is_open_attr);
|
||||
if (sym && name)
|
||||
printf (_(" (%s)"), name);
|
||||
|
||||
printf ("\n");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static bfd_boolean
|
||||
|
@ -17600,11 +17664,21 @@ print_gnu_build_attribute_name (Elf_Internal_Note * pnote)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
left = 20;
|
||||
if (do_wide)
|
||||
left = 28;
|
||||
else
|
||||
left = 20;
|
||||
|
||||
/* Version 2 of the spec adds a "GA" prefix to the name field. */
|
||||
if (name[0] == 'G' && name[1] == 'A')
|
||||
{
|
||||
if (pnote->namesz < 4)
|
||||
{
|
||||
error (_("corrupt name field in GNU build attribute note: size = %ld\n"), pnote->namesz);
|
||||
print_symbol (-20, _(" <corrupt name>"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
printf ("GA");
|
||||
name += 2;
|
||||
left -= 2;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue