xref: /dragonfly/contrib/gdb-7/gdb/objc-lang.c (revision ef5ccd6c)
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