From: "Potharla, Rupesh" <Rupesh.Potharla@amd.com>
To: "binutils@sourceware.org" <binutils@sourceware.org>
Cc: "George, Jini Susan" <JiniSusan.George@amd.com>,
"Parasuraman, Hariharan" <Hariharan.Parasuraman@amd.com>,
"Natarajan, Kavitha" <Kavitha.Natarajan@amd.com>
Subject: [PATCH] bfd: Add Support for DW_FORM_strx* and DW_FORM_addrx*.
Date: Fri, 22 Apr 2022 06:36:22 +0000 [thread overview]
Message-ID: <DM6PR12MB4219C4BB638321CD26370813E7F79@DM6PR12MB4219.namprd12.prod.outlook.com> (raw)
[-- Attachment #1: Type: text/plain, Size: 176 bytes --]
[AMD Official Use Only]
Hi,
Requesting to review the attached patch. The patch provides support for strx* and addrx* forms to the bfd library.
Regards,
Rupesh P
[-- Attachment #2: 0001-bfd-dwarf2-Add-Support-for-DW_FORM_strx-and-DW_FORM_addrx.patch --]
[-- Type: application/octet-stream, Size: 15448 bytes --]
From c7ffb795ba446b21809e7e5bd503968a2c103555 Mon Sep 17 00:00:00 2001
From: rupothar <rupesh.potharla@amd.com>
Date: Wed, 30 Mar 2022 15:38:19 +0530
Subject: [PATCH] bfd/dwarf2: Add Support for DW_FORM_strx* and
DW_FORM_addrx*.
Made code changes implementing strx* and addrx* forms to the BFD library.
Change-Id: I441dcd47d2b4a0fd152a0fb0df511cf994cee3c2
---
bfd/dwarf2.c | 302 +++++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 280 insertions(+), 22 deletions(-)
diff --git a/bfd/dwarf2.c b/bfd/dwarf2.c
index 9aa4e955a5e..f19df9c16c1 100644
--- a/bfd/dwarf2.c
+++ b/bfd/dwarf2.c
@@ -118,6 +118,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;
@@ -296,6 +308,12 @@ struct comp_unit
/* TRUE if symbols are cached in hash table for faster lookup by name. */
bool cached;
+
+ /* 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. */
@@ -338,6 +356,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 */
@@ -372,6 +392,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,
@@ -1221,12 +1243,92 @@ 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);
+
+}
+
+/* Function to handle DW_FORM_addrx*. */
+static int
+read_indexed_address (struct comp_unit *unit,
+ unsigned long idx)
+{
+ 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);
+}
+
+/* Return the string for DW_FORM_strx*. */
static const char *
-read_indexed_string (bfd_uint64_t idx ATTRIBUTE_UNUSED,
- struct comp_unit * unit ATTRIBUTE_UNUSED)
+read_indexed_string (struct comp_unit * unit,
+ unsigned long idx)
{
- /* 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.
@@ -1330,24 +1432,19 @@ 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);
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);
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);
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);
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);
break;
case DW_FORM_exprloc:
case DW_FORM_block:
@@ -1486,6 +1583,7 @@ struct line_info_table
unsigned int num_files;
unsigned int num_dirs;
unsigned int num_sequences;
+ unsigned int version;
char * comp_dir;
char ** dirs;
struct fileinfo* files;
@@ -2115,6 +2213,23 @@ read_formatted_entries (struct comp_unit *unit, bfd_byte **bufp,
return false;
switch (form)
{
+ case DW_FORM_strx:
+ case DW_FORM_strx1:
+ case DW_FORM_strx2:
+ case DW_FORM_strx3:
+ case DW_FORM_strx4:
+ attr.u.str = (char*) read_indexed_string(unit, attr.u.val);
+ *stringp = attr.u.str;
+ break;
+
+ case DW_FORM_addrx:
+ case DW_FORM_addrx1:
+ case DW_FORM_addrx2:
+ case DW_FORM_addrx3:
+ case DW_FORM_addrx4:
+ attr.u.val = read_indexed_address(unit, attr.u.val);
+ break;
+
case DW_FORM_string:
case DW_FORM_line_strp:
*stringp = attr.u.str;
@@ -2134,10 +2249,8 @@ read_formatted_entries (struct comp_unit *unit, bfd_byte **bufp,
}
}
- /* Skip the first "zero entry", which is the compilation dir/file. */
- if (datai != 0)
- if (!callback (table, fe.name, fe.dir, fe.time, fe.size))
- return false;
+ if (!callback (table, fe.name, fe.dir, fe.time, fe.size))
+ return false;
}
*bufp = buf;
@@ -2302,6 +2415,7 @@ decode_line_info (struct comp_unit *unit)
table->sequences = NULL;
table->lcl_head = NULL;
+ table->version = lh.version;
if (lh.version >= 5)
{
@@ -2484,6 +2598,8 @@ decode_line_info (struct comp_unit *unit)
filenum = _bfd_safe_read_leb128 (abfd, &line_ptr,
false, line_end);
free (filename);
+ if (table->version >= 5)
+ filenum = filenum + 1;
filename = concat_filename (table, filenum);
break;
}
@@ -3081,6 +3197,11 @@ find_abstract_instance (struct comp_unit *unit,
{
info_ptr = read_attribute (&attr, &abbrev->attrs[i], unit,
info_ptr, info_ptr_end);
+ if (is_strx_form(attr.form))
+ attr.u.str = (char*) read_indexed_string(unit, attr.u.val);
+ if (is_addrx_form(attr.form))
+ attr.u.val = read_indexed_address(unit, attr.u.val);
+
if (info_ptr == NULL)
break;
switch (attr.name)
@@ -3116,8 +3237,12 @@ find_abstract_instance (struct comp_unit *unit,
if (!comp_unit_maybe_decode_line_info (unit))
return false;
if (is_int_form (&attr))
- *filename_ptr = concat_filename (unit->line_table,
- attr.u.val);
+ {
+ if (unit->line_table->version >=5)
+ attr.u.val = attr.u.val + 1;
+ *filename_ptr = concat_filename (unit->line_table,
+ attr.u.val);
+ }
break;
case DW_AT_decl_line:
if (is_int_form (&attr))
@@ -3453,6 +3578,10 @@ scan_unit_for_symbols (struct comp_unit *unit)
unit, info_ptr, info_ptr_end);
if (info_ptr == NULL)
goto fail;
+ if (is_strx_form(attr.form))
+ attr.u.str = (char*) read_indexed_string(unit, attr.u.val);
+ if (is_addrx_form(attr.form))
+ attr.u.val = read_indexed_address(unit, attr.u.val);
}
if (abbrev->has_children)
@@ -3554,6 +3683,10 @@ scan_unit_for_symbols (struct comp_unit *unit)
unit, info_ptr, info_ptr_end);
if (info_ptr == NULL)
goto fail;
+ if (is_strx_form(attr.form))
+ attr.u.str = (char*) read_indexed_string(unit, attr.u.val);
+ if (is_addrx_form(attr.form))
+ attr.u.val = read_indexed_address(unit, attr.u.val);
if (func)
{
@@ -3561,8 +3694,12 @@ scan_unit_for_symbols (struct comp_unit *unit)
{
case DW_AT_call_file:
if (is_int_form (&attr))
- func->caller_file = concat_filename (unit->line_table,
- attr.u.val);
+ {
+ if (unit->line_table->version >= 5)
+ attr.u.val = attr.u.val + 1;
+ func->caller_file = concat_filename (unit->line_table,
+ attr.u.val);
+ }
break;
case DW_AT_call_line:
@@ -3624,8 +3761,12 @@ scan_unit_for_symbols (struct comp_unit *unit)
case DW_AT_decl_file:
if (is_int_form (&attr))
- func->file = concat_filename (unit->line_table,
- attr.u.val);
+ {
+ if (unit->line_table->version >= 5)
+ attr.u.val = attr.u.val + 1;
+ func->file = concat_filename (unit->line_table,
+ attr.u.val);
+ }
break;
case DW_AT_decl_line:
@@ -3675,8 +3816,12 @@ scan_unit_for_symbols (struct comp_unit *unit)
case DW_AT_decl_file:
if (is_int_form (&attr))
- var->file = concat_filename (unit->line_table,
- attr.u.val);
+ {
+ if (unit->line_table->version >=5)
+ attr.u.val = attr.u.val + 1;
+ var->file = concat_filename (unit->line_table,
+ attr.u.val);
+ }
break;
case DW_AT_decl_line:
@@ -3750,6 +3895,78 @@ 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(unit, attr.u.val);
+ if (is_addrx_form(attr.form))
+ attr.u.val = read_indexed_address(unit, attr.u.val);
+
+ 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
@@ -3783,6 +4000,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)
@@ -3887,12 +4107,29 @@ 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 store them in
+ an array and process them again. */
+ if (is_strx_form(attr.form) ||
+ is_addrx_form(attr.form))
+ {
+ str_addrp = (struct attribute *) bfd_realloc(str_addrp,
+ (count + 1) * sizeof(struct attribute));
+ 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)
@@ -3917,7 +4154,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;
@@ -3966,10 +4203,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)
@@ -3979,6 +4233,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
next reply other threads:[~2022-04-22 6:36 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-04-22 6:36 Potharla, Rupesh [this message]
2022-04-25 12:56 ` Jan Beulich
2022-05-08 16:28 ` Potharla, Rupesh
2022-05-17 11:38 ` Jan Beulich
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=DM6PR12MB4219C4BB638321CD26370813E7F79@DM6PR12MB4219.namprd12.prod.outlook.com \
--to=rupesh.potharla@amd.com \
--cc=Hariharan.Parasuraman@amd.com \
--cc=JiniSusan.George@amd.com \
--cc=Kavitha.Natarajan@amd.com \
--cc=binutils@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).