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] maint info dwarf2-cfi


Hi,
once again a patch that adds 'maint info dwarf2-cfi' command.
I modified it for the mainline and incorporated all the requests that appeared on the list last time I sent it, i.e.
- the command is 'maint info dwarf2-cfi', not 'maint print dwarf2-cfi'
- the exported function starts with dwarf2_frame_
- self-desctiption is more verbose


OK to commit now?

Michal Ludvig
2003-06-05  Michal Ludvig  <mludvig@suse.cz>

	* dwarf2-frame.h (dwarf2_frame_cmd_info_cfi): New prototype.
	* dwarf2-frame.c (decode_cfa_instruction): New function.
	(print_cfa_program): Ditto.
	(dwarf2_frame_cmd_info_cfi): Ditto.
	* maint.c (maintenance_info_dwarf2_cfi): New function.
	(_initialize_maint_cmds): Add command info dwarf2-cfi.
	* doc/gdb.texinfo: Document "maint info dwarf2-cfi" command.

Index: dwarf2-frame.c
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2-frame.c,v
retrieving revision 1.5
diff -u -p -r1.5 dwarf2-frame.c
--- dwarf2-frame.c	4 Jun 2003 21:03:23 -0000	1.5
+++ dwarf2-frame.c	5 Jun 2003 12:06:45 -0000
@@ -1302,3 +1302,244 @@ 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_frame_cmd_info_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: dwarf2-frame.h
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2-frame.h,v
retrieving revision 1.1
diff -u -p -r1.1 dwarf2-frame.h
--- dwarf2-frame.h	31 May 2003 19:18:05 -0000	1.1
+++ dwarf2-frame.h	5 Jun 2003 12:06:45 -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_frame_cmd_info_cfi (CORE_ADDR addr);
+
 #endif /* dwarf2-frame.h */
Index: maint.c
===================================================================
RCS file: /cvs/src/src/gdb/maint.c,v
retrieving revision 1.38
diff -u -p -r1.38 maint.c
--- maint.c	7 May 2003 21:42:47 -0000	1.38
+++ maint.c	5 Jun 2003 12:06:45 -0000
@@ -35,6 +35,7 @@
 #include "symfile.h"
 #include "objfiles.h"
 #include "value.h"
+#include "dwarf2-frame.h"
 
 #include "cli/cli-decode.h"
 
@@ -399,6 +400,18 @@ maintenance_info_sections (char *arg, in
     }
 }
 
+void
+maintenance_info_dwarf2_cfi (char *args, int from_tty)
+{
+  CORE_ADDR addr;
+  
+  if (! args)
+    error_no_arg ("address");
+
+  addr = parse_and_eval_address (args);
+  dwarf2_frame_cmd_info_cfi (addr);
+}
+
 /* ARGSUSED */
 void
 maintenance_print_statistics (char *args, int from_tty)
@@ -809,6 +822,13 @@ 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_info_dwarf2_cfi,
+	   "Find and print CFI for a given function.\n"
+	   "CFI stands for Call Frame Information which is a format\n"
+	   "of encoding information that could be used for doing\n"
+	   "a stack backtrace.\n",
+	   &maintenanceinfolist);
 
   add_cmd ("symtabs", class_maintenance, maintenance_info_symtabs,
 	   "List the full symbol tables for all object files.\n\
Index: doc/gdb.texinfo
===================================================================
RCS file: /cvs/src/src/gdb/doc/gdb.texinfo,v
retrieving revision 1.162
diff -u -p -r1.162 gdb.texinfo
--- doc/gdb.texinfo	8 May 2003 21:33:49 -0000	1.162
+++ doc/gdb.texinfo	5 Jun 2003 12:06:53 -0000
@@ -19386,6 +19386,46 @@ The program being debugged stopped while
 
 Takes an optional file parameter.
 
+@kindex maint info dwarf2-cfi
+@item maint info dwarf2-cfi
+
+Print Call Frame Information (CFI) found by @value{GDBN} 
+for a given address.
+
+@smallexample
+(gdb) @kbd{maintenance info 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]