{
unsigned int i;
- assert (filedata->section_headers != NULL);
+ if (filedata->section_headers == NULL)
+ return NULL;
for (i = 0; i < filedata->file_header.e_shnum; i++)
if (streq (SECTION_NAME (filedata->section_headers + i), name))
{
unsigned int i;
+ if (filedata->section_headers == NULL)
+ return NULL;
+
for (i = 0; i < filedata->file_header.e_shnum; i++)
{
Elf_Internal_Shdr *sec = filedata->section_headers + i;
{
unsigned int i;
+ if (filedata->section_headers == NULL)
+ return NULL;
+
for (i = 0; i < filedata->file_header.e_shnum; i++)
{
Elf_Internal_Shdr *sec = filedata->section_headers + i;
{
unsigned int i;
+ if (filedata->section_headers == NULL)
+ return NULL;
+
if (set != NULL)
{
while ((i = *set++) > 0)
case EM_PARISC: return "HPPA";
case EM_VPP550: return "Fujitsu VPP500";
case EM_SPARC32PLUS: return "Sparc v8+" ;
- case EM_960: return "Intel 90860";
+ case EM_960: return "Intel 80960";
case EM_PPC: return "PowerPC";
/* 20 */
case EM_PPC64: return "PowerPC64";
if (archive_file_offset != 0)
str_tab_len = archive_file_size - offset;
else
- str_tab_len = filedata->file_size;
+ str_tab_len = filedata->file_size - offset;
if (str_tab_len < 1)
{
printf (" PIE");
val ^= DF_1_PIE;
}
+ if (val & DF_1_KMOD)
+ {
+ printf (" KMOD");
+ val ^= DF_1_KMOD;
+ }
+ if (val & DF_1_WEAKFILTER)
+ {
+ printf (" WEAKFILTER");
+ val ^= DF_1_WEAKFILTER;
+ }
+ if (val & DF_1_NOCOMMON)
+ {
+ printf (" NOCOMMON");
+ val ^= DF_1_NOCOMMON;
+ }
if (val != 0)
printf (" %lx", val);
puts ("");
static char *
get_ver_flags (unsigned int flags)
{
- static char buff[32];
+ static char buff[128];
buff[0] = 0;
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;
}
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;
}
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 ++)
if (strtab[sym->st_name] == 0)
continue;
+ /* The AArch64 and ARM architectures define mapping symbols
+ (eg $d, $x, $t) which we want to ignore. */
+ if (strtab[sym->st_name] == '$'
+ && strtab[sym->st_name + 1] != 0
+ && strtab[sym->st_name + 2] == 0)
+ continue;
+
if (is_open_attr)
{
/* For OPEN attributes we prefer GLOBAL over LOCAL symbols
FUNC symbols entirely. */
switch (ELF_ST_TYPE (sym->st_info))
{
- case STT_FILE:
- saved_sym = sym;
- /* We can stop searching now. */
- sym = symtab + nsyms;
- continue;
-
case STT_OBJECT:
+ case STT_FILE:
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:
}
}
- 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;
+
+ 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;
- if (pnote->descsz == 0)
+ 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);
+ /* As of version 5 of the annobin plugin, filename symbols are biased by 2
+ in order to avoid them being confused with the start address of the
+ first function in the file... */
+ if (sym == NULL && is_open_attr)
+ sym = get_symbol_for_build_attribute (filedata, start + 2, 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
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;