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]

Re: [RFA/i386newframe] info cfi command


Mark Kettenis told me that:
From: Michal Ludvig <mludvig@suse.cz>
this patch adds 'info cfi' command which is to be used for examining debug info. For now it only prints the instructions in a hex-form, but I'll make a resolver to nice strings later.


Hmm, I wonder whether that should be a maintenance command instead:
   'maintenance print cfi'
or even
   'maintenance print dwarf cfi'
or something like that.

I named it "maint print dwarf2-cfi" - is that OK?


The attached version already resolves the data to verbose instructions like DW_CFA_nop. Documentation is also there.

Can I commit it?

Michal Ludvig
--
* SuSE CR, s.r.o     * mludvig@suse.cz
* (+420) 296.545.373 * http://www.suse.cz
2003-05-30  Michal Ludvig  <mludvig@suse.cz>

	* maint.c (maintenance_print_dwarf2_cfi): New function.
	(_initialize_maint_cmds): Add command dwarf2-cfi.
	* dwarf-frame.h (dwarf2_cmd_print_cfi): New prototype.
	* dwarf-frame.c (decode_cfa_instruction): New function.
	(print_cfa_program): Ditto.
	(dwarf2_cmd_print_cfi): Ditto.
	* doc/gdb.texinfo: Document "maint print dwarf2-cfi" command.

Index: maint.c
===================================================================
RCS file: /cvs/src/src/gdb/maint.c,v
retrieving revision 1.37.2.1
diff -u -p -r1.37.2.1 maint.c
--- maint.c	18 May 2003 09:44:16 -0000	1.37.2.1
+++ maint.c	30 May 2003 12:23:06 -0000
@@ -35,6 +35,7 @@
 #include "symfile.h"
 #include "objfiles.h"
 #include "value.h"
+#include "dwarf-frame.h"
 
 #include "cli/cli-decode.h"
 
@@ -422,6 +423,18 @@ maintenance_print_architecture (char *ar
     }
 }
 
+void
+maintenance_print_dwarf2_cfi (char *args, int from_tty)
+{
+  CORE_ADDR addr;
+  
+  if (! args)
+    error_no_arg ("address");
+
+  addr = parse_and_eval_address (args);
+  dwarf2_cmd_print_cfi (addr);
+}
+
 /* The "maintenance print" command is defined as a prefix, with
    allow_unknown 0.  Therefore, its own definition is called only for
    "maintenance print" with no args.  */
@@ -808,6 +821,10 @@ If a SOURCE file is specified, dump only
 
   add_cmd ("objfiles", class_maintenance, maintenance_print_objfiles,
 	   "Print dump of current object file definitions.",
+	   &maintenanceprintlist);
+
+  add_cmd ("dwarf2-cfi", class_maintenance, maintenance_print_dwarf2_cfi,
+	   "Find and print CFI for a given function.",
 	   &maintenanceprintlist);
 
   add_cmd ("symtabs", class_maintenance, maintenance_info_symtabs,
Index: dwarf-frame.h
===================================================================
RCS file: /cvs/src/src/gdb/Attic/dwarf-frame.h,v
retrieving revision 1.1.2.2
diff -u -p -r1.1.2.2 dwarf-frame.h
--- dwarf-frame.h	23 May 2003 20:18:32 -0000	1.1.2.2
+++ dwarf-frame.h	30 May 2003 12:27:00 -0000
@@ -40,4 +40,7 @@ const struct frame_base *dwarf2_frame_ba
 
 void dwarf2_frame_build_info (struct objfile *objfile);
 
+/* Find and print CFI for a given addr.  */
+void dwarf2_cmd_print_cfi (CORE_ADDR addr);
+
 #endif /* dwarf-frame.h */
Index: dwarf-frame.c
===================================================================
RCS file: /cvs/src/src/gdb/Attic/dwarf-frame.c,v
retrieving revision 1.1.2.7
diff -u -p -r1.1.2.7 dwarf-frame.c
--- dwarf-frame.c	29 May 2003 15:49:22 -0000	1.1.2.7
+++ dwarf-frame.c	30 May 2003 12:23:06 -0000
@@ -1234,3 +1234,242 @@ dwarf2_build_frame_info (struct objfile 
 	frame_ptr = decode_frame_entry (&unit, frame_ptr, 0);
     }
 }
+
+/* Make strings from CFA instructions.  */
+
+static int
+decode_cfa_instruction (char *buf, unsigned long buf_length,
+			unsigned char *insn_start, unsigned char *insn_end,
+			struct dwarf2_cie *cie)
+{
+  unsigned char *insn_ptr = insn_start;
+  unsigned char insn = *insn_ptr++;
+  int bytes_read;
+  ULONGEST utmp, reg;
+  LONGEST offset;
+  CORE_ADDR pc;
+
+  if ((insn & 0xc0) == DW_CFA_advance_loc)
+    snprintf (buf, buf_length, "DW_CFA_advance_loc(%llu)", 
+		     (insn & 0x3f) * cie->code_alignment_factor);
+  else if ((insn & 0xc0) == DW_CFA_offset)
+    {
+      reg = insn & 0x3f;
+      insn_ptr = read_uleb128 (insn_ptr, insn_end, &utmp);
+      offset = utmp * cie->data_alignment_factor;
+      snprintf (buf, buf_length, "DW_CFA_offset(%lld, r%llu)",
+		offset, reg);
+    }
+  else if ((insn & 0xc0) == DW_CFA_restore)
+    {
+      reg = insn & 0x3f;
+      snprintf (buf, buf_length, "DW_CFA_restore(r%llu)", reg);
+    }
+  else
+    {
+      switch (insn)
+	{
+	case DW_CFA_set_loc:
+	  pc = dwarf2_read_address (insn_ptr, insn_end, &bytes_read);
+	  insn_ptr += bytes_read;
+	  snprintf (buf, buf_length, "DW_CFA_set_loc(0x%llx)", pc);
+	  break;
+
+	case DW_CFA_advance_loc1:
+	  utmp = extract_unsigned_integer (insn_ptr, 1);
+	  pc += utmp * cie->code_alignment_factor;
+	  insn_ptr++;
+	  snprintf (buf, buf_length, "DW_CFA_advance_loc1(0x%llx)", pc);
+	  break;
+	case DW_CFA_advance_loc2:
+	  utmp = extract_unsigned_integer (insn_ptr, 2);
+	  pc += utmp * cie->code_alignment_factor;
+	  insn_ptr += 2;
+	  snprintf (buf, buf_length, "DW_CFA_advance_loc2(0x%llx)", pc);
+	  break;
+	case DW_CFA_advance_loc4:
+	  utmp = extract_unsigned_integer (insn_ptr, 4);
+	  pc += utmp * cie->code_alignment_factor;
+	  insn_ptr += 4;
+	  snprintf (buf, buf_length, "DW_CFA_advance_loc4(0x%llx)", pc);
+	  break;
+
+	case DW_CFA_offset_extended:
+	  insn_ptr = read_uleb128 (insn_ptr, insn_end, &reg);
+	  insn_ptr = read_uleb128 (insn_ptr, insn_end, &utmp);
+	  offset = utmp * cie->data_alignment_factor;
+	  snprintf (buf, buf_length,
+		    "DW_CFA_offset_extended(%lld, r%llu)", offset, reg);
+	  break;
+
+	case DW_CFA_restore_extended:
+	  insn_ptr = read_uleb128 (insn_ptr, insn_end, &reg);
+	  snprintf (buf, buf_length, "DW_CFA_restore_extended(r%llu)",
+		    reg);
+	  break;
+
+	case DW_CFA_undefined:
+	  insn_ptr = read_uleb128 (insn_ptr, insn_end, &reg);
+	  snprintf (buf, buf_length, "DW_CFA_undefined(r%llu)", reg);
+	  break;
+
+	case DW_CFA_same_value:
+	  insn_ptr = read_uleb128 (insn_ptr, insn_end, &reg);
+	  snprintf (buf, buf_length, "DW_CFA_same_value(r%llu)", reg);
+	  break;
+
+	case DW_CFA_register:
+	  insn_ptr = read_uleb128 (insn_ptr, insn_end, &reg);
+	  insn_ptr = read_uleb128 (insn_ptr, insn_end, &utmp);
+	  snprintf (buf, buf_length, "DW_CFA_register(r%llu, r%llu)",
+		    reg, utmp);
+	  break;
+
+	case DW_CFA_remember_state:
+	  snprintf (buf, buf_length, "DW_CFA_remember_state");
+	  break;
+
+	case DW_CFA_restore_state:
+	  snprintf (buf, buf_length, "DW_CFA_restore_state");
+	  break;
+
+	case DW_CFA_def_cfa:
+	  insn_ptr = read_uleb128 (insn_ptr, insn_end, &reg);
+	  insn_ptr = read_uleb128 (insn_ptr, insn_end, &utmp);
+	  snprintf (buf, buf_length, "DW_CFA_def_cfa(r%llu, %lld)",
+		    reg, utmp);
+	  break;
+
+	case DW_CFA_def_cfa_register:
+	  insn_ptr = read_uleb128 (insn_ptr, insn_end, &reg);
+	  snprintf (buf, buf_length, "DW_CFA_def_cfa_register(r%llu)",
+		    reg);
+	  break;
+
+	case DW_CFA_def_cfa_offset:
+	  insn_ptr = read_uleb128 (insn_ptr, insn_end, &utmp);
+	  snprintf (buf, buf_length, "DW_CFA_def_cfa_offset(%lld)",
+		    utmp);
+	  break;
+
+	case DW_CFA_def_cfa_expression:
+	  insn_ptr = read_uleb128 (insn_ptr, insn_end, &utmp);
+	  insn_ptr += utmp;
+	  snprintf (buf, buf_length, "DW_CFA_def_cfa_expression(%llu)",
+		    utmp);
+	  break;
+
+	case DW_CFA_expression:
+	  insn_ptr = read_uleb128 (insn_ptr, insn_end, &reg);
+	  insn_ptr = read_uleb128 (insn_ptr, insn_end, &utmp);
+	  insn_ptr += utmp;
+	  snprintf (buf, buf_length, "DW_CFA_expression(r%llu, %lld)",
+		    reg, utmp);
+	  break;
+
+	case DW_CFA_nop:
+	  snprintf (buf, buf_length, "DW_CFA_nop");
+	  break;
+
+	case DW_CFA_GNU_args_size:
+	  insn_ptr = read_uleb128 (insn_ptr, insn_end, &utmp);
+	  snprintf (buf, buf_length, "DW_CFA_GNU_args_size(%llu)",
+		    utmp);
+	  break;
+
+	default:
+	  snprintf (buf, buf_length, "DW_CFA_<unknown> (0x%x)", insn);
+	}
+    }
+
+  return insn_ptr - insn_start;
+}
+
+static void
+print_cfa_program (unsigned char *insn_start, unsigned char *insn_end,
+		   struct dwarf2_cie *cie)
+{
+  char string[100];
+  int bytes_used;
+  
+  while (insn_start < insn_end)
+    {
+      bytes_used = decode_cfa_instruction (string, sizeof (string),
+					    insn_start, insn_end,
+					    cie);
+      insn_start += bytes_used;
+      printf_filtered ("\t%s\n", string);
+    }
+}
+
+/* Interactive interface.  */
+
+void
+dwarf2_cmd_print_cfi (CORE_ADDR addr)
+{
+  CORE_ADDR low, high;
+  unsigned long data_length;
+  struct dwarf2_fde *fde;
+  char *name;
+  int i;
+
+  printf_filtered ("Searching CFI for address 0x%llx...\n", addr);
+  
+  if (find_pc_partial_function (addr, &name, &low, &high))
+    printf_filtered ("Belongs to function '%s' (0x%llx..0x%llx).\n",
+		     name, low, high);
+  
+  fde = dwarf2_frame_find_fde (&addr);
+  if (! fde)
+  {
+    printf_filtered ("CFI entry not found.\n");
+    return;
+  }
+
+  /* Print out CIE.  */
+  data_length = fde->cie->end - fde->cie->initial_instructions;
+  printf_filtered ("CIE:\n");
+  printf_filtered ("\toffset = %llx\n"
+		   "\tcode_align = %llu, data_align = %lld, ra_column = 0x%llx\n"
+		   "\tdata_length = %lu\n\t",
+		   fde->cie->cie_pointer,
+		   fde->cie->code_alignment_factor, 
+		   fde->cie->data_alignment_factor,
+		   fde->cie->return_address_register,
+		   data_length);
+  
+  printf_filtered ("raw data:\n\t\t");
+  for (i = 0; i < data_length; i++)
+  {
+    printf_filtered ("0x%02x ", fde->cie->initial_instructions[i] & 0xff);
+    if ((i + 1) % 8 == 0)
+      printf_filtered ("\n\t\t");
+    else if ((i + 1) % 4 == 0)
+      printf_filtered ("  ");
+  }
+  if (i % 8)
+    printf_filtered ("\n");
+  print_cfa_program (fde->cie->initial_instructions, fde->cie->end, fde->cie);
+  
+  /* Print out FDE.  */
+  data_length = fde->end - fde->instructions;
+  printf_filtered ("FDE:\n");
+  printf_filtered ("\tlocation = 0x%llx..0x%llx (size = %lld)\n"
+		   "\tdata_length = %lu\n\t",
+		   fde->initial_location,
+		   (fde->initial_location + fde->address_range),
+		   fde->address_range, data_length);
+
+  printf_filtered ("raw data:\n\t\t");
+  for (i = 0; i < data_length; i++)
+  {
+    printf_filtered ("0x%02x ", fde->instructions[i] & 0xff);
+    if ((i + 1) % 8 == 0)
+      printf_filtered ("\n%s", i + 1 < data_length ? "\t\t" : "");
+    else if ((i + 1) % 4 == 0)
+      printf_filtered ("  ");
+  }
+  if (i % 8)
+    printf_filtered ("\n");
+  print_cfa_program (fde->instructions, fde->end, fde->cie);
+}
Index: doc/gdb.texinfo
===================================================================
RCS file: /cvs/src/src/gdb/doc/gdb.texinfo,v
retrieving revision 1.156.2.2
diff -u -p -r1.156.2.2 gdb.texinfo
--- doc/gdb.texinfo	18 May 2003 09:44:31 -0000	1.156.2.2
+++ doc/gdb.texinfo	30 May 2003 12:23:08 -0000
@@ -19386,6 +19386,46 @@ The program being debugged stopped while
 
 Takes an optional file parameter.
 
+@kindex maint print dwarf2-cfi
+@item maint print dwarf2-cfi
+
+Print Call Frame Information (CFI) found by @value{GDBN} 
+for a given address.
+
+@smallexample
+(gdb) @kbd{maintenance print dwarf2-cfi main}
+Searching CFI for address 0x40038b38...
+Belongs to function 'main' (0x40038b38..0x40038b82).
+CIE:
+        offset = 18
+        code_align = 1, data_align = -8, ra_column = 0x10
+        data_length = 11
+        raw data:
+                0x0c 0x07 0x08 0x90   0x01 0x00 0x00 0x00 
+                0x00 0x00 0x00 
+        DW_CFA_def_cfa(r7, 8)
+        DW_CFA_offset(-8, r16)
+        DW_CFA_nop
+        DW_CFA_nop
+        DW_CFA_nop
+        DW_CFA_nop
+        DW_CFA_nop
+        DW_CFA_nop
+FDE:
+        location = 0x40038b38..0x40038b82 (size = 74)
+        data_length = 8
+        raw data:
+                0x41 0x0e 0x10 0x86   0x02 0x43 0x0d 0x06 
+        DW_CFA_advance_loc(1)
+        DW_CFA_def_cfa_offset(16)
+        DW_CFA_offset(-16, r6)
+        DW_CFA_advance_loc(3)
+        DW_CFA_def_cfa_register(r6)
+(gdb)
+@end smallexample
+
+Takes an address or a function name as an argument.
+
 @kindex maint print registers
 @kindex maint print raw-registers
 @kindex maint print cooked-registers

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