* [RFA] Artifical dwarf2 debug info
@ 2002-12-14 17:31 Michal Ludvig
2002-12-14 22:53 ` Eli Zaretskii
` (2 more replies)
0 siblings, 3 replies; 33+ messages in thread
From: Michal Ludvig @ 2002-12-14 17:31 UTC (permalink / raw)
To: GDB Patches
[-- Attachment #1: Type: text/plain, Size: 1651 bytes --]
Hi all,
this long patch provides a fix for a very annoying fact, that GDB on
x86-64 can't do backtraces from hand-optimized assembler functions (that
applies for example to glibc's memset, str*, etc as well as to syscall
wrappers).
This is caused by the lack of a valid debug_frame/eh_frame FDE entry for
such a function (noone really writes .debug_frame section in his
assembler code :-)
My approach to fix this behaviour is based on the fortunate fact, that
most of those affected glibc's functions don't touch the stack at all,
so creating an artifical FDE for them is easy.
Since this debug info is hardware dependent, I introduce a new gdbarch
item: dwarf2_create_fde. Any architecture using Dwarf2 CFI that will
like to profit from it must have it's own <whtever>_dwarf2_create_fde()
function, very similar to the one I did for x86-64.
In x86_64_dwarf2_create_fde() I handle two cases: functions that have a
prologue and those that don't (the most usual case). Soon I'll try to
create FDE for signal handler caller there as well.
Advantages of this approach are simplicity and cleanliness. There is no
need to "manually" fill in values in CFI's context structure - just
provide a valid, simple FDE and everything else will be done
automagically. This new FDE is of course joined to all other FDEs read
from the file before and is automatically used when needed again.
The patch is transparent to architectures that are not prepared to have
advantage of it and shouldn't hurt anything.
OK to commit to branch and mainline?
Michal Ludvig
--
* SuSE CR, s.r.o * mludvig@suse.cz
* (+420) 296.545.373 * http://www.suse.cz
[-- Attachment #2: bthack-2.diff --]
[-- Type: text/plain, Size: 19395 bytes --]
2002-12-15 Michal Ludvig <mludvig@suse.cz>
* x86-64-tdep.c (x86_64_function_has_prologue): New function,
cut off from x86_64_skip_prologue().
(x86_64_skip_prologue): Call x86_64_function_has_prologue().
(x86_64_dwarf2_create_fde): Brand new function.
(x86_64_gdbarch_init): Call set_gdbarch_dwarf2_create_fde().
* dwarf2cfi.c (struct cie_unit, struct fde_unit)
(struct fde_array): Moved to dwarf2cfi.h
(cie_chunks, fde_chunks): Made extern.
(fde_unit_alloc, cie_unit_alloc, fde_chunks_need_space)
(compare_fde_unit): Made extern.
(guess_generic_fde): New function.
(frame_state_for): Call guess_generic_fde if FDE wasn't
found.
(parse_frame_info): Remove duplicate line.
* dwarf2cfi.h (struct cie_unit, struct fde_unit)
(struct fde_array, cie_chunks, fde_chunks)
(fde_unit_alloc, cie_unit_alloc, fde_chunks_need_space)
(compare_fde_unit): New, moved from dwarf2cfi.c
* gdbarch.h (gdbarch_dwarf2_create_fde_ftype): New type.
(gdbarch_dwarf2_create_fde_p, gdbarch_dwarf2_create_fde)
(set_gdbarch_dwarf2_create_fde): New prototypes.
* gdbarch.h (struct gdbarch): Added dwarf2_create_fde.
(startup_gdbarch): Initialization for dwarf2_create_fde.
(gdbarch_dwarf2_create_fde_p, gdbarch_dwarf2_create_fde)
(set_gdbarch_dwarf2_create_fde): New functions.
Index: x86-64-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/x86-64-tdep.c,v
retrieving revision 1.26
diff -u -p -r1.26 x86-64-tdep.c
--- x86-64-tdep.c 24 Aug 2002 00:21:35 -0000 1.26
+++ x86-64-tdep.c 14 Dec 2002 23:51:12 -0000
@@ -850,11 +850,31 @@ x86_64_frameless_function_invocation (st
return 0;
}
+/* We will handle only functions beginning with:
+ 55 pushq %rbp
+ 48 89 e5 movq %rsp,%rbp */
+#define PROLOG_BUFSIZE 4
+static int
+x86_64_function_has_prologue (CORE_ADDR pc)
+{
+ int i;
+ unsigned char prolog_expect[PROLOG_BUFSIZE] = { 0x55, 0x48, 0x89, 0xe5 },
+ prolog_buf[PROLOG_BUFSIZE];
+
+ read_memory (pc, (char *) prolog_buf, PROLOG_BUFSIZE);
+
+ /* First check, whether pc points to pushq %rbp, movq %rsp,%rbp. */
+ for (i = 0; i < PROLOG_BUFSIZE; i++)
+ if (prolog_expect[i] != prolog_buf[i])
+ return 0; /* ... no, it doesn't. Nothing to skip. */
+
+ return 1;
+}
+
/* If a function with debugging information and known beginning
is detected, we will return pc of the next line in the source
code. With this approach we effectively skip the prolog. */
-#define PROLOG_BUFSIZE 4
CORE_ADDR
x86_64_skip_prologue (CORE_ADDR pc)
{
@@ -863,19 +883,8 @@ x86_64_skip_prologue (CORE_ADDR pc)
struct symbol *v_function;
CORE_ADDR endaddr;
- /* We will handle only functions beginning with:
- 55 pushq %rbp
- 48 89 e5 movq %rsp,%rbp
- */
- unsigned char prolog_expect[PROLOG_BUFSIZE] = { 0x55, 0x48, 0x89, 0xe5 },
- prolog_buf[PROLOG_BUFSIZE];
-
- read_memory (pc, (char *) prolog_buf, PROLOG_BUFSIZE);
-
- /* First check, whether pc points to pushq %rbp, movq %rsp,%rbp. */
- for (i = 0; i < PROLOG_BUFSIZE; i++)
- if (prolog_expect[i] != prolog_buf[i])
- return pc; /* ... no, it doesn't. Nothing to skip. */
+ if (! x86_64_function_has_prologue (pc))
+ return pc;
/* OK, we have found the prologue and want PC of the first
non-prologue instruction. */
@@ -902,6 +911,178 @@ x86_64_skip_prologue (CORE_ADDR pc)
return pc;
}
+static struct fde_unit *
+x86_64_dwarf2_create_fde (CORE_ADDR pc)
+{
+ struct fde_unit *fde;
+ struct cie_unit *cie;
+ struct obj_section *osection;
+ CORE_ADDR loaddr, hiaddr;
+ char *name;
+
+ if (!find_pc_partial_function (pc, &name, &loaddr, &hiaddr))
+ return NULL;
+
+ if (info_verbose)
+ printf_filtered ("Dwarf2: Creating missing FDE for pc=%p (%s): ",
+ (void*)pc, name);
+
+ osection = find_pc_section(pc);
+ if (! osection)
+ return NULL;
+
+ /* First create CIE */
+ cie = cie_unit_alloc ();
+ cie->objfile = osection->objfile;
+ cie->next = cie_chunks;
+ cie_chunks = cie;
+
+ cie->code_align = 1;
+ cie->data_align = -8;
+ cie->ra = 0x10;
+
+ /* Now create FDE */
+ fde_chunks_need_space ();
+ fde = fde_unit_alloc ();
+
+ fde_chunks.array[fde_chunks.elems++] = fde;
+
+ fde->initial_location = loaddr;
+ fde->address_range = hiaddr - loaddr;
+
+ fde->cie_ptr = cie;
+
+ /* if (x86_64_linux_in_sigtramp (pc, name)) ... not yet implemented. */
+ if (x86_64_function_has_prologue (loaddr))
+ {
+ /* CIE and FDE for functions that have a valid prologue...
+
+ This is the sample function:
+ .text
+ sample_function:
+ .LFB1:
+ pushq %rbp
+ .LCFI0:
+ movq %rsp, %rbp
+ .LCFI1:
+ xor %rax, %rax
+ leave
+ ret
+ .LFE1:
+
+ This is the appropriate CIE:
+ .section .debug_frame
+ .Lframe0:
+ .long .LECIE0-.LSCIE0 # Length of Common Information Entry
+ .LSCIE0:
+ .long 0xffffffff # CIE Identifier Tag
+ .byte 0x1 # CIE Version
+ .ascii "\0" # CIE Augmentation
+ .uleb128 0x1 # CIE Code Alignment Factor
+ .sleb128 -8 # CIE Data Alignment Factor
+ .byte 0x10 # CIE RA Column
+ .byte 0xc # DW_CFA_def_cfa
+ .uleb128 0x7
+ .uleb128 0x8
+ .byte 0x90 # DW_CFA_offset, column 0x10
+ .uleb128 0x1
+ .align 8
+ .LECIE0:
+
+ And the appropriate FDE:
+ .LSFDE0:
+ .long .LEFDE0-.LASFDE0 # FDE Length
+ .LASFDE0:
+ .long .Lframe0 # FDE CIE offset
+ .quad .LFB1 # FDE initial location
+ .quad .LFE1-.LFB1 # FDE address range
+ .byte 0x4 # DW_CFA_advance_loc4
+ .long .LCFI0-.LFB1 # sizeof(pushq %rbp) = 1
+ .byte 0xe # DW_CFA_def_cfa_offset
+ .uleb128 0x10
+ .byte 0x86 # DW_CFA_offset, column 0x6
+ .uleb128 0x2
+ .byte 0x4 # DW_CFA_advance_loc4
+ .long .LCFI1-.LCFI0 # sizeof(movq %rsp, %rbp) = 3
+ .byte 0xd # DW_CFA_def_cfa_register
+ .uleb128 0x6
+ .align 8
+ .LEFDE0:
+ */
+ static char ciedata[] = {0x0c, 0x07, 0x08, 0x90, 0x01, 0};
+ static char fdedata[] = {0x41, 0x0e, 0x10, 0x86, 0x02,
+ 0x43, 0x0d, 0x06, 0};
+
+ if (info_verbose)
+ printf_filtered ("with prologue\n");
+
+ cie->data = ciedata;
+ cie->data_length = sizeof(ciedata);
+
+ fde->data = fdedata;
+ fde->data_length = sizeof(fdedata);
+ }
+ else
+ {
+ /* CIE and FDE for functions that don't touch stack:
+
+ This is the sample function:
+ .text
+ sample_function:
+ .LFB1:
+ xor %rax, %rax
+ ret
+ .LFE1:
+
+ This is CIE:
+ .section .debug_frame
+ .Lframe0:
+ .long .LECIE0-.LSCIE0 # Length of Common Information Entry
+ .LSCIE0:
+ .long 0xffffffff # CIE Identifier Tag
+ .byte 0x1 # CIE Version
+ .ascii "\0" # CIE Augmentation
+ .uleb128 0x1 # CIE Code Alignment Factor
+ .sleb128 -8 # CIE Data Alignment Factor
+ .byte 0x10 # CIE RA Column
+ .byte 0xc # DW_CFA_def_cfa
+ .uleb128 0x7
+ .uleb128 0x8
+ .byte 0x90 # DW_CFA_offset, column 0x10
+ .uleb128 0x1
+ .align 8
+ .LECIE0:
+
+ And the appropriate FDE:
+ .LSFDE0:
+ .long .LEFDE0-.LASFDE0 # FDE Length
+ .LASFDE0:
+ .long .Lframe0 # FDE CIE offset
+ .quad .LFB1 # FDE initial location
+ .quad .LFE1-.LFB1 # FDE address range
+ .align 8 # no instructions for CFA
+ .LEFDE0:
+ */
+ static char ciedata[] = {0x0c, 0x07, 0x08, 0x90, 0x01, 0};
+ static char fdedata[] = {0};
+
+ if (info_verbose)
+ printf_filtered ("without prologue\n");
+
+ cie->data = ciedata;
+ cie->data_length = sizeof(ciedata);
+
+ fde->data = fdedata;
+ fde->data_length = sizeof(fdedata);
+ }
+
+ /* Finally sort FDEs for future use. */
+ qsort (fde_chunks.array, fde_chunks.elems,
+ sizeof (struct fde_unit *), compare_fde_unit);
+
+ return fde;
+}
+
/* Sequence of bytes for breakpoint instruction. */
static unsigned char *
x86_64_breakpoint_from_pc (CORE_ADDR * pc, int *lenptr)
@@ -1121,6 +1302,7 @@ x86_64_gdbarch_init (struct gdbarch_info
/* Use dwarf2 debug frame informations. */
set_gdbarch_dwarf2_build_frame_info (gdbarch, dwarf2_build_frame_info);
set_gdbarch_dwarf2_reg_to_regnum (gdbarch, x86_64_dwarf2_reg_to_regnum);
+ set_gdbarch_dwarf2_create_fde (gdbarch, x86_64_dwarf2_create_fde);
return gdbarch;
}
Index: dwarf2cfi.c
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2cfi.c,v
retrieving revision 1.16
diff -u -p -r1.16 dwarf2cfi.c
--- dwarf2cfi.c 19 Jul 2002 09:40:51 -0000 1.16
+++ dwarf2cfi.c 14 Dec 2002 23:51:11 -0000
@@ -32,64 +32,6 @@
#include "dwarf2cfi.h"
#include "gdb_assert.h"
-/* Common Information Entry - holds information that is shared among many
- Frame Descriptors. */
-struct cie_unit
-{
- /* Offset of this unit in .debug_frame or .eh_frame. */
- ULONGEST offset;
-
- /* A null-terminated string that identifies the augmentation to this CIE or
- to the FDEs that use it. */
- char *augmentation;
-
- /* A constant that is factored out of all advance location instructions. */
- unsigned int code_align;
-
- /* A constant that is factored out of all offset instructions. */
- int data_align;
-
- /* A constant that indicates which regiter represents the return address
- of a function. */
- unsigned char ra;
-
- /* Indicates how addresses are encoded. */
- unsigned char addr_encoding;
-
- /* Pointer and length of the cie program. */
- char *data;
- unsigned int data_length;
-
- struct objfile *objfile;
-
- /* Next in chain. */
- struct cie_unit *next;
-};
-
-/* Frame Description Entry. */
-struct fde_unit
-{
- /* Address of the first location associated with this entry. */
- CORE_ADDR initial_location;
-
- /* Length of program section described by this entry. */
- CORE_ADDR address_range;
-
- /* Pointer to asociated CIE. */
- struct cie_unit *cie_ptr;
-
- /* Pointer and length of the cie program. */
- char *data;
- unsigned int data_length;
-};
-
-struct fde_array
-{
- struct fde_unit **array;
- int elems;
- int array_size;
-};
-
struct context_reg
{
union
@@ -190,8 +132,8 @@ enum ptr_encoding
#define UNWIND_CONTEXT(fi) ((struct context *) (fi->context))
\f
-static struct cie_unit *cie_chunks;
-static struct fde_array fde_chunks;
+struct cie_unit *cie_chunks = NULL;
+struct fde_array fde_chunks = { 0 };
/* Obstack for allocating temporary storage used during unwind operations. */
static struct obstack unwind_tmp_obstack;
@@ -204,10 +146,6 @@ extern unsigned int dwarf_eh_frame_size;
extern char *dwarf2_read_section (struct objfile *objfile, file_ptr offset,
unsigned int size);
-static struct fde_unit *fde_unit_alloc (void);
-static struct cie_unit *cie_unit_alloc (void);
-static void fde_chunks_need_space ();
-
static struct context *context_alloc ();
static struct frame_state *frame_state_alloc ();
static void unwind_tmp_obstack_init ();
@@ -235,7 +173,6 @@ static ULONGEST read_length (bfd * abfd,
int dwarf64);
static int is_cie (ULONGEST cie_id, int dwarf64);
-static int compare_fde_unit (const void *a, const void *b);
void dwarf2_build_frame_info (struct objfile *objfile);
static void execute_cfa_program (struct objfile *objfile, char *insn_ptr,
@@ -253,7 +190,7 @@ static void update_context (struct conte
\f
/* Memory allocation functions. */
-static struct fde_unit *
+struct fde_unit *
fde_unit_alloc (void)
{
struct fde_unit *fde;
@@ -263,7 +200,7 @@ fde_unit_alloc (void)
return fde;
}
-static struct cie_unit *
+struct cie_unit *
cie_unit_alloc (void)
{
struct cie_unit *cie;
@@ -273,7 +210,7 @@ cie_unit_alloc (void)
return cie;
}
-static void
+void
fde_chunks_need_space (void)
{
if (fde_chunks.elems < fde_chunks.array_size)
@@ -829,6 +766,15 @@ get_fde_for_addr (CORE_ADDR pc)
return 0;
}
+static struct fde_unit *
+guess_generic_fde (CORE_ADDR pc)
+{
+ if (gdbarch_dwarf2_create_fde_p (current_gdbarch))
+ return gdbarch_dwarf2_create_fde (current_gdbarch, pc);
+ else
+ return NULL;
+}
+
static void
frame_state_for (struct context *context, struct frame_state *fs)
{
@@ -839,6 +785,9 @@ frame_state_for (struct context *context
context->lsda = 0;
fde = get_fde_for_addr (context->ra - 1);
+
+ if (fde == NULL)
+ fde = guess_generic_fde (context->ra - 1);
if (fde == NULL)
return;
@@ -1378,7 +1327,7 @@ is_cie (ULONGEST cie_id, int dwarf64)
return dwarf64 ? (cie_id == 0xffffffffffffffff) : (cie_id == 0xffffffff);
}
-static int
+int
compare_fde_unit (const void *a, const void *b)
{
struct fde_unit **first, **second;
@@ -1466,8 +1415,6 @@ parse_frame_info (struct objfile *objfil
cie->objfile = objfile;
cie->next = cie_chunks;
cie_chunks = cie;
-
- cie->objfile = objfile;
cie->offset = unit_offset;
Index: dwarf2cfi.h
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2cfi.h,v
retrieving revision 1.1
diff -u -p -r1.1 dwarf2cfi.h
--- dwarf2cfi.h 7 Dec 2001 12:10:15 -0000 1.1
+++ dwarf2cfi.h 14 Dec 2002 23:51:11 -0000
@@ -22,6 +22,67 @@
#ifndef DWARF2CFI_H
#define DWARF2CFI_H
+/* Common Information Entry - holds information that is shared among many
+ Frame Descriptors. */
+struct cie_unit
+{
+ /* Offset of this unit in .debug_frame or .eh_frame. */
+ ULONGEST offset;
+
+ /* A null-terminated string that identifies the augmentation to this CIE or
+ to the FDEs that use it. */
+ char *augmentation;
+
+ /* A constant that is factored out of all advance location instructions. */
+ unsigned int code_align;
+
+ /* A constant that is factored out of all offset instructions. */
+ int data_align;
+
+ /* A constant that indicates which regiter represents the return address
+ of a function. */
+ unsigned char ra;
+
+ /* Indicates how addresses are encoded. */
+ unsigned char addr_encoding;
+
+ /* Pointer and length of the cie program. */
+ char *data;
+ unsigned int data_length;
+
+ struct objfile *objfile;
+
+ /* Next in chain. */
+ struct cie_unit *next;
+};
+
+/* Frame Description Entry. */
+struct fde_unit
+{
+ /* Address of the first location associated with this entry. */
+ CORE_ADDR initial_location;
+
+ /* Length of program section described by this entry. */
+ CORE_ADDR address_range;
+
+ /* Pointer to asociated CIE. */
+ struct cie_unit *cie_ptr;
+
+ /* Pointer and length of the cie program. */
+ char *data;
+ unsigned int data_length;
+};
+
+struct fde_array
+{
+ struct fde_unit **array;
+ int elems;
+ int array_size;
+};
+
+extern struct cie_unit *cie_chunks;
+extern struct fde_array fde_chunks;
+
/* Return the frame address. */
CORE_ADDR cfi_read_fp ();
@@ -62,5 +123,10 @@ void cfi_get_saved_register (char *raw_b
any frame pointer offsets. */
void cfi_virtual_frame_pointer (CORE_ADDR pc, int *frame_regnum,
LONGEST * frame_offset);
+
+struct cie_unit *cie_unit_alloc (void);
+struct fde_unit *fde_unit_alloc (void);
+void fde_chunks_need_space (void);
+int compare_fde_unit (const void *a, const void *b);
#endif
Index: gdbarch.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbarch.c,v
retrieving revision 1.146
diff -u -p -r1.146 gdbarch.c
--- gdbarch.c 24 Aug 2002 00:21:34 -0000 1.146
+++ gdbarch.c 14 Dec 2002 23:51:12 -0000
@@ -263,6 +263,7 @@ struct gdbarch
gdbarch_in_function_epilogue_p_ftype *in_function_epilogue_p;
gdbarch_construct_inferior_arguments_ftype *construct_inferior_arguments;
gdbarch_dwarf2_build_frame_info_ftype *dwarf2_build_frame_info;
+ gdbarch_dwarf2_create_fde_ftype *dwarf2_create_fde;
gdbarch_elf_make_msymbol_special_ftype *elf_make_msymbol_special;
gdbarch_coff_make_msymbol_special_ftype *coff_make_msymbol_special;
};
@@ -419,6 +420,7 @@ struct gdbarch startup_gdbarch =
0,
0,
0,
+ 0,
/* startup_gdbarch() */
};
@@ -649,6 +651,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
/* Skip verify of print_registers_info, invalid_p == 0 */
/* Skip verify of print_float_info, has predicate */
/* Skip verify of print_vector_info, has predicate */
+ /* Skip verify of dwarf2_create_fde, has predicate */
/* Skip verify of register_sim_regno, invalid_p == 0 */
/* Skip verify of register_bytes_ok, has predicate */
/* Skip verify of cannot_fetch_register, invalid_p == 0 */
@@ -3110,6 +3113,32 @@ set_gdbarch_print_vector_info (struct gd
gdbarch_print_vector_info_ftype print_vector_info)
{
gdbarch->print_vector_info = print_vector_info;
+}
+
+int
+gdbarch_dwarf2_create_fde_p (struct gdbarch *gdbarch)
+{
+ gdb_assert (gdbarch != NULL);
+ return gdbarch->dwarf2_create_fde != 0;
+}
+
+struct fde_unit *
+gdbarch_dwarf2_create_fde (struct gdbarch *gdbarch, CORE_ADDR pc)
+{
+ gdb_assert (gdbarch != NULL);
+ if (gdbarch->dwarf2_create_fde == 0)
+ internal_error (__FILE__, __LINE__,
+ "gdbarch: gdbarch_dwarf2_create_fde invalid");
+ if (gdbarch_debug >= 2)
+ fprintf_unfiltered (gdb_stdlog, "gdbarch_dwarf2_create_fde called\n");
+ return gdbarch->dwarf2_create_fde (pc);
+}
+
+void
+set_gdbarch_dwarf2_create_fde (struct gdbarch *gdbarch,
+ gdbarch_dwarf2_create_fde_ftype dwarf2_create_fde)
+{
+ gdbarch->dwarf2_create_fde = dwarf2_create_fde;
}
int
Index: gdbarch.h
===================================================================
RCS file: /cvs/src/src/gdb/gdbarch.h,v
retrieving revision 1.114
diff -u -p -r1.114 gdbarch.h
--- gdbarch.h 24 Aug 2002 00:21:34 -0000 1.114
+++ gdbarch.h 14 Dec 2002 23:51:12 -0000
@@ -831,6 +831,14 @@ typedef void (gdbarch_print_vector_info_
extern void gdbarch_print_vector_info (struct gdbarch *gdbarch, struct ui_file *file, struct frame_info *frame, const char *args);
extern void set_gdbarch_print_vector_info (struct gdbarch *gdbarch, gdbarch_print_vector_info_ftype *print_vector_info);
+/* Target specific functions for creating debug info
+ for functions that miss it (mostly pure assembler
+ objects. */
+typedef struct fde_unit *(gdbarch_dwarf2_create_fde_ftype) (CORE_ADDR pc);
+extern int gdbarch_dwarf2_create_fde_p (struct gdbarch *gdbarch);
+extern struct fde_unit *gdbarch_dwarf2_create_fde (struct gdbarch *gdbarch, CORE_ADDR pc);
+extern void set_gdbarch_dwarf2_create_fde (struct gdbarch *gdbarch, gdbarch_dwarf2_create_fde_ftype *create_fde);
+
/* MAP a GDB RAW register number onto a simulator register number. See
also include/...-sim.h. */
^ permalink raw reply [flat|nested] 33+ messages in thread* Re: [RFA] Artifical dwarf2 debug info 2002-12-14 17:31 [RFA] Artifical dwarf2 debug info Michal Ludvig @ 2002-12-14 22:53 ` Eli Zaretskii 2002-12-15 11:03 ` Daniel Jacobowitz 2002-12-16 9:25 ` Andrew Cagney 2 siblings, 0 replies; 33+ messages in thread From: Eli Zaretskii @ 2002-12-14 22:53 UTC (permalink / raw) To: Michal Ludvig; +Cc: GDB Patches On Sun, 15 Dec 2002, Michal Ludvig wrote: > Since this debug info is hardware dependent, I introduce a new gdbarch > item: dwarf2_create_fde. Any architecture using Dwarf2 CFI that will > like to profit from it must have it's own <whtever>_dwarf2_create_fde() > function, very similar to the one I did for x86-64. I submit that this should be documented in gdbint.texinfo. I think _any_ feature that needs arch-specific code to be supported should be mentioned in the internals manual. Assuming the code is accepted, could you please consider writing a short section about this? It sounds like the comments you've put in the code could serve as the good starting point for the documentation. TIA ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [RFA] Artifical dwarf2 debug info 2002-12-14 17:31 [RFA] Artifical dwarf2 debug info Michal Ludvig 2002-12-14 22:53 ` Eli Zaretskii @ 2002-12-15 11:03 ` Daniel Jacobowitz 2002-12-16 7:28 ` Michal Ludvig 2002-12-16 9:25 ` Andrew Cagney 2 siblings, 1 reply; 33+ messages in thread From: Daniel Jacobowitz @ 2002-12-15 11:03 UTC (permalink / raw) To: Michal Ludvig; +Cc: GDB Patches On Sun, Dec 15, 2002 at 01:48:12AM +0100, Michal Ludvig wrote: > Hi all, > this long patch provides a fix for a very annoying fact, that GDB on > x86-64 can't do backtraces from hand-optimized assembler functions (that > applies for example to glibc's memset, str*, etc as well as to syscall > wrappers). Workaround, really - just for some particular functions... > My approach to fix this behaviour is based on the fortunate fact, that > most of those affected glibc's functions don't touch the stack at all, > so creating an artifical FDE for them is easy. Lucky. We can use this to solve a similar problem on i386 but that will require an actual FDE. > Advantages of this approach are simplicity and cleanliness. There is no > need to "manually" fill in values in CFI's context structure - just > provide a valid, simple FDE and everything else will be done > automagically. This new FDE is of course joined to all other FDEs read > from the file before and is automatically used when needed again. > > The patch is transparent to architectures that are not prepared to have > advantage of it and shouldn't hurt anything. Great. One big problem: gdbarch.h and gdbarch.c are generated files. Add this to gdbarch.sh instead, and regenerate them. Also it needs documentation, as Eli said. It would be nice if there were routines in dwarf2cfi.[ch] for creating FDEs instead of having hex in the tdep file but that doesn't really bother me. We can do that later when I need real FDEs. > OK to commit to branch and mainline? I do not believe this is appropriate for the branch, at least until it's sat on mainline without causing problems for some time. -- Daniel Jacobowitz MontaVista Software Debian GNU/Linux Developer ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [RFA] Artifical dwarf2 debug info 2002-12-15 11:03 ` Daniel Jacobowitz @ 2002-12-16 7:28 ` Michal Ludvig 2002-12-16 7:49 ` Daniel Jacobowitz 0 siblings, 1 reply; 33+ messages in thread From: Michal Ludvig @ 2002-12-16 7:28 UTC (permalink / raw) To: Daniel Jacobowitz; +Cc: GDB Patches [-- Attachment #1: Type: text/plain, Size: 2072 bytes --] Daniel Jacobowitz wrote: > On Sun, Dec 15, 2002 at 01:48:12AM +0100, Michal Ludvig wrote: > >>this long patch provides a fix for a very annoying fact, that GDB on >>x86-64 can't do backtraces from hand-optimized assembler functions (that >>applies for example to glibc's memset, str*, etc as well as to syscall >>wrappers). > > Workaround, really - just for some particular functions... Yes, but still better than nothing ;-) >>My approach to fix this behaviour is based on the fortunate fact, that >>most of those affected glibc's functions don't touch the stack at all, >>so creating an artifical FDE for them is easy. > > Lucky. We can use this to solve a similar problem on i386 but that > will require an actual FDE. I got it by compiling a sample program with 'gcc -S -g -dA'. >>The patch is transparent to architectures that are not prepared to have >>advantage of it and shouldn't hurt anything. > > Great. One big problem: gdbarch.h and gdbarch.c are generated files. > Add this to gdbarch.sh instead, and regenerate them. Also it needs > documentation, as Eli said. OK, the attached patch has a modified gdbarch.sh and regenerated gdbarch.[ch]. I've also put a description into gdbint.texinfo > It would be nice if there were routines in dwarf2cfi.[ch] for creating > FDEs instead of having hex in the tdep file but that doesn't really > bother me. We can do that later when I need real FDEs. Yes, that could be taken from GCC I believe. But it can wait a little longer I belive... >>OK to commit to branch and mainline? > > I do not believe this is appropriate for the branch, at least until > it's sat on mainline without causing problems for some time. It shouldn't cause any problems because all the machinery is invoked if and only if the target allowed it, and then if a FDE isn't found for a particular function. Typically only two or three times on x86-64 and zero times on other archs. Can I put it at least to mainline? Michal Ludvig -- * SuSE CR, s.r.o * mludvig@suse.cz * (+420) 296.545.373 * http://www.suse.cz [-- Attachment #2: bthack-3.diff --] [-- Type: text/plain, Size: 24210 bytes --] 2002-12-16 Michal Ludvig <mludvig@suse.cz> * x86-64-tdep.c (x86_64_function_has_prologue): New function, cut off from x86_64_skip_prologue(). (x86_64_skip_prologue): Call x86_64_function_has_prologue(). (x86_64_dwarf2_create_fde): Brand new function. (x86_64_gdbarch_init): Call set_gdbarch_dwarf2_create_fde(). * dwarf2cfi.c (struct cie_unit, struct fde_unit) (struct fde_array): Moved to dwarf2cfi.h (cie_chunks, fde_chunks): Made extern. (fde_unit_alloc, cie_unit_alloc, fde_chunks_need_space) (compare_fde_unit): Made extern. (frame_state_for): Call DWARF2_CREATE_FDE when FDE wasn't found. (parse_frame_info): Remove duplicate line. * dwarf2cfi.h (struct cie_unit, struct fde_unit) (struct fde_array, cie_chunks, fde_chunks) (fde_unit_alloc, cie_unit_alloc, fde_chunks_need_space) (compare_fde_unit): New, moved from dwarf2cfi.c * doc/gdbint.texi: Described DWARF2_CREATE_FDE(). * gdbarch.sh (dwarf2_create_fde): New function. * gdbarch.c, gdbarch.h: Regenerated. * x86-64-linux-tdep.c (linux_sigtramp_code): Moved comment. Index: x86-64-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/x86-64-tdep.c,v retrieving revision 1.26 diff -u -p -r1.26 x86-64-tdep.c --- x86-64-tdep.c 24 Aug 2002 00:21:35 -0000 1.26 +++ x86-64-tdep.c 16 Dec 2002 13:26:47 -0000 @@ -850,11 +850,31 @@ x86_64_frameless_function_invocation (st return 0; } +/* We will handle only functions beginning with: + 55 pushq %rbp + 48 89 e5 movq %rsp,%rbp */ +#define PROLOG_BUFSIZE 4 +static int +x86_64_function_has_prologue (CORE_ADDR pc) +{ + int i; + unsigned char prolog_expect[PROLOG_BUFSIZE] = { 0x55, 0x48, 0x89, 0xe5 }, + prolog_buf[PROLOG_BUFSIZE]; + + read_memory (pc, (char *) prolog_buf, PROLOG_BUFSIZE); + + /* First check, whether pc points to pushq %rbp, movq %rsp,%rbp. */ + for (i = 0; i < PROLOG_BUFSIZE; i++) + if (prolog_expect[i] != prolog_buf[i]) + return 0; /* ... no, it doesn't. Nothing to skip. */ + + return 1; +} + /* If a function with debugging information and known beginning is detected, we will return pc of the next line in the source code. With this approach we effectively skip the prolog. */ -#define PROLOG_BUFSIZE 4 CORE_ADDR x86_64_skip_prologue (CORE_ADDR pc) { @@ -863,19 +883,8 @@ x86_64_skip_prologue (CORE_ADDR pc) struct symbol *v_function; CORE_ADDR endaddr; - /* We will handle only functions beginning with: - 55 pushq %rbp - 48 89 e5 movq %rsp,%rbp - */ - unsigned char prolog_expect[PROLOG_BUFSIZE] = { 0x55, 0x48, 0x89, 0xe5 }, - prolog_buf[PROLOG_BUFSIZE]; - - read_memory (pc, (char *) prolog_buf, PROLOG_BUFSIZE); - - /* First check, whether pc points to pushq %rbp, movq %rsp,%rbp. */ - for (i = 0; i < PROLOG_BUFSIZE; i++) - if (prolog_expect[i] != prolog_buf[i]) - return pc; /* ... no, it doesn't. Nothing to skip. */ + if (! x86_64_function_has_prologue (pc)) + return pc; /* OK, we have found the prologue and want PC of the first non-prologue instruction. */ @@ -902,6 +911,178 @@ x86_64_skip_prologue (CORE_ADDR pc) return pc; } +static struct fde_unit * +x86_64_dwarf2_create_fde (CORE_ADDR pc) +{ + struct fde_unit *fde; + struct cie_unit *cie; + struct obj_section *osection; + CORE_ADDR loaddr, hiaddr; + char *name; + + if (!find_pc_partial_function (pc, &name, &loaddr, &hiaddr)) + return NULL; + + if (info_verbose) + printf_filtered ("Dwarf2: Creating missing FDE for pc=%p (%s): ", + (void*)pc, name); + + osection = find_pc_section(pc); + if (! osection) + return NULL; + + /* First create CIE */ + cie = cie_unit_alloc (); + cie->objfile = osection->objfile; + cie->next = cie_chunks; + cie_chunks = cie; + + cie->code_align = 1; + cie->data_align = -8; + cie->ra = 0x10; + + /* Now create FDE */ + fde_chunks_need_space (); + fde = fde_unit_alloc (); + + fde_chunks.array[fde_chunks.elems++] = fde; + + fde->initial_location = loaddr; + fde->address_range = hiaddr - loaddr; + + fde->cie_ptr = cie; + + /* if (x86_64_linux_in_sigtramp (pc, name)) ... not yet implemented. */ + if (x86_64_function_has_prologue (loaddr)) + { + /* CIE and FDE for functions that have a valid prologue... + + This is the sample function: + .text + sample_function: + .LFB1: + pushq %rbp + .LCFI0: + movq %rsp, %rbp + .LCFI1: + xor %rax, %rax + leave + ret + .LFE1: + + This is the appropriate CIE: + .section .debug_frame + .Lframe0: + .long .LECIE0-.LSCIE0 # Length of Common Information Entry + .LSCIE0: + .long 0xffffffff # CIE Identifier Tag + .byte 0x1 # CIE Version + .ascii "\0" # CIE Augmentation + .uleb128 0x1 # CIE Code Alignment Factor + .sleb128 -8 # CIE Data Alignment Factor + .byte 0x10 # CIE RA Column + .byte 0xc # DW_CFA_def_cfa + .uleb128 0x7 + .uleb128 0x8 + .byte 0x90 # DW_CFA_offset, column 0x10 + .uleb128 0x1 + .align 8 + .LECIE0: + + And the appropriate FDE: + .LSFDE0: + .long .LEFDE0-.LASFDE0 # FDE Length + .LASFDE0: + .long .Lframe0 # FDE CIE offset + .quad .LFB1 # FDE initial location + .quad .LFE1-.LFB1 # FDE address range + .byte 0x4 # DW_CFA_advance_loc4 + .long .LCFI0-.LFB1 # sizeof(pushq %rbp) = 1 + .byte 0xe # DW_CFA_def_cfa_offset + .uleb128 0x10 + .byte 0x86 # DW_CFA_offset, column 0x6 + .uleb128 0x2 + .byte 0x4 # DW_CFA_advance_loc4 + .long .LCFI1-.LCFI0 # sizeof(movq %rsp, %rbp) = 3 + .byte 0xd # DW_CFA_def_cfa_register + .uleb128 0x6 + .align 8 + .LEFDE0: + */ + static char ciedata[] = {0x0c, 0x07, 0x08, 0x90, 0x01, 0}; + static char fdedata[] = {0x41, 0x0e, 0x10, 0x86, 0x02, + 0x43, 0x0d, 0x06, 0}; + + if (info_verbose) + printf_filtered ("with prologue\n"); + + cie->data = ciedata; + cie->data_length = sizeof(ciedata); + + fde->data = fdedata; + fde->data_length = sizeof(fdedata); + } + else + { + /* CIE and FDE for functions that don't touch stack: + + This is the sample function: + .text + sample_function: + .LFB1: + xor %rax, %rax + ret + .LFE1: + + This is CIE: + .section .debug_frame + .Lframe0: + .long .LECIE0-.LSCIE0 # Length of Common Information Entry + .LSCIE0: + .long 0xffffffff # CIE Identifier Tag + .byte 0x1 # CIE Version + .ascii "\0" # CIE Augmentation + .uleb128 0x1 # CIE Code Alignment Factor + .sleb128 -8 # CIE Data Alignment Factor + .byte 0x10 # CIE RA Column + .byte 0xc # DW_CFA_def_cfa + .uleb128 0x7 + .uleb128 0x8 + .byte 0x90 # DW_CFA_offset, column 0x10 + .uleb128 0x1 + .align 8 + .LECIE0: + + And the appropriate FDE: + .LSFDE0: + .long .LEFDE0-.LASFDE0 # FDE Length + .LASFDE0: + .long .Lframe0 # FDE CIE offset + .quad .LFB1 # FDE initial location + .quad .LFE1-.LFB1 # FDE address range + .align 8 # no instructions for CFA + .LEFDE0: + */ + static char ciedata[] = {0x0c, 0x07, 0x08, 0x90, 0x01, 0}; + static char fdedata[] = {0}; + + if (info_verbose) + printf_filtered ("without prologue\n"); + + cie->data = ciedata; + cie->data_length = sizeof(ciedata); + + fde->data = fdedata; + fde->data_length = sizeof(fdedata); + } + + /* Finally sort FDEs for future use. */ + qsort (fde_chunks.array, fde_chunks.elems, + sizeof (struct fde_unit *), compare_fde_unit); + + return fde; +} + /* Sequence of bytes for breakpoint instruction. */ static unsigned char * x86_64_breakpoint_from_pc (CORE_ADDR * pc, int *lenptr) @@ -1121,6 +1302,7 @@ x86_64_gdbarch_init (struct gdbarch_info /* Use dwarf2 debug frame informations. */ set_gdbarch_dwarf2_build_frame_info (gdbarch, dwarf2_build_frame_info); set_gdbarch_dwarf2_reg_to_regnum (gdbarch, x86_64_dwarf2_reg_to_regnum); + set_gdbarch_dwarf2_create_fde (gdbarch, x86_64_dwarf2_create_fde); return gdbarch; } Index: x86-64-tdep.h =================================================================== RCS file: /cvs/src/src/gdb/x86-64-tdep.h,v retrieving revision 1.5 diff -u -p -r1.5 x86-64-tdep.h --- x86-64-tdep.h 20 Jun 2002 13:08:12 -0000 1.5 +++ x86-64-tdep.h 16 Dec 2002 13:26:47 -0000 @@ -31,8 +31,8 @@ extern int x86_64_num_gregs; int x86_64_register_number (const char *name); const char *x86_64_register_name (int reg_nr); - gdbarch_frame_saved_pc_ftype x86_64_linux_frame_saved_pc; gdbarch_saved_pc_after_call_ftype x86_64_linux_saved_pc_after_call; +int x86_64_function_has_prologue (CORE_ADDR pc); #endif Index: dwarf2cfi.c =================================================================== RCS file: /cvs/src/src/gdb/dwarf2cfi.c,v retrieving revision 1.16 diff -u -p -r1.16 dwarf2cfi.c --- dwarf2cfi.c 19 Jul 2002 09:40:51 -0000 1.16 +++ dwarf2cfi.c 16 Dec 2002 13:26:45 -0000 @@ -32,64 +32,6 @@ #include "dwarf2cfi.h" #include "gdb_assert.h" -/* Common Information Entry - holds information that is shared among many - Frame Descriptors. */ -struct cie_unit -{ - /* Offset of this unit in .debug_frame or .eh_frame. */ - ULONGEST offset; - - /* A null-terminated string that identifies the augmentation to this CIE or - to the FDEs that use it. */ - char *augmentation; - - /* A constant that is factored out of all advance location instructions. */ - unsigned int code_align; - - /* A constant that is factored out of all offset instructions. */ - int data_align; - - /* A constant that indicates which regiter represents the return address - of a function. */ - unsigned char ra; - - /* Indicates how addresses are encoded. */ - unsigned char addr_encoding; - - /* Pointer and length of the cie program. */ - char *data; - unsigned int data_length; - - struct objfile *objfile; - - /* Next in chain. */ - struct cie_unit *next; -}; - -/* Frame Description Entry. */ -struct fde_unit -{ - /* Address of the first location associated with this entry. */ - CORE_ADDR initial_location; - - /* Length of program section described by this entry. */ - CORE_ADDR address_range; - - /* Pointer to asociated CIE. */ - struct cie_unit *cie_ptr; - - /* Pointer and length of the cie program. */ - char *data; - unsigned int data_length; -}; - -struct fde_array -{ - struct fde_unit **array; - int elems; - int array_size; -}; - struct context_reg { union @@ -190,8 +132,8 @@ enum ptr_encoding #define UNWIND_CONTEXT(fi) ((struct context *) (fi->context)) \f -static struct cie_unit *cie_chunks; -static struct fde_array fde_chunks; +struct cie_unit *cie_chunks = NULL; +struct fde_array fde_chunks = { 0 }; /* Obstack for allocating temporary storage used during unwind operations. */ static struct obstack unwind_tmp_obstack; @@ -204,10 +146,6 @@ extern unsigned int dwarf_eh_frame_size; extern char *dwarf2_read_section (struct objfile *objfile, file_ptr offset, unsigned int size); -static struct fde_unit *fde_unit_alloc (void); -static struct cie_unit *cie_unit_alloc (void); -static void fde_chunks_need_space (); - static struct context *context_alloc (); static struct frame_state *frame_state_alloc (); static void unwind_tmp_obstack_init (); @@ -235,7 +173,6 @@ static ULONGEST read_length (bfd * abfd, int dwarf64); static int is_cie (ULONGEST cie_id, int dwarf64); -static int compare_fde_unit (const void *a, const void *b); void dwarf2_build_frame_info (struct objfile *objfile); static void execute_cfa_program (struct objfile *objfile, char *insn_ptr, @@ -253,7 +190,7 @@ static void update_context (struct conte \f /* Memory allocation functions. */ -static struct fde_unit * +struct fde_unit * fde_unit_alloc (void) { struct fde_unit *fde; @@ -263,7 +200,7 @@ fde_unit_alloc (void) return fde; } -static struct cie_unit * +struct cie_unit * cie_unit_alloc (void) { struct cie_unit *cie; @@ -273,7 +210,7 @@ cie_unit_alloc (void) return cie; } -static void +void fde_chunks_need_space (void) { if (fde_chunks.elems < fde_chunks.array_size) @@ -839,6 +776,9 @@ frame_state_for (struct context *context context->lsda = 0; fde = get_fde_for_addr (context->ra - 1); + + if (fde == NULL && DWARF2_CREATE_FDE_P ()) + fde = DWARF2_CREATE_FDE (context->ra - 1); if (fde == NULL) return; @@ -1378,7 +1318,7 @@ is_cie (ULONGEST cie_id, int dwarf64) return dwarf64 ? (cie_id == 0xffffffffffffffff) : (cie_id == 0xffffffff); } -static int +int compare_fde_unit (const void *a, const void *b) { struct fde_unit **first, **second; @@ -1466,8 +1406,6 @@ parse_frame_info (struct objfile *objfil cie->objfile = objfile; cie->next = cie_chunks; cie_chunks = cie; - - cie->objfile = objfile; cie->offset = unit_offset; Index: dwarf2cfi.h =================================================================== RCS file: /cvs/src/src/gdb/dwarf2cfi.h,v retrieving revision 1.1 diff -u -p -r1.1 dwarf2cfi.h --- dwarf2cfi.h 7 Dec 2001 12:10:15 -0000 1.1 +++ dwarf2cfi.h 16 Dec 2002 13:26:45 -0000 @@ -22,6 +22,67 @@ #ifndef DWARF2CFI_H #define DWARF2CFI_H +/* Common Information Entry - holds information that is shared among many + Frame Descriptors. */ +struct cie_unit +{ + /* Offset of this unit in .debug_frame or .eh_frame. */ + ULONGEST offset; + + /* A null-terminated string that identifies the augmentation to this CIE or + to the FDEs that use it. */ + char *augmentation; + + /* A constant that is factored out of all advance location instructions. */ + unsigned int code_align; + + /* A constant that is factored out of all offset instructions. */ + int data_align; + + /* A constant that indicates which regiter represents the return address + of a function. */ + unsigned char ra; + + /* Indicates how addresses are encoded. */ + unsigned char addr_encoding; + + /* Pointer and length of the cie program. */ + char *data; + unsigned int data_length; + + struct objfile *objfile; + + /* Next in chain. */ + struct cie_unit *next; +}; + +/* Frame Description Entry. */ +struct fde_unit +{ + /* Address of the first location associated with this entry. */ + CORE_ADDR initial_location; + + /* Length of program section described by this entry. */ + CORE_ADDR address_range; + + /* Pointer to asociated CIE. */ + struct cie_unit *cie_ptr; + + /* Pointer and length of the cie program. */ + char *data; + unsigned int data_length; +}; + +struct fde_array +{ + struct fde_unit **array; + int elems; + int array_size; +}; + +extern struct cie_unit *cie_chunks; +extern struct fde_array fde_chunks; + /* Return the frame address. */ CORE_ADDR cfi_read_fp (); @@ -62,5 +123,10 @@ void cfi_get_saved_register (char *raw_b any frame pointer offsets. */ void cfi_virtual_frame_pointer (CORE_ADDR pc, int *frame_regnum, LONGEST * frame_offset); + +struct cie_unit *cie_unit_alloc (void); +struct fde_unit *fde_unit_alloc (void); +void fde_chunks_need_space (void); +int compare_fde_unit (const void *a, const void *b); #endif Index: doc/gdbint.texinfo =================================================================== RCS file: /cvs/src/src/gdb/doc/gdbint.texinfo,v retrieving revision 1.100 diff -u -p -r1.100 gdbint.texinfo --- doc/gdbint.texinfo 24 Aug 2002 00:21:37 -0000 1.100 +++ doc/gdbint.texinfo 16 Dec 2002 13:29:18 -0000 @@ -3249,6 +3249,16 @@ automatically. Thus, since the offset f its first instruction is two bytes, @code{FUNCTION_START_OFFSET} would be 2 on the VAX. +@item DWARF2_CREATE_FDE (@var{pc}) +@findex DWARF2_CREATE_FDE +This function is called from Dwarf2 CFI engine, when there is no FDE +found for a given @var{pc}. It should create a new valid FDE +(along with the corresponding CIE) regarding to the type of the function +to which @var{pc} belongs and join these two structures to @var{cie_chunks} +and @var{fde_chunks} respectively. If the FDE can't be created return +@code{NULL}, otherwise a pointer to the newly created @code{struct fde_unit} +is returned. + @item GCC_COMPILED_FLAG_SYMBOL @itemx GCC2_COMPILED_FLAG_SYMBOL @findex GCC2_COMPILED_FLAG_SYMBOL Index: gdbarch.sh =================================================================== RCS file: /cvs/src/src/gdb/gdbarch.sh,v retrieving revision 1.158.6.1 diff -u -p -r1.158.6.1 gdbarch.sh --- gdbarch.sh 20 Nov 2002 00:43:57 -0000 1.158.6.1 +++ gdbarch.sh 16 Dec 2002 13:26:46 -0000 @@ -656,6 +656,7 @@ m:::int:in_function_epilogue_p:CORE_ADDR # ARGV is an array of strings, one per argument. m::CONSTRUCT_INFERIOR_ARGUMENTS:char *:construct_inferior_arguments:int argc, char **argv:argc, argv:::construct_inferior_arguments::0 F:2:DWARF2_BUILD_FRAME_INFO:void:dwarf2_build_frame_info:struct objfile *objfile:objfile:::0 +F:2:DWARF2_CREATE_FDE:struct fde_unit *:dwarf2_create_fde:CORE_ADDR pc:pc:::0 f:2:ELF_MAKE_MSYMBOL_SPECIAL:void:elf_make_msymbol_special:asymbol *sym, struct minimal_symbol *msym:sym, msym:::default_elf_make_msymbol_special::0 f:2:COFF_MAKE_MSYMBOL_SPECIAL:void:coff_make_msymbol_special:int val, struct minimal_symbol *msym:val, msym:::default_coff_make_msymbol_special::0 EOF Index: gdbarch.c =================================================================== RCS file: /cvs/src/src/gdb/gdbarch.c,v retrieving revision 1.146 diff -u -p -r1.146 gdbarch.c --- gdbarch.c 24 Aug 2002 00:21:34 -0000 1.146 +++ gdbarch.c 16 Dec 2002 13:26:46 -0000 @@ -263,6 +263,7 @@ struct gdbarch gdbarch_in_function_epilogue_p_ftype *in_function_epilogue_p; gdbarch_construct_inferior_arguments_ftype *construct_inferior_arguments; gdbarch_dwarf2_build_frame_info_ftype *dwarf2_build_frame_info; + gdbarch_dwarf2_create_fde_ftype *dwarf2_create_fde; gdbarch_elf_make_msymbol_special_ftype *elf_make_msymbol_special; gdbarch_coff_make_msymbol_special_ftype *coff_make_msymbol_special; }; @@ -419,6 +420,7 @@ struct gdbarch startup_gdbarch = 0, 0, 0, + 0, /* startup_gdbarch() */ }; @@ -789,6 +791,7 @@ verify_gdbarch (struct gdbarch *gdbarch) /* Skip verify of in_function_epilogue_p, invalid_p == 0 */ /* Skip verify of construct_inferior_arguments, invalid_p == 0 */ /* Skip verify of dwarf2_build_frame_info, has predicate */ + /* Skip verify of dwarf2_create_fde, has predicate */ /* Skip verify of elf_make_msymbol_special, invalid_p == 0 */ /* Skip verify of coff_make_msymbol_special, invalid_p == 0 */ buf = ui_file_xstrdup (log, &dummy); @@ -1113,6 +1116,17 @@ gdbarch_dump (struct gdbarch *gdbarch, s (long) current_gdbarch->dwarf2_build_frame_info /*DWARF2_BUILD_FRAME_INFO ()*/); #endif +#ifdef DWARF2_CREATE_FDE + fprintf_unfiltered (file, + "gdbarch_dump: %s # %s\n", + "DWARF2_CREATE_FDE(pc)", + XSTRING (DWARF2_CREATE_FDE (pc))); + if (GDB_MULTI_ARCH) + fprintf_unfiltered (file, + "gdbarch_dump: DWARF2_CREATE_FDE = 0x%08lx\n", + (long) current_gdbarch->dwarf2_create_fde + /*DWARF2_CREATE_FDE ()*/); +#endif #ifdef DWARF2_REG_TO_REGNUM fprintf_unfiltered (file, "gdbarch_dump: %s # %s\n", @@ -4842,6 +4856,32 @@ set_gdbarch_dwarf2_build_frame_info (str gdbarch_dwarf2_build_frame_info_ftype dwarf2_build_frame_info) { gdbarch->dwarf2_build_frame_info = dwarf2_build_frame_info; +} + +int +gdbarch_dwarf2_create_fde_p (struct gdbarch *gdbarch) +{ + gdb_assert (gdbarch != NULL); + return gdbarch->dwarf2_create_fde != 0; +} + +struct fde_unit * +gdbarch_dwarf2_create_fde (struct gdbarch *gdbarch, CORE_ADDR pc) +{ + gdb_assert (gdbarch != NULL); + if (gdbarch->dwarf2_create_fde == 0) + internal_error (__FILE__, __LINE__, + "gdbarch: gdbarch_dwarf2_create_fde invalid"); + if (gdbarch_debug >= 2) + fprintf_unfiltered (gdb_stdlog, "gdbarch_dwarf2_create_fde called\n"); + return gdbarch->dwarf2_create_fde (pc); +} + +void +set_gdbarch_dwarf2_create_fde (struct gdbarch *gdbarch, + gdbarch_dwarf2_create_fde_ftype dwarf2_create_fde) +{ + gdbarch->dwarf2_create_fde = dwarf2_create_fde; } void Index: gdbarch.h =================================================================== RCS file: /cvs/src/src/gdb/gdbarch.h,v retrieving revision 1.114 diff -u -p -r1.114 gdbarch.h --- gdbarch.h 24 Aug 2002 00:21:34 -0000 1.114 +++ gdbarch.h 16 Dec 2002 13:26:46 -0000 @@ -2449,6 +2449,43 @@ extern void set_gdbarch_dwarf2_build_fra #endif #endif +#if defined (DWARF2_CREATE_FDE) +/* Legacy for systems yet to multi-arch DWARF2_CREATE_FDE */ +#if !defined (DWARF2_CREATE_FDE_P) +#define DWARF2_CREATE_FDE_P() (1) +#endif +#endif + +/* Default predicate for non- multi-arch targets. */ +#if (!GDB_MULTI_ARCH) && !defined (DWARF2_CREATE_FDE_P) +#define DWARF2_CREATE_FDE_P() (0) +#endif + +extern int gdbarch_dwarf2_create_fde_p (struct gdbarch *gdbarch); +#if (GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL) && defined (DWARF2_CREATE_FDE_P) +#error "Non multi-arch definition of DWARF2_CREATE_FDE" +#endif +#if (GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL) || !defined (DWARF2_CREATE_FDE_P) +#define DWARF2_CREATE_FDE_P() (gdbarch_dwarf2_create_fde_p (current_gdbarch)) +#endif + +/* Default (function) for non- multi-arch platforms. */ +#if (!GDB_MULTI_ARCH) && !defined (DWARF2_CREATE_FDE) +#define DWARF2_CREATE_FDE(pc) (internal_error (__FILE__, __LINE__, "DWARF2_CREATE_FDE"), 0) +#endif + +typedef struct fde_unit * (gdbarch_dwarf2_create_fde_ftype) (CORE_ADDR pc); +extern struct fde_unit * gdbarch_dwarf2_create_fde (struct gdbarch *gdbarch, CORE_ADDR pc); +extern void set_gdbarch_dwarf2_create_fde (struct gdbarch *gdbarch, gdbarch_dwarf2_create_fde_ftype *dwarf2_create_fde); +#if (GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL) && defined (DWARF2_CREATE_FDE) +#error "Non multi-arch definition of DWARF2_CREATE_FDE" +#endif +#if GDB_MULTI_ARCH +#if (GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL) || !defined (DWARF2_CREATE_FDE) +#define DWARF2_CREATE_FDE(pc) (gdbarch_dwarf2_create_fde (current_gdbarch, pc)) +#endif +#endif + /* Default (function) for non- multi-arch platforms. */ #if (!GDB_MULTI_ARCH) && !defined (ELF_MAKE_MSYMBOL_SPECIAL) #define ELF_MAKE_MSYMBOL_SPECIAL(sym, msym) (default_elf_make_msymbol_special (sym, msym)) Index: x86-64-linux-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/x86-64-linux-tdep.c,v retrieving revision 1.5 diff -u -p -r1.5 x86-64-linux-tdep.c --- x86-64-linux-tdep.c 3 Sep 2002 13:06:33 -0000 1.5 +++ x86-64-linux-tdep.c 16 Dec 2002 13:26:47 -0000 @@ -35,8 +35,10 @@ #define LINUX_SIGTRAMP_OFFSET1 (7) static const unsigned char linux_sigtramp_code[] = { - LINUX_SIGTRAMP_INSN0, 0xc7, 0xc0, 0x89, 0x00, 0x00, 0x00, /* mov $0x89,%rax */ - LINUX_SIGTRAMP_INSN1, 0x05 /* syscall */ + /* mov $__NR_rt_sigreturn,%rax */ + LINUX_SIGTRAMP_INSN0, 0xc7, 0xc0, 0x89, 0x00, 0x00, 0x00, + /* syscall */ + LINUX_SIGTRAMP_INSN1, 0x05 }; #define LINUX_SIGTRAMP_LEN (sizeof linux_sigtramp_code) ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [RFA] Artifical dwarf2 debug info 2002-12-16 7:28 ` Michal Ludvig @ 2002-12-16 7:49 ` Daniel Jacobowitz 2002-12-16 9:27 ` Michal Ludvig 0 siblings, 1 reply; 33+ messages in thread From: Daniel Jacobowitz @ 2002-12-16 7:49 UTC (permalink / raw) To: Michal Ludvig; +Cc: GDB Patches On Mon, Dec 16, 2002 at 02:58:18PM +0100, Michal Ludvig wrote: > Daniel Jacobowitz wrote: > >On Sun, Dec 15, 2002 at 01:48:12AM +0100, Michal Ludvig wrote: > > > >>this long patch provides a fix for a very annoying fact, that GDB on > >>x86-64 can't do backtraces from hand-optimized assembler functions (that > >>applies for example to glibc's memset, str*, etc as well as to syscall > >>wrappers). > > > >Workaround, really - just for some particular functions... > > Yes, but still better than nothing ;-) Yeah. > OK, the attached patch has a modified gdbarch.sh and regenerated > gdbarch.[ch]. > > I've also put a description into gdbint.texinfo OK, Eli will have to approve that part. > >>OK to commit to branch and mainline? > > > >I do not believe this is appropriate for the branch, at least until > >it's sat on mainline without causing problems for some time. > > It shouldn't cause any problems because all the machinery is invoked if > and only if the target allowed it, and then if a FDE isn't found for a > particular function. Typically only two or three times on x86-64 and > zero times on other archs. > > Can I put it at least to mainline? A little way to go yet. Please don't just export things from dwarf2cfi: > +/* Common Information Entry - holds information that is shared among many > + Frame Descriptors. */ > +struct cie_unit This is fine for now. > +/* Frame Description Entry. */ > +struct fde_unit > +{ So's this. > +struct fde_array > +{ > + struct fde_unit **array; > + int elems; > + int array_size; > +}; > + > +extern struct cie_unit *cie_chunks; > +extern struct fde_array fde_chunks; > + But these aren't. Add a function to link a new FDE or CIE, please. > +struct cie_unit *cie_unit_alloc (void); > +struct fde_unit *fde_unit_alloc (void); These make sense... > +void fde_chunks_need_space (void); > +int compare_fde_unit (const void *a, const void *b); But these aren't necessary if you add said function. -- Daniel Jacobowitz MontaVista Software Debian GNU/Linux Developer ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [RFA] Artifical dwarf2 debug info 2002-12-16 7:49 ` Daniel Jacobowitz @ 2002-12-16 9:27 ` Michal Ludvig 2002-12-16 9:54 ` Daniel Jacobowitz 2002-12-16 10:38 ` Eli Zaretskii 0 siblings, 2 replies; 33+ messages in thread From: Michal Ludvig @ 2002-12-16 9:27 UTC (permalink / raw) To: Daniel Jacobowitz; +Cc: GDB Patches [-- Attachment #1: Type: text/plain, Size: 568 bytes --] Daniel Jacobowitz wrote: > On Mon, Dec 16, 2002 at 02:58:18PM +0100, Michal Ludvig wrote: >>Can I put it at least to mainline? > > > A little way to go yet. Please don't just export things from > dwarf2cfi: > > > But these aren't. Add a function to link a new FDE or CIE, please. OK, added two new functions: store_fde_unit and store_cie_unit. Now only functions for allocation and functions for storing new units are exported. Do you like it more, now? :-) Michal Ludvig -- * SuSE CR, s.r.o * mludvig@suse.cz * (+420) 296.545.373 * http://www.suse.cz [-- Attachment #2: bthack-4.diff --] [-- Type: text/plain, Size: 22795 bytes --] 2002-12-16 Michal Ludvig <mludvig@suse.cz> * x86-64-tdep.c (x86_64_function_has_prologue): New function, cut off from x86_64_skip_prologue(). (x86_64_skip_prologue): Call x86_64_function_has_prologue(). (x86_64_dwarf2_create_fde): Brand new function. (x86_64_gdbarch_init): Call set_gdbarch_dwarf2_create_fde(). * dwarf2cfi.c (struct cie_unit, struct fde_unit): Moved to dwarf2cfi.h (fde_unit_alloc, cie_unit_alloc): Made extern. (store_fde_unit, store_cie_unit): New functions. (frame_state_for): Call DWARF2_CREATE_FDE when FDE wasn't found. (parse_frame_info): Remove duplicate line. * dwarf2cfi.h (struct cie_unit, struct fde_unit) (fde_unit_alloc, cie_unit_alloc): New, moved from dwarf2cfi.c (store_fde_unit, store_cie_unit): New prototypes. * doc/gdbint.texi: Described DWARF2_CREATE_FDE(). * gdbarch.sh (dwarf2_create_fde): New function. * gdbarch.c, gdbarch.h: Regenerated. * x86-64-linux-tdep.c (linux_sigtramp_code): Moved comment. Index: dwarf2cfi.c =================================================================== RCS file: /cvs/src/src/gdb/dwarf2cfi.c,v retrieving revision 1.16 diff -u -p -r1.16 dwarf2cfi.c --- dwarf2cfi.c 19 Jul 2002 09:40:51 -0000 1.16 +++ dwarf2cfi.c 16 Dec 2002 17:00:51 -0000 @@ -32,57 +32,6 @@ #include "dwarf2cfi.h" #include "gdb_assert.h" -/* Common Information Entry - holds information that is shared among many - Frame Descriptors. */ -struct cie_unit -{ - /* Offset of this unit in .debug_frame or .eh_frame. */ - ULONGEST offset; - - /* A null-terminated string that identifies the augmentation to this CIE or - to the FDEs that use it. */ - char *augmentation; - - /* A constant that is factored out of all advance location instructions. */ - unsigned int code_align; - - /* A constant that is factored out of all offset instructions. */ - int data_align; - - /* A constant that indicates which regiter represents the return address - of a function. */ - unsigned char ra; - - /* Indicates how addresses are encoded. */ - unsigned char addr_encoding; - - /* Pointer and length of the cie program. */ - char *data; - unsigned int data_length; - - struct objfile *objfile; - - /* Next in chain. */ - struct cie_unit *next; -}; - -/* Frame Description Entry. */ -struct fde_unit -{ - /* Address of the first location associated with this entry. */ - CORE_ADDR initial_location; - - /* Length of program section described by this entry. */ - CORE_ADDR address_range; - - /* Pointer to asociated CIE. */ - struct cie_unit *cie_ptr; - - /* Pointer and length of the cie program. */ - char *data; - unsigned int data_length; -}; - struct fde_array { struct fde_unit **array; @@ -190,8 +139,8 @@ enum ptr_encoding #define UNWIND_CONTEXT(fi) ((struct context *) (fi->context)) \f -static struct cie_unit *cie_chunks; -static struct fde_array fde_chunks; +static struct cie_unit *cie_chunks = NULL; +static struct fde_array fde_chunks = { 0 }; /* Obstack for allocating temporary storage used during unwind operations. */ static struct obstack unwind_tmp_obstack; @@ -839,6 +783,9 @@ frame_state_for (struct context *context context->lsda = 0; fde = get_fde_for_addr (context->ra - 1); + + if (fde == NULL && DWARF2_CREATE_FDE_P ()) + fde = DWARF2_CREATE_FDE (context->ra - 1); if (fde == NULL) return; @@ -1467,8 +1414,6 @@ parse_frame_info (struct objfile *objfil cie->next = cie_chunks; cie_chunks = cie; - cie->objfile = objfile; - cie->offset = unit_offset; start++; /* version */ @@ -1952,3 +1897,28 @@ cfi_virtual_frame_pointer (CORE_ADDR pc, unwind_tmp_obstack_free (); } + +void +store_fde_unit (struct fde_unit *fde) +{ + if (fde) + { + fde_chunks_need_space (); + fde_chunks.array[fde_chunks.elems++] = fde; + + qsort (fde_chunks.array, fde_chunks.elems, + sizeof (struct fde_unit *), compare_fde_unit); + + } + else + error ("Dwarf2 CFI error: Attempt to store NULL pointer to FDE list!"); +} + +void +store_cie_unit (struct cie_unit *cie) +{ + cie->next = cie_chunks; + cie_chunks = cie; +} + + Index: dwarf2cfi.h =================================================================== RCS file: /cvs/src/src/gdb/dwarf2cfi.h,v retrieving revision 1.1 diff -u -p -r1.1 dwarf2cfi.h --- dwarf2cfi.h 7 Dec 2001 12:10:15 -0000 1.1 +++ dwarf2cfi.h 16 Dec 2002 17:00:51 -0000 @@ -22,6 +22,57 @@ #ifndef DWARF2CFI_H #define DWARF2CFI_H +/* Common Information Entry - holds information that is shared among many + Frame Descriptors. */ +struct cie_unit +{ + /* Offset of this unit in .debug_frame or .eh_frame. */ + ULONGEST offset; + + /* A null-terminated string that identifies the augmentation to this CIE or + to the FDEs that use it. */ + char *augmentation; + + /* A constant that is factored out of all advance location instructions. */ + unsigned int code_align; + + /* A constant that is factored out of all offset instructions. */ + int data_align; + + /* A constant that indicates which regiter represents the return address + of a function. */ + unsigned char ra; + + /* Indicates how addresses are encoded. */ + unsigned char addr_encoding; + + /* Pointer and length of the cie program. */ + char *data; + unsigned int data_length; + + struct objfile *objfile; + + /* Next in chain. */ + struct cie_unit *next; +}; + +/* Frame Description Entry. */ +struct fde_unit +{ + /* Address of the first location associated with this entry. */ + CORE_ADDR initial_location; + + /* Length of program section described by this entry. */ + CORE_ADDR address_range; + + /* Pointer to asociated CIE. */ + struct cie_unit *cie_ptr; + + /* Pointer and length of the cie program. */ + char *data; + unsigned int data_length; +}; + /* Return the frame address. */ CORE_ADDR cfi_read_fp (); @@ -62,5 +113,11 @@ void cfi_get_saved_register (char *raw_b any frame pointer offsets. */ void cfi_virtual_frame_pointer (CORE_ADDR pc, int *frame_regnum, LONGEST * frame_offset); + +struct cie_unit *cie_unit_alloc (void); +struct fde_unit *fde_unit_alloc (void); + +void store_cie_unit (struct cie_unit *); +void store_fde_unit (struct fde_unit *); #endif Index: gdbarch.c =================================================================== RCS file: /cvs/src/src/gdb/gdbarch.c,v retrieving revision 1.146 diff -u -p -r1.146 gdbarch.c --- gdbarch.c 24 Aug 2002 00:21:34 -0000 1.146 +++ gdbarch.c 16 Dec 2002 17:00:52 -0000 @@ -263,6 +263,7 @@ struct gdbarch gdbarch_in_function_epilogue_p_ftype *in_function_epilogue_p; gdbarch_construct_inferior_arguments_ftype *construct_inferior_arguments; gdbarch_dwarf2_build_frame_info_ftype *dwarf2_build_frame_info; + gdbarch_dwarf2_create_fde_ftype *dwarf2_create_fde; gdbarch_elf_make_msymbol_special_ftype *elf_make_msymbol_special; gdbarch_coff_make_msymbol_special_ftype *coff_make_msymbol_special; }; @@ -419,6 +420,7 @@ struct gdbarch startup_gdbarch = 0, 0, 0, + 0, /* startup_gdbarch() */ }; @@ -789,6 +791,7 @@ verify_gdbarch (struct gdbarch *gdbarch) /* Skip verify of in_function_epilogue_p, invalid_p == 0 */ /* Skip verify of construct_inferior_arguments, invalid_p == 0 */ /* Skip verify of dwarf2_build_frame_info, has predicate */ + /* Skip verify of dwarf2_create_fde, has predicate */ /* Skip verify of elf_make_msymbol_special, invalid_p == 0 */ /* Skip verify of coff_make_msymbol_special, invalid_p == 0 */ buf = ui_file_xstrdup (log, &dummy); @@ -1113,6 +1116,17 @@ gdbarch_dump (struct gdbarch *gdbarch, s (long) current_gdbarch->dwarf2_build_frame_info /*DWARF2_BUILD_FRAME_INFO ()*/); #endif +#ifdef DWARF2_CREATE_FDE + fprintf_unfiltered (file, + "gdbarch_dump: %s # %s\n", + "DWARF2_CREATE_FDE(pc)", + XSTRING (DWARF2_CREATE_FDE (pc))); + if (GDB_MULTI_ARCH) + fprintf_unfiltered (file, + "gdbarch_dump: DWARF2_CREATE_FDE = 0x%08lx\n", + (long) current_gdbarch->dwarf2_create_fde + /*DWARF2_CREATE_FDE ()*/); +#endif #ifdef DWARF2_REG_TO_REGNUM fprintf_unfiltered (file, "gdbarch_dump: %s # %s\n", @@ -4842,6 +4856,32 @@ set_gdbarch_dwarf2_build_frame_info (str gdbarch_dwarf2_build_frame_info_ftype dwarf2_build_frame_info) { gdbarch->dwarf2_build_frame_info = dwarf2_build_frame_info; +} + +int +gdbarch_dwarf2_create_fde_p (struct gdbarch *gdbarch) +{ + gdb_assert (gdbarch != NULL); + return gdbarch->dwarf2_create_fde != 0; +} + +struct fde_unit * +gdbarch_dwarf2_create_fde (struct gdbarch *gdbarch, CORE_ADDR pc) +{ + gdb_assert (gdbarch != NULL); + if (gdbarch->dwarf2_create_fde == 0) + internal_error (__FILE__, __LINE__, + "gdbarch: gdbarch_dwarf2_create_fde invalid"); + if (gdbarch_debug >= 2) + fprintf_unfiltered (gdb_stdlog, "gdbarch_dwarf2_create_fde called\n"); + return gdbarch->dwarf2_create_fde (pc); +} + +void +set_gdbarch_dwarf2_create_fde (struct gdbarch *gdbarch, + gdbarch_dwarf2_create_fde_ftype dwarf2_create_fde) +{ + gdbarch->dwarf2_create_fde = dwarf2_create_fde; } void Index: gdbarch.h =================================================================== RCS file: /cvs/src/src/gdb/gdbarch.h,v retrieving revision 1.114 diff -u -p -r1.114 gdbarch.h --- gdbarch.h 24 Aug 2002 00:21:34 -0000 1.114 +++ gdbarch.h 16 Dec 2002 17:00:52 -0000 @@ -2449,6 +2449,43 @@ extern void set_gdbarch_dwarf2_build_fra #endif #endif +#if defined (DWARF2_CREATE_FDE) +/* Legacy for systems yet to multi-arch DWARF2_CREATE_FDE */ +#if !defined (DWARF2_CREATE_FDE_P) +#define DWARF2_CREATE_FDE_P() (1) +#endif +#endif + +/* Default predicate for non- multi-arch targets. */ +#if (!GDB_MULTI_ARCH) && !defined (DWARF2_CREATE_FDE_P) +#define DWARF2_CREATE_FDE_P() (0) +#endif + +extern int gdbarch_dwarf2_create_fde_p (struct gdbarch *gdbarch); +#if (GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL) && defined (DWARF2_CREATE_FDE_P) +#error "Non multi-arch definition of DWARF2_CREATE_FDE" +#endif +#if (GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL) || !defined (DWARF2_CREATE_FDE_P) +#define DWARF2_CREATE_FDE_P() (gdbarch_dwarf2_create_fde_p (current_gdbarch)) +#endif + +/* Default (function) for non- multi-arch platforms. */ +#if (!GDB_MULTI_ARCH) && !defined (DWARF2_CREATE_FDE) +#define DWARF2_CREATE_FDE(pc) (internal_error (__FILE__, __LINE__, "DWARF2_CREATE_FDE"), 0) +#endif + +typedef struct fde_unit * (gdbarch_dwarf2_create_fde_ftype) (CORE_ADDR pc); +extern struct fde_unit * gdbarch_dwarf2_create_fde (struct gdbarch *gdbarch, CORE_ADDR pc); +extern void set_gdbarch_dwarf2_create_fde (struct gdbarch *gdbarch, gdbarch_dwarf2_create_fde_ftype *dwarf2_create_fde); +#if (GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL) && defined (DWARF2_CREATE_FDE) +#error "Non multi-arch definition of DWARF2_CREATE_FDE" +#endif +#if GDB_MULTI_ARCH +#if (GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL) || !defined (DWARF2_CREATE_FDE) +#define DWARF2_CREATE_FDE(pc) (gdbarch_dwarf2_create_fde (current_gdbarch, pc)) +#endif +#endif + /* Default (function) for non- multi-arch platforms. */ #if (!GDB_MULTI_ARCH) && !defined (ELF_MAKE_MSYMBOL_SPECIAL) #define ELF_MAKE_MSYMBOL_SPECIAL(sym, msym) (default_elf_make_msymbol_special (sym, msym)) Index: gdbarch.sh =================================================================== RCS file: /cvs/src/src/gdb/gdbarch.sh,v retrieving revision 1.158.6.1 diff -u -p -r1.158.6.1 gdbarch.sh --- gdbarch.sh 20 Nov 2002 00:43:57 -0000 1.158.6.1 +++ gdbarch.sh 16 Dec 2002 17:00:52 -0000 @@ -656,6 +656,7 @@ m:::int:in_function_epilogue_p:CORE_ADDR # ARGV is an array of strings, one per argument. m::CONSTRUCT_INFERIOR_ARGUMENTS:char *:construct_inferior_arguments:int argc, char **argv:argc, argv:::construct_inferior_arguments::0 F:2:DWARF2_BUILD_FRAME_INFO:void:dwarf2_build_frame_info:struct objfile *objfile:objfile:::0 +F:2:DWARF2_CREATE_FDE:struct fde_unit *:dwarf2_create_fde:CORE_ADDR pc:pc:::0 f:2:ELF_MAKE_MSYMBOL_SPECIAL:void:elf_make_msymbol_special:asymbol *sym, struct minimal_symbol *msym:sym, msym:::default_elf_make_msymbol_special::0 f:2:COFF_MAKE_MSYMBOL_SPECIAL:void:coff_make_msymbol_special:int val, struct minimal_symbol *msym:val, msym:::default_coff_make_msymbol_special::0 EOF Index: x86-64-linux-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/x86-64-linux-tdep.c,v retrieving revision 1.5 diff -u -p -r1.5 x86-64-linux-tdep.c --- x86-64-linux-tdep.c 3 Sep 2002 13:06:33 -0000 1.5 +++ x86-64-linux-tdep.c 16 Dec 2002 17:00:52 -0000 @@ -35,8 +35,10 @@ #define LINUX_SIGTRAMP_OFFSET1 (7) static const unsigned char linux_sigtramp_code[] = { - LINUX_SIGTRAMP_INSN0, 0xc7, 0xc0, 0x89, 0x00, 0x00, 0x00, /* mov $0x89,%rax */ - LINUX_SIGTRAMP_INSN1, 0x05 /* syscall */ + /* mov $__NR_rt_sigreturn,%rax */ + LINUX_SIGTRAMP_INSN0, 0xc7, 0xc0, 0x89, 0x00, 0x00, 0x00, + /* syscall */ + LINUX_SIGTRAMP_INSN1, 0x05 }; #define LINUX_SIGTRAMP_LEN (sizeof linux_sigtramp_code) Index: x86-64-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/x86-64-tdep.c,v retrieving revision 1.26 diff -u -p -r1.26 x86-64-tdep.c --- x86-64-tdep.c 24 Aug 2002 00:21:35 -0000 1.26 +++ x86-64-tdep.c 16 Dec 2002 17:00:55 -0000 @@ -850,11 +850,31 @@ x86_64_frameless_function_invocation (st return 0; } +/* We will handle only functions beginning with: + 55 pushq %rbp + 48 89 e5 movq %rsp,%rbp */ +#define PROLOG_BUFSIZE 4 +static int +x86_64_function_has_prologue (CORE_ADDR pc) +{ + int i; + unsigned char prolog_expect[PROLOG_BUFSIZE] = { 0x55, 0x48, 0x89, 0xe5 }, + prolog_buf[PROLOG_BUFSIZE]; + + read_memory (pc, (char *) prolog_buf, PROLOG_BUFSIZE); + + /* First check, whether pc points to pushq %rbp, movq %rsp,%rbp. */ + for (i = 0; i < PROLOG_BUFSIZE; i++) + if (prolog_expect[i] != prolog_buf[i]) + return 0; /* ... no, it doesn't. Nothing to skip. */ + + return 1; +} + /* If a function with debugging information and known beginning is detected, we will return pc of the next line in the source code. With this approach we effectively skip the prolog. */ -#define PROLOG_BUFSIZE 4 CORE_ADDR x86_64_skip_prologue (CORE_ADDR pc) { @@ -863,19 +883,8 @@ x86_64_skip_prologue (CORE_ADDR pc) struct symbol *v_function; CORE_ADDR endaddr; - /* We will handle only functions beginning with: - 55 pushq %rbp - 48 89 e5 movq %rsp,%rbp - */ - unsigned char prolog_expect[PROLOG_BUFSIZE] = { 0x55, 0x48, 0x89, 0xe5 }, - prolog_buf[PROLOG_BUFSIZE]; - - read_memory (pc, (char *) prolog_buf, PROLOG_BUFSIZE); - - /* First check, whether pc points to pushq %rbp, movq %rsp,%rbp. */ - for (i = 0; i < PROLOG_BUFSIZE; i++) - if (prolog_expect[i] != prolog_buf[i]) - return pc; /* ... no, it doesn't. Nothing to skip. */ + if (! x86_64_function_has_prologue (pc)) + return pc; /* OK, we have found the prologue and want PC of the first non-prologue instruction. */ @@ -902,6 +911,175 @@ x86_64_skip_prologue (CORE_ADDR pc) return pc; } +static struct fde_unit * +x86_64_dwarf2_create_fde (CORE_ADDR pc) +{ + struct fde_unit *fde; + struct cie_unit *cie; + struct obj_section *osection; + CORE_ADDR loaddr, hiaddr; + char *name; + + if (!find_pc_partial_function (pc, &name, &loaddr, &hiaddr)) + return NULL; + + if (info_verbose) + printf_filtered ("Dwarf2: Creating missing FDE for pc=%p (%s): ", + (void*)pc, name); + + osection = find_pc_section(pc); + if (! osection) + return NULL; + + /* First create CIE */ + cie = cie_unit_alloc (); + + cie->objfile = osection->objfile; + cie->code_align = 1; + cie->data_align = -8; + cie->ra = 0x10; + + /* Now create FDE */ + fde = fde_unit_alloc (); + + fde->initial_location = loaddr; + fde->address_range = hiaddr - loaddr; + fde->cie_ptr = cie; + + /* Now fill in data appropriate for a given function type. */ + + /* if (x86_64_linux_in_sigtramp (pc, name)) ... not yet implemented. */ + if (x86_64_function_has_prologue (loaddr)) + { + /* CIE and FDE for functions that have a valid prologue... + + This is the sample function: + .text + sample_function: + .LFB1: + pushq %rbp + .LCFI0: + movq %rsp, %rbp + .LCFI1: + xor %rax, %rax + leave + ret + .LFE1: + + This is the appropriate CIE: + .section .debug_frame + .Lframe0: + .long .LECIE0-.LSCIE0 # Length of Common Information Entry + .LSCIE0: + .long 0xffffffff # CIE Identifier Tag + .byte 0x1 # CIE Version + .ascii "\0" # CIE Augmentation + .uleb128 0x1 # CIE Code Alignment Factor + .sleb128 -8 # CIE Data Alignment Factor + .byte 0x10 # CIE RA Column + .byte 0xc # DW_CFA_def_cfa + .uleb128 0x7 + .uleb128 0x8 + .byte 0x90 # DW_CFA_offset, column 0x10 + .uleb128 0x1 + .align 8 + .LECIE0: + + And the appropriate FDE: + .LSFDE0: + .long .LEFDE0-.LASFDE0 # FDE Length + .LASFDE0: + .long .Lframe0 # FDE CIE offset + .quad .LFB1 # FDE initial location + .quad .LFE1-.LFB1 # FDE address range + .byte 0x4 # DW_CFA_advance_loc4 + .long .LCFI0-.LFB1 # sizeof(pushq %rbp) = 1 + .byte 0xe # DW_CFA_def_cfa_offset + .uleb128 0x10 + .byte 0x86 # DW_CFA_offset, column 0x6 + .uleb128 0x2 + .byte 0x4 # DW_CFA_advance_loc4 + .long .LCFI1-.LCFI0 # sizeof(movq %rsp, %rbp) = 3 + .byte 0xd # DW_CFA_def_cfa_register + .uleb128 0x6 + .align 8 + .LEFDE0: + */ + static char ciedata[] = {0x0c, 0x07, 0x08, 0x90, 0x01, 0}; + static char fdedata[] = {0x41, 0x0e, 0x10, 0x86, 0x02, + 0x43, 0x0d, 0x06, 0}; + + if (info_verbose) + printf_filtered ("with prologue\n"); + + cie->data = ciedata; + cie->data_length = sizeof(ciedata); + + fde->data = fdedata; + fde->data_length = sizeof(fdedata); + } + else + { + /* CIE and FDE for functions that don't touch stack: + + This is the sample function: + .text + sample_function: + .LFB1: + xor %rax, %rax + ret + .LFE1: + + This is CIE: + .section .debug_frame + .Lframe0: + .long .LECIE0-.LSCIE0 # Length of Common Information Entry + .LSCIE0: + .long 0xffffffff # CIE Identifier Tag + .byte 0x1 # CIE Version + .ascii "\0" # CIE Augmentation + .uleb128 0x1 # CIE Code Alignment Factor + .sleb128 -8 # CIE Data Alignment Factor + .byte 0x10 # CIE RA Column + .byte 0xc # DW_CFA_def_cfa + .uleb128 0x7 + .uleb128 0x8 + .byte 0x90 # DW_CFA_offset, column 0x10 + .uleb128 0x1 + .align 8 + .LECIE0: + + And the appropriate FDE: + .LSFDE0: + .long .LEFDE0-.LASFDE0 # FDE Length + .LASFDE0: + .long .Lframe0 # FDE CIE offset + .quad .LFB1 # FDE initial location + .quad .LFE1-.LFB1 # FDE address range + .align 8 # no instructions for CFA + .LEFDE0: + */ + static char ciedata[] = {0x0c, 0x07, 0x08, 0x90, 0x01, 0}; + static char fdedata[] = {0}; + + if (info_verbose) + printf_filtered ("without prologue\n"); + + cie->data = ciedata; + cie->data_length = sizeof(ciedata); + + fde->data = fdedata; + fde->data_length = sizeof(fdedata); + } + + /* Store both units for future use after + they are filled up with values. */ + store_fde_unit (fde); + store_cie_unit (cie); + + return fde; +} + /* Sequence of bytes for breakpoint instruction. */ static unsigned char * x86_64_breakpoint_from_pc (CORE_ADDR * pc, int *lenptr) @@ -1121,6 +1299,7 @@ x86_64_gdbarch_init (struct gdbarch_info /* Use dwarf2 debug frame informations. */ set_gdbarch_dwarf2_build_frame_info (gdbarch, dwarf2_build_frame_info); set_gdbarch_dwarf2_reg_to_regnum (gdbarch, x86_64_dwarf2_reg_to_regnum); + set_gdbarch_dwarf2_create_fde (gdbarch, x86_64_dwarf2_create_fde); return gdbarch; } Index: x86-64-tdep.h =================================================================== RCS file: /cvs/src/src/gdb/x86-64-tdep.h,v retrieving revision 1.5 diff -u -p -r1.5 x86-64-tdep.h --- x86-64-tdep.h 20 Jun 2002 13:08:12 -0000 1.5 +++ x86-64-tdep.h 16 Dec 2002 17:00:55 -0000 @@ -31,8 +31,8 @@ extern int x86_64_num_gregs; int x86_64_register_number (const char *name); const char *x86_64_register_name (int reg_nr); - gdbarch_frame_saved_pc_ftype x86_64_linux_frame_saved_pc; gdbarch_saved_pc_after_call_ftype x86_64_linux_saved_pc_after_call; +int x86_64_function_has_prologue (CORE_ADDR pc); #endif Index: doc/gdbint.texinfo =================================================================== RCS file: /cvs/src/src/gdb/doc/gdbint.texinfo,v retrieving revision 1.100 diff -u -p -r1.100 gdbint.texinfo --- doc/gdbint.texinfo 24 Aug 2002 00:21:37 -0000 1.100 +++ doc/gdbint.texinfo 16 Dec 2002 13:29:18 -0000 @@ -3249,6 +3249,16 @@ automatically. Thus, since the offset f its first instruction is two bytes, @code{FUNCTION_START_OFFSET} would be 2 on the VAX. +@item DWARF2_CREATE_FDE (@var{pc}) +@findex DWARF2_CREATE_FDE +This function is called from Dwarf2 CFI engine, when there is no FDE +found for a given @var{pc}. It should create a new valid FDE +(along with the corresponding CIE) regarding to the type of the function +to which @var{pc} belongs and join these two structures to @var{cie_chunks} +and @var{fde_chunks} respectively. If the FDE can't be created return +@code{NULL}, otherwise a pointer to the newly created @code{struct fde_unit} +is returned. + @item GCC_COMPILED_FLAG_SYMBOL @itemx GCC2_COMPILED_FLAG_SYMBOL @findex GCC2_COMPILED_FLAG_SYMBOL ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [RFA] Artifical dwarf2 debug info 2002-12-16 9:27 ` Michal Ludvig @ 2002-12-16 9:54 ` Daniel Jacobowitz 2002-12-16 10:38 ` Eli Zaretskii 1 sibling, 0 replies; 33+ messages in thread From: Daniel Jacobowitz @ 2002-12-16 9:54 UTC (permalink / raw) To: Michal Ludvig; +Cc: GDB Patches On Mon, Dec 16, 2002 at 06:25:29PM +0100, Michal Ludvig wrote: > Daniel Jacobowitz wrote: > >On Mon, Dec 16, 2002 at 02:58:18PM +0100, Michal Ludvig wrote: > >>Can I put it at least to mainline? > > > > > >A little way to go yet. Please don't just export things from > >dwarf2cfi: > > > > > >But these aren't. Add a function to link a new FDE or CIE, please. > > OK, added two new functions: store_fde_unit and store_cie_unit. > > Now only functions for allocation and functions for storing new units > are exported. > > Do you like it more, now? :-) From a technical standpoint it looks good to me, now. Thanks! You still need approval for the documentation, and obviously it can't go in until we reach consensus about the right way to solve this problem. > > Michal Ludvig > -- > * SuSE CR, s.r.o * mludvig@suse.cz > * (+420) 296.545.373 * http://www.suse.cz > 2002-12-16 Michal Ludvig <mludvig@suse.cz> > > * x86-64-tdep.c (x86_64_function_has_prologue): New function, > cut off from x86_64_skip_prologue(). > (x86_64_skip_prologue): Call x86_64_function_has_prologue(). > (x86_64_dwarf2_create_fde): Brand new function. > (x86_64_gdbarch_init): Call set_gdbarch_dwarf2_create_fde(). > * dwarf2cfi.c (struct cie_unit, struct fde_unit): Moved to > dwarf2cfi.h > (fde_unit_alloc, cie_unit_alloc): Made extern. > (store_fde_unit, store_cie_unit): New functions. > (frame_state_for): Call DWARF2_CREATE_FDE when FDE wasn't > found. > (parse_frame_info): Remove duplicate line. > * dwarf2cfi.h (struct cie_unit, struct fde_unit) > (fde_unit_alloc, cie_unit_alloc): New, moved from dwarf2cfi.c > (store_fde_unit, store_cie_unit): New prototypes. > * doc/gdbint.texi: Described DWARF2_CREATE_FDE(). > * gdbarch.sh (dwarf2_create_fde): New function. > * gdbarch.c, gdbarch.h: Regenerated. > * x86-64-linux-tdep.c (linux_sigtramp_code): Moved comment. > > Index: dwarf2cfi.c > =================================================================== > RCS file: /cvs/src/src/gdb/dwarf2cfi.c,v > retrieving revision 1.16 > diff -u -p -r1.16 dwarf2cfi.c > --- dwarf2cfi.c 19 Jul 2002 09:40:51 -0000 1.16 > +++ dwarf2cfi.c 16 Dec 2002 17:00:51 -0000 > @@ -32,57 +32,6 @@ > #include "dwarf2cfi.h" > #include "gdb_assert.h" > > -/* Common Information Entry - holds information that is shared among many > - Frame Descriptors. */ > -struct cie_unit > -{ > - /* Offset of this unit in .debug_frame or .eh_frame. */ > - ULONGEST offset; > - > - /* A null-terminated string that identifies the augmentation to this CIE or > - to the FDEs that use it. */ > - char *augmentation; > - > - /* A constant that is factored out of all advance location instructions. */ > - unsigned int code_align; > - > - /* A constant that is factored out of all offset instructions. */ > - int data_align; > - > - /* A constant that indicates which regiter represents the return address > - of a function. */ > - unsigned char ra; > - > - /* Indicates how addresses are encoded. */ > - unsigned char addr_encoding; > - > - /* Pointer and length of the cie program. */ > - char *data; > - unsigned int data_length; > - > - struct objfile *objfile; > - > - /* Next in chain. */ > - struct cie_unit *next; > -}; > - > -/* Frame Description Entry. */ > -struct fde_unit > -{ > - /* Address of the first location associated with this entry. */ > - CORE_ADDR initial_location; > - > - /* Length of program section described by this entry. */ > - CORE_ADDR address_range; > - > - /* Pointer to asociated CIE. */ > - struct cie_unit *cie_ptr; > - > - /* Pointer and length of the cie program. */ > - char *data; > - unsigned int data_length; > -}; > - > struct fde_array > { > struct fde_unit **array; > @@ -190,8 +139,8 @@ enum ptr_encoding > #define UNWIND_CONTEXT(fi) ((struct context *) (fi->context)) > \f > > -static struct cie_unit *cie_chunks; > -static struct fde_array fde_chunks; > +static struct cie_unit *cie_chunks = NULL; > +static struct fde_array fde_chunks = { 0 }; > /* Obstack for allocating temporary storage used during unwind operations. */ > static struct obstack unwind_tmp_obstack; > > @@ -839,6 +783,9 @@ frame_state_for (struct context *context > context->lsda = 0; > > fde = get_fde_for_addr (context->ra - 1); > + > + if (fde == NULL && DWARF2_CREATE_FDE_P ()) > + fde = DWARF2_CREATE_FDE (context->ra - 1); > > if (fde == NULL) > return; > @@ -1467,8 +1414,6 @@ parse_frame_info (struct objfile *objfil > cie->next = cie_chunks; > cie_chunks = cie; > > - cie->objfile = objfile; > - > cie->offset = unit_offset; > > start++; /* version */ > @@ -1952,3 +1897,28 @@ cfi_virtual_frame_pointer (CORE_ADDR pc, > > unwind_tmp_obstack_free (); > } > + > +void > +store_fde_unit (struct fde_unit *fde) > +{ > + if (fde) > + { > + fde_chunks_need_space (); > + fde_chunks.array[fde_chunks.elems++] = fde; > + > + qsort (fde_chunks.array, fde_chunks.elems, > + sizeof (struct fde_unit *), compare_fde_unit); > + > + } > + else > + error ("Dwarf2 CFI error: Attempt to store NULL pointer to FDE list!"); > +} > + > +void > +store_cie_unit (struct cie_unit *cie) > +{ > + cie->next = cie_chunks; > + cie_chunks = cie; > +} > + > + > Index: dwarf2cfi.h > =================================================================== > RCS file: /cvs/src/src/gdb/dwarf2cfi.h,v > retrieving revision 1.1 > diff -u -p -r1.1 dwarf2cfi.h > --- dwarf2cfi.h 7 Dec 2001 12:10:15 -0000 1.1 > +++ dwarf2cfi.h 16 Dec 2002 17:00:51 -0000 > @@ -22,6 +22,57 @@ > #ifndef DWARF2CFI_H > #define DWARF2CFI_H > > +/* Common Information Entry - holds information that is shared among many > + Frame Descriptors. */ > +struct cie_unit > +{ > + /* Offset of this unit in .debug_frame or .eh_frame. */ > + ULONGEST offset; > + > + /* A null-terminated string that identifies the augmentation to this CIE or > + to the FDEs that use it. */ > + char *augmentation; > + > + /* A constant that is factored out of all advance location instructions. */ > + unsigned int code_align; > + > + /* A constant that is factored out of all offset instructions. */ > + int data_align; > + > + /* A constant that indicates which regiter represents the return address > + of a function. */ > + unsigned char ra; > + > + /* Indicates how addresses are encoded. */ > + unsigned char addr_encoding; > + > + /* Pointer and length of the cie program. */ > + char *data; > + unsigned int data_length; > + > + struct objfile *objfile; > + > + /* Next in chain. */ > + struct cie_unit *next; > +}; > + > +/* Frame Description Entry. */ > +struct fde_unit > +{ > + /* Address of the first location associated with this entry. */ > + CORE_ADDR initial_location; > + > + /* Length of program section described by this entry. */ > + CORE_ADDR address_range; > + > + /* Pointer to asociated CIE. */ > + struct cie_unit *cie_ptr; > + > + /* Pointer and length of the cie program. */ > + char *data; > + unsigned int data_length; > +}; > + > /* Return the frame address. */ > CORE_ADDR cfi_read_fp (); > > @@ -62,5 +113,11 @@ void cfi_get_saved_register (char *raw_b > any frame pointer offsets. */ > void cfi_virtual_frame_pointer (CORE_ADDR pc, int *frame_regnum, > LONGEST * frame_offset); > + > +struct cie_unit *cie_unit_alloc (void); > +struct fde_unit *fde_unit_alloc (void); > + > +void store_cie_unit (struct cie_unit *); > +void store_fde_unit (struct fde_unit *); > > #endif > Index: gdbarch.c > =================================================================== > RCS file: /cvs/src/src/gdb/gdbarch.c,v > retrieving revision 1.146 > diff -u -p -r1.146 gdbarch.c > --- gdbarch.c 24 Aug 2002 00:21:34 -0000 1.146 > +++ gdbarch.c 16 Dec 2002 17:00:52 -0000 > @@ -263,6 +263,7 @@ struct gdbarch > gdbarch_in_function_epilogue_p_ftype *in_function_epilogue_p; > gdbarch_construct_inferior_arguments_ftype *construct_inferior_arguments; > gdbarch_dwarf2_build_frame_info_ftype *dwarf2_build_frame_info; > + gdbarch_dwarf2_create_fde_ftype *dwarf2_create_fde; > gdbarch_elf_make_msymbol_special_ftype *elf_make_msymbol_special; > gdbarch_coff_make_msymbol_special_ftype *coff_make_msymbol_special; > }; > @@ -419,6 +420,7 @@ struct gdbarch startup_gdbarch = > 0, > 0, > 0, > + 0, > /* startup_gdbarch() */ > }; > > @@ -789,6 +791,7 @@ verify_gdbarch (struct gdbarch *gdbarch) > /* Skip verify of in_function_epilogue_p, invalid_p == 0 */ > /* Skip verify of construct_inferior_arguments, invalid_p == 0 */ > /* Skip verify of dwarf2_build_frame_info, has predicate */ > + /* Skip verify of dwarf2_create_fde, has predicate */ > /* Skip verify of elf_make_msymbol_special, invalid_p == 0 */ > /* Skip verify of coff_make_msymbol_special, invalid_p == 0 */ > buf = ui_file_xstrdup (log, &dummy); > @@ -1113,6 +1116,17 @@ gdbarch_dump (struct gdbarch *gdbarch, s > (long) current_gdbarch->dwarf2_build_frame_info > /*DWARF2_BUILD_FRAME_INFO ()*/); > #endif > +#ifdef DWARF2_CREATE_FDE > + fprintf_unfiltered (file, > + "gdbarch_dump: %s # %s\n", > + "DWARF2_CREATE_FDE(pc)", > + XSTRING (DWARF2_CREATE_FDE (pc))); > + if (GDB_MULTI_ARCH) > + fprintf_unfiltered (file, > + "gdbarch_dump: DWARF2_CREATE_FDE = 0x%08lx\n", > + (long) current_gdbarch->dwarf2_create_fde > + /*DWARF2_CREATE_FDE ()*/); > +#endif > #ifdef DWARF2_REG_TO_REGNUM > fprintf_unfiltered (file, > "gdbarch_dump: %s # %s\n", > @@ -4842,6 +4856,32 @@ set_gdbarch_dwarf2_build_frame_info (str > gdbarch_dwarf2_build_frame_info_ftype dwarf2_build_frame_info) > { > gdbarch->dwarf2_build_frame_info = dwarf2_build_frame_info; > +} > + > +int > +gdbarch_dwarf2_create_fde_p (struct gdbarch *gdbarch) > +{ > + gdb_assert (gdbarch != NULL); > + return gdbarch->dwarf2_create_fde != 0; > +} > + > +struct fde_unit * > +gdbarch_dwarf2_create_fde (struct gdbarch *gdbarch, CORE_ADDR pc) > +{ > + gdb_assert (gdbarch != NULL); > + if (gdbarch->dwarf2_create_fde == 0) > + internal_error (__FILE__, __LINE__, > + "gdbarch: gdbarch_dwarf2_create_fde invalid"); > + if (gdbarch_debug >= 2) > + fprintf_unfiltered (gdb_stdlog, "gdbarch_dwarf2_create_fde called\n"); > + return gdbarch->dwarf2_create_fde (pc); > +} > + > +void > +set_gdbarch_dwarf2_create_fde (struct gdbarch *gdbarch, > + gdbarch_dwarf2_create_fde_ftype dwarf2_create_fde) > +{ > + gdbarch->dwarf2_create_fde = dwarf2_create_fde; > } > > void > Index: gdbarch.h > =================================================================== > RCS file: /cvs/src/src/gdb/gdbarch.h,v > retrieving revision 1.114 > diff -u -p -r1.114 gdbarch.h > --- gdbarch.h 24 Aug 2002 00:21:34 -0000 1.114 > +++ gdbarch.h 16 Dec 2002 17:00:52 -0000 > @@ -2449,6 +2449,43 @@ extern void set_gdbarch_dwarf2_build_fra > #endif > #endif > > +#if defined (DWARF2_CREATE_FDE) > +/* Legacy for systems yet to multi-arch DWARF2_CREATE_FDE */ > +#if !defined (DWARF2_CREATE_FDE_P) > +#define DWARF2_CREATE_FDE_P() (1) > +#endif > +#endif > + > +/* Default predicate for non- multi-arch targets. */ > +#if (!GDB_MULTI_ARCH) && !defined (DWARF2_CREATE_FDE_P) > +#define DWARF2_CREATE_FDE_P() (0) > +#endif > + > +extern int gdbarch_dwarf2_create_fde_p (struct gdbarch *gdbarch); > +#if (GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL) && defined (DWARF2_CREATE_FDE_P) > +#error "Non multi-arch definition of DWARF2_CREATE_FDE" > +#endif > +#if (GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL) || !defined (DWARF2_CREATE_FDE_P) > +#define DWARF2_CREATE_FDE_P() (gdbarch_dwarf2_create_fde_p (current_gdbarch)) > +#endif > + > +/* Default (function) for non- multi-arch platforms. */ > +#if (!GDB_MULTI_ARCH) && !defined (DWARF2_CREATE_FDE) > +#define DWARF2_CREATE_FDE(pc) (internal_error (__FILE__, __LINE__, "DWARF2_CREATE_FDE"), 0) > +#endif > + > +typedef struct fde_unit * (gdbarch_dwarf2_create_fde_ftype) (CORE_ADDR pc); > +extern struct fde_unit * gdbarch_dwarf2_create_fde (struct gdbarch *gdbarch, CORE_ADDR pc); > +extern void set_gdbarch_dwarf2_create_fde (struct gdbarch *gdbarch, gdbarch_dwarf2_create_fde_ftype *dwarf2_create_fde); > +#if (GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL) && defined (DWARF2_CREATE_FDE) > +#error "Non multi-arch definition of DWARF2_CREATE_FDE" > +#endif > +#if GDB_MULTI_ARCH > +#if (GDB_MULTI_ARCH > GDB_MULTI_ARCH_PARTIAL) || !defined (DWARF2_CREATE_FDE) > +#define DWARF2_CREATE_FDE(pc) (gdbarch_dwarf2_create_fde (current_gdbarch, pc)) > +#endif > +#endif > + > /* Default (function) for non- multi-arch platforms. */ > #if (!GDB_MULTI_ARCH) && !defined (ELF_MAKE_MSYMBOL_SPECIAL) > #define ELF_MAKE_MSYMBOL_SPECIAL(sym, msym) (default_elf_make_msymbol_special (sym, msym)) > Index: gdbarch.sh > =================================================================== > RCS file: /cvs/src/src/gdb/gdbarch.sh,v > retrieving revision 1.158.6.1 > diff -u -p -r1.158.6.1 gdbarch.sh > --- gdbarch.sh 20 Nov 2002 00:43:57 -0000 1.158.6.1 > +++ gdbarch.sh 16 Dec 2002 17:00:52 -0000 > @@ -656,6 +656,7 @@ m:::int:in_function_epilogue_p:CORE_ADDR > # ARGV is an array of strings, one per argument. > m::CONSTRUCT_INFERIOR_ARGUMENTS:char *:construct_inferior_arguments:int argc, char **argv:argc, argv:::construct_inferior_arguments::0 > F:2:DWARF2_BUILD_FRAME_INFO:void:dwarf2_build_frame_info:struct objfile *objfile:objfile:::0 > +F:2:DWARF2_CREATE_FDE:struct fde_unit *:dwarf2_create_fde:CORE_ADDR pc:pc:::0 > f:2:ELF_MAKE_MSYMBOL_SPECIAL:void:elf_make_msymbol_special:asymbol *sym, struct minimal_symbol *msym:sym, msym:::default_elf_make_msymbol_special::0 > f:2:COFF_MAKE_MSYMBOL_SPECIAL:void:coff_make_msymbol_special:int val, struct minimal_symbol *msym:val, msym:::default_coff_make_msymbol_special::0 > EOF > Index: x86-64-linux-tdep.c > =================================================================== > RCS file: /cvs/src/src/gdb/x86-64-linux-tdep.c,v > retrieving revision 1.5 > diff -u -p -r1.5 x86-64-linux-tdep.c > --- x86-64-linux-tdep.c 3 Sep 2002 13:06:33 -0000 1.5 > +++ x86-64-linux-tdep.c 16 Dec 2002 17:00:52 -0000 > @@ -35,8 +35,10 @@ > #define LINUX_SIGTRAMP_OFFSET1 (7) > > static const unsigned char linux_sigtramp_code[] = { > - LINUX_SIGTRAMP_INSN0, 0xc7, 0xc0, 0x89, 0x00, 0x00, 0x00, /* mov $0x89,%rax */ > - LINUX_SIGTRAMP_INSN1, 0x05 /* syscall */ > + /* mov $__NR_rt_sigreturn,%rax */ > + LINUX_SIGTRAMP_INSN0, 0xc7, 0xc0, 0x89, 0x00, 0x00, 0x00, > + /* syscall */ > + LINUX_SIGTRAMP_INSN1, 0x05 > }; > > #define LINUX_SIGTRAMP_LEN (sizeof linux_sigtramp_code) > Index: x86-64-tdep.c > =================================================================== > RCS file: /cvs/src/src/gdb/x86-64-tdep.c,v > retrieving revision 1.26 > diff -u -p -r1.26 x86-64-tdep.c > --- x86-64-tdep.c 24 Aug 2002 00:21:35 -0000 1.26 > +++ x86-64-tdep.c 16 Dec 2002 17:00:55 -0000 > @@ -850,11 +850,31 @@ x86_64_frameless_function_invocation (st > return 0; > } > > +/* We will handle only functions beginning with: > + 55 pushq %rbp > + 48 89 e5 movq %rsp,%rbp */ > +#define PROLOG_BUFSIZE 4 > +static int > +x86_64_function_has_prologue (CORE_ADDR pc) > +{ > + int i; > + unsigned char prolog_expect[PROLOG_BUFSIZE] = { 0x55, 0x48, 0x89, 0xe5 }, > + prolog_buf[PROLOG_BUFSIZE]; > + > + read_memory (pc, (char *) prolog_buf, PROLOG_BUFSIZE); > + > + /* First check, whether pc points to pushq %rbp, movq %rsp,%rbp. */ > + for (i = 0; i < PROLOG_BUFSIZE; i++) > + if (prolog_expect[i] != prolog_buf[i]) > + return 0; /* ... no, it doesn't. Nothing to skip. */ > + > + return 1; > +} > + > /* If a function with debugging information and known beginning > is detected, we will return pc of the next line in the source > code. With this approach we effectively skip the prolog. */ > > -#define PROLOG_BUFSIZE 4 > CORE_ADDR > x86_64_skip_prologue (CORE_ADDR pc) > { > @@ -863,19 +883,8 @@ x86_64_skip_prologue (CORE_ADDR pc) > struct symbol *v_function; > CORE_ADDR endaddr; > > - /* We will handle only functions beginning with: > - 55 pushq %rbp > - 48 89 e5 movq %rsp,%rbp > - */ > - unsigned char prolog_expect[PROLOG_BUFSIZE] = { 0x55, 0x48, 0x89, 0xe5 }, > - prolog_buf[PROLOG_BUFSIZE]; > - > - read_memory (pc, (char *) prolog_buf, PROLOG_BUFSIZE); > - > - /* First check, whether pc points to pushq %rbp, movq %rsp,%rbp. */ > - for (i = 0; i < PROLOG_BUFSIZE; i++) > - if (prolog_expect[i] != prolog_buf[i]) > - return pc; /* ... no, it doesn't. Nothing to skip. */ > + if (! x86_64_function_has_prologue (pc)) > + return pc; > > /* OK, we have found the prologue and want PC of the first > non-prologue instruction. */ > @@ -902,6 +911,175 @@ x86_64_skip_prologue (CORE_ADDR pc) > return pc; > } > > +static struct fde_unit * > +x86_64_dwarf2_create_fde (CORE_ADDR pc) > +{ > + struct fde_unit *fde; > + struct cie_unit *cie; > + struct obj_section *osection; > + CORE_ADDR loaddr, hiaddr; > + char *name; > + > + if (!find_pc_partial_function (pc, &name, &loaddr, &hiaddr)) > + return NULL; > + > + if (info_verbose) > + printf_filtered ("Dwarf2: Creating missing FDE for pc=%p (%s): ", > + (void*)pc, name); > + > + osection = find_pc_section(pc); > + if (! osection) > + return NULL; > + > + /* First create CIE */ > + cie = cie_unit_alloc (); > + > + cie->objfile = osection->objfile; > + cie->code_align = 1; > + cie->data_align = -8; > + cie->ra = 0x10; > + > + /* Now create FDE */ > + fde = fde_unit_alloc (); > + > + fde->initial_location = loaddr; > + fde->address_range = hiaddr - loaddr; > + fde->cie_ptr = cie; > + > + /* Now fill in data appropriate for a given function type. */ > + > + /* if (x86_64_linux_in_sigtramp (pc, name)) ... not yet implemented. */ > + if (x86_64_function_has_prologue (loaddr)) > + { > + /* CIE and FDE for functions that have a valid prologue... > + > + This is the sample function: > + .text > + sample_function: > + .LFB1: > + pushq %rbp > + .LCFI0: > + movq %rsp, %rbp > + .LCFI1: > + xor %rax, %rax > + leave > + ret > + .LFE1: > + > + This is the appropriate CIE: > + .section .debug_frame > + .Lframe0: > + .long .LECIE0-.LSCIE0 # Length of Common Information Entry > + .LSCIE0: > + .long 0xffffffff # CIE Identifier Tag > + .byte 0x1 # CIE Version > + .ascii "\0" # CIE Augmentation > + .uleb128 0x1 # CIE Code Alignment Factor > + .sleb128 -8 # CIE Data Alignment Factor > + .byte 0x10 # CIE RA Column > + .byte 0xc # DW_CFA_def_cfa > + .uleb128 0x7 > + .uleb128 0x8 > + .byte 0x90 # DW_CFA_offset, column 0x10 > + .uleb128 0x1 > + .align 8 > + .LECIE0: > + > + And the appropriate FDE: > + .LSFDE0: > + .long .LEFDE0-.LASFDE0 # FDE Length > + .LASFDE0: > + .long .Lframe0 # FDE CIE offset > + .quad .LFB1 # FDE initial location > + .quad .LFE1-.LFB1 # FDE address range > + .byte 0x4 # DW_CFA_advance_loc4 > + .long .LCFI0-.LFB1 # sizeof(pushq %rbp) = 1 > + .byte 0xe # DW_CFA_def_cfa_offset > + .uleb128 0x10 > + .byte 0x86 # DW_CFA_offset, column 0x6 > + .uleb128 0x2 > + .byte 0x4 # DW_CFA_advance_loc4 > + .long .LCFI1-.LCFI0 # sizeof(movq %rsp, %rbp) = 3 > + .byte 0xd # DW_CFA_def_cfa_register > + .uleb128 0x6 > + .align 8 > + .LEFDE0: > + */ > + static char ciedata[] = {0x0c, 0x07, 0x08, 0x90, 0x01, 0}; > + static char fdedata[] = {0x41, 0x0e, 0x10, 0x86, 0x02, > + 0x43, 0x0d, 0x06, 0}; > + > + if (info_verbose) > + printf_filtered ("with prologue\n"); > + > + cie->data = ciedata; > + cie->data_length = sizeof(ciedata); > + > + fde->data = fdedata; > + fde->data_length = sizeof(fdedata); > + } > + else > + { > + /* CIE and FDE for functions that don't touch stack: > + > + This is the sample function: > + .text > + sample_function: > + .LFB1: > + xor %rax, %rax > + ret > + .LFE1: > + > + This is CIE: > + .section .debug_frame > + .Lframe0: > + .long .LECIE0-.LSCIE0 # Length of Common Information Entry > + .LSCIE0: > + .long 0xffffffff # CIE Identifier Tag > + .byte 0x1 # CIE Version > + .ascii "\0" # CIE Augmentation > + .uleb128 0x1 # CIE Code Alignment Factor > + .sleb128 -8 # CIE Data Alignment Factor > + .byte 0x10 # CIE RA Column > + .byte 0xc # DW_CFA_def_cfa > + .uleb128 0x7 > + .uleb128 0x8 > + .byte 0x90 # DW_CFA_offset, column 0x10 > + .uleb128 0x1 > + .align 8 > + .LECIE0: > + > + And the appropriate FDE: > + .LSFDE0: > + .long .LEFDE0-.LASFDE0 # FDE Length > + .LASFDE0: > + .long .Lframe0 # FDE CIE offset > + .quad .LFB1 # FDE initial location > + .quad .LFE1-.LFB1 # FDE address range > + .align 8 # no instructions for CFA > + .LEFDE0: > + */ > + static char ciedata[] = {0x0c, 0x07, 0x08, 0x90, 0x01, 0}; > + static char fdedata[] = {0}; > + > + if (info_verbose) > + printf_filtered ("without prologue\n"); > + > + cie->data = ciedata; > + cie->data_length = sizeof(ciedata); > + > + fde->data = fdedata; > + fde->data_length = sizeof(fdedata); > + } > + > + /* Store both units for future use after > + they are filled up with values. */ > + store_fde_unit (fde); > + store_cie_unit (cie); > + > + return fde; > +} > + > /* Sequence of bytes for breakpoint instruction. */ > static unsigned char * > x86_64_breakpoint_from_pc (CORE_ADDR * pc, int *lenptr) > @@ -1121,6 +1299,7 @@ x86_64_gdbarch_init (struct gdbarch_info > /* Use dwarf2 debug frame informations. */ > set_gdbarch_dwarf2_build_frame_info (gdbarch, dwarf2_build_frame_info); > set_gdbarch_dwarf2_reg_to_regnum (gdbarch, x86_64_dwarf2_reg_to_regnum); > + set_gdbarch_dwarf2_create_fde (gdbarch, x86_64_dwarf2_create_fde); > > return gdbarch; > } > Index: x86-64-tdep.h > =================================================================== > RCS file: /cvs/src/src/gdb/x86-64-tdep.h,v > retrieving revision 1.5 > diff -u -p -r1.5 x86-64-tdep.h > --- x86-64-tdep.h 20 Jun 2002 13:08:12 -0000 1.5 > +++ x86-64-tdep.h 16 Dec 2002 17:00:55 -0000 > @@ -31,8 +31,8 @@ extern int x86_64_num_gregs; > int x86_64_register_number (const char *name); > const char *x86_64_register_name (int reg_nr); > > - > gdbarch_frame_saved_pc_ftype x86_64_linux_frame_saved_pc; > gdbarch_saved_pc_after_call_ftype x86_64_linux_saved_pc_after_call; > +int x86_64_function_has_prologue (CORE_ADDR pc); > > #endif > Index: doc/gdbint.texinfo > =================================================================== > RCS file: /cvs/src/src/gdb/doc/gdbint.texinfo,v > retrieving revision 1.100 > diff -u -p -r1.100 gdbint.texinfo > --- doc/gdbint.texinfo 24 Aug 2002 00:21:37 -0000 1.100 > +++ doc/gdbint.texinfo 16 Dec 2002 13:29:18 -0000 > @@ -3249,6 +3249,16 @@ automatically. Thus, since the offset f > its first instruction is two bytes, @code{FUNCTION_START_OFFSET} would > be 2 on the VAX. > > +@item DWARF2_CREATE_FDE (@var{pc}) > +@findex DWARF2_CREATE_FDE > +This function is called from Dwarf2 CFI engine, when there is no FDE > +found for a given @var{pc}. It should create a new valid FDE > +(along with the corresponding CIE) regarding to the type of the function > +to which @var{pc} belongs and join these two structures to @var{cie_chunks} > +and @var{fde_chunks} respectively. If the FDE can't be created return > +@code{NULL}, otherwise a pointer to the newly created @code{struct fde_unit} > +is returned. > + > @item GCC_COMPILED_FLAG_SYMBOL > @itemx GCC2_COMPILED_FLAG_SYMBOL > @findex GCC2_COMPILED_FLAG_SYMBOL -- Daniel Jacobowitz MontaVista Software Debian GNU/Linux Developer ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [RFA] Artifical dwarf2 debug info 2002-12-16 9:27 ` Michal Ludvig 2002-12-16 9:54 ` Daniel Jacobowitz @ 2002-12-16 10:38 ` Eli Zaretskii 2002-12-20 8:43 ` Michal Ludvig 1 sibling, 1 reply; 33+ messages in thread From: Eli Zaretskii @ 2002-12-16 10:38 UTC (permalink / raw) To: mludvig; +Cc: drow, gdb-patches > Date: Mon, 16 Dec 2002 18:25:29 +0100 > From: Michal Ludvig <mludvig@suse.cz> > > OK, added two new functions: store_fde_unit and store_cie_unit. > > Now only functions for allocation and functions for storing new units > are exported. > > Do you like it more, now? :-) The doco part is approved, thanks. However, I have one question: is the term "FDE" explained anywhere else in the manual (sorry, I cannot find out myself where I'm typing this)? If not, perhaps we should say a few words about what an FDE is. ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [RFA] Artifical dwarf2 debug info 2002-12-16 10:38 ` Eli Zaretskii @ 2002-12-20 8:43 ` Michal Ludvig 2002-12-20 10:51 ` Eli Zaretskii 0 siblings, 1 reply; 33+ messages in thread From: Michal Ludvig @ 2002-12-20 8:43 UTC (permalink / raw) To: Eli Zaretskii; +Cc: gdb-patches Eli Zaretskii wrote: >>Date: Mon, 16 Dec 2002 18:25:29 +0100 >>From: Michal Ludvig <mludvig@suse.cz> >> >>OK, added two new functions: store_fde_unit and store_cie_unit. >> >>Now only functions for allocation and functions for storing new units >>are exported. >> >>Do you like it more, now? :-) > > > The doco part is approved, thanks. However, I have one question: is > the term "FDE" explained anywhere else in the manual (sorry, I cannot > find out myself where I'm typing this)? If not, perhaps we should say > a few words about what an FDE is. FDE (Frame description entry) and CIE (common information entry) are abbrevs used in Dwarf2 unwinding. Basically each function should have an appropriate FDE that contains information about how to unwind from the given function. CIE contains information common for several FDEs. Where in the doco should I write this very brief description? Michal Ludvig -- * SuSE CR, s.r.o * mludvig@suse.cz * (+420) 296.545.373 * http://www.suse.cz ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [RFA] Artifical dwarf2 debug info 2002-12-20 8:43 ` Michal Ludvig @ 2002-12-20 10:51 ` Eli Zaretskii 0 siblings, 0 replies; 33+ messages in thread From: Eli Zaretskii @ 2002-12-20 10:51 UTC (permalink / raw) To: mludvig; +Cc: gdb-patches > Date: Fri, 20 Dec 2002 15:50:02 +0100 > From: Michal Ludvig <mludvig@suse.cz> > > FDE (Frame description entry) and CIE (common information entry) are > abbrevs used in Dwarf2 unwinding. > Basically each function should have an appropriate FDE that contains > information about how to unwind from the given function. CIE contains > information common for several FDEs. > Where in the doco should I write this very brief description? I suggest to put this right where you mention the terms for the first time. If you feel that the explanations take you too far from the main subject, you could make this text a @footnote. Thanks. ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [RFA] Artifical dwarf2 debug info 2002-12-14 17:31 [RFA] Artifical dwarf2 debug info Michal Ludvig 2002-12-14 22:53 ` Eli Zaretskii 2002-12-15 11:03 ` Daniel Jacobowitz @ 2002-12-16 9:25 ` Andrew Cagney 2002-12-16 9:40 ` Daniel Jacobowitz 2002-12-16 9:46 ` Michal Ludvig 2 siblings, 2 replies; 33+ messages in thread From: Andrew Cagney @ 2002-12-16 9:25 UTC (permalink / raw) To: Michal Ludvig; +Cc: GDB Patches > Hi all, > this long patch provides a fix for a very annoying fact, that GDB on x86-64 can't do backtraces from hand-optimized assembler functions (that applies for example to glibc's memset, str*, etc as well as to syscall wrappers). > This is caused by the lack of a valid debug_frame/eh_frame FDE entry for such a function (noone really writes .debug_frame section in his assembler code :-) > > My approach to fix this behaviour is based on the fortunate fact, that most of those affected glibc's functions don't touch the stack at all, so creating an artifical FDE for them is easy. If I understand this correctly, you've created create dwarf2cfi info for a function that has no such info. That way the dwarf2cfi code can unwind a function that doesn't actually have CFI? If that is the case then I don't think this is either necessary or correct. A `struct frame_info' allows frame specific unwind functions - at present only dummy-frame and saved-regs-frame versions are implemented, however the next ones to implement are cfi-frame (unwind using CFI info) and regs-frame (unwind using the register cache). For your problem, wouldn't it be better to, instead of creating fake CFI info, implement custom frame unwind functions that handle your case? Andrew ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [RFA] Artifical dwarf2 debug info 2002-12-16 9:25 ` Andrew Cagney @ 2002-12-16 9:40 ` Daniel Jacobowitz 2002-12-16 10:04 ` Andrew Cagney 2002-12-16 9:46 ` Michal Ludvig 1 sibling, 1 reply; 33+ messages in thread From: Daniel Jacobowitz @ 2002-12-16 9:40 UTC (permalink / raw) To: Andrew Cagney; +Cc: Michal Ludvig, GDB Patches On Mon, Dec 16, 2002 at 12:02:57PM -0500, Andrew Cagney wrote: > >Hi all, > >this long patch provides a fix for a very annoying fact, that GDB on > >x86-64 can't do backtraces from hand-optimized assembler functions (that > >applies for example to glibc's memset, str*, etc as well as to syscall > >wrappers). > >This is caused by the lack of a valid debug_frame/eh_frame FDE entry for > >such a function (noone really writes .debug_frame section in his assembler > >code :-) > > > >My approach to fix this behaviour is based on the fortunate fact, that > >most of those affected glibc's functions don't touch the stack at all, so > >creating an artifical FDE for them is easy. > > If I understand this correctly, you've created create dwarf2cfi info for > a function that has no such info. That way the dwarf2cfi code can > unwind a function that doesn't actually have CFI? That's right. > If that is the case then I don't think this is either necessary or > correct. A `struct frame_info' allows frame specific unwind functions - > at present only dummy-frame and saved-regs-frame versions are > implemented, however the next ones to implement are cfi-frame (unwind > using CFI info) and regs-frame (unwind using the register cache). > > For your problem, wouldn't it be better to, instead of creating fake CFI > info, implement custom frame unwind functions that handle your case? Hrm. What do you mean by regs-frame? If it's for the current frame wouldn't that be a frame which just doesn't unwind? As for this situation, and the similar one for i386... there are three unwind functions, to find the previous frame's registers, ID, and PC. For this case we just want to express a normal function call which saves no registers; pretty easy. But for i386 I'll want to express something which initially pushes a register, and then does some work, pops it, and does more work before returning. There's plenty of ways to express that but it seems to me that the most useful one would be to have essentially a glorified prologue reader which builds that description. Then the machinery to handle that description is - you guessed it - a standard CFI reader. It might be nice to someday split up the CFI parser and executer so that we could provide the description less obtusely, but I'd hate to see us duplicate the machinery. BTW, /* See description above. The previous frame's resume address. Save the previous PC in a local cache. */ frame_pc_unwind_ftype *pc_unwind; /* See description above. The previous frame's resume address. Save the previous PC in a local cache. */ frame_id_unwind_ftype *id_unwind; Second comment is a past-o? -- Daniel Jacobowitz MontaVista Software Debian GNU/Linux Developer ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [RFA] Artifical dwarf2 debug info 2002-12-16 9:40 ` Daniel Jacobowitz @ 2002-12-16 10:04 ` Andrew Cagney 2002-12-16 10:17 ` Daniel Jacobowitz 0 siblings, 1 reply; 33+ messages in thread From: Andrew Cagney @ 2002-12-16 10:04 UTC (permalink / raw) To: Daniel Jacobowitz; +Cc: Michal Ludvig, GDB Patches > That's right. > > >> If that is the case then I don't think this is either necessary or >> correct. A `struct frame_info' allows frame specific unwind functions - >> at present only dummy-frame and saved-regs-frame versions are >> implemented, however the next ones to implement are cfi-frame (unwind >> using CFI info) and regs-frame (unwind using the register cache). >> >> For your problem, wouldn't it be better to, instead of creating fake CFI >> info, implement custom frame unwind functions that handle your case? > > > Hrm. What do you mean by regs-frame? If it's for the current frame > wouldn't that be a frame which just doesn't unwind? A frame that gets the saved registers from the register cache. As for uses: - an inner-most frame that for some reason doesn't unwind (i.e., create_new_frame() barfs). - the frame that is inner to `current frame'. > As for this situation, and the similar one for i386... there are three > unwind functions, to find the previous frame's registers, ID, and PC. > For this case we just want to express a normal function call which > saves no registers; pretty easy. But for i386 I'll want to express > something which initially pushes a register, and then does some work, > pops it, and does more work before returning. So you're proposing that the saved-regs code be used to generate a cfi description as well? Interesting. Andrew > There's plenty of ways to express that but it seems to me that the most > useful one would be to have essentially a glorified prologue reader > which builds that description. Then the machinery to handle that > description is - you guessed it - a standard CFI reader. It might be > nice to someday split up the CFI parser and executer so that we could > provide the description less obtusely, but I'd hate to see us duplicate > the machinery. > BTW, > /* See description above. The previous frame's resume address. > Save the previous PC in a local cache. */ > frame_pc_unwind_ftype *pc_unwind; > > /* See description above. The previous frame's resume address. > Save the previous PC in a local cache. */ > frame_id_unwind_ftype *id_unwind; > > Second comment is a past-o? Thanks. Andrew ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [RFA] Artifical dwarf2 debug info 2002-12-16 10:04 ` Andrew Cagney @ 2002-12-16 10:17 ` Daniel Jacobowitz 2002-12-16 10:56 ` Andrew Cagney 0 siblings, 1 reply; 33+ messages in thread From: Daniel Jacobowitz @ 2002-12-16 10:17 UTC (permalink / raw) To: Andrew Cagney; +Cc: Michal Ludvig, GDB Patches On Mon, Dec 16, 2002 at 01:00:57PM -0500, Andrew Cagney wrote: > > >That's right. > > > > > >>If that is the case then I don't think this is either necessary or > >>correct. A `struct frame_info' allows frame specific unwind functions - > >>at present only dummy-frame and saved-regs-frame versions are > >>implemented, however the next ones to implement are cfi-frame (unwind > >>using CFI info) and regs-frame (unwind using the register cache). > >> > >>For your problem, wouldn't it be better to, instead of creating fake CFI > >>info, implement custom frame unwind functions that handle your case? > > > > > >Hrm. What do you mean by regs-frame? If it's for the current frame > >wouldn't that be a frame which just doesn't unwind? > > A frame that gets the saved registers from the register cache. As for uses: > - an inner-most frame that for some reason doesn't unwind (i.e., > create_new_frame() barfs). > - the frame that is inner to `current frame'. I'm confused again :) "Current frame" is one which does not unwind, right? No saved PC, no saved registers. The concepts are meaningless. Its frame ID corresponds (very) loosely to the current stack pointer. This would be frame #0 in a backtrace. There's nothing inside of it. Or are you saying that the innermost frame is this special regs-frame, and the current frame (still #0) is outside of that? OK, that jives with some things I remember you describing earlier. Makes sense now. I don't see what you mean by "doesn't unwind", since we always start with having the current frame (i.e. there would be at least two) but I think I'm back on your page again. > >As for this situation, and the similar one for i386... there are three > >unwind functions, to find the previous frame's registers, ID, and PC. > >For this case we just want to express a normal function call which > >saves no registers; pretty easy. But for i386 I'll want to express > >something which initially pushes a register, and then does some work, > >pops it, and does more work before returning. > > So you're proposing that the saved-regs code be used to generate a cfi > description as well? > > Interesting. Precisely. When given a function without enough information to backtrace through it in the debug info, the prologue scanner could implement this new method in order to provide backtraces. It could really clear up some messes. I think it's a promising idea. -- Daniel Jacobowitz MontaVista Software Debian GNU/Linux Developer ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [RFA] Artifical dwarf2 debug info 2002-12-16 10:17 ` Daniel Jacobowitz @ 2002-12-16 10:56 ` Andrew Cagney 2002-12-16 11:13 ` Daniel Jacobowitz 0 siblings, 1 reply; 33+ messages in thread From: Andrew Cagney @ 2002-12-16 10:56 UTC (permalink / raw) To: Daniel Jacobowitz; +Cc: Michal Ludvig, GDB Patches >> A frame that gets the saved registers from the register cache. As for uses: >> - an inner-most frame that for some reason doesn't unwind (i.e., >> create_new_frame() barfs). >> - the frame that is inner to `current frame'. > > > I'm confused again :) > > "Current frame" is one which does not unwind, right? No saved PC, no > saved registers. The concepts are meaningless. Its frame ID > corresponds (very) loosely to the current stack pointer. This would be > frame #0 in a backtrace. There's nothing inside of it. The, in theory, operation: frame_register_unwind (get_next_frame (get_current_frame()), ...) however, they wouldn't be implemented that way. I'm sitting on patch that shows this working. The operation: frame_id_unwind (get_next_frame (current_frame), ...) frame_pc_unwind (get_next_frame (current_frame), ...) are, unfortunatly, more complicated. At their core is DECR_PC_AFTER_BREAK (and why I've not posted that patch). > Or are you saying that the innermost frame is this special regs-frame, > and the current frame (still #0) is outside of that? OK, that jives > with some things I remember you describing earlier. Makes sense now. > > I don't see what you mean by "doesn't unwind", since we always start > with having the current frame (i.e. there would be at least two) but I > think I'm back on your page again. INIT_FRAME_EXTRA_INFO() can throw an error. For instance, due to an attempt to read from an address specified by PC/FP/SP when that address is invalid. For such cases, there should still be a current frame (so that `info registers' works) but it shouldn't unwind any further. So again, yes, you'll end up with current-frame -> regs-frame. >> >As for this situation, and the similar one for i386... there are three >> >unwind functions, to find the previous frame's registers, ID, and PC. >> >For this case we just want to express a normal function call which >> >saves no registers; pretty easy. But for i386 I'll want to express >> >something which initially pushes a register, and then does some work, >> >pops it, and does more work before returning. > >> >> So you're proposing that the saved-regs code be used to generate a cfi >> description as well? >> >> Interesting. > > > Precisely. When given a function without enough information to > backtrace through it in the debug info, the prologue scanner could > implement this new method in order to provide backtraces. It could > really clear up some messes. > > I think it's a promising idea. Need to figure out how/were this should tie into the rest of the frame structure. The CFI code is not exactly integrated into the mainstream. Here, the key function is get_prev_frame() where GDB first unwinds the PC and then uses that to determine what is needed to unwind/create the rest of the frame. It could easily read: if (pc in dummy-frame) create dummy frame; else if (pc in cfi frame) create cfi frame; else if (pc in something else) create some other frame; or even: while (frame in known unwind types) if (frame and pc match) return create that frame; that is, a target will support a number of frame types, each identified using the PC. Andrew ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [RFA] Artifical dwarf2 debug info 2002-12-16 10:56 ` Andrew Cagney @ 2002-12-16 11:13 ` Daniel Jacobowitz 2002-12-16 11:34 ` Andrew Cagney 0 siblings, 1 reply; 33+ messages in thread From: Daniel Jacobowitz @ 2002-12-16 11:13 UTC (permalink / raw) To: Andrew Cagney; +Cc: Michal Ludvig, GDB Patches On Mon, Dec 16, 2002 at 01:43:25PM -0500, Andrew Cagney wrote: > INIT_FRAME_EXTRA_INFO() can throw an error. For instance, due to an > attempt to read from an address specified by PC/FP/SP when that address > is invalid. For such cases, there should still be a current frame (so > that `info registers' works) but it shouldn't unwind any further. > > So again, yes, you'll end up with current-frame -> regs-frame. OK, I follow you now. Hmm... > >>>As for this situation, and the similar one for i386... there are three > >>>unwind functions, to find the previous frame's registers, ID, and PC. > >>>For this case we just want to express a normal function call which > >>>saves no registers; pretty easy. But for i386 I'll want to express > >>>something which initially pushes a register, and then does some work, > >>>pops it, and does more work before returning. > > > >> > >>So you're proposing that the saved-regs code be used to generate a cfi > >>description as well? > >> > >>Interesting. > > > > > >Precisely. When given a function without enough information to > >backtrace through it in the debug info, the prologue scanner could > >implement this new method in order to provide backtraces. It could > >really clear up some messes. > > > >I think it's a promising idea. > > Need to figure out how/were this should tie into the rest of the frame > structure. The CFI code is not exactly integrated into the mainstream. > > Here, the key function is get_prev_frame() where GDB first unwinds the > PC and then uses that to determine what is needed to unwind/create the > rest of the frame. It could easily read: > > if (pc in dummy-frame) > create dummy frame; > else if (pc in cfi frame) > create cfi frame; > else if (pc in something else) > create some other frame; > > or even: > > while (frame in known unwind types) > if (frame and pc match) > return create that frame; > > that is, a target will support a number of frame types, each identified > using the PC. If I'm scanning this code correctly, all we would need to do would be to connect set_unwind_by_pc to the CFI machinery. No, it's more complicated than that, we still call both FRAME_CHAIN and frame_pc_unwind; I'm not entirely clear on how frame_saved_regs_id_unwind works. Similarly in get_prev_frame. But what I'd like to see is something like you've sketched above. Probably check first for dummy frame, then for sigtramp frame, then for CFI frame, and then fall back to the defaults. -- Daniel Jacobowitz MontaVista Software Debian GNU/Linux Developer ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [RFA] Artifical dwarf2 debug info 2002-12-16 11:13 ` Daniel Jacobowitz @ 2002-12-16 11:34 ` Andrew Cagney 2002-12-16 11:57 ` Daniel Jacobowitz 0 siblings, 1 reply; 33+ messages in thread From: Andrew Cagney @ 2002-12-16 11:34 UTC (permalink / raw) To: Daniel Jacobowitz; +Cc: Michal Ludvig, GDB Patches >> >> Need to figure out how/were this should tie into the rest of the frame >> structure. The CFI code is not exactly integrated into the mainstream. >> >> Here, the key function is get_prev_frame() where GDB first unwinds the >> PC and then uses that to determine what is needed to unwind/create the >> rest of the frame. It could easily read: >> >> if (pc in dummy-frame) >> create dummy frame; >> else if (pc in cfi frame) >> create cfi frame; >> else if (pc in something else) >> create some other frame; >> >> or even: >> >> while (frame in known unwind types) >> if (frame and pc match) >> return create that frame; >> >> that is, a target will support a number of frame types, each identified >> using the PC. > > > If I'm scanning this code correctly, all we would need to do would be > to connect set_unwind_by_pc to the CFI machinery. No, it's more > complicated than that, we still call both FRAME_CHAIN and frame_pc_unwind; > I'm not entirely clear on how frame_saved_regs_id_unwind works. > Similarly in get_prev_frame. FRAME_CHAIN is going away. The steps are broadly: pc = pc-unwind (next_frame) if (not an edge case like dummy frame where the id doesn't need to be unwound because the frame can be identified using the callee's ID) id = id-unwind (next_frame); create frame from pc/id setting new unwind methods using pc. (frame_saved_regs_id_unwind is there to keep code that just implements frame chain working.). > But what I'd like to see is something like you've sketched above. > Probably check first for dummy frame, then for sigtramp frame, then for > CFI frame, and then fall back to the defaults. Yes. Should the choices/order be hardwired or specified by the architecture though? I.e., iterate over a list of possible frames that are specified by the architecture. The catch is that it needs to unwind the PC before anything else. That way it can correctly set the type. Like I said, patch for that pending. Andrew ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [RFA] Artifical dwarf2 debug info 2002-12-16 11:34 ` Andrew Cagney @ 2002-12-16 11:57 ` Daniel Jacobowitz 2002-12-16 12:10 ` Andrew Cagney 0 siblings, 1 reply; 33+ messages in thread From: Daniel Jacobowitz @ 2002-12-16 11:57 UTC (permalink / raw) To: Andrew Cagney; +Cc: Michal Ludvig, GDB Patches On Mon, Dec 16, 2002 at 02:25:15PM -0500, Andrew Cagney wrote: > > >> > >>Need to figure out how/were this should tie into the rest of the frame > >>structure. The CFI code is not exactly integrated into the mainstream. > >> > >>Here, the key function is get_prev_frame() where GDB first unwinds the > >>PC and then uses that to determine what is needed to unwind/create the > >>rest of the frame. It could easily read: > >> > >> if (pc in dummy-frame) > >> create dummy frame; > >> else if (pc in cfi frame) > >> create cfi frame; > >> else if (pc in something else) > >> create some other frame; > >> > >>or even: > >> > >> while (frame in known unwind types) > >> if (frame and pc match) > >> return create that frame; > >> > >>that is, a target will support a number of frame types, each identified > >>using the PC. > > > > > >If I'm scanning this code correctly, all we would need to do would be > >to connect set_unwind_by_pc to the CFI machinery. No, it's more > >complicated than that, we still call both FRAME_CHAIN and frame_pc_unwind; > >I'm not entirely clear on how frame_saved_regs_id_unwind works. > >Similarly in get_prev_frame. > > FRAME_CHAIN is going away. > > The steps are broadly: > pc = pc-unwind (next_frame) > if (not an edge case like dummy frame where the id doesn't need to > be unwound because the frame can be identified using the callee's ID) > id = id-unwind (next_frame); > create frame from pc/id setting new unwind methods using pc. > (frame_saved_regs_id_unwind is there to keep code that just implements > frame chain working.). Great! > >But what I'd like to see is something like you've sketched above. > >Probably check first for dummy frame, then for sigtramp frame, then for > >CFI frame, and then fall back to the defaults. > > Yes. Should the choices/order be hardwired or specified by the > architecture though? I.e., iterate over a list of possible frames that > are specified by the architecture. Hmm, I'm not sure. Do we have any architectures that would want to specify their own frame types? In such a way that using this CFI approach wouldn't suffice? > The catch is that it needs to unwind the PC before anything else. That > way it can correctly set the type. Like I said, patch for that pending. Right. I really appreciate all your cleanups in this area. I have some work to do on FRAME_CHAIN_VALID but I'll sit on it for a while, until I see what this looks like when you're done revamping the unwinders. (That's the backtrace-to-or-through-main conversation from some months ago.) Back to the patch at the beginning of this thread - do you think this view of fake CFI information is feasible? Any comments on Michal's patch? -- Daniel Jacobowitz MontaVista Software Debian GNU/Linux Developer ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [RFA] Artifical dwarf2 debug info 2002-12-16 11:57 ` Daniel Jacobowitz @ 2002-12-16 12:10 ` Andrew Cagney 2002-12-16 12:42 ` Daniel Jacobowitz 0 siblings, 1 reply; 33+ messages in thread From: Andrew Cagney @ 2002-12-16 12:10 UTC (permalink / raw) To: Daniel Jacobowitz; +Cc: Michal Ludvig, GDB Patches >> >If I'm scanning this code correctly, all we would need to do would be >> >to connect set_unwind_by_pc to the CFI machinery. No, it's more >> >complicated than that, we still call both FRAME_CHAIN and frame_pc_unwind; >> >I'm not entirely clear on how frame_saved_regs_id_unwind works. >> >Similarly in get_prev_frame. > >> >> FRAME_CHAIN is going away. >> >> The steps are broadly: >> pc = pc-unwind (next_frame) >> if (not an edge case like dummy frame where the id doesn't need to >> be unwound because the frame can be identified using the callee's ID) >> id = id-unwind (next_frame); >> create frame from pc/id setting new unwind methods using pc. >> (frame_saved_regs_id_unwind is there to keep code that just implements >> frame chain working.). > > > Great! > > >> >But what I'd like to see is something like you've sketched above. >> >Probably check first for dummy frame, then for sigtramp frame, then for >> >CFI frame, and then fall back to the defaults. > >> >> Yes. Should the choices/order be hardwired or specified by the >> architecture though? I.e., iterate over a list of possible frames that >> are specified by the architecture. > > > Hmm, I'm not sure. Do we have any architectures that would want to > specify their own frame types? In such a way that using this CFI > approach wouldn't suffice? Well, I'd not want to be the one enabling CFI on all architectures. That code needs some serious cleanups. As for own frame types, a SIGTRAMP frames are one case. >> The catch is that it needs to unwind the PC before anything else. That >> way it can correctly set the type. Like I said, patch for that pending. > > > Right. I really appreciate all your cleanups in this area. I have > some work to do on FRAME_CHAIN_VALID but I'll sit on it for a while, > until I see what this looks like when you're done revamping the > unwinders. (That's the backtrace-to-or-through-main conversation from > some months ago.) > > Back to the patch at the beginning of this thread - do you think this > view of fake CFI information is feasible? Any comments on Michal's > patch? It's feasible. It may long term solve another problem. Apparently GDB needs to generate, at run time, debug info for things like Java. It may also be easier to handle this case by implementing direct functions and not going via CFI. That actual code, though, is a mess. It is adding another edge case to code that shouldn't have to handle anything at all. BTW, exactly is the difference between a prologueless and frameless function? The prologue case appears to be checking for a push -> the reverse of frameless. Andrew ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [RFA] Artifical dwarf2 debug info 2002-12-16 12:10 ` Andrew Cagney @ 2002-12-16 12:42 ` Daniel Jacobowitz 2002-12-17 6:23 ` Michal Ludvig 0 siblings, 1 reply; 33+ messages in thread From: Daniel Jacobowitz @ 2002-12-16 12:42 UTC (permalink / raw) To: Andrew Cagney; +Cc: Michal Ludvig, GDB Patches On Mon, Dec 16, 2002 at 02:56:55PM -0500, Andrew Cagney wrote: > > >>>If I'm scanning this code correctly, all we would need to do would be > >>>to connect set_unwind_by_pc to the CFI machinery. No, it's more > >>>complicated than that, we still call both FRAME_CHAIN and > >>frame_pc_unwind; > >>>I'm not entirely clear on how frame_saved_regs_id_unwind works. > >>>Similarly in get_prev_frame. > > > >> > >>FRAME_CHAIN is going away. > >> > >>The steps are broadly: > >> pc = pc-unwind (next_frame) > >> if (not an edge case like dummy frame where the id doesn't need to > >> be unwound because the frame can be identified using the callee's ID) > >> id = id-unwind (next_frame); > >> create frame from pc/id setting new unwind methods using pc. > >>(frame_saved_regs_id_unwind is there to keep code that just implements > >>frame chain working.). > > > > > >Great! > > > > > >>>But what I'd like to see is something like you've sketched above. > >>>Probably check first for dummy frame, then for sigtramp frame, then for > >>>CFI frame, and then fall back to the defaults. > > > >> > >>Yes. Should the choices/order be hardwired or specified by the > >>architecture though? I.e., iterate over a list of possible frames that > >>are specified by the architecture. > > > > > >Hmm, I'm not sure. Do we have any architectures that would want to > >specify their own frame types? In such a way that using this CFI > >approach wouldn't suffice? > > Well, I'd not want to be the one enabling CFI on all architectures. > That code needs some serious cleanups. Yes. I'd like to start turning this on for other architectures, and I suspect it'll come on for i386 when Mark K. really gets his teeth into bringing that together with the x86-64 port. Hopefully it will clean up over time. > As for own frame types, a SIGTRAMP frames are one case. Hmm, good point, that could be handled by an architecture-dependent list of frame types. > >>The catch is that it needs to unwind the PC before anything else. That > >>way it can correctly set the type. Like I said, patch for that pending. > > > > > >Right. I really appreciate all your cleanups in this area. I have > >some work to do on FRAME_CHAIN_VALID but I'll sit on it for a while, > >until I see what this looks like when you're done revamping the > >unwinders. (That's the backtrace-to-or-through-main conversation from > >some months ago.) > > > >Back to the patch at the beginning of this thread - do you think this > >view of fake CFI information is feasible? Any comments on Michal's > >patch? > > It's feasible. It may long term solve another problem. Apparently GDB > needs to generate, at run time, debug info for things like Java. It may > also be easier to handle this case by implementing direct functions and > not going via CFI. > > That actual code, though, is a mess. It is adding another edge case to > code that shouldn't have to handle anything at all. Where's the case you're concerned about - are you refering to code in the tdep file or in dwarf2cfi.c? > BTW, exactly is the difference between a prologueless and frameless > function? The prologue case appears to be checking for a push -> the > reverse of frameless. The patch doesn't talk about frameless functions particularly - it checks for _has_prologue, and generates an FDE based on whether it does or not... -- Daniel Jacobowitz MontaVista Software Debian GNU/Linux Developer ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [RFA] Artifical dwarf2 debug info 2002-12-16 12:42 ` Daniel Jacobowitz @ 2002-12-17 6:23 ` Michal Ludvig 2002-12-17 6:28 ` Andrew Cagney 0 siblings, 1 reply; 33+ messages in thread From: Michal Ludvig @ 2002-12-17 6:23 UTC (permalink / raw) To: Daniel Jacobowitz; +Cc: Andrew Cagney, GDB Patches Ehm ... what's the result regarding to my patch, guys? Michal Ludvig -- * SuSE CR, s.r.o * mludvig@suse.cz * (+420) 296.545.373 * http://www.suse.cz ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [RFA] Artifical dwarf2 debug info 2002-12-17 6:23 ` Michal Ludvig @ 2002-12-17 6:28 ` Andrew Cagney 2002-12-17 8:42 ` Daniel Jacobowitz 0 siblings, 1 reply; 33+ messages in thread From: Andrew Cagney @ 2002-12-17 6:28 UTC (permalink / raw) To: Michal Ludvig; +Cc: Daniel Jacobowitz, GDB Patches > Ehm ... what's the result regarding to my patch, guys? I think pending changes for the most part render the cornerstone of this patch obsolete. This is because the dwarf2cfi code wont't be called when the frame doesn't have dwarf2 info -> the case that this code is trying to handle. The idea of being able to create debug info at run time, though, is very much worth persuing. Andrew ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [RFA] Artifical dwarf2 debug info 2002-12-17 6:28 ` Andrew Cagney @ 2002-12-17 8:42 ` Daniel Jacobowitz 2002-12-18 4:39 ` Andrew Cagney 0 siblings, 1 reply; 33+ messages in thread From: Daniel Jacobowitz @ 2002-12-17 8:42 UTC (permalink / raw) To: Andrew Cagney; +Cc: Michal Ludvig, GDB Patches On Tue, Dec 17, 2002 at 09:23:15AM -0500, Andrew Cagney wrote: > >Ehm ... what's the result regarding to my patch, guys? > > I think pending changes for the most part render the cornerstone of this > patch obsolete. This is because the dwarf2cfi code wont't be called > when the frame doesn't have dwarf2 info -> the case that this code is > trying to handle. > > The idea of being able to create debug info at run time, though, is very > much worth persuing. Eh, I don't agree at all. We'll be calling a function to figure out if the affected PC value has CFI information. Where's that function going to live? In the CFI reader presumably, and it would be the appropriate time to construct fake debug info. I think that Michal's patch would look substantively the same after these pending changes. -- Daniel Jacobowitz MontaVista Software Debian GNU/Linux Developer ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [RFA] Artifical dwarf2 debug info 2002-12-17 8:42 ` Daniel Jacobowitz @ 2002-12-18 4:39 ` Andrew Cagney 2002-12-18 10:05 ` Daniel Jacobowitz 0 siblings, 1 reply; 33+ messages in thread From: Andrew Cagney @ 2002-12-18 4:39 UTC (permalink / raw) To: Daniel Jacobowitz; +Cc: Michal Ludvig, GDB Patches > On Tue, Dec 17, 2002 at 09:23:15AM -0500, Andrew Cagney wrote: > >> >Ehm ... what's the result regarding to my patch, guys? > >> >> I think pending changes for the most part render the cornerstone of this >> patch obsolete. This is because the dwarf2cfi code wont't be called >> when the frame doesn't have dwarf2 info -> the case that this code is >> trying to handle. >> >> The idea of being able to create debug info at run time, though, is very >> much worth persuing. > > > Eh, I don't agree at all. We'll be calling a function to figure out if > the affected PC value has CFI information. Where's that function going > to live? In the CFI reader presumably, and it would be the appropriate > time to construct fake debug info. > > I think that Michal's patch would look substantively the same after > these pending changes. Not bits like this (michael, is this actually separate and how does it compare to the code identifying a frameless function?) > CORE_ADDR > x86_64_skip_prologue (CORE_ADDR pc) > { > @@ -863,19 +883,8 @@ x86_64_skip_prologue (CORE_ADDR pc) > struct symbol *v_function; > CORE_ADDR endaddr; > > - /* We will handle only functions beginning with: > - 55 pushq %rbp > - 48 89 e5 movq %rsp,%rbp > - */ > - unsigned char prolog_expect[PROLOG_BUFSIZE] = { 0x55, 0x48, 0x89, 0xe5 }, > - prolog_buf[PROLOG_BUFSIZE]; > - > - read_memory (pc, (char *) prolog_buf, PROLOG_BUFSIZE); > - > - /* First check, whether pc points to pushq %rbp, movq %rsp,%rbp. */ > - for (i = 0; i < PROLOG_BUFSIZE; i++) > - if (prolog_expect[i] != prolog_buf[i]) > - return pc; /* ... no, it doesn't. Nothing to skip. */ > + if (! x86_64_function_has_prologue (pc)) > + return pc; And I don't think this would be used either. Instead the decision to create the FDE would have been made earlier. > @@ -839,6 +785,9 @@ frame_state_for (struct context *context > context->lsda = 0; > > fde = get_fde_for_addr (context->ra - 1); > + > + if (fde == NULL) > + fde = guess_generic_fde (context->ra - 1); > > if (fde == NULL) > return; However, the code masaging would likely be the same, yes. Andrew (hmm, bet that context->ra - 1 should be frame_address_in_block (fi)) ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [RFA] Artifical dwarf2 debug info 2002-12-18 4:39 ` Andrew Cagney @ 2002-12-18 10:05 ` Daniel Jacobowitz 2003-01-02 20:54 ` Andrew Cagney 0 siblings, 1 reply; 33+ messages in thread From: Daniel Jacobowitz @ 2002-12-18 10:05 UTC (permalink / raw) To: Andrew Cagney; +Cc: Michal Ludvig, GDB Patches On Wed, Dec 18, 2002 at 11:11:39AM +0000, Andrew Cagney wrote: > >On Tue, Dec 17, 2002 at 09:23:15AM -0500, Andrew Cagney wrote: > > > >>>Ehm ... what's the result regarding to my patch, guys? > > > >> > >>I think pending changes for the most part render the cornerstone of this > >>patch obsolete. This is because the dwarf2cfi code wont't be called > >>when the frame doesn't have dwarf2 info -> the case that this code is > >>trying to handle. > >> > >>The idea of being able to create debug info at run time, though, is very > >>much worth persuing. > > > > > >Eh, I don't agree at all. We'll be calling a function to figure out if > >the affected PC value has CFI information. Where's that function going > >to live? In the CFI reader presumably, and it would be the appropriate > >time to construct fake debug info. > > > >I think that Michal's patch would look substantively the same after > >these pending changes. > > Not bits like this (michael, is this actually separate and how does it > compare to the code identifying a frameless function?) > > > CORE_ADDR > > x86_64_skip_prologue (CORE_ADDR pc) > > { > >@@ -863,19 +883,8 @@ x86_64_skip_prologue (CORE_ADDR pc) > > struct symbol *v_function; > > CORE_ADDR endaddr; > > > >- /* We will handle only functions beginning with: > >- 55 pushq %rbp > >- 48 89 e5 movq %rsp,%rbp > >- */ > >- unsigned char prolog_expect[PROLOG_BUFSIZE] = { 0x55, 0x48, 0x89, 0xe5 > >}, > >- prolog_buf[PROLOG_BUFSIZE]; > >- > >- read_memory (pc, (char *) prolog_buf, PROLOG_BUFSIZE); > >- > >- /* First check, whether pc points to pushq %rbp, movq %rsp,%rbp. */ > >- for (i = 0; i < PROLOG_BUFSIZE; i++) > >- if (prolog_expect[i] != prolog_buf[i]) > >- return pc; /* ... no, it doesn't. Nothing to skip. */ > >+ if (! x86_64_function_has_prologue (pc)) > >+ return pc; > > And I don't think this would be used either. Instead the decision to > create the FDE would have been made earlier. That's just code factoring - he broke x86_64_function_has_prologue out of x86_64_skip_prologue. Or am I missing your point? You're right, some bits would change. How pending are the other frame changes - are they really worth him waiting for? (In respone to "what's the fire" - I know how annoying it is to have to shelve something and pick it up when you've completely lost the train of thought that produced it...) > >@@ -839,6 +785,9 @@ frame_state_for (struct context *context > > context->lsda = 0; > > > > fde = get_fde_for_addr (context->ra - 1); > >+ > >+ if (fde == NULL) > >+ fde = guess_generic_fde (context->ra - 1); > > > > if (fde == NULL) > > return; > > However, the code masaging would likely be the same, yes. > > Andrew > > (hmm, bet that context->ra - 1 should be frame_address_in_block (fi)) Probably, but do we have the right frame at that point? Answer is apparently no. It means the same thing though. -- Daniel Jacobowitz MontaVista Software Debian GNU/Linux Developer ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [RFA] Artifical dwarf2 debug info 2002-12-18 10:05 ` Daniel Jacobowitz @ 2003-01-02 20:54 ` Andrew Cagney 2003-01-02 21:19 ` Daniel Jacobowitz 0 siblings, 1 reply; 33+ messages in thread From: Andrew Cagney @ 2003-01-02 20:54 UTC (permalink / raw) To: Daniel Jacobowitz, Michal Ludvig; +Cc: GDB Patches fde = get_fde_for_addr (context->ra - 1); > >+ > >+ if (fde == NULL) > >+ fde = guess_generic_fde (context->ra - 1); > > > > if (fde == NULL) > > return; Just to be clear. The above is the change that I think is wrong. Instead of this function `guessing' the source of the FDE, the code needs to be re-structured so that the caller always supplies a pre-created FDE. That way a dwarf2 cfi frame can call the above function with an FDE built from the object files debug info, while an artifical frame can call it with an artifically created FDE. There is no guessing involved. -- This is part of a long standing problem - it predates dwarf2cf by many years. Instead of using recursion, people modify debug/target dependent frame code so that it attempts to directly handle all cases. Cf all the PC_IN_CALL_DUMMY(frame->next), PC_IN_SIGTRAMP(frame->next) and other tests scattered through out the -tdep.c code; and the calls to get_next_frame() in dwarf2cfi.c. Andrew ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [RFA] Artifical dwarf2 debug info 2003-01-02 20:54 ` Andrew Cagney @ 2003-01-02 21:19 ` Daniel Jacobowitz 2003-01-02 23:05 ` Andrew Cagney 0 siblings, 1 reply; 33+ messages in thread From: Daniel Jacobowitz @ 2003-01-02 21:19 UTC (permalink / raw) To: Andrew Cagney; +Cc: Michal Ludvig, GDB Patches On Thu, Jan 02, 2003 at 08:54:33PM +0000, Andrew Cagney wrote: > fde = get_fde_for_addr (context->ra - 1); > > >+ > > >+ if (fde == NULL) > > >+ fde = guess_generic_fde (context->ra - 1); > > > > > > if (fde == NULL) > > > return; > > Just to be clear. The above is the change that I think is wrong. > > Instead of this function `guessing' the source of the FDE, the code > needs to be re-structured so that the caller always supplies a > pre-created FDE. > > That way a dwarf2 cfi frame can call the above function with an FDE > built from the object files debug info, while an artifical frame can > call it with an artifically created FDE. There is no guessing involved. Hold a second here; I don't think we're really communicating on what this change is supposed to do. Look at where that code is: it's in frame_state_for. Its inputs are a CONTEXT and FS (struct frame_state *). The first line in your quote is: fde = get_fde_for_addr (context->ra - 1); I just don't understand what you mean by "the caller supplies an FDE"; this is where we locate the FDE. The caller's got no business knowing what an FDE is. This new mechanism is supposed to handled any code which doesn't have a defined FDE, for which an architecutre-specific (yes) hook can deduce the appropriate FDE from code inspection. These are not "artificial frames". We've got four types of frames that we've been talking about recently: - the magical register frame/inner frame - dummy frames - sigtramp frames - "normal" stack frames caused by compiled code calling other compiled code Maybe there will be others, but notice that all the above are conceptually different kinds of things. These "artifical" frames are just normal frames, where we synthesize the debug information because we didn't have any. It's a mechanism to coalesce things like prologue readers. It is absolutely not a new type of frame. That's why I think this code is in exactly the right place, right now. Are you saying that the CFI code should just be returning, saying "no idea, go away, don't talk to me", and leaving this be? That's all well and good but that way we end up duplicating the whole of the CFI reader. A good long term direction, with appropriate code factoring, but it's hardly practical. > This is part of a long standing problem - it predates dwarf2cf by many > years. Instead of using recursion, people modify debug/target dependent > frame code so that it attempts to directly handle all cases. Cf all the > PC_IN_CALL_DUMMY(frame->next), PC_IN_SIGTRAMP(frame->next) and other > tests scattered through out the -tdep.c code; and the calls to > get_next_frame() in dwarf2cfi.c. The one call to get_next_frame, which parallels init_frame_pc_default. -- Daniel Jacobowitz MontaVista Software Debian GNU/Linux Developer ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [RFA] Artifical dwarf2 debug info 2003-01-02 21:19 ` Daniel Jacobowitz @ 2003-01-02 23:05 ` Andrew Cagney 2003-01-02 23:27 ` Daniel Jacobowitz 0 siblings, 1 reply; 33+ messages in thread From: Andrew Cagney @ 2003-01-02 23:05 UTC (permalink / raw) To: Daniel Jacobowitz; +Cc: Michal Ludvig, GDB Patches > On Thu, Jan 02, 2003 at 08:54:33PM +0000, Andrew Cagney wrote: > >> fde = get_fde_for_addr (context->ra - 1); > >> > >+ >> > >+ if (fde == NULL) >> > >+ fde = guess_generic_fde (context->ra - 1); >> > > >> > > if (fde == NULL) >> > > return; > >> >> Just to be clear. The above is the change that I think is wrong. >> >> Instead of this function `guessing' the source of the FDE, the code >> needs to be re-structured so that the caller always supplies a >> pre-created FDE. >> >> That way a dwarf2 cfi frame can call the above function with an FDE >> built from the object files debug info, while an artifical frame can >> call it with an artifically created FDE. There is no guessing involved. > > > Hold a second here; I don't think we're really communicating on what > this change is supposed to do. Look at where that code is: it's in > frame_state_for. Its inputs are a CONTEXT and FS (struct frame_state > *). The first line in your quote is: > fde = get_fde_for_addr (context->ra - 1); Right. That gets removed. Instead that info gets passed to the CFI code as a `parameter' (perhaphs explicitly, or perhaps implicitly as part of a member of the CONTEXT object). > I just don't understand what you mean by "the caller supplies an FDE"; > this is where we locate the FDE. The caller's got no business knowing > what an FDE is. This new mechanism is supposed to handled any code > which doesn't have a defined FDE, for which an architecutre-specific > (yes) hook can deduce the appropriate FDE from code inspection. > These are not "artificial frames". We've got four types of frames that > we've been talking about recently: [`artificial frame' was a poor choice of name - a real frame that uses artifically created dwarf2 debug info] > - the magical register frame/inner frame > - dummy frames > - sigtramp frames > - "normal" stack frames caused by compiled code calling other > compiled code The latter can be further broken down into: dwarf2 fde / cfi frames saved-register frames artifical fde / cfi frames ... > Maybe there will be others, but notice that all the above are > conceptually different kinds of things. These "artifical" frames are > just normal frames, where we synthesize the debug information because > we didn't have any. It's a mechanism to coalesce things like prologue > readers. It is absolutely not a new type of frame. > > That's why I think this code is in exactly the right place, right now. > Are you saying that the CFI code should just be returning, saying "no > idea, go away, don't talk to me", and leaving this be? Why was the dwarf2cfi code even called? Since there is no dwarf2 cfi that code path should not have been reached. Per my comment below, this would have happend because the caller (or something up the stack) failed to check for an edge condition. That change is patching things up after the event. Instead, during `struct frame_info' creation, if there isn't any dwarf2 info, and the architecture really wants to use the dwarf2cfi logic, it should create an `artifical fde / cfi frame' that first fakes up the FDE info and then supplies that to the dwarf2cfi logic. Similarly, a dwarf2 cfi frame can first read the fde and then call the relevant code. > That's all well > and good but that way we end up duplicating the whole of the CFI > reader. A good long term direction, with appropriate code factoring, > but it's hardly practical. How does this result in the duplication of the CFI reader? >> This is part of a long standing problem - it predates dwarf2cf by many >> years. Instead of using recursion, people modify debug/target dependent >> frame code so that it attempts to directly handle all cases. Cf all the >> PC_IN_CALL_DUMMY(frame->next), PC_IN_SIGTRAMP(frame->next) and other >> tests scattered through out the -tdep.c code; and the calls to >> get_next_frame() in dwarf2cfi.c. > > > The one call to get_next_frame, which parallels init_frame_pc_default. Right. And init_frame_pc_default() is, again, typical of the problem. It shouldn't need to refer to frame->next. Andrew ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [RFA] Artifical dwarf2 debug info 2003-01-02 23:05 ` Andrew Cagney @ 2003-01-02 23:27 ` Daniel Jacobowitz 2003-01-03 0:28 ` Andrew Cagney 0 siblings, 1 reply; 33+ messages in thread From: Daniel Jacobowitz @ 2003-01-02 23:27 UTC (permalink / raw) To: Andrew Cagney; +Cc: Michal Ludvig, GDB Patches On Thu, Jan 02, 2003 at 11:05:37PM +0000, Andrew Cagney wrote: > >On Thu, Jan 02, 2003 at 08:54:33PM +0000, Andrew Cagney wrote: > > > >> fde = get_fde_for_addr (context->ra - 1); > > > >>> >+ > >>> >+ if (fde == NULL) > >>> >+ fde = guess_generic_fde (context->ra - 1); > >>> > > >>> > if (fde == NULL) > >>> > return; > > > >> > >>Just to be clear. The above is the change that I think is wrong. > >> > >>Instead of this function `guessing' the source of the FDE, the code > >>needs to be re-structured so that the caller always supplies a > >>pre-created FDE. > >> > >>That way a dwarf2 cfi frame can call the above function with an FDE > >>built from the object files debug info, while an artifical frame can > >>call it with an artifically created FDE. There is no guessing involved. > > > > > >Hold a second here; I don't think we're really communicating on what > >this change is supposed to do. Look at where that code is: it's in > >frame_state_for. Its inputs are a CONTEXT and FS (struct frame_state > >*). The first line in your quote is: > > fde = get_fde_for_addr (context->ra - 1); > > Right. That gets removed. Instead that info gets passed to the CFI > code as a `parameter' (perhaphs explicitly, or perhaps implicitly as > part of a member of the CONTEXT object). This I don't get at all. Why? What advantage is there? Whose business besides the CFI reader's is it whether or not there is an FDE? > The latter can be further broken down into: > > dwarf2 fde / cfi frames > saved-register frames > artifical fde / cfi frames > ... I still don't see the point of this distinction. What differentiates a saved-register frame from a dwarf2 fde / cfi frame, anyway? There are saved registers; we figure out where they are via CFI. > >Maybe there will be others, but notice that all the above are > >conceptually different kinds of things. These "artifical" frames are > >just normal frames, where we synthesize the debug information because > >we didn't have any. It's a mechanism to coalesce things like prologue > >readers. It is absolutely not a new type of frame. > > > >That's why I think this code is in exactly the right place, right now. > >Are you saying that the CFI code should just be returning, saying "no > >idea, go away, don't talk to me", and leaving this be? > > Why was the dwarf2cfi code even called? Since there is no dwarf2 cfi > that code path should not have been reached. Per my comment below, this > would have happend because the caller (or something up the stack) failed > to check for an edge condition. That change is patching things up after > the event. > > Instead, during `struct frame_info' creation, if there isn't any dwarf2 > info, and the architecture really wants to use the dwarf2cfi logic, it > should create an `artifical fde / cfi frame' that first fakes up the FDE > info and then supplies that to the dwarf2cfi logic. Similarly, a dwarf2 > cfi frame can first read the fde and then call the relevant code. It sounds to me as if you want to move the call to the frame creation logic somewhere else and that's it. The place you want to move it doesn't exist yet, as far as I can tell. Am I right? > > That's all well > > and good but that way we end up duplicating the whole of the CFI > > reader. A good long term direction, with appropriate code factoring, > > but it's hardly practical. > > How does this result in the duplication of the CFI reader? The entire CFA program execution and unwind logic would be exactly identical to that of the "artificial frame" case. > >>This is part of a long standing problem - it predates dwarf2cf by many > >>years. Instead of using recursion, people modify debug/target dependent > >>frame code so that it attempts to directly handle all cases. Cf all the > >>PC_IN_CALL_DUMMY(frame->next), PC_IN_SIGTRAMP(frame->next) and other > >>tests scattered through out the -tdep.c code; and the calls to > >>get_next_frame() in dwarf2cfi.c. > > > > > >The one call to get_next_frame, which parallels init_frame_pc_default. > > Right. And init_frame_pc_default() is, again, typical of the problem. > It shouldn't need to refer to frame->next. I can't claim to understand how that would work. -- Daniel Jacobowitz MontaVista Software Debian GNU/Linux Developer ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [RFA] Artifical dwarf2 debug info 2003-01-02 23:27 ` Daniel Jacobowitz @ 2003-01-03 0:28 ` Andrew Cagney 0 siblings, 0 replies; 33+ messages in thread From: Andrew Cagney @ 2003-01-03 0:28 UTC (permalink / raw) To: Daniel Jacobowitz; +Cc: Michal Ludvig, GDB Patches >> Right. That gets removed. Instead that info gets passed to the CFI >> code as a `parameter' (perhaphs explicitly, or perhaps implicitly as >> part of a member of the CONTEXT object). > > > This I don't get at all. Why? What advantage is there? Whose > business besides the CFI reader's is it whether or not there is an FDE? The logic that makes the decision to use dwarf2 cfi, the dwarf2 like unwind code, or this artificial info, or even the old style saved-regs. That logic lives in get_prev_frame(). Why should the dwarf2 unwind et.al. code assume that the info it needs is comming from the dwarf2 reader? I thought the point of the change was that the dwarf2 cfi reader from all the code that uses that information - hence allowing us to fake up dwarf2 info. >> The latter can be further broken down into: >> >> dwarf2 fde / cfi frames >> saved-register frames >> artifical fde / cfi frames >> ... > > > I still don't see the point of this distinction. What differentiates a > saved-register frame from a dwarf2 fde / cfi frame, anyway? There are > saved registers; we figure out where they are via CFI. A saved-registers frame uses the existing code (frame->saved_regs) to locate a saved register. It doesn't read dwarf2 debug info and then use that to do CFI. CFI is just one of a number of ways to unwind a normal frame. >> >Maybe there will be others, but notice that all the above are >> >conceptually different kinds of things. These "artifical" frames are >> >just normal frames, where we synthesize the debug information because >> >we didn't have any. It's a mechanism to coalesce things like prologue >> >readers. It is absolutely not a new type of frame. >> > >> >That's why I think this code is in exactly the right place, right now. >> >Are you saying that the CFI code should just be returning, saying "no >> >idea, go away, don't talk to me", and leaving this be? > >> >> Why was the dwarf2cfi code even called? Since there is no dwarf2 cfi >> that code path should not have been reached. Per my comment below, this >> would have happend because the caller (or something up the stack) failed >> to check for an edge condition. That change is patching things up after >> the event. >> >> Instead, during `struct frame_info' creation, if there isn't any dwarf2 >> info, and the architecture really wants to use the dwarf2cfi logic, it >> should create an `artifical fde / cfi frame' that first fakes up the FDE >> info and then supplies that to the dwarf2cfi logic. Similarly, a dwarf2 >> cfi frame can first read the fde and then call the relevant code. > > > It sounds to me as if you want to move the call to the frame creation > logic somewhere else and that's it. The place you want to move it > doesn't exist yet, as far as I can tell. Am I right? The `struct frame_info' creation logic lives in frame.c - see get_prev_frame(). It hasn't moved but is being expanded. Only problem is with the x86-64. That code is trying to locally handle cases that are better handled by get_prev_frame(). Again, note all those pc_in_call_dummy() et.al. tests? >> > That's all well >> > and good but that way we end up duplicating the whole of the CFI >> > reader. A good long term direction, with appropriate code factoring, >> > but it's hardly practical. > >> >> How does this result in the duplication of the CFI reader? > > > The entire CFA program execution and unwind logic would be exactly > identical to that of the "artificial frame" case. And hence wouldn't / shouldn't be duplicated. >> >>This is part of a long standing problem - it predates dwarf2cf by many >> >>years. Instead of using recursion, people modify debug/target dependent >> >>frame code so that it attempts to directly handle all cases. Cf all the >> >>PC_IN_CALL_DUMMY(frame->next), PC_IN_SIGTRAMP(frame->next) and other >> >>tests scattered through out the -tdep.c code; and the calls to >> >>get_next_frame() in dwarf2cfi.c. > >> > >> > >> >The one call to get_next_frame, which parallels init_frame_pc_default. > >> >> Right. And init_frame_pc_default() is, again, typical of the problem. >> It shouldn't need to refer to frame->next. > > > I can't claim to understand how that would work. Separate functions would handle separate cases. Andrew ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [RFA] Artifical dwarf2 debug info 2002-12-16 9:25 ` Andrew Cagney 2002-12-16 9:40 ` Daniel Jacobowitz @ 2002-12-16 9:46 ` Michal Ludvig 2002-12-16 9:57 ` Andrew Cagney 1 sibling, 1 reply; 33+ messages in thread From: Michal Ludvig @ 2002-12-16 9:46 UTC (permalink / raw) To: Andrew Cagney; +Cc: GDB Patches Andrew Cagney wrote: > If I understand this correctly, you've created create dwarf2cfi info for > a function that has no such info. That way the dwarf2cfi code can > unwind a function that doesn't actually have CFI? Yes. > If that is the case then I don't think this is either necessary or > correct. A `struct frame_info' allows frame specific unwind functions - > at present only dummy-frame and saved-regs-frame versions are > implemented, however the next ones to implement are cfi-frame (unwind > using CFI info) and regs-frame (unwind using the register cache). I think cfi_frame_chain() does what you expect from cfi-frame unwinding function. However it is useless if you have no CFI info ;-) And that's the goal of my patch - provide a CFI when there are none and continue as if it was there for ages. > For your problem, wouldn't it be better to, instead of creating fake CFI > info, implement custom frame unwind functions that handle your case? There is a lot of different cases (functions with and without prologue, functions allocating some space on the stack, signal trampolines, etc.), and each one of would need to have a special handler. My approach seems to be more general to me (only one more function per architecture and several sets of data). And no, it wouldn't be better to do it a different way, because this way it's already written and verified that it works ;-) Michal Ludvig -- * SuSE CR, s.r.o * mludvig@suse.cz * (+420) 296.545.373 * http://www.suse.cz ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [RFA] Artifical dwarf2 debug info 2002-12-16 9:46 ` Michal Ludvig @ 2002-12-16 9:57 ` Andrew Cagney 2002-12-16 10:01 ` Michal Ludvig 0 siblings, 1 reply; 33+ messages in thread From: Andrew Cagney @ 2002-12-16 9:57 UTC (permalink / raw) To: Michal Ludvig; +Cc: GDB Patches > Andrew Cagney wrote: > If I understand this correctly, you've created create dwarf2cfi info for a function that has no such info. That way the dwarf2cfi code can unwind a function that doesn't actually have CFI? > > Yes. > >> If that is the case then I don't think this is either necessary or correct. A `struct frame_info' allows frame specific unwind functions - at present only dummy-frame and saved-regs-frame versions are implemented, however the next ones to implement are cfi-frame (unwind using CFI info) and regs-frame (unwind using the register cache). > > I think cfi_frame_chain() does what you expect from cfi-frame unwinding function. However it is useless if you have no CFI info ;-) And that's the goal of my patch - provide a CFI when there are none and continue as if it was there for ages. cfi_frame_chain() is currently being replaced by frame->id_unwind(). > For your problem, wouldn't it be better to, instead of creating fake CFI info, implement custom frame unwind functions that handle your case? > > There is a lot of different cases (functions with and without prologue, functions allocating some space on the stack, signal trampolines, etc.), and each one of would need to have a special handler. My approach seems to be more general to me (only one more function per architecture and several sets of data). And no, it wouldn't be better to do it a different way, because this way it's already written and verified that it works ;-) Andrew ^ permalink raw reply [flat|nested] 33+ messages in thread
* Re: [RFA] Artifical dwarf2 debug info 2002-12-16 9:57 ` Andrew Cagney @ 2002-12-16 10:01 ` Michal Ludvig 0 siblings, 0 replies; 33+ messages in thread From: Michal Ludvig @ 2002-12-16 10:01 UTC (permalink / raw) To: Andrew Cagney; +Cc: GDB Patches Andrew Cagney wrote: >> I think cfi_frame_chain() does what you expect from cfi-frame >> unwinding function. However it is useless if you have no CFI info ;-) >> And that's the goal of my patch - provide a CFI when there are none >> and continue as if it was there for ages. > > cfi_frame_chain() is currently being replaced by frame->id_unwind(). Hmm, I haven't followed mainline for a while, but ... does this change something regarding to my patch? Or can I apply it? (preferred option :-) Michal Ludvig -- * SuSE CR, s.r.o * mludvig@suse.cz * (+420) 296.545.373 * http://www.suse.cz ^ permalink raw reply [flat|nested] 33+ messages in thread
end of thread, other threads:[~2003-01-03 0:28 UTC | newest] Thread overview: 33+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2002-12-14 17:31 [RFA] Artifical dwarf2 debug info Michal Ludvig 2002-12-14 22:53 ` Eli Zaretskii 2002-12-15 11:03 ` Daniel Jacobowitz 2002-12-16 7:28 ` Michal Ludvig 2002-12-16 7:49 ` Daniel Jacobowitz 2002-12-16 9:27 ` Michal Ludvig 2002-12-16 9:54 ` Daniel Jacobowitz 2002-12-16 10:38 ` Eli Zaretskii 2002-12-20 8:43 ` Michal Ludvig 2002-12-20 10:51 ` Eli Zaretskii 2002-12-16 9:25 ` Andrew Cagney 2002-12-16 9:40 ` Daniel Jacobowitz 2002-12-16 10:04 ` Andrew Cagney 2002-12-16 10:17 ` Daniel Jacobowitz 2002-12-16 10:56 ` Andrew Cagney 2002-12-16 11:13 ` Daniel Jacobowitz 2002-12-16 11:34 ` Andrew Cagney 2002-12-16 11:57 ` Daniel Jacobowitz 2002-12-16 12:10 ` Andrew Cagney 2002-12-16 12:42 ` Daniel Jacobowitz 2002-12-17 6:23 ` Michal Ludvig 2002-12-17 6:28 ` Andrew Cagney 2002-12-17 8:42 ` Daniel Jacobowitz 2002-12-18 4:39 ` Andrew Cagney 2002-12-18 10:05 ` Daniel Jacobowitz 2003-01-02 20:54 ` Andrew Cagney 2003-01-02 21:19 ` Daniel Jacobowitz 2003-01-02 23:05 ` Andrew Cagney 2003-01-02 23:27 ` Daniel Jacobowitz 2003-01-03 0:28 ` Andrew Cagney 2002-12-16 9:46 ` Michal Ludvig 2002-12-16 9:57 ` Andrew Cagney 2002-12-16 10:01 ` Michal Ludvig
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox