GDB (API)
/home/stan/gdb/src/gdb/objc-lang.c
Go to the documentation of this file.
00001 /* Objective-C language support routines for GDB, the GNU debugger.
00002 
00003    Copyright (C) 2002-2013 Free Software Foundation, Inc.
00004 
00005    Contributed by Apple Computer, Inc.
00006    Written by Michael Snyder.
00007 
00008    This file is part of GDB.
00009 
00010    This program is free software; you can redistribute it and/or modify
00011    it under the terms of the GNU General Public License as published by
00012    the Free Software Foundation; either version 3 of the License, or
00013    (at your option) any later version.
00014 
00015    This program is distributed in the hope that it will be useful,
00016    but WITHOUT ANY WARRANTY; without even the implied warranty of
00017    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018    GNU General Public License for more details.
00019 
00020    You should have received a copy of the GNU General Public License
00021    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
00022 
00023 #include "defs.h"
00024 #include "symtab.h"
00025 #include "gdbtypes.h"
00026 #include "expression.h"
00027 #include "parser-defs.h"
00028 #include "language.h"
00029 #include "c-lang.h"
00030 #include "objc-lang.h"
00031 #include "exceptions.h"
00032 #include "complaints.h"
00033 #include "value.h"
00034 #include "symfile.h"
00035 #include "objfiles.h"
00036 #include "gdb_string.h"         /* for strchr */
00037 #include "target.h"             /* for target_has_execution */
00038 #include "gdbcore.h"
00039 #include "gdbcmd.h"
00040 #include "frame.h"
00041 #include "gdb_regex.h"
00042 #include "regcache.h"
00043 #include "block.h"
00044 #include "infcall.h"
00045 #include "valprint.h"
00046 #include "gdb_assert.h"
00047 #include "cli/cli-utils.h"
00048 
00049 #include <ctype.h>
00050 
00051 struct objc_object {
00052   CORE_ADDR isa;
00053 };
00054 
00055 struct objc_class {
00056   CORE_ADDR isa; 
00057   CORE_ADDR super_class; 
00058   CORE_ADDR name;               
00059   long version;
00060   long info;
00061   long instance_size;
00062   CORE_ADDR ivars;
00063   CORE_ADDR methods;
00064   CORE_ADDR cache;
00065   CORE_ADDR protocols;
00066 };
00067 
00068 struct objc_super {
00069   CORE_ADDR receiver;
00070   CORE_ADDR class;
00071 };
00072 
00073 struct objc_method {
00074   CORE_ADDR name;
00075   CORE_ADDR types;
00076   CORE_ADDR imp;
00077 };
00078 
00079 static const struct objfile_data *objc_objfile_data;
00080 
00081 /* Lookup a structure type named "struct NAME", visible in lexical
00082    block BLOCK.  If NOERR is nonzero, return zero if NAME is not
00083    suitably defined.  */
00084 
00085 struct symbol *
00086 lookup_struct_typedef (char *name, const struct block *block, int noerr)
00087 {
00088   struct symbol *sym;
00089 
00090   sym = lookup_symbol (name, block, STRUCT_DOMAIN, 0);
00091 
00092   if (sym == NULL)
00093     {
00094       if (noerr)
00095         return 0;
00096       else 
00097         error (_("No struct type named %s."), name);
00098     }
00099   if (TYPE_CODE (SYMBOL_TYPE (sym)) != TYPE_CODE_STRUCT)
00100     {
00101       if (noerr)
00102         return 0;
00103       else
00104         error (_("This context has class, union or enum %s, not a struct."), 
00105                name);
00106     }
00107   return sym;
00108 }
00109 
00110 CORE_ADDR 
00111 lookup_objc_class (struct gdbarch *gdbarch, char *classname)
00112 {
00113   struct type *char_type = builtin_type (gdbarch)->builtin_char;
00114   struct value * function, *classval;
00115 
00116   if (! target_has_execution)
00117     {
00118       /* Can't call into inferior to lookup class.  */
00119       return 0;
00120     }
00121 
00122   if (lookup_minimal_symbol("objc_lookUpClass", 0, 0))
00123     function = find_function_in_inferior("objc_lookUpClass", NULL);
00124   else if (lookup_minimal_symbol ("objc_lookup_class", 0, 0))
00125     function = find_function_in_inferior("objc_lookup_class", NULL);
00126   else
00127     {
00128       complaint (&symfile_complaints,
00129                  _("no way to lookup Objective-C classes"));
00130       return 0;
00131     }
00132 
00133   classval = value_string (classname, strlen (classname) + 1, char_type);
00134   classval = value_coerce_array (classval);
00135   return (CORE_ADDR) value_as_long (call_function_by_hand (function, 
00136                                                            1, &classval));
00137 }
00138 
00139 CORE_ADDR
00140 lookup_child_selector (struct gdbarch *gdbarch, char *selname)
00141 {
00142   struct type *char_type = builtin_type (gdbarch)->builtin_char;
00143   struct value * function, *selstring;
00144 
00145   if (! target_has_execution)
00146     {
00147       /* Can't call into inferior to lookup selector.  */
00148       return 0;
00149     }
00150 
00151   if (lookup_minimal_symbol("sel_getUid", 0, 0))
00152     function = find_function_in_inferior("sel_getUid", NULL);
00153   else if (lookup_minimal_symbol ("sel_get_any_uid", 0, 0))
00154     function = find_function_in_inferior("sel_get_any_uid", NULL);
00155   else
00156     {
00157       complaint (&symfile_complaints,
00158                  _("no way to lookup Objective-C selectors"));
00159       return 0;
00160     }
00161 
00162   selstring = value_coerce_array (value_string (selname, 
00163                                                 strlen (selname) + 1,
00164                                                 char_type));
00165   return value_as_long (call_function_by_hand (function, 1, &selstring));
00166 }
00167 
00168 struct value * 
00169 value_nsstring (struct gdbarch *gdbarch, char *ptr, int len)
00170 {
00171   struct type *char_type = builtin_type (gdbarch)->builtin_char;
00172   struct value *stringValue[3];
00173   struct value *function, *nsstringValue;
00174   struct symbol *sym;
00175   struct type *type;
00176 
00177   if (!target_has_execution)
00178     return 0;           /* Can't call into inferior to create NSString.  */
00179 
00180   stringValue[2] = value_string(ptr, len, char_type);
00181   stringValue[2] = value_coerce_array(stringValue[2]);
00182   /* _NSNewStringFromCString replaces "istr" after Lantern2A.  */
00183   if (lookup_minimal_symbol("_NSNewStringFromCString", 0, 0))
00184     {
00185       function = find_function_in_inferior("_NSNewStringFromCString", NULL);
00186       nsstringValue = call_function_by_hand(function, 1, &stringValue[2]);
00187     }
00188   else if (lookup_minimal_symbol("istr", 0, 0))
00189     {
00190       function = find_function_in_inferior("istr", NULL);
00191       nsstringValue = call_function_by_hand(function, 1, &stringValue[2]);
00192     }
00193   else if (lookup_minimal_symbol("+[NSString stringWithCString:]", 0, 0))
00194     {
00195       function
00196         = find_function_in_inferior("+[NSString stringWithCString:]", NULL);
00197       type = builtin_type (gdbarch)->builtin_long;
00198 
00199       stringValue[0] = value_from_longest 
00200         (type, lookup_objc_class (gdbarch, "NSString"));
00201       stringValue[1] = value_from_longest 
00202         (type, lookup_child_selector (gdbarch, "stringWithCString:"));
00203       nsstringValue = call_function_by_hand(function, 3, &stringValue[0]);
00204     }
00205   else
00206     error (_("NSString: internal error -- no way to create new NSString"));
00207 
00208   sym = lookup_struct_typedef("NSString", 0, 1);
00209   if (sym == NULL)
00210     sym = lookup_struct_typedef("NXString", 0, 1);
00211   if (sym == NULL)
00212     type = builtin_type (gdbarch)->builtin_data_ptr;
00213   else
00214     type = lookup_pointer_type(SYMBOL_TYPE (sym));
00215 
00216   deprecated_set_value_type (nsstringValue, type);
00217   return nsstringValue;
00218 }
00219 
00220 /* Objective-C name demangling.  */
00221 
00222 char *
00223 objc_demangle (const char *mangled, int options)
00224 {
00225   char *demangled, *cp;
00226 
00227   if (mangled[0] == '_' &&
00228      (mangled[1] == 'i' || mangled[1] == 'c') &&
00229       mangled[2] == '_')
00230     {
00231       cp = demangled = xmalloc(strlen(mangled) + 2);
00232 
00233       if (mangled[1] == 'i')
00234         *cp++ = '-';            /* for instance method */
00235       else
00236         *cp++ = '+';            /* for class    method */
00237 
00238       *cp++ = '[';              /* opening left brace  */
00239       strcpy(cp, mangled+3);    /* Tack on the rest of the mangled name.  */
00240 
00241       while (*cp && *cp == '_')
00242         cp++;                   /* Skip any initial underbars in class
00243                                    name.  */
00244 
00245       cp = strchr(cp, '_');
00246       if (!cp)                  /* Find first non-initial underbar.  */
00247         {
00248           xfree(demangled);     /* not mangled name */
00249           return NULL;
00250         }
00251       if (cp[1] == '_')         /* Easy case: no category name.    */
00252         {
00253           *cp++ = ' ';          /* Replace two '_' with one ' '.   */
00254           strcpy(cp, mangled + (cp - demangled) + 2);
00255         }
00256       else
00257         {
00258           *cp++ = '(';          /* Less easy case: category name.  */
00259           cp = strchr(cp, '_');
00260           if (!cp)
00261             {
00262               xfree(demangled); /* not mangled name */
00263               return NULL;
00264             }
00265           *cp++ = ')';
00266           *cp++ = ' ';          /* Overwriting 1st char of method name...  */
00267           strcpy(cp, mangled + (cp - demangled));       /* Get it back.  */
00268         }
00269 
00270       while (*cp && *cp == '_')
00271         cp++;                   /* Skip any initial underbars in
00272                                    method name.  */
00273 
00274       for (; *cp; cp++)
00275         if (*cp == '_')
00276           *cp = ':';            /* Replace remaining '_' with ':'.  */
00277 
00278       *cp++ = ']';              /* closing right brace */
00279       *cp++ = 0;                /* string terminator */
00280       return demangled;
00281     }
00282   else
00283     return NULL;        /* Not an objc mangled name.  */
00284 }
00285 
00286 /* Determine if we are currently in the Objective-C dispatch function.
00287    If so, get the address of the method function that the dispatcher
00288    would call and use that as the function to step into instead.  Also
00289    skip over the trampoline for the function (if any).  This is better
00290    for the user since they are only interested in stepping into the
00291    method function anyway.  */
00292 static CORE_ADDR 
00293 objc_skip_trampoline (struct frame_info *frame, CORE_ADDR stop_pc)
00294 {
00295   struct gdbarch *gdbarch = get_frame_arch (frame);
00296   CORE_ADDR real_stop_pc;
00297   CORE_ADDR method_stop_pc;
00298   
00299   real_stop_pc = gdbarch_skip_trampoline_code (gdbarch, frame, stop_pc);
00300 
00301   if (real_stop_pc != 0)
00302     find_objc_msgcall (real_stop_pc, &method_stop_pc);
00303   else
00304     find_objc_msgcall (stop_pc, &method_stop_pc);
00305 
00306   if (method_stop_pc)
00307     {
00308       real_stop_pc = gdbarch_skip_trampoline_code
00309                        (gdbarch, frame, method_stop_pc);
00310       if (real_stop_pc == 0)
00311         real_stop_pc = method_stop_pc;
00312     }
00313 
00314   return real_stop_pc;
00315 }
00316 
00317 
00318 /* Table mapping opcodes into strings for printing operators
00319    and precedences of the operators.  */
00320 
00321 static const struct op_print objc_op_print_tab[] =
00322   {
00323     {",",  BINOP_COMMA, PREC_COMMA, 0},
00324     {"=",  BINOP_ASSIGN, PREC_ASSIGN, 1},
00325     {"||", BINOP_LOGICAL_OR, PREC_LOGICAL_OR, 0},
00326     {"&&", BINOP_LOGICAL_AND, PREC_LOGICAL_AND, 0},
00327     {"|",  BINOP_BITWISE_IOR, PREC_BITWISE_IOR, 0},
00328     {"^",  BINOP_BITWISE_XOR, PREC_BITWISE_XOR, 0},
00329     {"&",  BINOP_BITWISE_AND, PREC_BITWISE_AND, 0},
00330     {"==", BINOP_EQUAL, PREC_EQUAL, 0},
00331     {"!=", BINOP_NOTEQUAL, PREC_EQUAL, 0},
00332     {"<=", BINOP_LEQ, PREC_ORDER, 0},
00333     {">=", BINOP_GEQ, PREC_ORDER, 0},
00334     {">",  BINOP_GTR, PREC_ORDER, 0},
00335     {"<",  BINOP_LESS, PREC_ORDER, 0},
00336     {">>", BINOP_RSH, PREC_SHIFT, 0},
00337     {"<<", BINOP_LSH, PREC_SHIFT, 0},
00338     {"+",  BINOP_ADD, PREC_ADD, 0},
00339     {"-",  BINOP_SUB, PREC_ADD, 0},
00340     {"*",  BINOP_MUL, PREC_MUL, 0},
00341     {"/",  BINOP_DIV, PREC_MUL, 0},
00342     {"%",  BINOP_REM, PREC_MUL, 0},
00343     {"@",  BINOP_REPEAT, PREC_REPEAT, 0},
00344     {"-",  UNOP_NEG, PREC_PREFIX, 0},
00345     {"!",  UNOP_LOGICAL_NOT, PREC_PREFIX, 0},
00346     {"~",  UNOP_COMPLEMENT, PREC_PREFIX, 0},
00347     {"*",  UNOP_IND, PREC_PREFIX, 0},
00348     {"&",  UNOP_ADDR, PREC_PREFIX, 0},
00349     {"sizeof ", UNOP_SIZEOF, PREC_PREFIX, 0},
00350     {"++", UNOP_PREINCREMENT, PREC_PREFIX, 0},
00351     {"--", UNOP_PREDECREMENT, PREC_PREFIX, 0},
00352     {NULL, OP_NULL, PREC_NULL, 0}
00353 };
00354 
00355 const struct language_defn objc_language_defn = {
00356   "objective-c",                /* Language name */
00357   language_objc,
00358   range_check_off,
00359   case_sensitive_on,
00360   array_row_major,
00361   macro_expansion_c,
00362   &exp_descriptor_standard,
00363   c_parse,
00364   c_error,
00365   null_post_parser,
00366   c_printchar,                 /* Print a character constant */
00367   c_printstr,                  /* Function to print string constant */
00368   c_emit_char,
00369   c_print_type,                 /* Print a type using appropriate syntax */
00370   c_print_typedef,              /* Print a typedef using appropriate syntax */
00371   c_val_print,                  /* Print a value using appropriate syntax */
00372   c_value_print,                /* Print a top-level value */
00373   default_read_var_value,       /* la_read_var_value */
00374   objc_skip_trampoline,         /* Language specific skip_trampoline */
00375   "self",                       /* name_of_this */
00376   basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
00377   basic_lookup_transparent_type,/* lookup_transparent_type */
00378   objc_demangle,                /* Language specific symbol demangler */
00379   NULL,                         /* Language specific
00380                                    class_name_from_physname */
00381   objc_op_print_tab,            /* Expression operators for printing */
00382   1,                            /* C-style arrays */
00383   0,                            /* String lower bound */
00384   default_word_break_characters,
00385   default_make_symbol_completion_list,
00386   c_language_arch_info,
00387   default_print_array_index,
00388   default_pass_by_reference,
00389   default_get_string,
00390   NULL,                         /* la_get_symbol_name_cmp */
00391   iterate_over_symbols,
00392   LANG_MAGIC
00393 };
00394 
00395 /*
00396  * ObjC:
00397  * Following functions help construct Objective-C message calls.
00398  */
00399 
00400 struct selname          /* For parsing Objective-C.  */
00401   {
00402     struct selname *next;
00403     char *msglist_sel;
00404     int msglist_len;
00405   };
00406 
00407 static int msglist_len;
00408 static struct selname *selname_chain;
00409 static char *msglist_sel;
00410 
00411 void
00412 start_msglist(void)
00413 {
00414   struct selname *new = 
00415     (struct selname *) xmalloc (sizeof (struct selname));
00416 
00417   new->next = selname_chain;
00418   new->msglist_len = msglist_len;
00419   new->msglist_sel = msglist_sel;
00420   msglist_len = 0;
00421   msglist_sel = (char *)xmalloc(1);
00422   *msglist_sel = 0;
00423   selname_chain = new;
00424 }
00425 
00426 void
00427 add_msglist(struct stoken *str, int addcolon)
00428 {
00429   char *s;
00430   const char *p;
00431   int len, plen;
00432 
00433   if (str == 0)                 /* Unnamed arg, or...  */
00434     {
00435       if (addcolon == 0)        /* variable number of args.  */
00436         {
00437           msglist_len++;
00438           return;
00439         }
00440       p = "";
00441       plen = 0;
00442     }
00443   else
00444     {
00445       p = str->ptr;
00446       plen = str->length;
00447     }
00448   len = plen + strlen(msglist_sel) + 2;
00449   s = (char *)xmalloc(len);
00450   strcpy(s, msglist_sel);
00451   strncat(s, p, plen);
00452   xfree(msglist_sel);
00453   msglist_sel = s;
00454   if (addcolon)
00455     {
00456       s[len-2] = ':';
00457       s[len-1] = 0;
00458       msglist_len++;
00459     }
00460   else
00461     s[len-2] = '\0';
00462 }
00463 
00464 int
00465 end_msglist(void)
00466 {
00467   int val = msglist_len;
00468   struct selname *sel = selname_chain;
00469   char *p = msglist_sel;
00470   CORE_ADDR selid;
00471 
00472   selname_chain = sel->next;
00473   msglist_len = sel->msglist_len;
00474   msglist_sel = sel->msglist_sel;
00475   selid = lookup_child_selector (parse_gdbarch, p);
00476   if (!selid)
00477     error (_("Can't find selector \"%s\""), p);
00478   write_exp_elt_longcst (selid);
00479   xfree(p);
00480   write_exp_elt_longcst (val);  /* Number of args */
00481   xfree(sel);
00482 
00483   return val;
00484 }
00485 
00486 /*
00487  * Function: specialcmp (const char *a, const char *b)
00488  *
00489  * Special strcmp: treats ']' and ' ' as end-of-string.
00490  * Used for qsorting lists of objc methods (either by class or selector).
00491  */
00492 
00493 static int
00494 specialcmp (const char *a, const char *b)
00495 {
00496   while (*a && *a != ' ' && *a != ']' && *b && *b != ' ' && *b != ']')
00497     {
00498       if (*a != *b)
00499         return *a - *b;
00500       a++, b++;
00501     }
00502   if (*a && *a != ' ' && *a != ']')
00503     return  1;          /* a is longer therefore greater.  */
00504   if (*b && *b != ' ' && *b != ']')
00505     return -1;          /* a is shorter therefore lesser.  */
00506   return    0;          /* a and b are identical.  */
00507 }
00508 
00509 /*
00510  * Function: compare_selectors (const void *, const void *)
00511  *
00512  * Comparison function for use with qsort.  Arguments are symbols or
00513  * msymbols Compares selector part of objc method name alphabetically.
00514  */
00515 
00516 static int
00517 compare_selectors (const void *a, const void *b)
00518 {
00519   const char *aname, *bname;
00520 
00521   aname = SYMBOL_PRINT_NAME (*(struct symbol **) a);
00522   bname = SYMBOL_PRINT_NAME (*(struct symbol **) b);
00523   if (aname == NULL || bname == NULL)
00524     error (_("internal: compare_selectors(1)"));
00525 
00526   aname = strchr(aname, ' ');
00527   bname = strchr(bname, ' ');
00528   if (aname == NULL || bname == NULL)
00529     error (_("internal: compare_selectors(2)"));
00530 
00531   return specialcmp (aname+1, bname+1);
00532 }
00533 
00534 /*
00535  * Function: selectors_info (regexp, from_tty)
00536  *
00537  * Implements the "Info selectors" command.  Takes an optional regexp
00538  * arg.  Lists all objective c selectors that match the regexp.  Works
00539  * by grepping thru all symbols for objective c methods.  Output list
00540  * is sorted and uniqued. 
00541  */
00542 
00543 static void
00544 selectors_info (char *regexp, int from_tty)
00545 {
00546   struct objfile        *objfile;
00547   struct minimal_symbol *msymbol;
00548   const char            *name;
00549   char                  *val;
00550   int                    matches = 0;
00551   int                    maxlen  = 0;
00552   int                    ix;
00553   char                   myregexp[2048];
00554   char                   asel[256];
00555   struct symbol        **sym_arr;
00556   int                    plusminus = 0;
00557 
00558   if (regexp == NULL)
00559     strcpy(myregexp, ".*]");    /* Null input, match all objc methods.  */
00560   else
00561     {
00562       if (*regexp == '+' || *regexp == '-')
00563         { /* User wants only class methods or only instance methods.  */
00564           plusminus = *regexp++;
00565           while (*regexp == ' ' || *regexp == '\t')
00566             regexp++;
00567         }
00568       if (*regexp == '\0')
00569         strcpy(myregexp, ".*]");
00570       else
00571         {
00572           /* Allow a few extra bytes because of the strcat below.  */
00573           if (sizeof (myregexp) < strlen (regexp) + 4)
00574             error (_("Regexp is too long: %s"), regexp);
00575           strcpy(myregexp, regexp);
00576           if (myregexp[strlen(myregexp) - 1] == '$') /* end of selector */
00577             myregexp[strlen(myregexp) - 1] = ']';    /* end of method name */
00578           else
00579             strcat(myregexp, ".*]");
00580         }
00581     }
00582 
00583   if (regexp != NULL)
00584     {
00585       val = re_comp (myregexp);
00586       if (val != 0)
00587         error (_("Invalid regexp (%s): %s"), val, regexp);
00588     }
00589 
00590   /* First time thru is JUST to get max length and count.  */
00591   ALL_MSYMBOLS (objfile, msymbol)
00592     {
00593       QUIT;
00594       name = SYMBOL_NATURAL_NAME (msymbol);
00595       if (name
00596           && (name[0] == '-' || name[0] == '+')
00597           && name[1] == '[')            /* Got a method name.  */
00598         {
00599           /* Filter for class/instance methods.  */
00600           if (plusminus && name[0] != plusminus)
00601             continue;
00602           /* Find selector part.  */
00603           name = (char *) strchr (name+2, ' ');
00604           if (name == NULL)
00605             {
00606               complaint (&symfile_complaints, 
00607                          _("Bad method name '%s'"), 
00608                          SYMBOL_NATURAL_NAME (msymbol));
00609               continue;
00610             }
00611           if (regexp == NULL || re_exec(++name) != 0)
00612             { 
00613               const char *mystart = name;
00614               const char *myend   = strchr (mystart, ']');
00615               
00616               if (myend && (myend - mystart > maxlen))
00617                 maxlen = myend - mystart;       /* Get longest selector.  */
00618               matches++;
00619             }
00620         }
00621     }
00622   if (matches)
00623     {
00624       printf_filtered (_("Selectors matching \"%s\":\n\n"), 
00625                        regexp ? regexp : "*");
00626 
00627       sym_arr = alloca (matches * sizeof (struct symbol *));
00628       matches = 0;
00629       ALL_MSYMBOLS (objfile, msymbol)
00630         {
00631           QUIT;
00632           name = SYMBOL_NATURAL_NAME (msymbol);
00633           if (name &&
00634              (name[0] == '-' || name[0] == '+') &&
00635               name[1] == '[')           /* Got a method name.  */
00636             {
00637               /* Filter for class/instance methods.  */
00638               if (plusminus && name[0] != plusminus)
00639                 continue;
00640               /* Find selector part.  */
00641               name = (char *) strchr(name+2, ' ');
00642               if (regexp == NULL || re_exec(++name) != 0)
00643                 sym_arr[matches++] = (struct symbol *) msymbol;
00644             }
00645         }
00646 
00647       qsort (sym_arr, matches, sizeof (struct minimal_symbol *), 
00648              compare_selectors);
00649       /* Prevent compare on first iteration.  */
00650       asel[0] = 0;
00651       for (ix = 0; ix < matches; ix++)  /* Now do the output.  */
00652         {
00653           char *p = asel;
00654 
00655           QUIT;
00656           name = SYMBOL_NATURAL_NAME (sym_arr[ix]);
00657           name = strchr (name, ' ') + 1;
00658           if (p[0] && specialcmp(name, p) == 0)
00659             continue;           /* Seen this one already (not unique).  */
00660 
00661           /* Copy selector part.  */
00662           while (*name && *name != ']')
00663             *p++ = *name++;
00664           *p++ = '\0';
00665           /* Print in columns.  */
00666           puts_filtered_tabular(asel, maxlen + 1, 0);
00667         }
00668       begin_line();
00669     }
00670   else
00671     printf_filtered (_("No selectors matching \"%s\"\n"),
00672                      regexp ? regexp : "*");
00673 }
00674 
00675 /*
00676  * Function: compare_classes (const void *, const void *)
00677  *
00678  * Comparison function for use with qsort.  Arguments are symbols or
00679  * msymbols Compares class part of objc method name alphabetically. 
00680  */
00681 
00682 static int
00683 compare_classes (const void *a, const void *b)
00684 {
00685   const char *aname, *bname;
00686 
00687   aname = SYMBOL_PRINT_NAME (*(struct symbol **) a);
00688   bname = SYMBOL_PRINT_NAME (*(struct symbol **) b);
00689   if (aname == NULL || bname == NULL)
00690     error (_("internal: compare_classes(1)"));
00691 
00692   return specialcmp (aname+1, bname+1);
00693 }
00694 
00695 /*
00696  * Function: classes_info(regexp, from_tty)
00697  *
00698  * Implements the "info classes" command for objective c classes.
00699  * Lists all objective c classes that match the optional regexp.
00700  * Works by grepping thru the list of objective c methods.  List will
00701  * be sorted and uniqued (since one class may have many methods).
00702  * BUGS: will not list a class that has no methods. 
00703  */
00704 
00705 static void
00706 classes_info (char *regexp, int from_tty)
00707 {
00708   struct objfile        *objfile;
00709   struct minimal_symbol *msymbol;
00710   const char            *name;
00711   char                  *val;
00712   int                    matches = 0;
00713   int                    maxlen  = 0;
00714   int                    ix;
00715   char                   myregexp[2048];
00716   char                   aclass[256];
00717   struct symbol        **sym_arr;
00718 
00719   if (regexp == NULL)
00720     strcpy(myregexp, ".* ");    /* Null input: match all objc classes.  */
00721   else
00722     {
00723       /* Allow a few extra bytes because of the strcat below.  */
00724       if (sizeof (myregexp) < strlen (regexp) + 4)
00725         error (_("Regexp is too long: %s"), regexp);
00726       strcpy(myregexp, regexp);
00727       if (myregexp[strlen(myregexp) - 1] == '$')
00728         /* In the method name, the end of the class name is marked by ' '.  */
00729         myregexp[strlen(myregexp) - 1] = ' ';
00730       else
00731         strcat(myregexp, ".* ");
00732     }
00733 
00734   if (regexp != NULL)
00735     {
00736       val = re_comp (myregexp);
00737       if (val != 0)
00738         error (_("Invalid regexp (%s): %s"), val, regexp);
00739     }
00740 
00741   /* First time thru is JUST to get max length and count.  */
00742   ALL_MSYMBOLS (objfile, msymbol)
00743     {
00744       QUIT;
00745       name = SYMBOL_NATURAL_NAME (msymbol);
00746       if (name &&
00747          (name[0] == '-' || name[0] == '+') &&
00748           name[1] == '[')                       /* Got a method name.  */
00749         if (regexp == NULL || re_exec(name+2) != 0)
00750           { 
00751             /* Compute length of classname part.  */
00752             const char *mystart = name + 2;
00753             const char *myend   = strchr (mystart, ' ');
00754             
00755             if (myend && (myend - mystart > maxlen))
00756               maxlen = myend - mystart;
00757             matches++;
00758           }
00759     }
00760   if (matches)
00761     {
00762       printf_filtered (_("Classes matching \"%s\":\n\n"), 
00763                        regexp ? regexp : "*");
00764       sym_arr = alloca (matches * sizeof (struct symbol *));
00765       matches = 0;
00766       ALL_MSYMBOLS (objfile, msymbol)
00767         {
00768           QUIT;
00769           name = SYMBOL_NATURAL_NAME (msymbol);
00770           if (name &&
00771              (name[0] == '-' || name[0] == '+') &&
00772               name[1] == '[')                   /* Got a method name.  */
00773             if (regexp == NULL || re_exec(name+2) != 0)
00774                 sym_arr[matches++] = (struct symbol *) msymbol;
00775         }
00776 
00777       qsort (sym_arr, matches, sizeof (struct minimal_symbol *), 
00778              compare_classes);
00779       /* Prevent compare on first iteration.  */
00780       aclass[0] = 0;
00781       for (ix = 0; ix < matches; ix++)  /* Now do the output.  */
00782         {
00783           char *p = aclass;
00784 
00785           QUIT;
00786           name = SYMBOL_NATURAL_NAME (sym_arr[ix]);
00787           name += 2;
00788           if (p[0] && specialcmp(name, p) == 0)
00789             continue;   /* Seen this one already (not unique).  */
00790 
00791           /* Copy class part of method name.  */
00792           while (*name && *name != ' ')
00793             *p++ = *name++;
00794           *p++ = '\0';
00795           /* Print in columns.  */
00796           puts_filtered_tabular(aclass, maxlen + 1, 0);
00797         }
00798       begin_line();
00799     }
00800   else
00801     printf_filtered (_("No classes matching \"%s\"\n"), regexp ? regexp : "*");
00802 }
00803 
00804 static char * 
00805 parse_selector (char *method, char **selector)
00806 {
00807   char *s1 = NULL;
00808   char *s2 = NULL;
00809   int found_quote = 0;
00810 
00811   char *nselector = NULL;
00812 
00813   gdb_assert (selector != NULL);
00814 
00815   s1 = method;
00816 
00817   s1 = skip_spaces (s1);
00818   if (*s1 == '\'') 
00819     {
00820       found_quote = 1;
00821       s1++;
00822     }
00823   s1 = skip_spaces (s1);
00824    
00825   nselector = s1;
00826   s2 = s1;
00827 
00828   for (;;)
00829     {
00830       if (isalnum (*s2) || (*s2 == '_') || (*s2 == ':'))
00831         *s1++ = *s2;
00832       else if (isspace (*s2))
00833         ;
00834       else if ((*s2 == '\0') || (*s2 == '\''))
00835         break;
00836       else
00837         return NULL;
00838       s2++;
00839     }
00840   *s1++ = '\0';
00841 
00842   s2 = skip_spaces (s2);
00843   if (found_quote)
00844     {
00845       if (*s2 == '\'') 
00846         s2++;
00847       s2 = skip_spaces (s2);
00848     }
00849 
00850   if (selector != NULL)
00851     *selector = nselector;
00852 
00853   return s2;
00854 }
00855 
00856 static char * 
00857 parse_method (char *method, char *type, char **class, 
00858               char **category, char **selector)
00859 {
00860   char *s1 = NULL;
00861   char *s2 = NULL;
00862   int found_quote = 0;
00863 
00864   char ntype = '\0';
00865   char *nclass = NULL;
00866   char *ncategory = NULL;
00867   char *nselector = NULL;
00868 
00869   gdb_assert (type != NULL);
00870   gdb_assert (class != NULL);
00871   gdb_assert (category != NULL);
00872   gdb_assert (selector != NULL);
00873   
00874   s1 = method;
00875 
00876   s1 = skip_spaces (s1);
00877   if (*s1 == '\'') 
00878     {
00879       found_quote = 1;
00880       s1++;
00881     }
00882   s1 = skip_spaces (s1);
00883   
00884   if ((s1[0] == '+') || (s1[0] == '-'))
00885     ntype = *s1++;
00886 
00887   s1 = skip_spaces (s1);
00888 
00889   if (*s1 != '[')
00890     return NULL;
00891   s1++;
00892 
00893   nclass = s1;
00894   while (isalnum (*s1) || (*s1 == '_'))
00895     s1++;
00896   
00897   s2 = s1;
00898   s2 = skip_spaces (s2);
00899   
00900   if (*s2 == '(')
00901     {
00902       s2++;
00903       s2 = skip_spaces (s2);
00904       ncategory = s2;
00905       while (isalnum (*s2) || (*s2 == '_'))
00906         s2++;
00907       *s2++ = '\0';
00908     }
00909 
00910   /* Truncate the class name now that we're not using the open paren.  */
00911   *s1++ = '\0';
00912 
00913   nselector = s2;
00914   s1 = s2;
00915 
00916   for (;;)
00917     {
00918       if (isalnum (*s2) || (*s2 == '_') || (*s2 == ':'))
00919         *s1++ = *s2;
00920       else if (isspace (*s2))
00921         ;
00922       else if (*s2 == ']')
00923         break;
00924       else
00925         return NULL;
00926       s2++;
00927     }
00928   *s1++ = '\0';
00929   s2++;
00930 
00931   s2 = skip_spaces (s2);
00932   if (found_quote)
00933     {
00934       if (*s2 != '\'') 
00935         return NULL;
00936       s2++;
00937       s2 = skip_spaces (s2);
00938     }
00939 
00940   if (type != NULL)
00941     *type = ntype;
00942   if (class != NULL)
00943     *class = nclass;
00944   if (category != NULL)
00945     *category = ncategory;
00946   if (selector != NULL)
00947     *selector = nselector;
00948 
00949   return s2;
00950 }
00951 
00952 static void
00953 find_methods (char type, const char *class, const char *category, 
00954               const char *selector,
00955               VEC (const_char_ptr) **symbol_names)
00956 {
00957   struct objfile *objfile = NULL;
00958 
00959   const char *symname = NULL;
00960 
00961   char ntype = '\0';
00962   char *nclass = NULL;
00963   char *ncategory = NULL;
00964   char *nselector = NULL;
00965 
00966   static char *tmp = NULL;
00967   static unsigned int tmplen = 0;
00968 
00969   gdb_assert (symbol_names != NULL);
00970 
00971   ALL_OBJFILES (objfile)
00972     {
00973       unsigned int *objc_csym;
00974       struct minimal_symbol *msymbol = NULL;
00975 
00976       /* The objfile_csym variable counts the number of ObjC methods
00977          that this objfile defines.  We save that count as a private
00978          objfile data.  If we have already determined that this objfile
00979          provides no ObjC methods, we can skip it entirely.  */
00980 
00981       unsigned int objfile_csym = 0;
00982 
00983       objc_csym = objfile_data (objfile, objc_objfile_data);
00984       if (objc_csym != NULL && *objc_csym == 0)
00985         /* There are no ObjC symbols in this objfile.  Skip it entirely.  */
00986         continue;
00987 
00988       ALL_OBJFILE_MSYMBOLS (objfile, msymbol)
00989         {
00990           QUIT;
00991 
00992           /* Check the symbol name first as this can be done entirely without
00993              sending any query to the target.  */
00994           symname = SYMBOL_NATURAL_NAME (msymbol);
00995           if (symname == NULL)
00996             continue;
00997 
00998           if ((symname[0] != '-' && symname[0] != '+') || (symname[1] != '['))
00999             /* Not a method name.  */
01000             continue;
01001 
01002           objfile_csym++;
01003 
01004           /* Now that thinks are a bit sane, clean up the symname.  */
01005           while ((strlen (symname) + 1) >= tmplen)
01006             {
01007               tmplen = (tmplen == 0) ? 1024 : tmplen * 2;
01008               tmp = xrealloc (tmp, tmplen);
01009             }
01010           strcpy (tmp, symname);
01011 
01012           if (parse_method (tmp, &ntype, &nclass,
01013                             &ncategory, &nselector) == NULL)
01014             continue;
01015 
01016           if ((type != '\0') && (ntype != type))
01017             continue;
01018 
01019           if ((class != NULL) 
01020               && ((nclass == NULL) || (strcmp (class, nclass) != 0)))
01021             continue;
01022 
01023           if ((category != NULL) && 
01024               ((ncategory == NULL) || (strcmp (category, ncategory) != 0)))
01025             continue;
01026 
01027           if ((selector != NULL) && 
01028               ((nselector == NULL) || (strcmp (selector, nselector) != 0)))
01029             continue;
01030 
01031           VEC_safe_push (const_char_ptr, *symbol_names, symname);
01032         }
01033 
01034       if (objc_csym == NULL)
01035         {
01036           objc_csym = obstack_alloc (&objfile->objfile_obstack,
01037                                      sizeof (*objc_csym));
01038           *objc_csym = objfile_csym;
01039           set_objfile_data (objfile, objc_objfile_data, objc_csym);
01040         }
01041       else
01042         /* Count of ObjC methods in this objfile should be constant.  */
01043         gdb_assert (*objc_csym == objfile_csym);
01044     }
01045 }
01046 
01047 /* Uniquify a VEC of strings.  */
01048 
01049 static void
01050 uniquify_strings (VEC (const_char_ptr) **strings)
01051 {
01052   int ix;
01053   const char *elem, *last = NULL;
01054   int out;
01055 
01056   qsort (VEC_address (const_char_ptr, *strings),
01057          VEC_length (const_char_ptr, *strings),
01058          sizeof (const_char_ptr),
01059          compare_strings);
01060   out = 0;
01061   for (ix = 0; VEC_iterate (const_char_ptr, *strings, ix, elem); ++ix)
01062     {
01063       if (last == NULL || strcmp (last, elem) != 0)
01064         {
01065           /* Keep ELEM.  */
01066           VEC_replace (const_char_ptr, *strings, out, elem);
01067           ++out;
01068         }
01069       last = elem;
01070     }
01071   VEC_truncate (const_char_ptr, *strings, out);
01072 }
01073 
01074 /* 
01075  * Function: find_imps (const char *selector, struct symbol **sym_arr)
01076  *
01077  * Input:  a string representing a selector
01078  *         a pointer to an array of symbol pointers
01079  *         possibly a pointer to a symbol found by the caller.
01080  *
01081  * Output: number of methods that implement that selector.  Side
01082  * effects: The array of symbol pointers is filled with matching syms.
01083  *
01084  * By analogy with function "find_methods" (symtab.c), builds a list
01085  * of symbols matching the ambiguous input, so that "decode_line_2"
01086  * (symtab.c) can list them and ask the user to choose one or more.
01087  * In this case the matches are objective c methods
01088  * ("implementations") matching an objective c selector.
01089  *
01090  * Note that it is possible for a normal (c-style) function to have
01091  * the same name as an objective c selector.  To prevent the selector
01092  * from eclipsing the function, we allow the caller (decode_line_1) to
01093  * search for such a function first, and if it finds one, pass it in
01094  * to us.  We will then integrate it into the list.  We also search
01095  * for one here, among the minsyms.
01096  *
01097  * NOTE: if NUM_DEBUGGABLE is non-zero, the sym_arr will be divided
01098  *       into two parts: debuggable (struct symbol) syms, and
01099  *       non_debuggable (struct minimal_symbol) syms.  The debuggable
01100  *       ones will come first, before NUM_DEBUGGABLE (which will thus
01101  *       be the index of the first non-debuggable one).
01102  */
01103 
01104 const char *
01105 find_imps (const char *method, VEC (const_char_ptr) **symbol_names)
01106 {
01107   char type = '\0';
01108   char *class = NULL;
01109   char *category = NULL;
01110   char *selector = NULL;
01111 
01112   char *buf = NULL;
01113   char *tmp = NULL;
01114 
01115   int selector_case = 0;
01116 
01117   gdb_assert (symbol_names != NULL);
01118 
01119   buf = (char *) alloca (strlen (method) + 1);
01120   strcpy (buf, method);
01121   tmp = parse_method (buf, &type, &class, &category, &selector);
01122 
01123   if (tmp == NULL)
01124     {
01125       strcpy (buf, method);
01126       tmp = parse_selector (buf, &selector);
01127 
01128       if (tmp == NULL)
01129         return NULL;
01130 
01131       selector_case = 1;
01132     }
01133 
01134   find_methods (type, class, category, selector, symbol_names);
01135 
01136   /* If we hit the "selector" case, and we found some methods, then
01137      add the selector itself as a symbol, if it exists.  */
01138   if (selector_case && !VEC_empty (const_char_ptr, *symbol_names))
01139     {
01140       struct symbol *sym = lookup_symbol (selector, NULL, VAR_DOMAIN, 0);
01141 
01142       if (sym != NULL) 
01143         VEC_safe_push (const_char_ptr, *symbol_names,
01144                        SYMBOL_NATURAL_NAME (sym));
01145       else
01146         {
01147           struct minimal_symbol *msym = lookup_minimal_symbol (selector, 0, 0);
01148 
01149           if (msym != NULL) 
01150             VEC_safe_push (const_char_ptr, *symbol_names,
01151                            SYMBOL_NATURAL_NAME (msym));
01152         }
01153     }
01154 
01155   uniquify_strings (symbol_names);
01156 
01157   return method + (tmp - buf);
01158 }
01159 
01160 static void 
01161 print_object_command (char *args, int from_tty)
01162 {
01163   struct value *object, *function, *description;
01164   CORE_ADDR string_addr, object_addr;
01165   int i = 0;
01166   gdb_byte c = 0;
01167 
01168   if (!args || !*args)
01169     error (
01170 "The 'print-object' command requires an argument (an Objective-C object)");
01171 
01172   {
01173     struct expression *expr = parse_expression (args);
01174     struct cleanup *old_chain = 
01175       make_cleanup (free_current_contents, &expr);
01176     int pc = 0;
01177 
01178     object = evaluate_subexp (builtin_type (expr->gdbarch)->builtin_data_ptr,
01179                               expr, &pc, EVAL_NORMAL);
01180     do_cleanups (old_chain);
01181   }
01182 
01183   /* Validate the address for sanity.  */
01184   object_addr = value_as_long (object);
01185   read_memory (object_addr, &c, 1);
01186 
01187   function = find_function_in_inferior ("_NSPrintForDebugger", NULL);
01188   if (function == NULL)
01189     error (_("Unable to locate _NSPrintForDebugger in child process"));
01190 
01191   description = call_function_by_hand (function, 1, &object);
01192 
01193   string_addr = value_as_long (description);
01194   if (string_addr == 0)
01195     error (_("object returns null description"));
01196 
01197   read_memory (string_addr + i++, &c, 1);
01198   if (c != 0)
01199     do
01200       { /* Read and print characters up to EOS.  */
01201         QUIT;
01202         printf_filtered ("%c", c);
01203         read_memory (string_addr + i++, &c, 1);
01204       } while (c != 0);
01205   else
01206     printf_filtered(_("<object returns empty description>"));
01207   printf_filtered ("\n");
01208 }
01209 
01210 /* The data structure 'methcalls' is used to detect method calls (thru
01211  * ObjC runtime lib functions objc_msgSend, objc_msgSendSuper, etc.),
01212  * and ultimately find the method being called.
01213  */
01214 
01215 struct objc_methcall {
01216   char *name;
01217  /* Return instance method to be called.  */
01218   int (*stop_at) (CORE_ADDR, CORE_ADDR *);
01219   /* Start of pc range corresponding to method invocation.  */
01220   CORE_ADDR begin;
01221   /* End of pc range corresponding to method invocation.  */
01222   CORE_ADDR end;
01223 };
01224 
01225 static int resolve_msgsend (CORE_ADDR pc, CORE_ADDR *new_pc);
01226 static int resolve_msgsend_stret (CORE_ADDR pc, CORE_ADDR *new_pc);
01227 static int resolve_msgsend_super (CORE_ADDR pc, CORE_ADDR *new_pc);
01228 static int resolve_msgsend_super_stret (CORE_ADDR pc, CORE_ADDR *new_pc);
01229 
01230 static struct objc_methcall methcalls[] = {
01231   { "_objc_msgSend", resolve_msgsend, 0, 0},
01232   { "_objc_msgSend_stret", resolve_msgsend_stret, 0, 0},
01233   { "_objc_msgSendSuper", resolve_msgsend_super, 0, 0},
01234   { "_objc_msgSendSuper_stret", resolve_msgsend_super_stret, 0, 0},
01235   { "_objc_getClass", NULL, 0, 0},
01236   { "_objc_getMetaClass", NULL, 0, 0}
01237 };
01238 
01239 #define nmethcalls (sizeof (methcalls) / sizeof (methcalls[0]))
01240 
01241 /* The following function, "find_objc_msgsend", fills in the data
01242  * structure "objc_msgs" by finding the addresses of each of the
01243  * (currently four) functions that it holds (of which objc_msgSend is
01244  * the first).  This must be called each time symbols are loaded, in
01245  * case the functions have moved for some reason.
01246  */
01247 
01248 static void 
01249 find_objc_msgsend (void)
01250 {
01251   unsigned int i;
01252 
01253   for (i = 0; i < nmethcalls; i++)
01254     {
01255       struct minimal_symbol *func;
01256 
01257       /* Try both with and without underscore.  */
01258       func = lookup_minimal_symbol (methcalls[i].name, NULL, NULL);
01259       if ((func == NULL) && (methcalls[i].name[0] == '_'))
01260         {
01261           func = lookup_minimal_symbol (methcalls[i].name + 1, NULL, NULL);
01262         }
01263       if (func == NULL)
01264         { 
01265           methcalls[i].begin = 0;
01266           methcalls[i].end = 0;
01267           continue; 
01268         }
01269 
01270       methcalls[i].begin = SYMBOL_VALUE_ADDRESS (func);
01271       do {
01272         methcalls[i].end = SYMBOL_VALUE_ADDRESS (++func);
01273       } while (methcalls[i].begin == methcalls[i].end);
01274     }
01275 }
01276 
01277 /* find_objc_msgcall (replaces pc_off_limits)
01278  *
01279  * ALL that this function now does is to determine whether the input
01280  * address ("pc") is the address of one of the Objective-C message
01281  * dispatch functions (mainly objc_msgSend or objc_msgSendSuper), and
01282  * if so, it returns the address of the method that will be called.
01283  *
01284  * The old function "pc_off_limits" used to do a lot of other things
01285  * in addition, such as detecting shared library jump stubs and
01286  * returning the address of the shlib function that would be called.
01287  * That functionality has been moved into the gdbarch_skip_trampoline_code and
01288  * IN_SOLIB_TRAMPOLINE macros, which are resolved in the target-
01289  * dependent modules.
01290  */
01291 
01292 struct objc_submethod_helper_data {
01293   int (*f) (CORE_ADDR, CORE_ADDR *);
01294   CORE_ADDR pc;
01295   CORE_ADDR *new_pc;
01296 };
01297 
01298 static int 
01299 find_objc_msgcall_submethod_helper (void * arg)
01300 {
01301   struct objc_submethod_helper_data *s = 
01302     (struct objc_submethod_helper_data *) arg;
01303 
01304   if (s->f (s->pc, s->new_pc) == 0) 
01305     return 1;
01306   else 
01307     return 0;
01308 }
01309 
01310 static int 
01311 find_objc_msgcall_submethod (int (*f) (CORE_ADDR, CORE_ADDR *),
01312                              CORE_ADDR pc, 
01313                              CORE_ADDR *new_pc)
01314 {
01315   struct objc_submethod_helper_data s;
01316 
01317   s.f = f;
01318   s.pc = pc;
01319   s.new_pc = new_pc;
01320 
01321   if (catch_errors (find_objc_msgcall_submethod_helper,
01322                     (void *) &s,
01323                     "Unable to determine target of "
01324                     "Objective-C method call (ignoring):\n",
01325                     RETURN_MASK_ALL) == 0) 
01326     return 1;
01327   else 
01328     return 0;
01329 }
01330 
01331 int 
01332 find_objc_msgcall (CORE_ADDR pc, CORE_ADDR *new_pc)
01333 {
01334   unsigned int i;
01335 
01336   find_objc_msgsend ();
01337   if (new_pc != NULL)
01338     {
01339       *new_pc = 0;
01340     }
01341 
01342   for (i = 0; i < nmethcalls; i++) 
01343     if ((pc >= methcalls[i].begin) && (pc < methcalls[i].end)) 
01344       {
01345         if (methcalls[i].stop_at != NULL) 
01346           return find_objc_msgcall_submethod (methcalls[i].stop_at, 
01347                                               pc, new_pc);
01348         else 
01349           return 0;
01350       }
01351 
01352   return 0;
01353 }
01354 
01355 /* -Wmissing-prototypes */
01356 extern initialize_file_ftype _initialize_objc_language;
01357 
01358 void
01359 _initialize_objc_language (void)
01360 {
01361   add_language (&objc_language_defn);
01362   add_info ("selectors", selectors_info,    /* INFO SELECTORS command.  */
01363             _("All Objective-C selectors, or those matching REGEXP."));
01364   add_info ("classes", classes_info,        /* INFO CLASSES   command.  */
01365             _("All Objective-C classes, or those matching REGEXP."));
01366   add_com ("print-object", class_vars, print_object_command, 
01367            _("Ask an Objective-C object to print itself."));
01368   add_com_alias ("po", "print-object", class_vars, 1);
01369 }
01370 
01371 static void 
01372 read_objc_method (struct gdbarch *gdbarch, CORE_ADDR addr,
01373                   struct objc_method *method)
01374 {
01375   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
01376 
01377   method->name  = read_memory_unsigned_integer (addr + 0, 4, byte_order);
01378   method->types = read_memory_unsigned_integer (addr + 4, 4, byte_order);
01379   method->imp   = read_memory_unsigned_integer (addr + 8, 4, byte_order);
01380 }
01381 
01382 static unsigned long
01383 read_objc_methlist_nmethods (struct gdbarch *gdbarch, CORE_ADDR addr)
01384 {
01385   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
01386 
01387   return read_memory_unsigned_integer (addr + 4, 4, byte_order);
01388 }
01389 
01390 static void 
01391 read_objc_methlist_method (struct gdbarch *gdbarch, CORE_ADDR addr,
01392                            unsigned long num, struct objc_method *method)
01393 {
01394   gdb_assert (num < read_objc_methlist_nmethods (gdbarch, addr));
01395   read_objc_method (gdbarch, addr + 8 + (12 * num), method);
01396 }
01397   
01398 static void 
01399 read_objc_object (struct gdbarch *gdbarch, CORE_ADDR addr,
01400                   struct objc_object *object)
01401 {
01402   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
01403 
01404   object->isa = read_memory_unsigned_integer (addr, 4, byte_order);
01405 }
01406 
01407 static void 
01408 read_objc_super (struct gdbarch *gdbarch, CORE_ADDR addr,
01409                  struct objc_super *super)
01410 {
01411   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
01412 
01413   super->receiver = read_memory_unsigned_integer (addr, 4, byte_order);
01414   super->class = read_memory_unsigned_integer (addr + 4, 4, byte_order);
01415 };
01416 
01417 static void 
01418 read_objc_class (struct gdbarch *gdbarch, CORE_ADDR addr,
01419                  struct objc_class *class)
01420 {
01421   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
01422 
01423   class->isa = read_memory_unsigned_integer (addr, 4, byte_order);
01424   class->super_class = read_memory_unsigned_integer (addr + 4, 4, byte_order);
01425   class->name = read_memory_unsigned_integer (addr + 8, 4, byte_order);
01426   class->version = read_memory_unsigned_integer (addr + 12, 4, byte_order);
01427   class->info = read_memory_unsigned_integer (addr + 16, 4, byte_order);
01428   class->instance_size = read_memory_unsigned_integer (addr + 18, 4,
01429                                                        byte_order);
01430   class->ivars = read_memory_unsigned_integer (addr + 24, 4, byte_order);
01431   class->methods = read_memory_unsigned_integer (addr + 28, 4, byte_order);
01432   class->cache = read_memory_unsigned_integer (addr + 32, 4, byte_order);
01433   class->protocols = read_memory_unsigned_integer (addr + 36, 4, byte_order);
01434 }
01435 
01436 static CORE_ADDR
01437 find_implementation_from_class (struct gdbarch *gdbarch,
01438                                 CORE_ADDR class, CORE_ADDR sel)
01439 {
01440   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
01441   CORE_ADDR subclass = class;
01442 
01443   while (subclass != 0) 
01444     {
01445 
01446       struct objc_class class_str;
01447       unsigned mlistnum = 0;
01448 
01449       read_objc_class (gdbarch, subclass, &class_str);
01450 
01451       for (;;) 
01452         {
01453           CORE_ADDR mlist;
01454           unsigned long nmethods;
01455           unsigned long i;
01456       
01457           mlist = read_memory_unsigned_integer (class_str.methods + 
01458                                                 (4 * mlistnum),
01459                                                 4, byte_order);
01460           if (mlist == 0) 
01461             break;
01462 
01463           nmethods = read_objc_methlist_nmethods (gdbarch, mlist);
01464 
01465           for (i = 0; i < nmethods; i++) 
01466             {
01467               struct objc_method meth_str;
01468 
01469               read_objc_methlist_method (gdbarch, mlist, i, &meth_str);
01470 #if 0
01471               fprintf (stderr, 
01472                        "checking method 0x%lx against selector 0x%lx\n", 
01473                        meth_str.name, sel);
01474 #endif
01475 
01476               if (meth_str.name == sel) 
01477                 /* FIXME: hppa arch was doing a pointer dereference
01478                    here.  There needs to be a better way to do that.  */
01479                 return meth_str.imp;
01480             }
01481           mlistnum++;
01482         }
01483       subclass = class_str.super_class;
01484     }
01485 
01486   return 0;
01487 }
01488 
01489 static CORE_ADDR
01490 find_implementation (struct gdbarch *gdbarch,
01491                      CORE_ADDR object, CORE_ADDR sel)
01492 {
01493   struct objc_object ostr;
01494 
01495   if (object == 0)
01496     return 0;
01497   read_objc_object (gdbarch, object, &ostr);
01498   if (ostr.isa == 0)
01499     return 0;
01500 
01501   return find_implementation_from_class (gdbarch, ostr.isa, sel);
01502 }
01503 
01504 static int
01505 resolve_msgsend (CORE_ADDR pc, CORE_ADDR *new_pc)
01506 {
01507   struct frame_info *frame = get_current_frame ();
01508   struct gdbarch *gdbarch = get_frame_arch (frame);
01509   struct type *ptr_type = builtin_type (gdbarch)->builtin_func_ptr;
01510 
01511   CORE_ADDR object;
01512   CORE_ADDR sel;
01513   CORE_ADDR res;
01514 
01515   object = gdbarch_fetch_pointer_argument (gdbarch, frame, 0, ptr_type);
01516   sel = gdbarch_fetch_pointer_argument (gdbarch, frame, 1, ptr_type);
01517 
01518   res = find_implementation (gdbarch, object, sel);
01519   if (new_pc != 0)
01520     *new_pc = res;
01521   if (res == 0)
01522     return 1;
01523   return 0;
01524 }
01525 
01526 static int
01527 resolve_msgsend_stret (CORE_ADDR pc, CORE_ADDR *new_pc)
01528 {
01529   struct frame_info *frame = get_current_frame ();
01530   struct gdbarch *gdbarch = get_frame_arch (frame);
01531   struct type *ptr_type = builtin_type (gdbarch)->builtin_func_ptr;
01532 
01533   CORE_ADDR object;
01534   CORE_ADDR sel;
01535   CORE_ADDR res;
01536 
01537   object = gdbarch_fetch_pointer_argument (gdbarch, frame, 1, ptr_type);
01538   sel = gdbarch_fetch_pointer_argument (gdbarch, frame, 2, ptr_type);
01539 
01540   res = find_implementation (gdbarch, object, sel);
01541   if (new_pc != 0)
01542     *new_pc = res;
01543   if (res == 0)
01544     return 1;
01545   return 0;
01546 }
01547 
01548 static int
01549 resolve_msgsend_super (CORE_ADDR pc, CORE_ADDR *new_pc)
01550 {
01551   struct frame_info *frame = get_current_frame ();
01552   struct gdbarch *gdbarch = get_frame_arch (frame);
01553   struct type *ptr_type = builtin_type (gdbarch)->builtin_func_ptr;
01554 
01555   struct objc_super sstr;
01556 
01557   CORE_ADDR super;
01558   CORE_ADDR sel;
01559   CORE_ADDR res;
01560 
01561   super = gdbarch_fetch_pointer_argument (gdbarch, frame, 0, ptr_type);
01562   sel = gdbarch_fetch_pointer_argument (gdbarch, frame, 1, ptr_type);
01563 
01564   read_objc_super (gdbarch, super, &sstr);
01565   if (sstr.class == 0)
01566     return 0;
01567   
01568   res = find_implementation_from_class (gdbarch, sstr.class, sel);
01569   if (new_pc != 0)
01570     *new_pc = res;
01571   if (res == 0)
01572     return 1;
01573   return 0;
01574 }
01575 
01576 static int
01577 resolve_msgsend_super_stret (CORE_ADDR pc, CORE_ADDR *new_pc)
01578 {
01579   struct frame_info *frame = get_current_frame ();
01580   struct gdbarch *gdbarch = get_frame_arch (frame);
01581   struct type *ptr_type = builtin_type (gdbarch)->builtin_func_ptr;
01582 
01583   struct objc_super sstr;
01584 
01585   CORE_ADDR super;
01586   CORE_ADDR sel;
01587   CORE_ADDR res;
01588 
01589   super = gdbarch_fetch_pointer_argument (gdbarch, frame, 1, ptr_type);
01590   sel = gdbarch_fetch_pointer_argument (gdbarch, frame, 2, ptr_type);
01591 
01592   read_objc_super (gdbarch, super, &sstr);
01593   if (sstr.class == 0)
01594     return 0;
01595   
01596   res = find_implementation_from_class (gdbarch, sstr.class, sel);
01597   if (new_pc != 0)
01598     *new_pc = res;
01599   if (res == 0)
01600     return 1;
01601   return 0;
01602 }
01603 
01604 /* Provide a prototype to silence -Wmissing-prototypes.  */
01605 extern initialize_file_ftype _initialize_objc_lang;
01606 
01607 void
01608 _initialize_objc_lang (void)
01609 {
01610   objc_objfile_data = register_objfile_data ();
01611 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines