aboutsummaryrefslogtreecommitdiff
path: root/gprofng
diff options
context:
space:
mode:
authorVladimir Mezentsev <vladimir.mezentsev@oracle.com>2023-03-05 17:35:53 -0800
committerVladimir Mezentsev <vladimir.mezentsev@oracle.com>2023-03-07 09:56:19 -0800
commit74f1d7f4a3183bca13058dde29f5559d480a1b51 (patch)
tree3c9e830cbc6c2fd17b55b1629e3a251a06d7451d /gprofng
parent5fc6b6d44cd63651c2902cbfc5b9734a55aaa617 (diff)
downloadgdb-74f1d7f4a3183bca13058dde29f5559d480a1b51.zip
gdb-74f1d7f4a3183bca13058dde29f5559d480a1b51.tar.gz
gdb-74f1d7f4a3183bca13058dde29f5559d480a1b51.tar.bz2
gprofng: read Dwarf 5
gprofng reads Dwarf to find function names, sources, and line numbers. gprofng skips other debug information. I fixed three places in gprofng Dwarf reader: - parsing the compilation unit header. - parsing the line number table header. - parsing new DW_FORMs. Tested on aarch64-linux/x86_64-linux. gprofng/ChangeLog 2023-03-05 Vladimir Mezentsev <vladimir.mezentsev@oracle.com> PR gprofng/30195 gprofng/src/Dwarf.cc: Support Dwarf-5. gprofng/src/DwarfLib.cc: Likewise. gprofng/src/Dwarf.h: Likewise. gprofng/src/DwarfLib.h: Likewise. gprofng/src/collctrl.cc: Don't read freed memory.
Diffstat (limited to 'gprofng')
-rw-r--r--gprofng/src/Dwarf.cc10
-rw-r--r--gprofng/src/Dwarf.h1
-rw-r--r--gprofng/src/DwarfLib.cc458
-rw-r--r--gprofng/src/DwarfLib.h14
-rw-r--r--gprofng/src/collctrl.cc4
5 files changed, 382 insertions, 105 deletions
diff --git a/gprofng/src/Dwarf.cc b/gprofng/src/Dwarf.cc
index fb430cd..c982102 100644
--- a/gprofng/src/Dwarf.cc
+++ b/gprofng/src/Dwarf.cc
@@ -369,6 +369,7 @@ Dwarf::Dwarf (Stabs *_stabs)
debug_abbrevSec = NULL;
debug_strSec = NULL;
debug_lineSec = NULL;
+ debug_line_strSec = NULL;
debug_rangesSec = NULL;
elf = stabs->openElf (true);
if (elf == NULL)
@@ -388,6 +389,7 @@ Dwarf::Dwarf (Stabs *_stabs)
debug_strSec = dwrGetSec (NTXT (".debug_str"));
debug_lineSec = dwrGetSec (NTXT (".debug_line"));
debug_rangesSec = dwrGetSec (NTXT (".debug_ranges"));
+ debug_line_strSec = dwrGetSec (".debug_line_str");
if ((debug_infoSec == NULL) || (debug_abbrevSec == NULL) || (debug_lineSec == NULL))
{
@@ -610,9 +612,9 @@ Dwarf::archive_Dwarf (LoadObject *lo)
dwrCU->srcFiles = new Vector<SourceFile *> (VecSize (lineReg->file_names));
for (long i = 0, sz = VecSize (lineReg->file_names); i < sz; i++)
{
- char *fname = lineReg->getPath (i + 1);
- SourceFile *sf = mod->findSource (fname, true);
- dwrCU->srcFiles->append (sf);
+ char *fname = lineReg->getPath (i);
+ if (fname)
+ dwrCU->srcFiles->append (mod->findSource (fname, true));
}
}
@@ -988,7 +990,7 @@ DwrCU::append_Function (Dwarf_cnt *ctx)
if (lineno > 0)
{
func->setLineFirst (lineno);
- int fileno = ((int) Dwarf_data (DW_AT_decl_file)) - 1;
+ int fileno = ((int) Dwarf_data (DW_AT_decl_file));
SourceFile *sf = ((fileno >= 0) && (fileno < VecSize (srcFiles))) ? srcFiles->get (fileno)
: module->getMainSrc ();
func->setDefSrc (sf);
diff --git a/gprofng/src/Dwarf.h b/gprofng/src/Dwarf.h
index 1d99d78..0d77563 100644
--- a/gprofng/src/Dwarf.h
+++ b/gprofng/src/Dwarf.h
@@ -76,6 +76,7 @@ public:
DwrSec *debug_abbrevSec;
DwrSec *debug_strSec;
DwrSec *debug_lineSec;
+ DwrSec *debug_line_strSec;
DwrSec *debug_rangesSec;
Elf *elf;
Stabs *stabs;
diff --git a/gprofng/src/DwarfLib.cc b/gprofng/src/DwarfLib.cc
index e7130a7..e90c685 100644
--- a/gprofng/src/DwarfLib.cc
+++ b/gprofng/src/DwarfLib.cc
@@ -140,6 +140,33 @@ template<> void Vector<DwrLine *>
Dprintf (1, NTXT ("\n\n"));
}
+template<> void Vector<DwrFileName *>
+::dump (const char *msg)
+{
+ Dprintf (1, "\n%s Vector<DwrFileName *> [%lld]: [dir_ind tstamp fsize]\n",
+ msg ? msg : NTXT (""), (long long) size ());
+ for (long i = 0, sz = size (); i < sz; i++)
+ {
+ DwrFileName *fnp = get (i);
+ Dprintf (1, " %2ld %3lld %8lld %8lld %s\n", i, (long long) fnp->dir_index,
+ (long long) fnp->timestamp, (long long) fnp->file_size,
+ STR (fnp->fname));
+ }
+ Dprintf (1, "\n");
+}
+
+static char *
+get_string (DwrSec *sec, uint64_t off)
+{
+ if (sec)
+ {
+ sec->offset = off;
+ return sec->GetString ();
+ }
+ return NULL;
+}
+
+
//////////////////////////////////////////////////////////
// class ElfReloc
@@ -687,6 +714,16 @@ DwrCU::tag2str (int tag)
CASE_S (DW_TAG_SUN_memop_info);
CASE_S (DW_TAG_hi_user);
CASE_S (DW_TAG_icc_compile_unit);
+ CASE_S (DW_TAG_rvalue_reference_type);
+ CASE_S (DW_TAG_coarray_type);
+ CASE_S (DW_TAG_generic_subrange);
+ CASE_S (DW_TAG_dynamic_type);
+ CASE_S (DW_TAG_atomic_type);
+ CASE_S (DW_TAG_call_site);
+ CASE_S (DW_TAG_call_site_parameter);
+ CASE_S (DW_TAG_skeleton_unit);
+ CASE_S (DW_TAG_immutable_type);
+ CASE_S (0);
default: s = NTXT ("???");
break;
}
@@ -833,6 +870,8 @@ DwrCU::at2str (int tag)
CASE_S (DW_AT_GNU_all_tail_call_sites);
CASE_S (DW_AT_GNU_all_call_sites);
CASE_S (DW_AT_GNU_all_source_call_sites);
+ CASE_S (DW_AT_GNU_locviews);
+ CASE_S (DW_AT_GNU_entry_view);
CASE_S (DW_AT_SUN_command_line);
CASE_S (DW_AT_SUN_func_offsets);
CASE_S (DW_AT_SUN_cf_kind);
@@ -846,6 +885,36 @@ DwrCU::at2str (int tag)
CASE_S (DW_AT_SUN_link_name);
CASE_S (DW_AT_hi_user);
CASE_S (DW_AT_icc_flags);
+ CASE_S (DW_AT_string_length_bit_size);
+ CASE_S (DW_AT_string_length_byte_size);
+ CASE_S (DW_AT_rank);
+ CASE_S (DW_AT_str_offsets_base);
+ CASE_S (DW_AT_addr_base);
+ CASE_S (DW_AT_rnglists_base);
+ CASE_S (DW_AT_dwo_name);
+ CASE_S (DW_AT_reference);
+ CASE_S (DW_AT_rvalue_reference);
+ CASE_S (DW_AT_macros);
+ CASE_S (DW_AT_call_all_calls);
+ CASE_S (DW_AT_call_all_source_calls);
+ CASE_S (DW_AT_call_all_tail_calls);
+ CASE_S (DW_AT_call_return_pc);
+ CASE_S (DW_AT_call_value);
+ CASE_S (DW_AT_call_origin);
+ CASE_S (DW_AT_call_parameter);
+ CASE_S (DW_AT_call_pc);
+ CASE_S (DW_AT_call_tail_call);
+ CASE_S (DW_AT_call_target);
+ CASE_S (DW_AT_call_target_clobbered);
+ CASE_S (DW_AT_call_data_location);
+ CASE_S (DW_AT_call_data_value);
+ CASE_S (DW_AT_noreturn);
+ CASE_S (DW_AT_alignment);
+ CASE_S (DW_AT_export_symbols);
+ CASE_S (DW_AT_deleted);
+ CASE_S (DW_AT_defaulted);
+ CASE_S (DW_AT_loclists_base);
+
default: s = NTXT ("???");
break;
}
@@ -867,6 +936,9 @@ DwrCU::form2str (int tag)
CASE_S (DW_FORM_data2);
CASE_S (DW_FORM_data4);
CASE_S (DW_FORM_data8);
+ CASE_S (DW_FORM_data16);
+ CASE_S (DW_FORM_line_strp);
+ CASE_S (DW_FORM_implicit_const);
CASE_S (DW_FORM_string);
CASE_S (DW_FORM_block);
CASE_S (DW_FORM_block1);
@@ -894,6 +966,28 @@ DwrCU::form2str (int tag)
return buf;
}
+char *
+DwrCU::lnct2str (int ty)
+{
+ static char buf[128];
+ char *s;
+ switch (ty)
+ {
+ CASE_S (DW_LNCT_path);
+ CASE_S (DW_LNCT_directory_index);
+ CASE_S (DW_LNCT_timestamp);
+ CASE_S (DW_LNCT_size);
+ CASE_S (DW_LNCT_MD5);
+ CASE_S (DW_LNCT_lo_user);
+ CASE_S (DW_LNCT_hi_user);
+ default: s = NTXT ("???");
+ break;
+ }
+ snprintf (buf, sizeof (buf), NTXT ("%s(%d)"), s, ty);
+ buf[sizeof (buf) - 1] = 0;
+ return buf;
+}
+
void
Dwr_Tag::dump ()
{
@@ -910,14 +1004,16 @@ Dwr_Tag::dump ()
{
case DW_FORM_strp:
case DW_FORM_string:
- Dprintf (DUMP_DWARFLIB, " \"%s\" len=%ld",
- atrp->u.str ? atrp->u.str : NTXT ("<NULL>"),
- (long) atrp->len);
+ case DW_FORM_line_strp:
+ case DW_FORM_strp_sup:
+ case DW_FORM_implicit_const:
+ Dprintf (DUMP_DWARFLIB, " \"%s\"", atrp->u.str ? atrp->u.str : "<NULL>");
break;
case DW_FORM_block:
case DW_FORM_block1:
case DW_FORM_block2:
case DW_FORM_block4:
+ case DW_FORM_data16:
Dprintf (DUMP_DWARFLIB, " len=%3ld %p", (long) atrp->len,
atrp->u.str);
break;
@@ -1042,6 +1138,19 @@ DwrSec::Get_16 ()
}
uint32_t
+DwrSec::Get_24 ()
+{
+ uint32_t n = 0;
+ if (bounds_violation (3))
+ return n;
+ memcpy ((char *) &n, data + offset, 3);
+ offset += 3;
+ if (need_swap_endian)
+ SWAP_ENDIAN (n);
+ return n;
+}
+
+uint32_t
DwrSec::Get_32 ()
{
uint32_t n = 0;
@@ -1078,27 +1187,17 @@ DwrSec::GetData (uint64_t len)
}
char *
-DwrSec::GetString (uint64_t *lenp)
-{
- if (offset < size)
- {
- uint64_t len = 0;
- for (char *s = ((char *) data) + offset; offset + len < size; len++)
- {
- if (s[len] == 0)
- { // '\0' is inside section
- offset += len + 1;
- if (len == 0)
- return NULL;
- if (lenp)
- *lenp = len + 1;
- return s;
- }
- }
- offset += len;
- return NULL; // The section is not '\0' terminated
- }
- return NULL;
+DwrSec::GetString ()
+{
+ uint64_t off = offset;
+ while (offset < size)
+ if (data[offset++] == 0)
+ { // '\0' is inside section
+ if (off + 1 == offset)
+ return NULL;
+ return ((char *) data) + off;
+ }
+ return NULL; // The section is not '\0' terminated
}
uint64_t
@@ -1173,6 +1272,37 @@ DwrSec::GetSLEB128 ()
return (SLEB128) res;
}
+uint64_t
+DwrSec::get_value (int dw_form)
+{
+ uint64_t v;
+ switch (dw_form)
+ {
+ case DW_FORM_line_strp:
+ case DW_FORM_strp:
+ case DW_FORM_strp_sup:
+ return GetRef ();
+ case DW_FORM_data1:
+ return Get_8 ();
+ case DW_FORM_data2:
+ return Get_16 ();
+ case DW_FORM_data4:
+ return Get_32 ();
+ case DW_FORM_data8:
+ return Get_64 ();
+ case DW_FORM_udata:
+ return GetULEB128 ();
+ case DW_FORM_data16:
+ offset += 16;
+ return offset - 16;
+ case DW_FORM_block:
+ v = GetULEB128 ();
+ offset += v;
+ return offset - v;
+ }
+ return 0;
+}
+
static void
fillBuf (unsigned char *s, int len, int col, unsigned char *buf)
{
@@ -1229,7 +1359,7 @@ DwrSec::dump (char *msg)
DwrFileName::DwrFileName (char *_fname)
{
path = NULL;
- fname = _fname;
+ fname = dbe_strdup (_fname);
dir_index = 0;
timestamp = 0;
file_size = 0;
@@ -1267,8 +1397,13 @@ LineRegsCmp (const void *a, const void *b)
item1->address > item2->address ? 1 : -1;
}
-DwrLineRegs::DwrLineRegs (DwrSec *secp, char *dirName)
+DwrLineRegs::DwrLineRegs (Dwarf *_dwarf, DwrSec *secp, char *dirName)
{
+ dwarf = _dwarf;
+ dir_names = NULL;
+ file_names = NULL;
+ lines = NULL;
+ fname = NULL;
// `dwarfdump -vv -l` shows a line section (.debug_line)
debug_lineSec = secp;
uint64_t stmt_offset = debug_lineSec->offset;
@@ -1276,11 +1411,16 @@ DwrLineRegs::DwrLineRegs (DwrSec *secp, char *dirName)
uint64_t header_offset = debug_lineSec->offset;
debug_lineSec->size = next_cu_offset;
version = debug_lineSec->Get_16 ();
+ if (version == 5)
+ {
+ debug_lineSec->address_size = debug_lineSec->Get_8();
+ debug_lineSec->segment_selector_size = debug_lineSec->Get_8();
+ }
header_length = debug_lineSec->GetLong ();
opcode_start = debug_lineSec->offset + header_length;
minimum_instruction_length = debug_lineSec->Get_8 ();
op_index_register = 0;
- if (version == 4)
+ if (version >= 4)
maximum_operations_per_instruction = debug_lineSec->Get_8 ();
else
maximum_operations_per_instruction = 1;
@@ -1295,9 +1435,9 @@ DwrLineRegs::DwrLineRegs (DwrSec *secp, char *dirName)
{
Dprintf (DUMP_DWR_LINE_REGS,
"\n.debug_line version=%d stmt_offset=0x%llx"
- "header_offset=0x%llx size=%lld dirname='%s'\n"
+ " header_offset=0x%llx size=%lld dirname='%s'\n"
" header_length=0x%llx opcode_start=0x%llx"
- "minimum_instruction_length=%d default_is_stmt=%d\n"
+ " minimum_instruction_length=%d default_is_stmt=%d\n"
" line_base=%d line_range=%d opcode_base=%d\n",
(int) version, (long long) stmt_offset,
(long long) header_offset,
@@ -1313,40 +1453,122 @@ DwrLineRegs::DwrLineRegs (DwrSec *secp, char *dirName)
(int) standard_opcode_length[i]);
}
- include_directories = new Vector<char *>;
- include_directories->append (dirName);
- while (true)
+ if (version == 5)
{
- char *s = debug_lineSec->GetString (NULL);
- if (s == NULL)
- break;
- include_directories->append (s);
+ dir_names = read_file_names_dwarf5 ();
+ file_names = read_file_names_dwarf5 ();
}
-
- file_names = new Vector<DwrFileName *>;
- while (true)
+ else
{
- char *s = debug_lineSec->GetString (NULL);
- if (s == NULL)
- break;
- DwrFileName *fnp = new DwrFileName (s);
- fnp->path = NULL;
- fnp->fname = s;
- fnp->dir_index = debug_lineSec->GetULEB128_32 ();
- fnp->timestamp = debug_lineSec->GetULEB128 ();
- fnp->file_size = debug_lineSec->GetULEB128 ();
- file_names->append (fnp);
+ dir_names = new Vector<DwrFileName *>;
+ dir_names->append (new DwrFileName (dirName));
+ while (true)
+ {
+ char *s = debug_lineSec->GetString ();
+ if (s == NULL)
+ break;
+ dir_names->append (new DwrFileName (s));
+ }
+
+ file_names = new Vector<DwrFileName *>;
+ file_names->append (new DwrFileName (dirName));
+ while (true)
+ {
+ char *s = debug_lineSec->GetString ();
+ if (s == NULL)
+ break;
+ DwrFileName *fnp = new DwrFileName (s);
+ fnp->dir_index = debug_lineSec->GetULEB128_32 ();
+ fnp->timestamp = debug_lineSec->GetULEB128 ();
+ fnp->file_size = debug_lineSec->GetULEB128 ();
+ file_names->append (fnp);
+ }
}
- lines = NULL;
dump ();
}
DwrLineRegs::~DwrLineRegs ()
{
+ Destroy (dir_names);
Destroy (file_names);
Destroy (lines);
delete debug_lineSec;
- delete include_directories;
+}
+
+Vector <DwrFileName *> *
+DwrLineRegs::read_file_names_dwarf5 ()
+{
+
+ typedef struct
+ {
+ int type_code;
+ int form_code;
+ } t_entry_fmt;
+
+ int efmt_cnt = debug_lineSec->Get_8 ();
+ Dprintf (DUMP_DWR_LINE_REGS, "\nRead names: offset=0x%llx entry_fmt_cnt=%d\n",
+ (long long) debug_lineSec->offset, efmt_cnt);
+ if (efmt_cnt == 0)
+ return NULL;
+ t_entry_fmt *efmt = (t_entry_fmt *) malloc (sizeof (t_entry_fmt) * efmt_cnt);
+ for (int i = 0; i < efmt_cnt; i++)
+ {
+ efmt[i].type_code = debug_lineSec->GetULEB128 ();
+ efmt[i].form_code = debug_lineSec->GetULEB128 ();
+ Dprintf (DUMP_DWR_LINE_REGS, " %2d %20s %s\n", i,
+ DwrCU::lnct2str (efmt[i].type_code),
+ DwrCU::form2str (efmt[i].form_code));
+ }
+
+ int cnt = debug_lineSec->GetULEB128_32 ();
+ Dprintf (DUMP_DWR_LINE_REGS, "\nRead names: offset=0x%llx names_cnt=%d\n",
+ (long long) debug_lineSec->offset, cnt);
+ Vector<DwrFileName *> *fnames = new Vector<DwrFileName *> (cnt);
+ for (int i = 0; i < cnt; i++)
+ {
+ int ind = 0;
+ uint64_t off = 0;
+ uint64_t tstamp = 0;
+ uint64_t fsize = 0;
+ char *nm = NULL;
+ for (int k = 0; k < efmt_cnt; k++)
+ switch (efmt[k].type_code)
+ {
+ case DW_LNCT_path:
+ if (efmt[k].form_code == DW_FORM_string)
+ nm = debug_lineSec->GetString ();
+ else
+ {
+ off = debug_lineSec->get_value (efmt[k].form_code);
+ if (efmt[k].form_code == DW_FORM_line_strp)
+ nm = get_string (dwarf->debug_line_strSec, off);
+ else if (efmt[k].form_code == DW_FORM_strp)
+ nm = get_string (dwarf->debug_strSec, off);
+ }
+ break;
+ case DW_LNCT_directory_index:
+ ind = debug_lineSec->get_value (efmt[k].form_code);
+ break;
+ case DW_LNCT_timestamp:
+ tstamp = debug_lineSec->get_value (efmt[k].form_code);
+ break;
+ case DW_LNCT_size:
+ fsize = debug_lineSec->get_value (efmt[k].form_code);
+ break;
+ case DW_LNCT_MD5:
+ (void) debug_lineSec->get_value (efmt[k].form_code);
+ break;
+ }
+ Dprintf (DUMP_DWR_LINE_REGS, " %3d ind=%d off=0x%08llx %s\n",
+ i, ind, (long long) off, STR (nm));
+ DwrFileName *fnp = new DwrFileName (nm);
+ fnp->dir_index = ind;
+ fnp->timestamp = tstamp;
+ fnp->file_size = fsize;
+ fnames->append (fnp);
+ }
+ free (efmt);
+ return fnames;
}
void
@@ -1354,12 +1576,10 @@ DwrLineRegs::dump ()
{
if (!DUMP_DWR_LINE_REGS)
return;
- Dprintf (DUMP_DWR_LINE_REGS, NTXT ("\ninclude_directories size=%lld\n"), (long long) VecSize (include_directories));
- for (long i = 0, sz = VecSize (include_directories); i < sz; i++)
- {
- char *s = include_directories->get (i);
- Dprintf (DUMP_DWR_LINE_REGS, NTXT (" %2lld %s\n"), (long long) i, STR (s));
- }
+ if (dir_names)
+ dir_names->dump ("dir_names");
+ if (file_names)
+ file_names->dump ("file_names");
Dprintf (DUMP_DWR_LINE_REGS, NTXT ("\nfile_names size=%lld\n"), (long long) VecSize (file_names));
for (long i = 0, sz = VecSize (file_names); i < sz; i++)
@@ -1396,7 +1616,7 @@ DwrLineRegs::DoExtendedOpcode ()
break;
case DW_LNE_define_file:
// TODO, add file to file list
- fname = debug_lineSec->GetString (NULL);
+ fname = debug_lineSec->GetString ();
dir_index = debug_lineSec->GetULEB128 ();
timestamp = debug_lineSec->GetULEB128 ();
file_size = debug_lineSec->GetULEB128 ();
@@ -1467,7 +1687,7 @@ DwrLineRegs::reset ()
timestamp = 0;
file_size = 0;
address = 0;
- file = 1;
+ file = 0;
line = 1;
column = 0;
is_stmt = (default_is_stmt != 0);
@@ -1535,39 +1755,31 @@ DwrLineRegs::get_lines ()
char *
DwrLineRegs::getPath (int fn)
{
- fn--;
- if ((fn >= VecSize (file_names)) || (fn < 0))
+ if (fn >= VecSize (file_names) || fn < 0)
{
Dprintf (DEBUG_ERR_MSG, NTXT ("DwrLineRegs::getPath: fn=0x%lld file_names->size()=%lld\n"),
(long long) fn, (long long) VecSize (file_names));
return NULL;
}
DwrFileName *fnp = file_names->fetch (fn);
+ if (fnp->fname == NULL)
+ return NULL;
if (fnp->path)
return fnp->path;
- char *dir = fnp->dir_index < include_directories->size () ?
- include_directories->fetch (fnp->dir_index) : NULL;
- if ((fnp->fname[0] == '/') || (dir == NULL) || (*dir == 0))
- {
- fnp->path = fnp->fname;
- return fnp->path;
- }
+ fnp->path = fnp->fname;
+ if (fnp->fname[0] == '/')
+ return fnp->path;
- StringBuilder sb;
- if (*dir != '/')
- { // not absolute
- char *s = include_directories->fetch (0);
- if (s != NULL && *s != 0)
- {
- sb.append (s);
- sb.append ('/');
- }
+ char *dir = NULL;
+ if (dir_names)
+ {
+ if (fnp->dir_index < dir_names->size () && fnp->dir_index >= 0)
+ dir = dir_names->get (fnp->dir_index)->fname;
}
- sb.append (dir);
- sb.append ('/');
- sb.append (fnp->fname);
- fnp->path = canonical_path (sb.toString ());
+ if (dir == NULL || *dir == 0)
+ return fnp->path;
+ fnp->path = canonical_path (dbe_sprintf ("%s/%s", dir, fnp->fname));
return fnp->path;
}
@@ -1586,8 +1798,18 @@ DwrCU::DwrCU (Dwarf *_dwarf)
}
debug_infoSec->size = next_cu_offset;
version = debug_infoSec->Get_16 ();
- debug_abbrev_offset = debug_infoSec->GetLong ();
- address_size = debug_infoSec->Get_8 ();
+ if (version == 5)
+ {
+ unit_type = debug_infoSec->Get_8 ();
+ address_size = debug_infoSec->Get_8 ();
+ debug_abbrev_offset = debug_infoSec->GetLong ();
+ }
+ else
+ {
+ unit_type = DW_UT_compile;
+ debug_abbrev_offset = debug_infoSec->GetLong ();
+ address_size = debug_infoSec->Get_8 ();
+ }
cu_header_offset = debug_infoSec->offset;
comp_dir = NULL;
module = NULL;
@@ -1606,7 +1828,7 @@ DwrCU::DwrCU (Dwarf *_dwarf)
{
Dprintf (DUMP_DWARFLIB,
"CU_HEADER: header_offset = 0x%08llx %lld"
- "next_header_offset=0x%08llx %lld\n"
+ " next_header_offset=0x%08llx %lld\n"
" abbrev_offset = 0x%08llx %lld\n"
" unit_length = %lld\n"
" version = %d\n"
@@ -1685,10 +1907,18 @@ DwrCU::build_abbrevTable (DwrSec *_debug_abbrevSec, uint64_t _offset)
while (debug_abbrevSec->offset < debug_abbrevSec->size)
{
Dwr_Attr atf;
+ atf.len = 0;
+ atf.u.str = NULL;
atf.at_name = debug_abbrevSec->GetULEB128_32 ();
atf.at_form = debug_abbrevSec->GetULEB128_32 ();
if (atf.at_name == 0 && atf.at_form == 0)
break;
+ switch (atf.at_form)
+ {
+ case DW_FORM_implicit_const:
+ atf.len = debug_abbrevSec->GetSLEB128 ();
+ break;
+ }
abbrevAtForm->append (atf);
}
abbTbl.lastAtForm = abbrevAtForm->size ();
@@ -1782,20 +2012,12 @@ DwrCU::set_die (Dwarf_Die die)
atf->u.offset = debug_infoSec->Get_64 ();
break;
case DW_FORM_string:
- atf->u.str = debug_infoSec->GetString (&atf->len);
+ atf->u.offset = debug_infoSec->offset;
+ atf->u.str = debug_infoSec->GetString ();
break;
case DW_FORM_strp:
atf->u.offset = debug_infoSec->GetRef ();
- if (dwarf->debug_strSec == NULL)
- {
- atf->u.str = NULL;
- atf->len = 0;
- }
- else
- {
- dwarf->debug_strSec->offset = atf->u.offset;
- atf->u.str = dwarf->debug_strSec->GetString (&atf->len);
- }
+ atf->u.str = get_string (dwarf->debug_strSec, atf->u.offset);
break;
case DW_FORM_sdata:
atf->u.val = debug_infoSec->GetSLEB128 ();
@@ -1819,6 +2041,49 @@ DwrCU::set_die (Dwarf_Die die)
case DW_FORM_ref_sig8:
atf->u.offset = debug_infoSec->GetADDR_64 ();
break;
+ case DW_FORM_data16: // we never use this data. Skip 16 bytes
+ atf->len = 16;
+ (void) debug_infoSec->Get_64 ();
+ (void) debug_infoSec->Get_64 ();
+ break;
+ case DW_FORM_addrx:
+ case DW_FORM_strx:
+ case DW_FORM_loclistx:
+ case DW_FORM_rnglistx:
+ atf->u.offset = debug_infoSec->GetULEB128 ();
+ break;
+ case DW_FORM_addrx1:
+ case DW_FORM_strx1:
+ atf->u.offset = debug_infoSec->Get_8 ();
+ break;
+ case DW_FORM_addrx2:
+ case DW_FORM_strx2:
+ atf->u.offset = debug_infoSec->Get_16 ();
+ break;
+ case DW_FORM_addrx3:
+ case DW_FORM_strx3:
+ atf->u.offset = debug_infoSec->Get_24 ();
+ break;
+ case DW_FORM_addrx4:
+ case DW_FORM_strx4:
+ case DW_FORM_ref_sup4:
+ atf->u.offset = debug_infoSec->Get_32 ();
+ break;
+ case DW_FORM_ref_sup8:
+ atf->u.offset = debug_infoSec->Get_64 ();
+ break;
+ case DW_FORM_line_strp:
+ atf->u.offset = debug_infoSec->GetRef ();
+ atf->u.str = get_string (dwarf->debug_line_strSec, atf->u.offset);
+ break;
+ case DW_FORM_strp_sup:
+ atf->u.offset = debug_infoSec->GetRef ();
+ atf->u.str = NULL;
+ atf->len = 0;
+ break;
+ case DW_FORM_implicit_const:
+ atf->u.str = NULL;
+ break;
default:
DEBUG_CODE
{
@@ -1974,6 +2239,7 @@ DwrCU::read_data_attr (Dwarf_Half attr, int64_t *retVal)
case DW_FORM_data2:
case DW_FORM_data4:
case DW_FORM_data8:
+ case DW_FORM_data16:
case DW_FORM_udata:
case DW_FORM_sec_offset:
*retVal = dwrAttr->u.val;
@@ -2132,7 +2398,7 @@ DwrLineRegs *
DwrCU::get_dwrLineReg ()
{
if (dwrLineReg == NULL && stmt_list_offset != NO_STMT_LIST)
- dwrLineReg = new DwrLineRegs (new DwrSec (dwarf->debug_lineSec,
+ dwrLineReg = new DwrLineRegs (dwarf, new DwrSec (dwarf->debug_lineSec,
stmt_list_offset), comp_dir);
return dwrLineReg;
}
diff --git a/gprofng/src/DwarfLib.h b/gprofng/src/DwarfLib.h
index d359c75..6baecac 100644
--- a/gprofng/src/DwarfLib.h
+++ b/gprofng/src/DwarfLib.h
@@ -61,8 +61,10 @@ public:
uint64_t ReadLength ();
SLEB128 GetSLEB128 ();
ULEB128 GetULEB128 ();
- char *GetString (uint64_t *lenp);
+ char *GetString ();
char *GetData (uint64_t len);
+ uint32_t Get_24 ();
+ uint64_t get_value (int dw_form);
void dump (char *msg);
inline uint32_t
@@ -84,6 +86,8 @@ public:
bool fmt64;
bool addr32;
bool need_swap_endian;
+ int address_size;
+ int segment_selector_size; // DWARF 5
private:
bool isCopy;
@@ -132,7 +136,7 @@ public:
class DwrLineRegs
{
public:
- DwrLineRegs (DwrSec *_secp, char *dirName);
+ DwrLineRegs (Dwarf *_dwarf, DwrSec *_secp, char *dirName);
~DwrLineRegs ();
char *getPath (int fn);
Vector<DwrLine *> *get_lines ();
@@ -146,7 +150,9 @@ private:
void DoSpecialOpcode (int opcode);
void EmitLine ();
void reset ();
+ Vector <DwrFileName *> *read_file_names_dwarf5 ();
+ Dwarf *dwarf;
char *fname;
uint64_t dir_index;
uint64_t timestamp;
@@ -167,7 +173,7 @@ private:
bool basic_block;
bool end_sequence;
Vector<DwrLine *> *lines;
- Vector<char *> *include_directories;
+ Vector<DwrFileName *> *dir_names;
Dwarf_Small *standard_opcode_length;
DwrSec *debug_lineSec;
uint64_t header_length;
@@ -269,6 +275,7 @@ public:
static char *at2str (int tag);
static char *form2str (int tag);
static char *tag2str (int tag);
+ static char *lnct2str (int ty);
uint64_t cu_header_offset;
uint64_t cu_offset;
@@ -302,6 +309,7 @@ private:
uint64_t stmt_list_offset; // offset in .debug_line section (DW_AT_stmt_list)
char *comp_dir; // compilation directory (DW_AT_comp_dir)
Module *module;
+ int unit_type;
Dwarf_Half version;
Dwarf_Small address_size;
Dwr_Tag dwrTag;
diff --git a/gprofng/src/collctrl.cc b/gprofng/src/collctrl.cc
index 692d3e6..5d68b68 100644
--- a/gprofng/src/collctrl.cc
+++ b/gprofng/src/collctrl.cc
@@ -114,7 +114,6 @@ Coll_Ctrl::Coll_Ctrl (int _interactive, bool _defHWC, bool _kernelHWC)
#elif defined(__aarch64__)
asm volatile("mrs %0, cntfrq_el0" : "=r" (cpu_clk_freq));
- dbe_write (2, GTXT ("CPU clock frequency: %d\n"), cpu_clk_freq);
#else
FILE *procf = fopen ("/proc/cpuinfo", "r");
@@ -1079,15 +1078,16 @@ Coll_Ctrl::set_synctrace (const char *string)
/* the remaining string should be a number >= 0 */
char *endchar = NULL;
int tval = (int) strtol (val, &endchar, 0);
- free (val);
if (*endchar != 0 || tval < 0)
{
+ free (val);
/* invalid setting */
/* restore the comma, if it was zeroed out */
if (comma_p != NULL)
*comma_p = ',';
return dbe_sprintf (GTXT ("Unrecognized synchronization tracing threshold `%s'\n"), string);
}
+ free (val);
synctrace_thresh = tval;
synctrace_enabled = 1;
return NULL;