This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
Re: [RFA/i386newframe] info cfi command
- From: Michal Ludvig <mludvig at suse dot cz>
- To: Mark Kettenis <kettenis at chello dot nl>
- Cc: gdb-patches at sources dot redhat dot com,Andrew Cagney <ac131313 at redhat dot com>, Eli Zaretskii <eliz at elta dot co dot il>
- Date: Fri, 30 May 2003 14:33:30 +0200
- Subject: Re: [RFA/i386newframe] info cfi command
- Organization: SuSE CR, s.r.o.
- References: <3ED60F2A.9060108@suse.cz> <200305291629.h4TGTLe0000304@elgar.kettenis.dyndns.org>
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, ®);
+ 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, ®);
+ snprintf (buf, buf_length, "DW_CFA_restore_extended(r%llu)",
+ reg);
+ break;
+
+ case DW_CFA_undefined:
+ insn_ptr = read_uleb128 (insn_ptr, insn_end, ®);
+ snprintf (buf, buf_length, "DW_CFA_undefined(r%llu)", reg);
+ break;
+
+ case DW_CFA_same_value:
+ insn_ptr = read_uleb128 (insn_ptr, insn_end, ®);
+ snprintf (buf, buf_length, "DW_CFA_same_value(r%llu)", reg);
+ break;
+
+ case DW_CFA_register:
+ insn_ptr = read_uleb128 (insn_ptr, insn_end, ®);
+ 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, ®);
+ 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, ®);
+ 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, ®);
+ 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