1b725ae77Skettenis /* Objective-C language support routines for GDB, the GNU debugger.
2b725ae77Skettenis
3b725ae77Skettenis Copyright 2002, 2003, 2004 Free Software Foundation, Inc.
4b725ae77Skettenis
5b725ae77Skettenis Contributed by Apple Computer, Inc.
6b725ae77Skettenis Written by Michael Snyder.
7b725ae77Skettenis
8b725ae77Skettenis This file is part of GDB.
9b725ae77Skettenis
10b725ae77Skettenis This program is free software; you can redistribute it and/or modify
11b725ae77Skettenis it under the terms of the GNU General Public License as published by
12b725ae77Skettenis the Free Software Foundation; either version 2 of the License, or
13b725ae77Skettenis (at your option) any later version.
14b725ae77Skettenis
15b725ae77Skettenis This program is distributed in the hope that it will be useful,
16b725ae77Skettenis but WITHOUT ANY WARRANTY; without even the implied warranty of
17b725ae77Skettenis MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18b725ae77Skettenis GNU General Public License for more details.
19b725ae77Skettenis
20b725ae77Skettenis You should have received a copy of the GNU General Public License
21b725ae77Skettenis along with this program; if not, write to the Free Software
22b725ae77Skettenis Foundation, Inc., 59 Temple Place - Suite 330,
23b725ae77Skettenis Boston, MA 02111-1307, USA. */
24b725ae77Skettenis
25b725ae77Skettenis #include "defs.h"
26b725ae77Skettenis #include "symtab.h"
27b725ae77Skettenis #include "gdbtypes.h"
28b725ae77Skettenis #include "expression.h"
29b725ae77Skettenis #include "parser-defs.h"
30b725ae77Skettenis #include "language.h"
31b725ae77Skettenis #include "c-lang.h"
32b725ae77Skettenis #include "objc-lang.h"
33b725ae77Skettenis #include "complaints.h"
34b725ae77Skettenis #include "value.h"
35b725ae77Skettenis #include "symfile.h"
36b725ae77Skettenis #include "objfiles.h"
37b725ae77Skettenis #include "gdb_string.h" /* for strchr */
38b725ae77Skettenis #include "target.h" /* for target_has_execution */
39b725ae77Skettenis #include "gdbcore.h"
40b725ae77Skettenis #include "gdbcmd.h"
41b725ae77Skettenis #include "frame.h"
42b725ae77Skettenis #include "gdb_regex.h"
43b725ae77Skettenis #include "regcache.h"
44b725ae77Skettenis #include "block.h"
45b725ae77Skettenis #include "infcall.h"
46b725ae77Skettenis #include "valprint.h"
47b725ae77Skettenis #include "gdb_assert.h"
48b725ae77Skettenis
49b725ae77Skettenis #include <ctype.h>
50b725ae77Skettenis
51b725ae77Skettenis struct objc_object {
52b725ae77Skettenis CORE_ADDR isa;
53b725ae77Skettenis };
54b725ae77Skettenis
55b725ae77Skettenis struct objc_class {
56b725ae77Skettenis CORE_ADDR isa;
57b725ae77Skettenis CORE_ADDR super_class;
58b725ae77Skettenis CORE_ADDR name;
59b725ae77Skettenis long version;
60b725ae77Skettenis long info;
61b725ae77Skettenis long instance_size;
62b725ae77Skettenis CORE_ADDR ivars;
63b725ae77Skettenis CORE_ADDR methods;
64b725ae77Skettenis CORE_ADDR cache;
65b725ae77Skettenis CORE_ADDR protocols;
66b725ae77Skettenis };
67b725ae77Skettenis
68b725ae77Skettenis struct objc_super {
69b725ae77Skettenis CORE_ADDR receiver;
70b725ae77Skettenis CORE_ADDR class;
71b725ae77Skettenis };
72b725ae77Skettenis
73b725ae77Skettenis struct objc_method {
74b725ae77Skettenis CORE_ADDR name;
75b725ae77Skettenis CORE_ADDR types;
76b725ae77Skettenis CORE_ADDR imp;
77b725ae77Skettenis };
78b725ae77Skettenis
79b725ae77Skettenis /* Lookup a structure type named "struct NAME", visible in lexical
80b725ae77Skettenis block BLOCK. If NOERR is nonzero, return zero if NAME is not
81b725ae77Skettenis suitably defined. */
82b725ae77Skettenis
83b725ae77Skettenis struct symbol *
lookup_struct_typedef(char * name,struct block * block,int noerr)84b725ae77Skettenis lookup_struct_typedef (char *name, struct block *block, int noerr)
85b725ae77Skettenis {
86b725ae77Skettenis struct symbol *sym;
87b725ae77Skettenis
88b725ae77Skettenis sym = lookup_symbol (name, block, STRUCT_DOMAIN, 0,
89b725ae77Skettenis (struct symtab **) NULL);
90b725ae77Skettenis
91b725ae77Skettenis if (sym == NULL)
92b725ae77Skettenis {
93b725ae77Skettenis if (noerr)
94b725ae77Skettenis return 0;
95b725ae77Skettenis else
96b725ae77Skettenis error ("No struct type named %s.", name);
97b725ae77Skettenis }
98b725ae77Skettenis if (TYPE_CODE (SYMBOL_TYPE (sym)) != TYPE_CODE_STRUCT)
99b725ae77Skettenis {
100b725ae77Skettenis if (noerr)
101b725ae77Skettenis return 0;
102b725ae77Skettenis else
103b725ae77Skettenis error ("This context has class, union or enum %s, not a struct.",
104b725ae77Skettenis name);
105b725ae77Skettenis }
106b725ae77Skettenis return sym;
107b725ae77Skettenis }
108b725ae77Skettenis
109b725ae77Skettenis CORE_ADDR
lookup_objc_class(char * classname)110b725ae77Skettenis lookup_objc_class (char *classname)
111b725ae77Skettenis {
112b725ae77Skettenis struct value * function, *classval;
113b725ae77Skettenis
114b725ae77Skettenis if (! target_has_execution)
115b725ae77Skettenis {
116b725ae77Skettenis /* Can't call into inferior to lookup class. */
117b725ae77Skettenis return 0;
118b725ae77Skettenis }
119b725ae77Skettenis
120b725ae77Skettenis if (lookup_minimal_symbol("objc_lookUpClass", 0, 0))
121b725ae77Skettenis function = find_function_in_inferior("objc_lookUpClass");
122b725ae77Skettenis else if (lookup_minimal_symbol ("objc_lookup_class", 0, 0))
123b725ae77Skettenis function = find_function_in_inferior("objc_lookup_class");
124b725ae77Skettenis else
125b725ae77Skettenis {
126b725ae77Skettenis complaint (&symfile_complaints, "no way to lookup Objective-C classes");
127b725ae77Skettenis return 0;
128b725ae77Skettenis }
129b725ae77Skettenis
130b725ae77Skettenis classval = value_string (classname, strlen (classname) + 1);
131b725ae77Skettenis classval = value_coerce_array (classval);
132b725ae77Skettenis return (CORE_ADDR) value_as_long (call_function_by_hand (function,
133b725ae77Skettenis 1, &classval));
134b725ae77Skettenis }
135b725ae77Skettenis
136b725ae77Skettenis CORE_ADDR
lookup_child_selector(char * selname)137b725ae77Skettenis lookup_child_selector (char *selname)
138b725ae77Skettenis {
139b725ae77Skettenis struct value * function, *selstring;
140b725ae77Skettenis
141b725ae77Skettenis if (! target_has_execution)
142b725ae77Skettenis {
143b725ae77Skettenis /* Can't call into inferior to lookup selector. */
144b725ae77Skettenis return 0;
145b725ae77Skettenis }
146b725ae77Skettenis
147b725ae77Skettenis if (lookup_minimal_symbol("sel_getUid", 0, 0))
148b725ae77Skettenis function = find_function_in_inferior("sel_getUid");
149b725ae77Skettenis else if (lookup_minimal_symbol ("sel_get_any_uid", 0, 0))
150b725ae77Skettenis function = find_function_in_inferior("sel_get_any_uid");
151b725ae77Skettenis else
152b725ae77Skettenis {
153b725ae77Skettenis complaint (&symfile_complaints, "no way to lookup Objective-C selectors");
154b725ae77Skettenis return 0;
155b725ae77Skettenis }
156b725ae77Skettenis
157b725ae77Skettenis selstring = value_coerce_array (value_string (selname,
158b725ae77Skettenis strlen (selname) + 1));
159b725ae77Skettenis return value_as_long (call_function_by_hand (function, 1, &selstring));
160b725ae77Skettenis }
161b725ae77Skettenis
162b725ae77Skettenis struct value *
value_nsstring(char * ptr,int len)163b725ae77Skettenis value_nsstring (char *ptr, int len)
164b725ae77Skettenis {
165b725ae77Skettenis struct value *stringValue[3];
166b725ae77Skettenis struct value *function, *nsstringValue;
167b725ae77Skettenis struct symbol *sym;
168b725ae77Skettenis struct type *type;
169b725ae77Skettenis
170b725ae77Skettenis if (!target_has_execution)
171b725ae77Skettenis return 0; /* Can't call into inferior to create NSString. */
172b725ae77Skettenis
173b725ae77Skettenis sym = lookup_struct_typedef("NSString", 0, 1);
174b725ae77Skettenis if (sym == NULL)
175b725ae77Skettenis sym = lookup_struct_typedef("NXString", 0, 1);
176b725ae77Skettenis if (sym == NULL)
177b725ae77Skettenis type = lookup_pointer_type(builtin_type_void);
178b725ae77Skettenis else
179b725ae77Skettenis type = lookup_pointer_type(SYMBOL_TYPE (sym));
180b725ae77Skettenis
181b725ae77Skettenis stringValue[2] = value_string(ptr, len);
182b725ae77Skettenis stringValue[2] = value_coerce_array(stringValue[2]);
183b725ae77Skettenis /* _NSNewStringFromCString replaces "istr" after Lantern2A. */
184b725ae77Skettenis if (lookup_minimal_symbol("_NSNewStringFromCString", 0, 0))
185b725ae77Skettenis {
186b725ae77Skettenis function = find_function_in_inferior("_NSNewStringFromCString");
187b725ae77Skettenis nsstringValue = call_function_by_hand(function, 1, &stringValue[2]);
188b725ae77Skettenis }
189b725ae77Skettenis else if (lookup_minimal_symbol("istr", 0, 0))
190b725ae77Skettenis {
191b725ae77Skettenis function = find_function_in_inferior("istr");
192b725ae77Skettenis nsstringValue = call_function_by_hand(function, 1, &stringValue[2]);
193b725ae77Skettenis }
194b725ae77Skettenis else if (lookup_minimal_symbol("+[NSString stringWithCString:]", 0, 0))
195b725ae77Skettenis {
196b725ae77Skettenis function = find_function_in_inferior("+[NSString stringWithCString:]");
197b725ae77Skettenis stringValue[0] = value_from_longest
198b725ae77Skettenis (builtin_type_long, lookup_objc_class ("NSString"));
199b725ae77Skettenis stringValue[1] = value_from_longest
200b725ae77Skettenis (builtin_type_long, lookup_child_selector ("stringWithCString:"));
201b725ae77Skettenis nsstringValue = call_function_by_hand(function, 3, &stringValue[0]);
202b725ae77Skettenis }
203b725ae77Skettenis else
204b725ae77Skettenis error ("NSString: internal error -- no way to create new NSString");
205b725ae77Skettenis
206b725ae77Skettenis VALUE_TYPE(nsstringValue) = type;
207b725ae77Skettenis return nsstringValue;
208b725ae77Skettenis }
209b725ae77Skettenis
210b725ae77Skettenis /* Objective-C name demangling. */
211b725ae77Skettenis
212b725ae77Skettenis char *
objc_demangle(const char * mangled,int options)213b725ae77Skettenis objc_demangle (const char *mangled, int options)
214b725ae77Skettenis {
215b725ae77Skettenis char *demangled, *cp;
216b725ae77Skettenis
217b725ae77Skettenis if (mangled[0] == '_' &&
218b725ae77Skettenis (mangled[1] == 'i' || mangled[1] == 'c') &&
219b725ae77Skettenis mangled[2] == '_')
220b725ae77Skettenis {
221b725ae77Skettenis cp = demangled = xmalloc(strlen(mangled) + 2);
222b725ae77Skettenis
223b725ae77Skettenis if (mangled[1] == 'i')
224b725ae77Skettenis *cp++ = '-'; /* for instance method */
225b725ae77Skettenis else
226b725ae77Skettenis *cp++ = '+'; /* for class method */
227b725ae77Skettenis
228b725ae77Skettenis *cp++ = '['; /* opening left brace */
229b725ae77Skettenis strcpy(cp, mangled+3); /* tack on the rest of the mangled name */
230b725ae77Skettenis
231b725ae77Skettenis while (*cp && *cp == '_')
232b725ae77Skettenis cp++; /* skip any initial underbars in class name */
233b725ae77Skettenis
234b725ae77Skettenis cp = strchr(cp, '_');
235b725ae77Skettenis if (!cp) /* find first non-initial underbar */
236b725ae77Skettenis {
237b725ae77Skettenis xfree(demangled); /* not mangled name */
238b725ae77Skettenis return NULL;
239b725ae77Skettenis }
240b725ae77Skettenis if (cp[1] == '_') { /* easy case: no category name */
241b725ae77Skettenis *cp++ = ' '; /* replace two '_' with one ' ' */
242b725ae77Skettenis strcpy(cp, mangled + (cp - demangled) + 2);
243b725ae77Skettenis }
244b725ae77Skettenis else {
245b725ae77Skettenis *cp++ = '('; /* less easy case: category name */
246b725ae77Skettenis cp = strchr(cp, '_');
247b725ae77Skettenis if (!cp)
248b725ae77Skettenis {
249b725ae77Skettenis xfree(demangled); /* not mangled name */
250b725ae77Skettenis return NULL;
251b725ae77Skettenis }
252b725ae77Skettenis *cp++ = ')';
253b725ae77Skettenis *cp++ = ' '; /* overwriting 1st char of method name... */
254b725ae77Skettenis strcpy(cp, mangled + (cp - demangled)); /* get it back */
255b725ae77Skettenis }
256b725ae77Skettenis
257b725ae77Skettenis while (*cp && *cp == '_')
258b725ae77Skettenis cp++; /* skip any initial underbars in method name */
259b725ae77Skettenis
260b725ae77Skettenis for (; *cp; cp++)
261b725ae77Skettenis if (*cp == '_')
262b725ae77Skettenis *cp = ':'; /* replace remaining '_' with ':' */
263b725ae77Skettenis
264b725ae77Skettenis *cp++ = ']'; /* closing right brace */
265b725ae77Skettenis *cp++ = 0; /* string terminator */
266b725ae77Skettenis return demangled;
267b725ae77Skettenis }
268b725ae77Skettenis else
269b725ae77Skettenis return NULL; /* Not an objc mangled name. */
270b725ae77Skettenis }
271b725ae77Skettenis
272b725ae77Skettenis /* Print the character C on STREAM as part of the contents of a
273b725ae77Skettenis literal string whose delimiter is QUOTER. Note that that format
274b725ae77Skettenis for printing characters and strings is language specific. */
275b725ae77Skettenis
276b725ae77Skettenis static void
objc_emit_char(int c,struct ui_file * stream,int quoter)277b725ae77Skettenis objc_emit_char (int c, struct ui_file *stream, int quoter)
278b725ae77Skettenis {
279b725ae77Skettenis
280b725ae77Skettenis c &= 0xFF; /* Avoid sign bit follies. */
281b725ae77Skettenis
282b725ae77Skettenis if (PRINT_LITERAL_FORM (c))
283b725ae77Skettenis {
284b725ae77Skettenis if (c == '\\' || c == quoter)
285b725ae77Skettenis {
286b725ae77Skettenis fputs_filtered ("\\", stream);
287b725ae77Skettenis }
288b725ae77Skettenis fprintf_filtered (stream, "%c", c);
289b725ae77Skettenis }
290b725ae77Skettenis else
291b725ae77Skettenis {
292b725ae77Skettenis switch (c)
293b725ae77Skettenis {
294b725ae77Skettenis case '\n':
295b725ae77Skettenis fputs_filtered ("\\n", stream);
296b725ae77Skettenis break;
297b725ae77Skettenis case '\b':
298b725ae77Skettenis fputs_filtered ("\\b", stream);
299b725ae77Skettenis break;
300b725ae77Skettenis case '\t':
301b725ae77Skettenis fputs_filtered ("\\t", stream);
302b725ae77Skettenis break;
303b725ae77Skettenis case '\f':
304b725ae77Skettenis fputs_filtered ("\\f", stream);
305b725ae77Skettenis break;
306b725ae77Skettenis case '\r':
307b725ae77Skettenis fputs_filtered ("\\r", stream);
308b725ae77Skettenis break;
309b725ae77Skettenis case '\033':
310b725ae77Skettenis fputs_filtered ("\\e", stream);
311b725ae77Skettenis break;
312b725ae77Skettenis case '\007':
313b725ae77Skettenis fputs_filtered ("\\a", stream);
314b725ae77Skettenis break;
315b725ae77Skettenis default:
316b725ae77Skettenis fprintf_filtered (stream, "\\%.3o", (unsigned int) c);
317b725ae77Skettenis break;
318b725ae77Skettenis }
319b725ae77Skettenis }
320b725ae77Skettenis }
321b725ae77Skettenis
322b725ae77Skettenis static void
objc_printchar(int c,struct ui_file * stream)323b725ae77Skettenis objc_printchar (int c, struct ui_file *stream)
324b725ae77Skettenis {
325b725ae77Skettenis fputs_filtered ("'", stream);
326b725ae77Skettenis objc_emit_char (c, stream, '\'');
327b725ae77Skettenis fputs_filtered ("'", stream);
328b725ae77Skettenis }
329b725ae77Skettenis
330b725ae77Skettenis /* Print the character string STRING, printing at most LENGTH
331b725ae77Skettenis characters. Printing stops early if the number hits print_max;
332b725ae77Skettenis repeat counts are printed as appropriate. Print ellipses at the
333b725ae77Skettenis end if we had to stop before printing LENGTH characters, or if
334b725ae77Skettenis FORCE_ELLIPSES. */
335b725ae77Skettenis
336b725ae77Skettenis static void
objc_printstr(struct ui_file * stream,char * string,unsigned int length,int width,int force_ellipses)337b725ae77Skettenis objc_printstr (struct ui_file *stream, char *string,
338b725ae77Skettenis unsigned int length, int width, int force_ellipses)
339b725ae77Skettenis {
340b725ae77Skettenis unsigned int i;
341b725ae77Skettenis unsigned int things_printed = 0;
342b725ae77Skettenis int in_quotes = 0;
343b725ae77Skettenis int need_comma = 0;
344b725ae77Skettenis
345b725ae77Skettenis /* If the string was not truncated due to `set print elements', and
346b725ae77Skettenis the last byte of it is a null, we don't print that, in
347b725ae77Skettenis traditional C style. */
348b725ae77Skettenis if ((!force_ellipses) && length > 0 && string[length-1] == '\0')
349b725ae77Skettenis length--;
350b725ae77Skettenis
351b725ae77Skettenis if (length == 0)
352b725ae77Skettenis {
353b725ae77Skettenis fputs_filtered ("\"\"", stream);
354b725ae77Skettenis return;
355b725ae77Skettenis }
356b725ae77Skettenis
357b725ae77Skettenis for (i = 0; i < length && things_printed < print_max; ++i)
358b725ae77Skettenis {
359b725ae77Skettenis /* Position of the character we are examining to see whether it
360b725ae77Skettenis is repeated. */
361b725ae77Skettenis unsigned int rep1;
362b725ae77Skettenis /* Number of repetitions we have detected so far. */
363b725ae77Skettenis unsigned int reps;
364b725ae77Skettenis
365b725ae77Skettenis QUIT;
366b725ae77Skettenis
367b725ae77Skettenis if (need_comma)
368b725ae77Skettenis {
369b725ae77Skettenis fputs_filtered (", ", stream);
370b725ae77Skettenis need_comma = 0;
371b725ae77Skettenis }
372b725ae77Skettenis
373b725ae77Skettenis rep1 = i + 1;
374b725ae77Skettenis reps = 1;
375b725ae77Skettenis while (rep1 < length && string[rep1] == string[i])
376b725ae77Skettenis {
377b725ae77Skettenis ++rep1;
378b725ae77Skettenis ++reps;
379b725ae77Skettenis }
380b725ae77Skettenis
381b725ae77Skettenis if (reps > repeat_count_threshold)
382b725ae77Skettenis {
383b725ae77Skettenis if (in_quotes)
384b725ae77Skettenis {
385b725ae77Skettenis if (inspect_it)
386b725ae77Skettenis fputs_filtered ("\\\", ", stream);
387b725ae77Skettenis else
388b725ae77Skettenis fputs_filtered ("\", ", stream);
389b725ae77Skettenis in_quotes = 0;
390b725ae77Skettenis }
391b725ae77Skettenis objc_printchar (string[i], stream);
392b725ae77Skettenis fprintf_filtered (stream, " <repeats %u times>", reps);
393b725ae77Skettenis i = rep1 - 1;
394b725ae77Skettenis things_printed += repeat_count_threshold;
395b725ae77Skettenis need_comma = 1;
396b725ae77Skettenis }
397b725ae77Skettenis else
398b725ae77Skettenis {
399b725ae77Skettenis if (!in_quotes)
400b725ae77Skettenis {
401b725ae77Skettenis if (inspect_it)
402b725ae77Skettenis fputs_filtered ("\\\"", stream);
403b725ae77Skettenis else
404b725ae77Skettenis fputs_filtered ("\"", stream);
405b725ae77Skettenis in_quotes = 1;
406b725ae77Skettenis }
407b725ae77Skettenis objc_emit_char (string[i], stream, '"');
408b725ae77Skettenis ++things_printed;
409b725ae77Skettenis }
410b725ae77Skettenis }
411b725ae77Skettenis
412b725ae77Skettenis /* Terminate the quotes if necessary. */
413b725ae77Skettenis if (in_quotes)
414b725ae77Skettenis {
415b725ae77Skettenis if (inspect_it)
416b725ae77Skettenis fputs_filtered ("\\\"", stream);
417b725ae77Skettenis else
418b725ae77Skettenis fputs_filtered ("\"", stream);
419b725ae77Skettenis }
420b725ae77Skettenis
421b725ae77Skettenis if (force_ellipses || i < length)
422b725ae77Skettenis fputs_filtered ("...", stream);
423b725ae77Skettenis }
424b725ae77Skettenis
425b725ae77Skettenis /* Create a fundamental C type using default reasonable for the
426b725ae77Skettenis current target.
427b725ae77Skettenis
428b725ae77Skettenis Some object/debugging file formats (DWARF version 1, COFF, etc) do
429b725ae77Skettenis not define fundamental types such as "int" or "double". Others
430b725ae77Skettenis (stabs or DWARF version 2, etc) do define fundamental types. For
431b725ae77Skettenis the formats which don't provide fundamental types, gdb can create
432b725ae77Skettenis such types using this function.
433b725ae77Skettenis
434b725ae77Skettenis FIXME: Some compilers distinguish explicitly signed integral types
435b725ae77Skettenis (signed short, signed int, signed long) from "regular" integral
436b725ae77Skettenis types (short, int, long) in the debugging information. There is
437b725ae77Skettenis some disagreement as to how useful this feature is. In particular,
438b725ae77Skettenis gcc does not support this. Also, only some debugging formats allow
439b725ae77Skettenis the distinction to be passed on to a debugger. For now, we always
440b725ae77Skettenis just use "short", "int", or "long" as the type name, for both the
441b725ae77Skettenis implicit and explicitly signed types. This also makes life easier
442b725ae77Skettenis for the gdb test suite since we don't have to account for the
443b725ae77Skettenis differences in output depending upon what the compiler and
444b725ae77Skettenis debugging format support. We will probably have to re-examine the
445b725ae77Skettenis issue when gdb starts taking it's fundamental type information
446b725ae77Skettenis directly from the debugging information supplied by the compiler.
447b725ae77Skettenis fnf@cygnus.com */
448b725ae77Skettenis
449b725ae77Skettenis static struct type *
objc_create_fundamental_type(struct objfile * objfile,int typeid)450b725ae77Skettenis objc_create_fundamental_type (struct objfile *objfile, int typeid)
451b725ae77Skettenis {
452b725ae77Skettenis struct type *type = NULL;
453b725ae77Skettenis
454b725ae77Skettenis switch (typeid)
455b725ae77Skettenis {
456b725ae77Skettenis default:
457b725ae77Skettenis /* FIXME: For now, if we are asked to produce a type not in
458b725ae77Skettenis this language, create the equivalent of a C integer type
459b725ae77Skettenis with the name "<?type?>". When all the dust settles from
460b725ae77Skettenis the type reconstruction work, this should probably become
461b725ae77Skettenis an error. */
462b725ae77Skettenis type = init_type (TYPE_CODE_INT,
463b725ae77Skettenis TARGET_INT_BIT / TARGET_CHAR_BIT,
464b725ae77Skettenis 0, "<?type?>", objfile);
465b725ae77Skettenis warning ("internal error: no C/C++ fundamental type %d", typeid);
466b725ae77Skettenis break;
467b725ae77Skettenis case FT_VOID:
468b725ae77Skettenis type = init_type (TYPE_CODE_VOID,
469b725ae77Skettenis TARGET_CHAR_BIT / TARGET_CHAR_BIT,
470b725ae77Skettenis 0, "void", objfile);
471b725ae77Skettenis break;
472b725ae77Skettenis case FT_CHAR:
473b725ae77Skettenis type = init_type (TYPE_CODE_INT,
474b725ae77Skettenis TARGET_CHAR_BIT / TARGET_CHAR_BIT,
475b725ae77Skettenis 0, "char", objfile);
476b725ae77Skettenis break;
477b725ae77Skettenis case FT_SIGNED_CHAR:
478b725ae77Skettenis type = init_type (TYPE_CODE_INT,
479b725ae77Skettenis TARGET_CHAR_BIT / TARGET_CHAR_BIT,
480b725ae77Skettenis 0, "signed char", objfile);
481b725ae77Skettenis break;
482b725ae77Skettenis case FT_UNSIGNED_CHAR:
483b725ae77Skettenis type = init_type (TYPE_CODE_INT,
484b725ae77Skettenis TARGET_CHAR_BIT / TARGET_CHAR_BIT,
485b725ae77Skettenis TYPE_FLAG_UNSIGNED, "unsigned char", objfile);
486b725ae77Skettenis break;
487b725ae77Skettenis case FT_SHORT:
488b725ae77Skettenis type = init_type (TYPE_CODE_INT,
489b725ae77Skettenis TARGET_SHORT_BIT / TARGET_CHAR_BIT,
490b725ae77Skettenis 0, "short", objfile);
491b725ae77Skettenis break;
492b725ae77Skettenis case FT_SIGNED_SHORT:
493b725ae77Skettenis type = init_type (TYPE_CODE_INT,
494b725ae77Skettenis TARGET_SHORT_BIT / TARGET_CHAR_BIT,
495b725ae77Skettenis 0, "short", objfile); /* FIXME-fnf */
496b725ae77Skettenis break;
497b725ae77Skettenis case FT_UNSIGNED_SHORT:
498b725ae77Skettenis type = init_type (TYPE_CODE_INT,
499b725ae77Skettenis TARGET_SHORT_BIT / TARGET_CHAR_BIT,
500b725ae77Skettenis TYPE_FLAG_UNSIGNED, "unsigned short", objfile);
501b725ae77Skettenis break;
502b725ae77Skettenis case FT_INTEGER:
503b725ae77Skettenis type = init_type (TYPE_CODE_INT,
504b725ae77Skettenis TARGET_INT_BIT / TARGET_CHAR_BIT,
505b725ae77Skettenis 0, "int", objfile);
506b725ae77Skettenis break;
507b725ae77Skettenis case FT_SIGNED_INTEGER:
508b725ae77Skettenis type = init_type (TYPE_CODE_INT,
509b725ae77Skettenis TARGET_INT_BIT / TARGET_CHAR_BIT,
510b725ae77Skettenis 0, "int", objfile); /* FIXME -fnf */
511b725ae77Skettenis break;
512b725ae77Skettenis case FT_UNSIGNED_INTEGER:
513b725ae77Skettenis type = init_type (TYPE_CODE_INT,
514b725ae77Skettenis TARGET_INT_BIT / TARGET_CHAR_BIT,
515b725ae77Skettenis TYPE_FLAG_UNSIGNED, "unsigned int", objfile);
516b725ae77Skettenis break;
517b725ae77Skettenis case FT_LONG:
518b725ae77Skettenis type = init_type (TYPE_CODE_INT,
519b725ae77Skettenis TARGET_LONG_BIT / TARGET_CHAR_BIT,
520b725ae77Skettenis 0, "long", objfile);
521b725ae77Skettenis break;
522b725ae77Skettenis case FT_SIGNED_LONG:
523b725ae77Skettenis type = init_type (TYPE_CODE_INT,
524b725ae77Skettenis TARGET_LONG_BIT / TARGET_CHAR_BIT,
525b725ae77Skettenis 0, "long", objfile); /* FIXME -fnf */
526b725ae77Skettenis break;
527b725ae77Skettenis case FT_UNSIGNED_LONG:
528b725ae77Skettenis type = init_type (TYPE_CODE_INT,
529b725ae77Skettenis TARGET_LONG_BIT / TARGET_CHAR_BIT,
530b725ae77Skettenis TYPE_FLAG_UNSIGNED, "unsigned long", objfile);
531b725ae77Skettenis break;
532b725ae77Skettenis case FT_LONG_LONG:
533b725ae77Skettenis type = init_type (TYPE_CODE_INT,
534b725ae77Skettenis TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT,
535b725ae77Skettenis 0, "long long", objfile);
536b725ae77Skettenis break;
537b725ae77Skettenis case FT_SIGNED_LONG_LONG:
538b725ae77Skettenis type = init_type (TYPE_CODE_INT,
539b725ae77Skettenis TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT,
540b725ae77Skettenis 0, "signed long long", objfile);
541b725ae77Skettenis break;
542b725ae77Skettenis case FT_UNSIGNED_LONG_LONG:
543b725ae77Skettenis type = init_type (TYPE_CODE_INT,
544b725ae77Skettenis TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT,
545b725ae77Skettenis TYPE_FLAG_UNSIGNED, "unsigned long long", objfile);
546b725ae77Skettenis break;
547b725ae77Skettenis case FT_FLOAT:
548b725ae77Skettenis type = init_type (TYPE_CODE_FLT,
549b725ae77Skettenis TARGET_FLOAT_BIT / TARGET_CHAR_BIT,
550b725ae77Skettenis 0, "float", objfile);
551b725ae77Skettenis break;
552b725ae77Skettenis case FT_DBL_PREC_FLOAT:
553b725ae77Skettenis type = init_type (TYPE_CODE_FLT,
554b725ae77Skettenis TARGET_DOUBLE_BIT / TARGET_CHAR_BIT,
555b725ae77Skettenis 0, "double", objfile);
556b725ae77Skettenis break;
557b725ae77Skettenis case FT_EXT_PREC_FLOAT:
558b725ae77Skettenis type = init_type (TYPE_CODE_FLT,
559b725ae77Skettenis TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT,
560b725ae77Skettenis 0, "long double", objfile);
561b725ae77Skettenis break;
562b725ae77Skettenis }
563b725ae77Skettenis return (type);
564b725ae77Skettenis }
565b725ae77Skettenis
566b725ae77Skettenis /* Determine if we are currently in the Objective-C dispatch function.
567b725ae77Skettenis If so, get the address of the method function that the dispatcher
568b725ae77Skettenis would call and use that as the function to step into instead. Also
569b725ae77Skettenis skip over the trampoline for the function (if any). This is better
570b725ae77Skettenis for the user since they are only interested in stepping into the
571b725ae77Skettenis method function anyway. */
572b725ae77Skettenis static CORE_ADDR
objc_skip_trampoline(CORE_ADDR stop_pc)573b725ae77Skettenis objc_skip_trampoline (CORE_ADDR stop_pc)
574b725ae77Skettenis {
575b725ae77Skettenis CORE_ADDR real_stop_pc;
576b725ae77Skettenis CORE_ADDR method_stop_pc;
577b725ae77Skettenis
578b725ae77Skettenis real_stop_pc = SKIP_TRAMPOLINE_CODE (stop_pc);
579b725ae77Skettenis
580b725ae77Skettenis if (real_stop_pc != 0)
581b725ae77Skettenis find_objc_msgcall (real_stop_pc, &method_stop_pc);
582b725ae77Skettenis else
583b725ae77Skettenis find_objc_msgcall (stop_pc, &method_stop_pc);
584b725ae77Skettenis
585b725ae77Skettenis if (method_stop_pc)
586b725ae77Skettenis {
587b725ae77Skettenis real_stop_pc = SKIP_TRAMPOLINE_CODE (method_stop_pc);
588b725ae77Skettenis if (real_stop_pc == 0)
589b725ae77Skettenis real_stop_pc = method_stop_pc;
590b725ae77Skettenis }
591b725ae77Skettenis
592b725ae77Skettenis return real_stop_pc;
593b725ae77Skettenis }
594b725ae77Skettenis
595b725ae77Skettenis
596b725ae77Skettenis /* Table mapping opcodes into strings for printing operators
597b725ae77Skettenis and precedences of the operators. */
598b725ae77Skettenis
599b725ae77Skettenis static const struct op_print objc_op_print_tab[] =
600b725ae77Skettenis {
601b725ae77Skettenis {",", BINOP_COMMA, PREC_COMMA, 0},
602b725ae77Skettenis {"=", BINOP_ASSIGN, PREC_ASSIGN, 1},
603b725ae77Skettenis {"||", BINOP_LOGICAL_OR, PREC_LOGICAL_OR, 0},
604b725ae77Skettenis {"&&", BINOP_LOGICAL_AND, PREC_LOGICAL_AND, 0},
605b725ae77Skettenis {"|", BINOP_BITWISE_IOR, PREC_BITWISE_IOR, 0},
606b725ae77Skettenis {"^", BINOP_BITWISE_XOR, PREC_BITWISE_XOR, 0},
607b725ae77Skettenis {"&", BINOP_BITWISE_AND, PREC_BITWISE_AND, 0},
608b725ae77Skettenis {"==", BINOP_EQUAL, PREC_EQUAL, 0},
609b725ae77Skettenis {"!=", BINOP_NOTEQUAL, PREC_EQUAL, 0},
610b725ae77Skettenis {"<=", BINOP_LEQ, PREC_ORDER, 0},
611b725ae77Skettenis {">=", BINOP_GEQ, PREC_ORDER, 0},
612b725ae77Skettenis {">", BINOP_GTR, PREC_ORDER, 0},
613b725ae77Skettenis {"<", BINOP_LESS, PREC_ORDER, 0},
614b725ae77Skettenis {">>", BINOP_RSH, PREC_SHIFT, 0},
615b725ae77Skettenis {"<<", BINOP_LSH, PREC_SHIFT, 0},
616b725ae77Skettenis {"+", BINOP_ADD, PREC_ADD, 0},
617b725ae77Skettenis {"-", BINOP_SUB, PREC_ADD, 0},
618b725ae77Skettenis {"*", BINOP_MUL, PREC_MUL, 0},
619b725ae77Skettenis {"/", BINOP_DIV, PREC_MUL, 0},
620b725ae77Skettenis {"%", BINOP_REM, PREC_MUL, 0},
621b725ae77Skettenis {"@", BINOP_REPEAT, PREC_REPEAT, 0},
622b725ae77Skettenis {"-", UNOP_NEG, PREC_PREFIX, 0},
623b725ae77Skettenis {"!", UNOP_LOGICAL_NOT, PREC_PREFIX, 0},
624b725ae77Skettenis {"~", UNOP_COMPLEMENT, PREC_PREFIX, 0},
625b725ae77Skettenis {"*", UNOP_IND, PREC_PREFIX, 0},
626b725ae77Skettenis {"&", UNOP_ADDR, PREC_PREFIX, 0},
627b725ae77Skettenis {"sizeof ", UNOP_SIZEOF, PREC_PREFIX, 0},
628b725ae77Skettenis {"++", UNOP_PREINCREMENT, PREC_PREFIX, 0},
629b725ae77Skettenis {"--", UNOP_PREDECREMENT, PREC_PREFIX, 0},
630b725ae77Skettenis {NULL, OP_NULL, PREC_NULL, 0}
631b725ae77Skettenis };
632b725ae77Skettenis
633b725ae77Skettenis struct type ** const (objc_builtin_types[]) =
634b725ae77Skettenis {
635b725ae77Skettenis &builtin_type_int,
636b725ae77Skettenis &builtin_type_long,
637b725ae77Skettenis &builtin_type_short,
638b725ae77Skettenis &builtin_type_char,
639b725ae77Skettenis &builtin_type_float,
640b725ae77Skettenis &builtin_type_double,
641b725ae77Skettenis &builtin_type_void,
642b725ae77Skettenis &builtin_type_long_long,
643b725ae77Skettenis &builtin_type_signed_char,
644b725ae77Skettenis &builtin_type_unsigned_char,
645b725ae77Skettenis &builtin_type_unsigned_short,
646b725ae77Skettenis &builtin_type_unsigned_int,
647b725ae77Skettenis &builtin_type_unsigned_long,
648b725ae77Skettenis &builtin_type_unsigned_long_long,
649b725ae77Skettenis &builtin_type_long_double,
650b725ae77Skettenis &builtin_type_complex,
651b725ae77Skettenis &builtin_type_double_complex,
652b725ae77Skettenis 0
653b725ae77Skettenis };
654b725ae77Skettenis
655b725ae77Skettenis const struct language_defn objc_language_defn = {
656b725ae77Skettenis "objective-c", /* Language name */
657b725ae77Skettenis language_objc,
658b725ae77Skettenis objc_builtin_types,
659b725ae77Skettenis range_check_off,
660b725ae77Skettenis type_check_off,
661b725ae77Skettenis case_sensitive_on,
662*11efff7fSkettenis array_row_major,
663b725ae77Skettenis &exp_descriptor_standard,
664b725ae77Skettenis objc_parse,
665b725ae77Skettenis objc_error,
666*11efff7fSkettenis null_post_parser,
667b725ae77Skettenis objc_printchar, /* Print a character constant */
668b725ae77Skettenis objc_printstr, /* Function to print string constant */
669b725ae77Skettenis objc_emit_char,
670b725ae77Skettenis objc_create_fundamental_type, /* Create fundamental type in this language */
671b725ae77Skettenis c_print_type, /* Print a type using appropriate syntax */
672b725ae77Skettenis c_val_print, /* Print a value using appropriate syntax */
673b725ae77Skettenis c_value_print, /* Print a top-level value */
674b725ae77Skettenis objc_skip_trampoline, /* Language specific skip_trampoline */
675b725ae77Skettenis value_of_this, /* value_of_this */
676b725ae77Skettenis basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
677b725ae77Skettenis basic_lookup_transparent_type,/* lookup_transparent_type */
678b725ae77Skettenis objc_demangle, /* Language specific symbol demangler */
679*11efff7fSkettenis NULL, /* Language specific class_name_from_physname */
680b725ae77Skettenis objc_op_print_tab, /* Expression operators for printing */
681b725ae77Skettenis 1, /* C-style arrays */
682b725ae77Skettenis 0, /* String lower bound */
683b725ae77Skettenis &builtin_type_char, /* Type of string elements */
684b725ae77Skettenis default_word_break_characters,
685*11efff7fSkettenis NULL, /* FIXME: la_language_arch_info. */
686b725ae77Skettenis LANG_MAGIC
687b725ae77Skettenis };
688b725ae77Skettenis
689b725ae77Skettenis /*
690b725ae77Skettenis * ObjC:
691b725ae77Skettenis * Following functions help construct Objective-C message calls
692b725ae77Skettenis */
693b725ae77Skettenis
694b725ae77Skettenis struct selname /* For parsing Objective-C. */
695b725ae77Skettenis {
696b725ae77Skettenis struct selname *next;
697b725ae77Skettenis char *msglist_sel;
698b725ae77Skettenis int msglist_len;
699b725ae77Skettenis };
700b725ae77Skettenis
701b725ae77Skettenis static int msglist_len;
702b725ae77Skettenis static struct selname *selname_chain;
703b725ae77Skettenis static char *msglist_sel;
704b725ae77Skettenis
705b725ae77Skettenis void
start_msglist(void)706b725ae77Skettenis start_msglist(void)
707b725ae77Skettenis {
708b725ae77Skettenis struct selname *new =
709b725ae77Skettenis (struct selname *) xmalloc (sizeof (struct selname));
710b725ae77Skettenis
711b725ae77Skettenis new->next = selname_chain;
712b725ae77Skettenis new->msglist_len = msglist_len;
713b725ae77Skettenis new->msglist_sel = msglist_sel;
714b725ae77Skettenis msglist_len = 0;
715b725ae77Skettenis msglist_sel = (char *)xmalloc(1);
716b725ae77Skettenis *msglist_sel = 0;
717b725ae77Skettenis selname_chain = new;
718b725ae77Skettenis }
719b725ae77Skettenis
720b725ae77Skettenis void
add_msglist(struct stoken * str,int addcolon)721b725ae77Skettenis add_msglist(struct stoken *str, int addcolon)
722b725ae77Skettenis {
723b725ae77Skettenis char *s, *p;
724b725ae77Skettenis int len, plen;
725b725ae77Skettenis
726b725ae77Skettenis if (str == 0) { /* Unnamed arg, or... */
727b725ae77Skettenis if (addcolon == 0) { /* variable number of args. */
728b725ae77Skettenis msglist_len++;
729b725ae77Skettenis return;
730b725ae77Skettenis }
731b725ae77Skettenis p = "";
732b725ae77Skettenis plen = 0;
733b725ae77Skettenis } else {
734b725ae77Skettenis p = str->ptr;
735b725ae77Skettenis plen = str->length;
736b725ae77Skettenis }
737b725ae77Skettenis len = plen + strlen(msglist_sel) + 2;
738b725ae77Skettenis s = (char *)xmalloc(len);
739b725ae77Skettenis strcpy(s, msglist_sel);
740b725ae77Skettenis strncat(s, p, plen);
741b725ae77Skettenis xfree(msglist_sel);
742b725ae77Skettenis msglist_sel = s;
743b725ae77Skettenis if (addcolon) {
744b725ae77Skettenis s[len-2] = ':';
745b725ae77Skettenis s[len-1] = 0;
746b725ae77Skettenis msglist_len++;
747b725ae77Skettenis } else
748b725ae77Skettenis s[len-2] = '\0';
749b725ae77Skettenis }
750b725ae77Skettenis
751b725ae77Skettenis int
end_msglist(void)752b725ae77Skettenis end_msglist(void)
753b725ae77Skettenis {
754b725ae77Skettenis int val = msglist_len;
755b725ae77Skettenis struct selname *sel = selname_chain;
756b725ae77Skettenis char *p = msglist_sel;
757b725ae77Skettenis CORE_ADDR selid;
758b725ae77Skettenis
759b725ae77Skettenis selname_chain = sel->next;
760b725ae77Skettenis msglist_len = sel->msglist_len;
761b725ae77Skettenis msglist_sel = sel->msglist_sel;
762b725ae77Skettenis selid = lookup_child_selector(p);
763b725ae77Skettenis if (!selid)
764b725ae77Skettenis error("Can't find selector \"%s\"", p);
765b725ae77Skettenis write_exp_elt_longcst (selid);
766b725ae77Skettenis xfree(p);
767b725ae77Skettenis write_exp_elt_longcst (val); /* Number of args */
768b725ae77Skettenis xfree(sel);
769b725ae77Skettenis
770b725ae77Skettenis return val;
771b725ae77Skettenis }
772b725ae77Skettenis
773b725ae77Skettenis /*
774b725ae77Skettenis * Function: specialcmp (char *a, char *b)
775b725ae77Skettenis *
776b725ae77Skettenis * Special strcmp: treats ']' and ' ' as end-of-string.
777b725ae77Skettenis * Used for qsorting lists of objc methods (either by class or selector).
778b725ae77Skettenis */
779b725ae77Skettenis
780b725ae77Skettenis static int
specialcmp(char * a,char * b)781b725ae77Skettenis specialcmp (char *a, char *b)
782b725ae77Skettenis {
783b725ae77Skettenis while (*a && *a != ' ' && *a != ']' && *b && *b != ' ' && *b != ']')
784b725ae77Skettenis {
785b725ae77Skettenis if (*a != *b)
786b725ae77Skettenis return *a - *b;
787b725ae77Skettenis a++, b++;
788b725ae77Skettenis }
789b725ae77Skettenis if (*a && *a != ' ' && *a != ']')
790b725ae77Skettenis return 1; /* a is longer therefore greater */
791b725ae77Skettenis if (*b && *b != ' ' && *b != ']')
792b725ae77Skettenis return -1; /* a is shorter therefore lesser */
793b725ae77Skettenis return 0; /* a and b are identical */
794b725ae77Skettenis }
795b725ae77Skettenis
796b725ae77Skettenis /*
797b725ae77Skettenis * Function: compare_selectors (const void *, const void *)
798b725ae77Skettenis *
799b725ae77Skettenis * Comparison function for use with qsort. Arguments are symbols or
800b725ae77Skettenis * msymbols Compares selector part of objc method name alphabetically.
801b725ae77Skettenis */
802b725ae77Skettenis
803b725ae77Skettenis static int
compare_selectors(const void * a,const void * b)804b725ae77Skettenis compare_selectors (const void *a, const void *b)
805b725ae77Skettenis {
806b725ae77Skettenis char *aname, *bname;
807b725ae77Skettenis
808b725ae77Skettenis aname = SYMBOL_PRINT_NAME (*(struct symbol **) a);
809b725ae77Skettenis bname = SYMBOL_PRINT_NAME (*(struct symbol **) b);
810b725ae77Skettenis if (aname == NULL || bname == NULL)
811b725ae77Skettenis error ("internal: compare_selectors(1)");
812b725ae77Skettenis
813b725ae77Skettenis aname = strchr(aname, ' ');
814b725ae77Skettenis bname = strchr(bname, ' ');
815b725ae77Skettenis if (aname == NULL || bname == NULL)
816b725ae77Skettenis error ("internal: compare_selectors(2)");
817b725ae77Skettenis
818b725ae77Skettenis return specialcmp (aname+1, bname+1);
819b725ae77Skettenis }
820b725ae77Skettenis
821b725ae77Skettenis /*
822b725ae77Skettenis * Function: selectors_info (regexp, from_tty)
823b725ae77Skettenis *
824b725ae77Skettenis * Implements the "Info selectors" command. Takes an optional regexp
825b725ae77Skettenis * arg. Lists all objective c selectors that match the regexp. Works
826b725ae77Skettenis * by grepping thru all symbols for objective c methods. Output list
827b725ae77Skettenis * is sorted and uniqued.
828b725ae77Skettenis */
829b725ae77Skettenis
830b725ae77Skettenis static void
selectors_info(char * regexp,int from_tty)831b725ae77Skettenis selectors_info (char *regexp, int from_tty)
832b725ae77Skettenis {
833b725ae77Skettenis struct objfile *objfile;
834b725ae77Skettenis struct minimal_symbol *msymbol;
835b725ae77Skettenis char *name;
836b725ae77Skettenis char *val;
837b725ae77Skettenis int matches = 0;
838b725ae77Skettenis int maxlen = 0;
839b725ae77Skettenis int ix;
840b725ae77Skettenis char myregexp[2048];
841b725ae77Skettenis char asel[256];
842b725ae77Skettenis struct symbol **sym_arr;
843b725ae77Skettenis int plusminus = 0;
844b725ae77Skettenis
845b725ae77Skettenis if (regexp == NULL)
846b725ae77Skettenis strcpy(myregexp, ".*]"); /* Null input, match all objc methods. */
847b725ae77Skettenis else
848b725ae77Skettenis {
849b725ae77Skettenis if (*regexp == '+' || *regexp == '-')
850b725ae77Skettenis { /* User wants only class methods or only instance methods. */
851b725ae77Skettenis plusminus = *regexp++;
852b725ae77Skettenis while (*regexp == ' ' || *regexp == '\t')
853b725ae77Skettenis regexp++;
854b725ae77Skettenis }
855b725ae77Skettenis if (*regexp == '\0')
856b725ae77Skettenis strcpy(myregexp, ".*]");
857b725ae77Skettenis else
858b725ae77Skettenis {
859b725ae77Skettenis strcpy(myregexp, regexp);
860b725ae77Skettenis if (myregexp[strlen(myregexp) - 1] == '$') /* end of selector */
861b725ae77Skettenis myregexp[strlen(myregexp) - 1] = ']'; /* end of method name */
862b725ae77Skettenis else
863b725ae77Skettenis strcat(myregexp, ".*]");
864b725ae77Skettenis }
865b725ae77Skettenis }
866b725ae77Skettenis
867b725ae77Skettenis if (regexp != NULL)
868b725ae77Skettenis {
869b725ae77Skettenis val = re_comp (myregexp);
870b725ae77Skettenis if (val != 0)
871b725ae77Skettenis error ("Invalid regexp (%s): %s", val, regexp);
872b725ae77Skettenis }
873b725ae77Skettenis
874b725ae77Skettenis /* First time thru is JUST to get max length and count. */
875b725ae77Skettenis ALL_MSYMBOLS (objfile, msymbol)
876b725ae77Skettenis {
877b725ae77Skettenis QUIT;
878b725ae77Skettenis name = SYMBOL_NATURAL_NAME (msymbol);
879b725ae77Skettenis if (name &&
880b725ae77Skettenis (name[0] == '-' || name[0] == '+') &&
881b725ae77Skettenis name[1] == '[') /* Got a method name. */
882b725ae77Skettenis {
883b725ae77Skettenis /* Filter for class/instance methods. */
884b725ae77Skettenis if (plusminus && name[0] != plusminus)
885b725ae77Skettenis continue;
886b725ae77Skettenis /* Find selector part. */
887b725ae77Skettenis name = (char *) strchr(name+2, ' ');
888b725ae77Skettenis if (regexp == NULL || re_exec(++name) != 0)
889b725ae77Skettenis {
890b725ae77Skettenis char *mystart = name;
891b725ae77Skettenis char *myend = (char *) strchr(mystart, ']');
892b725ae77Skettenis
893b725ae77Skettenis if (myend && (myend - mystart > maxlen))
894b725ae77Skettenis maxlen = myend - mystart; /* Get longest selector. */
895b725ae77Skettenis matches++;
896b725ae77Skettenis }
897b725ae77Skettenis }
898b725ae77Skettenis }
899b725ae77Skettenis if (matches)
900b725ae77Skettenis {
901b725ae77Skettenis printf_filtered ("Selectors matching \"%s\":\n\n",
902b725ae77Skettenis regexp ? regexp : "*");
903b725ae77Skettenis
904b725ae77Skettenis sym_arr = alloca (matches * sizeof (struct symbol *));
905b725ae77Skettenis matches = 0;
906b725ae77Skettenis ALL_MSYMBOLS (objfile, msymbol)
907b725ae77Skettenis {
908b725ae77Skettenis QUIT;
909b725ae77Skettenis name = SYMBOL_NATURAL_NAME (msymbol);
910b725ae77Skettenis if (name &&
911b725ae77Skettenis (name[0] == '-' || name[0] == '+') &&
912b725ae77Skettenis name[1] == '[') /* Got a method name. */
913b725ae77Skettenis {
914b725ae77Skettenis /* Filter for class/instance methods. */
915b725ae77Skettenis if (plusminus && name[0] != plusminus)
916b725ae77Skettenis continue;
917b725ae77Skettenis /* Find selector part. */
918b725ae77Skettenis name = (char *) strchr(name+2, ' ');
919b725ae77Skettenis if (regexp == NULL || re_exec(++name) != 0)
920b725ae77Skettenis sym_arr[matches++] = (struct symbol *) msymbol;
921b725ae77Skettenis }
922b725ae77Skettenis }
923b725ae77Skettenis
924b725ae77Skettenis qsort (sym_arr, matches, sizeof (struct minimal_symbol *),
925b725ae77Skettenis compare_selectors);
926b725ae77Skettenis /* Prevent compare on first iteration. */
927b725ae77Skettenis asel[0] = 0;
928b725ae77Skettenis for (ix = 0; ix < matches; ix++) /* Now do the output. */
929b725ae77Skettenis {
930b725ae77Skettenis char *p = asel;
931b725ae77Skettenis
932b725ae77Skettenis QUIT;
933b725ae77Skettenis name = SYMBOL_NATURAL_NAME (sym_arr[ix]);
934b725ae77Skettenis name = strchr (name, ' ') + 1;
935b725ae77Skettenis if (p[0] && specialcmp(name, p) == 0)
936b725ae77Skettenis continue; /* Seen this one already (not unique). */
937b725ae77Skettenis
938b725ae77Skettenis /* Copy selector part. */
939b725ae77Skettenis while (*name && *name != ']')
940b725ae77Skettenis *p++ = *name++;
941b725ae77Skettenis *p++ = '\0';
942b725ae77Skettenis /* Print in columns. */
943b725ae77Skettenis puts_filtered_tabular(asel, maxlen + 1, 0);
944b725ae77Skettenis }
945b725ae77Skettenis begin_line();
946b725ae77Skettenis }
947b725ae77Skettenis else
948b725ae77Skettenis printf_filtered ("No selectors matching \"%s\"\n", regexp ? regexp : "*");
949b725ae77Skettenis }
950b725ae77Skettenis
951b725ae77Skettenis /*
952b725ae77Skettenis * Function: compare_classes (const void *, const void *)
953b725ae77Skettenis *
954b725ae77Skettenis * Comparison function for use with qsort. Arguments are symbols or
955b725ae77Skettenis * msymbols Compares class part of objc method name alphabetically.
956b725ae77Skettenis */
957b725ae77Skettenis
958b725ae77Skettenis static int
compare_classes(const void * a,const void * b)959b725ae77Skettenis compare_classes (const void *a, const void *b)
960b725ae77Skettenis {
961b725ae77Skettenis char *aname, *bname;
962b725ae77Skettenis
963b725ae77Skettenis aname = SYMBOL_PRINT_NAME (*(struct symbol **) a);
964b725ae77Skettenis bname = SYMBOL_PRINT_NAME (*(struct symbol **) b);
965b725ae77Skettenis if (aname == NULL || bname == NULL)
966b725ae77Skettenis error ("internal: compare_classes(1)");
967b725ae77Skettenis
968b725ae77Skettenis return specialcmp (aname+1, bname+1);
969b725ae77Skettenis }
970b725ae77Skettenis
971b725ae77Skettenis /*
972b725ae77Skettenis * Function: classes_info(regexp, from_tty)
973b725ae77Skettenis *
974b725ae77Skettenis * Implements the "info classes" command for objective c classes.
975b725ae77Skettenis * Lists all objective c classes that match the optional regexp.
976b725ae77Skettenis * Works by grepping thru the list of objective c methods. List will
977b725ae77Skettenis * be sorted and uniqued (since one class may have many methods).
978b725ae77Skettenis * BUGS: will not list a class that has no methods.
979b725ae77Skettenis */
980b725ae77Skettenis
981b725ae77Skettenis static void
classes_info(char * regexp,int from_tty)982b725ae77Skettenis classes_info (char *regexp, int from_tty)
983b725ae77Skettenis {
984b725ae77Skettenis struct objfile *objfile;
985b725ae77Skettenis struct minimal_symbol *msymbol;
986b725ae77Skettenis char *name;
987b725ae77Skettenis char *val;
988b725ae77Skettenis int matches = 0;
989b725ae77Skettenis int maxlen = 0;
990b725ae77Skettenis int ix;
991b725ae77Skettenis char myregexp[2048];
992b725ae77Skettenis char aclass[256];
993b725ae77Skettenis struct symbol **sym_arr;
994b725ae77Skettenis
995b725ae77Skettenis if (regexp == NULL)
996b725ae77Skettenis strcpy(myregexp, ".* "); /* Null input: match all objc classes. */
997b725ae77Skettenis else
998b725ae77Skettenis {
999b725ae77Skettenis strcpy(myregexp, regexp);
1000b725ae77Skettenis if (myregexp[strlen(myregexp) - 1] == '$')
1001b725ae77Skettenis /* In the method name, the end of the class name is marked by ' '. */
1002b725ae77Skettenis myregexp[strlen(myregexp) - 1] = ' ';
1003b725ae77Skettenis else
1004b725ae77Skettenis strcat(myregexp, ".* ");
1005b725ae77Skettenis }
1006b725ae77Skettenis
1007b725ae77Skettenis if (regexp != NULL)
1008b725ae77Skettenis {
1009b725ae77Skettenis val = re_comp (myregexp);
1010b725ae77Skettenis if (val != 0)
1011b725ae77Skettenis error ("Invalid regexp (%s): %s", val, regexp);
1012b725ae77Skettenis }
1013b725ae77Skettenis
1014b725ae77Skettenis /* First time thru is JUST to get max length and count. */
1015b725ae77Skettenis ALL_MSYMBOLS (objfile, msymbol)
1016b725ae77Skettenis {
1017b725ae77Skettenis QUIT;
1018b725ae77Skettenis name = SYMBOL_NATURAL_NAME (msymbol);
1019b725ae77Skettenis if (name &&
1020b725ae77Skettenis (name[0] == '-' || name[0] == '+') &&
1021b725ae77Skettenis name[1] == '[') /* Got a method name. */
1022b725ae77Skettenis if (regexp == NULL || re_exec(name+2) != 0)
1023b725ae77Skettenis {
1024b725ae77Skettenis /* Compute length of classname part. */
1025b725ae77Skettenis char *mystart = name + 2;
1026b725ae77Skettenis char *myend = (char *) strchr(mystart, ' ');
1027b725ae77Skettenis
1028b725ae77Skettenis if (myend && (myend - mystart > maxlen))
1029b725ae77Skettenis maxlen = myend - mystart;
1030b725ae77Skettenis matches++;
1031b725ae77Skettenis }
1032b725ae77Skettenis }
1033b725ae77Skettenis if (matches)
1034b725ae77Skettenis {
1035b725ae77Skettenis printf_filtered ("Classes matching \"%s\":\n\n",
1036b725ae77Skettenis regexp ? regexp : "*");
1037b725ae77Skettenis sym_arr = alloca (matches * sizeof (struct symbol *));
1038b725ae77Skettenis matches = 0;
1039b725ae77Skettenis ALL_MSYMBOLS (objfile, msymbol)
1040b725ae77Skettenis {
1041b725ae77Skettenis QUIT;
1042b725ae77Skettenis name = SYMBOL_NATURAL_NAME (msymbol);
1043b725ae77Skettenis if (name &&
1044b725ae77Skettenis (name[0] == '-' || name[0] == '+') &&
1045b725ae77Skettenis name[1] == '[') /* Got a method name. */
1046b725ae77Skettenis if (regexp == NULL || re_exec(name+2) != 0)
1047b725ae77Skettenis sym_arr[matches++] = (struct symbol *) msymbol;
1048b725ae77Skettenis }
1049b725ae77Skettenis
1050b725ae77Skettenis qsort (sym_arr, matches, sizeof (struct minimal_symbol *),
1051b725ae77Skettenis compare_classes);
1052b725ae77Skettenis /* Prevent compare on first iteration. */
1053b725ae77Skettenis aclass[0] = 0;
1054b725ae77Skettenis for (ix = 0; ix < matches; ix++) /* Now do the output. */
1055b725ae77Skettenis {
1056b725ae77Skettenis char *p = aclass;
1057b725ae77Skettenis
1058b725ae77Skettenis QUIT;
1059b725ae77Skettenis name = SYMBOL_NATURAL_NAME (sym_arr[ix]);
1060b725ae77Skettenis name += 2;
1061b725ae77Skettenis if (p[0] && specialcmp(name, p) == 0)
1062b725ae77Skettenis continue; /* Seen this one already (not unique). */
1063b725ae77Skettenis
1064b725ae77Skettenis /* Copy class part of method name. */
1065b725ae77Skettenis while (*name && *name != ' ')
1066b725ae77Skettenis *p++ = *name++;
1067b725ae77Skettenis *p++ = '\0';
1068b725ae77Skettenis /* Print in columns. */
1069b725ae77Skettenis puts_filtered_tabular(aclass, maxlen + 1, 0);
1070b725ae77Skettenis }
1071b725ae77Skettenis begin_line();
1072b725ae77Skettenis }
1073b725ae77Skettenis else
1074b725ae77Skettenis printf_filtered ("No classes matching \"%s\"\n", regexp ? regexp : "*");
1075b725ae77Skettenis }
1076b725ae77Skettenis
1077b725ae77Skettenis /*
1078b725ae77Skettenis * Function: find_imps (char *selector, struct symbol **sym_arr)
1079b725ae77Skettenis *
1080b725ae77Skettenis * Input: a string representing a selector
1081b725ae77Skettenis * a pointer to an array of symbol pointers
1082b725ae77Skettenis * possibly a pointer to a symbol found by the caller.
1083b725ae77Skettenis *
1084b725ae77Skettenis * Output: number of methods that implement that selector. Side
1085b725ae77Skettenis * effects: The array of symbol pointers is filled with matching syms.
1086b725ae77Skettenis *
1087b725ae77Skettenis * By analogy with function "find_methods" (symtab.c), builds a list
1088b725ae77Skettenis * of symbols matching the ambiguous input, so that "decode_line_2"
1089b725ae77Skettenis * (symtab.c) can list them and ask the user to choose one or more.
1090b725ae77Skettenis * In this case the matches are objective c methods
1091b725ae77Skettenis * ("implementations") matching an objective c selector.
1092b725ae77Skettenis *
1093b725ae77Skettenis * Note that it is possible for a normal (c-style) function to have
1094b725ae77Skettenis * the same name as an objective c selector. To prevent the selector
1095b725ae77Skettenis * from eclipsing the function, we allow the caller (decode_line_1) to
1096b725ae77Skettenis * search for such a function first, and if it finds one, pass it in
1097b725ae77Skettenis * to us. We will then integrate it into the list. We also search
1098b725ae77Skettenis * for one here, among the minsyms.
1099b725ae77Skettenis *
1100b725ae77Skettenis * NOTE: if NUM_DEBUGGABLE is non-zero, the sym_arr will be divided
1101b725ae77Skettenis * into two parts: debuggable (struct symbol) syms, and
1102b725ae77Skettenis * non_debuggable (struct minimal_symbol) syms. The debuggable
1103b725ae77Skettenis * ones will come first, before NUM_DEBUGGABLE (which will thus
1104b725ae77Skettenis * be the index of the first non-debuggable one).
1105b725ae77Skettenis */
1106b725ae77Skettenis
1107b725ae77Skettenis /*
1108b725ae77Skettenis * Function: total_number_of_imps (char *selector);
1109b725ae77Skettenis *
1110b725ae77Skettenis * Input: a string representing a selector
1111b725ae77Skettenis * Output: number of methods that implement that selector.
1112b725ae77Skettenis *
1113b725ae77Skettenis * By analogy with function "total_number_of_methods", this allows
1114b725ae77Skettenis * decode_line_1 (symtab.c) to detect if there are objective c methods
1115b725ae77Skettenis * matching the input, and to allocate an array of pointers to them
1116b725ae77Skettenis * which can be manipulated by "decode_line_2" (also in symtab.c).
1117b725ae77Skettenis */
1118b725ae77Skettenis
1119b725ae77Skettenis char *
parse_selector(char * method,char ** selector)1120b725ae77Skettenis parse_selector (char *method, char **selector)
1121b725ae77Skettenis {
1122b725ae77Skettenis char *s1 = NULL;
1123b725ae77Skettenis char *s2 = NULL;
1124b725ae77Skettenis int found_quote = 0;
1125b725ae77Skettenis
1126b725ae77Skettenis char *nselector = NULL;
1127b725ae77Skettenis
1128b725ae77Skettenis gdb_assert (selector != NULL);
1129b725ae77Skettenis
1130b725ae77Skettenis s1 = method;
1131b725ae77Skettenis
1132b725ae77Skettenis while (isspace (*s1))
1133b725ae77Skettenis s1++;
1134b725ae77Skettenis if (*s1 == '\'')
1135b725ae77Skettenis {
1136b725ae77Skettenis found_quote = 1;
1137b725ae77Skettenis s1++;
1138b725ae77Skettenis }
1139b725ae77Skettenis while (isspace (*s1))
1140b725ae77Skettenis s1++;
1141b725ae77Skettenis
1142b725ae77Skettenis nselector = s1;
1143b725ae77Skettenis s2 = s1;
1144b725ae77Skettenis
1145b725ae77Skettenis for (;;) {
1146b725ae77Skettenis if (isalnum (*s2) || (*s2 == '_') || (*s2 == ':'))
1147b725ae77Skettenis *s1++ = *s2;
1148b725ae77Skettenis else if (isspace (*s2))
1149b725ae77Skettenis ;
1150b725ae77Skettenis else if ((*s2 == '\0') || (*s2 == '\''))
1151b725ae77Skettenis break;
1152b725ae77Skettenis else
1153b725ae77Skettenis return NULL;
1154b725ae77Skettenis s2++;
1155b725ae77Skettenis }
1156b725ae77Skettenis *s1++ = '\0';
1157b725ae77Skettenis
1158b725ae77Skettenis while (isspace (*s2))
1159b725ae77Skettenis s2++;
1160b725ae77Skettenis if (found_quote)
1161b725ae77Skettenis {
1162b725ae77Skettenis if (*s2 == '\'')
1163b725ae77Skettenis s2++;
1164b725ae77Skettenis while (isspace (*s2))
1165b725ae77Skettenis s2++;
1166b725ae77Skettenis }
1167b725ae77Skettenis
1168b725ae77Skettenis if (selector != NULL)
1169b725ae77Skettenis *selector = nselector;
1170b725ae77Skettenis
1171b725ae77Skettenis return s2;
1172b725ae77Skettenis }
1173b725ae77Skettenis
1174b725ae77Skettenis char *
parse_method(char * method,char * type,char ** class,char ** category,char ** selector)1175b725ae77Skettenis parse_method (char *method, char *type, char **class,
1176b725ae77Skettenis char **category, char **selector)
1177b725ae77Skettenis {
1178b725ae77Skettenis char *s1 = NULL;
1179b725ae77Skettenis char *s2 = NULL;
1180b725ae77Skettenis int found_quote = 0;
1181b725ae77Skettenis
1182b725ae77Skettenis char ntype = '\0';
1183b725ae77Skettenis char *nclass = NULL;
1184b725ae77Skettenis char *ncategory = NULL;
1185b725ae77Skettenis char *nselector = NULL;
1186b725ae77Skettenis
1187b725ae77Skettenis gdb_assert (type != NULL);
1188b725ae77Skettenis gdb_assert (class != NULL);
1189b725ae77Skettenis gdb_assert (category != NULL);
1190b725ae77Skettenis gdb_assert (selector != NULL);
1191b725ae77Skettenis
1192b725ae77Skettenis s1 = method;
1193b725ae77Skettenis
1194b725ae77Skettenis while (isspace (*s1))
1195b725ae77Skettenis s1++;
1196b725ae77Skettenis if (*s1 == '\'')
1197b725ae77Skettenis {
1198b725ae77Skettenis found_quote = 1;
1199b725ae77Skettenis s1++;
1200b725ae77Skettenis }
1201b725ae77Skettenis while (isspace (*s1))
1202b725ae77Skettenis s1++;
1203b725ae77Skettenis
1204b725ae77Skettenis if ((s1[0] == '+') || (s1[0] == '-'))
1205b725ae77Skettenis ntype = *s1++;
1206b725ae77Skettenis
1207b725ae77Skettenis while (isspace (*s1))
1208b725ae77Skettenis s1++;
1209b725ae77Skettenis
1210b725ae77Skettenis if (*s1 != '[')
1211b725ae77Skettenis return NULL;
1212b725ae77Skettenis s1++;
1213b725ae77Skettenis
1214b725ae77Skettenis nclass = s1;
1215b725ae77Skettenis while (isalnum (*s1) || (*s1 == '_'))
1216b725ae77Skettenis s1++;
1217b725ae77Skettenis
1218b725ae77Skettenis s2 = s1;
1219b725ae77Skettenis while (isspace (*s2))
1220b725ae77Skettenis s2++;
1221b725ae77Skettenis
1222b725ae77Skettenis if (*s2 == '(')
1223b725ae77Skettenis {
1224b725ae77Skettenis s2++;
1225b725ae77Skettenis while (isspace (*s2))
1226b725ae77Skettenis s2++;
1227b725ae77Skettenis ncategory = s2;
1228b725ae77Skettenis while (isalnum (*s2) || (*s2 == '_'))
1229b725ae77Skettenis s2++;
1230b725ae77Skettenis *s2++ = '\0';
1231b725ae77Skettenis }
1232b725ae77Skettenis
1233b725ae77Skettenis /* Truncate the class name now that we're not using the open paren. */
1234b725ae77Skettenis *s1++ = '\0';
1235b725ae77Skettenis
1236b725ae77Skettenis nselector = s2;
1237b725ae77Skettenis s1 = s2;
1238b725ae77Skettenis
1239b725ae77Skettenis for (;;) {
1240b725ae77Skettenis if (isalnum (*s2) || (*s2 == '_') || (*s2 == ':'))
1241b725ae77Skettenis *s1++ = *s2;
1242b725ae77Skettenis else if (isspace (*s2))
1243b725ae77Skettenis ;
1244b725ae77Skettenis else if (*s2 == ']')
1245b725ae77Skettenis break;
1246b725ae77Skettenis else
1247b725ae77Skettenis return NULL;
1248b725ae77Skettenis s2++;
1249b725ae77Skettenis }
1250b725ae77Skettenis *s1++ = '\0';
1251b725ae77Skettenis s2++;
1252b725ae77Skettenis
1253b725ae77Skettenis while (isspace (*s2))
1254b725ae77Skettenis s2++;
1255b725ae77Skettenis if (found_quote)
1256b725ae77Skettenis {
1257b725ae77Skettenis if (*s2 != '\'')
1258b725ae77Skettenis return NULL;
1259b725ae77Skettenis s2++;
1260b725ae77Skettenis while (isspace (*s2))
1261b725ae77Skettenis s2++;
1262b725ae77Skettenis }
1263b725ae77Skettenis
1264b725ae77Skettenis if (type != NULL)
1265b725ae77Skettenis *type = ntype;
1266b725ae77Skettenis if (class != NULL)
1267b725ae77Skettenis *class = nclass;
1268b725ae77Skettenis if (category != NULL)
1269b725ae77Skettenis *category = ncategory;
1270b725ae77Skettenis if (selector != NULL)
1271b725ae77Skettenis *selector = nselector;
1272b725ae77Skettenis
1273b725ae77Skettenis return s2;
1274b725ae77Skettenis }
1275b725ae77Skettenis
1276b725ae77Skettenis static void
find_methods(struct symtab * symtab,char type,const char * class,const char * category,const char * selector,struct symbol ** syms,unsigned int * nsym,unsigned int * ndebug)1277b725ae77Skettenis find_methods (struct symtab *symtab, char type,
1278b725ae77Skettenis const char *class, const char *category,
1279b725ae77Skettenis const char *selector, struct symbol **syms,
1280b725ae77Skettenis unsigned int *nsym, unsigned int *ndebug)
1281b725ae77Skettenis {
1282b725ae77Skettenis struct objfile *objfile = NULL;
1283b725ae77Skettenis struct minimal_symbol *msymbol = NULL;
1284b725ae77Skettenis struct block *block = NULL;
1285b725ae77Skettenis struct symbol *sym = NULL;
1286b725ae77Skettenis
1287b725ae77Skettenis char *symname = NULL;
1288b725ae77Skettenis
1289b725ae77Skettenis char ntype = '\0';
1290b725ae77Skettenis char *nclass = NULL;
1291b725ae77Skettenis char *ncategory = NULL;
1292b725ae77Skettenis char *nselector = NULL;
1293b725ae77Skettenis
1294b725ae77Skettenis unsigned int csym = 0;
1295b725ae77Skettenis unsigned int cdebug = 0;
1296b725ae77Skettenis
1297b725ae77Skettenis static char *tmp = NULL;
1298b725ae77Skettenis static unsigned int tmplen = 0;
1299b725ae77Skettenis
1300b725ae77Skettenis gdb_assert (nsym != NULL);
1301b725ae77Skettenis gdb_assert (ndebug != NULL);
1302b725ae77Skettenis
1303b725ae77Skettenis if (symtab)
1304b725ae77Skettenis block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (symtab), STATIC_BLOCK);
1305b725ae77Skettenis
1306b725ae77Skettenis ALL_MSYMBOLS (objfile, msymbol)
1307b725ae77Skettenis {
1308b725ae77Skettenis QUIT;
1309b725ae77Skettenis
1310b725ae77Skettenis if ((msymbol->type != mst_text) && (msymbol->type != mst_file_text))
1311b725ae77Skettenis /* Not a function or method. */
1312b725ae77Skettenis continue;
1313b725ae77Skettenis
1314b725ae77Skettenis if (symtab)
1315b725ae77Skettenis if ((SYMBOL_VALUE_ADDRESS (msymbol) < BLOCK_START (block)) ||
1316b725ae77Skettenis (SYMBOL_VALUE_ADDRESS (msymbol) >= BLOCK_END (block)))
1317b725ae77Skettenis /* Not in the specified symtab. */
1318b725ae77Skettenis continue;
1319b725ae77Skettenis
1320b725ae77Skettenis symname = SYMBOL_NATURAL_NAME (msymbol);
1321b725ae77Skettenis if (symname == NULL)
1322b725ae77Skettenis continue;
1323b725ae77Skettenis
1324b725ae77Skettenis if ((symname[0] != '-' && symname[0] != '+') || (symname[1] != '['))
1325b725ae77Skettenis /* Not a method name. */
1326b725ae77Skettenis continue;
1327b725ae77Skettenis
1328b725ae77Skettenis while ((strlen (symname) + 1) >= tmplen)
1329b725ae77Skettenis {
1330b725ae77Skettenis tmplen = (tmplen == 0) ? 1024 : tmplen * 2;
1331b725ae77Skettenis tmp = xrealloc (tmp, tmplen);
1332b725ae77Skettenis }
1333b725ae77Skettenis strcpy (tmp, symname);
1334b725ae77Skettenis
1335b725ae77Skettenis if (parse_method (tmp, &ntype, &nclass, &ncategory, &nselector) == NULL)
1336b725ae77Skettenis continue;
1337b725ae77Skettenis
1338b725ae77Skettenis if ((type != '\0') && (ntype != type))
1339b725ae77Skettenis continue;
1340b725ae77Skettenis
1341b725ae77Skettenis if ((class != NULL)
1342b725ae77Skettenis && ((nclass == NULL) || (strcmp (class, nclass) != 0)))
1343b725ae77Skettenis continue;
1344b725ae77Skettenis
1345b725ae77Skettenis if ((category != NULL) &&
1346b725ae77Skettenis ((ncategory == NULL) || (strcmp (category, ncategory) != 0)))
1347b725ae77Skettenis continue;
1348b725ae77Skettenis
1349b725ae77Skettenis if ((selector != NULL) &&
1350b725ae77Skettenis ((nselector == NULL) || (strcmp (selector, nselector) != 0)))
1351b725ae77Skettenis continue;
1352b725ae77Skettenis
1353b725ae77Skettenis sym = find_pc_function (SYMBOL_VALUE_ADDRESS (msymbol));
1354b725ae77Skettenis if (sym != NULL)
1355b725ae77Skettenis {
1356b725ae77Skettenis const char *newsymname = SYMBOL_NATURAL_NAME (sym);
1357b725ae77Skettenis
1358b725ae77Skettenis if (strcmp (symname, newsymname) == 0)
1359b725ae77Skettenis {
1360b725ae77Skettenis /* Found a high-level method sym: swap it into the
1361b725ae77Skettenis lower part of sym_arr (below num_debuggable). */
1362b725ae77Skettenis if (syms != NULL)
1363b725ae77Skettenis {
1364b725ae77Skettenis syms[csym] = syms[cdebug];
1365b725ae77Skettenis syms[cdebug] = sym;
1366b725ae77Skettenis }
1367b725ae77Skettenis csym++;
1368b725ae77Skettenis cdebug++;
1369b725ae77Skettenis }
1370b725ae77Skettenis else
1371b725ae77Skettenis {
1372b725ae77Skettenis warning (
1373b725ae77Skettenis "debugging symbol \"%s\" does not match minimal symbol (\"%s\"); ignoring",
1374b725ae77Skettenis newsymname, symname);
1375b725ae77Skettenis if (syms != NULL)
1376b725ae77Skettenis syms[csym] = (struct symbol *) msymbol;
1377b725ae77Skettenis csym++;
1378b725ae77Skettenis }
1379b725ae77Skettenis }
1380b725ae77Skettenis else
1381b725ae77Skettenis {
1382b725ae77Skettenis /* Found a non-debuggable method symbol. */
1383b725ae77Skettenis if (syms != NULL)
1384b725ae77Skettenis syms[csym] = (struct symbol *) msymbol;
1385b725ae77Skettenis csym++;
1386b725ae77Skettenis }
1387b725ae77Skettenis }
1388b725ae77Skettenis
1389b725ae77Skettenis if (nsym != NULL)
1390b725ae77Skettenis *nsym = csym;
1391b725ae77Skettenis if (ndebug != NULL)
1392b725ae77Skettenis *ndebug = cdebug;
1393b725ae77Skettenis }
1394b725ae77Skettenis
find_imps(struct symtab * symtab,struct block * block,char * method,struct symbol ** syms,unsigned int * nsym,unsigned int * ndebug)1395b725ae77Skettenis char *find_imps (struct symtab *symtab, struct block *block,
1396b725ae77Skettenis char *method, struct symbol **syms,
1397b725ae77Skettenis unsigned int *nsym, unsigned int *ndebug)
1398b725ae77Skettenis {
1399b725ae77Skettenis char type = '\0';
1400b725ae77Skettenis char *class = NULL;
1401b725ae77Skettenis char *category = NULL;
1402b725ae77Skettenis char *selector = NULL;
1403b725ae77Skettenis
1404b725ae77Skettenis unsigned int csym = 0;
1405b725ae77Skettenis unsigned int cdebug = 0;
1406b725ae77Skettenis
1407b725ae77Skettenis unsigned int ncsym = 0;
1408b725ae77Skettenis unsigned int ncdebug = 0;
1409b725ae77Skettenis
1410b725ae77Skettenis char *buf = NULL;
1411b725ae77Skettenis char *tmp = NULL;
1412b725ae77Skettenis
1413b725ae77Skettenis gdb_assert (nsym != NULL);
1414b725ae77Skettenis gdb_assert (ndebug != NULL);
1415b725ae77Skettenis
1416b725ae77Skettenis if (nsym != NULL)
1417b725ae77Skettenis *nsym = 0;
1418b725ae77Skettenis if (ndebug != NULL)
1419b725ae77Skettenis *ndebug = 0;
1420b725ae77Skettenis
1421b725ae77Skettenis buf = (char *) alloca (strlen (method) + 1);
1422b725ae77Skettenis strcpy (buf, method);
1423b725ae77Skettenis tmp = parse_method (buf, &type, &class, &category, &selector);
1424b725ae77Skettenis
1425b725ae77Skettenis if (tmp == NULL) {
1426b725ae77Skettenis
1427b725ae77Skettenis struct symbol *sym = NULL;
1428b725ae77Skettenis struct minimal_symbol *msym = NULL;
1429b725ae77Skettenis
1430b725ae77Skettenis strcpy (buf, method);
1431b725ae77Skettenis tmp = parse_selector (buf, &selector);
1432b725ae77Skettenis
1433b725ae77Skettenis if (tmp == NULL)
1434b725ae77Skettenis return NULL;
1435b725ae77Skettenis
1436b725ae77Skettenis sym = lookup_symbol (selector, block, VAR_DOMAIN, 0, NULL);
1437b725ae77Skettenis if (sym != NULL)
1438b725ae77Skettenis {
1439b725ae77Skettenis if (syms)
1440b725ae77Skettenis syms[csym] = sym;
1441b725ae77Skettenis csym++;
1442b725ae77Skettenis cdebug++;
1443b725ae77Skettenis }
1444b725ae77Skettenis
1445b725ae77Skettenis if (sym == NULL)
1446b725ae77Skettenis msym = lookup_minimal_symbol (selector, 0, 0);
1447b725ae77Skettenis
1448b725ae77Skettenis if (msym != NULL)
1449b725ae77Skettenis {
1450b725ae77Skettenis if (syms)
1451b725ae77Skettenis syms[csym] = (struct symbol *)msym;
1452b725ae77Skettenis csym++;
1453b725ae77Skettenis }
1454b725ae77Skettenis }
1455b725ae77Skettenis
1456b725ae77Skettenis if (syms != NULL)
1457b725ae77Skettenis find_methods (symtab, type, class, category, selector,
1458b725ae77Skettenis syms + csym, &ncsym, &ncdebug);
1459b725ae77Skettenis else
1460b725ae77Skettenis find_methods (symtab, type, class, category, selector,
1461b725ae77Skettenis NULL, &ncsym, &ncdebug);
1462b725ae77Skettenis
1463b725ae77Skettenis /* If we didn't find any methods, just return. */
1464b725ae77Skettenis if (ncsym == 0 && ncdebug == 0)
1465b725ae77Skettenis return method;
1466b725ae77Skettenis
1467b725ae77Skettenis /* Take debug symbols from the second batch of symbols and swap them
1468b725ae77Skettenis * with debug symbols from the first batch. Repeat until either the
1469b725ae77Skettenis * second section is out of debug symbols or the first section is
1470b725ae77Skettenis * full of debug symbols. Either way we have all debug symbols
1471b725ae77Skettenis * packed to the beginning of the buffer.
1472b725ae77Skettenis */
1473b725ae77Skettenis
1474b725ae77Skettenis if (syms != NULL)
1475b725ae77Skettenis {
1476b725ae77Skettenis while ((cdebug < csym) && (ncdebug > 0))
1477b725ae77Skettenis {
1478b725ae77Skettenis struct symbol *s = NULL;
1479b725ae77Skettenis /* First non-debugging symbol. */
1480b725ae77Skettenis unsigned int i = cdebug;
1481b725ae77Skettenis /* Last of second batch of debug symbols. */
1482b725ae77Skettenis unsigned int j = csym + ncdebug - 1;
1483b725ae77Skettenis
1484b725ae77Skettenis s = syms[j];
1485b725ae77Skettenis syms[j] = syms[i];
1486b725ae77Skettenis syms[i] = s;
1487b725ae77Skettenis
1488b725ae77Skettenis /* We've moved a symbol from the second debug section to the
1489b725ae77Skettenis first one. */
1490b725ae77Skettenis cdebug++;
1491b725ae77Skettenis ncdebug--;
1492b725ae77Skettenis }
1493b725ae77Skettenis }
1494b725ae77Skettenis
1495b725ae77Skettenis csym += ncsym;
1496b725ae77Skettenis cdebug += ncdebug;
1497b725ae77Skettenis
1498b725ae77Skettenis if (nsym != NULL)
1499b725ae77Skettenis *nsym = csym;
1500b725ae77Skettenis if (ndebug != NULL)
1501b725ae77Skettenis *ndebug = cdebug;
1502b725ae77Skettenis
1503b725ae77Skettenis if (syms == NULL)
1504b725ae77Skettenis return method + (tmp - buf);
1505b725ae77Skettenis
1506b725ae77Skettenis if (csym > 1)
1507b725ae77Skettenis {
1508b725ae77Skettenis /* Sort debuggable symbols. */
1509b725ae77Skettenis if (cdebug > 1)
1510b725ae77Skettenis qsort (syms, cdebug, sizeof (struct minimal_symbol *),
1511b725ae77Skettenis compare_classes);
1512b725ae77Skettenis
1513b725ae77Skettenis /* Sort minimal_symbols. */
1514b725ae77Skettenis if ((csym - cdebug) > 1)
1515b725ae77Skettenis qsort (&syms[cdebug], csym - cdebug,
1516b725ae77Skettenis sizeof (struct minimal_symbol *), compare_classes);
1517b725ae77Skettenis }
1518b725ae77Skettenis /* Terminate the sym_arr list. */
1519b725ae77Skettenis syms[csym] = 0;
1520b725ae77Skettenis
1521b725ae77Skettenis return method + (tmp - buf);
1522b725ae77Skettenis }
1523b725ae77Skettenis
1524b725ae77Skettenis static void
print_object_command(char * args,int from_tty)1525b725ae77Skettenis print_object_command (char *args, int from_tty)
1526b725ae77Skettenis {
1527b725ae77Skettenis struct value *object, *function, *description;
1528b725ae77Skettenis CORE_ADDR string_addr, object_addr;
1529b725ae77Skettenis int i = 0;
1530b725ae77Skettenis char c = -1;
1531b725ae77Skettenis
1532b725ae77Skettenis if (!args || !*args)
1533b725ae77Skettenis error (
1534b725ae77Skettenis "The 'print-object' command requires an argument (an Objective-C object)");
1535b725ae77Skettenis
1536b725ae77Skettenis {
1537b725ae77Skettenis struct expression *expr = parse_expression (args);
1538b725ae77Skettenis struct cleanup *old_chain =
1539b725ae77Skettenis make_cleanup (free_current_contents, &expr);
1540b725ae77Skettenis int pc = 0;
1541b725ae77Skettenis
1542b725ae77Skettenis object = expr->language_defn->la_exp_desc->evaluate_exp
1543b725ae77Skettenis (builtin_type_void_data_ptr, expr, &pc, EVAL_NORMAL);
1544b725ae77Skettenis do_cleanups (old_chain);
1545b725ae77Skettenis }
1546b725ae77Skettenis
1547b725ae77Skettenis /* Validate the address for sanity. */
1548b725ae77Skettenis object_addr = value_as_long (object);
1549b725ae77Skettenis read_memory (object_addr, &c, 1);
1550b725ae77Skettenis
1551b725ae77Skettenis function = find_function_in_inferior ("_NSPrintForDebugger");
1552b725ae77Skettenis if (function == NULL)
1553b725ae77Skettenis error ("Unable to locate _NSPrintForDebugger in child process");
1554b725ae77Skettenis
1555b725ae77Skettenis description = call_function_by_hand (function, 1, &object);
1556b725ae77Skettenis
1557b725ae77Skettenis string_addr = value_as_long (description);
1558b725ae77Skettenis if (string_addr == 0)
1559b725ae77Skettenis error ("object returns null description");
1560b725ae77Skettenis
1561b725ae77Skettenis read_memory (string_addr + i++, &c, 1);
1562b725ae77Skettenis if (c != '\0')
1563b725ae77Skettenis do
1564b725ae77Skettenis { /* Read and print characters up to EOS. */
1565b725ae77Skettenis QUIT;
1566b725ae77Skettenis printf_filtered ("%c", c);
1567b725ae77Skettenis read_memory (string_addr + i++, &c, 1);
1568b725ae77Skettenis } while (c != 0);
1569b725ae77Skettenis else
1570b725ae77Skettenis printf_filtered("<object returns empty description>");
1571b725ae77Skettenis printf_filtered ("\n");
1572b725ae77Skettenis }
1573b725ae77Skettenis
1574b725ae77Skettenis /* The data structure 'methcalls' is used to detect method calls (thru
1575b725ae77Skettenis * ObjC runtime lib functions objc_msgSend, objc_msgSendSuper, etc.),
1576b725ae77Skettenis * and ultimately find the method being called.
1577b725ae77Skettenis */
1578b725ae77Skettenis
1579b725ae77Skettenis struct objc_methcall {
1580b725ae77Skettenis char *name;
1581b725ae77Skettenis /* Return instance method to be called. */
1582b725ae77Skettenis int (*stop_at) (CORE_ADDR, CORE_ADDR *);
1583b725ae77Skettenis /* Start of pc range corresponding to method invocation. */
1584b725ae77Skettenis CORE_ADDR begin;
1585b725ae77Skettenis /* End of pc range corresponding to method invocation. */
1586b725ae77Skettenis CORE_ADDR end;
1587b725ae77Skettenis };
1588b725ae77Skettenis
1589b725ae77Skettenis static int resolve_msgsend (CORE_ADDR pc, CORE_ADDR *new_pc);
1590b725ae77Skettenis static int resolve_msgsend_stret (CORE_ADDR pc, CORE_ADDR *new_pc);
1591b725ae77Skettenis static int resolve_msgsend_super (CORE_ADDR pc, CORE_ADDR *new_pc);
1592b725ae77Skettenis static int resolve_msgsend_super_stret (CORE_ADDR pc, CORE_ADDR *new_pc);
1593b725ae77Skettenis
1594b725ae77Skettenis static struct objc_methcall methcalls[] = {
1595b725ae77Skettenis { "_objc_msgSend", resolve_msgsend, 0, 0},
1596b725ae77Skettenis { "_objc_msgSend_stret", resolve_msgsend_stret, 0, 0},
1597b725ae77Skettenis { "_objc_msgSendSuper", resolve_msgsend_super, 0, 0},
1598b725ae77Skettenis { "_objc_msgSendSuper_stret", resolve_msgsend_super_stret, 0, 0},
1599b725ae77Skettenis { "_objc_getClass", NULL, 0, 0},
1600b725ae77Skettenis { "_objc_getMetaClass", NULL, 0, 0}
1601b725ae77Skettenis };
1602b725ae77Skettenis
1603b725ae77Skettenis #define nmethcalls (sizeof (methcalls) / sizeof (methcalls[0]))
1604b725ae77Skettenis
1605b725ae77Skettenis /* The following function, "find_objc_msgsend", fills in the data
1606b725ae77Skettenis * structure "objc_msgs" by finding the addresses of each of the
1607b725ae77Skettenis * (currently four) functions that it holds (of which objc_msgSend is
1608b725ae77Skettenis * the first). This must be called each time symbols are loaded, in
1609b725ae77Skettenis * case the functions have moved for some reason.
1610b725ae77Skettenis */
1611b725ae77Skettenis
1612b725ae77Skettenis static void
find_objc_msgsend(void)1613b725ae77Skettenis find_objc_msgsend (void)
1614b725ae77Skettenis {
1615b725ae77Skettenis unsigned int i;
1616b725ae77Skettenis for (i = 0; i < nmethcalls; i++) {
1617b725ae77Skettenis
1618b725ae77Skettenis struct minimal_symbol *func;
1619b725ae77Skettenis
1620b725ae77Skettenis /* Try both with and without underscore. */
1621b725ae77Skettenis func = lookup_minimal_symbol (methcalls[i].name, NULL, NULL);
1622b725ae77Skettenis if ((func == NULL) && (methcalls[i].name[0] == '_')) {
1623b725ae77Skettenis func = lookup_minimal_symbol (methcalls[i].name + 1, NULL, NULL);
1624b725ae77Skettenis }
1625b725ae77Skettenis if (func == NULL) {
1626b725ae77Skettenis methcalls[i].begin = 0;
1627b725ae77Skettenis methcalls[i].end = 0;
1628b725ae77Skettenis continue;
1629b725ae77Skettenis }
1630b725ae77Skettenis
1631b725ae77Skettenis methcalls[i].begin = SYMBOL_VALUE_ADDRESS (func);
1632b725ae77Skettenis do {
1633b725ae77Skettenis methcalls[i].end = SYMBOL_VALUE_ADDRESS (++func);
1634b725ae77Skettenis } while (methcalls[i].begin == methcalls[i].end);
1635b725ae77Skettenis }
1636b725ae77Skettenis }
1637b725ae77Skettenis
1638b725ae77Skettenis /* find_objc_msgcall (replaces pc_off_limits)
1639b725ae77Skettenis *
1640b725ae77Skettenis * ALL that this function now does is to determine whether the input
1641b725ae77Skettenis * address ("pc") is the address of one of the Objective-C message
1642b725ae77Skettenis * dispatch functions (mainly objc_msgSend or objc_msgSendSuper), and
1643b725ae77Skettenis * if so, it returns the address of the method that will be called.
1644b725ae77Skettenis *
1645b725ae77Skettenis * The old function "pc_off_limits" used to do a lot of other things
1646b725ae77Skettenis * in addition, such as detecting shared library jump stubs and
1647b725ae77Skettenis * returning the address of the shlib function that would be called.
1648b725ae77Skettenis * That functionality has been moved into the SKIP_TRAMPOLINE_CODE and
1649b725ae77Skettenis * IN_SOLIB_TRAMPOLINE macros, which are resolved in the target-
1650b725ae77Skettenis * dependent modules.
1651b725ae77Skettenis */
1652b725ae77Skettenis
1653b725ae77Skettenis struct objc_submethod_helper_data {
1654b725ae77Skettenis int (*f) (CORE_ADDR, CORE_ADDR *);
1655b725ae77Skettenis CORE_ADDR pc;
1656b725ae77Skettenis CORE_ADDR *new_pc;
1657b725ae77Skettenis };
1658b725ae77Skettenis
1659b725ae77Skettenis static int
find_objc_msgcall_submethod_helper(void * arg)1660b725ae77Skettenis find_objc_msgcall_submethod_helper (void * arg)
1661b725ae77Skettenis {
1662b725ae77Skettenis struct objc_submethod_helper_data *s =
1663b725ae77Skettenis (struct objc_submethod_helper_data *) arg;
1664b725ae77Skettenis
1665b725ae77Skettenis if (s->f (s->pc, s->new_pc) == 0)
1666b725ae77Skettenis return 1;
1667b725ae77Skettenis else
1668b725ae77Skettenis return 0;
1669b725ae77Skettenis }
1670b725ae77Skettenis
1671b725ae77Skettenis static int
find_objc_msgcall_submethod(int (* f)(CORE_ADDR,CORE_ADDR *),CORE_ADDR pc,CORE_ADDR * new_pc)1672b725ae77Skettenis find_objc_msgcall_submethod (int (*f) (CORE_ADDR, CORE_ADDR *),
1673b725ae77Skettenis CORE_ADDR pc,
1674b725ae77Skettenis CORE_ADDR *new_pc)
1675b725ae77Skettenis {
1676b725ae77Skettenis struct objc_submethod_helper_data s;
1677b725ae77Skettenis
1678b725ae77Skettenis s.f = f;
1679b725ae77Skettenis s.pc = pc;
1680b725ae77Skettenis s.new_pc = new_pc;
1681b725ae77Skettenis
1682b725ae77Skettenis if (catch_errors (find_objc_msgcall_submethod_helper,
1683b725ae77Skettenis (void *) &s,
1684b725ae77Skettenis "Unable to determine target of Objective-C method call (ignoring):\n",
1685b725ae77Skettenis RETURN_MASK_ALL) == 0)
1686b725ae77Skettenis return 1;
1687b725ae77Skettenis else
1688b725ae77Skettenis return 0;
1689b725ae77Skettenis }
1690b725ae77Skettenis
1691b725ae77Skettenis int
find_objc_msgcall(CORE_ADDR pc,CORE_ADDR * new_pc)1692b725ae77Skettenis find_objc_msgcall (CORE_ADDR pc, CORE_ADDR *new_pc)
1693b725ae77Skettenis {
1694b725ae77Skettenis unsigned int i;
1695b725ae77Skettenis
1696b725ae77Skettenis find_objc_msgsend ();
1697b725ae77Skettenis if (new_pc != NULL)
1698b725ae77Skettenis {
1699b725ae77Skettenis *new_pc = 0;
1700b725ae77Skettenis }
1701b725ae77Skettenis
1702b725ae77Skettenis for (i = 0; i < nmethcalls; i++)
1703b725ae77Skettenis if ((pc >= methcalls[i].begin) && (pc < methcalls[i].end))
1704b725ae77Skettenis {
1705b725ae77Skettenis if (methcalls[i].stop_at != NULL)
1706b725ae77Skettenis return find_objc_msgcall_submethod (methcalls[i].stop_at,
1707b725ae77Skettenis pc, new_pc);
1708b725ae77Skettenis else
1709b725ae77Skettenis return 0;
1710b725ae77Skettenis }
1711b725ae77Skettenis
1712b725ae77Skettenis return 0;
1713b725ae77Skettenis }
1714b725ae77Skettenis
1715b725ae77Skettenis extern initialize_file_ftype _initialize_objc_language; /* -Wmissing-prototypes */
1716b725ae77Skettenis
1717b725ae77Skettenis void
_initialize_objc_language(void)1718b725ae77Skettenis _initialize_objc_language (void)
1719b725ae77Skettenis {
1720b725ae77Skettenis add_language (&objc_language_defn);
1721b725ae77Skettenis add_info ("selectors", selectors_info, /* INFO SELECTORS command. */
1722b725ae77Skettenis "All Objective-C selectors, or those matching REGEXP.");
1723b725ae77Skettenis add_info ("classes", classes_info, /* INFO CLASSES command. */
1724b725ae77Skettenis "All Objective-C classes, or those matching REGEXP.");
1725b725ae77Skettenis add_com ("print-object", class_vars, print_object_command,
1726b725ae77Skettenis "Ask an Objective-C object to print itself.");
1727b725ae77Skettenis add_com_alias ("po", "print-object", class_vars, 1);
1728b725ae77Skettenis }
1729b725ae77Skettenis
1730b725ae77Skettenis static void
read_objc_method(CORE_ADDR addr,struct objc_method * method)1731b725ae77Skettenis read_objc_method (CORE_ADDR addr, struct objc_method *method)
1732b725ae77Skettenis {
1733b725ae77Skettenis method->name = read_memory_unsigned_integer (addr + 0, 4);
1734b725ae77Skettenis method->types = read_memory_unsigned_integer (addr + 4, 4);
1735b725ae77Skettenis method->imp = read_memory_unsigned_integer (addr + 8, 4);
1736b725ae77Skettenis }
1737b725ae77Skettenis
1738b725ae77Skettenis static
read_objc_methlist_nmethods(CORE_ADDR addr)1739b725ae77Skettenis unsigned long read_objc_methlist_nmethods (CORE_ADDR addr)
1740b725ae77Skettenis {
1741b725ae77Skettenis return read_memory_unsigned_integer (addr + 4, 4);
1742b725ae77Skettenis }
1743b725ae77Skettenis
1744b725ae77Skettenis static void
read_objc_methlist_method(CORE_ADDR addr,unsigned long num,struct objc_method * method)1745b725ae77Skettenis read_objc_methlist_method (CORE_ADDR addr, unsigned long num,
1746b725ae77Skettenis struct objc_method *method)
1747b725ae77Skettenis {
1748b725ae77Skettenis gdb_assert (num < read_objc_methlist_nmethods (addr));
1749b725ae77Skettenis read_objc_method (addr + 8 + (12 * num), method);
1750b725ae77Skettenis }
1751b725ae77Skettenis
1752b725ae77Skettenis static void
read_objc_object(CORE_ADDR addr,struct objc_object * object)1753b725ae77Skettenis read_objc_object (CORE_ADDR addr, struct objc_object *object)
1754b725ae77Skettenis {
1755b725ae77Skettenis object->isa = read_memory_unsigned_integer (addr, 4);
1756b725ae77Skettenis }
1757b725ae77Skettenis
1758b725ae77Skettenis static void
read_objc_super(CORE_ADDR addr,struct objc_super * super)1759b725ae77Skettenis read_objc_super (CORE_ADDR addr, struct objc_super *super)
1760b725ae77Skettenis {
1761b725ae77Skettenis super->receiver = read_memory_unsigned_integer (addr, 4);
1762b725ae77Skettenis super->class = read_memory_unsigned_integer (addr + 4, 4);
1763b725ae77Skettenis };
1764b725ae77Skettenis
1765b725ae77Skettenis static void
read_objc_class(CORE_ADDR addr,struct objc_class * class)1766b725ae77Skettenis read_objc_class (CORE_ADDR addr, struct objc_class *class)
1767b725ae77Skettenis {
1768b725ae77Skettenis class->isa = read_memory_unsigned_integer (addr, 4);
1769b725ae77Skettenis class->super_class = read_memory_unsigned_integer (addr + 4, 4);
1770b725ae77Skettenis class->name = read_memory_unsigned_integer (addr + 8, 4);
1771b725ae77Skettenis class->version = read_memory_unsigned_integer (addr + 12, 4);
1772b725ae77Skettenis class->info = read_memory_unsigned_integer (addr + 16, 4);
1773b725ae77Skettenis class->instance_size = read_memory_unsigned_integer (addr + 18, 4);
1774b725ae77Skettenis class->ivars = read_memory_unsigned_integer (addr + 24, 4);
1775b725ae77Skettenis class->methods = read_memory_unsigned_integer (addr + 28, 4);
1776b725ae77Skettenis class->cache = read_memory_unsigned_integer (addr + 32, 4);
1777b725ae77Skettenis class->protocols = read_memory_unsigned_integer (addr + 36, 4);
1778b725ae77Skettenis }
1779b725ae77Skettenis
1780b725ae77Skettenis static CORE_ADDR
find_implementation_from_class(CORE_ADDR class,CORE_ADDR sel)1781b725ae77Skettenis find_implementation_from_class (CORE_ADDR class, CORE_ADDR sel)
1782b725ae77Skettenis {
1783b725ae77Skettenis CORE_ADDR subclass = class;
1784b725ae77Skettenis
1785b725ae77Skettenis while (subclass != 0)
1786b725ae77Skettenis {
1787b725ae77Skettenis
1788b725ae77Skettenis struct objc_class class_str;
1789b725ae77Skettenis unsigned mlistnum = 0;
1790b725ae77Skettenis
1791b725ae77Skettenis read_objc_class (subclass, &class_str);
1792b725ae77Skettenis
1793b725ae77Skettenis for (;;)
1794b725ae77Skettenis {
1795b725ae77Skettenis CORE_ADDR mlist;
1796b725ae77Skettenis unsigned long nmethods;
1797b725ae77Skettenis unsigned long i;
1798b725ae77Skettenis
1799b725ae77Skettenis mlist = read_memory_unsigned_integer (class_str.methods +
1800b725ae77Skettenis (4 * mlistnum), 4);
1801b725ae77Skettenis if (mlist == 0)
1802b725ae77Skettenis break;
1803b725ae77Skettenis
1804b725ae77Skettenis nmethods = read_objc_methlist_nmethods (mlist);
1805b725ae77Skettenis
1806b725ae77Skettenis for (i = 0; i < nmethods; i++)
1807b725ae77Skettenis {
1808b725ae77Skettenis struct objc_method meth_str;
1809b725ae77Skettenis read_objc_methlist_method (mlist, i, &meth_str);
1810b725ae77Skettenis
1811b725ae77Skettenis #if 0
1812b725ae77Skettenis fprintf (stderr,
1813b725ae77Skettenis "checking method 0x%lx against selector 0x%lx\n",
1814b725ae77Skettenis meth_str.name, sel);
1815b725ae77Skettenis #endif
1816b725ae77Skettenis
1817b725ae77Skettenis if (meth_str.name == sel)
1818b725ae77Skettenis /* FIXME: hppa arch was doing a pointer dereference
1819b725ae77Skettenis here. There needs to be a better way to do that. */
1820b725ae77Skettenis return meth_str.imp;
1821b725ae77Skettenis }
1822b725ae77Skettenis mlistnum++;
1823b725ae77Skettenis }
1824b725ae77Skettenis subclass = class_str.super_class;
1825b725ae77Skettenis }
1826b725ae77Skettenis
1827b725ae77Skettenis return 0;
1828b725ae77Skettenis }
1829b725ae77Skettenis
1830b725ae77Skettenis static CORE_ADDR
find_implementation(CORE_ADDR object,CORE_ADDR sel)1831b725ae77Skettenis find_implementation (CORE_ADDR object, CORE_ADDR sel)
1832b725ae77Skettenis {
1833b725ae77Skettenis struct objc_object ostr;
1834b725ae77Skettenis
1835b725ae77Skettenis if (object == 0)
1836b725ae77Skettenis return 0;
1837b725ae77Skettenis read_objc_object (object, &ostr);
1838b725ae77Skettenis if (ostr.isa == 0)
1839b725ae77Skettenis return 0;
1840b725ae77Skettenis
1841b725ae77Skettenis return find_implementation_from_class (ostr.isa, sel);
1842b725ae77Skettenis }
1843b725ae77Skettenis
1844b725ae77Skettenis #define OBJC_FETCH_POINTER_ARGUMENT(argi) \
1845b725ae77Skettenis FETCH_POINTER_ARGUMENT (get_current_frame (), argi, builtin_type_void_func_ptr)
1846b725ae77Skettenis
1847b725ae77Skettenis static int
resolve_msgsend(CORE_ADDR pc,CORE_ADDR * new_pc)1848b725ae77Skettenis resolve_msgsend (CORE_ADDR pc, CORE_ADDR *new_pc)
1849b725ae77Skettenis {
1850b725ae77Skettenis CORE_ADDR object;
1851b725ae77Skettenis CORE_ADDR sel;
1852b725ae77Skettenis CORE_ADDR res;
1853b725ae77Skettenis
1854b725ae77Skettenis object = OBJC_FETCH_POINTER_ARGUMENT (0);
1855b725ae77Skettenis sel = OBJC_FETCH_POINTER_ARGUMENT (1);
1856b725ae77Skettenis
1857b725ae77Skettenis res = find_implementation (object, sel);
1858b725ae77Skettenis if (new_pc != 0)
1859b725ae77Skettenis *new_pc = res;
1860b725ae77Skettenis if (res == 0)
1861b725ae77Skettenis return 1;
1862b725ae77Skettenis return 0;
1863b725ae77Skettenis }
1864b725ae77Skettenis
1865b725ae77Skettenis static int
resolve_msgsend_stret(CORE_ADDR pc,CORE_ADDR * new_pc)1866b725ae77Skettenis resolve_msgsend_stret (CORE_ADDR pc, CORE_ADDR *new_pc)
1867b725ae77Skettenis {
1868b725ae77Skettenis CORE_ADDR object;
1869b725ae77Skettenis CORE_ADDR sel;
1870b725ae77Skettenis CORE_ADDR res;
1871b725ae77Skettenis
1872b725ae77Skettenis object = OBJC_FETCH_POINTER_ARGUMENT (1);
1873b725ae77Skettenis sel = OBJC_FETCH_POINTER_ARGUMENT (2);
1874b725ae77Skettenis
1875b725ae77Skettenis res = find_implementation (object, sel);
1876b725ae77Skettenis if (new_pc != 0)
1877b725ae77Skettenis *new_pc = res;
1878b725ae77Skettenis if (res == 0)
1879b725ae77Skettenis return 1;
1880b725ae77Skettenis return 0;
1881b725ae77Skettenis }
1882b725ae77Skettenis
1883b725ae77Skettenis static int
resolve_msgsend_super(CORE_ADDR pc,CORE_ADDR * new_pc)1884b725ae77Skettenis resolve_msgsend_super (CORE_ADDR pc, CORE_ADDR *new_pc)
1885b725ae77Skettenis {
1886b725ae77Skettenis struct objc_super sstr;
1887b725ae77Skettenis
1888b725ae77Skettenis CORE_ADDR super;
1889b725ae77Skettenis CORE_ADDR sel;
1890b725ae77Skettenis CORE_ADDR res;
1891b725ae77Skettenis
1892b725ae77Skettenis super = OBJC_FETCH_POINTER_ARGUMENT (0);
1893b725ae77Skettenis sel = OBJC_FETCH_POINTER_ARGUMENT (1);
1894b725ae77Skettenis
1895b725ae77Skettenis read_objc_super (super, &sstr);
1896b725ae77Skettenis if (sstr.class == 0)
1897b725ae77Skettenis return 0;
1898b725ae77Skettenis
1899b725ae77Skettenis res = find_implementation_from_class (sstr.class, sel);
1900b725ae77Skettenis if (new_pc != 0)
1901b725ae77Skettenis *new_pc = res;
1902b725ae77Skettenis if (res == 0)
1903b725ae77Skettenis return 1;
1904b725ae77Skettenis return 0;
1905b725ae77Skettenis }
1906b725ae77Skettenis
1907b725ae77Skettenis static int
resolve_msgsend_super_stret(CORE_ADDR pc,CORE_ADDR * new_pc)1908b725ae77Skettenis resolve_msgsend_super_stret (CORE_ADDR pc, CORE_ADDR *new_pc)
1909b725ae77Skettenis {
1910b725ae77Skettenis struct objc_super sstr;
1911b725ae77Skettenis
1912b725ae77Skettenis CORE_ADDR super;
1913b725ae77Skettenis CORE_ADDR sel;
1914b725ae77Skettenis CORE_ADDR res;
1915b725ae77Skettenis
1916b725ae77Skettenis super = OBJC_FETCH_POINTER_ARGUMENT (1);
1917b725ae77Skettenis sel = OBJC_FETCH_POINTER_ARGUMENT (2);
1918b725ae77Skettenis
1919b725ae77Skettenis read_objc_super (super, &sstr);
1920b725ae77Skettenis if (sstr.class == 0)
1921b725ae77Skettenis return 0;
1922b725ae77Skettenis
1923b725ae77Skettenis res = find_implementation_from_class (sstr.class, sel);
1924b725ae77Skettenis if (new_pc != 0)
1925b725ae77Skettenis *new_pc = res;
1926b725ae77Skettenis if (res == 0)
1927b725ae77Skettenis return 1;
1928b725ae77Skettenis return 0;
1929b725ae77Skettenis }
1930