|
From: <sv...@va...> - 2005-06-14 21:51:59
|
Author: sewardj
Date: 2005-06-14 22:51:14 +0100 (Tue, 14 Jun 2005)
New Revision: 3911
Log:
Complete the merge of Eric Estievenart's DWARF2 directory-reading
patch. This actually requires a major restructuring of the DWARF2
line number reading stuff.
Modified:
trunk/coregrind/m_debuginfo/dwarf.c
trunk/coregrind/m_debuginfo/priv_symtab.h
trunk/coregrind/m_debuginfo/symtab.c
Modified: trunk/coregrind/m_debuginfo/dwarf.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/m_debuginfo/dwarf.c 2005-06-13 18:22:17 UTC (rev 3910=
)
+++ trunk/coregrind/m_debuginfo/dwarf.c 2005-06-14 21:51:14 UTC (rev 3911=
)
@@ -138,6 +138,17 @@
}
DWARF2_Internal_LineInfo;
=20
+/* Structure holding additional infos found from a .debug_info
+ * compilation unit block */
+typedef struct
+{
+ /* Feel free to add more members here if you need ! */
+ Char* compdir; /* Compilation directory - points to .debug_info */
+ Char* name; /* Main file name - points to .debug_info */
+ UInt stmt_list; /* Offset in .debug_line */
+}=20
+UnitInfo;
+
/* Line number opcodes. */
enum dwarf_line_number_ops
{
@@ -213,22 +224,43 @@
}
=20
=20
+/* Small helper functions easier to use
+ * value is returned and the given pointer is
+ * moved past end of leb128 data */
+static UInt read_leb128U( UChar **data )
+{
+ Int len;
+ UInt val =3D read_leb128( *data, &len, 0 );
+ *data +=3D len;
+ return val;
+}
+
+/* Same for signed data */
+static Int read_leb128S( UChar **data )
+{
+ Int len;
+ UInt val =3D read_leb128( *data, &len, 1 );
+ *data +=3D len;
+ return val;
+}
+
+
static SMR state_machine_regs;
=20
static=20
void reset_state_machine ( Int is_stmt )
{
- if (0) VG_(printf)("smr.a :=3D %p (reset)\n", 0 );
- state_machine_regs.last_address =3D 0;
- state_machine_regs.last_file =3D 1;
- state_machine_regs.last_line =3D 1;
- state_machine_regs.address =3D 0;
- state_machine_regs.file =3D 1;
- state_machine_regs.line =3D 1;
- state_machine_regs.column =3D 0;
- state_machine_regs.is_stmt =3D is_stmt;
- state_machine_regs.basic_block =3D 0;
- state_machine_regs.end_sequence =3D 0;
+ if (0) VG_(printf)("smr.a :=3D %p (reset)\n", 0 );
+ state_machine_regs.last_address =3D 0;
+ state_machine_regs.last_file =3D 1;
+ state_machine_regs.last_line =3D 1;
+ state_machine_regs.address =3D 0;
+ state_machine_regs.file =3D 1;
+ state_machine_regs.line =3D 1;
+ state_machine_regs.column =3D 0;
+ state_machine_regs.is_stmt =3D is_stmt;
+ state_machine_regs.basic_block =3D 0;
+ state_machine_regs.end_sequence =3D 0;
}
=20
/* Look up a directory name, or return NULL if unknown. */
@@ -242,416 +274,686 @@
return (Char*)dirname;
}
=20
+////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////
=20
/* Handled an extend line op. Returns true if this is the end
of sequence. */
static=20
-int process_extended_line_op( SegInfo *si,=20
+Int process_extended_line_op( SegInfo* si,=20
WordArray* filenames,=20
WordArray* dirnames,=20
WordArray* fnidx2dir,=20
UChar* data, Int is_stmt)
{
- UChar op_code;
- Int bytes_read;
- UInt len;
- UChar * name;
- Addr adr;
+ UChar op_code;
+ Int bytes_read;
+ UInt len;
+ UChar* name;
+ Addr adr;
=20
- len =3D read_leb128 (data, & bytes_read, 0);
- data +=3D bytes_read;
+ len =3D read_leb128 (data, & bytes_read, 0);
+ data +=3D bytes_read;
=20
- if (len =3D=3D 0)
- {
+ if (len =3D=3D 0) {
VG_(message)(Vg_UserMsg,
- "badly formed extended line op encountered!\n");
+ "badly formed extended line op encountered!\n");
return bytes_read;
- }
+ }
=20
- len +=3D bytes_read;
- op_code =3D * data ++;
+ len +=3D bytes_read;
+ op_code =3D * data ++;
=20
- if (0) VG_(printf)("dwarf2: ext OPC: %d\n", op_code);
+ if (0) VG_(printf)("dwarf2: ext OPC: %d\n", op_code);
=20
- switch (op_code)
- {
- case DW_LNE_end_sequence:
- if (0) VG_(printf)("1001: si->o %p, smr.a %p\n",=20
- si->offset, state_machine_regs.address );
- state_machine_regs.end_sequence =3D 1; /* JRS: added for complianc=
e
- with spec; is pointless due to reset_state_machine below=20
- */
- if (state_machine_regs.is_stmt) {
- if (state_machine_regs.last_address)
- VG_(addLineInfo) (
- si,=20
- (Char*)index_WordArray(filenames, state_machine_regs.last=
_file),=20
- lookupDir( state_machine_regs.last_file,
- fnidx2dir, dirnames ),
- si->offset + state_machine_regs.last_address,=20
- si->offset + state_machine_regs.address,=20
- state_machine_regs.last_line, 0
- );
- }
- reset_state_machine (is_stmt);
- break;
+ switch (op_code) {
+ case DW_LNE_end_sequence:
+ if (0) VG_(printf)("1001: si->o %p, smr.a %p\n",=20
+ si->offset, state_machine_regs.address );
+ /* JRS: added for compliance with spec; is pointless due to
+ reset_state_machine below */
+ state_machine_regs.end_sequence =3D 1;=20
=20
- case DW_LNE_set_address:
- adr =3D *((Addr *)data);
- if (0) VG_(printf)("smr.a :=3D %p\n", adr );
- state_machine_regs.address =3D adr;
- break;
+ if (state_machine_regs.is_stmt) {
+ if (state_machine_regs.last_address)
+ VG_(addLineInfo) (
+ si,=20
+ (Char*)index_WordArray(filenames,=20
+ state_machine_regs.last_file),=20
+ lookupDir( state_machine_regs.last_file,
+ fnidx2dir, dirnames ),
+ si->offset + state_machine_regs.last_address,=20
+ si->offset + state_machine_regs.address,=20
+ state_machine_regs.last_line, 0
+ );
+ }
+ reset_state_machine (is_stmt);
+ break;
=20
- case DW_LNE_define_file:
- name =3D data;
- addto_WordArray( filenames, (Word)VG_(addStr)(si,name,-1) );
- data +=3D VG_(strlen) ((char *) data) + 1;
- read_leb128 (data, & bytes_read, 0);
- data +=3D bytes_read;
- read_leb128 (data, & bytes_read, 0);
- data +=3D bytes_read;
- read_leb128 (data, & bytes_read, 0);
- break;
+ case DW_LNE_set_address:
+ adr =3D *((Addr *)data);
+ if (0) VG_(printf)("smr.a :=3D %p\n", adr );
+ state_machine_regs.address =3D adr;
+ break;
=20
- default:
- break;
- }
+ case DW_LNE_define_file:
+ name =3D data;
+ addto_WordArray( filenames, (Word)VG_(addStr)(si,name,-1) );
+ data +=3D VG_(strlen) ((char *) data) + 1;
+ read_leb128 (data, & bytes_read, 0);
+ data +=3D bytes_read;
+ read_leb128 (data, & bytes_read, 0);
+ data +=3D bytes_read;
+ read_leb128 (data, & bytes_read, 0);
+ break;
=20
- return len;
+ default:
+ break;
+ }
+
+ return len;
}
=20
+////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////
=20
-void VG_(read_debuginfo_dwarf2) ( SegInfo* si, UChar* dwarf2, Int dwarf2=
_sz )
+/* read a .debug_line section block for a compilation unit
+ *
+ * Input: - theBlock must point to the start of the block
+ * for the given compilation unit
+ * - ui contains additional info like the compilation dir
+ * for this unit
+ *
+ * Output: - si debug info structures get updated
+ */
+static=20
+void read_dwarf2_lineblock ( SegInfo* si,=20
+ UnitInfo* ui,=20
+ UChar* theBlock,=20
+ Int noLargerThan )
{
- DWARF2_External_LineInfo* external;
- DWARF2_Internal_LineInfo info;
- UChar* standard_opcodes;
- UChar* data =3D dwarf2;
- UChar* end =3D dwarf2 + dwarf2_sz;
- UChar* end_of_sequence;
- WordArray filenames;
- WordArray dirnames;
- WordArray fnidx2dir;
+ DWARF2_External_LineInfo* external;
+ DWARF2_Internal_LineInfo info;
+ UChar* standard_opcodes;
+ UChar* data =3D theBlock;
+ UChar* end_of_sequence;
+ WordArray filenames;
+ WordArray dirnames;
+ WordArray fnidx2dir;
=20
- /* filenames is an array of file names harvested from the DWARF2 info.=
=20
- Entry [0] is NULL and is never referred to by the state machine.
+ /* filenames is an array of file names harvested from the DWARF2
+ info. Entry [0] is NULL and is never referred to by the state
+ machine.
=20
- Similarly, dirnames is an array of directory names. Entry [0] is
- also NULL and denotes "we don't know what the path is", since
- that is different from "the path is the empty string". Unlike
- the file name table, the state machine does refer to entry [0],
- which basically means "." ("the current directory of the
- compilation", whatever that means, according to the DWARF3 spec.)
+ Similarly, dirnames is an array of directory names. Entry [0]
+ is also NULL and denotes "we don't know what the path is", since
+ that is different from "the path is the empty string". Unlike
+ the file name table, the state machine does refer to entry [0],
+ which basically means "." ("the current directory of the
+ compilation", whatever that means, according to the DWARF3
+ spec.)
=20
- fnidx2dir is an array of indexes into the dirnames table.
- (confused yet?) filenames[] and fnidx2dir[] are indexed together.
- That is, for some index i in the filename table, then
+ fnidx2dir is an array of indexes into the dirnames table.
+ (confused yet?) filenames[] and fnidx2dir[] are indexed
+ together. That is, for some index i in the filename table, then
=20
- the filename is filenames[i]
- the diretory is dirnames[ fnidx2dir[i] ] */
+ the filename is filenames[i]
+ the directory is dirnames[ fnidx2dir[i] ] */
=20
- /* Fails due to gcc padding ...
- vg_assert(sizeof(DWARF2_External_LineInfo)
- =3D=3D sizeof(DWARF2_Internal_LineInfo));
- */
+ /* Fails due to gcc padding ...
+ vg_assert(sizeof(DWARF2_External_LineInfo)
+ =3D=3D sizeof(DWARF2_Internal_LineInfo));
+ */
=20
- init_WordArray(&filenames);
- init_WordArray(&dirnames);
- init_WordArray(&fnidx2dir);
+ vg_assert(noLargerThan > 0);
=20
- while (data < end) {
+ init_WordArray(&filenames);
+ init_WordArray(&dirnames);
+ init_WordArray(&fnidx2dir);
=20
- /* Dump the file/dirname tables and start over. */
- free_WordArray(&filenames);
- free_WordArray(&dirnames);
- free_WordArray(&fnidx2dir);
+ /* DWARF2 starts numbering filename entries at 1, so we need to
+ add a dummy zeroth entry to the table. The zeroth dirnames
+ entry denotes 'current directory of compilation' so we might
+ as well make the fnidx2dir zeroth entry denote that.=20
+ */
+ addto_WordArray( &filenames, (Word)NULL );
=20
- init_WordArray(&filenames);
- init_WordArray(&dirnames);
- init_WordArray(&fnidx2dir);
+ if (ui->compdir)
+ addto_WordArray( &dirnames, (Word)VG_(addStr)(si, ui->compdir, -1)=
);
+ else
+ addto_WordArray( &dirnames, (Word)VG_(addStr)(si, ".", -1) );
=20
- /* DWARF2 starts numbering filename entries at 1, so we need to
- add a dummy zeroth entry to the table. The zeroth dirnames
- entry denotes 'current directory of compilation' so we might
- as well make the fnidx2dir zeroth entry denote that.=20
- */
- addto_WordArray( &filenames, (Word)NULL );
- addto_WordArray( &dirnames, (Word)VG_(addStr)(si,".",-1) );
- addto_WordArray( &fnidx2dir, (Word)0 ); /* "." */
+ addto_WordArray( &fnidx2dir, (Word)0 ); /* compilation dir */
=20
- external =3D (DWARF2_External_LineInfo *) data;
=20
- /* Check the length of the block. */
- info.li_length =3D * ((UInt *)(external->li_length));
+ external =3D (DWARF2_External_LineInfo *) data;
=20
- if (info.li_length =3D=3D 0xffffffff)=20
- {
- VG_(symerr)("64-bit DWARF line info is not supported yet.");
- goto out;
- }
+ /* Check the length of the block. */
+ info.li_length =3D * ((UInt *)(external->li_length));
=20
- if (info.li_length + sizeof (external->li_length) > dwarf2_sz)
- {
- VG_(symerr)("DWARF line info appears to be corrupt "
+ if (info.li_length =3D=3D 0xffffffff) {
+ VG_(symerr)("64-bit DWARF line info is not supported yet.");
+ goto out;
+ }
+
+ if (info.li_length + sizeof (external->li_length) > noLargerThan) {
+ VG_(symerr)("DWARF line info appears to be corrupt "
"- the section is too small");
- goto out;
- }
+ goto out;
+ }
=20
- /* Check its version number. */
- info.li_version =3D * ((UShort *) (external->li_version));
- if (info.li_version !=3D 2)
- {
- VG_(symerr)("Only DWARF version 2 line info "
- "is currently supported.");
- goto out;
- }
+ /* Check its version number. */
+ info.li_version =3D * ((UShort *) (external->li_version));
+ if (info.li_version !=3D 2) {
+ VG_(symerr)("Only DWARF version 2 line info "
+ "is currently supported.");
+ goto out;
+ }
=20
- info.li_prologue_length =3D * ((UInt *) (external->li_prologue_len=
gth));
- info.li_min_insn_length =3D * ((UChar *)(external->li_min_insn_len=
gth));
+ info.li_prologue_length =3D * ((UInt *) (external->li_prologue_length=
));
+ info.li_min_insn_length =3D * ((UChar *)(external->li_min_insn_length=
));
=20
- info.li_default_is_stmt =3D True;=20
- /* WAS: =3D * ((UChar *)(external->li_default_is_stmt)); */
- /* Josef Weidendorfer (20021021) writes:
+ info.li_default_is_stmt =3D True;=20
+ /* WAS: =3D * ((UChar *)(external->li_default_is_stmt)); */
+ /* Josef Weidendorfer (20021021) writes:
=20
- It seems to me that the Intel Fortran compiler generates
- bad DWARF2 line info code: It sets "is_stmt" of the state
- machine in the the line info reader to be always
- false. Thus, there is never a statement boundary generated
- and therefore never a instruction range/line number
- mapping generated for valgrind.
+ It seems to me that the Intel Fortran compiler generates bad
+ DWARF2 line info code: It sets "is_stmt" of the state machine in
+ the the line info reader to be always false. Thus, there is
+ never a statement boundary generated and therefore never a
+ instruction range/line number mapping generated for valgrind.
=20
- Please have a look at the DWARF2 specification, Ch. 6.2
- (x86.ddj.com/ftp/manuals/tools/dwarf.pdf). Perhaps I
- understand this wrong, but I don't think so.
+ Please have a look at the DWARF2 specification, Ch. 6.2
+ (x86.ddj.com/ftp/manuals/tools/dwarf.pdf). Perhaps I understand
+ this wrong, but I don't think so.
=20
- I just had a look at the GDB DWARF2 reader... They
- completely ignore "is_stmt" when recording line info ;-)
- That's the reason "objdump -S" works on files from the the
- intel fortran compiler. =20
- */
+ I just had a look at the GDB DWARF2 reader... They completely
+ ignore "is_stmt" when recording line info ;-) That's the reason
+ "objdump -S" works on files from the the intel fortran compiler.
+ */
=20
+ /* JRS: changed (UInt*) to (UChar*) */
+ info.li_line_base =3D * ((UChar *)(external->li_line_base));
=20
- /* JRS: changed (UInt*) to (UChar*) */
- info.li_line_base =3D * ((UChar *)(external->li_line_base));
+ info.li_line_range =3D * ((UChar *)(external->li_line_range));
+ info.li_opcode_base =3D * ((UChar *)(external->li_opcode_base));=20
=20
- info.li_line_range =3D * ((UChar *)(external->li_line_range))=
;
- info.li_opcode_base =3D * ((UChar *)(external->li_opcode_base)=
);=20
+ if (0) VG_(printf)("dwarf2: line base: %d, range %d, opc base: %d\n",
+ info.li_line_base,=20
+ info.li_line_range, info.li_opcode_base);
=20
- if (0) VG_(printf)("dwarf2: line base: %d, range %d, opc base: %d\=
n",
- info.li_line_base, info.li_line_range, info.li_opcode_=
base);
+ /* Sign extend the line base field. */
+ info.li_line_base <<=3D 24;
+ info.li_line_base >>=3D 24;
=20
- /* Sign extend the line base field. */
- info.li_line_base <<=3D 24;
- info.li_line_base >>=3D 24;
+ end_of_sequence =3D data + info.li_length=20
+ + sizeof (external->li_length);
=20
- end_of_sequence =3D data + info.li_length=20
- + sizeof (external->li_length);
+ reset_state_machine (info.li_default_is_stmt);
=20
- reset_state_machine (info.li_default_is_stmt);
+ /* Read the contents of the Opcodes table. */
+ standard_opcodes =3D data + sizeof (* external);
=20
- /* Read the contents of the Opcodes table. */
- standard_opcodes =3D data + sizeof (* external);
+ /* Read the contents of the Directory table. */
+ data =3D standard_opcodes + info.li_opcode_base - 1;
=20
- /* Read the contents of the Directory table. */
- data =3D standard_opcodes + info.li_opcode_base - 1;
+ while (* data !=3D 0) {
=20
- while (* data !=3D 0) {
+# define NBUF 4096
+ static Char buf[NBUF];
+
+ /* If data[0] is '/', then 'data' is an absolute path and we
+ don't mess with it. Otherwise, if we can, construct the
+ 'path ui->compdir' ++ "/" ++ 'data'. */
+
+ if (*data !=3D '/'=20
+ /* not an absolute path */
+ && VG_(strlen)(ui->compdir) + VG_(strlen)(data) + 5/*paranoia*=
/ < NBUF
+ /* it's short enough to concatenate */)=20
+ {
+ buf[0] =3D 0;
+ VG_(strcat)(buf, ui->compdir);
+ VG_(strcat)(buf, "/");
+ VG_(strcat)(buf, data);
+ vg_assert(VG_(strlen)(buf) < NBUF);
+ addto_WordArray( &dirnames, (Word)VG_(addStr)(si,buf,-1) );
+ if (0) VG_(printf)("rel path %s\n", buf);
+ } else {
+ /* just use 'data'. */
addto_WordArray( &dirnames, (Word)VG_(addStr)(si,data,-1) );
- data +=3D VG_(strlen) ((char *) data) + 1;
+ if (0) VG_(printf)("abs path %s\n", data);
}
- if (*data !=3D 0) {
- VG_(symerr)("can't find NUL at end of DWARF2 directory table");
- goto out;
- }
- data ++;
=20
- /* Read the contents of the File Name table. This produces a
- bunch of file names, and for each, an index to the
- corresponding direcory name entry. */
- while (* data !=3D 0) {
- UChar* name;
- Int bytes_read, diridx;
- name =3D data;
- data +=3D VG_(strlen) ((Char *) data) + 1;
+ data +=3D VG_(strlen)(data) + 1;
=20
- diridx =3D read_leb128 (data, & bytes_read, 0);
- data +=3D bytes_read;
- read_leb128 (data, & bytes_read, 0);
- data +=3D bytes_read;
- read_leb128 (data, & bytes_read, 0);
- data +=3D bytes_read;
+# undef NBUF
+ }
+ if (*data !=3D 0) {
+ VG_(symerr)("can't find NUL at end of DWARF2 directory table");
+ goto out;
+ }
+ data ++;
=20
- addto_WordArray( &filenames, (Word)VG_(addStr)(si,name,-1) );
- addto_WordArray( &fnidx2dir, (Word)diridx );
- if (0) VG_(printf)("file %s diridx %d\n", name, diridx );
+ /* Read the contents of the File Name table. This produces a bunch
+ of file names, and for each, an index to the corresponding
+ direcory name entry. */
+ while (* data !=3D 0) {
+ UChar* name;
+ Int bytes_read, diridx;
+ name =3D data;
+ data +=3D VG_(strlen) ((Char *) data) + 1;
+
+ diridx =3D read_leb128 (data, & bytes_read, 0);
+ data +=3D bytes_read;
+ read_leb128 (data, & bytes_read, 0);
+ data +=3D bytes_read;
+ read_leb128 (data, & bytes_read, 0);
+ data +=3D bytes_read;
+
+ addto_WordArray( &filenames, (Word)VG_(addStr)(si,name,-1) );
+ addto_WordArray( &fnidx2dir, (Word)diridx );
+ if (0) VG_(printf)("file %s diridx %d\n", name, diridx );
+ }
+ if (*data !=3D 0) {
+ VG_(symerr)("can't find NUL at end of DWARF2 file name table");
+ goto out;
+ }
+ data ++;
+
+ /* Now display the statements. */
+
+ while (data < end_of_sequence) {
+
+ UChar op_code;
+ Int adv;
+ Int bytes_read;
+
+ op_code =3D * data ++;
+
+ if (0) VG_(printf)("dwarf2: OPC: %d\n", op_code);
+
+ if (op_code >=3D info.li_opcode_base) {
+
+ Int advAddr;
+ op_code -=3D info.li_opcode_base;
+ adv =3D (op_code / info.li_line_range)=20
+ * info.li_min_insn_length;
+ advAddr =3D adv;
+ state_machine_regs.address +=3D adv;
+ if (0) VG_(printf)("smr.a +=3D %p\n", adv );
+ adv =3D (op_code % info.li_line_range) + info.li_line_base;
+ if (0) VG_(printf)("1002: si->o %p, smr.a %p\n",=20
+ si->offset, state_machine_regs.address );
+ state_machine_regs.line +=3D adv;
+
+ if (state_machine_regs.is_stmt) {
+ /* only add a statement if there was a previous boundary */
+ if (state_machine_regs.last_address)=20
+ VG_(addLineInfo)(
+ si,=20
+ (Char*)index_WordArray( &filenames,
+ state_machine_regs.last_file )=
,
+ lookupDir( state_machine_regs.last_file,
+ &fnidx2dir, &dirnames ),
+ si->offset + state_machine_regs.last_address,=20
+ si->offset + state_machine_regs.address,=20
+ state_machine_regs.last_line,=20
+ 0
+ );
+ state_machine_regs.last_address =3D state_machine_regs.addre=
ss;
+ state_machine_regs.last_file =3D state_machine_regs.file;
+ state_machine_regs.last_line =3D state_machine_regs.line;
+ }
+
}
- if (*data !=3D 0) {
- VG_(symerr)("can't find NUL at end of DWARF2 file name table");
- goto out;
- }
- data ++;
=20
- /* Now display the statements. */
+ else /* ! (op_code >=3D info.li_opcode_base) */
+ switch (op_code) {
+ case DW_LNS_extended_op:
+ data +=3D process_extended_line_op (
+ si, &filenames, &dirnames, &fnidx2dir,
+ data, info.li_default_is_stmt);
+ break;
=20
- while (data < end_of_sequence)
- {
- UChar op_code;
- Int adv;
- Int bytes_read;
+ case DW_LNS_copy:
+ if (0) VG_(printf)("1002: si->o %p, smr.a %p\n",=20
+ si->offset, state_machine_regs.address );
+ if (state_machine_regs.is_stmt) {
+ /* only add a statement if there was a previous boundary =
*/
+ if (state_machine_regs.last_address)=20
+ VG_(addLineInfo)(
+ si,=20
+ (Char*)index_WordArray( &filenames,
+ state_machine_regs.last_fil=
e ),
+ lookupDir( state_machine_regs.last_file,
+ &fnidx2dir, &dirnames ),
+ si->offset + state_machine_regs.last_address,=20
+ si->offset + state_machine_regs.address,
+ state_machine_regs.last_line,=20
+ 0
+ );
+ state_machine_regs.last_address =3D state_machine_regs.ad=
dress;
+ state_machine_regs.last_file =3D state_machine_regs.file;
+ state_machine_regs.last_line =3D state_machine_regs.line;
+ }
+ state_machine_regs.basic_block =3D 0; /* JRS added */
+ break;
=20
- op_code =3D * data ++;
+ case DW_LNS_advance_pc:
+ adv =3D info.li_min_insn_length=20
+ * read_leb128 (data, & bytes_read, 0);
+ data +=3D bytes_read;
+ state_machine_regs.address +=3D adv;
+ if (0) VG_(printf)("smr.a +=3D %p\n", adv );
+ break;
=20
- if (0) VG_(printf)("dwarf2: OPC: %d\n", op_code);
+ case DW_LNS_advance_line:
+ adv =3D read_leb128 (data, & bytes_read, 1);
+ data +=3D bytes_read;
+ state_machine_regs.line +=3D adv;
+ break;
=20
- if (op_code >=3D info.li_opcode_base)
- {
- Int advAddr;
- op_code -=3D info.li_opcode_base;
- adv =3D (op_code / info.li_line_range)=20
- * info.li_min_insn_length;
- advAddr =3D adv;
- state_machine_regs.address +=3D adv;
- if (0) VG_(printf)("smr.a +=3D %p\n", adv );
- adv =3D (op_code % info.li_line_range) + info.li_line_base;
- if (0) VG_(printf)("1002: si->o %p, smr.a %p\n",=20
- si->offset, state_machine_regs.address )=
;
- state_machine_regs.line +=3D adv;
+ case DW_LNS_set_file:
+ adv =3D read_leb128 (data, & bytes_read, 0);
+ data +=3D bytes_read;
+ state_machine_regs.file =3D adv;
+ break;
=20
- if (state_machine_regs.is_stmt) {
- /* only add a statement if there was a previous boundary */
- if (state_machine_regs.last_address)=20
- VG_(addLineInfo)(
- si,=20
- (Char*)index_WordArray( &filenames,
- state_machine_regs.last_=
file ),
- lookupDir( state_machine_regs.last_file,
- &fnidx2dir, &dirnames ),
- si->offset + state_machine_regs.last_address,=20
- si->offset + state_machine_regs.address,=20
- state_machine_regs.last_line,=20
- 0
- );
- state_machine_regs.last_address =3D state_machine_regs.address;
- state_machine_regs.last_file =3D state_machine_regs.file;
- state_machine_regs.last_line =3D state_machine_regs.line;
- }
- }
- else switch (op_code)
- {
- case DW_LNS_extended_op:
- data +=3D process_extended_line_op (
- si, &filenames, &dirnames, &fnidx2dir,
- data, info.li_default_is_stmt);
- break;
+ case DW_LNS_set_column:
+ adv =3D read_leb128 (data, & bytes_read, 0);
+ data +=3D bytes_read;
+ state_machine_regs.column =3D adv;
+ break;
=20
- case DW_LNS_copy:
- if (0) VG_(printf)("1002: si->o %p, smr.a %p\n",=20
- si->offset, state_machine_regs.address )=
;
- if (state_machine_regs.is_stmt) {
- /* only add a statement if there was a previous boundary */
- if (state_machine_regs.last_address)=20
- VG_(addLineInfo)(
- si,=20
- (Char*)index_WordArray( &filenames,
- state_machine_regs.last_=
file ),
- lookupDir( state_machine_regs.last_file,
- &fnidx2dir, &dirnames ),
- si->offset + state_machine_regs.last_address,=20
- si->offset + state_machine_regs.address,
- state_machine_regs.last_line,=20
- 0
- );
- state_machine_regs.last_address =3D state_machine_regs.address;
- state_machine_regs.last_file =3D state_machine_regs.file;
- state_machine_regs.last_line =3D state_machine_regs.line;
- }
- state_machine_regs.basic_block =3D 0; /* JRS added */
- break;
+ case DW_LNS_negate_stmt:
+ adv =3D state_machine_regs.is_stmt;
+ adv =3D ! adv;
+ state_machine_regs.is_stmt =3D adv;
+ break;
=20
- case DW_LNS_advance_pc:
- adv =3D info.li_min_insn_length=20
- * read_leb128 (data, & bytes_read, 0);
- data +=3D bytes_read;
- state_machine_regs.address +=3D adv;
- if (0) VG_(printf)("smr.a +=3D %p\n", adv );
- break;
+ case DW_LNS_set_basic_block:
+ state_machine_regs.basic_block =3D 1;
+ break;
=20
- case DW_LNS_advance_line:
- adv =3D read_leb128 (data, & bytes_read, 1);
- data +=3D bytes_read;
- state_machine_regs.line +=3D adv;
- break;
+ case DW_LNS_const_add_pc:
+ adv =3D (((255 - info.li_opcode_base) / info.li_line_range)
+ * info.li_min_insn_length);
+ state_machine_regs.address +=3D adv;
+ if (0) VG_(printf)("smr.a +=3D %p\n", adv );
+ break;
=20
- case DW_LNS_set_file:
- adv =3D read_leb128 (data, & bytes_read, 0);
- data +=3D bytes_read;
- state_machine_regs.file =3D adv;
- break;
+ case DW_LNS_fixed_advance_pc:
+ /* XXX: Need something to get 2 bytes */
+ adv =3D *((UShort *)data);
+ data +=3D 2;
+ state_machine_regs.address +=3D adv;
+ if (0) VG_(printf)("smr.a +=3D %p\n", adv );
+ break;
=20
- case DW_LNS_set_column:
- adv =3D read_leb128 (data, & bytes_read, 0);
- data +=3D bytes_read;
- state_machine_regs.column =3D adv;
- break;
+ case DW_LNS_set_prologue_end:
+ break;
=20
- case DW_LNS_negate_stmt:
- adv =3D state_machine_regs.is_stmt;
- adv =3D ! adv;
- state_machine_regs.is_stmt =3D adv;
- break;
+ case DW_LNS_set_epilogue_begin:
+ break;
=20
- case DW_LNS_set_basic_block:
- state_machine_regs.basic_block =3D 1;
- break;
+ case DW_LNS_set_isa:
+ adv =3D read_leb128 (data, & bytes_read, 0);
+ data +=3D bytes_read;
+ break;
=20
- case DW_LNS_const_add_pc:
- adv =3D (((255 - info.li_opcode_base) / info.li_line_range)
- * info.li_min_insn_length);
- state_machine_regs.address +=3D adv;
- if (0) VG_(printf)("smr.a +=3D %p\n", adv );
- break;
+ default: {
+ Int j;
+ for (j =3D standard_opcodes[op_code - 1]; j > 0 ; --j) {
+ read_leb128 (data, &bytes_read, 0);
+ data +=3D bytes_read;
+ }
+ }
+ break;
+ } /* switch (op_code) */
=20
- case DW_LNS_fixed_advance_pc:
- /* XXX: Need something to get 2 bytes */
- adv =3D *((UShort *)data);
- data +=3D 2;
- state_machine_regs.address +=3D adv;
- if (0) VG_(printf)("smr.a +=3D %p\n", adv );
- break;
+ } /* while (data < end_of_sequence) */
=20
- case DW_LNS_set_prologue_end:
- break;
+ out:
+ free_WordArray(&filenames);
+ free_WordArray(&dirnames);
+ free_WordArray(&fnidx2dir);
+}
=20
- case DW_LNS_set_epilogue_begin:
- break;
+////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////
=20
- case DW_LNS_set_isa:
- adv =3D read_leb128 (data, & bytes_read, 0);
- data +=3D bytes_read;
- break;
+/* Return abbrev for given code=20
+ * Returned pointer points to the tag
+ * */
+static UChar* lookup_abbrev( UChar* p, UInt acode )
+{
+ UInt code;
+ UInt name;
+ for( ; ; ) {
+ code =3D read_leb128U( &p );
+ if ( code =3D=3D acode )
+ return p;
+ read_leb128U( &p ); /* skip tag */
+ p++; /* skip has_children flag */
+ do {
+ name =3D read_leb128U( &p ); /* name */
+ read_leb128U( &p ); /* form */
+ }
+ while( name !=3D 0 ); /* until name =3D=3D form =3D=3D 0 */
+ }
+ return NULL;
+}
=20
- default:
- {
- int j;
- for (j =3D standard_opcodes[op_code - 1]; j > 0 ; --j)
- {
- read_leb128 (data, &bytes_read, 0);
- data +=3D bytes_read;
- }
- }
- break;
- }
- } /* while (data < end_of_sequence) */
+/* Read general information for a particular compile unit block in
+ * the .debug_info section.
+ *=20
+ * Input: - unitblock is the start of a compilation
+ * unit block in .debuginfo section
+ * - debugabbrev is start of .debug_abbrev section
+ * - debugstr is start of .debug_str section
+ * =20
+ * Output: Fill members of ui pertaining to the compilation unit:
+ * - ui->name is the name of the compilation unit
+ * - ui->compdir is the compilation unit directory
+ * - ui->stmt_list is the offset in .debug_line section
+ * for the dbginfos of this compilation unit
+ * =20
+ * Note : the output strings are not allocated and point
+ * directly to the memory-mapped section.
+ */
+static=20
+void read_unitinfo_dwarf2( /*OUT*/UnitInfo* ui,
+ UChar* unitblock,
+ UChar* debugabbrev,
+ UChar* debugstr )
+{
+ UInt atoffs, acode, abcode, blklen;
+ Int addr_size, ver, level;
=20
- } /* while (data < end) */
+ UChar* p =3D unitblock;
+ UChar* end;
+ UChar* abbrev;
=20
- out:
- free_WordArray(&filenames);
- free_WordArray(&dirnames);
- free_WordArray(&fnidx2dir);
+ VG_(memset)( ui, 0, sizeof( UnitInfo ) );
+ ui->stmt_list =3D (UInt)-1;
+ =20
+ /* Read the compilation unit header in .debug_info section - See p 70=
*/ =20
+ blklen =3D *((UInt*)p); p +=3D 4; /* This block length */
+ ver =3D *((UShort*)p); p +=3D 2; /* version should be 2 */
+ atoffs =3D *((UInt*)p); p +=3D 4; /* get offset in abbrev */
+ addr_size =3D *p; p +=3D 1; /* Address size */
+
+ end =3D unitblock + blklen + 4; /* End of this block */
+ level =3D 0; /* Level in the abbrev tree */
+ abbrev =3D debugabbrev + atoffs; /* Abbreviation data for this bloc=
k */
+ =20
+ /* Read the compilation unit entries */
+ while ( p < end ) {
+ Bool has_child;
+ UInt tag;
+
+ acode =3D read_leb128U( &p ); /* abbreviation code */
+ if ( acode =3D=3D 0 ) {
+ /* NULL entry used for padding - or last child for a sequence
+ - see para 7.5.3 */
+ level--;
+ continue;
+ }
+ =20
+ /* Read abbreviation header */
+ abcode =3D read_leb128U( &abbrev ); /* abbreviation code */
+ if ( acode !=3D abcode ) {
+ /* We are in in children list, and must rewind to a
+ * previously declared abbrev code. This code works but is
+ * not triggered since we shortcut the parsing once we have
+ * read the compile_unit block. This should only occur when
+ * level > 0 */
+ abbrev =3D lookup_abbrev( debugabbrev + atoffs, acode );
+ }
+
+ tag =3D read_leb128U( &abbrev );
+ has_child =3D *(abbrev++) =3D=3D 1; /* DW_CHILDREN_yes */
+
+ if ( has_child )
+ level++;
+
+ /* And loop on entries */
+ for ( ; ; ) {
+ /* Read entry definition */
+ UInt name, form;
+ UInt cval =3D -1; /* Constant value read */
+ Char *sval =3D NULL; /* String value read */
+ name =3D read_leb128U( &abbrev );
+ form =3D read_leb128U( &abbrev );
+ if ( name =3D=3D 0 )
+ break;
+ =20
+ /* Read data */
+ /* Attributes encoding explained p 71 */
+ if ( form =3D=3D 0x16 /* FORM_indirect */ )
+ form =3D read_leb128U( &p );
+ /* Decode form. For most kinds, Just skip the amount of data si=
nce
+ we don't use it for now */
+ switch( form ) {
+ /* Those cases extract the data properly */
+ case 0x05: /* FORM_data2 */ cval =3D *((UShort*)p); p +=3D=
2; break;
+ case 0x06: /* FORM_data4 */ cval =3D *((UInt*)p);p +=3D4=
; break;
+ case 0x0e: /* FORM_strp */ sval =3D debugstr + *((UInt*=
)p);=20
+ p +=3D 4; break;
+ /* pointer in .debug_str */
+ case 0x08: /* FORM_string */ sval =3D (Char*)p;=20
+ p +=3D VG_(strlen)((Char*)p)=
+ 1; break;
+ case 0x0b: /* FORM_data1 */ cval =3D *p; p++; break;
+ =20
+ /* TODO : Following ones just skip data - implement if you n=
eed */
+ case 0x01: /* FORM_addr */ p +=3D addr_size; break;
+ case 0x03: /* FORM_block2 */ p +=3D *((UShort*)p) + 2; br=
eak;
+ case 0x04: /* FORM_block4 */ p +=3D *((UInt*)p) + 4; brea=
k;
+ case 0x07: /* FORM_data8 */ p +=3D8; break;
+ case 0x09: /* FORM_block */ p +=3D read_leb128U( &p ); b=
reak;
+ case 0x0a: /* FORM_block1 */ p +=3D *p + 1; break;
+ case 0x0c: /* FORM_flag */ p++; break;
+ case 0x0d: /* FORM_sdata */ read_leb128S( &p ); break;
+ case 0x0f: /* FORM_udata */ read_leb128U( &p ); break;
+ case 0x10: /* FORM_ref_addr */ p +=3D addr_size; break;
+ /* TODO Check that !!! */
+ case 0x11: /* FORM_ref1 */ p++; break;
+ case 0x12: /* FORM_ref2 */ p +=3D 2; break;
+ case 0x13: /* FORM_ref4 */ p +=3D 4; break;
+ case 0x14: /* FORM_ref8 */ p +=3D 8; break;
+ case 0x15: /* FORM_ref_udata */ read_leb128U( &p ); break;
+ =20
+ default:
+ VG_(printf)( "### unhandled dwarf2 abbrev form code 0x%x\=
n", form );
+ break;
+ }
+ =20
+ /* Now store the members we need in the UnitInfo structure */
+ if ( tag =3D=3D 0x0011 /*TAG_compile_unit*/ ) {
+ if ( name =3D=3D 0x03 ) ui->name =3D sval; /* DW_A=
T_name */
+ else if ( name =3D=3D 0x1b ) ui->compdir =3D sval; /* DW_A=
T_compdir */
+ else if ( name =3D=3D 0x10 ) ui->stmt_list =3D cval; /* DW_A=
T_stmt_list */
+ }
+ }
+ /* Shortcut the parsing once we have read the compile_unit block
+ * That's enough info for us, and we are not gdb ! */
+ if ( tag =3D=3D 0x0011 /*TAG_compile_unit*/ )
+ break;
+ } /* Loop on each sub block */
+
+ /* This test would be valid if we were not shortcuting the parsing
+ if( level !=3D 0 )
+ VG_(printf)( "#### Exiting debuginfo block at level %d !!!\n", lev=
el );
+ */
}
=20
=20
+////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////
+
+
+/* Collect the debug info from dwarf2 debugging sections
+ * of a given module.
+ *=20
+ * Inputs: given .debug_xxx sections
+ * Output: update si to contain all the dwarf2 debug infos
+ */
+void VG_(read_debuginfo_dwarf2)=20
+ ( SegInfo* si,
+ UChar* debuginfo, Int debug_info_sz, /* .debug_info */
+ UChar* debugabbrev, /* .debug_abbrev */
+ UChar* debugline, Int debug_line_sz, /* .debug_line */
+ UChar* debugstr ) /* .debug_str */
+{
+ UnitInfo ui;
+ Int ver;
+ UChar* block;
+ UChar* end =3D debuginfo + debug_info_sz;
+ UInt blklen;
+
+ /* Iterate on all the blocks we find in .debug_info */
+ for ( block =3D debuginfo; block < end - 4; block +=3D blklen + 4 ) {
+
+ /* Read the compilation unit header in .debug_info section - See
+ p 70 */
+ blklen =3D *((UInt*)block); /* This block length */
+
+ if ( block + blklen + 4 > end ) {
+ VG_(symerr)( "Last block truncated in .debug_info; ignoring" );
+ return;
+ }
+ ver =3D *((UShort*)(block + 4)); /* version should be 2 */
+ =20
+ if ( ver !=3D 2 ) {
+ VG_(symerr)( "Ignoring non-dwarf2 block in .debug_info" );
+ continue;
+ }
+ =20
+ /* Fill ui with offset in .debug_line and compdir */
+ if ( 0 )
+ VG_(printf)( "Reading UnitInfo at 0x%x.....\n", block - debugin=
fo );
+ read_unitinfo_dwarf2( &ui, block, debugabbrev, debugstr );
+ if ( 0 )
+ VG_(printf)( " =3D> LINES=3D0x%x NAME=3D%s DIR=3D%s\n",=
=20
+ ui.stmt_list, ui.name, ui.compdir );
+ =20
+ /* Ignore blocks with no .debug_line associated block */
+ if ( ui.stmt_list =3D=3D (UInt)-1 )
+ continue;
+ =20
+ if (0)=20
+ VG_(printf)("debug_line_sz %d, ui.stmt_list %d %s\n",=20
+ debug_line_sz, ui.stmt_list, ui.name );
+ /* Read the .debug_line block for this compile unit */
+ read_dwarf2_lineblock( si, &ui, debugline + ui.stmt_list,=20
+ debug_line_sz - ui.stmt_list );
+ }
+}
+
+
+////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////
+
/*------------------------------------------------------------*/
/*--- Read DWARF1 format line number info. ---*/
/*------------------------------------------------------------*/
Modified: trunk/coregrind/m_debuginfo/priv_symtab.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/m_debuginfo/priv_symtab.h 2005-06-13 18:22:17 UTC (re=
v 3910)
+++ trunk/coregrind/m_debuginfo/priv_symtab.h 2005-06-14 21:51:14 UTC (re=
v 3911)
@@ -231,20 +231,29 @@
struct _StabTypeTab *stab_typetab;
};
=20
+extern
Char *VG_(addStr) ( SegInfo* si, Char* str, Int len );
+
+extern
void VG_(addScopeInfo) ( SegInfo* si, Addr this, Addr next, Scope *scope=
);
+
+extern
void VG_(addLineInfo) ( SegInfo* si,=20
Char* filename,=20
Char* dirname, /* NULL is allowable */
Addr this, Addr next, Int lineno, Int entry);
+
+extern
void VG_(addCfiSI) ( SegInfo* si, CfiSI* cfisi );
=20
/* Non-fatal -- use vg_panic if terminal. */
+extern
void VG_(symerr) ( Char* msg );
=20
/* --------------------
Stabs reader
-------------------- */
+extern
void VG_(read_debuginfo_stabs) ( SegInfo* si,
UChar* stabC, Int stab_sz,=20
UChar* stabstr, Int stabstr_sz );
@@ -252,12 +261,18 @@
/* --------------------
DWARF2 reader
-------------------- */
-void VG_(read_debuginfo_dwarf2) ( SegInfo* si,=20
- UChar* dwarf2, Int dwarf2_sz );
+extern
+void VG_(read_debuginfo_dwarf2)=20
+ ( SegInfo* si,
+ UChar* debuginfo, Int debug_info_sz, /* .debug_info */
+ UChar* debugabbrev, /* .debug_abbrev */
+ UChar* debugline, Int debug_line_sz, /* .debug_line */
+ UChar* debugstr );
=20
/* --------------------
DWARF1 reader
-------------------- */
+extern
void VG_(read_debuginfo_dwarf1) ( SegInfo* si,=20
UChar* dwarf1d, Int dwarf1d_sz,=20
UChar* dwarf1l, Int dwarf1l_sz );
@@ -265,6 +280,7 @@
/* --------------------
CFI reader
-------------------- */
+extern
void VG_(read_callframe_info_dwarf2)=20
( /*OUT*/SegInfo* si, UChar* ehframe, Int ehframe_sz, Addr ehframe_a=
ddr );
=20
Modified: trunk/coregrind/m_debuginfo/symtab.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/m_debuginfo/symtab.c 2005-06-13 18:22:17 UTC (rev 391=
0)
+++ trunk/coregrind/m_debuginfo/symtab.c 2005-06-14 21:51:14 UTC (rev 391=
1)
@@ -1593,6 +1593,9 @@
UChar* stab =3D NULL; /* .stab (stabs) */
UChar* stabstr =3D NULL; /* .stabstr (stabs) */
UChar* debug_line =3D NULL; /* .debug_line (dwarf2) */
+ UChar* debug_info =3D NULL; /* .debug_info (dwarf2) */
+ UChar* debug_abbv =3D NULL; /* .debug_abbrev (dwarf2) */
+ UChar* debug_str =3D NULL; /* .debug_str (dwarf2) */
UChar* dwarf1d =3D NULL; /* .debug (dwarf1) */
UChar* dwarf1l =3D NULL; /* .line (dwarf1) */
UChar* ehframe =3D NULL; /* .eh_frame (dwarf2) */
@@ -1606,6 +1609,9 @@
UInt stab_sz =3D 0;
UInt stabstr_sz =3D 0;
UInt debug_line_sz =3D 0;
+ UInt debug_info_sz =3D 0;
+ UInt debug_abbv_sz =3D 0;
+ UInt debug_str_sz =3D 0;
UInt dwarf1d_sz =3D 0;
UInt dwarf1l_sz =3D 0;
UInt ehframe_sz =3D 0;
@@ -1647,7 +1653,12 @@
=20
else FIND(".stab", stab, stab_sz, dummy_a=
ddr, 0, UChar*)
else FIND(".stabstr", stabstr, stabstr_sz, dummy_a=
ddr, 0, UChar*)
+
else FIND(".debug_line", debug_line, debug_line_sz, dummy_a=
ddr, 0, UChar*)
+ else FIND(".debug_info", debug_info, debug_info_sz, dummy_a=
ddr, 0, UChar*)
+ else FIND(".debug_abbrev", debug_abbv, debug_abbv_sz, dummy_a=
ddr, 0, UChar*)
+ else FIND(".debug_str", debug_str, debug_str_sz, dummy_a=
ddr, 0, UChar*)
+
else FIND(".debug", dwarf1d, dwarf1d_sz, dummy_a=
ddr, 0, UChar*)
else FIND(".line", dwarf1l, dwarf1l_sz, dummy_a=
ddr, 0, UChar*)
else FIND(".eh_frame", ehframe, ehframe_sz, ehframe=
_addr, 0, UChar*)
@@ -1737,7 +1748,11 @@
# endif
if (debug_line) {
has_debuginfo =3D True;
- VG_(read_debuginfo_dwarf2) ( si, debug_line, debug_line_sz );
+ VG_(read_debuginfo_dwarf2) ( si,=20
+ debug_info, debug_info_sz,
+ debug_abbv,
+ debug_line, debug_line_sz,
+ debug_str );
}
if (dwarf1d && dwarf1l) {
has_debuginfo =3D True;
|