gprofng: read Dwarf 5
authorVladimir Mezentsev <vladimir.mezentsev@oracle.com>
Mon, 6 Mar 2023 01:35:53 +0000 (17:35 -0800)
committerVladimir Mezentsev <vladimir.mezentsev@oracle.com>
Tue, 7 Mar 2023 17:56:19 +0000 (09:56 -0800)
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.

gprofng/src/Dwarf.cc
gprofng/src/Dwarf.h
gprofng/src/DwarfLib.cc
gprofng/src/DwarfLib.h
gprofng/src/collctrl.cc

index fb430cdb079e46a0d7b87178153ed7f5853b2b02..c98210284dca511337761306d43defd76ed7e9a7 100644 (file)
@@ -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);
index 1d99d78745dd56ee901e37b1268c405314345976..0d7756397c4b4eff6890b3974cba95a4b919faa7 100644 (file)
@@ -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;
index e7130a7a438482024ea1a0ed52108334ac7f79d6..e90c685ebbb3604b3d88a6cfa318b593d22bab07 100644 (file)
@@ -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;
@@ -1041,6 +1137,19 @@ DwrSec::Get_16 ()
   return n;
 }
 
+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 ()
 {
@@ -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;
 }
index d359c7583b198b9833dc7f737a35ff4f96697c7f..6baecac3a1b786cada0c56054c9ec966b14601eb 100644 (file)
@@ -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;
index 692d3e67528af3d1196c845be8f9d80aafef883f..5d68b689a642d82ae78a77695466b9591967997c 100644 (file)
@@ -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;