From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 21604 invoked by alias); 27 Sep 2009 21:49:36 -0000 Received: (qmail 21596 invoked by uid 22791); 27 Sep 2009 21:49:35 -0000 X-SWARE-Spam-Status: No, hits=-0.6 required=5.0 tests=AWL,BAYES_00,KAM_STOCKGEN,MSGID_FROM_MTA_HEADER,SPF_SOFTFAIL X-Spam-Check-By: sourceware.org Received: from mtagate1.de.ibm.com (HELO mtagate1.de.ibm.com) (195.212.17.161) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Sun, 27 Sep 2009 21:49:31 +0000 Received: from d12nrmr1607.megacenter.de.ibm.com (d12nrmr1607.megacenter.de.ibm.com [9.149.167.49]) by mtagate1.de.ibm.com (8.13.1/8.13.1) with ESMTP id n8RLnSCF028715 for ; Sun, 27 Sep 2009 21:49:28 GMT Received: from d12av02.megacenter.de.ibm.com (d12av02.megacenter.de.ibm.com [9.149.165.228]) by d12nrmr1607.megacenter.de.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id n8RLnSMv3334282 for ; Sun, 27 Sep 2009 23:49:28 +0200 Received: from d12av02.megacenter.de.ibm.com (loopback [127.0.0.1]) by d12av02.megacenter.de.ibm.com (8.12.11.20060308/8.13.3) with ESMTP id n8RLnSlY032291 for ; Sun, 27 Sep 2009 23:49:28 +0200 Received: from tuxmaker.boeblingen.de.ibm.com (tuxmaker.boeblingen.de.ibm.com [9.152.85.9]) by d12av02.megacenter.de.ibm.com (8.12.11.20060308/8.12.11) with SMTP id n8RLnRxc032281 for ; Sun, 27 Sep 2009 23:49:27 +0200 Message-Id: <200909272149.n8RLnRxc032281@d12av02.megacenter.de.ibm.com> Received: by tuxmaker.boeblingen.de.ibm.com (sSMTP sendmail emulation); Sun, 27 Sep 2009 23:49:27 +0200 Subject: [rfc] Fix Obj-C method calls on 64-bit PowerPC To: gdb-patches@sourceware.org Date: Sun, 27 Sep 2009 21:49:00 -0000 From: "Ulrich Weigand" MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2009-09/txt/msg00857.txt.bz2 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, + ¤t_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, ! ¤t_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, ! ¤t_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