From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 3311 invoked by alias); 30 May 2003 12:33:53 -0000 Mailing-List: contact gdb-patches-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sources.redhat.com Received: (qmail 3236 invoked from network); 30 May 2003 12:33:52 -0000 Received: from unknown (HELO kerberos.suse.cz) (195.47.106.10) by sources.redhat.com with SMTP; 30 May 2003 12:33:52 -0000 Received: from chimera.suse.cz (chimera.suse.cz [10.20.0.2]) by kerberos.suse.cz (SuSE SMTP server) with ESMTP id 67B0259E840; Fri, 30 May 2003 14:33:51 +0200 (CEST) Received: from suse.cz (naga.suse.cz [10.20.1.16]) by chimera.suse.cz (Postfix) with ESMTP id C1A31453F; Fri, 30 May 2003 14:33:29 +0200 (CEST) Message-ID: <3ED74F9A.4000309@suse.cz> Date: Fri, 30 May 2003 12:33:00 -0000 From: Michal Ludvig Organization: SuSE CR, s.r.o. User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4b) Gecko/20030507 X-Accept-Language: cs, cz, en MIME-Version: 1.0 To: Mark Kettenis Cc: gdb-patches@sources.redhat.com, Andrew Cagney , Eli Zaretskii Subject: Re: [RFA/i386newframe] info cfi command References: <3ED60F2A.9060108@suse.cz> <200305291629.h4TGTLe0000304@elgar.kettenis.dyndns.org> In-Reply-To: <200305291629.h4TGTLe0000304@elgar.kettenis.dyndns.org> Content-Type: multipart/mixed; boundary="------------050008050908010409080204" X-SW-Source: 2003-05/txt/msg00567.txt.bz2 This is a multi-part message in MIME format. --------------050008050908010409080204 Content-Type: text/plain; charset=us-ascii; format=flowed Content-Transfer-Encoding: 7bit Content-length: 721 Mark Kettenis told me that: > From: Michal Ludvig > 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 --------------050008050908010409080204 Content-Type: text/plain; name="nf-cmd-maintcfi-1.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="nf-cmd-maintcfi-1.diff" Content-length: 11362 2003-05-30 Michal Ludvig * 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_ (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 --------------050008050908010409080204--