OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gdb-6.8/] [gdb/] [objc-lang.c] - Blame information for rev 309

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.