X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=bfd%2Fdwarf2.c;h=4cf50ccddd07d08f4961c521c6efb26cfd64fd35;hb=4b04bba2eb6b646e11a2c38c77667875b3db6828;hp=722ee0d9f5501e9c75a7c84b993a5cd8d1cd62b7;hpb=c7c3d11bead272b718bade379e3441ff239bbd16;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/dwarf2.c b/bfd/dwarf2.c index 722ee0d9f5..4cf50ccddd 100644 --- a/bfd/dwarf2.c +++ b/bfd/dwarf2.c @@ -125,8 +125,7 @@ struct dwarf2_debug /* A pointer to the memory block allocated for info_ptr. Neither info_ptr nor sec_info_ptr are guaranteed to stay pointing to the - beginning of the malloc block. This is used only to free the - memory later. */ + beginning of the malloc block. */ bfd_byte *info_ptr_memory; /* Pointer to the symbol table. */ @@ -150,6 +149,12 @@ struct dwarf2_debug /* Length of the loaded .debug_str section. */ bfd_size_type dwarf_str_size; + /* Pointer to the .debug_line_str section loaded into memory. */ + bfd_byte *dwarf_line_str_buffer; + + /* Length of the loaded .debug_line_str section. */ + bfd_size_type dwarf_line_str_size; + /* Pointer to the .debug_ranges section loaded into memory. */ bfd_byte *dwarf_ranges_buffer; @@ -244,9 +249,6 @@ struct comp_unit by its reference. */ bfd_byte *info_ptr_unit; - /* Pointer to the start of the debug section, for DW_FORM_ref_addr. */ - bfd_byte *sec_info_ptr; - /* The offset into .debug_line of the line number table. */ unsigned long line_offset; @@ -306,6 +308,7 @@ struct attr_abbrev { enum dwarf_attribute name; enum dwarf_form form; + bfd_vma implicit_const; }; /* Map of uncompressed DWARF debug section name to compressed one. It @@ -329,6 +332,7 @@ const struct dwarf_debug_section dwarf_debug_sections[] = { ".debug_static_vars", ".zdebug_static_vars" }, { ".debug_str", ".zdebug_str", }, { ".debug_str", ".zdebug_str", }, + { ".debug_line_str", ".zdebug_line_str", }, { ".debug_types", ".zdebug_types" }, /* GNU DWARF 1 extensions */ { ".debug_sfnames", ".zdebug_sfnames" }, @@ -361,15 +365,21 @@ enum dwarf_debug_section_enum debug_static_vars, debug_str, debug_str_alt, + debug_line_str, debug_types, debug_sfnames, debug_srcinfo, debug_funcnames, debug_typenames, debug_varnames, - debug_weaknames + debug_weaknames, + debug_max }; +/* A static assertion. */ +extern int dwarf_debug_section_assert[ARRAY_SIZE (dwarf_debug_sections) + == debug_max + 1 ? 1 : -1]; + #ifndef ABBREV_HASH_SIZE #define ABBREV_HASH_SIZE 121 #endif @@ -516,9 +526,10 @@ read_section (bfd * abfd, { asection *msec; const char *section_name = sec->uncompressed_name; + bfd_byte *contents = *section_buffer; /* The section may have already been read. */ - if (*section_buffer == NULL) + if (contents == NULL) { msec = bfd_get_section_by_name (abfd, section_name); if (! msec) @@ -536,22 +547,21 @@ read_section (bfd * abfd, } *section_size = msec->rawsize ? msec->rawsize : msec->size; - if (syms) - { - *section_buffer - = bfd_simple_get_relocated_section_contents (abfd, msec, NULL, syms); - if (! *section_buffer) - return FALSE; - } - else + /* Paranoia - alloc one extra so that we can make sure a string + section is NUL terminated. */ + contents = (bfd_byte *) bfd_malloc (*section_size + 1); + if (contents == NULL) + return FALSE; + if (syms + ? !bfd_simple_get_relocated_section_contents (abfd, msec, contents, + syms) + : !bfd_get_section_contents (abfd, msec, contents, 0, *section_size)) { - *section_buffer = (bfd_byte *) bfd_malloc (*section_size); - if (! *section_buffer) - return FALSE; - if (! bfd_get_section_contents (abfd, msec, *section_buffer, - 0, *section_size)) - return FALSE; + free (contents); + return FALSE; } + contents[*section_size] = 0; + *section_buffer = contents; } /* It is possible to get a bad value for the offset into the section @@ -559,9 +569,9 @@ read_section (bfd * abfd, if (offset != 0 && offset >= *section_size) { /* xgettext: c-format */ - _bfd_error_handler (_("Dwarf Error: Offset (%lu)" - " greater than or equal to %s size (%lu)."), - (long) offset, section_name, *section_size); + _bfd_error_handler (_("Dwarf Error: Offset (%llu)" + " greater than or equal to %s size (%Lu)."), + (long long) offset, section_name, *section_size); bfd_set_error (bfd_error_bad_value); return FALSE; } @@ -703,6 +713,45 @@ read_indirect_string (struct comp_unit * unit, return str; } +/* Like read_indirect_string but from .debug_line_str section. */ + +static char * +read_indirect_line_string (struct comp_unit * unit, + bfd_byte * buf, + bfd_byte * buf_end, + unsigned int * bytes_read_ptr) +{ + bfd_uint64_t offset; + struct dwarf2_debug *stash = unit->stash; + char *str; + + if (buf + unit->offset_size > buf_end) + { + * bytes_read_ptr = 0; + return NULL; + } + + if (unit->offset_size == 4) + offset = read_4_bytes (unit->abfd, buf, buf_end); + else + offset = read_8_bytes (unit->abfd, buf, buf_end); + + *bytes_read_ptr = unit->offset_size; + + if (! read_section (unit->abfd, &stash->debug_sections[debug_line_str], + stash->syms, offset, + &stash->dwarf_line_str_buffer, + &stash->dwarf_line_str_size)) + return NULL; + + if (offset >= stash->dwarf_line_str_size) + return NULL; + str = (char *) stash->dwarf_line_str_buffer + offset; + if (*str == '\0') + return NULL; + return str; +} + /* Like read_indirect_string but uses a .debug_str located in an alternate file pointed to by the .gnu_debugaltlink section. Used to impement DW_FORM_GNU_strp_alt. */ @@ -928,15 +977,28 @@ read_abbrevs (bfd *abfd, bfd_uint64_t offset, struct dwarf2_debug *stash) abbrev_ptr += 1; /* Now read in declarations. */ - abbrev_name = _bfd_safe_read_leb128 (abfd, abbrev_ptr, &bytes_read, - FALSE, abbrev_end); - abbrev_ptr += bytes_read; - abbrev_form = _bfd_safe_read_leb128 (abfd, abbrev_ptr, &bytes_read, - FALSE, abbrev_end); - abbrev_ptr += bytes_read; - - while (abbrev_name) + for (;;) { + /* Initialize it just to avoid a GCC false warning. */ + bfd_vma implicit_const = -1; + + abbrev_name = _bfd_safe_read_leb128 (abfd, abbrev_ptr, &bytes_read, + FALSE, abbrev_end); + abbrev_ptr += bytes_read; + abbrev_form = _bfd_safe_read_leb128 (abfd, abbrev_ptr, &bytes_read, + FALSE, abbrev_end); + abbrev_ptr += bytes_read; + if (abbrev_form == DW_FORM_implicit_const) + { + implicit_const = _bfd_safe_read_leb128 (abfd, abbrev_ptr, + &bytes_read, TRUE, + abbrev_end); + abbrev_ptr += bytes_read; + } + + if (abbrev_name == 0) + break; + if ((cur_abbrev->num_attrs % ATTR_ALLOC_CHUNK) == 0) { struct attr_abbrev *tmp; @@ -965,14 +1027,11 @@ read_abbrevs (bfd *abfd, bfd_uint64_t offset, struct dwarf2_debug *stash) cur_abbrev->attrs[cur_abbrev->num_attrs].name = (enum dwarf_attribute) abbrev_name; - cur_abbrev->attrs[cur_abbrev->num_attrs++].form + cur_abbrev->attrs[cur_abbrev->num_attrs].form = (enum dwarf_form) abbrev_form; - abbrev_name = _bfd_safe_read_leb128 (abfd, abbrev_ptr, &bytes_read, - FALSE, abbrev_end); - abbrev_ptr += bytes_read; - abbrev_form = _bfd_safe_read_leb128 (abfd, abbrev_ptr, &bytes_read, - FALSE, abbrev_end); - abbrev_ptr += bytes_read; + cur_abbrev->attrs[cur_abbrev->num_attrs].implicit_const + = implicit_const; + ++cur_abbrev->num_attrs; } hash_number = abbrev_number % ABBREV_HASH_SIZE; @@ -1004,7 +1063,8 @@ read_abbrevs (bfd *abfd, bfd_uint64_t offset, struct dwarf2_debug *stash) static inline bfd_boolean is_str_attr (enum dwarf_form form) { - return form == DW_FORM_string || form == DW_FORM_strp || form == DW_FORM_GNU_strp_alt; + return (form == DW_FORM_string || form == DW_FORM_strp + || form == DW_FORM_line_strp || form == DW_FORM_GNU_strp_alt); } /* Read and fill in the value of attribute ATTR as described by FORM. @@ -1014,6 +1074,7 @@ is_str_attr (enum dwarf_form form) static bfd_byte * read_attribute_value (struct attribute * attr, unsigned form, + bfd_vma implicit_const, struct comp_unit * unit, bfd_byte * info_ptr, bfd_byte * info_ptr_end) @@ -1101,6 +1162,10 @@ read_attribute_value (struct attribute * attr, attr->u.str = read_indirect_string (unit, info_ptr, info_ptr_end, &bytes_read); info_ptr += bytes_read; break; + case DW_FORM_line_strp: + attr->u.str = read_indirect_line_string (unit, info_ptr, info_ptr_end, &bytes_read); + info_ptr += bytes_read; + break; case DW_FORM_GNU_strp_alt: attr->u.str = read_alt_indirect_string (unit, info_ptr, info_ptr_end, &bytes_read); info_ptr += bytes_read; @@ -1179,7 +1244,18 @@ read_attribute_value (struct attribute * attr, form = _bfd_safe_read_leb128 (abfd, info_ptr, &bytes_read, FALSE, info_ptr_end); info_ptr += bytes_read; - info_ptr = read_attribute_value (attr, form, unit, info_ptr, info_ptr_end); + if (form == DW_FORM_implicit_const) + { + implicit_const = _bfd_safe_read_leb128 (abfd, info_ptr, &bytes_read, + TRUE, info_ptr_end); + info_ptr += bytes_read; + } + info_ptr = read_attribute_value (attr, form, implicit_const, unit, + info_ptr, info_ptr_end); + break; + case DW_FORM_implicit_const: + attr->form = DW_FORM_sdata; + attr->u.sval = implicit_const; break; default: _bfd_error_handler (_("Dwarf Error: Invalid or unhandled FORM value: %#x."), @@ -1200,7 +1276,8 @@ read_attribute (struct attribute * attr, bfd_byte * info_ptr_end) { attr->name = abbrev->name; - info_ptr = read_attribute_value (attr, abbrev->form, unit, info_ptr, info_ptr_end); + info_ptr = read_attribute_value (attr, abbrev->form, abbrev->implicit_const, + unit, info_ptr, info_ptr_end); return info_ptr; } @@ -1493,6 +1570,8 @@ concat_filename (struct line_info_table *table, unsigned int file) } filename = table->files[file - 1].name; + if (filename == NULL) + return strdup (""); if (!IS_ABSOLUTE_PATH (filename)) { @@ -1734,6 +1813,191 @@ sort_line_sequences (struct line_info_table* table) return TRUE; } +/* Add directory to TABLE. CUR_DIR memory ownership is taken by TABLE. */ + +static bfd_boolean +line_info_add_include_dir (struct line_info_table *table, char *cur_dir) +{ + if ((table->num_dirs % DIR_ALLOC_CHUNK) == 0) + { + char **tmp; + bfd_size_type amt; + + amt = table->num_dirs + DIR_ALLOC_CHUNK; + amt *= sizeof (char *); + + tmp = (char **) bfd_realloc (table->dirs, amt); + if (tmp == NULL) + return FALSE; + table->dirs = tmp; + } + + table->dirs[table->num_dirs++] = cur_dir; + return TRUE; +} + +static bfd_boolean +line_info_add_include_dir_stub (struct line_info_table *table, char *cur_dir, + unsigned int dir ATTRIBUTE_UNUSED, + unsigned int xtime ATTRIBUTE_UNUSED, + unsigned int size ATTRIBUTE_UNUSED) +{ + return line_info_add_include_dir (table, cur_dir); +} + +/* Add file to TABLE. CUR_FILE memory ownership is taken by TABLE. */ + +static bfd_boolean +line_info_add_file_name (struct line_info_table *table, char *cur_file, + unsigned int dir, unsigned int xtime, + unsigned int size) +{ + if ((table->num_files % FILE_ALLOC_CHUNK) == 0) + { + struct fileinfo *tmp; + bfd_size_type amt; + + amt = table->num_files + FILE_ALLOC_CHUNK; + amt *= sizeof (struct fileinfo); + + tmp = (struct fileinfo *) bfd_realloc (table->files, amt); + if (tmp == NULL) + return FALSE; + table->files = tmp; + } + + table->files[table->num_files].name = cur_file; + table->files[table->num_files].dir = dir; + table->files[table->num_files].time = xtime; + table->files[table->num_files].size = size; + table->num_files++; + return TRUE; +} + +/* Read directory or file name entry format, starting with byte of + format count entries, ULEB128 pairs of entry formats, ULEB128 of + entries count and the entries themselves in the described entry + format. */ + +static bfd_boolean +read_formatted_entries (struct comp_unit *unit, bfd_byte **bufp, + bfd_byte *buf_end, struct line_info_table *table, + bfd_boolean (*callback) (struct line_info_table *table, + char *cur_file, + unsigned int dir, + unsigned int time, + unsigned int size)) +{ + bfd *abfd = unit->abfd; + bfd_byte format_count, formati; + bfd_vma data_count, datai; + bfd_byte *buf = *bufp; + bfd_byte *format_header_data; + unsigned int bytes_read; + + format_count = read_1_byte (abfd, buf, buf_end); + buf += 1; + format_header_data = buf; + for (formati = 0; formati < format_count; formati++) + { + _bfd_safe_read_leb128 (abfd, buf, &bytes_read, FALSE, buf_end); + buf += bytes_read; + _bfd_safe_read_leb128 (abfd, buf, &bytes_read, FALSE, buf_end); + buf += bytes_read; + } + + data_count = _bfd_safe_read_leb128 (abfd, buf, &bytes_read, FALSE, buf_end); + buf += bytes_read; + if (format_count == 0 && data_count != 0) + { + _bfd_error_handler (_("Dwarf Error: Zero format count.")); + bfd_set_error (bfd_error_bad_value); + return FALSE; + } + + /* PR 22210. Paranoia check. Don't bother running the loop + if we know that we are going to run out of buffer. */ + if (data_count > (bfd_vma) (buf_end - buf)) + { + _bfd_error_handler (_("Dwarf Error: data count (%Lx) larger than buffer size."), + data_count); + bfd_set_error (bfd_error_bad_value); + return FALSE; + } + + for (datai = 0; datai < data_count; datai++) + { + bfd_byte *format = format_header_data; + struct fileinfo fe; + + memset (&fe, 0, sizeof fe); + for (formati = 0; formati < format_count; formati++) + { + bfd_vma content_type, form; + char *string_trash; + char **stringp = &string_trash; + unsigned int uint_trash, *uintp = &uint_trash; + struct attribute attr; + + content_type = _bfd_safe_read_leb128 (abfd, format, &bytes_read, + FALSE, buf_end); + format += bytes_read; + switch (content_type) + { + case DW_LNCT_path: + stringp = &fe.name; + break; + case DW_LNCT_directory_index: + uintp = &fe.dir; + break; + case DW_LNCT_timestamp: + uintp = &fe.time; + break; + case DW_LNCT_size: + uintp = &fe.size; + break; + case DW_LNCT_MD5: + break; + default: + _bfd_error_handler + (_("Dwarf Error: Unknown format content type %Lu."), + content_type); + bfd_set_error (bfd_error_bad_value); + return FALSE; + } + + form = _bfd_safe_read_leb128 (abfd, format, &bytes_read, FALSE, + buf_end); + format += bytes_read; + + buf = read_attribute_value (&attr, form, 0, unit, buf, buf_end); + if (buf == NULL) + return FALSE; + switch (form) + { + case DW_FORM_string: + case DW_FORM_line_strp: + *stringp = attr.u.str; + break; + + case DW_FORM_data1: + case DW_FORM_data2: + case DW_FORM_data4: + case DW_FORM_data8: + case DW_FORM_udata: + *uintp = attr.u.val; + break; + } + } + + if (!callback (table, fe.name, fe.dir, fe.time, fe.size)) + return FALSE; + } + + *bufp = buf; + return TRUE; +} + /* Decode the line number information for UNIT. */ static struct line_info_table* @@ -1776,8 +2040,8 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash) if (stash->dwarf_line_size < 16) { _bfd_error_handler - (_("Dwarf Error: Line info section is too small (%ld)"), - (long) stash->dwarf_line_size); + (_("Dwarf Error: Line info section is too small (%Ld)"), + stash->dwarf_line_size); bfd_set_error (bfd_error_bad_value); return NULL; } @@ -1802,12 +2066,13 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash) offset_size = 8; } - if (lh.total_length > stash->dwarf_line_size) + if (lh.total_length > (size_t) (line_end - line_ptr)) { _bfd_error_handler /* xgettext: c-format */ - (_("Dwarf Error: Line info data is bigger (0x%lx) than the section (0x%lx)"), - (long) lh.total_length, (long) stash->dwarf_line_size); + (_("Dwarf Error: Line info data is bigger (%#Lx)" + " than the space remaining in the section (%#lx)"), + lh.total_length, (unsigned long) (line_end - line_ptr)); bfd_set_error (bfd_error_bad_value); return NULL; } @@ -1815,7 +2080,7 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash) line_end = line_ptr + lh.total_length; lh.version = read_2_bytes (abfd, line_ptr, line_end); - if (lh.version < 2 || lh.version > 4) + if (lh.version < 2 || lh.version > 5) { _bfd_error_handler (_("Dwarf Error: Unhandled .debug_line version %d."), lh.version); @@ -1824,7 +2089,8 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash) } line_ptr += 2; - if (line_ptr + offset_size + (lh.version >=4 ? 6 : 5) >= line_end) + if (line_ptr + offset_size + (lh.version >= 5 ? 8 : (lh.version >= 4 ? 6 : 5)) + >= line_end) { _bfd_error_handler (_("Dwarf Error: Ran out of room reading prologue")); @@ -1832,6 +2098,26 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash) return NULL; } + if (lh.version >= 5) + { + unsigned int segment_selector_size; + + /* Skip address size. */ + read_1_byte (abfd, line_ptr, line_end); + line_ptr += 1; + + segment_selector_size = read_1_byte (abfd, line_ptr, line_end); + line_ptr += 1; + if (segment_selector_size != 0) + { + _bfd_error_handler + (_("Dwarf Error: Line info unsupported segment selector size %u."), + segment_selector_size); + bfd_set_error (bfd_error_bad_value); + return NULL; + } + } + if (offset_size == 4) lh.prologue_length = read_4_bytes (abfd, line_ptr, line_end); else @@ -1887,62 +2173,52 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash) line_ptr += 1; } - /* Read directory table. */ - while ((cur_dir = read_string (abfd, line_ptr, line_end, &bytes_read)) != NULL) + if (lh.version >= 5) { - line_ptr += bytes_read; + /* Read directory table. */ + if (!read_formatted_entries (unit, &line_ptr, line_end, table, + line_info_add_include_dir_stub)) + goto fail; - if ((table->num_dirs % DIR_ALLOC_CHUNK) == 0) + /* Read file name table. */ + if (!read_formatted_entries (unit, &line_ptr, line_end, table, + line_info_add_file_name)) + goto fail; + } + else + { + /* Read directory table. */ + while ((cur_dir = read_string (abfd, line_ptr, line_end, &bytes_read)) != NULL) { - char **tmp; + line_ptr += bytes_read; - amt = table->num_dirs + DIR_ALLOC_CHUNK; - amt *= sizeof (char *); - - tmp = (char **) bfd_realloc (table->dirs, amt); - if (tmp == NULL) + if (!line_info_add_include_dir (table, cur_dir)) goto fail; - table->dirs = tmp; } - table->dirs[table->num_dirs++] = cur_dir; - } - - line_ptr += bytes_read; - - /* Read file name table. */ - while ((cur_file = read_string (abfd, line_ptr, line_end, &bytes_read)) != NULL) - { line_ptr += bytes_read; - if ((table->num_files % FILE_ALLOC_CHUNK) == 0) + /* Read file name table. */ + while ((cur_file = read_string (abfd, line_ptr, line_end, &bytes_read)) != NULL) { - struct fileinfo *tmp; + unsigned int dir, xtime, size; + + line_ptr += bytes_read; - amt = table->num_files + FILE_ALLOC_CHUNK; - amt *= sizeof (struct fileinfo); + dir = _bfd_safe_read_leb128 (abfd, line_ptr, &bytes_read, FALSE, line_end); + line_ptr += bytes_read; + xtime = _bfd_safe_read_leb128 (abfd, line_ptr, &bytes_read, FALSE, line_end); + line_ptr += bytes_read; + size = _bfd_safe_read_leb128 (abfd, line_ptr, &bytes_read, FALSE, line_end); + line_ptr += bytes_read; - tmp = (struct fileinfo *) bfd_realloc (table->files, amt); - if (tmp == NULL) + if (!line_info_add_file_name (table, cur_file, dir, xtime, size)) goto fail; - table->files = tmp; } - table->files[table->num_files].name = cur_file; - table->files[table->num_files].dir = - _bfd_safe_read_leb128 (abfd, line_ptr, &bytes_read, FALSE, line_end); line_ptr += bytes_read; - table->files[table->num_files].time - = _bfd_safe_read_leb128 (abfd, line_ptr, &bytes_read, FALSE, line_end); - line_ptr += bytes_read; - table->files[table->num_files].size - = _bfd_safe_read_leb128 (abfd, line_ptr, &bytes_read, FALSE, line_end); - line_ptr += bytes_read; - table->num_files++; } - line_ptr += bytes_read; - /* Read the statement sequences until there's nothing left. */ while (line_ptr < line_end) { @@ -1955,6 +2231,7 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash) unsigned int discriminator = 0; int is_stmt = lh.default_is_stmt; int end_sequence = 0; + unsigned int dir, xtime, size; /* eraxxon@alumni.rice.edu: Against the DWARF2 specs, some compilers generate address sequences that are wildly out of order using DW_LNE_set_address (e.g. Intel C++ 6.0 compiler @@ -1964,7 +2241,7 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash) bfd_vma high_pc = 0; /* Decode the table. */ - while (! end_sequence) + while (!end_sequence && line_ptr < line_end) { op_code = read_1_byte (abfd, line_ptr, line_end); line_ptr += 1; @@ -2029,31 +2306,18 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash) case DW_LNE_define_file: cur_file = read_string (abfd, line_ptr, line_end, &bytes_read); line_ptr += bytes_read; - if ((table->num_files % FILE_ALLOC_CHUNK) == 0) - { - struct fileinfo *tmp; - - amt = table->num_files + FILE_ALLOC_CHUNK; - amt *= sizeof (struct fileinfo); - tmp = (struct fileinfo *) bfd_realloc (table->files, amt); - if (tmp == NULL) - goto line_fail; - table->files = tmp; - } - table->files[table->num_files].name = cur_file; - table->files[table->num_files].dir = - _bfd_safe_read_leb128 (abfd, line_ptr, &bytes_read, - FALSE, line_end); + dir = _bfd_safe_read_leb128 (abfd, line_ptr, &bytes_read, + FALSE, line_end); line_ptr += bytes_read; - table->files[table->num_files].time = - _bfd_safe_read_leb128 (abfd, line_ptr, &bytes_read, - FALSE, line_end); + xtime = _bfd_safe_read_leb128 (abfd, line_ptr, &bytes_read, + FALSE, line_end); line_ptr += bytes_read; - table->files[table->num_files].size = - _bfd_safe_read_leb128 (abfd, line_ptr, &bytes_read, - FALSE, line_end); + size = _bfd_safe_read_leb128 (abfd, line_ptr, &bytes_read, + FALSE, line_end); line_ptr += bytes_read; - table->num_files++; + if (!line_info_add_file_name (table, cur_file, dir, + xtime, size)) + goto line_fail; break; case DW_LNE_set_discriminator: discriminator = @@ -2131,6 +2395,8 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash) case DW_LNS_set_basic_block: break; case DW_LNS_const_add_pc: + if (lh.line_range == 0) + goto line_fail; if (lh.maximum_ops_per_insn == 1) address += (lh.minimum_instruction_length * ((255 - lh.opcode_base) / lh.line_range)); @@ -2168,8 +2434,12 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash) return table; fail: - if (table->sequences != NULL) - free (table->sequences); + while (table->sequences != NULL) + { + struct line_sequence* seq = table->sequences; + table->sequences = table->sequences->prev_sequence; + free (seq); + } if (table->files != NULL) free (table->files); if (table->dirs != NULL) @@ -2518,9 +2788,11 @@ lookup_symbol_in_variable_table (struct comp_unit *unit, return FALSE; } -static char * +static bfd_boolean find_abstract_instance_name (struct comp_unit *unit, + bfd_byte *orig_info_ptr, struct attribute *attr_ptr, + const char **pname, bfd_boolean *is_linkage) { bfd *abfd = unit->abfd; @@ -2530,23 +2802,44 @@ find_abstract_instance_name (struct comp_unit *unit, struct abbrev_info *abbrev; bfd_uint64_t die_ref = attr_ptr->u.val; struct attribute attr; - char *name = NULL; + const char *name = NULL; /* DW_FORM_ref_addr can reference an entry in a different CU. It is an offset from the .debug_info section, not the current CU. */ if (attr_ptr->form == DW_FORM_ref_addr) { /* We only support DW_FORM_ref_addr within the same file, so - any relocations should be resolved already. */ - if (!die_ref) - abort (); - - info_ptr = unit->sec_info_ptr + die_ref; - info_ptr_end = unit->end_ptr; + any relocations should be resolved already. Check this by + testing for a zero die_ref; There can't be a valid reference + to the header of a .debug_info section. + DW_FORM_ref_addr is an offset relative to .debug_info. + Normally when using the GNU linker this is accomplished by + emitting a symbolic reference to a label, because .debug_info + sections are linked at zero. When there are multiple section + groups containing .debug_info, as there might be in a + relocatable object file, it would be reasonable to assume that + a symbolic reference to a label in any .debug_info section + might be used. Since we lay out multiple .debug_info + sections at non-zero VMAs (see place_sections), and read + them contiguously into stash->info_ptr_memory, that means + the reference is relative to stash->info_ptr_memory. */ + size_t total; + + info_ptr = unit->stash->info_ptr_memory; + info_ptr_end = unit->stash->info_ptr_end; + total = info_ptr_end - info_ptr; + if (!die_ref || die_ref >= total) + { + _bfd_error_handler + (_("Dwarf Error: Invalid abstract instance DIE ref.")); + bfd_set_error (bfd_error_bad_value); + return FALSE; + } + info_ptr += die_ref; /* Now find the CU containing this pointer. */ if (info_ptr >= unit->info_ptr_unit && info_ptr < unit->end_ptr) - ; + info_ptr_end = unit->end_ptr; else { /* Check other CUs to see if they contain the abbrev. */ @@ -2562,7 +2855,10 @@ find_abstract_instance_name (struct comp_unit *unit, break; if (u) - unit = u; + { + unit = u; + info_ptr_end = unit->end_ptr; + } /* else FIXME: What do we do now ? */ } } @@ -2572,19 +2868,35 @@ find_abstract_instance_name (struct comp_unit *unit, if (info_ptr == NULL) { _bfd_error_handler - (_("Dwarf Error: Unable to read alt ref %u."), die_ref); + (_("Dwarf Error: Unable to read alt ref %llu."), + (long long) die_ref); bfd_set_error (bfd_error_bad_value); - return NULL; + return FALSE; } - info_ptr_end = unit->stash->alt_dwarf_info_buffer + unit->stash->alt_dwarf_info_size; + info_ptr_end = (unit->stash->alt_dwarf_info_buffer + + unit->stash->alt_dwarf_info_size); /* FIXME: Do we need to locate the correct CU, in a similar fashion to the code in the DW_FORM_ref_addr case above ? */ } else { - info_ptr = unit->info_ptr_unit + die_ref; + /* DW_FORM_ref1, DW_FORM_ref2, DW_FORM_ref4, DW_FORM_ref8 or + DW_FORM_ref_udata. These are all references relative to the + start of the current CU. */ + size_t total; + + info_ptr = unit->info_ptr_unit; info_ptr_end = unit->end_ptr; + total = info_ptr_end - info_ptr; + if (!die_ref || die_ref >= total) + { + _bfd_error_handler + (_("Dwarf Error: Invalid abstract instance DIE ref.")); + bfd_set_error (bfd_error_bad_value); + return FALSE; + } + info_ptr += die_ref; } abbrev_number = _bfd_safe_read_leb128 (abfd, info_ptr, &bytes_read, @@ -2599,6 +2911,7 @@ find_abstract_instance_name (struct comp_unit *unit, _bfd_error_handler (_("Dwarf Error: Could not find abbrev number %u."), abbrev_number); bfd_set_error (bfd_error_bad_value); + return FALSE; } else { @@ -2608,6 +2921,15 @@ find_abstract_instance_name (struct comp_unit *unit, info_ptr, info_ptr_end); if (info_ptr == NULL) break; + /* It doesn't ever make sense for DW_AT_specification to + refer to the same DIE. Stop simple recursion. */ + if (info_ptr == orig_info_ptr) + { + _bfd_error_handler + (_("Dwarf Error: Abstract instance recursion detected.")); + bfd_set_error (bfd_error_bad_value); + return FALSE; + } switch (attr.name) { case DW_AT_name: @@ -2621,7 +2943,9 @@ find_abstract_instance_name (struct comp_unit *unit, } break; case DW_AT_specification: - name = find_abstract_instance_name (unit, &attr, is_linkage); + if (!find_abstract_instance_name (unit, info_ptr, &attr, + pname, is_linkage)) + return FALSE; break; case DW_AT_linkage_name: case DW_AT_MIPS_linkage_name: @@ -2639,7 +2963,8 @@ find_abstract_instance_name (struct comp_unit *unit, } } } - return name; + *pname = name; + return TRUE; } static bfd_boolean @@ -2700,20 +3025,22 @@ scan_unit_for_symbols (struct comp_unit *unit) bfd *abfd = unit->abfd; bfd_byte *info_ptr = unit->first_child_die_ptr; bfd_byte *info_ptr_end = unit->stash->info_ptr_end; - int nesting_level = 1; - struct funcinfo **nested_funcs; + int nesting_level = 0; + struct nest_funcinfo { + struct funcinfo *func; + } *nested_funcs; int nested_funcs_size; /* Maintain a stack of in-scope functions and inlined functions, which we can use to set the caller_func field. */ nested_funcs_size = 32; - nested_funcs = (struct funcinfo **) - bfd_malloc (nested_funcs_size * sizeof (struct funcinfo *)); + nested_funcs = (struct nest_funcinfo *) + bfd_malloc (nested_funcs_size * sizeof (*nested_funcs)); if (nested_funcs == NULL) return FALSE; - nested_funcs[nesting_level] = 0; + nested_funcs[nesting_level].func = 0; - while (nesting_level) + while (nesting_level >= 0) { unsigned int abbrev_number, bytes_read, i; struct abbrev_info *abbrev; @@ -2738,12 +3065,19 @@ scan_unit_for_symbols (struct comp_unit *unit) continue; } - abbrev = lookup_abbrev (abbrev_number,unit->abbrevs); + abbrev = lookup_abbrev (abbrev_number, unit->abbrevs); if (! abbrev) { - _bfd_error_handler - (_("Dwarf Error: Could not find abbrev number %u."), - abbrev_number); + static unsigned int previous_failed_abbrev = -1U; + + /* Avoid multiple reports of the same missing abbrev. */ + if (abbrev_number != previous_failed_abbrev) + { + _bfd_error_handler + (_("Dwarf Error: Could not find abbrev number %u."), + abbrev_number); + previous_failed_abbrev = abbrev_number; + } bfd_set_error (bfd_error_bad_value); goto fail; } @@ -2760,17 +3094,17 @@ scan_unit_for_symbols (struct comp_unit *unit) func->tag = abbrev->tag; func->prev_func = unit->function_table; unit->function_table = func; - unit->number_of_functions++; + unit->number_of_functions++; BFD_ASSERT (!unit->cached); if (func->tag == DW_TAG_inlined_subroutine) - for (i = nesting_level - 1; i >= 1; i--) - if (nested_funcs[i]) + for (i = nesting_level; i-- != 0; ) + if (nested_funcs[i].func) { - func->caller_func = nested_funcs[i]; + func->caller_func = nested_funcs[i].func; break; } - nested_funcs[nesting_level] = func; + nested_funcs[nesting_level].func = func; } else { @@ -2785,16 +3119,18 @@ scan_unit_for_symbols (struct comp_unit *unit) var->stack = 1; var->prev_var = unit->variable_table; unit->variable_table = var; - BFD_ASSERT (!unit->cached); + /* PR 18205: Missing debug information can cause this + var to be attached to an already cached unit. */ } /* No inline function in scope at this nesting level. */ - nested_funcs[nesting_level] = 0; + nested_funcs[nesting_level].func = 0; } for (i = 0; i < abbrev->num_attrs; ++i) { - info_ptr = read_attribute (&attr, &abbrev->attrs[i], unit, info_ptr, info_ptr_end); + info_ptr = read_attribute (&attr, &abbrev->attrs[i], + unit, info_ptr, info_ptr_end); if (info_ptr == NULL) goto fail; @@ -2813,8 +3149,10 @@ scan_unit_for_symbols (struct comp_unit *unit) case DW_AT_abstract_origin: case DW_AT_specification: - func->name = find_abstract_instance_name (unit, &attr, - &func->is_linkage); + if (!find_abstract_instance_name (unit, info_ptr, &attr, + &func->name, + &func->is_linkage)) + goto fail; break; case DW_AT_name: @@ -2871,7 +3209,8 @@ scan_unit_for_symbols (struct comp_unit *unit) switch (attr.name) { case DW_AT_name: - var->name = attr.u.str; + if (is_str_attr (attr.form)) + var->name = attr.u.str; break; case DW_AT_decl_file: @@ -2896,7 +3235,8 @@ scan_unit_for_symbols (struct comp_unit *unit) case DW_FORM_block2: case DW_FORM_block4: case DW_FORM_exprloc: - if (*attr.u.blk->data == DW_OP_addr) + if (attr.u.blk->data != NULL + && *attr.u.blk->data == DW_OP_addr) { var->stack = 0; @@ -2939,17 +3279,17 @@ scan_unit_for_symbols (struct comp_unit *unit) if (nesting_level >= nested_funcs_size) { - struct funcinfo **tmp; + struct nest_funcinfo *tmp; nested_funcs_size *= 2; - tmp = (struct funcinfo **) + tmp = (struct nest_funcinfo *) bfd_realloc (nested_funcs, - nested_funcs_size * sizeof (struct funcinfo *)); + nested_funcs_size * sizeof (*nested_funcs)); if (tmp == NULL) goto fail; nested_funcs = tmp; } - nested_funcs[nesting_level] = 0; + nested_funcs[nesting_level].func = 0; } } @@ -2979,7 +3319,8 @@ parse_comp_unit (struct dwarf2_debug *stash, struct comp_unit* unit; unsigned int version; bfd_uint64_t abbrev_offset = 0; - unsigned int addr_size; + /* Initialize it just to avoid a GCC false warning. */ + unsigned int addr_size = -1; struct abbrev_info** abbrevs; unsigned int abbrev_number, bytes_read, i; struct abbrev_info *abbrev; @@ -2991,19 +3332,11 @@ parse_comp_unit (struct dwarf2_debug *stash, bfd_vma high_pc = 0; bfd *abfd = stash->bfd_ptr; bfd_boolean high_pc_relative = FALSE; + enum dwarf_unit_type unit_type; version = read_2_bytes (abfd, info_ptr, end_ptr); info_ptr += 2; - BFD_ASSERT (offset_size == 4 || offset_size == 8); - if (offset_size == 4) - abbrev_offset = read_4_bytes (abfd, info_ptr, end_ptr); - else - abbrev_offset = read_8_bytes (abfd, info_ptr, end_ptr); - info_ptr += offset_size; - addr_size = read_1_byte (abfd, info_ptr, end_ptr); - info_ptr += 1; - - if (version != 2 && version != 3 && version != 4) + if (version < 2 || version > 5) { /* PR 19872: A version number of 0 probably means that there is padding at the end of the .debug_info section. Gold puts it there when @@ -3013,12 +3346,45 @@ parse_comp_unit (struct dwarf2_debug *stash, { _bfd_error_handler (_("Dwarf Error: found dwarf version '%u', this reader" - " only handles version 2, 3 and 4 information."), version); + " only handles version 2, 3, 4 and 5 information."), version); bfd_set_error (bfd_error_bad_value); } return NULL; } + if (version < 5) + unit_type = DW_UT_compile; + else + { + unit_type = read_1_byte (abfd, info_ptr, end_ptr); + info_ptr += 1; + + addr_size = read_1_byte (abfd, info_ptr, end_ptr); + info_ptr += 1; + } + + BFD_ASSERT (offset_size == 4 || offset_size == 8); + if (offset_size == 4) + abbrev_offset = read_4_bytes (abfd, info_ptr, end_ptr); + else + abbrev_offset = read_8_bytes (abfd, info_ptr, end_ptr); + info_ptr += offset_size; + + if (version < 5) + { + addr_size = read_1_byte (abfd, info_ptr, end_ptr); + info_ptr += 1; + } + + if (unit_type == DW_UT_type) + { + /* Skip type signature. */ + info_ptr += 8; + + /* Skip type offset. */ + info_ptr += offset_size; + } + if (addr_size > sizeof (bfd_vma)) { _bfd_error_handler @@ -3078,7 +3444,6 @@ parse_comp_unit (struct dwarf2_debug *stash, unit->end_ptr = end_ptr; unit->stash = stash; unit->info_ptr_unit = info_ptr_unit; - unit->sec_info_ptr = stash->sec_info_ptr; for (i = 0; i < abbrev->num_attrs; ++i) { @@ -3096,7 +3461,8 @@ parse_comp_unit (struct dwarf2_debug *stash, break; case DW_AT_name: - unit->name = attr.u.str; + if (is_str_attr (attr.form)) + unit->name = attr.u.str; break; case DW_AT_low_pc: @@ -4197,7 +4563,7 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd, looking up the function by section + offset uses the DW_AT_decl_line from the function DW_TAG_subprogram for the line, which will be the line of the function name. */ - if ((section->flags & SEC_CODE) == 0) + if (symbols != NULL && (section->flags & SEC_CODE) == 0) { asymbol **tmp; @@ -4568,6 +4934,8 @@ _bfd_dwarf2_cleanup_debug_info (bfd *abfd, void **pinfo) free (stash->dwarf_line_buffer); if (stash->dwarf_str_buffer) free (stash->dwarf_str_buffer); + if (stash->dwarf_line_str_buffer) + free (stash->dwarf_line_str_buffer); if (stash->dwarf_ranges_buffer) free (stash->dwarf_ranges_buffer); if (stash->info_ptr_memory)