15796c8dcSSimon Schubert /* Objective-C language support routines for GDB, the GNU debugger.
25796c8dcSSimon Schubert
3*ef5ccd6cSJohn Marino Copyright (C) 2002-2013 Free Software Foundation, Inc.
45796c8dcSSimon Schubert
55796c8dcSSimon Schubert Contributed by Apple Computer, Inc.
65796c8dcSSimon Schubert Written by Michael Snyder.
75796c8dcSSimon Schubert
85796c8dcSSimon Schubert This file is part of GDB.
95796c8dcSSimon Schubert
105796c8dcSSimon Schubert This program is free software; you can redistribute it and/or modify
115796c8dcSSimon Schubert it under the terms of the GNU General Public License as published by
125796c8dcSSimon Schubert the Free Software Foundation; either version 3 of the License, or
135796c8dcSSimon Schubert (at your option) any later version.
145796c8dcSSimon Schubert
155796c8dcSSimon Schubert This program is distributed in the hope that it will be useful,
165796c8dcSSimon Schubert but WITHOUT ANY WARRANTY; without even the implied warranty of
175796c8dcSSimon Schubert MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
185796c8dcSSimon Schubert GNU General Public License for more details.
195796c8dcSSimon Schubert
205796c8dcSSimon Schubert You should have received a copy of the GNU General Public License
215796c8dcSSimon Schubert along with this program. If not, see <http://www.gnu.org/licenses/>. */
225796c8dcSSimon Schubert
235796c8dcSSimon Schubert #include "defs.h"
245796c8dcSSimon Schubert #include "symtab.h"
255796c8dcSSimon Schubert #include "gdbtypes.h"
265796c8dcSSimon Schubert #include "expression.h"
275796c8dcSSimon Schubert #include "parser-defs.h"
285796c8dcSSimon Schubert #include "language.h"
295796c8dcSSimon Schubert #include "c-lang.h"
305796c8dcSSimon Schubert #include "objc-lang.h"
315796c8dcSSimon Schubert #include "exceptions.h"
325796c8dcSSimon Schubert #include "complaints.h"
335796c8dcSSimon Schubert #include "value.h"
345796c8dcSSimon Schubert #include "symfile.h"
355796c8dcSSimon Schubert #include "objfiles.h"
365796c8dcSSimon Schubert #include "gdb_string.h" /* for strchr */
375796c8dcSSimon Schubert #include "target.h" /* for target_has_execution */
385796c8dcSSimon Schubert #include "gdbcore.h"
395796c8dcSSimon Schubert #include "gdbcmd.h"
405796c8dcSSimon Schubert #include "frame.h"
415796c8dcSSimon Schubert #include "gdb_regex.h"
425796c8dcSSimon Schubert #include "regcache.h"
435796c8dcSSimon Schubert #include "block.h"
445796c8dcSSimon Schubert #include "infcall.h"
455796c8dcSSimon Schubert #include "valprint.h"
465796c8dcSSimon Schubert #include "gdb_assert.h"
47*ef5ccd6cSJohn Marino #include "cli/cli-utils.h"
485796c8dcSSimon Schubert
495796c8dcSSimon Schubert #include <ctype.h>
505796c8dcSSimon Schubert
515796c8dcSSimon Schubert struct objc_object {
525796c8dcSSimon Schubert CORE_ADDR isa;
535796c8dcSSimon Schubert };
545796c8dcSSimon Schubert
555796c8dcSSimon Schubert struct objc_class {
565796c8dcSSimon Schubert CORE_ADDR isa;
575796c8dcSSimon Schubert CORE_ADDR super_class;
585796c8dcSSimon Schubert CORE_ADDR name;
595796c8dcSSimon Schubert long version;
605796c8dcSSimon Schubert long info;
615796c8dcSSimon Schubert long instance_size;
625796c8dcSSimon Schubert CORE_ADDR ivars;
635796c8dcSSimon Schubert CORE_ADDR methods;
645796c8dcSSimon Schubert CORE_ADDR cache;
655796c8dcSSimon Schubert CORE_ADDR protocols;
665796c8dcSSimon Schubert };
675796c8dcSSimon Schubert
685796c8dcSSimon Schubert struct objc_super {
695796c8dcSSimon Schubert CORE_ADDR receiver;
705796c8dcSSimon Schubert CORE_ADDR class;
715796c8dcSSimon Schubert };
725796c8dcSSimon Schubert
735796c8dcSSimon Schubert struct objc_method {
745796c8dcSSimon Schubert CORE_ADDR name;
755796c8dcSSimon Schubert CORE_ADDR types;
765796c8dcSSimon Schubert CORE_ADDR imp;
775796c8dcSSimon Schubert };
785796c8dcSSimon Schubert
795796c8dcSSimon Schubert static const struct objfile_data *objc_objfile_data;
805796c8dcSSimon Schubert
815796c8dcSSimon Schubert /* Lookup a structure type named "struct NAME", visible in lexical
825796c8dcSSimon Schubert block BLOCK. If NOERR is nonzero, return zero if NAME is not
835796c8dcSSimon Schubert suitably defined. */
845796c8dcSSimon Schubert
855796c8dcSSimon Schubert struct symbol *
lookup_struct_typedef(char * name,const struct block * block,int noerr)86*ef5ccd6cSJohn Marino lookup_struct_typedef (char *name, const struct block *block, int noerr)
875796c8dcSSimon Schubert {
885796c8dcSSimon Schubert struct symbol *sym;
895796c8dcSSimon Schubert
905796c8dcSSimon Schubert sym = lookup_symbol (name, block, STRUCT_DOMAIN, 0);
915796c8dcSSimon Schubert
925796c8dcSSimon Schubert if (sym == NULL)
935796c8dcSSimon Schubert {
945796c8dcSSimon Schubert if (noerr)
955796c8dcSSimon Schubert return 0;
965796c8dcSSimon Schubert else
975796c8dcSSimon Schubert error (_("No struct type named %s."), name);
985796c8dcSSimon Schubert }
995796c8dcSSimon Schubert if (TYPE_CODE (SYMBOL_TYPE (sym)) != TYPE_CODE_STRUCT)
1005796c8dcSSimon Schubert {
1015796c8dcSSimon Schubert if (noerr)
1025796c8dcSSimon Schubert return 0;
1035796c8dcSSimon Schubert else
1045796c8dcSSimon Schubert error (_("This context has class, union or enum %s, not a struct."),
1055796c8dcSSimon Schubert name);
1065796c8dcSSimon Schubert }
1075796c8dcSSimon Schubert return sym;
1085796c8dcSSimon Schubert }
1095796c8dcSSimon Schubert
1105796c8dcSSimon Schubert CORE_ADDR
lookup_objc_class(struct gdbarch * gdbarch,char * classname)1115796c8dcSSimon Schubert lookup_objc_class (struct gdbarch *gdbarch, char *classname)
1125796c8dcSSimon Schubert {
1135796c8dcSSimon Schubert struct type *char_type = builtin_type (gdbarch)->builtin_char;
1145796c8dcSSimon Schubert struct value * function, *classval;
1155796c8dcSSimon Schubert
1165796c8dcSSimon Schubert if (! target_has_execution)
1175796c8dcSSimon Schubert {
1185796c8dcSSimon Schubert /* Can't call into inferior to lookup class. */
1195796c8dcSSimon Schubert return 0;
1205796c8dcSSimon Schubert }
1215796c8dcSSimon Schubert
1225796c8dcSSimon Schubert if (lookup_minimal_symbol("objc_lookUpClass", 0, 0))
1235796c8dcSSimon Schubert function = find_function_in_inferior("objc_lookUpClass", NULL);
1245796c8dcSSimon Schubert else if (lookup_minimal_symbol ("objc_lookup_class", 0, 0))
1255796c8dcSSimon Schubert function = find_function_in_inferior("objc_lookup_class", NULL);
1265796c8dcSSimon Schubert else
1275796c8dcSSimon Schubert {
128c50c785cSJohn Marino complaint (&symfile_complaints,
129c50c785cSJohn Marino _("no way to lookup Objective-C classes"));
1305796c8dcSSimon Schubert return 0;
1315796c8dcSSimon Schubert }
1325796c8dcSSimon Schubert
1335796c8dcSSimon Schubert classval = value_string (classname, strlen (classname) + 1, char_type);
1345796c8dcSSimon Schubert classval = value_coerce_array (classval);
1355796c8dcSSimon Schubert return (CORE_ADDR) value_as_long (call_function_by_hand (function,
1365796c8dcSSimon Schubert 1, &classval));
1375796c8dcSSimon Schubert }
1385796c8dcSSimon Schubert
1395796c8dcSSimon Schubert CORE_ADDR
lookup_child_selector(struct gdbarch * gdbarch,char * selname)1405796c8dcSSimon Schubert lookup_child_selector (struct gdbarch *gdbarch, char *selname)
1415796c8dcSSimon Schubert {
1425796c8dcSSimon Schubert struct type *char_type = builtin_type (gdbarch)->builtin_char;
1435796c8dcSSimon Schubert struct value * function, *selstring;
1445796c8dcSSimon Schubert
1455796c8dcSSimon Schubert if (! target_has_execution)
1465796c8dcSSimon Schubert {
1475796c8dcSSimon Schubert /* Can't call into inferior to lookup selector. */
1485796c8dcSSimon Schubert return 0;
1495796c8dcSSimon Schubert }
1505796c8dcSSimon Schubert
1515796c8dcSSimon Schubert if (lookup_minimal_symbol("sel_getUid", 0, 0))
1525796c8dcSSimon Schubert function = find_function_in_inferior("sel_getUid", NULL);
1535796c8dcSSimon Schubert else if (lookup_minimal_symbol ("sel_get_any_uid", 0, 0))
1545796c8dcSSimon Schubert function = find_function_in_inferior("sel_get_any_uid", NULL);
1555796c8dcSSimon Schubert else
1565796c8dcSSimon Schubert {
157c50c785cSJohn Marino complaint (&symfile_complaints,
158c50c785cSJohn Marino _("no way to lookup Objective-C selectors"));
1595796c8dcSSimon Schubert return 0;
1605796c8dcSSimon Schubert }
1615796c8dcSSimon Schubert
1625796c8dcSSimon Schubert selstring = value_coerce_array (value_string (selname,
163c50c785cSJohn Marino strlen (selname) + 1,
164c50c785cSJohn Marino char_type));
1655796c8dcSSimon Schubert return value_as_long (call_function_by_hand (function, 1, &selstring));
1665796c8dcSSimon Schubert }
1675796c8dcSSimon Schubert
1685796c8dcSSimon Schubert struct value *
value_nsstring(struct gdbarch * gdbarch,char * ptr,int len)1695796c8dcSSimon Schubert value_nsstring (struct gdbarch *gdbarch, char *ptr, int len)
1705796c8dcSSimon Schubert {
1715796c8dcSSimon Schubert struct type *char_type = builtin_type (gdbarch)->builtin_char;
1725796c8dcSSimon Schubert struct value *stringValue[3];
1735796c8dcSSimon Schubert struct value *function, *nsstringValue;
1745796c8dcSSimon Schubert struct symbol *sym;
1755796c8dcSSimon Schubert struct type *type;
1765796c8dcSSimon Schubert
1775796c8dcSSimon Schubert if (!target_has_execution)
1785796c8dcSSimon Schubert return 0; /* Can't call into inferior to create NSString. */
1795796c8dcSSimon Schubert
1805796c8dcSSimon Schubert stringValue[2] = value_string(ptr, len, char_type);
1815796c8dcSSimon Schubert stringValue[2] = value_coerce_array(stringValue[2]);
1825796c8dcSSimon Schubert /* _NSNewStringFromCString replaces "istr" after Lantern2A. */
1835796c8dcSSimon Schubert if (lookup_minimal_symbol("_NSNewStringFromCString", 0, 0))
1845796c8dcSSimon Schubert {
1855796c8dcSSimon Schubert function = find_function_in_inferior("_NSNewStringFromCString", NULL);
1865796c8dcSSimon Schubert nsstringValue = call_function_by_hand(function, 1, &stringValue[2]);
1875796c8dcSSimon Schubert }
1885796c8dcSSimon Schubert else if (lookup_minimal_symbol("istr", 0, 0))
1895796c8dcSSimon Schubert {
1905796c8dcSSimon Schubert function = find_function_in_inferior("istr", NULL);
1915796c8dcSSimon Schubert nsstringValue = call_function_by_hand(function, 1, &stringValue[2]);
1925796c8dcSSimon Schubert }
1935796c8dcSSimon Schubert else if (lookup_minimal_symbol("+[NSString stringWithCString:]", 0, 0))
1945796c8dcSSimon Schubert {
1955796c8dcSSimon Schubert function
1965796c8dcSSimon Schubert = find_function_in_inferior("+[NSString stringWithCString:]", NULL);
1975796c8dcSSimon Schubert type = builtin_type (gdbarch)->builtin_long;
1985796c8dcSSimon Schubert
1995796c8dcSSimon Schubert stringValue[0] = value_from_longest
2005796c8dcSSimon Schubert (type, lookup_objc_class (gdbarch, "NSString"));
2015796c8dcSSimon Schubert stringValue[1] = value_from_longest
2025796c8dcSSimon Schubert (type, lookup_child_selector (gdbarch, "stringWithCString:"));
2035796c8dcSSimon Schubert nsstringValue = call_function_by_hand(function, 3, &stringValue[0]);
2045796c8dcSSimon Schubert }
2055796c8dcSSimon Schubert else
2065796c8dcSSimon Schubert error (_("NSString: internal error -- no way to create new NSString"));
2075796c8dcSSimon Schubert
2085796c8dcSSimon Schubert sym = lookup_struct_typedef("NSString", 0, 1);
2095796c8dcSSimon Schubert if (sym == NULL)
2105796c8dcSSimon Schubert sym = lookup_struct_typedef("NXString", 0, 1);
2115796c8dcSSimon Schubert if (sym == NULL)
2125796c8dcSSimon Schubert type = builtin_type (gdbarch)->builtin_data_ptr;
2135796c8dcSSimon Schubert else
2145796c8dcSSimon Schubert type = lookup_pointer_type(SYMBOL_TYPE (sym));
2155796c8dcSSimon Schubert
2165796c8dcSSimon Schubert deprecated_set_value_type (nsstringValue, type);
2175796c8dcSSimon Schubert return nsstringValue;
2185796c8dcSSimon Schubert }
2195796c8dcSSimon Schubert
2205796c8dcSSimon Schubert /* Objective-C name demangling. */
2215796c8dcSSimon Schubert
2225796c8dcSSimon Schubert char *
objc_demangle(const char * mangled,int options)2235796c8dcSSimon Schubert objc_demangle (const char *mangled, int options)
2245796c8dcSSimon Schubert {
2255796c8dcSSimon Schubert char *demangled, *cp;
2265796c8dcSSimon Schubert
2275796c8dcSSimon Schubert if (mangled[0] == '_' &&
2285796c8dcSSimon Schubert (mangled[1] == 'i' || mangled[1] == 'c') &&
2295796c8dcSSimon Schubert mangled[2] == '_')
2305796c8dcSSimon Schubert {
2315796c8dcSSimon Schubert cp = demangled = xmalloc(strlen(mangled) + 2);
2325796c8dcSSimon Schubert
2335796c8dcSSimon Schubert if (mangled[1] == 'i')
2345796c8dcSSimon Schubert *cp++ = '-'; /* for instance method */
2355796c8dcSSimon Schubert else
2365796c8dcSSimon Schubert *cp++ = '+'; /* for class method */
2375796c8dcSSimon Schubert
2385796c8dcSSimon Schubert *cp++ = '['; /* opening left brace */
239c50c785cSJohn Marino strcpy(cp, mangled+3); /* Tack on the rest of the mangled name. */
2405796c8dcSSimon Schubert
2415796c8dcSSimon Schubert while (*cp && *cp == '_')
242c50c785cSJohn Marino cp++; /* Skip any initial underbars in class
243c50c785cSJohn Marino name. */
2445796c8dcSSimon Schubert
2455796c8dcSSimon Schubert cp = strchr(cp, '_');
246c50c785cSJohn Marino if (!cp) /* Find first non-initial underbar. */
2475796c8dcSSimon Schubert {
2485796c8dcSSimon Schubert xfree(demangled); /* not mangled name */
2495796c8dcSSimon Schubert return NULL;
2505796c8dcSSimon Schubert }
251c50c785cSJohn Marino if (cp[1] == '_') /* Easy case: no category name. */
252cf7f2e2dSJohn Marino {
253c50c785cSJohn Marino *cp++ = ' '; /* Replace two '_' with one ' '. */
2545796c8dcSSimon Schubert strcpy(cp, mangled + (cp - demangled) + 2);
2555796c8dcSSimon Schubert }
256cf7f2e2dSJohn Marino else
257cf7f2e2dSJohn Marino {
258c50c785cSJohn Marino *cp++ = '('; /* Less easy case: category name. */
2595796c8dcSSimon Schubert cp = strchr(cp, '_');
2605796c8dcSSimon Schubert if (!cp)
2615796c8dcSSimon Schubert {
2625796c8dcSSimon Schubert xfree(demangled); /* not mangled name */
2635796c8dcSSimon Schubert return NULL;
2645796c8dcSSimon Schubert }
2655796c8dcSSimon Schubert *cp++ = ')';
266c50c785cSJohn Marino *cp++ = ' '; /* Overwriting 1st char of method name... */
267c50c785cSJohn Marino strcpy(cp, mangled + (cp - demangled)); /* Get it back. */
2685796c8dcSSimon Schubert }
2695796c8dcSSimon Schubert
2705796c8dcSSimon Schubert while (*cp && *cp == '_')
271c50c785cSJohn Marino cp++; /* Skip any initial underbars in
272c50c785cSJohn Marino method name. */
2735796c8dcSSimon Schubert
2745796c8dcSSimon Schubert for (; *cp; cp++)
2755796c8dcSSimon Schubert if (*cp == '_')
276c50c785cSJohn Marino *cp = ':'; /* Replace remaining '_' with ':'. */
2775796c8dcSSimon Schubert
2785796c8dcSSimon Schubert *cp++ = ']'; /* closing right brace */
2795796c8dcSSimon Schubert *cp++ = 0; /* string terminator */
2805796c8dcSSimon Schubert return demangled;
2815796c8dcSSimon Schubert }
2825796c8dcSSimon Schubert else
2835796c8dcSSimon Schubert return NULL; /* Not an objc mangled name. */
2845796c8dcSSimon Schubert }
2855796c8dcSSimon Schubert
2865796c8dcSSimon Schubert /* Determine if we are currently in the Objective-C dispatch function.
2875796c8dcSSimon Schubert If so, get the address of the method function that the dispatcher
2885796c8dcSSimon Schubert would call and use that as the function to step into instead. Also
2895796c8dcSSimon Schubert skip over the trampoline for the function (if any). This is better
2905796c8dcSSimon Schubert for the user since they are only interested in stepping into the
2915796c8dcSSimon Schubert method function anyway. */
2925796c8dcSSimon Schubert static CORE_ADDR
objc_skip_trampoline(struct frame_info * frame,CORE_ADDR stop_pc)2935796c8dcSSimon Schubert objc_skip_trampoline (struct frame_info *frame, CORE_ADDR stop_pc)
2945796c8dcSSimon Schubert {
2955796c8dcSSimon Schubert struct gdbarch *gdbarch = get_frame_arch (frame);
2965796c8dcSSimon Schubert CORE_ADDR real_stop_pc;
2975796c8dcSSimon Schubert CORE_ADDR method_stop_pc;
2985796c8dcSSimon Schubert
2995796c8dcSSimon Schubert real_stop_pc = gdbarch_skip_trampoline_code (gdbarch, frame, stop_pc);
3005796c8dcSSimon Schubert
3015796c8dcSSimon Schubert if (real_stop_pc != 0)
3025796c8dcSSimon Schubert find_objc_msgcall (real_stop_pc, &method_stop_pc);
3035796c8dcSSimon Schubert else
3045796c8dcSSimon Schubert find_objc_msgcall (stop_pc, &method_stop_pc);
3055796c8dcSSimon Schubert
3065796c8dcSSimon Schubert if (method_stop_pc)
3075796c8dcSSimon Schubert {
3085796c8dcSSimon Schubert real_stop_pc = gdbarch_skip_trampoline_code
3095796c8dcSSimon Schubert (gdbarch, frame, method_stop_pc);
3105796c8dcSSimon Schubert if (real_stop_pc == 0)
3115796c8dcSSimon Schubert real_stop_pc = method_stop_pc;
3125796c8dcSSimon Schubert }
3135796c8dcSSimon Schubert
3145796c8dcSSimon Schubert return real_stop_pc;
3155796c8dcSSimon Schubert }
3165796c8dcSSimon Schubert
3175796c8dcSSimon Schubert
3185796c8dcSSimon Schubert /* Table mapping opcodes into strings for printing operators
3195796c8dcSSimon Schubert and precedences of the operators. */
3205796c8dcSSimon Schubert
3215796c8dcSSimon Schubert static const struct op_print objc_op_print_tab[] =
3225796c8dcSSimon Schubert {
3235796c8dcSSimon Schubert {",", BINOP_COMMA, PREC_COMMA, 0},
3245796c8dcSSimon Schubert {"=", BINOP_ASSIGN, PREC_ASSIGN, 1},
3255796c8dcSSimon Schubert {"||", BINOP_LOGICAL_OR, PREC_LOGICAL_OR, 0},
3265796c8dcSSimon Schubert {"&&", BINOP_LOGICAL_AND, PREC_LOGICAL_AND, 0},
3275796c8dcSSimon Schubert {"|", BINOP_BITWISE_IOR, PREC_BITWISE_IOR, 0},
3285796c8dcSSimon Schubert {"^", BINOP_BITWISE_XOR, PREC_BITWISE_XOR, 0},
3295796c8dcSSimon Schubert {"&", BINOP_BITWISE_AND, PREC_BITWISE_AND, 0},
3305796c8dcSSimon Schubert {"==", BINOP_EQUAL, PREC_EQUAL, 0},
3315796c8dcSSimon Schubert {"!=", BINOP_NOTEQUAL, PREC_EQUAL, 0},
3325796c8dcSSimon Schubert {"<=", BINOP_LEQ, PREC_ORDER, 0},
3335796c8dcSSimon Schubert {">=", BINOP_GEQ, PREC_ORDER, 0},
3345796c8dcSSimon Schubert {">", BINOP_GTR, PREC_ORDER, 0},
3355796c8dcSSimon Schubert {"<", BINOP_LESS, PREC_ORDER, 0},
3365796c8dcSSimon Schubert {">>", BINOP_RSH, PREC_SHIFT, 0},
3375796c8dcSSimon Schubert {"<<", BINOP_LSH, PREC_SHIFT, 0},
3385796c8dcSSimon Schubert {"+", BINOP_ADD, PREC_ADD, 0},
3395796c8dcSSimon Schubert {"-", BINOP_SUB, PREC_ADD, 0},
3405796c8dcSSimon Schubert {"*", BINOP_MUL, PREC_MUL, 0},
3415796c8dcSSimon Schubert {"/", BINOP_DIV, PREC_MUL, 0},
3425796c8dcSSimon Schubert {"%", BINOP_REM, PREC_MUL, 0},
3435796c8dcSSimon Schubert {"@", BINOP_REPEAT, PREC_REPEAT, 0},
3445796c8dcSSimon Schubert {"-", UNOP_NEG, PREC_PREFIX, 0},
3455796c8dcSSimon Schubert {"!", UNOP_LOGICAL_NOT, PREC_PREFIX, 0},
3465796c8dcSSimon Schubert {"~", UNOP_COMPLEMENT, PREC_PREFIX, 0},
3475796c8dcSSimon Schubert {"*", UNOP_IND, PREC_PREFIX, 0},
3485796c8dcSSimon Schubert {"&", UNOP_ADDR, PREC_PREFIX, 0},
3495796c8dcSSimon Schubert {"sizeof ", UNOP_SIZEOF, PREC_PREFIX, 0},
3505796c8dcSSimon Schubert {"++", UNOP_PREINCREMENT, PREC_PREFIX, 0},
3515796c8dcSSimon Schubert {"--", UNOP_PREDECREMENT, PREC_PREFIX, 0},
3525796c8dcSSimon Schubert {NULL, OP_NULL, PREC_NULL, 0}
3535796c8dcSSimon Schubert };
3545796c8dcSSimon Schubert
3555796c8dcSSimon Schubert const struct language_defn objc_language_defn = {
3565796c8dcSSimon Schubert "objective-c", /* Language name */
3575796c8dcSSimon Schubert language_objc,
3585796c8dcSSimon Schubert range_check_off,
3595796c8dcSSimon Schubert case_sensitive_on,
3605796c8dcSSimon Schubert array_row_major,
3615796c8dcSSimon Schubert macro_expansion_c,
3625796c8dcSSimon Schubert &exp_descriptor_standard,
363*ef5ccd6cSJohn Marino c_parse,
364*ef5ccd6cSJohn Marino c_error,
3655796c8dcSSimon Schubert null_post_parser,
366*ef5ccd6cSJohn Marino c_printchar, /* Print a character constant */
367*ef5ccd6cSJohn Marino c_printstr, /* Function to print string constant */
368*ef5ccd6cSJohn Marino c_emit_char,
3695796c8dcSSimon Schubert c_print_type, /* Print a type using appropriate syntax */
3705796c8dcSSimon Schubert c_print_typedef, /* Print a typedef using appropriate syntax */
3715796c8dcSSimon Schubert c_val_print, /* Print a value using appropriate syntax */
3725796c8dcSSimon Schubert c_value_print, /* Print a top-level value */
373*ef5ccd6cSJohn Marino default_read_var_value, /* la_read_var_value */
3745796c8dcSSimon Schubert objc_skip_trampoline, /* Language specific skip_trampoline */
3755796c8dcSSimon Schubert "self", /* name_of_this */
3765796c8dcSSimon Schubert basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
3775796c8dcSSimon Schubert basic_lookup_transparent_type,/* lookup_transparent_type */
3785796c8dcSSimon Schubert objc_demangle, /* Language specific symbol demangler */
379c50c785cSJohn Marino NULL, /* Language specific
380c50c785cSJohn Marino class_name_from_physname */
3815796c8dcSSimon Schubert objc_op_print_tab, /* Expression operators for printing */
3825796c8dcSSimon Schubert 1, /* C-style arrays */
3835796c8dcSSimon Schubert 0, /* String lower bound */
3845796c8dcSSimon Schubert default_word_break_characters,
3855796c8dcSSimon Schubert default_make_symbol_completion_list,
3865796c8dcSSimon Schubert c_language_arch_info,
3875796c8dcSSimon Schubert default_print_array_index,
3885796c8dcSSimon Schubert default_pass_by_reference,
3895796c8dcSSimon Schubert default_get_string,
390*ef5ccd6cSJohn Marino NULL, /* la_get_symbol_name_cmp */
391a45ae5f8SJohn Marino iterate_over_symbols,
3925796c8dcSSimon Schubert LANG_MAGIC
3935796c8dcSSimon Schubert };
3945796c8dcSSimon Schubert
3955796c8dcSSimon Schubert /*
3965796c8dcSSimon Schubert * ObjC:
397c50c785cSJohn Marino * Following functions help construct Objective-C message calls.
3985796c8dcSSimon Schubert */
3995796c8dcSSimon Schubert
4005796c8dcSSimon Schubert struct selname /* For parsing Objective-C. */
4015796c8dcSSimon Schubert {
4025796c8dcSSimon Schubert struct selname *next;
4035796c8dcSSimon Schubert char *msglist_sel;
4045796c8dcSSimon Schubert int msglist_len;
4055796c8dcSSimon Schubert };
4065796c8dcSSimon Schubert
4075796c8dcSSimon Schubert static int msglist_len;
4085796c8dcSSimon Schubert static struct selname *selname_chain;
4095796c8dcSSimon Schubert static char *msglist_sel;
4105796c8dcSSimon Schubert
4115796c8dcSSimon Schubert void
start_msglist(void)4125796c8dcSSimon Schubert start_msglist(void)
4135796c8dcSSimon Schubert {
4145796c8dcSSimon Schubert struct selname *new =
4155796c8dcSSimon Schubert (struct selname *) xmalloc (sizeof (struct selname));
4165796c8dcSSimon Schubert
4175796c8dcSSimon Schubert new->next = selname_chain;
4185796c8dcSSimon Schubert new->msglist_len = msglist_len;
4195796c8dcSSimon Schubert new->msglist_sel = msglist_sel;
4205796c8dcSSimon Schubert msglist_len = 0;
4215796c8dcSSimon Schubert msglist_sel = (char *)xmalloc(1);
4225796c8dcSSimon Schubert *msglist_sel = 0;
4235796c8dcSSimon Schubert selname_chain = new;
4245796c8dcSSimon Schubert }
4255796c8dcSSimon Schubert
4265796c8dcSSimon Schubert void
add_msglist(struct stoken * str,int addcolon)4275796c8dcSSimon Schubert add_msglist(struct stoken *str, int addcolon)
4285796c8dcSSimon Schubert {
4295796c8dcSSimon Schubert char *s, *p;
4305796c8dcSSimon Schubert int len, plen;
4315796c8dcSSimon Schubert
432cf7f2e2dSJohn Marino if (str == 0) /* Unnamed arg, or... */
433cf7f2e2dSJohn Marino {
434cf7f2e2dSJohn Marino if (addcolon == 0) /* variable number of args. */
435cf7f2e2dSJohn Marino {
4365796c8dcSSimon Schubert msglist_len++;
4375796c8dcSSimon Schubert return;
4385796c8dcSSimon Schubert }
4395796c8dcSSimon Schubert p = "";
4405796c8dcSSimon Schubert plen = 0;
441cf7f2e2dSJohn Marino }
442cf7f2e2dSJohn Marino else
443cf7f2e2dSJohn Marino {
4445796c8dcSSimon Schubert p = str->ptr;
4455796c8dcSSimon Schubert plen = str->length;
4465796c8dcSSimon Schubert }
4475796c8dcSSimon Schubert len = plen + strlen(msglist_sel) + 2;
4485796c8dcSSimon Schubert s = (char *)xmalloc(len);
4495796c8dcSSimon Schubert strcpy(s, msglist_sel);
4505796c8dcSSimon Schubert strncat(s, p, plen);
4515796c8dcSSimon Schubert xfree(msglist_sel);
4525796c8dcSSimon Schubert msglist_sel = s;
453cf7f2e2dSJohn Marino if (addcolon)
454cf7f2e2dSJohn Marino {
4555796c8dcSSimon Schubert s[len-2] = ':';
4565796c8dcSSimon Schubert s[len-1] = 0;
4575796c8dcSSimon Schubert msglist_len++;
458cf7f2e2dSJohn Marino }
459cf7f2e2dSJohn Marino else
4605796c8dcSSimon Schubert s[len-2] = '\0';
4615796c8dcSSimon Schubert }
4625796c8dcSSimon Schubert
4635796c8dcSSimon Schubert int
end_msglist(void)4645796c8dcSSimon Schubert end_msglist(void)
4655796c8dcSSimon Schubert {
4665796c8dcSSimon Schubert int val = msglist_len;
4675796c8dcSSimon Schubert struct selname *sel = selname_chain;
4685796c8dcSSimon Schubert char *p = msglist_sel;
4695796c8dcSSimon Schubert CORE_ADDR selid;
4705796c8dcSSimon Schubert
4715796c8dcSSimon Schubert selname_chain = sel->next;
4725796c8dcSSimon Schubert msglist_len = sel->msglist_len;
4735796c8dcSSimon Schubert msglist_sel = sel->msglist_sel;
4745796c8dcSSimon Schubert selid = lookup_child_selector (parse_gdbarch, p);
4755796c8dcSSimon Schubert if (!selid)
4765796c8dcSSimon Schubert error (_("Can't find selector \"%s\""), p);
4775796c8dcSSimon Schubert write_exp_elt_longcst (selid);
4785796c8dcSSimon Schubert xfree(p);
4795796c8dcSSimon Schubert write_exp_elt_longcst (val); /* Number of args */
4805796c8dcSSimon Schubert xfree(sel);
4815796c8dcSSimon Schubert
4825796c8dcSSimon Schubert return val;
4835796c8dcSSimon Schubert }
4845796c8dcSSimon Schubert
4855796c8dcSSimon Schubert /*
486*ef5ccd6cSJohn Marino * Function: specialcmp (const char *a, const char *b)
4875796c8dcSSimon Schubert *
4885796c8dcSSimon Schubert * Special strcmp: treats ']' and ' ' as end-of-string.
4895796c8dcSSimon Schubert * Used for qsorting lists of objc methods (either by class or selector).
4905796c8dcSSimon Schubert */
4915796c8dcSSimon Schubert
4925796c8dcSSimon Schubert static int
specialcmp(const char * a,const char * b)493*ef5ccd6cSJohn Marino specialcmp (const char *a, const char *b)
4945796c8dcSSimon Schubert {
4955796c8dcSSimon Schubert while (*a && *a != ' ' && *a != ']' && *b && *b != ' ' && *b != ']')
4965796c8dcSSimon Schubert {
4975796c8dcSSimon Schubert if (*a != *b)
4985796c8dcSSimon Schubert return *a - *b;
4995796c8dcSSimon Schubert a++, b++;
5005796c8dcSSimon Schubert }
5015796c8dcSSimon Schubert if (*a && *a != ' ' && *a != ']')
502c50c785cSJohn Marino return 1; /* a is longer therefore greater. */
5035796c8dcSSimon Schubert if (*b && *b != ' ' && *b != ']')
504c50c785cSJohn Marino return -1; /* a is shorter therefore lesser. */
505c50c785cSJohn Marino return 0; /* a and b are identical. */
5065796c8dcSSimon Schubert }
5075796c8dcSSimon Schubert
5085796c8dcSSimon Schubert /*
5095796c8dcSSimon Schubert * Function: compare_selectors (const void *, const void *)
5105796c8dcSSimon Schubert *
5115796c8dcSSimon Schubert * Comparison function for use with qsort. Arguments are symbols or
5125796c8dcSSimon Schubert * msymbols Compares selector part of objc method name alphabetically.
5135796c8dcSSimon Schubert */
5145796c8dcSSimon Schubert
5155796c8dcSSimon Schubert static int
compare_selectors(const void * a,const void * b)5165796c8dcSSimon Schubert compare_selectors (const void *a, const void *b)
5175796c8dcSSimon Schubert {
518*ef5ccd6cSJohn Marino const char *aname, *bname;
5195796c8dcSSimon Schubert
5205796c8dcSSimon Schubert aname = SYMBOL_PRINT_NAME (*(struct symbol **) a);
5215796c8dcSSimon Schubert bname = SYMBOL_PRINT_NAME (*(struct symbol **) b);
5225796c8dcSSimon Schubert if (aname == NULL || bname == NULL)
5235796c8dcSSimon Schubert error (_("internal: compare_selectors(1)"));
5245796c8dcSSimon Schubert
5255796c8dcSSimon Schubert aname = strchr(aname, ' ');
5265796c8dcSSimon Schubert bname = strchr(bname, ' ');
5275796c8dcSSimon Schubert if (aname == NULL || bname == NULL)
5285796c8dcSSimon Schubert error (_("internal: compare_selectors(2)"));
5295796c8dcSSimon Schubert
5305796c8dcSSimon Schubert return specialcmp (aname+1, bname+1);
5315796c8dcSSimon Schubert }
5325796c8dcSSimon Schubert
5335796c8dcSSimon Schubert /*
5345796c8dcSSimon Schubert * Function: selectors_info (regexp, from_tty)
5355796c8dcSSimon Schubert *
5365796c8dcSSimon Schubert * Implements the "Info selectors" command. Takes an optional regexp
5375796c8dcSSimon Schubert * arg. Lists all objective c selectors that match the regexp. Works
5385796c8dcSSimon Schubert * by grepping thru all symbols for objective c methods. Output list
5395796c8dcSSimon Schubert * is sorted and uniqued.
5405796c8dcSSimon Schubert */
5415796c8dcSSimon Schubert
5425796c8dcSSimon Schubert static void
selectors_info(char * regexp,int from_tty)5435796c8dcSSimon Schubert selectors_info (char *regexp, int from_tty)
5445796c8dcSSimon Schubert {
5455796c8dcSSimon Schubert struct objfile *objfile;
5465796c8dcSSimon Schubert struct minimal_symbol *msymbol;
547*ef5ccd6cSJohn Marino const char *name;
5485796c8dcSSimon Schubert char *val;
5495796c8dcSSimon Schubert int matches = 0;
5505796c8dcSSimon Schubert int maxlen = 0;
5515796c8dcSSimon Schubert int ix;
5525796c8dcSSimon Schubert char myregexp[2048];
5535796c8dcSSimon Schubert char asel[256];
5545796c8dcSSimon Schubert struct symbol **sym_arr;
5555796c8dcSSimon Schubert int plusminus = 0;
5565796c8dcSSimon Schubert
5575796c8dcSSimon Schubert if (regexp == NULL)
5585796c8dcSSimon Schubert strcpy(myregexp, ".*]"); /* Null input, match all objc methods. */
5595796c8dcSSimon Schubert else
5605796c8dcSSimon Schubert {
5615796c8dcSSimon Schubert if (*regexp == '+' || *regexp == '-')
5625796c8dcSSimon Schubert { /* User wants only class methods or only instance methods. */
5635796c8dcSSimon Schubert plusminus = *regexp++;
5645796c8dcSSimon Schubert while (*regexp == ' ' || *regexp == '\t')
5655796c8dcSSimon Schubert regexp++;
5665796c8dcSSimon Schubert }
5675796c8dcSSimon Schubert if (*regexp == '\0')
5685796c8dcSSimon Schubert strcpy(myregexp, ".*]");
5695796c8dcSSimon Schubert else
5705796c8dcSSimon Schubert {
571c50c785cSJohn Marino /* Allow a few extra bytes because of the strcat below. */
572c50c785cSJohn Marino if (sizeof (myregexp) < strlen (regexp) + 4)
573c50c785cSJohn Marino error (_("Regexp is too long: %s"), regexp);
5745796c8dcSSimon Schubert strcpy(myregexp, regexp);
5755796c8dcSSimon Schubert if (myregexp[strlen(myregexp) - 1] == '$') /* end of selector */
5765796c8dcSSimon Schubert myregexp[strlen(myregexp) - 1] = ']'; /* end of method name */
5775796c8dcSSimon Schubert else
5785796c8dcSSimon Schubert strcat(myregexp, ".*]");
5795796c8dcSSimon Schubert }
5805796c8dcSSimon Schubert }
5815796c8dcSSimon Schubert
5825796c8dcSSimon Schubert if (regexp != NULL)
5835796c8dcSSimon Schubert {
5845796c8dcSSimon Schubert val = re_comp (myregexp);
5855796c8dcSSimon Schubert if (val != 0)
5865796c8dcSSimon Schubert error (_("Invalid regexp (%s): %s"), val, regexp);
5875796c8dcSSimon Schubert }
5885796c8dcSSimon Schubert
5895796c8dcSSimon Schubert /* First time thru is JUST to get max length and count. */
5905796c8dcSSimon Schubert ALL_MSYMBOLS (objfile, msymbol)
5915796c8dcSSimon Schubert {
5925796c8dcSSimon Schubert QUIT;
5935796c8dcSSimon Schubert name = SYMBOL_NATURAL_NAME (msymbol);
594c50c785cSJohn Marino if (name
595c50c785cSJohn Marino && (name[0] == '-' || name[0] == '+')
596c50c785cSJohn Marino && name[1] == '[') /* Got a method name. */
5975796c8dcSSimon Schubert {
5985796c8dcSSimon Schubert /* Filter for class/instance methods. */
5995796c8dcSSimon Schubert if (plusminus && name[0] != plusminus)
6005796c8dcSSimon Schubert continue;
6015796c8dcSSimon Schubert /* Find selector part. */
6025796c8dcSSimon Schubert name = (char *) strchr (name+2, ' ');
603c50c785cSJohn Marino if (name == NULL)
604c50c785cSJohn Marino {
605c50c785cSJohn Marino complaint (&symfile_complaints,
606c50c785cSJohn Marino _("Bad method name '%s'"),
607c50c785cSJohn Marino SYMBOL_NATURAL_NAME (msymbol));
608c50c785cSJohn Marino continue;
609c50c785cSJohn Marino }
6105796c8dcSSimon Schubert if (regexp == NULL || re_exec(++name) != 0)
6115796c8dcSSimon Schubert {
612*ef5ccd6cSJohn Marino const char *mystart = name;
613*ef5ccd6cSJohn Marino const char *myend = strchr (mystart, ']');
6145796c8dcSSimon Schubert
6155796c8dcSSimon Schubert if (myend && (myend - mystart > maxlen))
6165796c8dcSSimon Schubert maxlen = myend - mystart; /* Get longest selector. */
6175796c8dcSSimon Schubert matches++;
6185796c8dcSSimon Schubert }
6195796c8dcSSimon Schubert }
6205796c8dcSSimon Schubert }
6215796c8dcSSimon Schubert if (matches)
6225796c8dcSSimon Schubert {
6235796c8dcSSimon Schubert printf_filtered (_("Selectors matching \"%s\":\n\n"),
6245796c8dcSSimon Schubert regexp ? regexp : "*");
6255796c8dcSSimon Schubert
6265796c8dcSSimon Schubert sym_arr = alloca (matches * sizeof (struct symbol *));
6275796c8dcSSimon Schubert matches = 0;
6285796c8dcSSimon Schubert ALL_MSYMBOLS (objfile, msymbol)
6295796c8dcSSimon Schubert {
6305796c8dcSSimon Schubert QUIT;
6315796c8dcSSimon Schubert name = SYMBOL_NATURAL_NAME (msymbol);
6325796c8dcSSimon Schubert if (name &&
6335796c8dcSSimon Schubert (name[0] == '-' || name[0] == '+') &&
6345796c8dcSSimon Schubert name[1] == '[') /* Got a method name. */
6355796c8dcSSimon Schubert {
6365796c8dcSSimon Schubert /* Filter for class/instance methods. */
6375796c8dcSSimon Schubert if (plusminus && name[0] != plusminus)
6385796c8dcSSimon Schubert continue;
6395796c8dcSSimon Schubert /* Find selector part. */
6405796c8dcSSimon Schubert name = (char *) strchr(name+2, ' ');
6415796c8dcSSimon Schubert if (regexp == NULL || re_exec(++name) != 0)
6425796c8dcSSimon Schubert sym_arr[matches++] = (struct symbol *) msymbol;
6435796c8dcSSimon Schubert }
6445796c8dcSSimon Schubert }
6455796c8dcSSimon Schubert
6465796c8dcSSimon Schubert qsort (sym_arr, matches, sizeof (struct minimal_symbol *),
6475796c8dcSSimon Schubert compare_selectors);
6485796c8dcSSimon Schubert /* Prevent compare on first iteration. */
6495796c8dcSSimon Schubert asel[0] = 0;
6505796c8dcSSimon Schubert for (ix = 0; ix < matches; ix++) /* Now do the output. */
6515796c8dcSSimon Schubert {
6525796c8dcSSimon Schubert char *p = asel;
6535796c8dcSSimon Schubert
6545796c8dcSSimon Schubert QUIT;
6555796c8dcSSimon Schubert name = SYMBOL_NATURAL_NAME (sym_arr[ix]);
6565796c8dcSSimon Schubert name = strchr (name, ' ') + 1;
6575796c8dcSSimon Schubert if (p[0] && specialcmp(name, p) == 0)
6585796c8dcSSimon Schubert continue; /* Seen this one already (not unique). */
6595796c8dcSSimon Schubert
6605796c8dcSSimon Schubert /* Copy selector part. */
6615796c8dcSSimon Schubert while (*name && *name != ']')
6625796c8dcSSimon Schubert *p++ = *name++;
6635796c8dcSSimon Schubert *p++ = '\0';
6645796c8dcSSimon Schubert /* Print in columns. */
6655796c8dcSSimon Schubert puts_filtered_tabular(asel, maxlen + 1, 0);
6665796c8dcSSimon Schubert }
6675796c8dcSSimon Schubert begin_line();
6685796c8dcSSimon Schubert }
6695796c8dcSSimon Schubert else
670c50c785cSJohn Marino printf_filtered (_("No selectors matching \"%s\"\n"),
671c50c785cSJohn Marino regexp ? regexp : "*");
6725796c8dcSSimon Schubert }
6735796c8dcSSimon Schubert
6745796c8dcSSimon Schubert /*
6755796c8dcSSimon Schubert * Function: compare_classes (const void *, const void *)
6765796c8dcSSimon Schubert *
6775796c8dcSSimon Schubert * Comparison function for use with qsort. Arguments are symbols or
6785796c8dcSSimon Schubert * msymbols Compares class part of objc method name alphabetically.
6795796c8dcSSimon Schubert */
6805796c8dcSSimon Schubert
6815796c8dcSSimon Schubert static int
compare_classes(const void * a,const void * b)6825796c8dcSSimon Schubert compare_classes (const void *a, const void *b)
6835796c8dcSSimon Schubert {
684*ef5ccd6cSJohn Marino const char *aname, *bname;
6855796c8dcSSimon Schubert
6865796c8dcSSimon Schubert aname = SYMBOL_PRINT_NAME (*(struct symbol **) a);
6875796c8dcSSimon Schubert bname = SYMBOL_PRINT_NAME (*(struct symbol **) b);
6885796c8dcSSimon Schubert if (aname == NULL || bname == NULL)
6895796c8dcSSimon Schubert error (_("internal: compare_classes(1)"));
6905796c8dcSSimon Schubert
6915796c8dcSSimon Schubert return specialcmp (aname+1, bname+1);
6925796c8dcSSimon Schubert }
6935796c8dcSSimon Schubert
6945796c8dcSSimon Schubert /*
6955796c8dcSSimon Schubert * Function: classes_info(regexp, from_tty)
6965796c8dcSSimon Schubert *
6975796c8dcSSimon Schubert * Implements the "info classes" command for objective c classes.
6985796c8dcSSimon Schubert * Lists all objective c classes that match the optional regexp.
6995796c8dcSSimon Schubert * Works by grepping thru the list of objective c methods. List will
7005796c8dcSSimon Schubert * be sorted and uniqued (since one class may have many methods).
7015796c8dcSSimon Schubert * BUGS: will not list a class that has no methods.
7025796c8dcSSimon Schubert */
7035796c8dcSSimon Schubert
7045796c8dcSSimon Schubert static void
classes_info(char * regexp,int from_tty)7055796c8dcSSimon Schubert classes_info (char *regexp, int from_tty)
7065796c8dcSSimon Schubert {
7075796c8dcSSimon Schubert struct objfile *objfile;
7085796c8dcSSimon Schubert struct minimal_symbol *msymbol;
709*ef5ccd6cSJohn Marino const char *name;
7105796c8dcSSimon Schubert char *val;
7115796c8dcSSimon Schubert int matches = 0;
7125796c8dcSSimon Schubert int maxlen = 0;
7135796c8dcSSimon Schubert int ix;
7145796c8dcSSimon Schubert char myregexp[2048];
7155796c8dcSSimon Schubert char aclass[256];
7165796c8dcSSimon Schubert struct symbol **sym_arr;
7175796c8dcSSimon Schubert
7185796c8dcSSimon Schubert if (regexp == NULL)
7195796c8dcSSimon Schubert strcpy(myregexp, ".* "); /* Null input: match all objc classes. */
7205796c8dcSSimon Schubert else
7215796c8dcSSimon Schubert {
722c50c785cSJohn Marino /* Allow a few extra bytes because of the strcat below. */
723c50c785cSJohn Marino if (sizeof (myregexp) < strlen (regexp) + 4)
724c50c785cSJohn Marino error (_("Regexp is too long: %s"), regexp);
7255796c8dcSSimon Schubert strcpy(myregexp, regexp);
7265796c8dcSSimon Schubert if (myregexp[strlen(myregexp) - 1] == '$')
7275796c8dcSSimon Schubert /* In the method name, the end of the class name is marked by ' '. */
7285796c8dcSSimon Schubert myregexp[strlen(myregexp) - 1] = ' ';
7295796c8dcSSimon Schubert else
7305796c8dcSSimon Schubert strcat(myregexp, ".* ");
7315796c8dcSSimon Schubert }
7325796c8dcSSimon Schubert
7335796c8dcSSimon Schubert if (regexp != NULL)
7345796c8dcSSimon Schubert {
7355796c8dcSSimon Schubert val = re_comp (myregexp);
7365796c8dcSSimon Schubert if (val != 0)
7375796c8dcSSimon Schubert error (_("Invalid regexp (%s): %s"), val, regexp);
7385796c8dcSSimon Schubert }
7395796c8dcSSimon Schubert
7405796c8dcSSimon Schubert /* First time thru is JUST to get max length and count. */
7415796c8dcSSimon Schubert ALL_MSYMBOLS (objfile, msymbol)
7425796c8dcSSimon Schubert {
7435796c8dcSSimon Schubert QUIT;
7445796c8dcSSimon Schubert name = SYMBOL_NATURAL_NAME (msymbol);
7455796c8dcSSimon Schubert if (name &&
7465796c8dcSSimon Schubert (name[0] == '-' || name[0] == '+') &&
7475796c8dcSSimon Schubert name[1] == '[') /* Got a method name. */
7485796c8dcSSimon Schubert if (regexp == NULL || re_exec(name+2) != 0)
7495796c8dcSSimon Schubert {
7505796c8dcSSimon Schubert /* Compute length of classname part. */
751*ef5ccd6cSJohn Marino const char *mystart = name + 2;
752*ef5ccd6cSJohn Marino const char *myend = strchr (mystart, ' ');
7535796c8dcSSimon Schubert
7545796c8dcSSimon Schubert if (myend && (myend - mystart > maxlen))
7555796c8dcSSimon Schubert maxlen = myend - mystart;
7565796c8dcSSimon Schubert matches++;
7575796c8dcSSimon Schubert }
7585796c8dcSSimon Schubert }
7595796c8dcSSimon Schubert if (matches)
7605796c8dcSSimon Schubert {
7615796c8dcSSimon Schubert printf_filtered (_("Classes matching \"%s\":\n\n"),
7625796c8dcSSimon Schubert regexp ? regexp : "*");
7635796c8dcSSimon Schubert sym_arr = alloca (matches * sizeof (struct symbol *));
7645796c8dcSSimon Schubert matches = 0;
7655796c8dcSSimon Schubert ALL_MSYMBOLS (objfile, msymbol)
7665796c8dcSSimon Schubert {
7675796c8dcSSimon Schubert QUIT;
7685796c8dcSSimon Schubert name = SYMBOL_NATURAL_NAME (msymbol);
7695796c8dcSSimon Schubert if (name &&
7705796c8dcSSimon Schubert (name[0] == '-' || name[0] == '+') &&
7715796c8dcSSimon Schubert name[1] == '[') /* Got a method name. */
7725796c8dcSSimon Schubert if (regexp == NULL || re_exec(name+2) != 0)
7735796c8dcSSimon Schubert sym_arr[matches++] = (struct symbol *) msymbol;
7745796c8dcSSimon Schubert }
7755796c8dcSSimon Schubert
7765796c8dcSSimon Schubert qsort (sym_arr, matches, sizeof (struct minimal_symbol *),
7775796c8dcSSimon Schubert compare_classes);
7785796c8dcSSimon Schubert /* Prevent compare on first iteration. */
7795796c8dcSSimon Schubert aclass[0] = 0;
7805796c8dcSSimon Schubert for (ix = 0; ix < matches; ix++) /* Now do the output. */
7815796c8dcSSimon Schubert {
7825796c8dcSSimon Schubert char *p = aclass;
7835796c8dcSSimon Schubert
7845796c8dcSSimon Schubert QUIT;
7855796c8dcSSimon Schubert name = SYMBOL_NATURAL_NAME (sym_arr[ix]);
7865796c8dcSSimon Schubert name += 2;
7875796c8dcSSimon Schubert if (p[0] && specialcmp(name, p) == 0)
7885796c8dcSSimon Schubert continue; /* Seen this one already (not unique). */
7895796c8dcSSimon Schubert
7905796c8dcSSimon Schubert /* Copy class part of method name. */
7915796c8dcSSimon Schubert while (*name && *name != ' ')
7925796c8dcSSimon Schubert *p++ = *name++;
7935796c8dcSSimon Schubert *p++ = '\0';
7945796c8dcSSimon Schubert /* Print in columns. */
7955796c8dcSSimon Schubert puts_filtered_tabular(aclass, maxlen + 1, 0);
7965796c8dcSSimon Schubert }
7975796c8dcSSimon Schubert begin_line();
7985796c8dcSSimon Schubert }
7995796c8dcSSimon Schubert else
8005796c8dcSSimon Schubert printf_filtered (_("No classes matching \"%s\"\n"), regexp ? regexp : "*");
8015796c8dcSSimon Schubert }
8025796c8dcSSimon Schubert
803a45ae5f8SJohn Marino static char *
parse_selector(char * method,char ** selector)8045796c8dcSSimon Schubert parse_selector (char *method, char **selector)
8055796c8dcSSimon Schubert {
8065796c8dcSSimon Schubert char *s1 = NULL;
8075796c8dcSSimon Schubert char *s2 = NULL;
8085796c8dcSSimon Schubert int found_quote = 0;
8095796c8dcSSimon Schubert
8105796c8dcSSimon Schubert char *nselector = NULL;
8115796c8dcSSimon Schubert
8125796c8dcSSimon Schubert gdb_assert (selector != NULL);
8135796c8dcSSimon Schubert
8145796c8dcSSimon Schubert s1 = method;
8155796c8dcSSimon Schubert
816*ef5ccd6cSJohn Marino s1 = skip_spaces (s1);
8175796c8dcSSimon Schubert if (*s1 == '\'')
8185796c8dcSSimon Schubert {
8195796c8dcSSimon Schubert found_quote = 1;
8205796c8dcSSimon Schubert s1++;
8215796c8dcSSimon Schubert }
822*ef5ccd6cSJohn Marino s1 = skip_spaces (s1);
8235796c8dcSSimon Schubert
8245796c8dcSSimon Schubert nselector = s1;
8255796c8dcSSimon Schubert s2 = s1;
8265796c8dcSSimon Schubert
827cf7f2e2dSJohn Marino for (;;)
828cf7f2e2dSJohn Marino {
8295796c8dcSSimon Schubert if (isalnum (*s2) || (*s2 == '_') || (*s2 == ':'))
8305796c8dcSSimon Schubert *s1++ = *s2;
8315796c8dcSSimon Schubert else if (isspace (*s2))
8325796c8dcSSimon Schubert ;
8335796c8dcSSimon Schubert else if ((*s2 == '\0') || (*s2 == '\''))
8345796c8dcSSimon Schubert break;
8355796c8dcSSimon Schubert else
8365796c8dcSSimon Schubert return NULL;
8375796c8dcSSimon Schubert s2++;
8385796c8dcSSimon Schubert }
8395796c8dcSSimon Schubert *s1++ = '\0';
8405796c8dcSSimon Schubert
841*ef5ccd6cSJohn Marino s2 = skip_spaces (s2);
8425796c8dcSSimon Schubert if (found_quote)
8435796c8dcSSimon Schubert {
8445796c8dcSSimon Schubert if (*s2 == '\'')
8455796c8dcSSimon Schubert s2++;
846*ef5ccd6cSJohn Marino s2 = skip_spaces (s2);
8475796c8dcSSimon Schubert }
8485796c8dcSSimon Schubert
8495796c8dcSSimon Schubert if (selector != NULL)
8505796c8dcSSimon Schubert *selector = nselector;
8515796c8dcSSimon Schubert
8525796c8dcSSimon Schubert return s2;
8535796c8dcSSimon Schubert }
8545796c8dcSSimon Schubert
855a45ae5f8SJohn Marino static char *
parse_method(char * method,char * type,char ** class,char ** category,char ** selector)8565796c8dcSSimon Schubert parse_method (char *method, char *type, char **class,
8575796c8dcSSimon Schubert char **category, char **selector)
8585796c8dcSSimon Schubert {
8595796c8dcSSimon Schubert char *s1 = NULL;
8605796c8dcSSimon Schubert char *s2 = NULL;
8615796c8dcSSimon Schubert int found_quote = 0;
8625796c8dcSSimon Schubert
8635796c8dcSSimon Schubert char ntype = '\0';
8645796c8dcSSimon Schubert char *nclass = NULL;
8655796c8dcSSimon Schubert char *ncategory = NULL;
8665796c8dcSSimon Schubert char *nselector = NULL;
8675796c8dcSSimon Schubert
8685796c8dcSSimon Schubert gdb_assert (type != NULL);
8695796c8dcSSimon Schubert gdb_assert (class != NULL);
8705796c8dcSSimon Schubert gdb_assert (category != NULL);
8715796c8dcSSimon Schubert gdb_assert (selector != NULL);
8725796c8dcSSimon Schubert
8735796c8dcSSimon Schubert s1 = method;
8745796c8dcSSimon Schubert
875*ef5ccd6cSJohn Marino s1 = skip_spaces (s1);
8765796c8dcSSimon Schubert if (*s1 == '\'')
8775796c8dcSSimon Schubert {
8785796c8dcSSimon Schubert found_quote = 1;
8795796c8dcSSimon Schubert s1++;
8805796c8dcSSimon Schubert }
881*ef5ccd6cSJohn Marino s1 = skip_spaces (s1);
8825796c8dcSSimon Schubert
8835796c8dcSSimon Schubert if ((s1[0] == '+') || (s1[0] == '-'))
8845796c8dcSSimon Schubert ntype = *s1++;
8855796c8dcSSimon Schubert
886*ef5ccd6cSJohn Marino s1 = skip_spaces (s1);
8875796c8dcSSimon Schubert
8885796c8dcSSimon Schubert if (*s1 != '[')
8895796c8dcSSimon Schubert return NULL;
8905796c8dcSSimon Schubert s1++;
8915796c8dcSSimon Schubert
8925796c8dcSSimon Schubert nclass = s1;
8935796c8dcSSimon Schubert while (isalnum (*s1) || (*s1 == '_'))
8945796c8dcSSimon Schubert s1++;
8955796c8dcSSimon Schubert
8965796c8dcSSimon Schubert s2 = s1;
897*ef5ccd6cSJohn Marino s2 = skip_spaces (s2);
8985796c8dcSSimon Schubert
8995796c8dcSSimon Schubert if (*s2 == '(')
9005796c8dcSSimon Schubert {
9015796c8dcSSimon Schubert s2++;
902*ef5ccd6cSJohn Marino s2 = skip_spaces (s2);
9035796c8dcSSimon Schubert ncategory = s2;
9045796c8dcSSimon Schubert while (isalnum (*s2) || (*s2 == '_'))
9055796c8dcSSimon Schubert s2++;
9065796c8dcSSimon Schubert *s2++ = '\0';
9075796c8dcSSimon Schubert }
9085796c8dcSSimon Schubert
9095796c8dcSSimon Schubert /* Truncate the class name now that we're not using the open paren. */
9105796c8dcSSimon Schubert *s1++ = '\0';
9115796c8dcSSimon Schubert
9125796c8dcSSimon Schubert nselector = s2;
9135796c8dcSSimon Schubert s1 = s2;
9145796c8dcSSimon Schubert
915cf7f2e2dSJohn Marino for (;;)
916cf7f2e2dSJohn Marino {
9175796c8dcSSimon Schubert if (isalnum (*s2) || (*s2 == '_') || (*s2 == ':'))
9185796c8dcSSimon Schubert *s1++ = *s2;
9195796c8dcSSimon Schubert else if (isspace (*s2))
9205796c8dcSSimon Schubert ;
9215796c8dcSSimon Schubert else if (*s2 == ']')
9225796c8dcSSimon Schubert break;
9235796c8dcSSimon Schubert else
9245796c8dcSSimon Schubert return NULL;
9255796c8dcSSimon Schubert s2++;
9265796c8dcSSimon Schubert }
9275796c8dcSSimon Schubert *s1++ = '\0';
9285796c8dcSSimon Schubert s2++;
9295796c8dcSSimon Schubert
930*ef5ccd6cSJohn Marino s2 = skip_spaces (s2);
9315796c8dcSSimon Schubert if (found_quote)
9325796c8dcSSimon Schubert {
9335796c8dcSSimon Schubert if (*s2 != '\'')
9345796c8dcSSimon Schubert return NULL;
9355796c8dcSSimon Schubert s2++;
936*ef5ccd6cSJohn Marino s2 = skip_spaces (s2);
9375796c8dcSSimon Schubert }
9385796c8dcSSimon Schubert
9395796c8dcSSimon Schubert if (type != NULL)
9405796c8dcSSimon Schubert *type = ntype;
9415796c8dcSSimon Schubert if (class != NULL)
9425796c8dcSSimon Schubert *class = nclass;
9435796c8dcSSimon Schubert if (category != NULL)
9445796c8dcSSimon Schubert *category = ncategory;
9455796c8dcSSimon Schubert if (selector != NULL)
9465796c8dcSSimon Schubert *selector = nselector;
9475796c8dcSSimon Schubert
9485796c8dcSSimon Schubert return s2;
9495796c8dcSSimon Schubert }
9505796c8dcSSimon Schubert
9515796c8dcSSimon Schubert static void
find_methods(char type,const char * class,const char * category,const char * selector,VEC (const_char_ptr)** symbol_names)952a45ae5f8SJohn Marino find_methods (char type, const char *class, const char *category,
953a45ae5f8SJohn Marino const char *selector,
954a45ae5f8SJohn Marino VEC (const_char_ptr) **symbol_names)
9555796c8dcSSimon Schubert {
9565796c8dcSSimon Schubert struct objfile *objfile = NULL;
9575796c8dcSSimon Schubert
958*ef5ccd6cSJohn Marino const char *symname = NULL;
9595796c8dcSSimon Schubert
9605796c8dcSSimon Schubert char ntype = '\0';
9615796c8dcSSimon Schubert char *nclass = NULL;
9625796c8dcSSimon Schubert char *ncategory = NULL;
9635796c8dcSSimon Schubert char *nselector = NULL;
9645796c8dcSSimon Schubert
9655796c8dcSSimon Schubert static char *tmp = NULL;
9665796c8dcSSimon Schubert static unsigned int tmplen = 0;
9675796c8dcSSimon Schubert
968a45ae5f8SJohn Marino gdb_assert (symbol_names != NULL);
9695796c8dcSSimon Schubert
9705796c8dcSSimon Schubert ALL_OBJFILES (objfile)
9715796c8dcSSimon Schubert {
9725796c8dcSSimon Schubert unsigned int *objc_csym;
973a45ae5f8SJohn Marino struct minimal_symbol *msymbol = NULL;
9745796c8dcSSimon Schubert
9755796c8dcSSimon Schubert /* The objfile_csym variable counts the number of ObjC methods
9765796c8dcSSimon Schubert that this objfile defines. We save that count as a private
9775796c8dcSSimon Schubert objfile data. If we have already determined that this objfile
9785796c8dcSSimon Schubert provides no ObjC methods, we can skip it entirely. */
9795796c8dcSSimon Schubert
9805796c8dcSSimon Schubert unsigned int objfile_csym = 0;
9815796c8dcSSimon Schubert
9825796c8dcSSimon Schubert objc_csym = objfile_data (objfile, objc_objfile_data);
9835796c8dcSSimon Schubert if (objc_csym != NULL && *objc_csym == 0)
9845796c8dcSSimon Schubert /* There are no ObjC symbols in this objfile. Skip it entirely. */
9855796c8dcSSimon Schubert continue;
9865796c8dcSSimon Schubert
9875796c8dcSSimon Schubert ALL_OBJFILE_MSYMBOLS (objfile, msymbol)
9885796c8dcSSimon Schubert {
9895796c8dcSSimon Schubert QUIT;
9905796c8dcSSimon Schubert
991cf7f2e2dSJohn Marino /* Check the symbol name first as this can be done entirely without
992cf7f2e2dSJohn Marino sending any query to the target. */
9935796c8dcSSimon Schubert symname = SYMBOL_NATURAL_NAME (msymbol);
9945796c8dcSSimon Schubert if (symname == NULL)
9955796c8dcSSimon Schubert continue;
9965796c8dcSSimon Schubert
9975796c8dcSSimon Schubert if ((symname[0] != '-' && symname[0] != '+') || (symname[1] != '['))
9985796c8dcSSimon Schubert /* Not a method name. */
9995796c8dcSSimon Schubert continue;
10005796c8dcSSimon Schubert
1001c50c785cSJohn Marino objfile_csym++;
1002c50c785cSJohn Marino
1003cf7f2e2dSJohn Marino /* Now that thinks are a bit sane, clean up the symname. */
10045796c8dcSSimon Schubert while ((strlen (symname) + 1) >= tmplen)
10055796c8dcSSimon Schubert {
10065796c8dcSSimon Schubert tmplen = (tmplen == 0) ? 1024 : tmplen * 2;
10075796c8dcSSimon Schubert tmp = xrealloc (tmp, tmplen);
10085796c8dcSSimon Schubert }
10095796c8dcSSimon Schubert strcpy (tmp, symname);
10105796c8dcSSimon Schubert
1011c50c785cSJohn Marino if (parse_method (tmp, &ntype, &nclass,
1012c50c785cSJohn Marino &ncategory, &nselector) == NULL)
10135796c8dcSSimon Schubert continue;
10145796c8dcSSimon Schubert
10155796c8dcSSimon Schubert if ((type != '\0') && (ntype != type))
10165796c8dcSSimon Schubert continue;
10175796c8dcSSimon Schubert
10185796c8dcSSimon Schubert if ((class != NULL)
10195796c8dcSSimon Schubert && ((nclass == NULL) || (strcmp (class, nclass) != 0)))
10205796c8dcSSimon Schubert continue;
10215796c8dcSSimon Schubert
10225796c8dcSSimon Schubert if ((category != NULL) &&
10235796c8dcSSimon Schubert ((ncategory == NULL) || (strcmp (category, ncategory) != 0)))
10245796c8dcSSimon Schubert continue;
10255796c8dcSSimon Schubert
10265796c8dcSSimon Schubert if ((selector != NULL) &&
10275796c8dcSSimon Schubert ((nselector == NULL) || (strcmp (selector, nselector) != 0)))
10285796c8dcSSimon Schubert continue;
10295796c8dcSSimon Schubert
1030a45ae5f8SJohn Marino VEC_safe_push (const_char_ptr, *symbol_names, symname);
1031a45ae5f8SJohn Marino }
10325796c8dcSSimon Schubert
10335796c8dcSSimon Schubert if (objc_csym == NULL)
10345796c8dcSSimon Schubert {
10355796c8dcSSimon Schubert objc_csym = obstack_alloc (&objfile->objfile_obstack,
10365796c8dcSSimon Schubert sizeof (*objc_csym));
10375796c8dcSSimon Schubert *objc_csym = objfile_csym;
10385796c8dcSSimon Schubert set_objfile_data (objfile, objc_objfile_data, objc_csym);
10395796c8dcSSimon Schubert }
10405796c8dcSSimon Schubert else
10415796c8dcSSimon Schubert /* Count of ObjC methods in this objfile should be constant. */
10425796c8dcSSimon Schubert gdb_assert (*objc_csym == objfile_csym);
10435796c8dcSSimon Schubert }
10445796c8dcSSimon Schubert }
10455796c8dcSSimon Schubert
1046a45ae5f8SJohn Marino /* Uniquify a VEC of strings. */
1047a45ae5f8SJohn Marino
1048a45ae5f8SJohn Marino static void
uniquify_strings(VEC (const_char_ptr)** strings)1049a45ae5f8SJohn Marino uniquify_strings (VEC (const_char_ptr) **strings)
1050a45ae5f8SJohn Marino {
1051a45ae5f8SJohn Marino int ix;
1052a45ae5f8SJohn Marino const char *elem, *last = NULL;
1053a45ae5f8SJohn Marino int out;
1054a45ae5f8SJohn Marino
1055a45ae5f8SJohn Marino qsort (VEC_address (const_char_ptr, *strings),
1056a45ae5f8SJohn Marino VEC_length (const_char_ptr, *strings),
1057a45ae5f8SJohn Marino sizeof (const_char_ptr),
1058a45ae5f8SJohn Marino compare_strings);
1059a45ae5f8SJohn Marino out = 0;
1060a45ae5f8SJohn Marino for (ix = 0; VEC_iterate (const_char_ptr, *strings, ix, elem); ++ix)
1061a45ae5f8SJohn Marino {
1062a45ae5f8SJohn Marino if (last == NULL || strcmp (last, elem) != 0)
1063a45ae5f8SJohn Marino {
1064a45ae5f8SJohn Marino /* Keep ELEM. */
1065a45ae5f8SJohn Marino VEC_replace (const_char_ptr, *strings, out, elem);
1066a45ae5f8SJohn Marino ++out;
1067a45ae5f8SJohn Marino }
1068a45ae5f8SJohn Marino last = elem;
1069a45ae5f8SJohn Marino }
1070a45ae5f8SJohn Marino VEC_truncate (const_char_ptr, *strings, out);
1071a45ae5f8SJohn Marino }
1072a45ae5f8SJohn Marino
1073a45ae5f8SJohn Marino /*
1074a45ae5f8SJohn Marino * Function: find_imps (char *selector, struct symbol **sym_arr)
1075a45ae5f8SJohn Marino *
1076a45ae5f8SJohn Marino * Input: a string representing a selector
1077a45ae5f8SJohn Marino * a pointer to an array of symbol pointers
1078a45ae5f8SJohn Marino * possibly a pointer to a symbol found by the caller.
1079a45ae5f8SJohn Marino *
1080a45ae5f8SJohn Marino * Output: number of methods that implement that selector. Side
1081a45ae5f8SJohn Marino * effects: The array of symbol pointers is filled with matching syms.
1082a45ae5f8SJohn Marino *
1083a45ae5f8SJohn Marino * By analogy with function "find_methods" (symtab.c), builds a list
1084a45ae5f8SJohn Marino * of symbols matching the ambiguous input, so that "decode_line_2"
1085a45ae5f8SJohn Marino * (symtab.c) can list them and ask the user to choose one or more.
1086a45ae5f8SJohn Marino * In this case the matches are objective c methods
1087a45ae5f8SJohn Marino * ("implementations") matching an objective c selector.
1088a45ae5f8SJohn Marino *
1089a45ae5f8SJohn Marino * Note that it is possible for a normal (c-style) function to have
1090a45ae5f8SJohn Marino * the same name as an objective c selector. To prevent the selector
1091a45ae5f8SJohn Marino * from eclipsing the function, we allow the caller (decode_line_1) to
1092a45ae5f8SJohn Marino * search for such a function first, and if it finds one, pass it in
1093a45ae5f8SJohn Marino * to us. We will then integrate it into the list. We also search
1094a45ae5f8SJohn Marino * for one here, among the minsyms.
1095a45ae5f8SJohn Marino *
1096a45ae5f8SJohn Marino * NOTE: if NUM_DEBUGGABLE is non-zero, the sym_arr will be divided
1097a45ae5f8SJohn Marino * into two parts: debuggable (struct symbol) syms, and
1098a45ae5f8SJohn Marino * non_debuggable (struct minimal_symbol) syms. The debuggable
1099a45ae5f8SJohn Marino * ones will come first, before NUM_DEBUGGABLE (which will thus
1100a45ae5f8SJohn Marino * be the index of the first non-debuggable one).
1101a45ae5f8SJohn Marino */
1102a45ae5f8SJohn Marino
1103a45ae5f8SJohn Marino char *
find_imps(char * method,VEC (const_char_ptr)** symbol_names)1104a45ae5f8SJohn Marino find_imps (char *method, VEC (const_char_ptr) **symbol_names)
11055796c8dcSSimon Schubert {
11065796c8dcSSimon Schubert char type = '\0';
11075796c8dcSSimon Schubert char *class = NULL;
11085796c8dcSSimon Schubert char *category = NULL;
11095796c8dcSSimon Schubert char *selector = NULL;
11105796c8dcSSimon Schubert
11115796c8dcSSimon Schubert char *buf = NULL;
11125796c8dcSSimon Schubert char *tmp = NULL;
11135796c8dcSSimon Schubert
1114a45ae5f8SJohn Marino int selector_case = 0;
11155796c8dcSSimon Schubert
1116a45ae5f8SJohn Marino gdb_assert (symbol_names != NULL);
11175796c8dcSSimon Schubert
11185796c8dcSSimon Schubert buf = (char *) alloca (strlen (method) + 1);
11195796c8dcSSimon Schubert strcpy (buf, method);
11205796c8dcSSimon Schubert tmp = parse_method (buf, &type, &class, &category, &selector);
11215796c8dcSSimon Schubert
1122cf7f2e2dSJohn Marino if (tmp == NULL)
1123cf7f2e2dSJohn Marino {
11245796c8dcSSimon Schubert strcpy (buf, method);
11255796c8dcSSimon Schubert tmp = parse_selector (buf, &selector);
11265796c8dcSSimon Schubert
11275796c8dcSSimon Schubert if (tmp == NULL)
11285796c8dcSSimon Schubert return NULL;
11295796c8dcSSimon Schubert
1130a45ae5f8SJohn Marino selector_case = 1;
11315796c8dcSSimon Schubert }
11325796c8dcSSimon Schubert
1133a45ae5f8SJohn Marino find_methods (type, class, category, selector, symbol_names);
1134a45ae5f8SJohn Marino
1135a45ae5f8SJohn Marino /* If we hit the "selector" case, and we found some methods, then
1136a45ae5f8SJohn Marino add the selector itself as a symbol, if it exists. */
1137a45ae5f8SJohn Marino if (selector_case && !VEC_empty (const_char_ptr, *symbol_names))
1138a45ae5f8SJohn Marino {
1139a45ae5f8SJohn Marino struct symbol *sym = lookup_symbol (selector, NULL, VAR_DOMAIN, 0);
1140a45ae5f8SJohn Marino
1141a45ae5f8SJohn Marino if (sym != NULL)
1142a45ae5f8SJohn Marino VEC_safe_push (const_char_ptr, *symbol_names,
1143a45ae5f8SJohn Marino SYMBOL_NATURAL_NAME (sym));
1144a45ae5f8SJohn Marino else
1145a45ae5f8SJohn Marino {
1146a45ae5f8SJohn Marino struct minimal_symbol *msym = lookup_minimal_symbol (selector, 0, 0);
11475796c8dcSSimon Schubert
11485796c8dcSSimon Schubert if (msym != NULL)
1149a45ae5f8SJohn Marino VEC_safe_push (const_char_ptr, *symbol_names,
1150a45ae5f8SJohn Marino SYMBOL_NATURAL_NAME (msym));
11515796c8dcSSimon Schubert }
11525796c8dcSSimon Schubert }
11535796c8dcSSimon Schubert
1154a45ae5f8SJohn Marino uniquify_strings (symbol_names);
11555796c8dcSSimon Schubert
11565796c8dcSSimon Schubert return method + (tmp - buf);
11575796c8dcSSimon Schubert }
11585796c8dcSSimon Schubert
11595796c8dcSSimon Schubert static void
print_object_command(char * args,int from_tty)11605796c8dcSSimon Schubert print_object_command (char *args, int from_tty)
11615796c8dcSSimon Schubert {
11625796c8dcSSimon Schubert struct value *object, *function, *description;
11635796c8dcSSimon Schubert CORE_ADDR string_addr, object_addr;
11645796c8dcSSimon Schubert int i = 0;
11655796c8dcSSimon Schubert gdb_byte c = 0;
11665796c8dcSSimon Schubert
11675796c8dcSSimon Schubert if (!args || !*args)
11685796c8dcSSimon Schubert error (
11695796c8dcSSimon Schubert "The 'print-object' command requires an argument (an Objective-C object)");
11705796c8dcSSimon Schubert
11715796c8dcSSimon Schubert {
11725796c8dcSSimon Schubert struct expression *expr = parse_expression (args);
11735796c8dcSSimon Schubert struct cleanup *old_chain =
11745796c8dcSSimon Schubert make_cleanup (free_current_contents, &expr);
11755796c8dcSSimon Schubert int pc = 0;
11765796c8dcSSimon Schubert
11775796c8dcSSimon Schubert object = evaluate_subexp (builtin_type (expr->gdbarch)->builtin_data_ptr,
11785796c8dcSSimon Schubert expr, &pc, EVAL_NORMAL);
11795796c8dcSSimon Schubert do_cleanups (old_chain);
11805796c8dcSSimon Schubert }
11815796c8dcSSimon Schubert
11825796c8dcSSimon Schubert /* Validate the address for sanity. */
11835796c8dcSSimon Schubert object_addr = value_as_long (object);
11845796c8dcSSimon Schubert read_memory (object_addr, &c, 1);
11855796c8dcSSimon Schubert
11865796c8dcSSimon Schubert function = find_function_in_inferior ("_NSPrintForDebugger", NULL);
11875796c8dcSSimon Schubert if (function == NULL)
11885796c8dcSSimon Schubert error (_("Unable to locate _NSPrintForDebugger in child process"));
11895796c8dcSSimon Schubert
11905796c8dcSSimon Schubert description = call_function_by_hand (function, 1, &object);
11915796c8dcSSimon Schubert
11925796c8dcSSimon Schubert string_addr = value_as_long (description);
11935796c8dcSSimon Schubert if (string_addr == 0)
11945796c8dcSSimon Schubert error (_("object returns null description"));
11955796c8dcSSimon Schubert
11965796c8dcSSimon Schubert read_memory (string_addr + i++, &c, 1);
11975796c8dcSSimon Schubert if (c != 0)
11985796c8dcSSimon Schubert do
11995796c8dcSSimon Schubert { /* Read and print characters up to EOS. */
12005796c8dcSSimon Schubert QUIT;
12015796c8dcSSimon Schubert printf_filtered ("%c", c);
12025796c8dcSSimon Schubert read_memory (string_addr + i++, &c, 1);
12035796c8dcSSimon Schubert } while (c != 0);
12045796c8dcSSimon Schubert else
12055796c8dcSSimon Schubert printf_filtered(_("<object returns empty description>"));
12065796c8dcSSimon Schubert printf_filtered ("\n");
12075796c8dcSSimon Schubert }
12085796c8dcSSimon Schubert
12095796c8dcSSimon Schubert /* The data structure 'methcalls' is used to detect method calls (thru
12105796c8dcSSimon Schubert * ObjC runtime lib functions objc_msgSend, objc_msgSendSuper, etc.),
12115796c8dcSSimon Schubert * and ultimately find the method being called.
12125796c8dcSSimon Schubert */
12135796c8dcSSimon Schubert
12145796c8dcSSimon Schubert struct objc_methcall {
12155796c8dcSSimon Schubert char *name;
12165796c8dcSSimon Schubert /* Return instance method to be called. */
12175796c8dcSSimon Schubert int (*stop_at) (CORE_ADDR, CORE_ADDR *);
12185796c8dcSSimon Schubert /* Start of pc range corresponding to method invocation. */
12195796c8dcSSimon Schubert CORE_ADDR begin;
12205796c8dcSSimon Schubert /* End of pc range corresponding to method invocation. */
12215796c8dcSSimon Schubert CORE_ADDR end;
12225796c8dcSSimon Schubert };
12235796c8dcSSimon Schubert
12245796c8dcSSimon Schubert static int resolve_msgsend (CORE_ADDR pc, CORE_ADDR *new_pc);
12255796c8dcSSimon Schubert static int resolve_msgsend_stret (CORE_ADDR pc, CORE_ADDR *new_pc);
12265796c8dcSSimon Schubert static int resolve_msgsend_super (CORE_ADDR pc, CORE_ADDR *new_pc);
12275796c8dcSSimon Schubert static int resolve_msgsend_super_stret (CORE_ADDR pc, CORE_ADDR *new_pc);
12285796c8dcSSimon Schubert
12295796c8dcSSimon Schubert static struct objc_methcall methcalls[] = {
12305796c8dcSSimon Schubert { "_objc_msgSend", resolve_msgsend, 0, 0},
12315796c8dcSSimon Schubert { "_objc_msgSend_stret", resolve_msgsend_stret, 0, 0},
12325796c8dcSSimon Schubert { "_objc_msgSendSuper", resolve_msgsend_super, 0, 0},
12335796c8dcSSimon Schubert { "_objc_msgSendSuper_stret", resolve_msgsend_super_stret, 0, 0},
12345796c8dcSSimon Schubert { "_objc_getClass", NULL, 0, 0},
12355796c8dcSSimon Schubert { "_objc_getMetaClass", NULL, 0, 0}
12365796c8dcSSimon Schubert };
12375796c8dcSSimon Schubert
12385796c8dcSSimon Schubert #define nmethcalls (sizeof (methcalls) / sizeof (methcalls[0]))
12395796c8dcSSimon Schubert
12405796c8dcSSimon Schubert /* The following function, "find_objc_msgsend", fills in the data
12415796c8dcSSimon Schubert * structure "objc_msgs" by finding the addresses of each of the
12425796c8dcSSimon Schubert * (currently four) functions that it holds (of which objc_msgSend is
12435796c8dcSSimon Schubert * the first). This must be called each time symbols are loaded, in
12445796c8dcSSimon Schubert * case the functions have moved for some reason.
12455796c8dcSSimon Schubert */
12465796c8dcSSimon Schubert
12475796c8dcSSimon Schubert static void
find_objc_msgsend(void)12485796c8dcSSimon Schubert find_objc_msgsend (void)
12495796c8dcSSimon Schubert {
12505796c8dcSSimon Schubert unsigned int i;
12515796c8dcSSimon Schubert
1252cf7f2e2dSJohn Marino for (i = 0; i < nmethcalls; i++)
1253cf7f2e2dSJohn Marino {
12545796c8dcSSimon Schubert struct minimal_symbol *func;
12555796c8dcSSimon Schubert
12565796c8dcSSimon Schubert /* Try both with and without underscore. */
12575796c8dcSSimon Schubert func = lookup_minimal_symbol (methcalls[i].name, NULL, NULL);
1258cf7f2e2dSJohn Marino if ((func == NULL) && (methcalls[i].name[0] == '_'))
1259cf7f2e2dSJohn Marino {
12605796c8dcSSimon Schubert func = lookup_minimal_symbol (methcalls[i].name + 1, NULL, NULL);
12615796c8dcSSimon Schubert }
1262cf7f2e2dSJohn Marino if (func == NULL)
1263cf7f2e2dSJohn Marino {
12645796c8dcSSimon Schubert methcalls[i].begin = 0;
12655796c8dcSSimon Schubert methcalls[i].end = 0;
12665796c8dcSSimon Schubert continue;
12675796c8dcSSimon Schubert }
12685796c8dcSSimon Schubert
12695796c8dcSSimon Schubert methcalls[i].begin = SYMBOL_VALUE_ADDRESS (func);
12705796c8dcSSimon Schubert do {
12715796c8dcSSimon Schubert methcalls[i].end = SYMBOL_VALUE_ADDRESS (++func);
12725796c8dcSSimon Schubert } while (methcalls[i].begin == methcalls[i].end);
12735796c8dcSSimon Schubert }
12745796c8dcSSimon Schubert }
12755796c8dcSSimon Schubert
12765796c8dcSSimon Schubert /* find_objc_msgcall (replaces pc_off_limits)
12775796c8dcSSimon Schubert *
12785796c8dcSSimon Schubert * ALL that this function now does is to determine whether the input
12795796c8dcSSimon Schubert * address ("pc") is the address of one of the Objective-C message
12805796c8dcSSimon Schubert * dispatch functions (mainly objc_msgSend or objc_msgSendSuper), and
12815796c8dcSSimon Schubert * if so, it returns the address of the method that will be called.
12825796c8dcSSimon Schubert *
12835796c8dcSSimon Schubert * The old function "pc_off_limits" used to do a lot of other things
12845796c8dcSSimon Schubert * in addition, such as detecting shared library jump stubs and
12855796c8dcSSimon Schubert * returning the address of the shlib function that would be called.
12865796c8dcSSimon Schubert * That functionality has been moved into the gdbarch_skip_trampoline_code and
12875796c8dcSSimon Schubert * IN_SOLIB_TRAMPOLINE macros, which are resolved in the target-
12885796c8dcSSimon Schubert * dependent modules.
12895796c8dcSSimon Schubert */
12905796c8dcSSimon Schubert
12915796c8dcSSimon Schubert struct objc_submethod_helper_data {
12925796c8dcSSimon Schubert int (*f) (CORE_ADDR, CORE_ADDR *);
12935796c8dcSSimon Schubert CORE_ADDR pc;
12945796c8dcSSimon Schubert CORE_ADDR *new_pc;
12955796c8dcSSimon Schubert };
12965796c8dcSSimon Schubert
12975796c8dcSSimon Schubert static int
find_objc_msgcall_submethod_helper(void * arg)12985796c8dcSSimon Schubert find_objc_msgcall_submethod_helper (void * arg)
12995796c8dcSSimon Schubert {
13005796c8dcSSimon Schubert struct objc_submethod_helper_data *s =
13015796c8dcSSimon Schubert (struct objc_submethod_helper_data *) arg;
13025796c8dcSSimon Schubert
13035796c8dcSSimon Schubert if (s->f (s->pc, s->new_pc) == 0)
13045796c8dcSSimon Schubert return 1;
13055796c8dcSSimon Schubert else
13065796c8dcSSimon Schubert return 0;
13075796c8dcSSimon Schubert }
13085796c8dcSSimon Schubert
13095796c8dcSSimon Schubert static int
find_objc_msgcall_submethod(int (* f)(CORE_ADDR,CORE_ADDR *),CORE_ADDR pc,CORE_ADDR * new_pc)13105796c8dcSSimon Schubert find_objc_msgcall_submethod (int (*f) (CORE_ADDR, CORE_ADDR *),
13115796c8dcSSimon Schubert CORE_ADDR pc,
13125796c8dcSSimon Schubert CORE_ADDR *new_pc)
13135796c8dcSSimon Schubert {
13145796c8dcSSimon Schubert struct objc_submethod_helper_data s;
13155796c8dcSSimon Schubert
13165796c8dcSSimon Schubert s.f = f;
13175796c8dcSSimon Schubert s.pc = pc;
13185796c8dcSSimon Schubert s.new_pc = new_pc;
13195796c8dcSSimon Schubert
13205796c8dcSSimon Schubert if (catch_errors (find_objc_msgcall_submethod_helper,
13215796c8dcSSimon Schubert (void *) &s,
1322c50c785cSJohn Marino "Unable to determine target of "
1323c50c785cSJohn Marino "Objective-C method call (ignoring):\n",
13245796c8dcSSimon Schubert RETURN_MASK_ALL) == 0)
13255796c8dcSSimon Schubert return 1;
13265796c8dcSSimon Schubert else
13275796c8dcSSimon Schubert return 0;
13285796c8dcSSimon Schubert }
13295796c8dcSSimon Schubert
13305796c8dcSSimon Schubert int
find_objc_msgcall(CORE_ADDR pc,CORE_ADDR * new_pc)13315796c8dcSSimon Schubert find_objc_msgcall (CORE_ADDR pc, CORE_ADDR *new_pc)
13325796c8dcSSimon Schubert {
13335796c8dcSSimon Schubert unsigned int i;
13345796c8dcSSimon Schubert
13355796c8dcSSimon Schubert find_objc_msgsend ();
13365796c8dcSSimon Schubert if (new_pc != NULL)
13375796c8dcSSimon Schubert {
13385796c8dcSSimon Schubert *new_pc = 0;
13395796c8dcSSimon Schubert }
13405796c8dcSSimon Schubert
13415796c8dcSSimon Schubert for (i = 0; i < nmethcalls; i++)
13425796c8dcSSimon Schubert if ((pc >= methcalls[i].begin) && (pc < methcalls[i].end))
13435796c8dcSSimon Schubert {
13445796c8dcSSimon Schubert if (methcalls[i].stop_at != NULL)
13455796c8dcSSimon Schubert return find_objc_msgcall_submethod (methcalls[i].stop_at,
13465796c8dcSSimon Schubert pc, new_pc);
13475796c8dcSSimon Schubert else
13485796c8dcSSimon Schubert return 0;
13495796c8dcSSimon Schubert }
13505796c8dcSSimon Schubert
13515796c8dcSSimon Schubert return 0;
13525796c8dcSSimon Schubert }
13535796c8dcSSimon Schubert
1354c50c785cSJohn Marino /* -Wmissing-prototypes */
1355c50c785cSJohn Marino extern initialize_file_ftype _initialize_objc_language;
13565796c8dcSSimon Schubert
13575796c8dcSSimon Schubert void
_initialize_objc_language(void)13585796c8dcSSimon Schubert _initialize_objc_language (void)
13595796c8dcSSimon Schubert {
13605796c8dcSSimon Schubert add_language (&objc_language_defn);
13615796c8dcSSimon Schubert add_info ("selectors", selectors_info, /* INFO SELECTORS command. */
13625796c8dcSSimon Schubert _("All Objective-C selectors, or those matching REGEXP."));
13635796c8dcSSimon Schubert add_info ("classes", classes_info, /* INFO CLASSES command. */
13645796c8dcSSimon Schubert _("All Objective-C classes, or those matching REGEXP."));
13655796c8dcSSimon Schubert add_com ("print-object", class_vars, print_object_command,
13665796c8dcSSimon Schubert _("Ask an Objective-C object to print itself."));
13675796c8dcSSimon Schubert add_com_alias ("po", "print-object", class_vars, 1);
13685796c8dcSSimon Schubert }
13695796c8dcSSimon Schubert
13705796c8dcSSimon Schubert static void
read_objc_method(struct gdbarch * gdbarch,CORE_ADDR addr,struct objc_method * method)13715796c8dcSSimon Schubert read_objc_method (struct gdbarch *gdbarch, CORE_ADDR addr,
13725796c8dcSSimon Schubert struct objc_method *method)
13735796c8dcSSimon Schubert {
13745796c8dcSSimon Schubert enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
1375cf7f2e2dSJohn Marino
13765796c8dcSSimon Schubert method->name = read_memory_unsigned_integer (addr + 0, 4, byte_order);
13775796c8dcSSimon Schubert method->types = read_memory_unsigned_integer (addr + 4, 4, byte_order);
13785796c8dcSSimon Schubert method->imp = read_memory_unsigned_integer (addr + 8, 4, byte_order);
13795796c8dcSSimon Schubert }
13805796c8dcSSimon Schubert
13815796c8dcSSimon Schubert static unsigned long
read_objc_methlist_nmethods(struct gdbarch * gdbarch,CORE_ADDR addr)13825796c8dcSSimon Schubert read_objc_methlist_nmethods (struct gdbarch *gdbarch, CORE_ADDR addr)
13835796c8dcSSimon Schubert {
13845796c8dcSSimon Schubert enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
1385cf7f2e2dSJohn Marino
13865796c8dcSSimon Schubert return read_memory_unsigned_integer (addr + 4, 4, byte_order);
13875796c8dcSSimon Schubert }
13885796c8dcSSimon Schubert
13895796c8dcSSimon Schubert static void
read_objc_methlist_method(struct gdbarch * gdbarch,CORE_ADDR addr,unsigned long num,struct objc_method * method)13905796c8dcSSimon Schubert read_objc_methlist_method (struct gdbarch *gdbarch, CORE_ADDR addr,
13915796c8dcSSimon Schubert unsigned long num, struct objc_method *method)
13925796c8dcSSimon Schubert {
13935796c8dcSSimon Schubert gdb_assert (num < read_objc_methlist_nmethods (gdbarch, addr));
13945796c8dcSSimon Schubert read_objc_method (gdbarch, addr + 8 + (12 * num), method);
13955796c8dcSSimon Schubert }
13965796c8dcSSimon Schubert
13975796c8dcSSimon Schubert static void
read_objc_object(struct gdbarch * gdbarch,CORE_ADDR addr,struct objc_object * object)13985796c8dcSSimon Schubert read_objc_object (struct gdbarch *gdbarch, CORE_ADDR addr,
13995796c8dcSSimon Schubert struct objc_object *object)
14005796c8dcSSimon Schubert {
14015796c8dcSSimon Schubert enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
1402cf7f2e2dSJohn Marino
14035796c8dcSSimon Schubert object->isa = read_memory_unsigned_integer (addr, 4, byte_order);
14045796c8dcSSimon Schubert }
14055796c8dcSSimon Schubert
14065796c8dcSSimon Schubert static void
read_objc_super(struct gdbarch * gdbarch,CORE_ADDR addr,struct objc_super * super)14075796c8dcSSimon Schubert read_objc_super (struct gdbarch *gdbarch, CORE_ADDR addr,
14085796c8dcSSimon Schubert struct objc_super *super)
14095796c8dcSSimon Schubert {
14105796c8dcSSimon Schubert enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
1411cf7f2e2dSJohn Marino
14125796c8dcSSimon Schubert super->receiver = read_memory_unsigned_integer (addr, 4, byte_order);
14135796c8dcSSimon Schubert super->class = read_memory_unsigned_integer (addr + 4, 4, byte_order);
14145796c8dcSSimon Schubert };
14155796c8dcSSimon Schubert
14165796c8dcSSimon Schubert static void
read_objc_class(struct gdbarch * gdbarch,CORE_ADDR addr,struct objc_class * class)14175796c8dcSSimon Schubert read_objc_class (struct gdbarch *gdbarch, CORE_ADDR addr,
14185796c8dcSSimon Schubert struct objc_class *class)
14195796c8dcSSimon Schubert {
14205796c8dcSSimon Schubert enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
1421cf7f2e2dSJohn Marino
14225796c8dcSSimon Schubert class->isa = read_memory_unsigned_integer (addr, 4, byte_order);
14235796c8dcSSimon Schubert class->super_class = read_memory_unsigned_integer (addr + 4, 4, byte_order);
14245796c8dcSSimon Schubert class->name = read_memory_unsigned_integer (addr + 8, 4, byte_order);
14255796c8dcSSimon Schubert class->version = read_memory_unsigned_integer (addr + 12, 4, byte_order);
14265796c8dcSSimon Schubert class->info = read_memory_unsigned_integer (addr + 16, 4, byte_order);
1427c50c785cSJohn Marino class->instance_size = read_memory_unsigned_integer (addr + 18, 4,
1428c50c785cSJohn Marino byte_order);
14295796c8dcSSimon Schubert class->ivars = read_memory_unsigned_integer (addr + 24, 4, byte_order);
14305796c8dcSSimon Schubert class->methods = read_memory_unsigned_integer (addr + 28, 4, byte_order);
14315796c8dcSSimon Schubert class->cache = read_memory_unsigned_integer (addr + 32, 4, byte_order);
14325796c8dcSSimon Schubert class->protocols = read_memory_unsigned_integer (addr + 36, 4, byte_order);
14335796c8dcSSimon Schubert }
14345796c8dcSSimon Schubert
14355796c8dcSSimon Schubert static CORE_ADDR
find_implementation_from_class(struct gdbarch * gdbarch,CORE_ADDR class,CORE_ADDR sel)14365796c8dcSSimon Schubert find_implementation_from_class (struct gdbarch *gdbarch,
14375796c8dcSSimon Schubert CORE_ADDR class, CORE_ADDR sel)
14385796c8dcSSimon Schubert {
14395796c8dcSSimon Schubert enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
14405796c8dcSSimon Schubert CORE_ADDR subclass = class;
14415796c8dcSSimon Schubert
14425796c8dcSSimon Schubert while (subclass != 0)
14435796c8dcSSimon Schubert {
14445796c8dcSSimon Schubert
14455796c8dcSSimon Schubert struct objc_class class_str;
14465796c8dcSSimon Schubert unsigned mlistnum = 0;
14475796c8dcSSimon Schubert
14485796c8dcSSimon Schubert read_objc_class (gdbarch, subclass, &class_str);
14495796c8dcSSimon Schubert
14505796c8dcSSimon Schubert for (;;)
14515796c8dcSSimon Schubert {
14525796c8dcSSimon Schubert CORE_ADDR mlist;
14535796c8dcSSimon Schubert unsigned long nmethods;
14545796c8dcSSimon Schubert unsigned long i;
14555796c8dcSSimon Schubert
14565796c8dcSSimon Schubert mlist = read_memory_unsigned_integer (class_str.methods +
14575796c8dcSSimon Schubert (4 * mlistnum),
14585796c8dcSSimon Schubert 4, byte_order);
14595796c8dcSSimon Schubert if (mlist == 0)
14605796c8dcSSimon Schubert break;
14615796c8dcSSimon Schubert
14625796c8dcSSimon Schubert nmethods = read_objc_methlist_nmethods (gdbarch, mlist);
14635796c8dcSSimon Schubert
14645796c8dcSSimon Schubert for (i = 0; i < nmethods; i++)
14655796c8dcSSimon Schubert {
14665796c8dcSSimon Schubert struct objc_method meth_str;
14675796c8dcSSimon Schubert
1468cf7f2e2dSJohn Marino read_objc_methlist_method (gdbarch, mlist, i, &meth_str);
14695796c8dcSSimon Schubert #if 0
14705796c8dcSSimon Schubert fprintf (stderr,
14715796c8dcSSimon Schubert "checking method 0x%lx against selector 0x%lx\n",
14725796c8dcSSimon Schubert meth_str.name, sel);
14735796c8dcSSimon Schubert #endif
14745796c8dcSSimon Schubert
14755796c8dcSSimon Schubert if (meth_str.name == sel)
14765796c8dcSSimon Schubert /* FIXME: hppa arch was doing a pointer dereference
14775796c8dcSSimon Schubert here. There needs to be a better way to do that. */
14785796c8dcSSimon Schubert return meth_str.imp;
14795796c8dcSSimon Schubert }
14805796c8dcSSimon Schubert mlistnum++;
14815796c8dcSSimon Schubert }
14825796c8dcSSimon Schubert subclass = class_str.super_class;
14835796c8dcSSimon Schubert }
14845796c8dcSSimon Schubert
14855796c8dcSSimon Schubert return 0;
14865796c8dcSSimon Schubert }
14875796c8dcSSimon Schubert
14885796c8dcSSimon Schubert static CORE_ADDR
find_implementation(struct gdbarch * gdbarch,CORE_ADDR object,CORE_ADDR sel)14895796c8dcSSimon Schubert find_implementation (struct gdbarch *gdbarch,
14905796c8dcSSimon Schubert CORE_ADDR object, CORE_ADDR sel)
14915796c8dcSSimon Schubert {
14925796c8dcSSimon Schubert struct objc_object ostr;
14935796c8dcSSimon Schubert
14945796c8dcSSimon Schubert if (object == 0)
14955796c8dcSSimon Schubert return 0;
14965796c8dcSSimon Schubert read_objc_object (gdbarch, object, &ostr);
14975796c8dcSSimon Schubert if (ostr.isa == 0)
14985796c8dcSSimon Schubert return 0;
14995796c8dcSSimon Schubert
15005796c8dcSSimon Schubert return find_implementation_from_class (gdbarch, ostr.isa, sel);
15015796c8dcSSimon Schubert }
15025796c8dcSSimon Schubert
15035796c8dcSSimon Schubert static int
resolve_msgsend(CORE_ADDR pc,CORE_ADDR * new_pc)15045796c8dcSSimon Schubert resolve_msgsend (CORE_ADDR pc, CORE_ADDR *new_pc)
15055796c8dcSSimon Schubert {
15065796c8dcSSimon Schubert struct frame_info *frame = get_current_frame ();
15075796c8dcSSimon Schubert struct gdbarch *gdbarch = get_frame_arch (frame);
15085796c8dcSSimon Schubert struct type *ptr_type = builtin_type (gdbarch)->builtin_func_ptr;
15095796c8dcSSimon Schubert
15105796c8dcSSimon Schubert CORE_ADDR object;
15115796c8dcSSimon Schubert CORE_ADDR sel;
15125796c8dcSSimon Schubert CORE_ADDR res;
15135796c8dcSSimon Schubert
15145796c8dcSSimon Schubert object = gdbarch_fetch_pointer_argument (gdbarch, frame, 0, ptr_type);
15155796c8dcSSimon Schubert sel = gdbarch_fetch_pointer_argument (gdbarch, frame, 1, ptr_type);
15165796c8dcSSimon Schubert
15175796c8dcSSimon Schubert res = find_implementation (gdbarch, object, sel);
15185796c8dcSSimon Schubert if (new_pc != 0)
15195796c8dcSSimon Schubert *new_pc = res;
15205796c8dcSSimon Schubert if (res == 0)
15215796c8dcSSimon Schubert return 1;
15225796c8dcSSimon Schubert return 0;
15235796c8dcSSimon Schubert }
15245796c8dcSSimon Schubert
15255796c8dcSSimon Schubert static int
resolve_msgsend_stret(CORE_ADDR pc,CORE_ADDR * new_pc)15265796c8dcSSimon Schubert resolve_msgsend_stret (CORE_ADDR pc, CORE_ADDR *new_pc)
15275796c8dcSSimon Schubert {
15285796c8dcSSimon Schubert struct frame_info *frame = get_current_frame ();
15295796c8dcSSimon Schubert struct gdbarch *gdbarch = get_frame_arch (frame);
15305796c8dcSSimon Schubert struct type *ptr_type = builtin_type (gdbarch)->builtin_func_ptr;
15315796c8dcSSimon Schubert
15325796c8dcSSimon Schubert CORE_ADDR object;
15335796c8dcSSimon Schubert CORE_ADDR sel;
15345796c8dcSSimon Schubert CORE_ADDR res;
15355796c8dcSSimon Schubert
15365796c8dcSSimon Schubert object = gdbarch_fetch_pointer_argument (gdbarch, frame, 1, ptr_type);
15375796c8dcSSimon Schubert sel = gdbarch_fetch_pointer_argument (gdbarch, frame, 2, ptr_type);
15385796c8dcSSimon Schubert
15395796c8dcSSimon Schubert res = find_implementation (gdbarch, object, sel);
15405796c8dcSSimon Schubert if (new_pc != 0)
15415796c8dcSSimon Schubert *new_pc = res;
15425796c8dcSSimon Schubert if (res == 0)
15435796c8dcSSimon Schubert return 1;
15445796c8dcSSimon Schubert return 0;
15455796c8dcSSimon Schubert }
15465796c8dcSSimon Schubert
15475796c8dcSSimon Schubert static int
resolve_msgsend_super(CORE_ADDR pc,CORE_ADDR * new_pc)15485796c8dcSSimon Schubert resolve_msgsend_super (CORE_ADDR pc, CORE_ADDR *new_pc)
15495796c8dcSSimon Schubert {
15505796c8dcSSimon Schubert struct frame_info *frame = get_current_frame ();
15515796c8dcSSimon Schubert struct gdbarch *gdbarch = get_frame_arch (frame);
15525796c8dcSSimon Schubert struct type *ptr_type = builtin_type (gdbarch)->builtin_func_ptr;
15535796c8dcSSimon Schubert
15545796c8dcSSimon Schubert struct objc_super sstr;
15555796c8dcSSimon Schubert
15565796c8dcSSimon Schubert CORE_ADDR super;
15575796c8dcSSimon Schubert CORE_ADDR sel;
15585796c8dcSSimon Schubert CORE_ADDR res;
15595796c8dcSSimon Schubert
15605796c8dcSSimon Schubert super = gdbarch_fetch_pointer_argument (gdbarch, frame, 0, ptr_type);
15615796c8dcSSimon Schubert sel = gdbarch_fetch_pointer_argument (gdbarch, frame, 1, ptr_type);
15625796c8dcSSimon Schubert
15635796c8dcSSimon Schubert read_objc_super (gdbarch, super, &sstr);
15645796c8dcSSimon Schubert if (sstr.class == 0)
15655796c8dcSSimon Schubert return 0;
15665796c8dcSSimon Schubert
15675796c8dcSSimon Schubert res = find_implementation_from_class (gdbarch, sstr.class, sel);
15685796c8dcSSimon Schubert if (new_pc != 0)
15695796c8dcSSimon Schubert *new_pc = res;
15705796c8dcSSimon Schubert if (res == 0)
15715796c8dcSSimon Schubert return 1;
15725796c8dcSSimon Schubert return 0;
15735796c8dcSSimon Schubert }
15745796c8dcSSimon Schubert
15755796c8dcSSimon Schubert static int
resolve_msgsend_super_stret(CORE_ADDR pc,CORE_ADDR * new_pc)15765796c8dcSSimon Schubert resolve_msgsend_super_stret (CORE_ADDR pc, CORE_ADDR *new_pc)
15775796c8dcSSimon Schubert {
15785796c8dcSSimon Schubert struct frame_info *frame = get_current_frame ();
15795796c8dcSSimon Schubert struct gdbarch *gdbarch = get_frame_arch (frame);
15805796c8dcSSimon Schubert struct type *ptr_type = builtin_type (gdbarch)->builtin_func_ptr;
15815796c8dcSSimon Schubert
15825796c8dcSSimon Schubert struct objc_super sstr;
15835796c8dcSSimon Schubert
15845796c8dcSSimon Schubert CORE_ADDR super;
15855796c8dcSSimon Schubert CORE_ADDR sel;
15865796c8dcSSimon Schubert CORE_ADDR res;
15875796c8dcSSimon Schubert
15885796c8dcSSimon Schubert super = gdbarch_fetch_pointer_argument (gdbarch, frame, 1, ptr_type);
15895796c8dcSSimon Schubert sel = gdbarch_fetch_pointer_argument (gdbarch, frame, 2, ptr_type);
15905796c8dcSSimon Schubert
15915796c8dcSSimon Schubert read_objc_super (gdbarch, super, &sstr);
15925796c8dcSSimon Schubert if (sstr.class == 0)
15935796c8dcSSimon Schubert return 0;
15945796c8dcSSimon Schubert
15955796c8dcSSimon Schubert res = find_implementation_from_class (gdbarch, sstr.class, sel);
15965796c8dcSSimon Schubert if (new_pc != 0)
15975796c8dcSSimon Schubert *new_pc = res;
15985796c8dcSSimon Schubert if (res == 0)
15995796c8dcSSimon Schubert return 1;
16005796c8dcSSimon Schubert return 0;
16015796c8dcSSimon Schubert }
16025796c8dcSSimon Schubert
1603*ef5ccd6cSJohn Marino /* Provide a prototype to silence -Wmissing-prototypes. */
1604*ef5ccd6cSJohn Marino extern initialize_file_ftype _initialize_objc_lang;
1605*ef5ccd6cSJohn Marino
16065796c8dcSSimon Schubert void
_initialize_objc_lang(void)16075796c8dcSSimon Schubert _initialize_objc_lang (void)
16085796c8dcSSimon Schubert {
16095796c8dcSSimon Schubert objc_objfile_data = register_objfile_data ();
16105796c8dcSSimon Schubert }
1611