* [PATCH V2] bfd: Add Support for DW_FORM_strx* and DW_FORM_addrx*.
@ 2022-05-24 0:01 Potharla, Rupesh
2022-05-26 7:02 ` Alan Modra
0 siblings, 1 reply; 3+ messages in thread
From: Potharla, Rupesh @ 2022-05-24 0:01 UTC (permalink / raw)
To: binutils, Jan Beulich
Cc: George, Jini Susan, Parasuraman, Hariharan, Natarajan, Kavitha
[-- Attachment #1: Type: text/plain, Size: 14673 bytes --]
[Public]
Hi,
Made the suggested changes and isolated code changes related to file index for dwarf5 and send it as a separate patch for review. Can you review the code changes and send in your comments/suggestions?
Regards,
Rupesh P
Implement strx* and addrx* forms to the BFD library.
---
bfd/dwarf2.c | 274 ++++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 263 insertions(+), 11 deletions(-)
diff --git a/bfd/dwarf2.c b/bfd/dwarf2.c
index f6b0183720b..30f01442e93 100644
--- a/bfd/dwarf2.c
+++ b/bfd/dwarf2.c
@@ -189,6 +189,18 @@ struct dwarf2_debug_file
/* Length of the loaded .debug_str section. */
bfd_size_type dwarf_str_size;
+ /* Pointer to the .debug_str_offsets section loaded into memory. */
+ bfd_byte *dwarf_str_offsets_buffer;
+
+ /* Length of the loaded .debug_str_offsets section. */
+ bfd_size_type dwarf_str_offsets_size;
+
+ /* Pointer to the .debug_addr section loaded into memory. */
+ bfd_byte *dwarf_addr_buffer;
+
+ /* Length of the loaded .debug_addr section. */
+ bfd_size_type dwarf_addr_size;
+
/* Pointer to the .debug_line_str section loaded into memory. */
bfd_byte *dwarf_line_str_buffer;
@@ -382,6 +394,11 @@ struct comp_unit
/* Used when iterating over trie leaves to know which units we have
already seen in this iteration. */
bool mark;
+ /* Base address of debug_addr section. */
+ unsigned long dwarf_addr_offset;
+
+ /* Base address of string offset table. */
+ unsigned long dwarf_str_offset;
};
/* This data structure holds the information of an abbrev. */
@@ -424,6 +441,8 @@ const struct dwarf_debug_section dwarf_debug_sections[] =
{ ".debug_static_vars", ".zdebug_static_vars" },
{ ".debug_str", ".zdebug_str", },
{ ".debug_str", ".zdebug_str", },
+ { ".debug_str_offsets", ".zdebug_str_offsets", },
+ { ".debug_addr", ".zdebug_addr", },
{ ".debug_line_str", ".zdebug_line_str", },
{ ".debug_types", ".zdebug_types" },
/* GNU DWARF 1 extensions */
@@ -458,6 +477,8 @@ enum dwarf_debug_section_enum
debug_static_vars,
debug_str,
debug_str_alt,
+ debug_str_offsets,
+ debug_addr,
debug_line_str,
debug_types,
debug_sfnames,
@@ -1307,12 +1328,93 @@ is_int_form (const struct attribute *attr)
}
}
+/* Returns true if the form is strx[1-4]. */
+
+static inline bool
+is_strx_form(enum dwarf_form form)
+{
+ return (form == DW_FORM_strx
+ || form == DW_FORM_strx1
+ || form == DW_FORM_strx2
+ || form == DW_FORM_strx3
+ || form == DW_FORM_strx4);
+}
+
+/* Return true if the form is addrx[1-4]. */
+
+static inline bool
+is_addrx_form(enum dwarf_form form)
+{
+ return (form == DW_FORM_addrx
+ || form == DW_FORM_addrx1
+ || form == DW_FORM_addrx2
+ || form == DW_FORM_addrx3
+ || form == DW_FORM_addrx4);
+}
+
+/* Returns the address in .debug_addr section using DW_AT_addr_base.
+ Used to implement DW_FORM_addrx*. */
+static bfd_vma
+read_indexed_address (bfd_uint64_t idx,
+ struct comp_unit *unit)
+{
+ struct dwarf2_debug *stash = unit->stash;
+ struct dwarf2_debug_file *file = unit->file;
+ unsigned long addr_base = unit->dwarf_addr_offset;
+ bfd_byte *info_ptr;
+
+ if (stash == NULL)
+ return 0;
+
+ if (!read_section (unit->abfd, &stash->debug_sections[debug_addr],
+ file->syms, 0,
+ &file->dwarf_addr_buffer, &file->dwarf_addr_size))
+ return 0;
+
+ info_ptr = (bfd_byte *)(file->dwarf_addr_buffer + addr_base
+ + idx * unit->offset_size);
+
+ if (unit->offset_size == 4)
+ return bfd_get_32 (unit->abfd, info_ptr);
+ else
+ return bfd_get_64 (unit->abfd, info_ptr);
+}
+
+/* Returns the string using DW_AT_str_offsets_base.
+ Used to implement DW_FORM_strx*. */
static const char *
-read_indexed_string (bfd_uint64_t idx ATTRIBUTE_UNUSED,
- struct comp_unit * unit ATTRIBUTE_UNUSED)
+read_indexed_string (bfd_uint64_t idx,
+ struct comp_unit * unit)
{
- /* FIXME: Add support for indexed strings. */
- return "<indexed strings not yet supported>";
+ struct dwarf2_debug *stash = unit->stash;
+ struct dwarf2_debug_file *file = unit->file;
+ bfd_byte *info_ptr;
+ unsigned long str_offset;
+
+ if (stash == NULL)
+ return NULL;
+
+ if (!read_section (unit->abfd, &stash->debug_sections[debug_str],
+ file->syms, 0,
+ &file->dwarf_str_buffer, &file->dwarf_str_size))
+ return NULL;
+
+ if (!read_section (unit->abfd, &stash->debug_sections[debug_str_offsets],
+ file->syms, 0,
+ &file->dwarf_str_offsets_buffer,
+ &file->dwarf_str_offsets_size))
+ return NULL;
+
+ info_ptr = (bfd_byte *)(file->dwarf_str_offsets_buffer
+ + unit->dwarf_str_offset
+ + idx * unit->offset_size);
+
+ if (unit->offset_size == 4)
+ str_offset = bfd_get_32 (unit->abfd, info_ptr);
+ else
+ str_offset = bfd_get_64 (unit->abfd, info_ptr);
+
+ return (const char*) (file->dwarf_str_buffer + str_offset);
}
/* Read and fill in the value of attribute ATTR as described by FORM.
@@ -1381,21 +1483,37 @@ read_attribute_value (struct attribute * attr,
case DW_FORM_ref1:
case DW_FORM_flag:
case DW_FORM_data1:
+ attr->u.val = read_1_byte (abfd, &info_ptr, info_ptr_end);
+ break;
case DW_FORM_addrx1:
attr->u.val = read_1_byte (abfd, &info_ptr, info_ptr_end);
+ /* dwarf_addr_offset value 0 indicates the attribute DW_AT_addr_base
+ is not yet read. */
+ if (unit->dwarf_addr_offset != 0)
+ attr->u.val = read_indexed_address(attr->u.val, unit);
break;
case DW_FORM_data2:
- case DW_FORM_addrx2:
case DW_FORM_ref2:
attr->u.val = read_2_bytes (abfd, &info_ptr, info_ptr_end);
break;
+ case DW_FORM_addrx2:
+ attr->u.val = read_2_bytes (abfd, &info_ptr, info_ptr_end);
+ if (unit->dwarf_addr_offset != 0)
+ attr->u.val = read_indexed_address(attr->u.val, unit);
+ break;
case DW_FORM_addrx3:
attr->u.val = read_3_bytes (abfd, &info_ptr, info_ptr_end);
+ if (unit->dwarf_addr_offset != 0)
+ attr->u.val = read_indexed_address(attr->u.val, unit);
break;
case DW_FORM_ref4:
case DW_FORM_data4:
+ attr->u.val = read_4_bytes (abfd, &info_ptr, info_ptr_end);
+ break;
case DW_FORM_addrx4:
attr->u.val = read_4_bytes (abfd, &info_ptr, info_ptr_end);
+ if (unit->dwarf_addr_offset != 0)
+ attr->u.val = read_indexed_address(attr->u.val, unit);
break;
case DW_FORM_data8:
case DW_FORM_ref8:
@@ -1416,24 +1534,31 @@ read_attribute_value (struct attribute * attr,
break;
case DW_FORM_strx1:
attr->u.val = read_1_byte (abfd, &info_ptr, info_ptr_end);
- attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
+ /* dwarf_str_offset value 0 indicates the attribute DW_AT_str_offsets_base
+ is not yet read. */
+ if (unit->dwarf_str_offset != 0)
+ attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
break;
case DW_FORM_strx2:
attr->u.val = read_2_bytes (abfd, &info_ptr, info_ptr_end);
- attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
+ if (unit->dwarf_str_offset != 0)
+ attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
break;
case DW_FORM_strx3:
attr->u.val = read_3_bytes (abfd, &info_ptr, info_ptr_end);
- attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
+ if (unit->dwarf_str_offset != 0)
+ attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
break;
case DW_FORM_strx4:
attr->u.val = read_4_bytes (abfd, &info_ptr, info_ptr_end);
- attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
+ if (unit->dwarf_str_offset != 0)
+ attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
break;
case DW_FORM_strx:
attr->u.val = _bfd_safe_read_leb128 (abfd, &info_ptr,
false, info_ptr_end);
- attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
+ if (unit->dwarf_str_offset != 0)
+ attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
break;
case DW_FORM_exprloc:
case DW_FORM_block:
@@ -1455,9 +1580,14 @@ read_attribute_value (struct attribute * attr,
break;
case DW_FORM_ref_udata:
case DW_FORM_udata:
+ attr->u.val = _bfd_safe_read_leb128 (abfd, &info_ptr,
+ false, info_ptr_end);
+ break;
case DW_FORM_addrx:
attr->u.val = _bfd_safe_read_leb128 (abfd, &info_ptr,
false, info_ptr_end);
+ if (unit->dwarf_addr_offset != 0)
+ attr->u.val = read_indexed_address(attr->u.val, unit);
break;
case DW_FORM_indirect:
form = _bfd_safe_read_leb128 (abfd, &info_ptr,
@@ -2396,6 +2526,11 @@ read_formatted_entries (struct comp_unit *unit, bfd_byte **bufp,
{
case DW_FORM_string:
case DW_FORM_line_strp:
+ case DW_FORM_strx:
+ case DW_FORM_strx1:
+ case DW_FORM_strx2:
+ case DW_FORM_strx3:
+ case DW_FORM_strx4:
*stringp = attr.u.str;
break;
@@ -4031,6 +4166,77 @@ scan_unit_for_symbols (struct comp_unit *unit)
return false;
}
+/* read the attributes of the form strx and addrx. */
+static void reread_attribute (struct comp_unit * unit,
+ struct attribute attr,
+ bfd_vma *low_pc,
+ bfd_vma *high_pc,
+ bool *high_pc_relative,
+ bool compunit)
+{
+
+ if (is_strx_form(attr.form))
+ attr.u.str = (char*) read_indexed_string (attr.u.val, unit);
+ if (is_addrx_form(attr.form))
+ attr.u.val = read_indexed_address (attr.u.val, unit);
+
+ switch (attr.name)
+ {
+ case DW_AT_stmt_list:
+ unit->stmtlist = 1;
+ unit->line_offset = attr.u.val;
+ break;
+
+ case DW_AT_name:
+ if (is_str_form (&attr))
+ unit->name = attr.u.str;
+ break;
+
+ case DW_AT_low_pc:
+ *low_pc = attr.u.val;
+ if (compunit)
+ unit->base_address = *low_pc;
+ break;
+
+ case DW_AT_high_pc:
+ *high_pc = attr.u.val;
+ *high_pc_relative = attr.form != DW_FORM_addr;
+ break;
+
+ case DW_AT_ranges:
+ if (!read_rangelist (unit, &unit->arange, attr.u.val))
+ return;
+ break;
+
+ case DW_AT_comp_dir:
+ {
+ char *comp_dir = attr.u.str;
+
+ if (! is_str_form (&attr))
+ {
+ _bfd_error_handler
+ (_("DWARF error: DW_AT_comp_dir attribute encountered with a non-string form"));
+ comp_dir = NULL;
+ }
+
+ if (comp_dir)
+ {
+ char *cp = strchr (comp_dir, ':');
+
+ if (cp && cp != comp_dir && cp[-1] == '.' && cp[1] == '/')
+ comp_dir = cp + 1;
+ }
+ unit->comp_dir = comp_dir;
+ break;
+ }
+
+ case DW_AT_language:
+ unit->lang = attr.u.val;
+ default:
+ break;
+ }
+}
+
/* Parse a DWARF2 compilation unit starting at INFO_PTR. UNIT_LENGTH
includes the compilation unit header that proceeds the DIE's, but
does not include the length field that precedes each compilation
@@ -4064,6 +4270,9 @@ parse_comp_unit (struct dwarf2_debug *stash,
bfd *abfd = file->bfd_ptr;
bool high_pc_relative = false;
enum dwarf_unit_type unit_type;
+ struct attribute *str_addrp = NULL;
+ unsigned int count = 0;
+ bool compunit_flag = false;
version = read_2_bytes (abfd, &info_ptr, end_ptr);
if (version < 2 || version > 5)
@@ -4168,12 +4377,34 @@ parse_comp_unit (struct dwarf2_debug *stash,
unit->file = file;
unit->info_ptr_unit = info_ptr_unit;
+ if (abbrev->tag == DW_TAG_compile_unit)
+ compunit_flag = true;
+
for (i = 0; i < abbrev->num_attrs; ++i)
{
info_ptr = read_attribute (&attr, &abbrev->attrs[i], unit, info_ptr, end_ptr);
if (info_ptr == NULL)
return NULL;
+ /* Identify attributes of the form strx* and addrx* which come before
+ DW_AT_str_offsets_base and DW_AT_addr_base respectively in the CU.
+ Store the attributes in an array and process them later. */
+ if ((is_strx_form(attr.form) &&
+ unit->dwarf_str_offset == 0) ||
+ (is_addrx_form(attr.form) &&
+ unit->dwarf_addr_offset == 0))
+ {
+ str_addrp = (struct attribute *) bfd_realloc(str_addrp,
+ (count + 1) * sizeof(struct attribute));
+ if (str_addrp == NULL)
+ return NULL;
+ str_addrp[count].name = attr.name;
+ str_addrp[count].form = (enum dwarf_form) attr.form;
+ str_addrp[count].u.val = attr.u.val;
+ count++;
+ continue;
+ }
+
/* Store the data if it is of an attribute we want to keep in a
partial symbol table. */
switch (attr.name)
@@ -4198,7 +4429,7 @@ parse_comp_unit (struct dwarf2_debug *stash,
/* If the compilation unit DIE has a DW_AT_low_pc attribute,
this is the base address to use when reading location
lists or range lists. */
- if (abbrev->tag == DW_TAG_compile_unit)
+ if (compunit_flag)
unit->base_address = low_pc;
}
break;
@@ -4248,10 +4479,27 @@ parse_comp_unit (struct dwarf2_debug *stash,
unit->lang = attr.u.val;
break;
+ case DW_AT_addr_base:
+ unit->dwarf_addr_offset = attr.u.val;
+ break;
+
+ case DW_AT_str_offsets_base:
+ unit->dwarf_str_offset = attr.u.val;
+ break;
+
default:
break;
}
}
+
+ for (i = 0; i < count; ++i)
+ {
+ struct attribute attr1 = str_addrp[i];
+ reread_attribute(unit, attr1, &low_pc, &high_pc,
+ &high_pc_relative, compunit_flag);
+
+ }
+
if (high_pc_relative)
high_pc += low_pc;
if (high_pc != 0)
@@ -4262,6 +4510,10 @@ parse_comp_unit (struct dwarf2_debug *stash,
}
unit->first_child_die_ptr = info_ptr;
+
+ if (str_addrp != NULL)
+ free(str_addrp);
+
return unit;
}
--
2.17.1
[-- Attachment #2: 0001-bfd-dwarf2-Add-Support-for-DW_FORM_strx-and-DW_FORM_.patch --]
[-- Type: application/octet-stream, Size: 13926 bytes --]
Implement strx* and addrx* forms to the BFD library.
---
bfd/dwarf2.c | 274 ++++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 263 insertions(+), 11 deletions(-)
diff --git a/bfd/dwarf2.c b/bfd/dwarf2.c
index f6b0183720b..30f01442e93 100644
--- a/bfd/dwarf2.c
+++ b/bfd/dwarf2.c
@@ -189,6 +189,18 @@ struct dwarf2_debug_file
/* Length of the loaded .debug_str section. */
bfd_size_type dwarf_str_size;
+ /* Pointer to the .debug_str_offsets section loaded into memory. */
+ bfd_byte *dwarf_str_offsets_buffer;
+
+ /* Length of the loaded .debug_str_offsets section. */
+ bfd_size_type dwarf_str_offsets_size;
+
+ /* Pointer to the .debug_addr section loaded into memory. */
+ bfd_byte *dwarf_addr_buffer;
+
+ /* Length of the loaded .debug_addr section. */
+ bfd_size_type dwarf_addr_size;
+
/* Pointer to the .debug_line_str section loaded into memory. */
bfd_byte *dwarf_line_str_buffer;
@@ -382,6 +394,11 @@ struct comp_unit
/* Used when iterating over trie leaves to know which units we have
already seen in this iteration. */
bool mark;
+ /* Base address of debug_addr section. */
+ unsigned long dwarf_addr_offset;
+
+ /* Base address of string offset table. */
+ unsigned long dwarf_str_offset;
};
/* This data structure holds the information of an abbrev. */
@@ -424,6 +441,8 @@ const struct dwarf_debug_section dwarf_debug_sections[] =
{ ".debug_static_vars", ".zdebug_static_vars" },
{ ".debug_str", ".zdebug_str", },
{ ".debug_str", ".zdebug_str", },
+ { ".debug_str_offsets", ".zdebug_str_offsets", },
+ { ".debug_addr", ".zdebug_addr", },
{ ".debug_line_str", ".zdebug_line_str", },
{ ".debug_types", ".zdebug_types" },
/* GNU DWARF 1 extensions */
@@ -458,6 +477,8 @@ enum dwarf_debug_section_enum
debug_static_vars,
debug_str,
debug_str_alt,
+ debug_str_offsets,
+ debug_addr,
debug_line_str,
debug_types,
debug_sfnames,
@@ -1307,12 +1328,93 @@ is_int_form (const struct attribute *attr)
}
}
+/* Returns true if the form is strx[1-4]. */
+
+static inline bool
+is_strx_form(enum dwarf_form form)
+{
+ return (form == DW_FORM_strx
+ || form == DW_FORM_strx1
+ || form == DW_FORM_strx2
+ || form == DW_FORM_strx3
+ || form == DW_FORM_strx4);
+}
+
+/* Return true if the form is addrx[1-4]. */
+
+static inline bool
+is_addrx_form(enum dwarf_form form)
+{
+ return (form == DW_FORM_addrx
+ || form == DW_FORM_addrx1
+ || form == DW_FORM_addrx2
+ || form == DW_FORM_addrx3
+ || form == DW_FORM_addrx4);
+}
+
+/* Returns the address in .debug_addr section using DW_AT_addr_base.
+ Used to implement DW_FORM_addrx*. */
+static bfd_vma
+read_indexed_address (bfd_uint64_t idx,
+ struct comp_unit *unit)
+{
+ struct dwarf2_debug *stash = unit->stash;
+ struct dwarf2_debug_file *file = unit->file;
+ unsigned long addr_base = unit->dwarf_addr_offset;
+ bfd_byte *info_ptr;
+
+ if (stash == NULL)
+ return 0;
+
+ if (!read_section (unit->abfd, &stash->debug_sections[debug_addr],
+ file->syms, 0,
+ &file->dwarf_addr_buffer, &file->dwarf_addr_size))
+ return 0;
+
+ info_ptr = (bfd_byte *)(file->dwarf_addr_buffer + addr_base
+ + idx * unit->offset_size);
+
+ if (unit->offset_size == 4)
+ return bfd_get_32 (unit->abfd, info_ptr);
+ else
+ return bfd_get_64 (unit->abfd, info_ptr);
+}
+
+/* Returns the string using DW_AT_str_offsets_base.
+ Used to implement DW_FORM_strx*. */
static const char *
-read_indexed_string (bfd_uint64_t idx ATTRIBUTE_UNUSED,
- struct comp_unit * unit ATTRIBUTE_UNUSED)
+read_indexed_string (bfd_uint64_t idx,
+ struct comp_unit * unit)
{
- /* FIXME: Add support for indexed strings. */
- return "<indexed strings not yet supported>";
+ struct dwarf2_debug *stash = unit->stash;
+ struct dwarf2_debug_file *file = unit->file;
+ bfd_byte *info_ptr;
+ unsigned long str_offset;
+
+ if (stash == NULL)
+ return NULL;
+
+ if (!read_section (unit->abfd, &stash->debug_sections[debug_str],
+ file->syms, 0,
+ &file->dwarf_str_buffer, &file->dwarf_str_size))
+ return NULL;
+
+ if (!read_section (unit->abfd, &stash->debug_sections[debug_str_offsets],
+ file->syms, 0,
+ &file->dwarf_str_offsets_buffer,
+ &file->dwarf_str_offsets_size))
+ return NULL;
+
+ info_ptr = (bfd_byte *)(file->dwarf_str_offsets_buffer
+ + unit->dwarf_str_offset
+ + idx * unit->offset_size);
+
+ if (unit->offset_size == 4)
+ str_offset = bfd_get_32 (unit->abfd, info_ptr);
+ else
+ str_offset = bfd_get_64 (unit->abfd, info_ptr);
+
+ return (const char*) (file->dwarf_str_buffer + str_offset);
}
/* Read and fill in the value of attribute ATTR as described by FORM.
@@ -1381,21 +1483,37 @@ read_attribute_value (struct attribute * attr,
case DW_FORM_ref1:
case DW_FORM_flag:
case DW_FORM_data1:
+ attr->u.val = read_1_byte (abfd, &info_ptr, info_ptr_end);
+ break;
case DW_FORM_addrx1:
attr->u.val = read_1_byte (abfd, &info_ptr, info_ptr_end);
+ /* dwarf_addr_offset value 0 indicates the attribute DW_AT_addr_base
+ is not yet read. */
+ if (unit->dwarf_addr_offset != 0)
+ attr->u.val = read_indexed_address(attr->u.val, unit);
break;
case DW_FORM_data2:
- case DW_FORM_addrx2:
case DW_FORM_ref2:
attr->u.val = read_2_bytes (abfd, &info_ptr, info_ptr_end);
break;
+ case DW_FORM_addrx2:
+ attr->u.val = read_2_bytes (abfd, &info_ptr, info_ptr_end);
+ if (unit->dwarf_addr_offset != 0)
+ attr->u.val = read_indexed_address(attr->u.val, unit);
+ break;
case DW_FORM_addrx3:
attr->u.val = read_3_bytes (abfd, &info_ptr, info_ptr_end);
+ if (unit->dwarf_addr_offset != 0)
+ attr->u.val = read_indexed_address(attr->u.val, unit);
break;
case DW_FORM_ref4:
case DW_FORM_data4:
+ attr->u.val = read_4_bytes (abfd, &info_ptr, info_ptr_end);
+ break;
case DW_FORM_addrx4:
attr->u.val = read_4_bytes (abfd, &info_ptr, info_ptr_end);
+ if (unit->dwarf_addr_offset != 0)
+ attr->u.val = read_indexed_address(attr->u.val, unit);
break;
case DW_FORM_data8:
case DW_FORM_ref8:
@@ -1416,24 +1534,31 @@ read_attribute_value (struct attribute * attr,
break;
case DW_FORM_strx1:
attr->u.val = read_1_byte (abfd, &info_ptr, info_ptr_end);
- attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
+ /* dwarf_str_offset value 0 indicates the attribute DW_AT_str_offsets_base
+ is not yet read. */
+ if (unit->dwarf_str_offset != 0)
+ attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
break;
case DW_FORM_strx2:
attr->u.val = read_2_bytes (abfd, &info_ptr, info_ptr_end);
- attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
+ if (unit->dwarf_str_offset != 0)
+ attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
break;
case DW_FORM_strx3:
attr->u.val = read_3_bytes (abfd, &info_ptr, info_ptr_end);
- attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
+ if (unit->dwarf_str_offset != 0)
+ attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
break;
case DW_FORM_strx4:
attr->u.val = read_4_bytes (abfd, &info_ptr, info_ptr_end);
- attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
+ if (unit->dwarf_str_offset != 0)
+ attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
break;
case DW_FORM_strx:
attr->u.val = _bfd_safe_read_leb128 (abfd, &info_ptr,
false, info_ptr_end);
- attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
+ if (unit->dwarf_str_offset != 0)
+ attr->u.str = (char *) read_indexed_string (attr->u.val, unit);
break;
case DW_FORM_exprloc:
case DW_FORM_block:
@@ -1455,9 +1580,14 @@ read_attribute_value (struct attribute * attr,
break;
case DW_FORM_ref_udata:
case DW_FORM_udata:
+ attr->u.val = _bfd_safe_read_leb128 (abfd, &info_ptr,
+ false, info_ptr_end);
+ break;
case DW_FORM_addrx:
attr->u.val = _bfd_safe_read_leb128 (abfd, &info_ptr,
false, info_ptr_end);
+ if (unit->dwarf_addr_offset != 0)
+ attr->u.val = read_indexed_address(attr->u.val, unit);
break;
case DW_FORM_indirect:
form = _bfd_safe_read_leb128 (abfd, &info_ptr,
@@ -2396,6 +2526,11 @@ read_formatted_entries (struct comp_unit *unit, bfd_byte **bufp,
{
case DW_FORM_string:
case DW_FORM_line_strp:
+ case DW_FORM_strx:
+ case DW_FORM_strx1:
+ case DW_FORM_strx2:
+ case DW_FORM_strx3:
+ case DW_FORM_strx4:
*stringp = attr.u.str;
break;
@@ -4031,6 +4166,77 @@ scan_unit_for_symbols (struct comp_unit *unit)
return false;
}
+/* read the attributes of the form strx and addrx. */
+static void reread_attribute (struct comp_unit * unit,
+ struct attribute attr,
+ bfd_vma *low_pc,
+ bfd_vma *high_pc,
+ bool *high_pc_relative,
+ bool compunit)
+{
+
+ if (is_strx_form(attr.form))
+ attr.u.str = (char*) read_indexed_string (attr.u.val, unit);
+ if (is_addrx_form(attr.form))
+ attr.u.val = read_indexed_address (attr.u.val, unit);
+
+ switch (attr.name)
+ {
+ case DW_AT_stmt_list:
+ unit->stmtlist = 1;
+ unit->line_offset = attr.u.val;
+ break;
+
+ case DW_AT_name:
+ if (is_str_form (&attr))
+ unit->name = attr.u.str;
+ break;
+
+ case DW_AT_low_pc:
+ *low_pc = attr.u.val;
+ if (compunit)
+ unit->base_address = *low_pc;
+ break;
+
+ case DW_AT_high_pc:
+ *high_pc = attr.u.val;
+ *high_pc_relative = attr.form != DW_FORM_addr;
+ break;
+
+ case DW_AT_ranges:
+ if (!read_rangelist (unit, &unit->arange, attr.u.val))
+ return;
+ break;
+
+ case DW_AT_comp_dir:
+ {
+ char *comp_dir = attr.u.str;
+
+ if (! is_str_form (&attr))
+ {
+ _bfd_error_handler
+ (_("DWARF error: DW_AT_comp_dir attribute encountered with a non-string form"));
+ comp_dir = NULL;
+ }
+
+ if (comp_dir)
+ {
+ char *cp = strchr (comp_dir, ':');
+
+ if (cp && cp != comp_dir && cp[-1] == '.' && cp[1] == '/')
+ comp_dir = cp + 1;
+ }
+ unit->comp_dir = comp_dir;
+ break;
+ }
+
+ case DW_AT_language:
+ unit->lang = attr.u.val;
+ default:
+ break;
+ }
+}
+
/* Parse a DWARF2 compilation unit starting at INFO_PTR. UNIT_LENGTH
includes the compilation unit header that proceeds the DIE's, but
does not include the length field that precedes each compilation
@@ -4064,6 +4270,9 @@ parse_comp_unit (struct dwarf2_debug *stash,
bfd *abfd = file->bfd_ptr;
bool high_pc_relative = false;
enum dwarf_unit_type unit_type;
+ struct attribute *str_addrp = NULL;
+ unsigned int count = 0;
+ bool compunit_flag = false;
version = read_2_bytes (abfd, &info_ptr, end_ptr);
if (version < 2 || version > 5)
@@ -4168,12 +4377,34 @@ parse_comp_unit (struct dwarf2_debug *stash,
unit->file = file;
unit->info_ptr_unit = info_ptr_unit;
+ if (abbrev->tag == DW_TAG_compile_unit)
+ compunit_flag = true;
+
for (i = 0; i < abbrev->num_attrs; ++i)
{
info_ptr = read_attribute (&attr, &abbrev->attrs[i], unit, info_ptr, end_ptr);
if (info_ptr == NULL)
return NULL;
+ /* Identify attributes of the form strx* and addrx* which come before
+ DW_AT_str_offsets_base and DW_AT_addr_base respectively in the CU.
+ Store the attributes in an array and process them later. */
+ if ((is_strx_form(attr.form) &&
+ unit->dwarf_str_offset == 0) ||
+ (is_addrx_form(attr.form) &&
+ unit->dwarf_addr_offset == 0))
+ {
+ str_addrp = (struct attribute *) bfd_realloc(str_addrp,
+ (count + 1) * sizeof(struct attribute));
+ if (str_addrp == NULL)
+ return NULL;
+ str_addrp[count].name = attr.name;
+ str_addrp[count].form = (enum dwarf_form) attr.form;
+ str_addrp[count].u.val = attr.u.val;
+ count++;
+ continue;
+ }
+
/* Store the data if it is of an attribute we want to keep in a
partial symbol table. */
switch (attr.name)
@@ -4198,7 +4429,7 @@ parse_comp_unit (struct dwarf2_debug *stash,
/* If the compilation unit DIE has a DW_AT_low_pc attribute,
this is the base address to use when reading location
lists or range lists. */
- if (abbrev->tag == DW_TAG_compile_unit)
+ if (compunit_flag)
unit->base_address = low_pc;
}
break;
@@ -4248,10 +4479,27 @@ parse_comp_unit (struct dwarf2_debug *stash,
unit->lang = attr.u.val;
break;
+ case DW_AT_addr_base:
+ unit->dwarf_addr_offset = attr.u.val;
+ break;
+
+ case DW_AT_str_offsets_base:
+ unit->dwarf_str_offset = attr.u.val;
+ break;
+
default:
break;
}
}
+
+ for (i = 0; i < count; ++i)
+ {
+ struct attribute attr1 = str_addrp[i];
+ reread_attribute(unit, attr1, &low_pc, &high_pc,
+ &high_pc_relative, compunit_flag);
+
+ }
+
if (high_pc_relative)
high_pc += low_pc;
if (high_pc != 0)
@@ -4262,6 +4510,10 @@ parse_comp_unit (struct dwarf2_debug *stash,
}
unit->first_child_die_ptr = info_ptr;
+
+ if (str_addrp != NULL)
+ free(str_addrp);
+
return unit;
}
--
2.17.1
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH V2] bfd: Add Support for DW_FORM_strx* and DW_FORM_addrx*.
2022-05-24 0:01 [PATCH V2] bfd: Add Support for DW_FORM_strx* and DW_FORM_addrx* Potharla, Rupesh
@ 2022-05-26 7:02 ` Alan Modra
2022-05-26 16:42 ` Potharla, Rupesh
0 siblings, 1 reply; 3+ messages in thread
From: Alan Modra @ 2022-05-26 7:02 UTC (permalink / raw)
To: Potharla, Rupesh
Cc: binutils, Jan Beulich, George, Jini Susan, Parasuraman,
Hariharan, Natarajan, Kavitha
Thanks for the patch. I'm going to commit it with some formatting
fixes, and a few improvements.
- reread_attribute no longer copies its attr arg.
- str_addrp is alloc'd in chunks, not on each addition.
- error paths out of parse_comp_unit free str_addrp.
- variables used as offset into arrays are now size_t.
--
Alan Modra
Australia Development Lab, IBM
^ permalink raw reply [flat|nested] 3+ messages in thread
* RE: [PATCH V2] bfd: Add Support for DW_FORM_strx* and DW_FORM_addrx*.
2022-05-26 7:02 ` Alan Modra
@ 2022-05-26 16:42 ` Potharla, Rupesh
0 siblings, 0 replies; 3+ messages in thread
From: Potharla, Rupesh @ 2022-05-26 16:42 UTC (permalink / raw)
To: Alan Modra
Cc: binutils, Jan Beulich, George, Jini Susan, Parasuraman,
Hariharan, Natarajan, Kavitha
[AMD Official Use Only - General]
Thank you Alan for taking care of the commit.
Regards,
Rupesh P
>-----Original Message-----
>From: Alan Modra <amodra@gmail.com>
>Sent: Thursday, May 26, 2022 12:32 PM
>To: Potharla, Rupesh <Rupesh.Potharla@amd.com>
>Cc: binutils@sourceware.org; Jan Beulich <jbeulich@suse.com>; George, Jini
>Susan <JiniSusan.George@amd.com>; Parasuraman, Hariharan
><Hariharan.Parasuraman@amd.com>; Natarajan, Kavitha
><Kavitha.Natarajan@amd.com>
>Subject: Re: [PATCH V2] bfd: Add Support for DW_FORM_strx* and
>DW_FORM_addrx*.
>
>[CAUTION: External Email]
>
>Thanks for the patch. I'm going to commit it with some formatting fixes, and a
>few improvements.
>- reread_attribute no longer copies its attr arg.
>- str_addrp is alloc'd in chunks, not on each addition.
>- error paths out of parse_comp_unit free str_addrp.
>- variables used as offset into arrays are now size_t.
>
>--
>Alan Modra
>Australia Development Lab, IBM
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2022-05-26 16:42 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-05-24 0:01 [PATCH V2] bfd: Add Support for DW_FORM_strx* and DW_FORM_addrx* Potharla, Rupesh
2022-05-26 7:02 ` Alan Modra
2022-05-26 16:42 ` Potharla, Rupesh
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).