/* readelf.c -- display contents of an ELF format file
Copyright (C) 1998-2020 Free Software Foundation, Inc.
+ Copyright (C) 2019-2020 Advanced Micro Devices, Inc. All rights reserved.
Originally developed by Eric Youngdale <eric@andante.jic.com>
Modifications by Nick Clifton <nickc@redhat.com>
#include "elf/aarch64.h"
#include "elf/alpha.h"
+#include "elf/amdgcn.h"
#include "elf/arc.h"
#include "elf/arm.h"
#include "elf/avr.h"
case EM_Z80:
rtype = elf_z80_reloc_type (type);
break;
+
+ case EM_AMDGPU:
+ rtype = elf_amdgcn_reloc_type (type);
+ break;
}
if (rtype == NULL)
}
break;
+ case EM_AMDGPU:
+ switch (e_flags & EF_AMDGPU_MACH)
+ {
+ case EF_AMDGPU_MACH_AMDGCN_GFX801 : strcat (buf, ", gfx801"); break;
+ case EF_AMDGPU_MACH_AMDGCN_GFX802 : strcat (buf, ", gfx802"); break;
+ case EF_AMDGPU_MACH_AMDGCN_GFX803 : strcat (buf, ", gfx803"); break;
+ case EF_AMDGPU_MACH_AMDGCN_GFX810 : strcat (buf, ", gfx810"); break;
+ case EF_AMDGPU_MACH_AMDGCN_GFX900 : strcat (buf, ", gfx900"); break;
+ case EF_AMDGPU_MACH_AMDGCN_GFX902 : strcat (buf, ", gfx902"); break;
+ case EF_AMDGPU_MACH_AMDGCN_GFX904 : strcat (buf, ", gfx904"); break;
+ case EF_AMDGPU_MACH_AMDGCN_GFX906 : strcat (buf, ", gfx906"); break;
+ case EF_AMDGPU_MACH_AMDGCN_GFX908 : strcat (buf, ", gfx908"); break;
+ case EF_AMDGPU_MACH_AMDGCN_GFX909 : strcat (buf, ", gfx909"); break;
+ default: strcat (buf, _(", <unknown AMDGPU gpu type>")); break;
+ }
+
+ if (e_flags & ~ EF_AMDGPU_MACH)
+ sprintf (buf + strlen (buf), _(", unknown flags bits: %#x"),
+ e_flags & ~ EF_AMDGPU_MACH);
+ break;
+
case EM_CYGNUS_MEP:
switch (e_flags & EF_MEP_CPU_MASK)
{
if (osabi >= 64)
switch (filedata->file_header.e_machine)
{
+ case EM_AMDGPU:
+ switch (osabi)
+ {
+ case ELFOSABI_AMDGPU_HSA: return "AMD HSA Runtime";
+ default:
+ break;
+ }
+ break;
+
case EM_ARM:
switch (osabi)
{
return TRUE;
}
+ #if HAVE_LIBDEBUGINFOD
+ /* Return a hex string representation of the build-id. */
+ unsigned char *
+ get_build_id (void * data)
+ {
+ Filedata * filedata = (Filedata *)data;
+ Elf_Internal_Shdr * shdr;
+ unsigned long i;
+
+ /* Iterate through notes to find note.gnu.build-id. */
+ for (i = 0, shdr = filedata->section_headers;
+ i < filedata->file_header.e_shnum && shdr != NULL;
+ i++, shdr++)
+ {
+ if (shdr->sh_type != SHT_NOTE)
+ continue;
+
+ char * next;
+ char * end;
+ size_t data_remaining;
+ size_t min_notesz;
+ Elf_External_Note * enote;
+ Elf_Internal_Note inote;
+
+ bfd_vma offset = shdr->sh_offset;
+ bfd_vma align = shdr->sh_addralign;
+ bfd_vma length = shdr->sh_size;
+
+ enote = (Elf_External_Note *) get_section_contents (shdr, filedata);
+ if (enote == NULL)
+ continue;
+
+ if (align < 4)
+ align = 4;
+ else if (align != 4 && align != 8)
+ continue;
+
+ end = (char *) enote + length;
+ data_remaining = end - (char *) enote;
+
+ if (!is_ia64_vms (filedata))
+ {
+ min_notesz = offsetof (Elf_External_Note, name);
+ if (data_remaining < min_notesz)
+ {
+ warn (ngettext ("debuginfod: Corrupt note: only %ld byte remains, "
+ "not enough for a full note\n",
+ "Corrupt note: only %ld bytes remain, "
+ "not enough for a full note\n",
+ data_remaining),
+ (long) data_remaining);
+ break;
+ }
+ data_remaining -= min_notesz;
+
+ inote.type = BYTE_GET (enote->type);
+ inote.namesz = BYTE_GET (enote->namesz);
+ inote.namedata = enote->name;
+ inote.descsz = BYTE_GET (enote->descsz);
+ inote.descdata = ((char *) enote
+ + ELF_NOTE_DESC_OFFSET (inote.namesz, align));
+ inote.descpos = offset + (inote.descdata - (char *) enote);
+ next = ((char *) enote
+ + ELF_NOTE_NEXT_OFFSET (inote.namesz, inote.descsz, align));
+ }
+ else
+ {
+ Elf64_External_VMS_Note *vms_enote;
+
+ /* PR binutils/15191
+ Make sure that there is enough data to read. */
+ min_notesz = offsetof (Elf64_External_VMS_Note, name);
+ if (data_remaining < min_notesz)
+ {
+ warn (ngettext ("debuginfod: Corrupt note: only %ld byte remains, "
+ "not enough for a full note\n",
+ "Corrupt note: only %ld bytes remain, "
+ "not enough for a full note\n",
+ data_remaining),
+ (long) data_remaining);
+ break;
+ }
+ data_remaining -= min_notesz;
+
+ vms_enote = (Elf64_External_VMS_Note *) enote;
+ inote.type = BYTE_GET (vms_enote->type);
+ inote.namesz = BYTE_GET (vms_enote->namesz);
+ inote.namedata = vms_enote->name;
+ inote.descsz = BYTE_GET (vms_enote->descsz);
+ inote.descdata = inote.namedata + align_power (inote.namesz, 3);
+ inote.descpos = offset + (inote.descdata - (char *) enote);
+ next = inote.descdata + align_power (inote.descsz, 3);
+ }
+
+ /* Skip malformed notes. */
+ if ((size_t) (inote.descdata - inote.namedata) < inote.namesz
+ || (size_t) (inote.descdata - inote.namedata) > data_remaining
+ || (size_t) (next - inote.descdata) < inote.descsz
+ || ((size_t) (next - inote.descdata)
+ > data_remaining - (size_t) (inote.descdata - inote.namedata)))
+ {
+ warn (_("debuginfod: note with invalid namesz and/or descsz found\n"));
+ warn (_(" type: 0x%lx, namesize: 0x%08lx, descsize: 0x%08lx, alignment: %u\n"),
+ inote.type, inote.namesz, inote.descsz, (int) align);
+ continue;
+ }
+
+ /* Check if this is the build-id note. If so then convert the build-id
+ bytes to a hex string. */
+ if (inote.namesz > 0
+ && const_strneq (inote.namedata, "GNU")
+ && inote.type == NT_GNU_BUILD_ID)
+ {
+ unsigned long j;
+ char * build_id;
+
+ build_id = malloc (inote.descsz * 2 + 1);
+ if (build_id == NULL)
+ return NULL;
+
+ for (j = 0; j < inote.descsz; ++j)
+ sprintf (build_id + (j * 2), "%02x", inote.descdata[j] & 0xff);
+ build_id[inote.descsz * 2] = '\0';
+
+ return (unsigned char *)build_id;
+ }
+ }
+
+ return NULL;
+ }
+ #endif /* HAVE_LIBDEBUGINFOD */
+
/* If this is not NULL, load_debug_section will only look for sections
within the list of sections given here. */
static unsigned int * section_subset = NULL;
}
}
+static const char *
+get_amd_elf_note_type (unsigned e_type)
+{
+ static char buff[64];
+
+ switch (e_type)
+ {
+ case NT_AMDGPU_HSA_CODE_OBJECT_VERSION:
+ return _("NT_AMDGPU_HSA_CODE_OBJECT_VERSION (code object version)");
+ case NT_AMDGPU_HSA_HSAIL:
+ return _("NT_AMDGPU_HSA_HSAIL (hsail)");
+ case NT_AMDGPU_HSA_ISA:
+ return _("NT_AMDGPU_HSA_ISA (ISA name)");
+ case NT_AMDGPU_HSA_PRODUCER:
+ return _("NT_AMDGPU_HSA_PRODUCER (producer name)");
+ case NT_AMDGPU_HSA_PRODUCER_OPTIONS:
+ return _("NT_AMDGPU_HSA_PRODUCER_OPTIONS (producer options");
+ case NT_AMDGPU_HSA_EXTENSION:
+ return _("NT_AMDGPU_HSA_EXTENSION (extension)");
+ case NT_AMDGPU_HSA_METADATA:
+ return _("NT_AMDGPU_HSA_METADATA (code object metadata)");
+ case NT_AMDGPU_ISA:
+ return _("NT_AMDGPU_ISA");
+ case NT_AMDGPU_PAL_METADATA:
+ return _("NT_AMDGPU_PAL_METADATA (code object metadata)");
+ case NT_AMDGPU_METADATA:
+ return _("NT_AMDGPU_METADATA (code object metadata)");
+ default:
+ break;
+ }
+
+ snprintf (buff, sizeof (buff), _("Unknown note type: (0x%08x)"), e_type);
+ return buff;
+}
+
+static int
+print_amd_note (Elf_Internal_Note *pnote)
+{
+ switch (pnote->type)
+ {
+ case NT_AMDGPU_HSA_CODE_OBJECT_VERSION:
+ {
+ unsigned int major, minor;
+
+ major = byte_get ((unsigned char*) pnote->descdata, 4);
+ minor = byte_get ((unsigned char*) pnote->descdata + 4, 4);
+
+ printf (_(" Version: %d.%d\n"), major, minor);
+ }
+ break;
+
+ case NT_AMDGPU_HSA_ISA:
+ {
+ unsigned long i, vendorsz;
+ unsigned int major, minor, stepping;
+
+ vendorsz = byte_get ((unsigned char*) pnote->descdata, 2);
+ major = byte_get ((unsigned char*) pnote->descdata + 4, 4);
+ minor = byte_get ((unsigned char*) pnote->descdata + 8, 4);
+ stepping = byte_get ((unsigned char*) pnote->descdata + 12, 4);
+
+ printf (_(" Vendor: "));
+ for (i = 16; i < pnote->descsz && pnote->descdata[i] != '\0'; ++i)
+ printf ("%c", pnote->descdata[i]);
+ printf (_(", Architecture: "));
+ for (i = 16 + vendorsz; i < pnote->descsz && pnote->descdata[i] != '\0'; ++i)
+ printf ("%c", pnote->descdata[i]);
+
+ printf (_(", Version: %d.%d.%d"), major, minor, stepping);
+ printf ("\n");
+ }
+ break;
+ }
+ return 1;
+}
+
static void
decode_x86_feature_1 (unsigned int bitmask)
{
/* GNU-specific object file notes. */
nt = get_gnu_elf_note_type (pnote->type);
+ else if (const_strneq (pnote->namedata, "AMD")
+ || const_strneq (pnote->namedata, "AMDGPU"))
+ /* AMD-specific object file notes. */
+ nt = get_amd_elf_note_type (pnote->type);
+
else if (const_strneq (pnote->namedata, "FreeBSD"))
/* FreeBSD-specific core file notes. */
nt = get_freebsd_elfcore_note_type (filedata, pnote->type);
return print_ia64_vms_note (pnote);
else if (const_strneq (pnote->namedata, "GNU"))
return print_gnu_note (filedata, pnote);
+ else if (const_strneq (pnote->namedata, "AMD")
+ || const_strneq (pnote->namedata, "AMDGPU"))
+ return print_amd_note (pnote);
else if (const_strneq (pnote->namedata, "stapsdt"))
return print_stapsdt_note (pnote);
else if (const_strneq (pnote->namedata, "CORE"))