Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [rfc] Fix Obj-C method calls on 64-bit PowerPC
@ 2009-09-27 21:49 Ulrich Weigand
  2009-09-28 17:51 ` Joel Brobecker
  0 siblings, 1 reply; 16+ messages in thread
From: Ulrich Weigand @ 2009-09-27 21:49 UTC (permalink / raw)
  To: gdb-patches

Hello,

on ppc64-linux, most Obj-C test cases now fail with a timeout due to
segmentation faults, causing very long testsuite run times.

The fundamental problem is that calling an Obj-C method does not
properly support platforms where a function pointer actually points
to a function descriptor instead of the target address.  This showed
up in a number of places:

- linespec.c:decode_objc did not convert minimal symbol addresses to
  function addresses (in addition, it did not fully initialize the SAL
  it returned in that case, resulting in an uninitialized "section"
  pointer that sometimes caused GDB to crash).

- objc-lang.c:find_methods required minimal symbols to reside in the
  text section (which is not valid if the symbol points to a descriptor
  in the data section) and likewise did not convert the minsym address
  to the function address.

- eval.c:evaluate_subexp_standard did some quite interesting hand-crafted
  "type casts" between *function pointer* and *function* types, which
  fail if function pointers actually refer to descriptors.  This code
  needs to use real function pointers as long as possible (to avoid
  losing descriptor information that is needed later on).

- and finally, ppc-sysv-tdep.c:ppc64_sysv_abi_push_dummy_call is sometimes
  unable to re-construct a function descriptor for a function called via
  function pointer (if the target is in a library without debug info).
  But this is silly, as the function pointer actually contains all the
  descriptor information needed, we just have to look at it ...

With the patch below, the Obj-C test cases now work as well as on
32-bit ppc-linux (and other Linux platforms).  There is still the
one failure in objcdecode.exp (like on other platforms).

Tested on s390(x)-linux and ppc(64)-linux with no regressions.

Does this look OK?

Bye,
Ulrich


ChangeLog:

	* eval.c (evaluate_subexp_standard) [OP_OBJC_MSGCALL]: Support
	platforms that use function descriptors.  Prefer to use function
	pointer types instead of function types.
	* linespec.c (decode_objc): Support function descriptors.  Fully
	initialize SAL result.
	* objc-lang.c (find_methods): Support function descriptors.
	Do not require function symbol to point to text section.

	* ppc-sysv-tdep.c (ppc64_sysv_abi_push_dummy_call): When calling
	via a function pointer, use the descriptor it point to.


Index: gdb/eval.c
===================================================================
RCS file: /cvs/src/src/gdb/eval.c,v
retrieving revision 1.120
diff -c -p -r1.120 eval.c
*** gdb/eval.c	22 Sep 2009 17:39:53 -0000	1.120
--- gdb/eval.c	25 Sep 2009 17:54:25 -0000
*************** evaluate_subexp_standard (struct type *e
*** 1161,1168 ****
  	if (addr)
  	  {
  	    struct symbol *sym = NULL;
- 	    /* Is it a high_level symbol?  */
  
  	    sym = find_pc_function (addr);
  	    if (sym != NULL) 
  	      method = value_of_variable (sym, 0);
--- 1161,1173 ----
  	if (addr)
  	  {
  	    struct symbol *sym = NULL;
  
+ 	    /* The address might point to a function descriptor;
+ 	       resolve it to the actual code address instead.  */
+ 	    addr = gdbarch_convert_from_func_ptr_addr (exp->gdbarch, addr,
+ 						       &current_target);
+ 
+ 	    /* Is it a high_level symbol?  */
  	    sym = find_pc_function (addr);
  	    if (sym != NULL) 
  	      method = value_of_variable (sym, 0);
*************** evaluate_subexp_standard (struct type *e
*** 1216,1226 ****
  	  {
  	    if (TYPE_CODE (value_type (method)) != TYPE_CODE_FUNC)
  	      error (_("method address has symbol information with non-function type; skipping"));
  	    if (struct_return)
! 	      set_value_address (method, value_as_address (msg_send_stret));
  	    else
! 	      set_value_address (method, value_as_address (msg_send));
! 	    called_method = method;
  	  }
  	else
  	  {
--- 1221,1240 ----
  	  {
  	    if (TYPE_CODE (value_type (method)) != TYPE_CODE_FUNC)
  	      error (_("method address has symbol information with non-function type; skipping"));
+ 
+ 	    /* Create a function pointer of the appropriate type, and replace
+ 	       its value with the value of msg_send or msg_send_stret.  We must
+ 	       use a pointer here, as msg_send and msg_send_stret are of pointer
+ 	       type, and the representation may be different on systems that use
+ 	       function descriptors.  */
  	    if (struct_return)
! 	      called_method
! 		= value_from_pointer (lookup_pointer_type (value_type (method)),
! 				      value_as_address (msg_send_stret));
  	    else
! 	      called_method
! 		= value_from_pointer (lookup_pointer_type (value_type (method)),
! 				      value_as_address (msg_send));
  	  }
  	else
  	  {
*************** evaluate_subexp_standard (struct type *e
*** 1275,1281 ****
  	  {
  	    /* Function objc_msg_lookup returns a pointer.  */
  	    deprecated_set_value_type (argvec[0],
! 				       lookup_function_type (lookup_pointer_type (value_type (argvec[0]))));
  	    argvec[0] = call_function_by_hand (argvec[0], nargs + 2, argvec + 1);
  	  }
  
--- 1289,1295 ----
  	  {
  	    /* Function objc_msg_lookup returns a pointer.  */
  	    deprecated_set_value_type (argvec[0],
! 				       lookup_pointer_type (lookup_function_type (value_type (argvec[0]))));
  	    argvec[0] = call_function_by_hand (argvec[0], nargs + 2, argvec + 1);
  	  }
  
Index: gdb/linespec.c
===================================================================
RCS file: /cvs/src/src/gdb/linespec.c,v
retrieving revision 1.90
diff -c -p -r1.90 linespec.c
*** gdb/linespec.c	21 Sep 2009 19:46:43 -0000	1.90
--- gdb/linespec.c	25 Sep 2009 17:54:26 -0000
*************** decode_objc (char **argptr, int funfirst
*** 1172,1182 ****
  	}
        else
  	{
! 	  /* The only match was a non-debuggable symbol.  */
! 	  values.sals[0].symtab = NULL;
! 	  values.sals[0].line = 0;
! 	  values.sals[0].end = 0;
! 	  values.sals[0].pc = SYMBOL_VALUE_ADDRESS (sym_arr[0]);
  	}
        return values;
      }
--- 1172,1190 ----
  	}
        else
  	{
! 	  /* The only match was a non-debuggable symbol, which might point
! 	     to a function descriptor; resolve it to the actual code address
! 	     instead.  */
! 	  struct minimal_symbol *msymbol = (struct minimal_symbol *)sym_arr[0];
! 	  struct objfile *objfile = msymbol_objfile (msymbol);
! 	  struct gdbarch *gdbarch = get_objfile_arch (objfile);
! 	  CORE_ADDR pc = SYMBOL_VALUE_ADDRESS (msymbol);
! 
! 	  pc = gdbarch_convert_from_func_ptr_addr (gdbarch, pc,
! 						   &current_target);
! 
! 	  init_sal (&values.sals[0]);
! 	  values.sals[0].pc = pc;
  	}
        return values;
      }
Index: gdb/objc-lang.c
===================================================================
RCS file: /cvs/src/src/gdb/objc-lang.c,v
retrieving revision 1.83
diff -c -p -r1.83 objc-lang.c
*** gdb/objc-lang.c	2 Jul 2009 17:25:57 -0000	1.83
--- gdb/objc-lang.c	25 Sep 2009 17:54:27 -0000
*************** find_methods (struct symtab *symtab, cha
*** 1173,1188 ****
  
        ALL_OBJFILE_MSYMBOLS (objfile, msymbol)
  	{
  	  QUIT;
  
! 	  if ((MSYMBOL_TYPE (msymbol) != mst_text)
! 	      && (MSYMBOL_TYPE (msymbol) != mst_file_text))
! 	    /* Not a function or method.  */
! 	    continue;
  
  	  if (symtab)
! 	    if ((SYMBOL_VALUE_ADDRESS (msymbol) <  BLOCK_START (block)) ||
! 		(SYMBOL_VALUE_ADDRESS (msymbol) >= BLOCK_END (block)))
  	      /* Not in the specified symtab.  */
  	      continue;
  
--- 1173,1190 ----
  
        ALL_OBJFILE_MSYMBOLS (objfile, msymbol)
  	{
+ 	  struct gdbarch *gdbarch = get_objfile_arch (objfile);
+ 	  CORE_ADDR pc = SYMBOL_VALUE_ADDRESS (msymbol);
+ 
  	  QUIT;
  
! 	  /* The minimal symbol might point to a function descriptor;
! 	     resolve it to the actual code address instead.  */
! 	  pc = gdbarch_convert_from_func_ptr_addr (gdbarch, pc,
! 						   &current_target);
  
  	  if (symtab)
! 	    if (pc < BLOCK_START (block) || pc >= BLOCK_END (block))
  	      /* Not in the specified symtab.  */
  	      continue;
  
*************** find_methods (struct symtab *symtab, cha
*** 1221,1227 ****
  	      ((nselector == NULL) || (strcmp (selector, nselector) != 0)))
  	    continue;
  
! 	  sym = find_pc_function (SYMBOL_VALUE_ADDRESS (msymbol));
  	  if (sym != NULL)
  	    {
  	      const char *newsymname = SYMBOL_NATURAL_NAME (sym);
--- 1223,1229 ----
  	      ((nselector == NULL) || (strcmp (selector, nselector) != 0)))
  	    continue;
  
! 	  sym = find_pc_function (pc);
  	  if (sym != NULL)
  	    {
  	      const char *newsymname = SYMBOL_NATURAL_NAME (sym);
Index: gdb/ppc-sysv-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/ppc-sysv-tdep.c,v
retrieving revision 1.55
diff -c -p -r1.55 ppc-sysv-tdep.c
*** gdb/ppc-sysv-tdep.c	2 Jul 2009 17:25:58 -0000	1.55
--- gdb/ppc-sysv-tdep.c	25 Sep 2009 17:54:27 -0000
*************** ppc64_sysv_abi_push_dummy_call (struct g
*** 1326,1335 ****
    regcache_cooked_write_signed (regcache, tdep->ppc_lr_regnum, bp_addr);
  
    /* Use the func_addr to find the descriptor, and use that to find
!      the TOC.  */
    {
!     CORE_ADDR desc_addr;
!     if (convert_code_addr_to_desc_addr (func_addr, &desc_addr))
        {
  	/* The TOC is the second double word in the descriptor.  */
  	CORE_ADDR toc =
--- 1326,1339 ----
    regcache_cooked_write_signed (regcache, tdep->ppc_lr_regnum, bp_addr);
  
    /* Use the func_addr to find the descriptor, and use that to find
!      the TOC.  If we're calling via a function pointer, the pointer
!      itself identifies the descriptor.  */
    {
!     struct type *ftype = check_typedef (value_type (function));
!     CORE_ADDR desc_addr = value_as_address (function);
! 
!     if (TYPE_CODE (ftype) == TYPE_CODE_PTR
! 	|| convert_code_addr_to_desc_addr (func_addr, &desc_addr))
        {
  	/* The TOC is the second double word in the descriptor.  */
  	CORE_ADDR toc =
-- 
  Dr. Ulrich Weigand
  GNU Toolchain for Linux on System z and Cell BE
  Ulrich.Weigand@de.ibm.com


^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2009-09-29 21:08 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-09-27 21:49 [rfc] Fix Obj-C method calls on 64-bit PowerPC Ulrich Weigand
2009-09-28 17:51 ` Joel Brobecker
2009-09-28 22:41   ` Matt Rice
2009-09-29  0:50     ` Ulrich Weigand
2009-09-29 15:44       ` [ia64] Regression: " Jan Kratochvil
2009-09-29 16:07         ` Ulrich Weigand
2009-09-29 16:17           ` Jan Kratochvil
2009-09-29 16:16         ` Joel Brobecker
2009-09-29 16:30           ` Jan Kratochvil
2009-09-29 16:40             ` Joel Brobecker
2009-09-29 19:11               ` Jan Kratochvil
2009-09-29 16:45           ` Ulrich Weigand
2009-09-29 19:07             ` [commit] Avoid Obj-C test timeouts due to symbols not found Ulrich Weigand
2009-09-29 17:27         ` [rfc] Move PC in-range check in objc-lang.c:find_methods (Re: [ia64] Regression) Ulrich Weigand
2009-09-29 17:46           ` Joel Brobecker
2009-09-29 21:08         ` [ia64] Regression: Re: [rfc] Fix Obj-C method calls on 64-bit PowerPC Jan Kratochvil

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox