public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* Resetting section vma after _bfd_dwarf2_find_nearest_line
@ 2023-02-06  9:36 Alan Modra
  2023-02-08  0:59 ` Alan Modra
  0 siblings, 1 reply; 2+ messages in thread
From: Alan Modra @ 2023-02-06  9:36 UTC (permalink / raw)
  To: binutils

There are failure paths in _bfd_dwarf2_slurp_debug_info that can
result in altered section vmas.  Also, when setting ET_REL section
vmas it's not too difficult to handle cases where the original vma was
non-zero, so do that too.

This patch was really in response to an addr2line buffer overflow
processing a fuzzed mips relocatable object file.  The file had a
number of .debug_info sections with relocations that included lo16 and
hi16 relocs, and in that order.  At least one section VMA was
non-zero.  This resulted in processing of DWARF info twice, once via
the call to _bfd_dwarf2_find_nearest_line in
_bfd_mips_elf_find_nearest_line, and because that failed leaving VMAs
altered, the second via the call in _bfd_elf_find_nearest_line.  The
first call left entries on mips_hi16_list pointing at buffers
allocated during the first call, the second call processed the
mips_hi16_list after the buffers had been freed.  (At least when
running with asan and under valgrind.  Under gdb with a non-asan
addr2line the second call allocated exactly the same buffer and the
bug didn't show.)  Now I don't really care too much what happens with
fuzzed files, but the logic in _bfd_dwarf2_find_nearest_line is meant
to result in only one read of .debug_info, not multiple reads of the
same info when there are errors.  This patch fixes that problem.

	* dwarf2.c (struct adjusted_section): Add orig_vma.
	(unset_sections): Reset vma to it.
	(place_sections): Handle non-zero vma too.  Save orig_vma.
	(_bfd_dwarf2_slurp_debug_info): Tidy.  Correct outdated comment.
	On error returns after calling place_sections, call
	unset_sections.
	(_bfd_dwarf2_find_nearest_line_with_alt): Simplify call to
	unset_sections.

diff --git a/bfd/dwarf2.c b/bfd/dwarf2.c
index 835851e6afc..ab5a9f37ec1 100644
--- a/bfd/dwarf2.c
+++ b/bfd/dwarf2.c
@@ -82,6 +82,7 @@ struct adjusted_section
 {
   asection *section;
   bfd_vma adj_vma;
+  bfd_vma orig_vma;
 };
 
 /* A trie to map quickly from address range to compilation unit.
@@ -4952,7 +4953,7 @@ unset_sections (struct dwarf2_debug *stash)
   i = stash->adjusted_section_count;
   p = stash->adjusted_sections;
   for (; i > 0; i--, p++)
-    p->section->vma = 0;
+    p->section->vma = p->orig_vma;
 }
 
 /* Set VMAs for allocated and .debug_info sections in ORIG_BFD, a
@@ -4993,10 +4994,9 @@ place_sections (bfd *orig_bfd, struct dwarf2_debug *stash)
 	{
 	  int is_debug_info;
 
-	  if ((sect->output_section != NULL
-	       && sect->output_section != sect
-	       && (sect->flags & SEC_DEBUGGING) == 0)
-	      || sect->vma != 0)
+	  if (sect->output_section != NULL
+	      && sect->output_section != sect
+	      && (sect->flags & SEC_DEBUGGING) == 0)
 	    continue;
 
 	  is_debug_info = (strcmp (sect->name, debug_info_name) == 0
@@ -5037,10 +5037,9 @@ place_sections (bfd *orig_bfd, struct dwarf2_debug *stash)
 	      bfd_size_type sz;
 	      int is_debug_info;
 
-	      if ((sect->output_section != NULL
-		   && sect->output_section != sect
-		   && (sect->flags & SEC_DEBUGGING) == 0)
-		  || sect->vma != 0)
+	      if (sect->output_section != NULL
+		  && sect->output_section != sect
+		  && (sect->flags & SEC_DEBUGGING) == 0)
 		continue;
 
 	      is_debug_info = (strcmp (sect->name, debug_info_name) == 0
@@ -5052,24 +5051,17 @@ place_sections (bfd *orig_bfd, struct dwarf2_debug *stash)
 
 	      sz = sect->rawsize ? sect->rawsize : sect->size;
 
-	      if (is_debug_info)
-		{
-		  BFD_ASSERT (sect->alignment_power == 0);
-		  sect->vma = last_dwarf;
-		  last_dwarf += sz;
-		}
-	      else
-		{
-		  /* Align the new address to the current section
-		     alignment.  */
-		  last_vma = ((last_vma
-			       + ~(-((bfd_vma) 1 << sect->alignment_power)))
-			      & (-((bfd_vma) 1 << sect->alignment_power)));
-		  sect->vma = last_vma;
-		  last_vma += sz;
-		}
-
 	      p->section = sect;
+	      p->orig_vma = sect->vma;
+
+	      bfd_vma *v = is_debug_info ? &last_dwarf : &last_vma;
+	      /* Align the new address to the current section
+		 alignment.  */
+	      bfd_vma mask = -(bfd_vma) 1 << sect->alignment_power;
+	      *v = (*v + ~mask) & mask;
+	      sect->vma = *v;
+	      *v += sz;
+
 	      p->adj_vma = sect->vma;
 	      p++;
 	    }
@@ -5379,7 +5371,6 @@ _bfd_dwarf2_slurp_debug_info (bfd *abfd, bfd *debug_bfd,
 			      void **pinfo,
 			      bool do_place)
 {
-  size_t amt = sizeof (struct dwarf2_debug);
   bfd_size_type total_size;
   asection *msec;
   struct dwarf2_debug *stash = (struct dwarf2_debug *) *pinfo;
@@ -5401,11 +5392,11 @@ _bfd_dwarf2_slurp_debug_info (bfd *abfd, bfd *debug_bfd,
 	  return false;
 	}
       _bfd_dwarf2_cleanup_debug_info (abfd, pinfo);
-      memset (stash, 0, amt);
+      memset (stash, 0, sizeof (*stash));
     }
   else
     {
-      stash = (struct dwarf2_debug *) bfd_zalloc (abfd, amt);
+      stash = (struct dwarf2_debug *) bfd_zalloc (abfd, sizeof (*stash));
       if (! stash)
 	return false;
       *pinfo = stash;
@@ -5482,14 +5473,11 @@ _bfd_dwarf2_slurp_debug_info (bfd *abfd, bfd *debug_bfd,
 
   /* There can be more than one DWARF2 info section in a BFD these
      days.  First handle the easy case when there's only one.  If
-     there's more than one, try case two: none of the sections is
-     compressed.  In that case, read them all in and produce one
-     large stash.  We do this in two passes - in the first pass we
+     there's more than one, try case two: read them all in and produce
+     one large stash.  We do this in two passes - in the first pass we
      just accumulate the section sizes, and in the second pass we
      read in the section's contents.  (The allows us to avoid
-     reallocing the data as we add sections to the stash.)  If
-     some or all sections are compressed, then do things the slow
-     way, with a bunch of reallocs.  */
+     reallocing the data as we add sections to the stash.)  */
 
   if (! find_debug_info (debug_bfd, debug_sections, msec))
     {
@@ -5498,7 +5486,7 @@ _bfd_dwarf2_slurp_debug_info (bfd *abfd, bfd *debug_bfd,
       if (! read_section (debug_bfd, &stash->debug_sections[debug_info],
 			  symbols, 0,
 			  &stash->f.dwarf_info_buffer, &total_size))
-	return false;
+	goto restore_vma;
     }
   else
     {
@@ -5508,19 +5496,19 @@ _bfd_dwarf2_slurp_debug_info (bfd *abfd, bfd *debug_bfd,
 	   msec = find_debug_info (debug_bfd, debug_sections, msec))
 	{
 	  if (_bfd_section_size_insane (debug_bfd, msec))
-	    return false;
+	    goto restore_vma;
 	  /* Catch PR25070 testcase overflowing size calculation here.  */
 	  if (total_size + msec->size < total_size)
 	    {
 	      bfd_set_error (bfd_error_no_memory);
-	      return false;
+	      goto restore_vma;
 	    }
 	  total_size += msec->size;
 	}
 
       stash->f.dwarf_info_buffer = (bfd_byte *) bfd_malloc (total_size);
       if (stash->f.dwarf_info_buffer == NULL)
-	return false;
+	goto restore_vma;
 
       total_size = 0;
       for (msec = find_debug_info (debug_bfd, debug_sections, NULL);
@@ -5536,7 +5524,7 @@ _bfd_dwarf2_slurp_debug_info (bfd *abfd, bfd *debug_bfd,
 	  if (!(bfd_simple_get_relocated_section_contents
 		(debug_bfd, msec, stash->f.dwarf_info_buffer + total_size,
 		 symbols)))
-	    return false;
+	    goto restore_vma;
 
 	  total_size += size;
 	}
@@ -5545,6 +5533,10 @@ _bfd_dwarf2_slurp_debug_info (bfd *abfd, bfd *debug_bfd,
   stash->f.info_ptr = stash->f.dwarf_info_buffer;
   stash->f.dwarf_info_size = total_size;
   return true;
+
+ restore_vma:
+  unset_sections (stash);
+  return false;
 }
 
 /* Parse the next DWARF2 compilation unit at FILE->INFO_PTR.  */
@@ -6038,8 +6030,7 @@ _bfd_dwarf2_find_nearest_line_with_alt
 	}
     }
 
-  if ((abfd->flags & (EXEC_P | DYNAMIC)) == 0)
-    unset_sections (stash);
+  unset_sections (stash);
 
   return found;
 }

-- 
Alan Modra
Australia Development Lab, IBM

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

* Re: Resetting section vma after _bfd_dwarf2_find_nearest_line
  2023-02-06  9:36 Resetting section vma after _bfd_dwarf2_find_nearest_line Alan Modra
@ 2023-02-08  0:59 ` Alan Modra
  0 siblings, 0 replies; 2+ messages in thread
From: Alan Modra @ 2023-02-08  0:59 UTC (permalink / raw)
  To: binutils

f.bfd_ptr is set too early to be a reliable indicator of good debug
info.

	* dwarf2.c (_bfd_dwarf2_slurp_debug_info): Correct test for
	debug info being previously found.

diff --git a/bfd/dwarf2.c b/bfd/dwarf2.c
index ab5a9f37ec1..b16ae11e5f2 100644
--- a/bfd/dwarf2.c
+++ b/bfd/dwarf2.c
@@ -5382,7 +5382,7 @@ _bfd_dwarf2_slurp_debug_info (bfd *abfd, bfd *debug_bfd,
 	{
 	  /* Check that we did previously find some debug information
 	     before attempting to make use of it.  */
-	  if (stash->f.bfd_ptr != NULL)
+	  if (stash->f.dwarf_info_size != 0)
 	    {
 	      if (do_place && !place_sections (abfd, stash))
 		return false;

-- 
Alan Modra
Australia Development Lab, IBM

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

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

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-02-06  9:36 Resetting section vma after _bfd_dwarf2_find_nearest_line Alan Modra
2023-02-08  0:59 ` Alan Modra

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