GDB (API)
|
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 }