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