From 69e328b532b52befa92fb2d3a52db9914d2c918f Mon Sep 17 00:00:00 2001 From: naruse Date: Sun, 21 Oct 2018 00:07:53 +0000 Subject: Skip dwarf if its version is not supported git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@65256 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- addr2line.c | 220 ++++++++++++++++++++++++++++-------------------------------- 1 file changed, 104 insertions(+), 116 deletions(-) (limited to 'addr2line.c') diff --git a/addr2line.c b/addr2line.c index a035c82f51..244eb56fac 100644 --- a/addr2line.c +++ b/addr2line.c @@ -275,99 +275,114 @@ fill_line(int num_traces, void **traces, uintptr_t addr, int file, int line, } } +struct LineNumberProgramHeader { + uint64_t unit_length; + uint16_t version; + uint8_t format; /* 4 or 8 */ + uint64_t header_length; + uint8_t minimum_instruction_length; + uint8_t maximum_operations_per_instruction; + uint8_t default_is_stmt; + uint8_t line_base; + uint8_t line_range; + uint8_t opcode_base; + /* uint8_t standard_opcode_lengths[opcode_base-1]; */ + const char *include_directories; + const char *filenames; + const char *cu_start; + const char *cu_end; +}; + static int -parse_debug_line_cu(int num_traces, void **traces, char **debug_line, - obj_info_t *obj, line_info_t *lines, int offset) +parse_debug_line_header(const char **pp, struct LineNumberProgramHeader *header) { - char *p, *cu_end, *cu_start, *include_directories, *filenames; - unsigned long unit_length, header_length; - unsigned short dwarf_version; - ptrdiff_t dwarf_word = 4; - int default_is_stmt, line_base; - unsigned int minimum_instruction_length, line_range, opcode_base; - /* unsigned char *standard_opcode_lengths; */ - - /* The registers. */ - unsigned long addr = 0; - unsigned int file = 1; - unsigned int line = 1; - /* unsigned int column = 0; */ - int is_stmt; - /* int basic_block = 0; */ - /* int end_sequence = 0; */ - /* int prologue_end = 0; */ - /* int epilogue_begin = 0; */ - /* unsigned int isa = 0; */ - - p = *debug_line; + const char *p = *pp; + header->unit_length = *(uint32_t *)p; + p += sizeof(uint32_t); - unit_length = *(unsigned int *)p; - p += sizeof(unsigned int); - if (unit_length == 0xffffffff) { - unit_length = *(unsigned long *)p; - p += sizeof(unsigned long); - dwarf_word = 8; + header->format = 4; + if (header->unit_length == 0xffffffff) { + header->unit_length = *(uint64_t *)p; + p += sizeof(uint64_t); + header->format = 8; } - cu_end = p + unit_length; + header->cu_end = p + header->unit_length; - dwarf_version = *(unsigned short *)p; - p += 2; + header->version = *(uint16_t *)p; + p += sizeof(uint16_t); + if (header->version > 4) return -1; - header_length = dwarf_word == 4 ? *(unsigned int *)p : *(unsigned long *)p; - p += dwarf_word; + header->header_length = header->format == 4 ? *(uint32_t *)p : *(uint64_t *)p; + p += header->format; + header->cu_start = p + header->header_length; - cu_start = p + header_length; + header->minimum_instruction_length = *(uint8_t *)p++; - minimum_instruction_length = *(unsigned char *)p; - p++; - - if (dwarf_version >= 4) { - /* maximum_operations_per_instruction = *(unsigned char *)p; */ + if (header->version >= 4) { + /* maximum_operations_per_instruction = *(uint8_t *)p; */ p++; } - is_stmt = default_is_stmt = *(unsigned char *)p; - p++; + header->default_is_stmt = *(uint8_t *)p++; + header->line_base = *(int8_t *)p++; + header->line_range = *(uint8_t *)p++; + header->opcode_base = *(uint8_t *)p++; + /* header->standard_opcode_lengths = (uint8_t *)p - 1; */ + p += header->opcode_base - 1; - line_base = *(signed char *)p; - p++; - - line_range = *(unsigned char *)p; - p++; - - opcode_base = *(unsigned char *)p; - p++; - - /* standard_opcode_lengths = (unsigned char *)p - 1; */ - p += opcode_base - 1; - - include_directories = p; + header->include_directories = p; /* temporary measure for compress-debug-sections */ - if (p >= cu_end) return -1; + if (p >= header->cu_end) return -1; /* skip include directories */ while (*p) { - p = memchr(p, '\0', cu_end - p); + p = memchr(p, '\0', header->cu_end - p); if (!p) return -1; p++; } p++; - filenames = p; + header->filenames = p; + + *pp = header->cu_start; + + return 0; +} + +static int +parse_debug_line_cu(int num_traces, void **traces, char **debug_line, + obj_info_t *obj, line_info_t *lines, int offset) +{ + const char *p = (const char *)*debug_line; + struct LineNumberProgramHeader header; - p = cu_start; + /* The registers. */ + unsigned long addr = 0; + unsigned int file = 1; + unsigned int line = 1; + /* unsigned int column = 0; */ + int is_stmt; + /* int basic_block = 0; */ + /* int end_sequence = 0; */ + /* int prologue_end = 0; */ + /* int epilogue_begin = 0; */ + /* unsigned int isa = 0; */ + + if (parse_debug_line_header(&p, &header)) + return -1; #define FILL_LINE() \ do { \ fill_line(num_traces, traces, addr, file, line, \ - include_directories, filenames, \ + (char *)header.include_directories, \ + (char *)header.filenames, \ obj, lines, offset); \ /*basic_block = prologue_end = epilogue_begin = 0;*/ \ } while (0) - while (p < cu_end) { + while (p < header.cu_end) { unsigned long a; unsigned char op = *p++; switch (op) { @@ -375,19 +390,19 @@ parse_debug_line_cu(int num_traces, void **traces, char **debug_line, FILL_LINE(); break; case DW_LNS_advance_pc: - a = uleb128(&p); + a = uleb128((char **)&p); addr += a; break; case DW_LNS_advance_line: { - long a = sleb128(&p); + long a = sleb128((char **)&p); line += a; break; } case DW_LNS_set_file: - file = (unsigned int)uleb128(&p); + file = (unsigned int)uleb128((char **)&p); break; case DW_LNS_set_column: - /*column = (unsigned int)*/(void)uleb128(&p); + /*column = (unsigned int)*/(void)uleb128((char **)&p); break; case DW_LNS_negate_stmt: is_stmt = !is_stmt; @@ -396,8 +411,8 @@ parse_debug_line_cu(int num_traces, void **traces, char **debug_line, /*basic_block = 1; */ break; case DW_LNS_const_add_pc: - a = ((255 - opcode_base) / line_range) * - minimum_instruction_length; + a = ((255 - header.opcode_base) / header.line_range) * + header.minimum_instruction_length; addr += a; break; case DW_LNS_fixed_advance_pc: @@ -411,7 +426,7 @@ parse_debug_line_cu(int num_traces, void **traces, char **debug_line, /* epilogue_begin = 1; */ break; case DW_LNS_set_isa: - /* isa = (unsigned int)*/(void)uleb128(&p); + /* isa = (unsigned int)*/(void)uleb128((char **)&p); break; case 0: a = *(unsigned char *)p++; @@ -424,7 +439,7 @@ parse_debug_line_cu(int num_traces, void **traces, char **debug_line, file = 1; line = 1; /* column = 0; */ - is_stmt = default_is_stmt; + is_stmt = header.default_is_stmt; /* end_sequence = 0; */ /* isa = 0; */ break; @@ -438,7 +453,7 @@ parse_debug_line_cu(int num_traces, void **traces, char **debug_line, break; case DW_LNE_set_discriminator: /* TODO:currently ignore */ - uleb128(&p); + uleb128((char **)&p); break; default: kprintf("Unknown extended opcode: %d in %s\n", @@ -448,16 +463,16 @@ parse_debug_line_cu(int num_traces, void **traces, char **debug_line, default: { unsigned long addr_incr; unsigned long line_incr; - a = op - opcode_base; - addr_incr = (a / line_range) * minimum_instruction_length; - line_incr = line_base + (a % line_range); + a = op - header.opcode_base; + addr_incr = (a / header.line_range) * header.minimum_instruction_length; + line_incr = header.line_base + (a % header.line_range); addr += (unsigned int)addr_incr; line += (unsigned int)line_incr; FILL_LINE(); } } } - *debug_line = p; + *debug_line = (char *)p; return 0; } @@ -922,49 +937,21 @@ di_read_debug_abbrev_cu(DebugInfoReader *reader) } } -static void +static int di_read_debug_line_cu(DebugInfoReader *reader) { - char *p; - unsigned long unit_length; - unsigned short dwarf_version; - unsigned int opcode_base; - ptrdiff_t dwarf_word = 4; - - p = reader->debug_line_cu_end; - - unit_length = *(unsigned int *)p; - p += sizeof(unsigned int); - if (unit_length == 0xffffffff) { - unit_length = *(unsigned long *)p; - p += sizeof(unsigned long); - dwarf_word = 8; - } + const char *p; + struct LineNumberProgramHeader header; - reader->debug_line_cu_end = p + unit_length; - dwarf_version = *(unsigned short *)p; - p += 2; - p += dwarf_word; - p += dwarf_version >= 4 ? 5 : 4; - opcode_base = *(unsigned char *)p++; + p = (const char *)reader->debug_line_cu_end; + if (parse_debug_line_header(&p, &header)) + return -1; - /* standard_opcode_lengths = (unsigned char *)p - 1; */ - p += opcode_base - 1; + reader->debug_line_cu_end = (char *)header.cu_end; + reader->debug_line_directories = (char *)header.include_directories; + reader->debug_line_files = (char *)header.filenames; - reader->debug_line_directories = p; - - /* skip include directories */ - while (*p) { - p = memchr(p, '\0', reader->debug_line_cu_end - p); - if (!p) { - fprintf(stderr, "Wrongly reached the end of Directory Table at %tx", - reader->debug_line_directories - reader->obj->debug_line.ptr); - abort(); - } - p++; - } - p++; - reader->debug_line_files = p; + return 0; } static void @@ -1423,7 +1410,7 @@ ranges_inspect(DebugInfoReader *reader, ranges_t *ptr) } #endif -static void +static int di_read_cu(DebugInfoReader *reader) { DW_CompilationUnitHeader32 *hdr32 = (DW_CompilationUnitHeader32 *)reader->p; @@ -1445,7 +1432,7 @@ di_read_cu(DebugInfoReader *reader) } reader->level = 0; di_read_debug_abbrev_cu(reader); - di_read_debug_line_cu(reader); + if (di_read_debug_line_cu(reader)) return -1; #if defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER_BUILD_DATE) /* Though DWARF specifies "the applicable base address defaults to the base @@ -1473,6 +1460,7 @@ di_read_cu(DebugInfoReader *reader) } } while (0); #endif + return 0; } static void @@ -1760,7 +1748,7 @@ fill_lines(int num_traces, void **traces, int check_debuglink, i = 0; while (reader.p < reader.pend) { /* fprintf(stderr, "%d:%tx: CU[%d]\n", __LINE__, reader.p - reader.obj->debug_info.ptr, i++); */ - di_read_cu(&reader); + if (di_read_cu(&reader)) goto fail; debug_info_read(&reader, num_traces, traces, lines, offset); } } @@ -1952,7 +1940,7 @@ fill_lines(int num_traces, void **traces, int check_debuglink, DebugInfoReader reader; debug_info_reader_init(&reader, obj); while (reader.p < reader.pend) { - di_read_cu(&reader); + if (di_read_cu(&reader)) goto fail; debug_info_read(&reader, num_traces, traces, lines, offset); } } -- cgit v1.2.3