public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* gprofng SIGSEGV when processing unusual dwarf
@ 2023-02-06 16:37 Gilles DUBOSCQ
  2023-02-06 20:28 ` Ruud van der Pas
  0 siblings, 1 reply; 6+ messages in thread
From: Gilles DUBOSCQ @ 2023-02-06 16:37 UTC (permalink / raw)
  To: binutils

Hi all,

When running gprofng display text on some executables that contain unusual dwarf data I am getting a segfault.
In particular, the input dwarf has some compilation units (DW_TAG_compile_unit) that have neither DW_AT_comp_dir nor DW_AT_stmt_list.

The issue is that when that happens, DwrCU::stmt_list_offset remains 0, as a result, in Dwarf::archive_Dwarf, the `get_dwrLineReg` call will process whatever is at offset 0 in .debug_line.
Then while looking for source files, `DwrLineRegs::getPath` will potentially try to use include_directories->fetch (0) which is NULL (no comp_dir attribute).
This leads to a segfault in StringBuilder::append.

A quick local test show that the issue goes away with the change below.
The change in DwrLineRegs::getPath is not strictly necessary but makes the code more robust if some compilation unit has stmt_list but not comp_dir.

Does it make sense? How could we get a fix for this integrated?
If that helps, I can create a bugzilla issue.

Thanks,
 Gilles

diff --git a/gprofng/src/Dwarf.cc b/gprofng/src/Dwarf.cc
index 1b33ae8f243..b36fc424924 100644
--- a/gprofng/src/Dwarf.cc
+++ b/gprofng/src/Dwarf.cc
@@ -606,6 +606,8 @@ Dwarf::archive_Dwarf (LoadObject *lo)
 	{
 	  mod->hdrOffset = dwrCUs->size ();
 	  DwrLineRegs *lineReg = dwrCU->get_dwrLineReg ();
+          if (lineReg != NULL)
+            {
               dwrCU->srcFiles = new Vector<SourceFile *>(VecSize (lineReg->file_names));
               for (long i = 0, sz = VecSize (lineReg->file_names); i < sz; i++)
                 {
@@ -613,6 +615,7 @@ Dwarf::archive_Dwarf (LoadObject *lo)
                   SourceFile *sf = mod->findSource(fname, true);
                   dwrCU->srcFiles->append(sf);
                 }
+            }
 
 	  Dwarf_cnt ctx;
 	  ctx.module = mod;
@@ -986,9 +989,6 @@ DwrCU::append_Function (Dwarf_cnt *ctx)
       if (lineno > 0)
 	{
 	  func->setLineFirst (lineno);
-	  if (dwrLineReg == NULL)
-	    dwrLineReg = new DwrLineRegs (new DwrSec (dwarf->debug_lineSec,
-						   stmt_list_offset), comp_dir);
 	  int fileno = ((int) Dwarf_data (DW_AT_decl_file)) - 1;
 	  SourceFile *sf = ((fileno >= 0) && (fileno < VecSize (srcFiles))) ? srcFiles->get (fileno)
 		  : module->getMainSrc ();
diff --git a/gprofng/src/DwarfLib.cc b/gprofng/src/DwarfLib.cc
index 4f86a78d1c8..ad2f95be9fa 100644
--- a/gprofng/src/DwarfLib.cc
+++ b/gprofng/src/DwarfLib.cc
@@ -1557,9 +1557,12 @@ DwrLineRegs::getPath (int fn)
   if (*dir != '/')
     { // not absolute
       char *s = include_directories->fetch (0);
+      if (s != NULL && *s != 0)
+        {
           sb.append(s);
           sb.append('/');
         }
+    }
   sb.append (dir);
   sb.append ('/');
   sb.append (fnp->fname);
@@ -1590,7 +1593,7 @@ DwrCU::DwrCU (Dwarf *_dwarf)
   abbrevTable = NULL;
   dwrInlinedSubrs = NULL;
   srcFiles = NULL;
-  stmt_list_offset = 0;
+  stmt_list_offset = NO_STMT_LIST;
   dwrLineReg = NULL;
   isMemop = false;
   isGNU = false;
@@ -1857,7 +1860,7 @@ DwrCU::parse_cu_header (LoadObject *lo)
   char *name = Dwarf_string (DW_AT_name);
   if (name == NULL)
     name = NTXT ("UnnamedUnit");
-  stmt_list_offset = Dwarf_data (DW_AT_stmt_list);
+  read_ref_attr(DW_AT_stmt_list, reinterpret_cast<int64_t *>(&stmt_list_offset));
   comp_dir = dbe_strdup (Dwarf_string (DW_AT_comp_dir));
   char *dir_name = comp_dir ? StrChr (comp_dir, ':') : NULL;
   char *orig_name = Dwarf_string (DW_AT_SUN_original_name);
@@ -2073,6 +2076,8 @@ DwrCU::map_dwarf_lines (Module *mod)
 					Stabs::is_fortran (mod->lang_code));
 	}
     }
+  if (lineReg == NULL)
+      return;
   Vector<DwrLine *> *lines = lineReg->get_lines ();
 
   Include *includes = new Include;
@@ -2083,7 +2088,7 @@ DwrCU::map_dwarf_lines (Module *mod)
   for (long i = 0, sz = VecSize (lines); i < sz; i++)
     {
       DwrLine *dwrLine = lines->get (i);
-      char *filename = dwrLineReg->getPath (dwrLine->file);
+      char *filename = lineReg->getPath (dwrLine->file);
       if (filename == NULL)
 	continue;
       uint64_t pc = dwrLine->address;
@@ -2123,7 +2128,7 @@ DwrCU::map_dwarf_lines (Module *mod)
 DwrLineRegs *
 DwrCU::get_dwrLineReg ()
 {
-  if (dwrLineReg == NULL)
+  if (dwrLineReg == NULL && stmt_list_offset != NO_STMT_LIST)
     dwrLineReg = new DwrLineRegs (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 d359c7583b1..591d7d548c9 100644
--- a/gprofng/src/DwarfLib.h
+++ b/gprofng/src/DwarfLib.h
@@ -254,6 +254,8 @@ public:
   Dwr_type *put_dwr_type (Dwr_Tag *dwrTag);
 };
 
+#define NO_STMT_LIST 0xffffffffffffffffULL
+
 class DwrCU
 {
 public:

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2023-02-08  8:30 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-02-06 16:37 gprofng SIGSEGV when processing unusual dwarf Gilles DUBOSCQ
2023-02-06 20:28 ` Ruud van der Pas
2023-02-07  8:45   ` Gilles DUBOSCQ
2023-02-07  9:39     ` Gilles DUBOSCQ
2023-02-07 22:44       ` Vladimir Mezentsev
2023-02-08  8:30         ` Gilles DUBOSCQ

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).