This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFA] Dwarf2CFI fix


Hi all,
my code in dwarf2cfi.c assumed that CIE and FDE entries in .eh_frame are always in the chain CIE, FDE, FDE, ..., CIE, FDE, ...
where every FDE refers to the precedent CIE. Unfortunately this is not alway the case. Linker (?) sometimes optimizes things in a way that the assumption isn't true anymore. This patch addresses the problem.


OK to commit? Head and 5.3?

Michal Ludvig
--
* SuSE CR, s.r.o     * mludvig at suse dot cz
* (+420) 296.545.373 * http://www.suse.cz
2003-02-26  Michal Ludvig  <mludvig at suse dot cz>

	* dwarf2cfi.c (parse_frame_info): It's not true that FDEs 
	always refer to the last CIE. We must deal with such a
	situation.
	* dwarf2cfi.h (

diff -upr gdb-upto-08/dwarf2cfi.c gdb/dwarf2cfi.c
--- gdb-upto-08/dwarf2cfi.c	2003-02-26 10:20:02.000000000 +0100
+++ gdb/dwarf2cfi.c	2003-02-26 17:17:30.000000000 +0100
@@ -50,6 +50,10 @@ struct cie_unit
   char *data;
   unsigned int data_length;
 
+  /* This field is 1 for CIE from .eh_frame
+     and 0 for one from .debug_frame. */
+  int eh_frame;
+
   struct objfile *objfile;
 
   /* Next in chain.  */
@@ -1502,6 +1502,7 @@ parse_frame_info (struct objfile *objfil
 	      char *aug;
 
 	      cie->objfile = objfile;
+	      cie->eh_frame = (eh_frame > 0);
 	      cie->next = cie_chunks;
 	      cie_chunks = cie;
 
@@ -1586,26 +1587,31 @@ parse_frame_info (struct objfile *objfil
 
 	      /* We assume that debug_frame is in order 
 	         CIE,FDE,CIE,FDE,FDE,...  and thus the CIE for this FDE
-	         should be stored in last_cie pointer. If not, we'll 
-	         try to find it by the older way.  */
-	      if (last_cie)
+	         should be stored in last_cie pointer. 
+		 However this assumption is not always true, because
+		 the linker does some magic and adds ghost CIEs under
+		 some circumstances. Thus we need to do some safety
+		 checks.  If last_cie isn't valid, we'll try to find
+		 the correct one using the older way.  */
+	      if (last_cie && last_cie->objfile == objfile &&
+		  last_cie->eh_frame == (eh_frame > 0) &&
+		  ((eh_frame &&
+		    last_cie->offset == (unit_offset + bytes_read - cie_id)) ||
+		   (!eh_frame && (cie->offset == cie_id))))
 		cie = last_cie;
 	      else
 		{
-		  warning ("CFI: last_cie == NULL. "
-			   "Perhaps a malformed %s section in '%s'...?\n",
-			   curr_section_name, objfile->name);
-
 		  cie = cie_chunks;
 		  while (cie)
 		    {
 		      if (cie->objfile == objfile)
 			{
-			  if (eh_frame &&
-			      (cie->offset ==
-			       (unit_offset + bytes_read - cie_id)))
+			  if (eh_frame && cie->eh_frame &&
+			      cie->offset ==
+			       (unit_offset + bytes_read - cie_id))
 			    break;
-			  if (!eh_frame && (cie->offset == cie_id))
+			  if (!eh_frame && !cie->eh_frame && 
+			      cie->offset == cie_id)
 			    break;
 			}
 
@@ -1614,6 +1620,7 @@ parse_frame_info (struct objfile *objfil
 		  if (!cie)
 		    error ("CFI: can't find CIE pointer [in module %s]", 
 				    bfd_get_filename (abfd));
+		  last_cie = cie;
 		}
 
 	      init_loc = read_encoded_pointer (abfd, &start,

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]