static int dwarf2_locexpr_block_index;
static int dwarf2_loclist_block_index;
+/* Size of .debug_loclists section header for 32-bit DWARF format. */
+#define LOCLIST_HEADER_SIZE32 12
+
+/* Size of .debug_loclists section header for 64-bit DWARF format. */
+#define LOCLIST_HEADER_SIZE64 20
+
/* An index into a (C++) symbol name component in a symbol name as
recorded in the mapped_index's symbol table. For each C++ symbol
in the symbol table, we record one entry for the start of each
/* local data types */
+/* The location list section (.debug_loclists) begins with a header,
+ which contains the following information. */
+struct loclist_header
+{
+ /* A 4-byte or 12-byte length containing the length of the
+ set of entries for this compilation unit, not including the
+ length field itself. */
+ unsigned int length;
+
+ /* A 2-byte version identifier. */
+ short version;
+
+ /* A 1-byte unsigned integer containing the size in bytes of an address on
+ the target system. */
+ unsigned char addr_size;
+
+ /* A 1-byte unsigned integer containing the size in bytes of a segment selector
+ on the target system. */
+ unsigned char segment_collector_size;
+
+ /* A 4-byte count of the number of offsets that follow the header. */
+ unsigned int offset_entry_count;
+};
+
/* Type used for delaying computation of method physnames.
See comments for compute_delayed_physnames. */
struct delayed_method_info
whether the DW_AT_ranges attribute came from the skeleton or DWO. */
ULONGEST ranges_base = 0;
+ /* The DW_AT_loclists_base attribute if present. */
+ ULONGEST loclist_base = 0;
+
/* When reading debug info generated by older versions of rustc, we
have to rewrite some union types to be struct types with a
variant part. This rewriting must be done after the CU is fully
static int dwarf2_ranges_read (unsigned, CORE_ADDR *, CORE_ADDR *,
struct dwarf2_cu *, dwarf2_psymtab *);
+/* Return the .debug_loclists section to use for cu. */
+static struct dwarf2_section_info *cu_debug_loc_section (struct dwarf2_cu *cu);
+
/* How dwarf2_get_pc_bounds constructed its *LOWPC and *HIGHPC return
values. Keep the items ordered with increasing constraints compliance. */
enum pc_bounds_kind
case DW_FORM_GNU_addr_index:
case DW_FORM_GNU_str_index:
case DW_FORM_rnglistx:
+ case DW_FORM_loclistx:
info_ptr = safe_skip_leb128 (info_ptr, buffer_end);
break;
case DW_FORM_indirect:
dwo_sections->loc.s.section = sectp;
dwo_sections->loc.size = bfd_section_size (sectp);
}
+ else if (section_is_p (sectp->name, &names->loclists_dwo))
+ {
+ dwo_sections->loclists.s.section = sectp;
+ dwo_sections->loclists.size = bfd_section_size (sectp);
+ }
else if (section_is_p (sectp->name, &names->macinfo_dwo))
{
dwo_sections->macinfo.s.section = sectp;
if (attr != nullptr)
cu->str_offsets_base = DW_UNSND (attr);
+ attr = die->attr (DW_AT_loclists_base);
+ if (attr != nullptr)
+ cu->loclist_base = DW_UNSND (attr);
+
auto maybe_addr_base = die->addr_base ();
if (maybe_addr_base.has_value ())
cu->addr_base = *maybe_addr_base;
fixup_called = 1;
}
+/* Read the .debug_loclists header contents from the given SECTION in the
+ HEADER. */
+static void
+read_loclist_header (struct loclist_header *header,
+ struct dwarf2_section_info *section)
+{
+ unsigned int bytes_read;
+ bfd *abfd = section->get_bfd_owner ();
+ const gdb_byte *info_ptr = section->buffer;
+ header->length = read_initial_length (abfd, info_ptr, &bytes_read);
+ info_ptr += bytes_read;
+ header->version = read_2_bytes (abfd, info_ptr);
+ info_ptr += 2;
+ header->addr_size = read_1_byte (abfd, info_ptr);
+ info_ptr += 1;
+ header->segment_collector_size = read_1_byte (abfd, info_ptr);
+ info_ptr += 1;
+ header->offset_entry_count = read_4_bytes (abfd, info_ptr);
+}
+
+/* Return the DW_AT_loclists_base value for the CU. */
+static ULONGEST
+lookup_loclist_base (struct dwarf2_cu *cu)
+{
+ /* For the .dwo unit, the loclist_base points to the first offset following
+ the header. The header consists of the following entities-
+ 1. Unit Length (4 bytes for 32 bit DWARF format, and 12 bytes for the 64
+ bit format)
+ 2. version (2 bytes)
+ 3. address size (1 byte)
+ 4. segment selector size (1 byte)
+ 5. offset entry count (4 bytes)
+ These sizes are derived as per the DWARFv5 standard. */
+ if (cu->dwo_unit != nullptr)
+ {
+ if (cu->header.initial_length_size == 4)
+ return LOCLIST_HEADER_SIZE32;
+ return LOCLIST_HEADER_SIZE64;
+ }
+ return cu->loclist_base;
+}
+
+/* Given a DW_FORM_loclistx value LOCLIST_INDEX, fetch the offset from the
+ array of offsets in the .debug_loclists section. */
+static CORE_ADDR
+read_loclist_index (struct dwarf2_cu *cu, ULONGEST loclist_index)
+{
+ struct dwarf2_per_objfile *dwarf2_per_objfile
+ = cu->per_cu->dwarf2_per_objfile;
+ struct objfile *objfile = dwarf2_per_objfile->objfile;
+ bfd *abfd = objfile->obfd;
+ ULONGEST loclist_base = lookup_loclist_base (cu);
+ struct dwarf2_section_info *section = cu_debug_loc_section (cu);
+
+ section->read (objfile);
+ if (section->buffer == NULL)
+ complaint (_("DW_FORM_loclistx used without .debug_loclists "
+ "section [in module %s]"), objfile_name (objfile));
+ struct loclist_header header;
+ read_loclist_header (&header, section);
+ if (loclist_index >= header.offset_entry_count)
+ complaint (_("DW_FORM_loclistx pointing outside of "
+ ".debug_loclists offset array [in module %s]"),
+ objfile_name (objfile));
+ if (loclist_base + loclist_index * cu->header.offset_size
+ >= section->size)
+ complaint (_("DW_FORM_loclistx pointing outside of "
+ ".debug_loclists section [in module %s]"),
+ objfile_name (objfile));
+ const gdb_byte *info_ptr
+ = section->buffer + loclist_base + loclist_index * cu->header.offset_size;
+
+ if (cu->header.offset_size == 4)
+ return bfd_get_32 (abfd, info_ptr) + loclist_base;
+ else
+ return bfd_get_64 (abfd, info_ptr) + loclist_base;
+}
+
/* Process the attributes that had to be skipped in the first round. These
attributes are the ones that need str_offsets_base or addr_base attributes.
They could not have been processed in the first round, because at the time
case DW_FORM_GNU_addr_index:
DW_ADDR (attr) = read_addr_index (cu, DW_UNSND (attr));
break;
+ case DW_FORM_loclistx:
+ DW_UNSND (attr) = read_loclist_index (cu, DW_UNSND (attr));
+ break;
case DW_FORM_strx:
case DW_FORM_strx1:
case DW_FORM_strx2:
DW_UNSND (attr) = cu->header.read_offset (abfd, info_ptr, &bytes_read);
info_ptr += bytes_read;
break;
+ case DW_FORM_loclistx:
+ {
+ *need_reprocess = true;
+ DW_UNSND (attr) = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
+ info_ptr += bytes_read;
+ }
+ break;
case DW_FORM_string:
DW_STRING (attr) = read_direct_string (abfd, info_ptr, &bytes_read);
DW_STRING_IS_CANONICAL (attr) = 0;