From 1bfdfae2ff97e3dc4868864f523d799d2b029d37 Mon Sep 17 00:00:00 2001 From: nitachra Date: Fri, 1 Oct 2021 01:11:24 +0530 Subject: [PATCH] Fix for the gdb.base/macscp.exp testcase failure with split dwarf. Command used: make check RUNTESTFLAGS='CC_FOR_TARGET="clang -gdwarf-5 -gsplit-dwarf -fdebug-macro"' TESTS="gdb.base/macscp.exp" Before the patch: Number of expected passes 234 Number of unexpected failures 65 Number of known failures 40 After the patch: Number of expected passes 319 Number of unexpected failures 1 Number of known failures 19 Compiler used: clang 12.0.0 Clang is emitting both .debug_line and .debug_line.dwo sections and .debug _macro.dwo is pointing to the .debug_line.dwo section(file index in the .debug_macro.dwo is the index in the file_names array of .debug_line.dwo). However, GDB is reading only .debug_line section. In this patch, I have added the support for reading .debug_line.dwo section and added m_dwo_include _dirs and m_dwo_file_names vectors in struct line_header to store the directories and files respectively. --- gdb/dwarf2/line-header.c | 246 ++++++++++++++++++++++++++------------- gdb/dwarf2/line-header.h | 105 +++++++++++++---- gdb/dwarf2/read.c | 110 ++++++++++++++--- gdb/macrotab.c | 4 +- 4 files changed, 341 insertions(+), 124 deletions(-) diff --git a/gdb/dwarf2/line-header.c b/gdb/dwarf2/line-header.c index 938e9fd55d4..621c1c69ae5 100644 --- a/gdb/dwarf2/line-header.c +++ b/gdb/dwarf2/line-header.c @@ -26,57 +26,88 @@ #include "filenames.h" void -line_header::add_include_dir (const char *include_dir) +line_header::add_include_dir (const char *include_dir, bool is_dwo) { if (dwarf_line_debug >= 2) { size_t new_size; - if (version >= 5) - new_size = m_include_dirs.size (); + int include_dir_size = is_dwo ? m_dwo_include_dirs.size (): + m_include_dirs.size (); + if ((is_dwo && dwo_version >= 5) || (!is_dwo && version >= 5)) + new_size = include_dir_size; else - new_size = m_include_dirs.size () + 1; + new_size = include_dir_size + 1; fprintf_unfiltered (gdb_stdlog, "Adding dir %zu: %s\n", new_size, include_dir); } - m_include_dirs.push_back (include_dir); + + if (is_dwo) + m_dwo_include_dirs.push_back (include_dir); + else + m_include_dirs.push_back (include_dir); } void line_header::add_file_name (const char *name, dir_index d_index, unsigned int mod_time, - unsigned int length) + unsigned int length, + bool is_dwo) { if (dwarf_line_debug >= 2) { size_t new_size; - if (version >= 5) - new_size = file_names_size (); + bool file_name_size = is_dwo ? dwo_file_names_size (): + file_names_size (); + if ((is_dwo && dwo_version >= 5) || (!is_dwo && version >= 5)) + new_size = file_name_size; else - new_size = file_names_size () + 1; + new_size = file_name_size + 1; fprintf_unfiltered (gdb_stdlog, "Adding file %zu: %s\n", new_size, name); } - m_file_names.emplace_back (name, d_index, mod_time, length); + + if (is_dwo) + m_dwo_file_names.emplace_back (name, d_index, mod_time, length); + else + m_file_names.emplace_back (name, d_index, mod_time, length); } gdb::unique_xmalloc_ptr line_header::file_file_name (int file) const { /* Is the file number a valid index into the line header's file name - table? Remember that file numbers start with one, not zero. */ - if (is_valid_file_index (file)) + table? First check in the .debug_line.dwo file table and then in + .debug_line table. Remember that file numbers start with one in + DWARFv4 and with zero in DWARFv5. */ + if (is_valid_dwo_file_index (file)) { - const file_entry *fe = file_name_at (file); + const file_entry *fe = file_name_at (file, true); if (!IS_ABSOLUTE_PATH (fe->name)) - { - const char *dir = fe->include_dir (this); - if (dir != NULL) - return gdb::unique_xmalloc_ptr (concat (dir, SLASH_STRING, - fe->name, - (char *) NULL)); - } + { + const char *dir = fe->include_dir (this, true); + if (dir != NULL) + return gdb::unique_xmalloc_ptr (concat (dir, SLASH_STRING, + fe->name, + (char *) NULL)); + } + + return make_unique_xstrdup (fe->name); + } + else if (is_valid_file_index (file)) + { + const file_entry *fe = file_name_at (file, false); + + if (!IS_ABSOLUTE_PATH (fe->name)) + { + const char *dir = fe->include_dir (this, false); + if (dir != NULL) + return gdb::unique_xmalloc_ptr (concat (dir, SLASH_STRING, + fe->name, + (char *) NULL)); + } + return make_unique_xstrdup (fe->name); } else @@ -137,12 +168,13 @@ read_checked_initial_length_and_offset (bfd *abfd, const gdb_byte *buf, static void read_formatted_entries (dwarf2_per_objfile *per_objfile, bfd *abfd, const gdb_byte **bufp, struct line_header *lh, - unsigned int offset_size, + unsigned int offset_size, bool is_dwo, void (*callback) (struct line_header *lh, const char *name, dir_index d_index, unsigned int mod_time, - unsigned int length)) + unsigned int length, + bool is_dwo_section)) { gdb_byte format_count, formati; ULONGEST data_count, datai; @@ -257,7 +289,7 @@ read_formatted_entries (dwarf2_per_objfile *per_objfile, bfd *abfd, } } - callback (lh, fe.name, fe.d_index, fe.mod_time, fe.length); + callback (lh, fe.name, fe.d_index, fe.mod_time, fe.length, is_dwo); } *bufp = buf; @@ -265,11 +297,12 @@ read_formatted_entries (dwarf2_per_objfile *per_objfile, bfd *abfd, /* See line-header.h. */ -line_header_up +bool dwarf_decode_line_header (sect_offset sect_off, bool is_dwz, dwarf2_per_objfile *per_objfile, struct dwarf2_section_info *section, - const struct comp_unit_head *cu_header) + const struct comp_unit_head *cu_header, + line_header_up& lh, bool is_dwo) { const gdb_byte *line_ptr; unsigned int bytes_read, offset_size; @@ -283,40 +316,61 @@ dwarf_decode_line_header (sect_offset sect_off, bool is_dwz, if (to_underlying (sect_off) + 4 >= section->size) { dwarf2_statement_list_fits_in_line_number_section_complaint (); - return 0; + return false; } - line_header_up lh (new line_header ()); - lh->sect_off = sect_off; lh->offset_in_dwz = is_dwz; line_ptr = section->buffer + to_underlying (sect_off); /* Read in the header. */ - lh->total_length = + LONGEST total_length = read_checked_initial_length_and_offset (abfd, line_ptr, cu_header, &bytes_read, &offset_size); - line_ptr += bytes_read; - const gdb_byte *start_here = line_ptr; + line_ptr += bytes_read; - if (line_ptr + lh->total_length > (section->buffer + section->size)) + if (line_ptr + total_length > (section->buffer + section->size)) { dwarf2_statement_list_fits_in_line_number_section_complaint (); - return 0; + return false; } - lh->statement_program_end = start_here + lh->total_length; - lh->version = read_2_bytes (abfd, line_ptr); - line_ptr += 2; - if (lh->version > 5) + + if (is_dwo) { - /* This is a version we don't understand. The format could have - changed in ways we don't handle properly so just punt. */ - complaint (_("unsupported version in .debug_line section")); - return NULL; + lh->dwo_total_length = total_length; + lh->dwo_version = read_2_bytes (abfd, line_ptr); + + if (lh->dwo_version > 5) + { + /* This is a version we don't understand. The format could have + changed in ways we don't handle properly so just punt. */ + complaint (_("unsupported version in .debug_line.dwo section")); + return false; + } + + line_ptr += 2; } - if (lh->version >= 5) + else + { + lh->total_length = total_length; + const gdb_byte *start_here = line_ptr; + lh->statement_program_end = start_here + lh->total_length; + lh->version = read_2_bytes (abfd, line_ptr); + + if (lh->version > 5) + { + /* This is a version we don't understand. The format could have + changed in ways we don't handle properly so just punt. */ + complaint (_("unsupported version in .debug_line section")); + return false; + } + + line_ptr += 2; + } + + if ((is_dwo && lh->dwo_version >= 5) || (!is_dwo && lh->version >= 5)) { gdb_byte segment_selector_size; @@ -326,71 +380,103 @@ dwarf_decode_line_header (sect_offset sect_off, bool is_dwz, segment_selector_size = read_1_byte (abfd, line_ptr); line_ptr += 1; + if (segment_selector_size != 0) { complaint (_("unsupported segment selector size %u " "in .debug_line section"), segment_selector_size); - return NULL; + return false; } } - lh->header_length = read_offset (abfd, line_ptr, offset_size); + + unsigned int header_length = read_offset (abfd, line_ptr, offset_size); line_ptr += offset_size; - lh->statement_program_start = line_ptr + lh->header_length; - lh->minimum_instruction_length = read_1_byte (abfd, line_ptr); - line_ptr += 1; - if (lh->version >= 4) + + if (is_dwo) { - lh->maximum_ops_per_instruction = read_1_byte (abfd, line_ptr); + lh->dwo_header_length = header_length; + line_ptr += 1; /* Skip the minimum instruction length. */ + if (lh->dwo_version >= 4) + line_ptr += 1; /* Skip maximum ops per instruction. */ + line_ptr += 1; /* Skip default is stmt. */ + line_ptr += 2; /* Skip line base and line range. */ + + /* Read the opcode base. */ + lh->dwo_opcode_base = read_1_byte (abfd, line_ptr); line_ptr += 1; + lh->dwo_standard_opcode_lengths.reset (new unsigned char[lh->dwo_opcode_base]); + lh->dwo_standard_opcode_lengths[0] = 1; /* This should never be used anyway. */ + + for (i = 1; i < lh->dwo_opcode_base; ++i) + { + lh->dwo_standard_opcode_lengths[i] = read_1_byte (abfd, line_ptr); + line_ptr += 1; + } } else - lh->maximum_ops_per_instruction = 1; - - if (lh->maximum_ops_per_instruction == 0) { - lh->maximum_ops_per_instruction = 1; - complaint (_("invalid maximum_ops_per_instruction " - "in `.debug_line' section")); - } + lh->header_length = header_length; + lh->statement_program_start = line_ptr + lh->header_length; + lh->minimum_instruction_length = read_1_byte (abfd, line_ptr); + line_ptr += 1; - lh->default_is_stmt = read_1_byte (abfd, line_ptr); - line_ptr += 1; - lh->line_base = read_1_signed_byte (abfd, line_ptr); - line_ptr += 1; - lh->line_range = read_1_byte (abfd, line_ptr); - line_ptr += 1; - lh->opcode_base = read_1_byte (abfd, line_ptr); - line_ptr += 1; - lh->standard_opcode_lengths.reset (new unsigned char[lh->opcode_base]); - - lh->standard_opcode_lengths[0] = 1; /* This should never be used anyway. */ - for (i = 1; i < lh->opcode_base; ++i) - { - lh->standard_opcode_lengths[i] = read_1_byte (abfd, line_ptr); + if (lh->version >= 4) + { + lh->maximum_ops_per_instruction = read_1_byte (abfd, line_ptr); + line_ptr += 1; + } + else + { + lh->maximum_ops_per_instruction = 1; + } + + if (lh->maximum_ops_per_instruction == 0) + { + lh->maximum_ops_per_instruction = 1; + complaint (_("invalid maximum_ops_per_instruction " + "in `.debug_line' section")); + } + + lh->default_is_stmt = read_1_byte (abfd, line_ptr); + line_ptr += 1; + lh->line_base = read_1_signed_byte (abfd, line_ptr); line_ptr += 1; + lh->line_range = read_1_byte (abfd, line_ptr); + line_ptr += 1; + + lh->opcode_base = read_1_byte (abfd, line_ptr); + line_ptr += 1; + lh->standard_opcode_lengths.reset (new unsigned char[lh->opcode_base]); + lh->standard_opcode_lengths[0] = 1; /* This should never be used anyway. */ + + for (i = 1; i < lh->opcode_base; ++i) + { + lh->standard_opcode_lengths[i] = read_1_byte (abfd, line_ptr); + line_ptr += 1; + } } - if (lh->version >= 5) + if ((is_dwo && lh->dwo_version >= 5) || (!is_dwo && lh->version >=5)) { /* Read directory table. */ read_formatted_entries (per_objfile, abfd, &line_ptr, lh.get (), - offset_size, + offset_size, is_dwo, [] (struct line_header *header, const char *name, dir_index d_index, unsigned int mod_time, - unsigned int length) + unsigned int length, bool is_dwo_section) { - header->add_include_dir (name); + header->add_include_dir (name, is_dwo_section); }); /* Read file name table. */ read_formatted_entries (per_objfile, abfd, &line_ptr, lh.get (), - offset_size, + offset_size, is_dwo, [] (struct line_header *header, const char *name, dir_index d_index, unsigned int mod_time, - unsigned int length) + unsigned int length, bool is_dwo_section) { - header->add_file_name (name, d_index, mod_time, length); + header->add_file_name (name, d_index, mod_time, length, is_dwo_section); }); } else @@ -399,7 +485,7 @@ dwarf_decode_line_header (sect_offset sect_off, bool is_dwz, while ((cur_dir = read_direct_string (abfd, line_ptr, &bytes_read)) != NULL) { line_ptr += bytes_read; - lh->add_include_dir (cur_dir); + lh->add_include_dir (cur_dir, is_dwo); } line_ptr += bytes_read; @@ -417,7 +503,7 @@ dwarf_decode_line_header (sect_offset sect_off, bool is_dwz, length = read_unsigned_leb128 (abfd, line_ptr, &bytes_read); line_ptr += bytes_read; - lh->add_file_name (cur_file, d_index, mod_time, length); + lh->add_file_name (cur_file, d_index, mod_time, length, is_dwo); } line_ptr += bytes_read; } @@ -426,5 +512,5 @@ dwarf_decode_line_header (sect_offset sect_off, bool is_dwz, complaint (_("line number info header doesn't " "fit in `.debug_line' section")); - return lh; + return true; } diff --git a/gdb/dwarf2/line-header.h b/gdb/dwarf2/line-header.h index 8fb44be56b2..48cf9a5b742 100644 --- a/gdb/dwarf2/line-header.h +++ b/gdb/dwarf2/line-header.h @@ -44,9 +44,12 @@ struct file_entry length (length_) {} - /* Return the include directory at D_INDEX stored in LH. Returns - NULL if D_INDEX is out of bounds. */ - const char *include_dir (const line_header *lh) const; + /* Return the include directory at D_INDEX stored in m_include_dirs vector + in LH or in m_dwo_include_dirs vector in LH if IS_DWO is true. m_dwo_ + include_dirs contains the include_directories entries of .debug_line.dwo + section whereas m_include_dirs contains the include_directories array + entries of .debug_line section. Returns NULL if D_INDEX is out of bounds. */ + const char *include_dir (const line_header *lh, bool is_dwo) const; /* The file name. Note this is an observing pointer. The memory is owned by debug_line_buffer. */ @@ -75,25 +78,37 @@ struct line_header : offset_in_dwz {} {} - /* Add an entry to the include directory table. */ - void add_include_dir (const char *include_dir); + /* Add an entry to the m_include_dirs vector or to m_dwo_include_dirs vector + if IS_DWO is true. */ + void add_include_dir (const char *include_dir, bool is_dwo); - /* Add an entry to the file name table. */ + /* Add an entry to the m_file_names vector or to the m_dwo_file_names vector + if IS_DWO is true. m_dwo_file_names vector contains the file_names entries of + .debug_line.dwo section whereas m_file_names contains the file_names array + entries of .debug_line section. */ void add_file_name (const char *name, dir_index d_index, - unsigned int mod_time, unsigned int length); + unsigned int mod_time, unsigned int length, bool is_dwo); - /* Return the include dir at INDEX (0-based in DWARF 5 and 1-based before). + /* Return the include dir from m_include_dirs or from the m_dwo_include_dirs + if IS_DWO is true at INDEX (0-based in DWARF 5 and 1-based before). Returns NULL if INDEX is out of bounds. */ - const char *include_dir_at (dir_index index) const + const char *include_dir_at (dir_index index, bool is_dwo) const { int vec_index; - if (version >= 5) + + if (is_dwo && m_dwo_include_dirs.empty()) + is_dwo = false; + + if ((is_dwo && dwo_version >= 5) || (!is_dwo && version >= 5)) vec_index = index; else vec_index = index - 1; - if (vec_index < 0 || vec_index >= m_include_dirs.size ()) + int include_dirs_size = is_dwo ? m_dwo_include_dirs.size () : + m_include_dirs.size (); + if (vec_index < 0 || vec_index >= include_dirs_size) return NULL; - return m_include_dirs[vec_index]; + return is_dwo ? m_dwo_include_dirs[vec_index] : + m_include_dirs[vec_index]; } bool is_valid_file_index (int file_index) const @@ -103,25 +118,43 @@ struct line_header return 1 <= file_index && file_index <= file_names_size (); } - /* Return the file name at INDEX (0-based in DWARF 5 and 1-based before). + /* Returns true if the FILE_INDEX is a valid index in the file_names vector + of .debug_line.dwo section. */ + bool is_valid_dwo_file_index (int file_index) const + { + if (dwo_version >= 5) + return 0 <= file_index && file_index < dwo_file_names_size (); + return 1 <= file_index && file_index <= dwo_file_names_size (); + + } + + /* Return the file name from m_file_names or from m_dwo_file_names vector + if IS_DWO is true at INDEX (0-based in DWARF 5 and 1-based before). Returns NULL if INDEX is out of bounds. */ - file_entry *file_name_at (file_name_index index) + file_entry *file_name_at (file_name_index index, bool is_dwo) { int vec_index; - if (version >= 5) + + if (is_dwo && m_dwo_file_names.empty ()) + is_dwo = false; + + if ((is_dwo && dwo_version >= 5) || (!is_dwo && version >= 5)) vec_index = index; else vec_index = index - 1; - if (vec_index < 0 || vec_index >= m_file_names.size ()) + int file_names_size = is_dwo ? m_dwo_file_names.size (): + m_file_names.size (); + + if (vec_index < 0 || vec_index >= file_names_size) return NULL; - return &m_file_names[vec_index]; + return is_dwo ? &m_dwo_file_names[vec_index] : &m_file_names[vec_index]; } /* A const overload of the same. */ - const file_entry *file_name_at (file_name_index index) const + const file_entry *file_name_at (file_name_index index, bool is_dwo) const { line_header *lh = const_cast (this); - return lh->file_name_at (index); + return lh->file_name_at (index, is_dwo); } /* The indexes are 0-based in DWARF 5 and 1-based in DWARF 4. Therefore, @@ -133,6 +166,12 @@ struct line_header const std::vector &file_names () const { return m_file_names; } + std::vector &dwo_file_names () + { return m_dwo_file_names; } + /* A const overload of the same. */ + const std::vector &dwo_file_names () const + { return m_dwo_file_names; } + /* Offset of line number information in .debug_line section. */ sect_offset sect_off {}; @@ -140,14 +179,18 @@ struct line_header unsigned offset_in_dwz : 1; /* Can't initialize bitfields in-class. */ unsigned int total_length {}; + unsigned int dwo_total_length {}; unsigned short version {}; + unsigned short dwo_version {}; unsigned int header_length {}; + unsigned int dwo_header_length {}; unsigned char minimum_instruction_length {}; unsigned char maximum_ops_per_instruction {}; unsigned char default_is_stmt {}; int line_base {}; unsigned char line_range {}; unsigned char opcode_base {}; + unsigned char dwo_opcode_base {}; /* standard_opcode_lengths[i] is the number of operands for the standard opcode whose value is i. This means that @@ -155,9 +198,18 @@ struct line_header element is standard_opcode_lengths[opcode_base - 1]. */ std::unique_ptr standard_opcode_lengths; + /* dwo_standard_opcode_lengths[i] is the number of operands for the + standard opcode whose value is i. This means that + dwo_standard_opcode_lengths[0] is unused, and the last meaningful + element is dwo_standard_opcode_lengths[dwo_opcode_base - 1]. */ + std::unique_ptr dwo_standard_opcode_lengths; + int file_names_size () const { return m_file_names.size(); } + int dwo_file_names_size () const + { return m_dwo_file_names.size (); } + /* The start and end of the statement program following this header. These point into dwarf2_per_objfile->line_buffer. */ const gdb_byte *statement_program_start {}, *statement_program_end {}; @@ -173,19 +225,25 @@ struct line_header pointers. The memory is owned by debug_line_buffer. */ std::vector m_include_dirs; + /* The include_directories table from .debug_line.dwo section. */ + std::vector m_dwo_include_dirs; + /* The file_names table. This is private because the meaning of indexes differs among DWARF versions (The first valid index is 1 in DWARF 4 and before, and is 0 in DWARF 5 and later). So the client should use file_name_at method for access. */ std::vector m_file_names; + + /* The file_names table from .debug_line.dwo section. */ + std::vector m_dwo_file_names; }; typedef std::unique_ptr line_header_up; inline const char * -file_entry::include_dir (const line_header *lh) const +file_entry::include_dir (const line_header *lh, bool is_dwo) const { - return lh->include_dir_at (d_index); + return lh->include_dir_at (d_index, is_dwo); } /* Read the statement program header starting at SECT_OFF in SECTION. @@ -196,8 +254,9 @@ file_entry::include_dir (const line_header *lh) const the returned object point into the dwarf line section buffer, and must not be freed. */ -extern line_header_up dwarf_decode_line_header +extern bool dwarf_decode_line_header (sect_offset sect_off, bool is_dwz, dwarf2_per_objfile *per_objfile, - struct dwarf2_section_info *section, const struct comp_unit_head *cu_header); + struct dwarf2_section_info *section, const struct comp_unit_head *cu_header, + line_header_up& lh, bool is_dwo); #endif /* DWARF2_LINE_HEADER_H */ diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index 10550336063..b9700f70e9c 100644 --- a/gdb/dwarf2/read.c +++ b/gdb/dwarf2/read.c @@ -1544,7 +1544,7 @@ static const char *compute_include_file_name (const struct line_header *lh, const file_entry &fe, const file_and_directory &cu_info, - gdb::unique_xmalloc_ptr *name_holder); + gdb::unique_xmalloc_ptr *name_holder, bool is_dwo); static htab_up allocate_signatured_type_table (); @@ -3027,7 +3027,19 @@ dw2_get_file_names_reader (const struct die_reader_specs *reader, { gdb::unique_xmalloc_ptr name_holder; const char *include_name = - compute_include_file_name (lh.get (), entry, fnd, &name_holder); + compute_include_file_name (lh.get (), entry, fnd, &name_holder, false); + if (include_name != nullptr) + { + include_name = per_objfile->objfile->intern (include_name); + include_names.push_back (include_name); + } + } + + for (const auto &entry : lh->dwo_file_names ()) + { + gdb::unique_xmalloc_ptr name_holder; + const char *include_name = + compute_include_file_name (lh.get (), entry, fnd, &name_holder, true); if (include_name != nullptr) { include_name = per_objfile->objfile->intern (include_name); @@ -10753,7 +10765,7 @@ dwarf2_cu::setup_type_unit_groups (struct die_info *die) { file_entry &fe = file_names[i]; dwarf2_start_subfile (this, fe.name, - fe.include_dir (line_header)); + fe.include_dir (line_header, false)); buildsym_compunit *b = get_builder (); if (b->get_current_subfile ()->symtab == NULL) { @@ -20722,7 +20734,7 @@ get_debug_line_section (struct dwarf2_cu *cu) } /* Read the statement program header starting at OFFSET in - .debug_line, or .debug_line.dwo. Return a pointer + .debug_line and .debug_line.dwo. Return a pointer to a struct line_header, allocated using xmalloc. Returns NULL if there is a problem reading the header, e.g., if it has a version we don't understand. @@ -20735,21 +20747,48 @@ static line_header_up dwarf_decode_line_header (sect_offset sect_off, struct dwarf2_cu *cu) { struct dwarf2_section_info *section; + struct dwarf2_section_info *dwo_section = NULL; dwarf2_per_objfile *per_objfile = cu->per_objfile; section = get_debug_line_section (cu); section->read (per_objfile->objfile); + if (section->buffer == NULL) + { + if (cu->dwo_unit && cu->per_cu->is_debug_types) + complaint (_("missing .debug_line.dwo section")); + else + complaint (_("missing .debug_line section")); + return 0; + } + + line_header_up lh (new line_header ()); + + if (!dwarf_decode_line_header (sect_off, cu->per_cu->is_dwz, + per_objfile, section, + &cu->header, lh, false)) { - if (cu->dwo_unit && cu->per_cu->is_debug_types) - complaint (_("missing .debug_line.dwo section")); - else - complaint (_("missing .debug_line section")); return 0; } - return dwarf_decode_line_header (sect_off, cu->per_cu->is_dwz, - per_objfile, section, &cu->header); + if (cu->dwo_unit && !cu->per_cu->is_debug_types) + { + dwo_section = &cu->dwo_unit->dwo_file->sections.line; + dwo_section->read (per_objfile->objfile); + } + + if (cu->dwo_unit && dwo_section && (dwo_section->buffer != NULL)) + { + sect_offset dwo_sect_off = (sect_offset) 0; + if (!dwarf_decode_line_header (dwo_sect_off, cu->per_cu->is_dwz, + per_objfile, dwo_section, + &cu->header, lh, true)) + { + return 0; + } + } + + return lh; } /* Subroutine of dwarf_decode_lines to simplify it. @@ -20762,12 +20801,20 @@ dwarf_decode_line_header (sect_offset sect_off, struct dwarf2_cu *cu) static const char * compute_include_file_name (const struct line_header *lh, const file_entry &fe, const file_and_directory &cu_info, - gdb::unique_xmalloc_ptr *name_holder) + gdb::unique_xmalloc_ptr *name_holder, bool is_dwo) { const char *include_name = fe.name; const char *include_name_to_compare = include_name; + const char *dir_name; - const char *dir_name = fe.include_dir (lh); + if (is_dwo) + { + dir_name = fe.include_dir (lh, true); + } + else + { + dir_name = fe.include_dir (lh, false); + } gdb::unique_xmalloc_ptr hold_compare; if (!IS_ABSOLUTE_PATH (include_name) @@ -20838,7 +20885,7 @@ class lnp_state_machine { /* lh->file_names is 0-based, but the file name numbers in the statement program are 1-based. */ - return m_line_header->file_name_at (m_file); + return m_line_header->file_name_at (m_file, false); } /* Record the line in the state machine. END_SEQUENCE is true if @@ -21012,7 +21059,7 @@ lnp_state_machine::handle_set_file (file_name_index file) dwarf2_debug_line_missing_file_complaint (); else if (m_record_lines_p) { - const char *dir = fe->include_dir (m_line_header); + const char *dir = fe->include_dir (m_line_header, false); m_last_subfile = m_cu->get_builder ()->get_current_subfile (); m_line_has_non_zero_discriminator = m_discriminator != 0; @@ -21304,7 +21351,7 @@ dwarf_decode_lines_1 (struct line_header *lh, struct dwarf2_cu *cu, const file_entry *fe = state_machine.current_file (); if (fe != NULL) - dwarf2_start_subfile (cu, fe->name, fe->include_dir (lh)); + dwarf2_start_subfile (cu, fe->name, fe->include_dir (lh, false)); } /* Decode the table. */ @@ -21369,7 +21416,7 @@ dwarf_decode_lines_1 (struct line_header *lh, struct dwarf2_cu *cu, length = read_unsigned_leb128 (abfd, line_ptr, &bytes_read); line_ptr += bytes_read; - lh->add_file_name (cur_file, dindex, mod_time, length); + lh->add_file_name (cur_file, dindex, mod_time, length, false); } break; case DW_LNE_set_discriminator: @@ -21526,7 +21573,20 @@ dwarf_decode_lines (struct line_header *lh, const file_and_directory &fnd, { gdb::unique_xmalloc_ptr name_holder; const char *include_name = - compute_include_file_name (lh, file_entry, fnd, &name_holder); + compute_include_file_name (lh, file_entry, fnd, &name_holder, false); + if (include_name != NULL) + dwarf2_create_include_psymtab + (cu->per_objfile->per_bfd, include_name, pst, + cu->per_objfile->per_bfd->partial_symtabs.get (), + objfile->per_bfd); + } + + for (auto &file_entry : lh->dwo_file_names ()) + if (file_entry.included_p) + { + gdb::unique_xmalloc_ptr name_holder; + const char *include_name = + compute_include_file_name (lh, file_entry, fnd, &name_holder, true); if (include_name != NULL) dwarf2_create_include_psymtab (cu->per_objfile->per_bfd, include_name, pst, @@ -21544,7 +21604,19 @@ dwarf_decode_lines (struct line_header *lh, const file_and_directory &fnd, for (auto &fe : lh->file_names ()) { - dwarf2_start_subfile (cu, fe.name, fe.include_dir (lh)); + dwarf2_start_subfile (cu, fe.name, fe.include_dir (lh, false)); + if (builder->get_current_subfile ()->symtab == NULL) + { + builder->get_current_subfile ()->symtab + = allocate_symtab (cust, + builder->get_current_subfile ()->name); + } + fe.symtab = builder->get_current_subfile ()->symtab; + } + + for (auto &fe : lh->dwo_file_names ()) + { + dwarf2_start_subfile (cu, fe.name, fe.include_dir (lh, true)); if (builder->get_current_subfile ()->symtab == NULL) { builder->get_current_subfile ()->symtab @@ -21760,7 +21832,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu, struct file_entry *fe; if (cu->line_header != NULL) - fe = cu->line_header->file_name_at (file_index); + fe = cu->line_header->file_name_at (file_index, (cu->dwo_unit != nullptr)); else fe = NULL; diff --git a/gdb/macrotab.c b/gdb/macrotab.c index 7ca3f312d33..73a917541b6 100644 --- a/gdb/macrotab.c +++ b/gdb/macrotab.c @@ -238,7 +238,7 @@ compare_locations (struct macro_source_file *file1, int line1, /* If the two files are not the same, find their common ancestor in the #inclusion tree. */ - if (file1 != file2) + if (file1 != file2 || filename_cmp(file1->filename, file2->filename) != 0) { /* If one file is deeper than the other, walk up the #inclusion chain until the two files are at least at the same *depth*. @@ -266,7 +266,7 @@ compare_locations (struct macro_source_file *file1, int line1, /* Now both file1 and file2 are at the same depth. Walk toward the root of the tree until we find where the branches meet. */ - while (file1 != file2) + while (file1 != file2 || filename_cmp(file1->filename, file2->filename) != 0) { line1 = file1->included_at_line; file1 = file1->included_by; -- 2.17.1