diff --git a/gdb/ChangeLog b/gdb/ChangeLog index b9e6b1ec66..2447062cb0 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,16 @@ +2009-09-28 Ulrich Weigand + + * 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 points to. + 2009-09-28 Jan Kratochvil Fix ia64 breakpoints in the L-X slot. diff --git a/gdb/eval.c b/gdb/eval.c index 2926465c41..a1d6e124d5 100644 --- a/gdb/eval.c +++ b/gdb/eval.c @@ -1161,8 +1161,13 @@ evaluate_subexp_standard (struct type *expect_type, if (addr) { struct symbol *sym = NULL; - /* Is it a high_level symbol? */ + /* 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); @@ -1216,11 +1221,20 @@ evaluate_subexp_standard (struct type *expect_type, { 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) - set_value_address (method, value_as_address (msg_send_stret)); + called_method + = value_from_pointer (lookup_pointer_type (value_type (method)), + value_as_address (msg_send_stret)); else - set_value_address (method, value_as_address (msg_send)); - called_method = method; + called_method + = value_from_pointer (lookup_pointer_type (value_type (method)), + value_as_address (msg_send)); } else { @@ -1275,7 +1289,7 @@ evaluate_subexp_standard (struct type *expect_type, { /* Function objc_msg_lookup returns a pointer. */ deprecated_set_value_type (argvec[0], - lookup_function_type (lookup_pointer_type (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); } diff --git a/gdb/linespec.c b/gdb/linespec.c index 70e27f7683..19df329f45 100644 --- a/gdb/linespec.c +++ b/gdb/linespec.c @@ -1172,11 +1172,19 @@ decode_objc (char **argptr, int funfirstline, struct symtab *file_symtab, } 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]); + /* 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; } diff --git a/gdb/objc-lang.c b/gdb/objc-lang.c index 0e4fb71965..f3a8b7308f 100644 --- a/gdb/objc-lang.c +++ b/gdb/objc-lang.c @@ -1173,16 +1173,18 @@ find_methods (struct symtab *symtab, char type, ALL_OBJFILE_MSYMBOLS (objfile, msymbol) { + struct gdbarch *gdbarch = get_objfile_arch (objfile); + CORE_ADDR pc = SYMBOL_VALUE_ADDRESS (msymbol); + QUIT; - if ((MSYMBOL_TYPE (msymbol) != mst_text) - && (MSYMBOL_TYPE (msymbol) != mst_file_text)) - /* Not a function or method. */ - continue; + /* 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 ((SYMBOL_VALUE_ADDRESS (msymbol) < BLOCK_START (block)) || - (SYMBOL_VALUE_ADDRESS (msymbol) >= BLOCK_END (block))) + if (pc < BLOCK_START (block) || pc >= BLOCK_END (block)) /* Not in the specified symtab. */ continue; @@ -1221,7 +1223,7 @@ find_methods (struct symtab *symtab, char type, ((nselector == NULL) || (strcmp (selector, nselector) != 0))) continue; - sym = find_pc_function (SYMBOL_VALUE_ADDRESS (msymbol)); + sym = find_pc_function (pc); if (sym != NULL) { const char *newsymname = SYMBOL_NATURAL_NAME (sym); diff --git a/gdb/ppc-sysv-tdep.c b/gdb/ppc-sysv-tdep.c index 703ca4db40..031ec52da0 100644 --- a/gdb/ppc-sysv-tdep.c +++ b/gdb/ppc-sysv-tdep.c @@ -1326,10 +1326,14 @@ ppc64_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function, 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. */ + the TOC. If we're calling via a function pointer, the pointer + itself identifies the descriptor. */ { - CORE_ADDR desc_addr; - if (convert_code_addr_to_desc_addr (func_addr, &desc_addr)) + 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 =