diff options
author | Simon Marchi <simon.marchi@efficios.com> | 2022-03-16 09:01:36 -0400 |
---|---|---|
committer | Simon Marchi <simon.marchi@polymtl.ca> | 2022-03-16 09:01:43 -0400 |
commit | 2952f10cd79af4645222f124f28c7928287d8113 (patch) | |
tree | df776596c24ec839cad957eebb14c4bd1b2c3b8c /binutils/readelf.c | |
parent | 28cdbb183bf80157a71d222b66abc38f32019f2d (diff) | |
download | gdb-2952f10cd79af4645222f124f28c7928287d8113.zip gdb-2952f10cd79af4645222f124f28c7928287d8113.tar.gz gdb-2952f10cd79af4645222f124f28c7928287d8113.tar.bz2 |
binutils/readelf: build against msgpack, dump NT_AMDGPU_METADATA note contents
The AMDGPU HSA OS ABI (code object v3 and above) defines the
NT_AMDGPU_METADATA ELF note [1]. The content is a msgpack object
describing, among other things, the kernels present in the code object
and how to call them.
I think it would be useful for readelf to be able to display the content
of those notes. msgpack is a structured format, a bit like JSON, except
not text-based. It is therefore possible to dump the contents in
human-readable form without knowledge of the specific layout of the
note.
Add configury to binutils to optionally check for the msgpack C library
[2]. Add There is a new --with{,out}-msgpack configure flag, and the actual
library lookup is done using pkg-config.
If msgpack support is enabled, dumping a NT_AMDGPU_METADATA note looks
like:
$ readelf --notes amdgpu-code-object
Displaying notes found in: .note
Owner Data size Description
AMDGPU 0x0000040d NT_AMDGPU_METADATA (code object metadata)
{
"amdhsa.kernels": [
{
".args": [
{
".address_space": "global",
".name": "out.coerce",
".offset": 0,
".size": 8,
".value_kind": "global_buffer",
},
<snip>
If msgpack support is disabled, dump the contents as hex, as is done
with notes that are not handled in a special way. This allows one to
decode the contents manually (maybe using a command-line msgpack
decoder) if really needed.
[1] https://llvm.org/docs/AMDGPUUsage.html#code-object-metadata
[2] https://github.com/msgpack/msgpack-c/tree/c_master
binutils/ChangeLog:
* Makefile.am (readelf_CFLAGS): New.
(readelf_LDADD): Add MSGPACK_LIBS.
* Makefile.in: Re-generate.
* config.in: Re-generate.
* configure: Re-generate.
* configure.ac: Add --with-msgpack flag and check for msgpack
using pkg-config.
* readelf.c: Include msgpack.h if HAVE_MSGPACK.
(print_note_contents_hex): New.
(print_indents): New.
(dump_msgpack_obj): New.
(dump_msgpack): New.
(print_amdgpu_note): New.
(process_note): Handle NT_AMDGPU_METADATA note contents.
Use print_note_contents_hex.
Change-Id: Ia60a654e620bc32dfdb1bccd845594e2af328b84
Diffstat (limited to 'binutils/readelf.c')
-rw-r--r-- | binutils/readelf.c | 193 |
1 files changed, 179 insertions, 14 deletions
diff --git a/binutils/readelf.c b/binutils/readelf.c index 91515bd..ff07112 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -46,6 +46,10 @@ #include <zlib.h> #include <wchar.h> +#if defined HAVE_MSGPACK +#include <msgpack.h> +#endif + #if __GNUC__ >= 2 /* Define BFD64 here, even if our default architecture is 32 bit ELF as this will allow us to read in and parse 64bit and 32bit ELF files. @@ -21307,6 +21311,177 @@ print_gnu_build_attribute_name (Elf_Internal_Note * pnote) return true; } +/* Print the contents of PNOTE as hex. */ + +static void +print_note_contents_hex (Elf_Internal_Note *pnote) +{ + if (pnote->descsz) + { + unsigned long i; + + printf (_(" description data: ")); + for (i = 0; i < pnote->descsz; i++) + printf ("%02x ", pnote->descdata[i] & 0xff); + if (!do_wide) + printf ("\n"); + } + + if (do_wide) + printf ("\n"); +} + +#if defined HAVE_MSGPACK + +static void +print_indents (int n) +{ + printf (" "); + + for (int i = 0; i < n; i++) + printf (" "); +} + +/* Print OBJ in human-readable form. */ + +static void +dump_msgpack_obj (const msgpack_object *obj, int indent) +{ + switch (obj->type) + { + case MSGPACK_OBJECT_NIL: + printf ("(nil)"); + break; + + case MSGPACK_OBJECT_BOOLEAN: + printf ("%s", obj->via.boolean ? "true" : "false"); + break; + + case MSGPACK_OBJECT_POSITIVE_INTEGER: + printf ("%" PRIu64, obj->via.u64); + break; + + case MSGPACK_OBJECT_NEGATIVE_INTEGER: + printf ("%" PRIi64, obj->via.i64); + break; + + case MSGPACK_OBJECT_FLOAT32: + case MSGPACK_OBJECT_FLOAT64: + printf ("%f", obj->via.f64); + break; + + case MSGPACK_OBJECT_STR: + printf ("\"%.*s\"", obj->via.str.size, obj->via.str.ptr); + break; + + case MSGPACK_OBJECT_ARRAY: + { + const msgpack_object_array *array = &obj->via.array; + + printf ("[\n"); + ++indent; + + for (uint32_t i = 0; i < array->size; ++i) + { + const msgpack_object *item = &array->ptr[i]; + + print_indents (indent); + dump_msgpack_obj (item, indent); + printf (",\n"); + } + + --indent; + print_indents (indent); + printf ("]"); + break; + } + break; + + case MSGPACK_OBJECT_MAP: + { + const msgpack_object_map *map = &obj->via.map; + + printf ("{\n"); + ++indent; + + for (uint32_t i = 0; i < map->size; ++i) + { + const msgpack_object_kv *kv = &map->ptr[i]; + const msgpack_object *key = &kv->key; + const msgpack_object *val = &kv->val; + + print_indents (indent); + dump_msgpack_obj (key, indent); + printf (": "); + dump_msgpack_obj (val, indent); + + printf (",\n"); + } + + --indent; + print_indents (indent); + printf ("}"); + + break; + } + + case MSGPACK_OBJECT_BIN: + printf ("(bin)"); + break; + + case MSGPACK_OBJECT_EXT: + printf ("(ext)"); + break; + } +} + +static void +dump_msgpack (const msgpack_unpacked *msg) +{ + print_indents (0); + dump_msgpack_obj (&msg->data, 0); + printf ("\n"); +} + +#endif /* defined HAVE_MSGPACK */ + +static bool +print_amdgpu_note (Elf_Internal_Note *pnote) +{ +#if defined HAVE_MSGPACK + /* If msgpack is available, decode and dump the note's content. */ + bool ret; + msgpack_unpacked msg; + msgpack_unpack_return msgpack_ret; + + assert (pnote->type == NT_AMDGPU_METADATA); + + msgpack_unpacked_init (&msg); + msgpack_ret = msgpack_unpack_next (&msg, pnote->descdata, pnote->descsz, + NULL); + + switch (msgpack_ret) + { + case MSGPACK_UNPACK_SUCCESS: + dump_msgpack (&msg); + ret = true; + break; + + default: + error (_("failed to unpack msgpack contents in NT_AMDGPU_METADATA note")); + ret = false; + break; + } + + msgpack_unpacked_destroy (&msg); + return ret; +#else + /* msgpack is not available, dump contents as hex. */ + print_note_contents_hex (pnote); + return true; +#endif +} + /* Note that by the ELF standard, the name field is already null byte terminated, and namesz includes the terminating null byte. I.E. the value of namesz for the name "FSF" is 4. @@ -21404,21 +21579,11 @@ process_note (Elf_Internal_Note * pnote, && (pnote->type == NT_GNU_BUILD_ATTRIBUTE_OPEN || pnote->type == NT_GNU_BUILD_ATTRIBUTE_FUNC)) return print_gnu_build_attribute_description (pnote, filedata); + else if (startswith (pnote->namedata, "AMDGPU") + && pnote->type == NT_AMDGPU_METADATA) + return print_amdgpu_note (pnote); - if (pnote->descsz) - { - unsigned long i; - - printf (_(" description data: ")); - for (i = 0; i < pnote->descsz; i++) - printf ("%02x ", pnote->descdata[i] & 0xff); - if (!do_wide) - printf ("\n"); - } - - if (do_wide) - printf ("\n"); - + print_note_contents_hex (pnote); return true; } |