# git clone https://gitlab.com/gbenson/binutils-gdb.git gdb/src # git diff 1f1c02597cc199227226251a2ea51fe5f44b4d6d ec7642f5d7ba9bdbc35f08f3ffa3c360bd4618d0 --- a/include/elf/common.h +++ b/include/elf/common.h @@ -717,6 +717,7 @@ #define NT_GNU_BUILD_ID 3 /* Generated by ld --build-id. */ #define NT_GNU_GOLD_VERSION 4 /* Generated by gold. */ #define NT_GNU_PROPERTY_TYPE_0 5 /* Generated by gcc. */ +#define NT_GNU_INFINITY 8995 /* Generated by i8c. */ #define NT_GNU_BUILD_ATTRIBUTE_OPEN 0x100 #define NT_GNU_BUILD_ATTRIBUTE_FUNC 0x101 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -17339,6 +17339,8 @@ get_gnu_elf_note_type (unsigned e_type) return _("NT_GNU_BUILD_ATTRIBUTE_OPEN"); case NT_GNU_BUILD_ATTRIBUTE_FUNC: return _("NT_GNU_BUILD_ATTRIBUTE_FUNC"); + case NT_GNU_INFINITY: + return _("NT_GNU_INFINITY (Infinity function)"); default: { static char buff[64]; @@ -17829,6 +17831,133 @@ next: printf ("\n"); } +#define I8_CHUNK_SIGNATURE 1 +#define I8_CHUNK_STRINGS 4 + +typedef enum +{ + I8_NOTE_OK, + I8_NOTE_CORRUPT, + I8_NOTE_UNHANDLED, +} +i8_err_e; + +static i8_err_e +infinity_get_string (const char **result, + unsigned char **ptr, unsigned char *limit, + unsigned char *table_start, + unsigned char *table_limit) +{ + dwarf_vma offset; + unsigned int length; + const char *c; + + /* Read the offset. */ + if (*ptr > limit) + return I8_NOTE_CORRUPT; + + offset = read_uleb128 (*ptr, &length, limit); + *ptr += length; + if (*ptr > limit) + return I8_NOTE_CORRUPT; + + /* Get the string. */ + *result = (const char *) (table_start + offset); + + /* Check the result. */ + for (c = *result; c < (const char *) table_limit; c++) + { + if (*c == '\0') + return I8_NOTE_OK; + + if (*c < ' ' || *c > '~') + return I8_NOTE_UNHANDLED; + } + + return I8_NOTE_CORRUPT; +} + +static i8_err_e +print_infinity_note (Elf_Internal_Note *pnote) +{ + unsigned char *ptr = (unsigned char *) pnote->descdata; + unsigned char *limit = ptr + pnote->descsz; + unsigned char *sig_start = NULL; + unsigned char *str_start = NULL; + unsigned char *sig_limit, *str_limit; + const char *provider, *name, *ptypes, *rtypes; + i8_err_e status; + + /* Locate the info and string table chunks. */ + while (ptr < limit) + { + dwarf_vma type_id, version, size; + unsigned int length; + + type_id = read_uleb128 (ptr, &length, limit); + ptr += length; + if (ptr >= limit) + return I8_NOTE_CORRUPT; + + version = read_uleb128 (ptr, &length, limit); + ptr += length; + if (ptr >= limit) + return I8_NOTE_CORRUPT; + + size = read_uleb128 (ptr, &length, limit); + ptr += length; + if (ptr + size > limit) + return I8_NOTE_CORRUPT; + + switch (type_id) + { + case I8_CHUNK_SIGNATURE: + if (sig_start != NULL || (version != 1 && version != 2)) + return I8_NOTE_UNHANDLED; + + sig_start = ptr; + sig_limit = ptr + size; + break; + + case I8_CHUNK_STRINGS: + if (str_start != NULL || version != 1) + return I8_NOTE_UNHANDLED; + + str_start = ptr; + str_limit = ptr + size; + break; + } + + ptr += size; + } + if (sig_start == NULL || str_start == NULL) + return I8_NOTE_UNHANDLED; + + ptr = sig_start; + status = infinity_get_string (&provider, + &ptr, sig_limit, + str_start, str_limit); + if (status != I8_NOTE_OK) + return status; + status = infinity_get_string (&name, &ptr, sig_limit, + str_start, str_limit); + if (status != I8_NOTE_OK) + return status; + status = infinity_get_string (&ptypes, &ptr, sig_limit, + str_start, str_limit); + if (status != I8_NOTE_OK) + return status; + status = infinity_get_string (&rtypes, &ptr, sig_limit, + str_start, str_limit); + if (status != I8_NOTE_OK) + return status; + + printf (_(" Signature: %s::%s(%s)%s\n"), + provider, name, ptypes, rtypes); + + return I8_NOTE_OK; +} + static bfd_boolean print_gnu_note (Filedata * filedata, Elf_Internal_Note *pnote) { @@ -17946,6 +18075,24 @@ print_gnu_note (Filedata * filedata, Elf printf ("\n"); } break; + + case NT_GNU_INFINITY: + { + switch (print_infinity_note (pnote)) + { + case I8_NOTE_OK: + break; + + case I8_NOTE_CORRUPT: + printf (_(" \n")); + break; + + case I8_NOTE_UNHANDLED: + printf (_(" \n")); + break; + } + break; + } } return TRUE;