diff options
author | Mark Wielaard <mark@klomp.org> | 2018-04-26 11:53:49 +0200 |
---|---|---|
committer | Mark Wielaard <mark@klomp.org> | 2018-05-15 11:25:27 +0200 |
commit | 6ed8b94952ddf155960c799ef76f3048f033e873 (patch) | |
tree | b9270241542b3575e08f3639829137dee8caaa67 /src | |
parent | b9c76ded0f07d270bbb9314fb970bb0afcb71d58 (diff) | |
download | elfutils-6ed8b94952ddf155960c799ef76f3048f033e873.tar.gz |
readelf: Add DWARF5 .debug_line support.
This only changes the parsing of the directory and file name tables.
It does this by sharing the printing of (non-CU based) from data from
the .debug_macro code. Adding support for printing strx[1234] form data
by sharing the code that detects the correct str_offsets_base in libdw.
The header format is also cleaned up a bit so that it better lines out.
Testcases adjusted and new ones added.
Signed-off-by: Mark Wielaard <mark@klomp.org>
Diffstat (limited to 'src')
-rw-r--r-- | src/ChangeLog | 11 | ||||
-rw-r--r-- | src/readelf.c | 711 |
2 files changed, 528 insertions, 194 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 24504077..3870508a 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,14 @@ +2018-05-09 Mark Wielaard <mark@klomp.org> + + * readelf.c (dwarf_line_content_description_string): New function. + (dwarf_line_content_description_name): Likewise. + (print_bytes): Likewise. + (print_form_data): Likewise. Based on code taken from... + (print_debug_macro_section): ...here. Now calls print_form_data + and str_offsets_base_off. + (print_debug_line_section): Parse DWARF5 header, directory and file + name tables. + 2018-05-12 Mark Wielaard <mark@klomp.org> * addr2line.c (main): Add fflush (stdout) after handle_address () diff --git a/src/readelf.c b/src/readelf.c index 4b66cd0d..c3154cae 100644 --- a/src/readelf.c +++ b/src/readelf.c @@ -1,7 +1,6 @@ /* Print information from ELF file in human-readable form. - Copyright (C) 1999-2017 Red Hat, Inc. + Copyright (C) 1999-2018 Red Hat, Inc. This file is part of elfutils. - Written by Ulrich Drepper <drepper@redhat.com>, 1999. This file is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -3975,6 +3974,20 @@ dwarf_unit_string (unsigned int type) } +static const char * +dwarf_line_content_description_string (unsigned int kind) +{ + switch (kind) + { +#define DWARF_ONE_KNOWN_DW_LNCT(NAME, CODE) case CODE: return #NAME; + DWARF_ALL_KNOWN_DW_LNCT +#undef DWARF_ONE_KNOWN_DW_LNCT + default: + return NULL; + } +} + + /* Used by all dwarf_foo_name functions. */ static const char * string_or_unknown (const char *known, unsigned int code, @@ -4122,6 +4135,15 @@ dwarf_unit_name (unsigned int type) } +static const char * +dwarf_line_content_description_name (unsigned int kind) +{ + const char *ret = dwarf_line_content_description_string (kind); + return string_or_unknown (ret, kind, DW_LNCT_lo_user, DW_LNCT_hi_user, + false); +} + + static void print_block (size_t n, const void *block) { @@ -4139,6 +4161,17 @@ print_block (size_t n, const void *block) } static void +print_bytes (size_t n, const unsigned char *bytes) +{ + while (n-- > 0) + { + printf ("%02x", *bytes++); + if (n > 0) + printf (" "); + } +} + +static void print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest, unsigned int vers, unsigned int addrsize, unsigned int offset_size, struct Dwarf_CU *cu, Dwarf_Word len, const unsigned char *data) @@ -6749,6 +6782,230 @@ print_decoded_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, } +/* Print the value of a form. + Returns new value of readp, or readendp on failure. */ +static const unsigned char * +print_form_data (Dwarf *dbg, int form, const unsigned char *readp, + const unsigned char *readendp, unsigned int offset_len, + Dwarf_Off str_offsets_base) +{ + Dwarf_Word val; + unsigned char *endp; + Elf_Data *data; + char *str; + switch (form) + { + case DW_FORM_data1: + if (readendp - readp < 1) + { + invalid_data: + error (0, 0, "invalid data"); + return readendp; + } + val = *readp++; + printf (" %" PRIx8, (unsigned int) val); + break; + + case DW_FORM_data2: + if (readendp - readp < 2) + goto invalid_data; + val = read_2ubyte_unaligned_inc (dbg, readp); + printf(" %" PRIx16, (unsigned int) val); + break; + + case DW_FORM_data4: + if (readendp - readp < 4) + goto invalid_data; + val = read_4ubyte_unaligned_inc (dbg, readp); + printf (" %" PRIx32, (unsigned int) val); + break; + + case DW_FORM_data8: + if (readendp - readp < 8) + goto invalid_data; + val = read_8ubyte_unaligned_inc (dbg, readp); + printf (" %" PRIx64, val); + break; + + case DW_FORM_sdata: + if (readendp - readp < 1) + goto invalid_data; + get_sleb128 (val, readp, readendp); + printf (" %" PRIx64, val); + break; + + case DW_FORM_udata: + if (readendp - readp < 1) + goto invalid_data; + get_uleb128 (val, readp, readendp); + printf (" %" PRIx64, val); + break; + + case DW_FORM_block: + if (readendp - readp < 1) + goto invalid_data; + get_uleb128 (val, readp, readendp); + if (readendp - readp < (ptrdiff_t) val) + goto invalid_data; + print_bytes (val, readp); + readp += val; + break; + + case DW_FORM_block1: + if (readendp - readp < 1) + goto invalid_data; + val = *readp++; + if (readendp - readp < (ptrdiff_t) val) + goto invalid_data; + print_bytes (val, readp); + readp += val; + break; + + case DW_FORM_block2: + if (readendp - readp < 2) + goto invalid_data; + val = read_2ubyte_unaligned_inc (dbg, readp); + if (readendp - readp < (ptrdiff_t) val) + goto invalid_data; + print_bytes (val, readp); + readp += val; + break; + + case DW_FORM_block4: + if (readendp - readp < 2) + goto invalid_data; + val = read_4ubyte_unaligned_inc (dbg, readp); + if (readendp - readp < (ptrdiff_t) val) + goto invalid_data; + print_bytes (val, readp); + readp += val; + break; + + case DW_FORM_data16: + if (readendp - readp < 16) + goto invalid_data; + print_bytes (16, readp); + readp += 16; + break; + + case DW_FORM_flag: + if (readendp - readp < 1) + goto invalid_data; + val = *readp++; + printf ("%s", val != 0 ? gettext ("yes") : gettext ("no")); + break; + + case DW_FORM_string: + endp = memchr (readp, '\0', readendp - readp); + if (endp == NULL) + goto invalid_data; + printf ("%s", readp); + readp = endp + 1; + break; + + case DW_FORM_strp: + case DW_FORM_line_strp: + case DW_FORM_strp_sup: + if (readendp - readp < offset_len) + goto invalid_data; + if (offset_len == 8) + val = read_8ubyte_unaligned_inc (dbg, readp); + else + val = read_4ubyte_unaligned_inc (dbg, readp); + if (form == DW_FORM_strp) + data = dbg->sectiondata[IDX_debug_str]; + else if (form == DW_FORM_line_strp) + data = dbg->sectiondata[IDX_debug_line_str]; + else /* form == DW_FORM_strp_sup */ + { + Dwarf *alt = dwarf_getalt (dbg); + data = alt != NULL ? alt->sectiondata[IDX_debug_str] : NULL; + } + if (data == NULL || val >= data->d_size + || memchr (data->d_buf + val, '\0', data->d_size - val) == NULL) + str = "???"; + else + str = (char *) data->d_buf + val; + printf ("%s (%" PRIu64 ")", str, val); + break; + + case DW_FORM_sec_offset: + if (readendp - readp < offset_len) + goto invalid_data; + if (offset_len == 8) + val = read_8ubyte_unaligned_inc (dbg, readp); + else + val = read_4ubyte_unaligned_inc (dbg, readp); + printf ("[%" PRIx64 "]", val); + break; + + case DW_FORM_strx: + if (readendp - readp < 1) + goto invalid_data; + get_uleb128 (val, readp, readendp); + strx_val: + data = dbg->sectiondata[IDX_debug_str_offsets]; + if (data == NULL + || data->d_size - str_offsets_base < val) + str = "???"; + else + { + readp = data->d_buf + str_offsets_base + val; + readendp = data->d_buf + data->d_size; + if (readendp - readp < offset_len) + str = "???"; + else + { + Dwarf_Off idx; + if (offset_len == 8) + idx = read_8ubyte_unaligned_inc (dbg, readp); + else + idx = read_4ubyte_unaligned_inc (dbg, readp); + + data = dbg->sectiondata[IDX_debug_str]; + if (data == NULL || idx >= data->d_size + || memchr (data->d_buf + idx, '\0', + data->d_size - idx) == NULL) + str = "???"; + else + str = (char *) data->d_buf + idx; + } + } + printf ("%s (%" PRIu64 ")", str, val); + break; + + case DW_FORM_strx1: + if (readendp - readp < 1) + goto invalid_data; + val = *readp; + goto strx_val; + + case DW_FORM_strx2: + if (readendp - readp < 2) + goto invalid_data; + val = read_2ubyte_unaligned (dbg, readp); + goto strx_val; + + case DW_FORM_strx3: + if (readendp - readp < 3) + goto invalid_data; + val = read_3ubyte_unaligned (dbg, readp); + goto strx_val; + + case DW_FORM_strx4: + if (readendp - readp < 4) + goto invalid_data; + val = read_4ubyte_unaligned (dbg, readp); + goto strx_val; + + default: + error (0, 0, gettext ("unknown form: %s"), dwarf_form_name (form)); + return readendp; + } + + return readp; +} + static void print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg) @@ -6806,35 +7063,67 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, } /* Check whether we have enough room in the section. */ - if (unlikely (unit_length > (size_t) (lineendp - linep) - || unit_length < 2 + length + 5 * 1)) + if (unlikely (unit_length > (size_t) (lineendp - linep))) goto invalid_data; lineendp = linep + unit_length; /* The next element of the header is the version identifier. */ + if ((size_t) (lineendp - linep) < 2) + goto invalid_data; uint_fast16_t version = read_2ubyte_unaligned_inc (dbg, linep); + size_t address_size + = elf_getident (ebl->elf, NULL)[EI_CLASS] == ELFCLASS32 ? 4 : 8; + unsigned char segment_selector_size = 0; + if (version > 4) + { + if ((size_t) (lineendp - linep) < 2) + goto invalid_data; + address_size = *linep++; + segment_selector_size = *linep++; + } + /* Next comes the header length. */ Dwarf_Word header_length; if (length == 4) - header_length = read_4ubyte_unaligned_inc (dbg, linep); + { + if ((size_t) (lineendp - linep) < 4) + goto invalid_data; + header_length = read_4ubyte_unaligned_inc (dbg, linep); + } else - header_length = read_8ubyte_unaligned_inc (dbg, linep); - //const unsigned char *header_start = linep; + { + if ((size_t) (lineendp - linep) < 8) + goto invalid_data; + header_length = read_8ubyte_unaligned_inc (dbg, linep); + } /* Next the minimum instruction length. */ + if ((size_t) (lineendp - linep) < 1) + goto invalid_data; uint_fast8_t minimum_instr_len = *linep++; /* Next the maximum operations per instruction, in version 4 format. */ - uint_fast8_t max_ops_per_instr = version < 4 ? 1 : *linep++; + uint_fast8_t max_ops_per_instr; + if (version < 4) + max_ops_per_instr = 1; + else + { + if ((size_t) (lineendp - linep) < 1) + goto invalid_data; + max_ops_per_instr = *linep++; + } + + /* We need at least 4 more bytes. */ + if ((size_t) (lineendp - linep) < 4) + goto invalid_data; - /* Then the flag determining the default value of the is_stmt - register. */ + /* Then the flag determining the default value of the is_stmt + register. */ uint_fast8_t default_is_stmt = *linep++; /* Now the line base. */ - int_fast8_t line_base = *((const int_fast8_t *) linep); - ++linep; + int_fast8_t line_base = *linep++; /* And the line range. */ uint_fast8_t line_range = *linep++; @@ -6844,22 +7133,49 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, /* Print what we got so far. */ printf (gettext ("\n" - " Length: %" PRIu64 "\n" - " DWARF version: %" PRIuFAST16 "\n" - " Prologue length: %" PRIu64 "\n" - " Minimum instruction length: %" PRIuFAST8 "\n" - " Maximum operations per instruction: %" PRIuFAST8 "\n" - " Initial value if '%s': %" PRIuFAST8 "\n" - " Line base: %" PRIdFAST8 "\n" - " Line range: %" PRIuFAST8 "\n" - " Opcode base: %" PRIuFAST8 "\n" + " Length: %" PRIu64 "\n" + " DWARF version: %" PRIuFAST16 "\n" + " Prologue length: %" PRIu64 "\n" + " Address size: %zd\n" + " Segment selector size: %zd\n" + " Min instruction length: %" PRIuFAST8 "\n" + " Max operations per instruction: %" PRIuFAST8 "\n" + " Initial value if 'is_stmt': %" PRIuFAST8 "\n" + " Line base: %" PRIdFAST8 "\n" + " Line range: %" PRIuFAST8 "\n" + " Opcode base: %" PRIuFAST8 "\n" "\n" "Opcodes:\n"), (uint64_t) unit_length, version, (uint64_t) header_length, + address_size, (size_t) segment_selector_size, minimum_instr_len, max_ops_per_instr, - "is_stmt", default_is_stmt, line_base, + default_is_stmt, line_base, line_range, opcode_base); + if (version < 2 || version > 5) + { + error (0, 0, gettext ("cannot handle .debug_line version: %u\n"), + (unsigned int) version); + linep = lineendp; + continue; + } + + if (address_size != 4 && address_size != 8) + { + error (0, 0, gettext ("cannot handle address size: %u\n"), + (unsigned int) address_size); + linep = lineendp; + continue; + } + + if (segment_selector_size != 0) + { + error (0, 0, gettext ("cannot handle segment selector size: %u\n"), + (unsigned int) segment_selector_size); + linep = lineendp; + continue; + } + if (unlikely (linep + opcode_base - 1 >= lineendp)) { invalid_unit: @@ -6884,59 +7200,178 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, (int) linep[cnt - 1]), opcode_base_l10, cnt, linep[cnt - 1]); linep += opcode_base - 1; + if (unlikely (linep >= lineendp)) goto invalid_unit; + Dwarf_Off str_offsets_base = str_offsets_base_off (dbg, NULL); + puts (gettext ("\nDirectory table:")); - while (*linep != 0) + if (version > 4) { - unsigned char *endp = memchr (linep, '\0', lineendp - linep); - if (unlikely (endp == NULL)) - goto invalid_unit; + struct encpair { uint16_t desc; uint16_t form; }; + struct encpair enc[256]; + + printf (gettext (" [")); + if ((size_t) (lineendp - linep) < 1) + goto invalid_data; + unsigned char directory_entry_format_count = *linep++; + for (int i = 0; i < directory_entry_format_count; i++) + { + uint16_t desc, form; + if ((size_t) (lineendp - linep) < 1) + goto invalid_data; + get_uleb128 (desc, linep, lineendp); + if ((size_t) (lineendp - linep) < 1) + goto invalid_data; + get_uleb128 (form, linep, lineendp); + + enc[i].desc = desc; + enc[i].form = form; + + printf ("%s(%s)", + dwarf_line_content_description_name (desc), + dwarf_form_name (form)); + if (i + 1 < directory_entry_format_count) + printf (", "); + } + printf ("]\n"); + + uint64_t directories_count; + if ((size_t) (lineendp - linep) < 1) + goto invalid_data; + get_uleb128 (directories_count, linep, lineendp); - printf (" %s\n", (char *) linep); + if (directory_entry_format_count == 0 + && directories_count != 0) + goto invalid_data; + + for (uint64_t i = 0; i < directories_count; i++) + { + printf (" %-5lu ", i); + for (int j = 0; j < directory_entry_format_count; j++) + { + linep = print_form_data (dbg, enc[j].form, + linep, lineendp, length, + str_offsets_base); + if (j + 1 < directory_entry_format_count) + printf (", "); + } + printf ("\n"); + } + } + else + { + while (*linep != 0) + { + unsigned char *endp = memchr (linep, '\0', lineendp - linep); + if (unlikely (endp == NULL)) + goto invalid_unit; - linep = endp + 1; + printf (" %s\n", (char *) linep); + + linep = endp + 1; + } + /* Skip the final NUL byte. */ + ++linep; } - /* Skip the final NUL byte. */ - ++linep; if (unlikely (linep >= lineendp)) goto invalid_unit; - puts (gettext ("\nFile name table:\n" - " Entry Dir Time Size Name")); - for (unsigned int cnt = 1; *linep != 0; ++cnt) + + puts (gettext ("\nFile name table:")); + if (version > 4) { - /* First comes the file name. */ - char *fname = (char *) linep; - unsigned char *endp = memchr (fname, '\0', lineendp - linep); - if (unlikely (endp == NULL)) - goto invalid_unit; - linep = endp + 1; + struct encpair { uint16_t desc; uint16_t form; }; + struct encpair enc[256]; - /* Then the index. */ - unsigned int diridx; - if (lineendp - linep < 1) - goto invalid_unit; - get_uleb128 (diridx, linep, lineendp); + printf (gettext (" [")); + if ((size_t) (lineendp - linep) < 1) + goto invalid_data; + unsigned char file_name_format_count = *linep++; + for (int i = 0; i < file_name_format_count; i++) + { + uint64_t desc, form; + if ((size_t) (lineendp - linep) < 1) + goto invalid_data; + get_uleb128 (desc, linep, lineendp); + if ((size_t) (lineendp - linep) < 1) + goto invalid_data; + get_uleb128 (form, linep, lineendp); - /* Next comes the modification time. */ - unsigned int mtime; - if (lineendp - linep < 1) - goto invalid_unit; - get_uleb128 (mtime, linep, lineendp); + if (! libdw_valid_user_form (form)) + goto invalid_data; - /* Finally the length of the file. */ - unsigned int fsize; - if (lineendp - linep < 1) - goto invalid_unit; - get_uleb128 (fsize, linep, lineendp); + enc[i].desc = desc; + enc[i].form = form; - printf (" %-5u %-5u %-9u %-9u %s\n", - cnt, diridx, mtime, fsize, fname); + printf ("%s(%s)", + dwarf_line_content_description_name (desc), + dwarf_form_name (form)); + if (i + 1 < file_name_format_count) + printf (", "); + } + printf ("]\n"); + + uint64_t file_name_count; + if ((size_t) (lineendp - linep) < 1) + goto invalid_data; + get_uleb128 (file_name_count, linep, lineendp); + + if (file_name_format_count == 0 + && file_name_count != 0) + goto invalid_data; + + for (uint64_t i = 0; i < file_name_count; i++) + { + printf (" %-5lu ", i); + for (int j = 0; j < file_name_format_count; j++) + { + linep = print_form_data (dbg, enc[j].form, + linep, lineendp, length, + str_offsets_base); + if (j + 1 < file_name_format_count) + printf (", "); + } + printf ("\n"); + } + } + else + { + puts (gettext (" Entry Dir Time Size Name")); + for (unsigned int cnt = 1; *linep != 0; ++cnt) + { + /* First comes the file name. */ + char *fname = (char *) linep; + unsigned char *endp = memchr (fname, '\0', lineendp - linep); + if (unlikely (endp == NULL)) + goto invalid_unit; + linep = endp + 1; + + /* Then the index. */ + unsigned int diridx; + if (lineendp - linep < 1) + goto invalid_unit; + get_uleb128 (diridx, linep, lineendp); + + /* Next comes the modification time. */ + unsigned int mtime; + if (lineendp - linep < 1) + goto invalid_unit; + get_uleb128 (mtime, linep, lineendp); + + /* Finally the length of the file. */ + unsigned int fsize; + if (lineendp - linep < 1) + goto invalid_unit; + get_uleb128 (fsize, linep, lineendp); + + printf (" %-5u %-5u %-9u %-9u %s\n", + cnt, diridx, mtime, fsize, fname); + } + /* Skip the final NUL byte. */ + ++linep; } - /* Skip the final NUL byte. */ - ++linep; puts (gettext ("\nLine number statements:")); Dwarf_Word address = 0; @@ -6944,10 +7379,6 @@ print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, size_t line = 1; uint_fast8_t is_stmt = default_is_stmt; - /* Default address value, in case we do not find the CU. */ - size_t address_size - = elf_getident (ebl->elf, NULL)[EI_CLASS] == ELFCLASS32 ? 4 : 8; - /* Determine the CU this block is for. */ Dwarf_Off cuoffset; Dwarf_Off ncuoffset = 0; @@ -7727,6 +8158,18 @@ print_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)), line_offset); } + struct mac_culist *cu = NULL; + if (line_offset != (Dwarf_Off) -1) + { + cu = culist; + while (cu != NULL && line_offset != cu->offset) + cu = cu->next; + } + + Dwarf_Off str_offsets_base = str_offsets_base_off (dbg, (cu != NULL + ? cu->die.cu + : NULL)); + const unsigned char *vendor[DW_MACRO_hi_user - DW_MACRO_lo_user]; memset (vendor, 0, sizeof vendor); if (flag & 0x04) @@ -7810,22 +8253,16 @@ print_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)), /* Find the CU DIE that matches this line offset. */ const char *fname = "???"; - if (line_offset != (Dwarf_Off) -1) + if (cu != NULL) { - struct mac_culist *cu = culist; - while (cu != NULL && line_offset != cu->offset) - cu = cu->next; - if (cu != NULL) - { - if (cu->files == NULL - && dwarf_getsrcfiles (&cu->die, &cu->files, - NULL) != 0) - cu->files = (Dwarf_Files *) -1l; - - if (cu->files != (Dwarf_Files *) -1l) - fname = (dwarf_filesrc (cu->files, u128_2, - NULL, NULL) ?: "???"); - } + if (cu->files == NULL + && dwarf_getsrcfiles (&cu->die, &cu->files, + NULL) != 0) + cu->files = (Dwarf_Files *) -1l; + + if (cu->files != (Dwarf_Files *) -1l) + fname = (dwarf_filesrc (cu->files, u128_2, + NULL, NULL) ?: "???"); } printf ("%*sstart_file %u, [%u] %s\n", level, "", u128, u128_2, fname); @@ -7971,125 +8408,11 @@ print_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)), while (args > 0) { unsigned int form = *op_desc++; - Dwarf_Word val; - switch (form) - { - case DW_FORM_data1: - if (readp + 1 > readendp) - goto invalid_data; - val = *readp++; - printf (" %" PRIx8, (unsigned int) val); - break; - - case DW_FORM_data2: - if (readp + 2 > readendp) - goto invalid_data; - val = read_2ubyte_unaligned_inc (dbg, readp); - printf(" %" PRIx16, (unsigned int) val); - break; - - case DW_FORM_data4: - if (readp + 4 > readendp) - goto invalid_data; - val = read_4ubyte_unaligned_inc (dbg, readp); - printf (" %" PRIx32, (unsigned int) val); - break; - - case DW_FORM_data8: - if (readp + 8 > readendp) - goto invalid_data; - val = read_8ubyte_unaligned_inc (dbg, readp); - printf (" %" PRIx64, val); - break; - - case DW_FORM_sdata: - get_sleb128 (val, readp, readendp); - printf (" %" PRIx64, val); - break; - - case DW_FORM_udata: - get_uleb128 (val, readp, readendp); - printf (" %" PRIx64, val); - break; - - case DW_FORM_block: - get_uleb128 (val, readp, readendp); - printf (" block[%" PRIu64 "]", val); - if (readp + val > readendp) - goto invalid_data; - readp += val; - break; - - case DW_FORM_block1: - if (readp + 1 > readendp) - goto invalid_data; - val = *readp++; - printf (" block[%" PRIu64 "]", val); - if (readp + val > readendp) - goto invalid_data; - break; - - case DW_FORM_block2: - if (readp + 2 > readendp) - goto invalid_data; - val = read_2ubyte_unaligned_inc (dbg, readp); - printf (" block[%" PRIu64 "]", val); - if (readp + val > readendp) - goto invalid_data; - break; - - case DW_FORM_block4: - if (readp + 2 > readendp) - goto invalid_data; - val =read_4ubyte_unaligned_inc (dbg, readp); - printf (" block[%" PRIu64 "]", val); - if (readp + val > readendp) - goto invalid_data; - break; - - case DW_FORM_flag: - if (readp + 1 > readendp) - goto invalid_data; - val = *readp++; - printf (" %s", val != 0 ? gettext ("yes") : gettext ("no")); - break; - - case DW_FORM_string: - endp = memchr (readp, '\0', readendp - readp); - if (endp == NULL) - goto invalid_data; - printf (" %s", readp); - readp = endp + 1; - break; - - case DW_FORM_strp: - if (readp + offset_len > readendp) - goto invalid_data; - if (offset_len == 8) - val = read_8ubyte_unaligned_inc (dbg, readp); - else - val = read_4ubyte_unaligned_inc (dbg, readp); - printf (" %s", dwarf_getstring (dbg, val, NULL)); - break; - - case DW_FORM_sec_offset: - if (readp + offset_len > readendp) - goto invalid_data; - if (offset_len == 8) - val = read_8ubyte_unaligned_inc (dbg, readp); - else - val = read_4ubyte_unaligned_inc (dbg, readp); - printf (" %" PRIx64, val); - break; - - default: - error (0, 0, gettext ("vendor opcode not verified?")); - return; - } - + print_form_data (dbg, form, readp, readendp, offset_len, + str_offsets_base); args--; if (args > 0) - putchar_unlocked (','); + printf (", "); } putchar_unlocked ('\n'); } |