This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

skip __main


Hi all, Pierre,

Here's the much smaller patch I mentioned at gdb@.

This version is about as small as it can get.  First the
prologue is analysed and skipped, then line info is used
to get at the first line of user code in the function.  If
the function is called "main" (humm, I shall move that into
the callback, as I believe the place where __main/__gccmain
is emitted is configurable on the gcc side), call a gdbarch
method that skips the __main call.  Works OK as long as nothing
is scheduled into before the __main call.  That means that it
should work OK at -O0, which is enough for fixing the
runto_main problems in the testsuite.  Then again,
debugging code with .stabs debug info at anything but -O0
is not pleasant anyway.

Last time I looked at the results, it uncovered other
more serious problems, so it was a win just for that fact.

I'm starting an overnight testrun on Cygwin, as the
last time I did that was a couple of months back.

Any comments?  Suggestions for a better gdbarch
callback name?

--
Pedro Alves
2007-10-13  Pedro Alves  <pedro_alves@portugalmail.pt>

	* gdbarch.sh (gdbarch_skip___main_call): New.
	* gdbarch.h, gdbarch.c: Regenerate.

	* i386-tdep.h (i386_skip___main_call): Declare.
	* i386-tdep.c (i386_skip___main_call): New.
	* i386-cygwin-tdep.c (i386_cygwin_init_abi): Register
	i386_skip___main_call as gdbarch_skip___main_call gdbarch
	callback.
	* symtab.c (find_function_start_sal): When pc points at the "main"
	function, call gdbarch_skip___main_call.

---
 gdb/gdbarch.c          |   33 +++++++++++++++++++++++++++++++++
 gdb/gdbarch.h          |    6 ++++++
 gdb/gdbarch.sh         |    1 +
 gdb/i386-cygwin-tdep.c |    2 ++
 gdb/i386-tdep.c        |   27 +++++++++++++++++++++++++++
 gdb/i386-tdep.h        |    1 +
 gdb/symtab.c           |   15 +++++++++++++++
 7 files changed, 85 insertions(+)

Index: src/gdb/i386-tdep.c
===================================================================
--- src.orig/gdb/i386-tdep.c	2008-01-29 04:39:24.000000000 +0000
+++ src/gdb/i386-tdep.c	2008-01-29 04:39:40.000000000 +0000
@@ -949,6 +949,33 @@ i386_skip_prologue (struct gdbarch *gdba
   return pc;
 }
 
+/* Check that the code pointed to by PC corresponds to a call to
+   __main, skip it if so.  Return PC otherwise.  */
+
+CORE_ADDR
+i386_skip___main_call (struct gdbarch *gdbarch, CORE_ADDR pc)
+{
+  gdb_byte op;
+
+  read_memory_nobpt (pc, &op, 1);
+  if (op == 0xe8)
+    {
+      gdb_byte buf[4];
+      if (target_read_memory (pc + 1, buf, sizeof buf) == 0)
+ 	{
+ 	  CORE_ADDR call_dest = pc + 5 + extract_unsigned_integer (buf, 4);
+
+ 	  struct minimal_symbol *s = lookup_minimal_symbol_by_pc (call_dest);
+ 	  if (s != NULL
+ 	      && SYMBOL_LINKAGE_NAME (s) != NULL
+ 	      && strcmp (SYMBOL_LINKAGE_NAME (s), "__main") == 0)
+ 	    pc += 5;
+ 	}
+    }
+
+  return pc;
+}
+
 /* This function is 64-bit safe.  */
 
 static CORE_ADDR
Index: src/gdb/gdbarch.c
===================================================================
--- src.orig/gdb/gdbarch.c	2008-01-29 04:39:16.000000000 +0000
+++ src/gdb/gdbarch.c	2008-01-29 04:39:40.000000000 +0000
@@ -184,6 +184,7 @@ struct gdbarch
   gdbarch_integer_to_address_ftype *integer_to_address;
   gdbarch_return_value_ftype *return_value;
   gdbarch_skip_prologue_ftype *skip_prologue;
+  gdbarch_skip___main_call_ftype *skip___main_call;
   gdbarch_inner_than_ftype *inner_than;
   gdbarch_breakpoint_from_pc_ftype *breakpoint_from_pc;
   gdbarch_adjust_breakpoint_address_ftype *adjust_breakpoint_address;
@@ -306,6 +307,7 @@ struct gdbarch startup_gdbarch =
   0,  /* integer_to_address */
   0,  /* return_value */
   0,  /* skip_prologue */
+  0,  /* skip___main_call */
   0,  /* inner_than */
   0,  /* breakpoint_from_pc */
   0,  /* adjust_breakpoint_address */
@@ -542,6 +544,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
   /* Skip verify of return_value, has predicate */
   if (gdbarch->skip_prologue == 0)
     fprintf_unfiltered (log, "\n\tskip_prologue");
+  /* Skip verify of skip___main_call, has predicate */
   if (gdbarch->inner_than == 0)
     fprintf_unfiltered (log, "\n\tinner_than");
   if (gdbarch->breakpoint_from_pc == 0)
@@ -934,6 +937,12 @@ gdbarch_dump (struct gdbarch *gdbarch, s
                       "gdbarch_dump: single_step_through_delay = <0x%lx>\n",
                       (long) gdbarch->single_step_through_delay);
   fprintf_unfiltered (file,
+                      "gdbarch_dump: gdbarch_skip___main_call_p() = %d\n",
+                      gdbarch_skip___main_call_p (gdbarch));
+  fprintf_unfiltered (file,
+                      "gdbarch_dump: skip___main_call = <0x%lx>\n",
+                      (long) gdbarch->skip___main_call);
+  fprintf_unfiltered (file,
                       "gdbarch_dump: gdbarch_skip_permanent_breakpoint_p() = %d\n",
                       gdbarch_skip_permanent_breakpoint_p (gdbarch));
   fprintf_unfiltered (file,
@@ -2075,6 +2084,30 @@ set_gdbarch_skip_prologue (struct gdbarc
 }
 
 int
+gdbarch_skip___main_call_p (struct gdbarch *gdbarch)
+{
+  gdb_assert (gdbarch != NULL);
+  return gdbarch->skip___main_call != NULL;
+}
+
+CORE_ADDR
+gdbarch_skip___main_call (struct gdbarch *gdbarch, CORE_ADDR ip)
+{
+  gdb_assert (gdbarch != NULL);
+  gdb_assert (gdbarch->skip___main_call != NULL);
+  if (gdbarch_debug >= 2)
+    fprintf_unfiltered (gdb_stdlog, "gdbarch_skip___main_call called\n");
+  return gdbarch->skip___main_call (gdbarch, ip);
+}
+
+void
+set_gdbarch_skip___main_call (struct gdbarch *gdbarch,
+                              gdbarch_skip___main_call_ftype skip___main_call)
+{
+  gdbarch->skip___main_call = skip___main_call;
+}
+
+int
 gdbarch_inner_than (struct gdbarch *gdbarch, CORE_ADDR lhs, CORE_ADDR rhs)
 {
   gdb_assert (gdbarch != NULL);
Index: src/gdb/gdbarch.h
===================================================================
--- src.orig/gdb/gdbarch.h	2008-01-29 04:39:16.000000000 +0000
+++ src/gdb/gdbarch.h	2008-01-29 04:39:40.000000000 +0000
@@ -374,6 +374,12 @@ typedef CORE_ADDR (gdbarch_skip_prologue
 extern CORE_ADDR gdbarch_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR ip);
 extern void set_gdbarch_skip_prologue (struct gdbarch *gdbarch, gdbarch_skip_prologue_ftype *skip_prologue);
 
+extern int gdbarch_skip___main_call_p (struct gdbarch *gdbarch);
+
+typedef CORE_ADDR (gdbarch_skip___main_call_ftype) (struct gdbarch *gdbarch, CORE_ADDR ip);
+extern CORE_ADDR gdbarch_skip___main_call (struct gdbarch *gdbarch, CORE_ADDR ip);
+extern void set_gdbarch_skip___main_call (struct gdbarch *gdbarch, gdbarch_skip___main_call_ftype *skip___main_call);
+
 typedef int (gdbarch_inner_than_ftype) (CORE_ADDR lhs, CORE_ADDR rhs);
 extern int gdbarch_inner_than (struct gdbarch *gdbarch, CORE_ADDR lhs, CORE_ADDR rhs);
 extern void set_gdbarch_inner_than (struct gdbarch *gdbarch, gdbarch_inner_than_ftype *inner_than);
Index: src/gdb/gdbarch.sh
===================================================================
--- src.orig/gdb/gdbarch.sh	2008-01-29 04:39:16.000000000 +0000
+++ src/gdb/gdbarch.sh	2008-01-29 04:39:40.000000000 +0000
@@ -477,6 +477,7 @@ M:CORE_ADDR:integer_to_address:struct ty
 M:enum return_value_convention:return_value:struct type *valtype, struct regcache *regcache, gdb_byte *readbuf, const gdb_byte *writebuf:valtype, regcache, readbuf, writebuf
 
 m:CORE_ADDR:skip_prologue:CORE_ADDR ip:ip:0:0
+M:CORE_ADDR:skip___main_call:CORE_ADDR ip:ip
 f:int:inner_than:CORE_ADDR lhs, CORE_ADDR rhs:lhs, rhs:0:0
 m:const gdb_byte *:breakpoint_from_pc:CORE_ADDR *pcptr, int *lenptr:pcptr, lenptr::0:
 M:CORE_ADDR:adjust_breakpoint_address:CORE_ADDR bpaddr:bpaddr
Index: src/gdb/i386-cygwin-tdep.c
===================================================================
--- src.orig/gdb/i386-cygwin-tdep.c	2008-01-29 04:39:18.000000000 +0000
+++ src/gdb/i386-cygwin-tdep.c	2008-01-29 04:39:40.000000000 +0000
@@ -227,6 +227,8 @@ i386_cygwin_init_abi (struct gdbarch_inf
 
   set_gdbarch_skip_trampoline_code (gdbarch, i386_cygwin_skip_trampoline_code);
 
+  set_gdbarch_skip___main_call (gdbarch, i386_skip___main_call);
+
   tdep->struct_return = reg_struct_return;
 
   tdep->gregset_reg_offset = i386_win32_gregset_reg_offset;
Index: src/gdb/i386-tdep.h
===================================================================
--- src.orig/gdb/i386-tdep.h	2008-01-29 04:39:18.000000000 +0000
+++ src/gdb/i386-tdep.h	2008-01-29 04:39:40.000000000 +0000
@@ -166,6 +166,7 @@ extern struct type *i386_sse_type (struc
 
 /* Functions exported from i386-tdep.c.  */
 extern CORE_ADDR i386_pe_skip_trampoline_code (CORE_ADDR pc, char *name);
+extern CORE_ADDR i386_skip___main_call (struct gdbarch *gdbarch, CORE_ADDR pc);
 
 /* Return the name of register REGNUM.  */
 extern char const *i386_register_name (struct gdbarch * gdbarch, int regnum);
Index: src/gdb/symtab.c
===================================================================
--- src.orig/gdb/symtab.c	2008-01-29 04:39:16.000000000 +0000
+++ src/gdb/symtab.c	2008-01-29 04:39:40.000000000 +0000
@@ -2506,6 +2506,21 @@ find_function_start_sal (struct symbol *
       /* Recalculate the line number (might not be N+1).  */
       sal = find_pc_sect_line (pc, SYMBOL_BFD_SECTION (sym), 0);
     }
+
+  /* On targets with executable formats that don't have a concept of
+     constructors (ELF with .init has, PE doesn't), gcc emits a call
+     to `__main' in `main' between the prologue and before user
+     code.  */
+  if (funfirstline
+      && gdbarch_skip___main_call_p (current_gdbarch)
+      && SYMBOL_LINKAGE_NAME (sym)
+      && strcmp (SYMBOL_LINKAGE_NAME (sym), "main") == 0)
+    {
+      pc = gdbarch_skip___main_call (current_gdbarch, pc);
+      /* Recalculate the line number (might not be N+1).  */
+      sal = find_pc_sect_line (pc, SYMBOL_BFD_SECTION (sym), 0);
+    }
+
   sal.pc = pc;
 
   return sal;

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