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]

[rfc] Fix Obj-C method calls on 64-bit PowerPC


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


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