1130803Smarcel/* Objective-C language support routines for GDB, the GNU debugger. 2130803Smarcel 3130803Smarcel Copyright 2002, 2003, 2004 Free Software Foundation, Inc. 4130803Smarcel 5130803Smarcel Contributed by Apple Computer, Inc. 6130803Smarcel Written by Michael Snyder. 7130803Smarcel 8130803Smarcel This file is part of GDB. 9130803Smarcel 10130803Smarcel This program is free software; you can redistribute it and/or modify 11130803Smarcel it under the terms of the GNU General Public License as published by 12130803Smarcel the Free Software Foundation; either version 2 of the License, or 13130803Smarcel (at your option) any later version. 14130803Smarcel 15130803Smarcel This program is distributed in the hope that it will be useful, 16130803Smarcel but WITHOUT ANY WARRANTY; without even the implied warranty of 17130803Smarcel MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18130803Smarcel GNU General Public License for more details. 19130803Smarcel 20130803Smarcel You should have received a copy of the GNU General Public License 21130803Smarcel along with this program; if not, write to the Free Software 22130803Smarcel Foundation, Inc., 59 Temple Place - Suite 330, 23130803Smarcel Boston, MA 02111-1307, USA. */ 24130803Smarcel 25130803Smarcel#include "defs.h" 26130803Smarcel#include "symtab.h" 27130803Smarcel#include "gdbtypes.h" 28130803Smarcel#include "expression.h" 29130803Smarcel#include "parser-defs.h" 30130803Smarcel#include "language.h" 31130803Smarcel#include "c-lang.h" 32130803Smarcel#include "objc-lang.h" 33130803Smarcel#include "complaints.h" 34130803Smarcel#include "value.h" 35130803Smarcel#include "symfile.h" 36130803Smarcel#include "objfiles.h" 37130803Smarcel#include "gdb_string.h" /* for strchr */ 38130803Smarcel#include "target.h" /* for target_has_execution */ 39130803Smarcel#include "gdbcore.h" 40130803Smarcel#include "gdbcmd.h" 41130803Smarcel#include "frame.h" 42130803Smarcel#include "gdb_regex.h" 43130803Smarcel#include "regcache.h" 44130803Smarcel#include "block.h" 45130803Smarcel#include "infcall.h" 46130803Smarcel#include "valprint.h" 47130803Smarcel#include "gdb_assert.h" 48130803Smarcel 49130803Smarcel#include <ctype.h> 50130803Smarcel 51130803Smarcelstruct objc_object { 52130803Smarcel CORE_ADDR isa; 53130803Smarcel}; 54130803Smarcel 55130803Smarcelstruct objc_class { 56130803Smarcel CORE_ADDR isa; 57130803Smarcel CORE_ADDR super_class; 58130803Smarcel CORE_ADDR name; 59130803Smarcel long version; 60130803Smarcel long info; 61130803Smarcel long instance_size; 62130803Smarcel CORE_ADDR ivars; 63130803Smarcel CORE_ADDR methods; 64130803Smarcel CORE_ADDR cache; 65130803Smarcel CORE_ADDR protocols; 66130803Smarcel}; 67130803Smarcel 68130803Smarcelstruct objc_super { 69130803Smarcel CORE_ADDR receiver; 70130803Smarcel CORE_ADDR class; 71130803Smarcel}; 72130803Smarcel 73130803Smarcelstruct objc_method { 74130803Smarcel CORE_ADDR name; 75130803Smarcel CORE_ADDR types; 76130803Smarcel CORE_ADDR imp; 77130803Smarcel}; 78130803Smarcel 79130803Smarcel/* Lookup a structure type named "struct NAME", visible in lexical 80130803Smarcel block BLOCK. If NOERR is nonzero, return zero if NAME is not 81130803Smarcel suitably defined. */ 82130803Smarcel 83130803Smarcelstruct symbol * 84130803Smarcellookup_struct_typedef (char *name, struct block *block, int noerr) 85130803Smarcel{ 86130803Smarcel struct symbol *sym; 87130803Smarcel 88130803Smarcel sym = lookup_symbol (name, block, STRUCT_DOMAIN, 0, 89130803Smarcel (struct symtab **) NULL); 90130803Smarcel 91130803Smarcel if (sym == NULL) 92130803Smarcel { 93130803Smarcel if (noerr) 94130803Smarcel return 0; 95130803Smarcel else 96130803Smarcel error ("No struct type named %s.", name); 97130803Smarcel } 98130803Smarcel if (TYPE_CODE (SYMBOL_TYPE (sym)) != TYPE_CODE_STRUCT) 99130803Smarcel { 100130803Smarcel if (noerr) 101130803Smarcel return 0; 102130803Smarcel else 103130803Smarcel error ("This context has class, union or enum %s, not a struct.", 104130803Smarcel name); 105130803Smarcel } 106130803Smarcel return sym; 107130803Smarcel} 108130803Smarcel 109130803SmarcelCORE_ADDR 110130803Smarcellookup_objc_class (char *classname) 111130803Smarcel{ 112130803Smarcel struct value * function, *classval; 113130803Smarcel 114130803Smarcel if (! target_has_execution) 115130803Smarcel { 116130803Smarcel /* Can't call into inferior to lookup class. */ 117130803Smarcel return 0; 118130803Smarcel } 119130803Smarcel 120130803Smarcel if (lookup_minimal_symbol("objc_lookUpClass", 0, 0)) 121130803Smarcel function = find_function_in_inferior("objc_lookUpClass"); 122130803Smarcel else if (lookup_minimal_symbol ("objc_lookup_class", 0, 0)) 123130803Smarcel function = find_function_in_inferior("objc_lookup_class"); 124130803Smarcel else 125130803Smarcel { 126130803Smarcel complaint (&symfile_complaints, "no way to lookup Objective-C classes"); 127130803Smarcel return 0; 128130803Smarcel } 129130803Smarcel 130130803Smarcel classval = value_string (classname, strlen (classname) + 1); 131130803Smarcel classval = value_coerce_array (classval); 132130803Smarcel return (CORE_ADDR) value_as_long (call_function_by_hand (function, 133130803Smarcel 1, &classval)); 134130803Smarcel} 135130803Smarcel 136130803SmarcelCORE_ADDR 137130803Smarcellookup_child_selector (char *selname) 138130803Smarcel{ 139130803Smarcel struct value * function, *selstring; 140130803Smarcel 141130803Smarcel if (! target_has_execution) 142130803Smarcel { 143130803Smarcel /* Can't call into inferior to lookup selector. */ 144130803Smarcel return 0; 145130803Smarcel } 146130803Smarcel 147130803Smarcel if (lookup_minimal_symbol("sel_getUid", 0, 0)) 148130803Smarcel function = find_function_in_inferior("sel_getUid"); 149130803Smarcel else if (lookup_minimal_symbol ("sel_get_any_uid", 0, 0)) 150130803Smarcel function = find_function_in_inferior("sel_get_any_uid"); 151130803Smarcel else 152130803Smarcel { 153130803Smarcel complaint (&symfile_complaints, "no way to lookup Objective-C selectors"); 154130803Smarcel return 0; 155130803Smarcel } 156130803Smarcel 157130803Smarcel selstring = value_coerce_array (value_string (selname, 158130803Smarcel strlen (selname) + 1)); 159130803Smarcel return value_as_long (call_function_by_hand (function, 1, &selstring)); 160130803Smarcel} 161130803Smarcel 162130803Smarcelstruct value * 163130803Smarcelvalue_nsstring (char *ptr, int len) 164130803Smarcel{ 165130803Smarcel struct value *stringValue[3]; 166130803Smarcel struct value *function, *nsstringValue; 167130803Smarcel struct symbol *sym; 168130803Smarcel struct type *type; 169130803Smarcel 170130803Smarcel if (!target_has_execution) 171130803Smarcel return 0; /* Can't call into inferior to create NSString. */ 172130803Smarcel 173130803Smarcel sym = lookup_struct_typedef("NSString", 0, 1); 174130803Smarcel if (sym == NULL) 175130803Smarcel sym = lookup_struct_typedef("NXString", 0, 1); 176130803Smarcel if (sym == NULL) 177130803Smarcel type = lookup_pointer_type(builtin_type_void); 178130803Smarcel else 179130803Smarcel type = lookup_pointer_type(SYMBOL_TYPE (sym)); 180130803Smarcel 181130803Smarcel stringValue[2] = value_string(ptr, len); 182130803Smarcel stringValue[2] = value_coerce_array(stringValue[2]); 183130803Smarcel /* _NSNewStringFromCString replaces "istr" after Lantern2A. */ 184130803Smarcel if (lookup_minimal_symbol("_NSNewStringFromCString", 0, 0)) 185130803Smarcel { 186130803Smarcel function = find_function_in_inferior("_NSNewStringFromCString"); 187130803Smarcel nsstringValue = call_function_by_hand(function, 1, &stringValue[2]); 188130803Smarcel } 189130803Smarcel else if (lookup_minimal_symbol("istr", 0, 0)) 190130803Smarcel { 191130803Smarcel function = find_function_in_inferior("istr"); 192130803Smarcel nsstringValue = call_function_by_hand(function, 1, &stringValue[2]); 193130803Smarcel } 194130803Smarcel else if (lookup_minimal_symbol("+[NSString stringWithCString:]", 0, 0)) 195130803Smarcel { 196130803Smarcel function = find_function_in_inferior("+[NSString stringWithCString:]"); 197130803Smarcel stringValue[0] = value_from_longest 198130803Smarcel (builtin_type_long, lookup_objc_class ("NSString")); 199130803Smarcel stringValue[1] = value_from_longest 200130803Smarcel (builtin_type_long, lookup_child_selector ("stringWithCString:")); 201130803Smarcel nsstringValue = call_function_by_hand(function, 3, &stringValue[0]); 202130803Smarcel } 203130803Smarcel else 204130803Smarcel error ("NSString: internal error -- no way to create new NSString"); 205130803Smarcel 206130803Smarcel VALUE_TYPE(nsstringValue) = type; 207130803Smarcel return nsstringValue; 208130803Smarcel} 209130803Smarcel 210130803Smarcel/* Objective-C name demangling. */ 211130803Smarcel 212130803Smarcelchar * 213130803Smarcelobjc_demangle (const char *mangled, int options) 214130803Smarcel{ 215130803Smarcel char *demangled, *cp; 216130803Smarcel 217130803Smarcel if (mangled[0] == '_' && 218130803Smarcel (mangled[1] == 'i' || mangled[1] == 'c') && 219130803Smarcel mangled[2] == '_') 220130803Smarcel { 221130803Smarcel cp = demangled = xmalloc(strlen(mangled) + 2); 222130803Smarcel 223130803Smarcel if (mangled[1] == 'i') 224130803Smarcel *cp++ = '-'; /* for instance method */ 225130803Smarcel else 226130803Smarcel *cp++ = '+'; /* for class method */ 227130803Smarcel 228130803Smarcel *cp++ = '['; /* opening left brace */ 229130803Smarcel strcpy(cp, mangled+3); /* tack on the rest of the mangled name */ 230130803Smarcel 231130803Smarcel while (*cp && *cp == '_') 232130803Smarcel cp++; /* skip any initial underbars in class name */ 233130803Smarcel 234130803Smarcel cp = strchr(cp, '_'); 235130803Smarcel if (!cp) /* find first non-initial underbar */ 236130803Smarcel { 237130803Smarcel xfree(demangled); /* not mangled name */ 238130803Smarcel return NULL; 239130803Smarcel } 240130803Smarcel if (cp[1] == '_') { /* easy case: no category name */ 241130803Smarcel *cp++ = ' '; /* replace two '_' with one ' ' */ 242130803Smarcel strcpy(cp, mangled + (cp - demangled) + 2); 243130803Smarcel } 244130803Smarcel else { 245130803Smarcel *cp++ = '('; /* less easy case: category name */ 246130803Smarcel cp = strchr(cp, '_'); 247130803Smarcel if (!cp) 248130803Smarcel { 249130803Smarcel xfree(demangled); /* not mangled name */ 250130803Smarcel return NULL; 251130803Smarcel } 252130803Smarcel *cp++ = ')'; 253130803Smarcel *cp++ = ' '; /* overwriting 1st char of method name... */ 254130803Smarcel strcpy(cp, mangled + (cp - demangled)); /* get it back */ 255130803Smarcel } 256130803Smarcel 257130803Smarcel while (*cp && *cp == '_') 258130803Smarcel cp++; /* skip any initial underbars in method name */ 259130803Smarcel 260130803Smarcel for (; *cp; cp++) 261130803Smarcel if (*cp == '_') 262130803Smarcel *cp = ':'; /* replace remaining '_' with ':' */ 263130803Smarcel 264130803Smarcel *cp++ = ']'; /* closing right brace */ 265130803Smarcel *cp++ = 0; /* string terminator */ 266130803Smarcel return demangled; 267130803Smarcel } 268130803Smarcel else 269130803Smarcel return NULL; /* Not an objc mangled name. */ 270130803Smarcel} 271130803Smarcel 272130803Smarcel/* Print the character C on STREAM as part of the contents of a 273130803Smarcel literal string whose delimiter is QUOTER. Note that that format 274130803Smarcel for printing characters and strings is language specific. */ 275130803Smarcel 276130803Smarcelstatic void 277130803Smarcelobjc_emit_char (int c, struct ui_file *stream, int quoter) 278130803Smarcel{ 279130803Smarcel 280130803Smarcel c &= 0xFF; /* Avoid sign bit follies. */ 281130803Smarcel 282130803Smarcel if (PRINT_LITERAL_FORM (c)) 283130803Smarcel { 284130803Smarcel if (c == '\\' || c == quoter) 285130803Smarcel { 286130803Smarcel fputs_filtered ("\\", stream); 287130803Smarcel } 288130803Smarcel fprintf_filtered (stream, "%c", c); 289130803Smarcel } 290130803Smarcel else 291130803Smarcel { 292130803Smarcel switch (c) 293130803Smarcel { 294130803Smarcel case '\n': 295130803Smarcel fputs_filtered ("\\n", stream); 296130803Smarcel break; 297130803Smarcel case '\b': 298130803Smarcel fputs_filtered ("\\b", stream); 299130803Smarcel break; 300130803Smarcel case '\t': 301130803Smarcel fputs_filtered ("\\t", stream); 302130803Smarcel break; 303130803Smarcel case '\f': 304130803Smarcel fputs_filtered ("\\f", stream); 305130803Smarcel break; 306130803Smarcel case '\r': 307130803Smarcel fputs_filtered ("\\r", stream); 308130803Smarcel break; 309130803Smarcel case '\033': 310130803Smarcel fputs_filtered ("\\e", stream); 311130803Smarcel break; 312130803Smarcel case '\007': 313130803Smarcel fputs_filtered ("\\a", stream); 314130803Smarcel break; 315130803Smarcel default: 316130803Smarcel fprintf_filtered (stream, "\\%.3o", (unsigned int) c); 317130803Smarcel break; 318130803Smarcel } 319130803Smarcel } 320130803Smarcel} 321130803Smarcel 322130803Smarcelstatic void 323130803Smarcelobjc_printchar (int c, struct ui_file *stream) 324130803Smarcel{ 325130803Smarcel fputs_filtered ("'", stream); 326130803Smarcel objc_emit_char (c, stream, '\''); 327130803Smarcel fputs_filtered ("'", stream); 328130803Smarcel} 329130803Smarcel 330130803Smarcel/* Print the character string STRING, printing at most LENGTH 331130803Smarcel characters. Printing stops early if the number hits print_max; 332130803Smarcel repeat counts are printed as appropriate. Print ellipses at the 333130803Smarcel end if we had to stop before printing LENGTH characters, or if 334130803Smarcel FORCE_ELLIPSES. */ 335130803Smarcel 336130803Smarcelstatic void 337130803Smarcelobjc_printstr (struct ui_file *stream, char *string, 338130803Smarcel unsigned int length, int width, int force_ellipses) 339130803Smarcel{ 340130803Smarcel unsigned int i; 341130803Smarcel unsigned int things_printed = 0; 342130803Smarcel int in_quotes = 0; 343130803Smarcel int need_comma = 0; 344130803Smarcel 345130803Smarcel /* If the string was not truncated due to `set print elements', and 346130803Smarcel the last byte of it is a null, we don't print that, in 347130803Smarcel traditional C style. */ 348130803Smarcel if ((!force_ellipses) && length > 0 && string[length-1] == '\0') 349130803Smarcel length--; 350130803Smarcel 351130803Smarcel if (length == 0) 352130803Smarcel { 353130803Smarcel fputs_filtered ("\"\"", stream); 354130803Smarcel return; 355130803Smarcel } 356130803Smarcel 357130803Smarcel for (i = 0; i < length && things_printed < print_max; ++i) 358130803Smarcel { 359130803Smarcel /* Position of the character we are examining to see whether it 360130803Smarcel is repeated. */ 361130803Smarcel unsigned int rep1; 362130803Smarcel /* Number of repetitions we have detected so far. */ 363130803Smarcel unsigned int reps; 364130803Smarcel 365130803Smarcel QUIT; 366130803Smarcel 367130803Smarcel if (need_comma) 368130803Smarcel { 369130803Smarcel fputs_filtered (", ", stream); 370130803Smarcel need_comma = 0; 371130803Smarcel } 372130803Smarcel 373130803Smarcel rep1 = i + 1; 374130803Smarcel reps = 1; 375130803Smarcel while (rep1 < length && string[rep1] == string[i]) 376130803Smarcel { 377130803Smarcel ++rep1; 378130803Smarcel ++reps; 379130803Smarcel } 380130803Smarcel 381130803Smarcel if (reps > repeat_count_threshold) 382130803Smarcel { 383130803Smarcel if (in_quotes) 384130803Smarcel { 385130803Smarcel if (inspect_it) 386130803Smarcel fputs_filtered ("\\\", ", stream); 387130803Smarcel else 388130803Smarcel fputs_filtered ("\", ", stream); 389130803Smarcel in_quotes = 0; 390130803Smarcel } 391130803Smarcel objc_printchar (string[i], stream); 392130803Smarcel fprintf_filtered (stream, " <repeats %u times>", reps); 393130803Smarcel i = rep1 - 1; 394130803Smarcel things_printed += repeat_count_threshold; 395130803Smarcel need_comma = 1; 396130803Smarcel } 397130803Smarcel else 398130803Smarcel { 399130803Smarcel if (!in_quotes) 400130803Smarcel { 401130803Smarcel if (inspect_it) 402130803Smarcel fputs_filtered ("\\\"", stream); 403130803Smarcel else 404130803Smarcel fputs_filtered ("\"", stream); 405130803Smarcel in_quotes = 1; 406130803Smarcel } 407130803Smarcel objc_emit_char (string[i], stream, '"'); 408130803Smarcel ++things_printed; 409130803Smarcel } 410130803Smarcel } 411130803Smarcel 412130803Smarcel /* Terminate the quotes if necessary. */ 413130803Smarcel if (in_quotes) 414130803Smarcel { 415130803Smarcel if (inspect_it) 416130803Smarcel fputs_filtered ("\\\"", stream); 417130803Smarcel else 418130803Smarcel fputs_filtered ("\"", stream); 419130803Smarcel } 420130803Smarcel 421130803Smarcel if (force_ellipses || i < length) 422130803Smarcel fputs_filtered ("...", stream); 423130803Smarcel} 424130803Smarcel 425130803Smarcel/* Create a fundamental C type using default reasonable for the 426130803Smarcel current target. 427130803Smarcel 428130803Smarcel Some object/debugging file formats (DWARF version 1, COFF, etc) do 429130803Smarcel not define fundamental types such as "int" or "double". Others 430130803Smarcel (stabs or DWARF version 2, etc) do define fundamental types. For 431130803Smarcel the formats which don't provide fundamental types, gdb can create 432130803Smarcel such types using this function. 433130803Smarcel 434130803Smarcel FIXME: Some compilers distinguish explicitly signed integral types 435130803Smarcel (signed short, signed int, signed long) from "regular" integral 436130803Smarcel types (short, int, long) in the debugging information. There is 437130803Smarcel some disagreement as to how useful this feature is. In particular, 438130803Smarcel gcc does not support this. Also, only some debugging formats allow 439130803Smarcel the distinction to be passed on to a debugger. For now, we always 440130803Smarcel just use "short", "int", or "long" as the type name, for both the 441130803Smarcel implicit and explicitly signed types. This also makes life easier 442130803Smarcel for the gdb test suite since we don't have to account for the 443130803Smarcel differences in output depending upon what the compiler and 444130803Smarcel debugging format support. We will probably have to re-examine the 445130803Smarcel issue when gdb starts taking it's fundamental type information 446130803Smarcel directly from the debugging information supplied by the compiler. 447130803Smarcel fnf@cygnus.com */ 448130803Smarcel 449130803Smarcelstatic struct type * 450130803Smarcelobjc_create_fundamental_type (struct objfile *objfile, int typeid) 451130803Smarcel{ 452130803Smarcel struct type *type = NULL; 453130803Smarcel 454130803Smarcel switch (typeid) 455130803Smarcel { 456130803Smarcel default: 457130803Smarcel /* FIXME: For now, if we are asked to produce a type not in 458130803Smarcel this language, create the equivalent of a C integer type 459130803Smarcel with the name "<?type?>". When all the dust settles from 460130803Smarcel the type reconstruction work, this should probably become 461130803Smarcel an error. */ 462130803Smarcel type = init_type (TYPE_CODE_INT, 463130803Smarcel TARGET_INT_BIT / TARGET_CHAR_BIT, 464130803Smarcel 0, "<?type?>", objfile); 465130803Smarcel warning ("internal error: no C/C++ fundamental type %d", typeid); 466130803Smarcel break; 467130803Smarcel case FT_VOID: 468130803Smarcel type = init_type (TYPE_CODE_VOID, 469130803Smarcel TARGET_CHAR_BIT / TARGET_CHAR_BIT, 470130803Smarcel 0, "void", objfile); 471130803Smarcel break; 472130803Smarcel case FT_CHAR: 473130803Smarcel type = init_type (TYPE_CODE_INT, 474130803Smarcel TARGET_CHAR_BIT / TARGET_CHAR_BIT, 475130803Smarcel 0, "char", objfile); 476130803Smarcel break; 477130803Smarcel case FT_SIGNED_CHAR: 478130803Smarcel type = init_type (TYPE_CODE_INT, 479130803Smarcel TARGET_CHAR_BIT / TARGET_CHAR_BIT, 480130803Smarcel 0, "signed char", objfile); 481130803Smarcel break; 482130803Smarcel case FT_UNSIGNED_CHAR: 483130803Smarcel type = init_type (TYPE_CODE_INT, 484130803Smarcel TARGET_CHAR_BIT / TARGET_CHAR_BIT, 485130803Smarcel TYPE_FLAG_UNSIGNED, "unsigned char", objfile); 486130803Smarcel break; 487130803Smarcel case FT_SHORT: 488130803Smarcel type = init_type (TYPE_CODE_INT, 489130803Smarcel TARGET_SHORT_BIT / TARGET_CHAR_BIT, 490130803Smarcel 0, "short", objfile); 491130803Smarcel break; 492130803Smarcel case FT_SIGNED_SHORT: 493130803Smarcel type = init_type (TYPE_CODE_INT, 494130803Smarcel TARGET_SHORT_BIT / TARGET_CHAR_BIT, 495130803Smarcel 0, "short", objfile); /* FIXME-fnf */ 496130803Smarcel break; 497130803Smarcel case FT_UNSIGNED_SHORT: 498130803Smarcel type = init_type (TYPE_CODE_INT, 499130803Smarcel TARGET_SHORT_BIT / TARGET_CHAR_BIT, 500130803Smarcel TYPE_FLAG_UNSIGNED, "unsigned short", objfile); 501130803Smarcel break; 502130803Smarcel case FT_INTEGER: 503130803Smarcel type = init_type (TYPE_CODE_INT, 504130803Smarcel TARGET_INT_BIT / TARGET_CHAR_BIT, 505130803Smarcel 0, "int", objfile); 506130803Smarcel break; 507130803Smarcel case FT_SIGNED_INTEGER: 508130803Smarcel type = init_type (TYPE_CODE_INT, 509130803Smarcel TARGET_INT_BIT / TARGET_CHAR_BIT, 510130803Smarcel 0, "int", objfile); /* FIXME -fnf */ 511130803Smarcel break; 512130803Smarcel case FT_UNSIGNED_INTEGER: 513130803Smarcel type = init_type (TYPE_CODE_INT, 514130803Smarcel TARGET_INT_BIT / TARGET_CHAR_BIT, 515130803Smarcel TYPE_FLAG_UNSIGNED, "unsigned int", objfile); 516130803Smarcel break; 517130803Smarcel case FT_LONG: 518130803Smarcel type = init_type (TYPE_CODE_INT, 519130803Smarcel TARGET_LONG_BIT / TARGET_CHAR_BIT, 520130803Smarcel 0, "long", objfile); 521130803Smarcel break; 522130803Smarcel case FT_SIGNED_LONG: 523130803Smarcel type = init_type (TYPE_CODE_INT, 524130803Smarcel TARGET_LONG_BIT / TARGET_CHAR_BIT, 525130803Smarcel 0, "long", objfile); /* FIXME -fnf */ 526130803Smarcel break; 527130803Smarcel case FT_UNSIGNED_LONG: 528130803Smarcel type = init_type (TYPE_CODE_INT, 529130803Smarcel TARGET_LONG_BIT / TARGET_CHAR_BIT, 530130803Smarcel TYPE_FLAG_UNSIGNED, "unsigned long", objfile); 531130803Smarcel break; 532130803Smarcel case FT_LONG_LONG: 533130803Smarcel type = init_type (TYPE_CODE_INT, 534130803Smarcel TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT, 535130803Smarcel 0, "long long", objfile); 536130803Smarcel break; 537130803Smarcel case FT_SIGNED_LONG_LONG: 538130803Smarcel type = init_type (TYPE_CODE_INT, 539130803Smarcel TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT, 540130803Smarcel 0, "signed long long", objfile); 541130803Smarcel break; 542130803Smarcel case FT_UNSIGNED_LONG_LONG: 543130803Smarcel type = init_type (TYPE_CODE_INT, 544130803Smarcel TARGET_LONG_LONG_BIT / TARGET_CHAR_BIT, 545130803Smarcel TYPE_FLAG_UNSIGNED, "unsigned long long", objfile); 546130803Smarcel break; 547130803Smarcel case FT_FLOAT: 548130803Smarcel type = init_type (TYPE_CODE_FLT, 549130803Smarcel TARGET_FLOAT_BIT / TARGET_CHAR_BIT, 550130803Smarcel 0, "float", objfile); 551130803Smarcel break; 552130803Smarcel case FT_DBL_PREC_FLOAT: 553130803Smarcel type = init_type (TYPE_CODE_FLT, 554130803Smarcel TARGET_DOUBLE_BIT / TARGET_CHAR_BIT, 555130803Smarcel 0, "double", objfile); 556130803Smarcel break; 557130803Smarcel case FT_EXT_PREC_FLOAT: 558130803Smarcel type = init_type (TYPE_CODE_FLT, 559130803Smarcel TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT, 560130803Smarcel 0, "long double", objfile); 561130803Smarcel break; 562130803Smarcel } 563130803Smarcel return (type); 564130803Smarcel} 565130803Smarcel 566130803Smarcel/* Determine if we are currently in the Objective-C dispatch function. 567130803Smarcel If so, get the address of the method function that the dispatcher 568130803Smarcel would call and use that as the function to step into instead. Also 569130803Smarcel skip over the trampoline for the function (if any). This is better 570130803Smarcel for the user since they are only interested in stepping into the 571130803Smarcel method function anyway. */ 572130803Smarcelstatic CORE_ADDR 573130803Smarcelobjc_skip_trampoline (CORE_ADDR stop_pc) 574130803Smarcel{ 575130803Smarcel CORE_ADDR real_stop_pc; 576130803Smarcel CORE_ADDR method_stop_pc; 577130803Smarcel 578130803Smarcel real_stop_pc = SKIP_TRAMPOLINE_CODE (stop_pc); 579130803Smarcel 580130803Smarcel if (real_stop_pc != 0) 581130803Smarcel find_objc_msgcall (real_stop_pc, &method_stop_pc); 582130803Smarcel else 583130803Smarcel find_objc_msgcall (stop_pc, &method_stop_pc); 584130803Smarcel 585130803Smarcel if (method_stop_pc) 586130803Smarcel { 587130803Smarcel real_stop_pc = SKIP_TRAMPOLINE_CODE (method_stop_pc); 588130803Smarcel if (real_stop_pc == 0) 589130803Smarcel real_stop_pc = method_stop_pc; 590130803Smarcel } 591130803Smarcel 592130803Smarcel return real_stop_pc; 593130803Smarcel} 594130803Smarcel 595130803Smarcel 596130803Smarcel/* Table mapping opcodes into strings for printing operators 597130803Smarcel and precedences of the operators. */ 598130803Smarcel 599130803Smarcelstatic const struct op_print objc_op_print_tab[] = 600130803Smarcel { 601130803Smarcel {",", BINOP_COMMA, PREC_COMMA, 0}, 602130803Smarcel {"=", BINOP_ASSIGN, PREC_ASSIGN, 1}, 603130803Smarcel {"||", BINOP_LOGICAL_OR, PREC_LOGICAL_OR, 0}, 604130803Smarcel {"&&", BINOP_LOGICAL_AND, PREC_LOGICAL_AND, 0}, 605130803Smarcel {"|", BINOP_BITWISE_IOR, PREC_BITWISE_IOR, 0}, 606130803Smarcel {"^", BINOP_BITWISE_XOR, PREC_BITWISE_XOR, 0}, 607130803Smarcel {"&", BINOP_BITWISE_AND, PREC_BITWISE_AND, 0}, 608130803Smarcel {"==", BINOP_EQUAL, PREC_EQUAL, 0}, 609130803Smarcel {"!=", BINOP_NOTEQUAL, PREC_EQUAL, 0}, 610130803Smarcel {"<=", BINOP_LEQ, PREC_ORDER, 0}, 611130803Smarcel {">=", BINOP_GEQ, PREC_ORDER, 0}, 612130803Smarcel {">", BINOP_GTR, PREC_ORDER, 0}, 613130803Smarcel {"<", BINOP_LESS, PREC_ORDER, 0}, 614130803Smarcel {">>", BINOP_RSH, PREC_SHIFT, 0}, 615130803Smarcel {"<<", BINOP_LSH, PREC_SHIFT, 0}, 616130803Smarcel {"+", BINOP_ADD, PREC_ADD, 0}, 617130803Smarcel {"-", BINOP_SUB, PREC_ADD, 0}, 618130803Smarcel {"*", BINOP_MUL, PREC_MUL, 0}, 619130803Smarcel {"/", BINOP_DIV, PREC_MUL, 0}, 620130803Smarcel {"%", BINOP_REM, PREC_MUL, 0}, 621130803Smarcel {"@", BINOP_REPEAT, PREC_REPEAT, 0}, 622130803Smarcel {"-", UNOP_NEG, PREC_PREFIX, 0}, 623130803Smarcel {"!", UNOP_LOGICAL_NOT, PREC_PREFIX, 0}, 624130803Smarcel {"~", UNOP_COMPLEMENT, PREC_PREFIX, 0}, 625130803Smarcel {"*", UNOP_IND, PREC_PREFIX, 0}, 626130803Smarcel {"&", UNOP_ADDR, PREC_PREFIX, 0}, 627130803Smarcel {"sizeof ", UNOP_SIZEOF, PREC_PREFIX, 0}, 628130803Smarcel {"++", UNOP_PREINCREMENT, PREC_PREFIX, 0}, 629130803Smarcel {"--", UNOP_PREDECREMENT, PREC_PREFIX, 0}, 630130803Smarcel {NULL, OP_NULL, PREC_NULL, 0} 631130803Smarcel}; 632130803Smarcel 633130803Smarcelstruct type ** const (objc_builtin_types[]) = 634130803Smarcel{ 635130803Smarcel &builtin_type_int, 636130803Smarcel &builtin_type_long, 637130803Smarcel &builtin_type_short, 638130803Smarcel &builtin_type_char, 639130803Smarcel &builtin_type_float, 640130803Smarcel &builtin_type_double, 641130803Smarcel &builtin_type_void, 642130803Smarcel &builtin_type_long_long, 643130803Smarcel &builtin_type_signed_char, 644130803Smarcel &builtin_type_unsigned_char, 645130803Smarcel &builtin_type_unsigned_short, 646130803Smarcel &builtin_type_unsigned_int, 647130803Smarcel &builtin_type_unsigned_long, 648130803Smarcel &builtin_type_unsigned_long_long, 649130803Smarcel &builtin_type_long_double, 650130803Smarcel &builtin_type_complex, 651130803Smarcel &builtin_type_double_complex, 652130803Smarcel 0 653130803Smarcel}; 654130803Smarcel 655130803Smarcelconst struct language_defn objc_language_defn = { 656130803Smarcel "objective-c", /* Language name */ 657130803Smarcel language_objc, 658130803Smarcel objc_builtin_types, 659130803Smarcel range_check_off, 660130803Smarcel type_check_off, 661130803Smarcel case_sensitive_on, 662130803Smarcel &exp_descriptor_standard, 663130803Smarcel objc_parse, 664130803Smarcel objc_error, 665130803Smarcel objc_printchar, /* Print a character constant */ 666130803Smarcel objc_printstr, /* Function to print string constant */ 667130803Smarcel objc_emit_char, 668130803Smarcel objc_create_fundamental_type, /* Create fundamental type in this language */ 669130803Smarcel c_print_type, /* Print a type using appropriate syntax */ 670130803Smarcel c_val_print, /* Print a value using appropriate syntax */ 671130803Smarcel c_value_print, /* Print a top-level value */ 672130803Smarcel objc_skip_trampoline, /* Language specific skip_trampoline */ 673130803Smarcel value_of_this, /* value_of_this */ 674130803Smarcel basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */ 675130803Smarcel basic_lookup_transparent_type,/* lookup_transparent_type */ 676130803Smarcel objc_demangle, /* Language specific symbol demangler */ 677130803Smarcel {"", "", "", ""}, /* Binary format info */ 678130803Smarcel {"0%lo", "0", "o", ""}, /* Octal format info */ 679130803Smarcel {"%ld", "", "d", ""}, /* Decimal format info */ 680130803Smarcel {"0x%lx", "0x", "x", ""}, /* Hex format info */ 681130803Smarcel objc_op_print_tab, /* Expression operators for printing */ 682130803Smarcel 1, /* C-style arrays */ 683130803Smarcel 0, /* String lower bound */ 684130803Smarcel &builtin_type_char, /* Type of string elements */ 685130803Smarcel default_word_break_characters, 686130803Smarcel LANG_MAGIC 687130803Smarcel}; 688130803Smarcel 689130803Smarcel/* 690130803Smarcel * ObjC: 691130803Smarcel * Following functions help construct Objective-C message calls 692130803Smarcel */ 693130803Smarcel 694130803Smarcelstruct selname /* For parsing Objective-C. */ 695130803Smarcel { 696130803Smarcel struct selname *next; 697130803Smarcel char *msglist_sel; 698130803Smarcel int msglist_len; 699130803Smarcel }; 700130803Smarcel 701130803Smarcelstatic int msglist_len; 702130803Smarcelstatic struct selname *selname_chain; 703130803Smarcelstatic char *msglist_sel; 704130803Smarcel 705130803Smarcelvoid 706130803Smarcelstart_msglist(void) 707130803Smarcel{ 708130803Smarcel struct selname *new = 709130803Smarcel (struct selname *) xmalloc (sizeof (struct selname)); 710130803Smarcel 711130803Smarcel new->next = selname_chain; 712130803Smarcel new->msglist_len = msglist_len; 713130803Smarcel new->msglist_sel = msglist_sel; 714130803Smarcel msglist_len = 0; 715130803Smarcel msglist_sel = (char *)xmalloc(1); 716130803Smarcel *msglist_sel = 0; 717130803Smarcel selname_chain = new; 718130803Smarcel} 719130803Smarcel 720130803Smarcelvoid 721130803Smarceladd_msglist(struct stoken *str, int addcolon) 722130803Smarcel{ 723130803Smarcel char *s, *p; 724130803Smarcel int len, plen; 725130803Smarcel 726130803Smarcel if (str == 0) { /* Unnamed arg, or... */ 727130803Smarcel if (addcolon == 0) { /* variable number of args. */ 728130803Smarcel msglist_len++; 729130803Smarcel return; 730130803Smarcel } 731130803Smarcel p = ""; 732130803Smarcel plen = 0; 733130803Smarcel } else { 734130803Smarcel p = str->ptr; 735130803Smarcel plen = str->length; 736130803Smarcel } 737130803Smarcel len = plen + strlen(msglist_sel) + 2; 738130803Smarcel s = (char *)xmalloc(len); 739130803Smarcel strcpy(s, msglist_sel); 740130803Smarcel strncat(s, p, plen); 741130803Smarcel xfree(msglist_sel); 742130803Smarcel msglist_sel = s; 743130803Smarcel if (addcolon) { 744130803Smarcel s[len-2] = ':'; 745130803Smarcel s[len-1] = 0; 746130803Smarcel msglist_len++; 747130803Smarcel } else 748130803Smarcel s[len-2] = '\0'; 749130803Smarcel} 750130803Smarcel 751130803Smarcelint 752130803Smarcelend_msglist(void) 753130803Smarcel{ 754130803Smarcel int val = msglist_len; 755130803Smarcel struct selname *sel = selname_chain; 756130803Smarcel char *p = msglist_sel; 757130803Smarcel CORE_ADDR selid; 758130803Smarcel 759130803Smarcel selname_chain = sel->next; 760130803Smarcel msglist_len = sel->msglist_len; 761130803Smarcel msglist_sel = sel->msglist_sel; 762130803Smarcel selid = lookup_child_selector(p); 763130803Smarcel if (!selid) 764130803Smarcel error("Can't find selector \"%s\"", p); 765130803Smarcel write_exp_elt_longcst (selid); 766130803Smarcel xfree(p); 767130803Smarcel write_exp_elt_longcst (val); /* Number of args */ 768130803Smarcel xfree(sel); 769130803Smarcel 770130803Smarcel return val; 771130803Smarcel} 772130803Smarcel 773130803Smarcel/* 774130803Smarcel * Function: specialcmp (char *a, char *b) 775130803Smarcel * 776130803Smarcel * Special strcmp: treats ']' and ' ' as end-of-string. 777130803Smarcel * Used for qsorting lists of objc methods (either by class or selector). 778130803Smarcel */ 779130803Smarcel 780130803Smarcelstatic int 781130803Smarcelspecialcmp (char *a, char *b) 782130803Smarcel{ 783130803Smarcel while (*a && *a != ' ' && *a != ']' && *b && *b != ' ' && *b != ']') 784130803Smarcel { 785130803Smarcel if (*a != *b) 786130803Smarcel return *a - *b; 787130803Smarcel a++, b++; 788130803Smarcel } 789130803Smarcel if (*a && *a != ' ' && *a != ']') 790130803Smarcel return 1; /* a is longer therefore greater */ 791130803Smarcel if (*b && *b != ' ' && *b != ']') 792130803Smarcel return -1; /* a is shorter therefore lesser */ 793130803Smarcel return 0; /* a and b are identical */ 794130803Smarcel} 795130803Smarcel 796130803Smarcel/* 797130803Smarcel * Function: compare_selectors (const void *, const void *) 798130803Smarcel * 799130803Smarcel * Comparison function for use with qsort. Arguments are symbols or 800130803Smarcel * msymbols Compares selector part of objc method name alphabetically. 801130803Smarcel */ 802130803Smarcel 803130803Smarcelstatic int 804130803Smarcelcompare_selectors (const void *a, const void *b) 805130803Smarcel{ 806130803Smarcel char *aname, *bname; 807130803Smarcel 808130803Smarcel aname = SYMBOL_PRINT_NAME (*(struct symbol **) a); 809130803Smarcel bname = SYMBOL_PRINT_NAME (*(struct symbol **) b); 810130803Smarcel if (aname == NULL || bname == NULL) 811130803Smarcel error ("internal: compare_selectors(1)"); 812130803Smarcel 813130803Smarcel aname = strchr(aname, ' '); 814130803Smarcel bname = strchr(bname, ' '); 815130803Smarcel if (aname == NULL || bname == NULL) 816130803Smarcel error ("internal: compare_selectors(2)"); 817130803Smarcel 818130803Smarcel return specialcmp (aname+1, bname+1); 819130803Smarcel} 820130803Smarcel 821130803Smarcel/* 822130803Smarcel * Function: selectors_info (regexp, from_tty) 823130803Smarcel * 824130803Smarcel * Implements the "Info selectors" command. Takes an optional regexp 825130803Smarcel * arg. Lists all objective c selectors that match the regexp. Works 826130803Smarcel * by grepping thru all symbols for objective c methods. Output list 827130803Smarcel * is sorted and uniqued. 828130803Smarcel */ 829130803Smarcel 830130803Smarcelstatic void 831130803Smarcelselectors_info (char *regexp, int from_tty) 832130803Smarcel{ 833130803Smarcel struct objfile *objfile; 834130803Smarcel struct minimal_symbol *msymbol; 835130803Smarcel char *name; 836130803Smarcel char *val; 837130803Smarcel int matches = 0; 838130803Smarcel int maxlen = 0; 839130803Smarcel int ix; 840130803Smarcel char myregexp[2048]; 841130803Smarcel char asel[256]; 842130803Smarcel struct symbol **sym_arr; 843130803Smarcel int plusminus = 0; 844130803Smarcel 845130803Smarcel if (regexp == NULL) 846130803Smarcel strcpy(myregexp, ".*]"); /* Null input, match all objc methods. */ 847130803Smarcel else 848130803Smarcel { 849130803Smarcel if (*regexp == '+' || *regexp == '-') 850130803Smarcel { /* User wants only class methods or only instance methods. */ 851130803Smarcel plusminus = *regexp++; 852130803Smarcel while (*regexp == ' ' || *regexp == '\t') 853130803Smarcel regexp++; 854130803Smarcel } 855130803Smarcel if (*regexp == '\0') 856130803Smarcel strcpy(myregexp, ".*]"); 857130803Smarcel else 858130803Smarcel { 859130803Smarcel strcpy(myregexp, regexp); 860130803Smarcel if (myregexp[strlen(myregexp) - 1] == '$') /* end of selector */ 861130803Smarcel myregexp[strlen(myregexp) - 1] = ']'; /* end of method name */ 862130803Smarcel else 863130803Smarcel strcat(myregexp, ".*]"); 864130803Smarcel } 865130803Smarcel } 866130803Smarcel 867130803Smarcel if (regexp != NULL) 868130803Smarcel { 869130803Smarcel val = re_comp (myregexp); 870130803Smarcel if (val != 0) 871130803Smarcel error ("Invalid regexp (%s): %s", val, regexp); 872130803Smarcel } 873130803Smarcel 874130803Smarcel /* First time thru is JUST to get max length and count. */ 875130803Smarcel ALL_MSYMBOLS (objfile, msymbol) 876130803Smarcel { 877130803Smarcel QUIT; 878130803Smarcel name = SYMBOL_NATURAL_NAME (msymbol); 879130803Smarcel if (name && 880130803Smarcel (name[0] == '-' || name[0] == '+') && 881130803Smarcel name[1] == '[') /* Got a method name. */ 882130803Smarcel { 883130803Smarcel /* Filter for class/instance methods. */ 884130803Smarcel if (plusminus && name[0] != plusminus) 885130803Smarcel continue; 886130803Smarcel /* Find selector part. */ 887130803Smarcel name = (char *) strchr(name+2, ' '); 888130803Smarcel if (regexp == NULL || re_exec(++name) != 0) 889130803Smarcel { 890130803Smarcel char *mystart = name; 891130803Smarcel char *myend = (char *) strchr(mystart, ']'); 892130803Smarcel 893130803Smarcel if (myend && (myend - mystart > maxlen)) 894130803Smarcel maxlen = myend - mystart; /* Get longest selector. */ 895130803Smarcel matches++; 896130803Smarcel } 897130803Smarcel } 898130803Smarcel } 899130803Smarcel if (matches) 900130803Smarcel { 901130803Smarcel printf_filtered ("Selectors matching \"%s\":\n\n", 902130803Smarcel regexp ? regexp : "*"); 903130803Smarcel 904130803Smarcel sym_arr = alloca (matches * sizeof (struct symbol *)); 905130803Smarcel matches = 0; 906130803Smarcel ALL_MSYMBOLS (objfile, msymbol) 907130803Smarcel { 908130803Smarcel QUIT; 909130803Smarcel name = SYMBOL_NATURAL_NAME (msymbol); 910130803Smarcel if (name && 911130803Smarcel (name[0] == '-' || name[0] == '+') && 912130803Smarcel name[1] == '[') /* Got a method name. */ 913130803Smarcel { 914130803Smarcel /* Filter for class/instance methods. */ 915130803Smarcel if (plusminus && name[0] != plusminus) 916130803Smarcel continue; 917130803Smarcel /* Find selector part. */ 918130803Smarcel name = (char *) strchr(name+2, ' '); 919130803Smarcel if (regexp == NULL || re_exec(++name) != 0) 920130803Smarcel sym_arr[matches++] = (struct symbol *) msymbol; 921130803Smarcel } 922130803Smarcel } 923130803Smarcel 924130803Smarcel qsort (sym_arr, matches, sizeof (struct minimal_symbol *), 925130803Smarcel compare_selectors); 926130803Smarcel /* Prevent compare on first iteration. */ 927130803Smarcel asel[0] = 0; 928130803Smarcel for (ix = 0; ix < matches; ix++) /* Now do the output. */ 929130803Smarcel { 930130803Smarcel char *p = asel; 931130803Smarcel 932130803Smarcel QUIT; 933130803Smarcel name = SYMBOL_NATURAL_NAME (sym_arr[ix]); 934130803Smarcel name = strchr (name, ' ') + 1; 935130803Smarcel if (p[0] && specialcmp(name, p) == 0) 936130803Smarcel continue; /* Seen this one already (not unique). */ 937130803Smarcel 938130803Smarcel /* Copy selector part. */ 939130803Smarcel while (*name && *name != ']') 940130803Smarcel *p++ = *name++; 941130803Smarcel *p++ = '\0'; 942130803Smarcel /* Print in columns. */ 943130803Smarcel puts_filtered_tabular(asel, maxlen + 1, 0); 944130803Smarcel } 945130803Smarcel begin_line(); 946130803Smarcel } 947130803Smarcel else 948130803Smarcel printf_filtered ("No selectors matching \"%s\"\n", regexp ? regexp : "*"); 949130803Smarcel} 950130803Smarcel 951130803Smarcel/* 952130803Smarcel * Function: compare_classes (const void *, const void *) 953130803Smarcel * 954130803Smarcel * Comparison function for use with qsort. Arguments are symbols or 955130803Smarcel * msymbols Compares class part of objc method name alphabetically. 956130803Smarcel */ 957130803Smarcel 958130803Smarcelstatic int 959130803Smarcelcompare_classes (const void *a, const void *b) 960130803Smarcel{ 961130803Smarcel char *aname, *bname; 962130803Smarcel 963130803Smarcel aname = SYMBOL_PRINT_NAME (*(struct symbol **) a); 964130803Smarcel bname = SYMBOL_PRINT_NAME (*(struct symbol **) b); 965130803Smarcel if (aname == NULL || bname == NULL) 966130803Smarcel error ("internal: compare_classes(1)"); 967130803Smarcel 968130803Smarcel return specialcmp (aname+1, bname+1); 969130803Smarcel} 970130803Smarcel 971130803Smarcel/* 972130803Smarcel * Function: classes_info(regexp, from_tty) 973130803Smarcel * 974130803Smarcel * Implements the "info classes" command for objective c classes. 975130803Smarcel * Lists all objective c classes that match the optional regexp. 976130803Smarcel * Works by grepping thru the list of objective c methods. List will 977130803Smarcel * be sorted and uniqued (since one class may have many methods). 978130803Smarcel * BUGS: will not list a class that has no methods. 979130803Smarcel */ 980130803Smarcel 981130803Smarcelstatic void 982130803Smarcelclasses_info (char *regexp, int from_tty) 983130803Smarcel{ 984130803Smarcel struct objfile *objfile; 985130803Smarcel struct minimal_symbol *msymbol; 986130803Smarcel char *name; 987130803Smarcel char *val; 988130803Smarcel int matches = 0; 989130803Smarcel int maxlen = 0; 990130803Smarcel int ix; 991130803Smarcel char myregexp[2048]; 992130803Smarcel char aclass[256]; 993130803Smarcel struct symbol **sym_arr; 994130803Smarcel 995130803Smarcel if (regexp == NULL) 996130803Smarcel strcpy(myregexp, ".* "); /* Null input: match all objc classes. */ 997130803Smarcel else 998130803Smarcel { 999130803Smarcel strcpy(myregexp, regexp); 1000130803Smarcel if (myregexp[strlen(myregexp) - 1] == '$') 1001130803Smarcel /* In the method name, the end of the class name is marked by ' '. */ 1002130803Smarcel myregexp[strlen(myregexp) - 1] = ' '; 1003130803Smarcel else 1004130803Smarcel strcat(myregexp, ".* "); 1005130803Smarcel } 1006130803Smarcel 1007130803Smarcel if (regexp != NULL) 1008130803Smarcel { 1009130803Smarcel val = re_comp (myregexp); 1010130803Smarcel if (val != 0) 1011130803Smarcel error ("Invalid regexp (%s): %s", val, regexp); 1012130803Smarcel } 1013130803Smarcel 1014130803Smarcel /* First time thru is JUST to get max length and count. */ 1015130803Smarcel ALL_MSYMBOLS (objfile, msymbol) 1016130803Smarcel { 1017130803Smarcel QUIT; 1018130803Smarcel name = SYMBOL_NATURAL_NAME (msymbol); 1019130803Smarcel if (name && 1020130803Smarcel (name[0] == '-' || name[0] == '+') && 1021130803Smarcel name[1] == '[') /* Got a method name. */ 1022130803Smarcel if (regexp == NULL || re_exec(name+2) != 0) 1023130803Smarcel { 1024130803Smarcel /* Compute length of classname part. */ 1025130803Smarcel char *mystart = name + 2; 1026130803Smarcel char *myend = (char *) strchr(mystart, ' '); 1027130803Smarcel 1028130803Smarcel if (myend && (myend - mystart > maxlen)) 1029130803Smarcel maxlen = myend - mystart; 1030130803Smarcel matches++; 1031130803Smarcel } 1032130803Smarcel } 1033130803Smarcel if (matches) 1034130803Smarcel { 1035130803Smarcel printf_filtered ("Classes matching \"%s\":\n\n", 1036130803Smarcel regexp ? regexp : "*"); 1037130803Smarcel sym_arr = alloca (matches * sizeof (struct symbol *)); 1038130803Smarcel matches = 0; 1039130803Smarcel ALL_MSYMBOLS (objfile, msymbol) 1040130803Smarcel { 1041130803Smarcel QUIT; 1042130803Smarcel name = SYMBOL_NATURAL_NAME (msymbol); 1043130803Smarcel if (name && 1044130803Smarcel (name[0] == '-' || name[0] == '+') && 1045130803Smarcel name[1] == '[') /* Got a method name. */ 1046130803Smarcel if (regexp == NULL || re_exec(name+2) != 0) 1047130803Smarcel sym_arr[matches++] = (struct symbol *) msymbol; 1048130803Smarcel } 1049130803Smarcel 1050130803Smarcel qsort (sym_arr, matches, sizeof (struct minimal_symbol *), 1051130803Smarcel compare_classes); 1052130803Smarcel /* Prevent compare on first iteration. */ 1053130803Smarcel aclass[0] = 0; 1054130803Smarcel for (ix = 0; ix < matches; ix++) /* Now do the output. */ 1055130803Smarcel { 1056130803Smarcel char *p = aclass; 1057130803Smarcel 1058130803Smarcel QUIT; 1059130803Smarcel name = SYMBOL_NATURAL_NAME (sym_arr[ix]); 1060130803Smarcel name += 2; 1061130803Smarcel if (p[0] && specialcmp(name, p) == 0) 1062130803Smarcel continue; /* Seen this one already (not unique). */ 1063130803Smarcel 1064130803Smarcel /* Copy class part of method name. */ 1065130803Smarcel while (*name && *name != ' ') 1066130803Smarcel *p++ = *name++; 1067130803Smarcel *p++ = '\0'; 1068130803Smarcel /* Print in columns. */ 1069130803Smarcel puts_filtered_tabular(aclass, maxlen + 1, 0); 1070130803Smarcel } 1071130803Smarcel begin_line(); 1072130803Smarcel } 1073130803Smarcel else 1074130803Smarcel printf_filtered ("No classes matching \"%s\"\n", regexp ? regexp : "*"); 1075130803Smarcel} 1076130803Smarcel 1077130803Smarcel/* 1078130803Smarcel * Function: find_imps (char *selector, struct symbol **sym_arr) 1079130803Smarcel * 1080130803Smarcel * Input: a string representing a selector 1081130803Smarcel * a pointer to an array of symbol pointers 1082130803Smarcel * possibly a pointer to a symbol found by the caller. 1083130803Smarcel * 1084130803Smarcel * Output: number of methods that implement that selector. Side 1085130803Smarcel * effects: The array of symbol pointers is filled with matching syms. 1086130803Smarcel * 1087130803Smarcel * By analogy with function "find_methods" (symtab.c), builds a list 1088130803Smarcel * of symbols matching the ambiguous input, so that "decode_line_2" 1089130803Smarcel * (symtab.c) can list them and ask the user to choose one or more. 1090130803Smarcel * In this case the matches are objective c methods 1091130803Smarcel * ("implementations") matching an objective c selector. 1092130803Smarcel * 1093130803Smarcel * Note that it is possible for a normal (c-style) function to have 1094130803Smarcel * the same name as an objective c selector. To prevent the selector 1095130803Smarcel * from eclipsing the function, we allow the caller (decode_line_1) to 1096130803Smarcel * search for such a function first, and if it finds one, pass it in 1097130803Smarcel * to us. We will then integrate it into the list. We also search 1098130803Smarcel * for one here, among the minsyms. 1099130803Smarcel * 1100130803Smarcel * NOTE: if NUM_DEBUGGABLE is non-zero, the sym_arr will be divided 1101130803Smarcel * into two parts: debuggable (struct symbol) syms, and 1102130803Smarcel * non_debuggable (struct minimal_symbol) syms. The debuggable 1103130803Smarcel * ones will come first, before NUM_DEBUGGABLE (which will thus 1104130803Smarcel * be the index of the first non-debuggable one). 1105130803Smarcel */ 1106130803Smarcel 1107130803Smarcel/* 1108130803Smarcel * Function: total_number_of_imps (char *selector); 1109130803Smarcel * 1110130803Smarcel * Input: a string representing a selector 1111130803Smarcel * Output: number of methods that implement that selector. 1112130803Smarcel * 1113130803Smarcel * By analogy with function "total_number_of_methods", this allows 1114130803Smarcel * decode_line_1 (symtab.c) to detect if there are objective c methods 1115130803Smarcel * matching the input, and to allocate an array of pointers to them 1116130803Smarcel * which can be manipulated by "decode_line_2" (also in symtab.c). 1117130803Smarcel */ 1118130803Smarcel 1119130803Smarcelchar * 1120130803Smarcelparse_selector (char *method, char **selector) 1121130803Smarcel{ 1122130803Smarcel char *s1 = NULL; 1123130803Smarcel char *s2 = NULL; 1124130803Smarcel int found_quote = 0; 1125130803Smarcel 1126130803Smarcel char *nselector = NULL; 1127130803Smarcel 1128130803Smarcel gdb_assert (selector != NULL); 1129130803Smarcel 1130130803Smarcel s1 = method; 1131130803Smarcel 1132130803Smarcel while (isspace (*s1)) 1133130803Smarcel s1++; 1134130803Smarcel if (*s1 == '\'') 1135130803Smarcel { 1136130803Smarcel found_quote = 1; 1137130803Smarcel s1++; 1138130803Smarcel } 1139130803Smarcel while (isspace (*s1)) 1140130803Smarcel s1++; 1141130803Smarcel 1142130803Smarcel nselector = s1; 1143130803Smarcel s2 = s1; 1144130803Smarcel 1145130803Smarcel for (;;) { 1146130803Smarcel if (isalnum (*s2) || (*s2 == '_') || (*s2 == ':')) 1147130803Smarcel *s1++ = *s2; 1148130803Smarcel else if (isspace (*s2)) 1149130803Smarcel ; 1150130803Smarcel else if ((*s2 == '\0') || (*s2 == '\'')) 1151130803Smarcel break; 1152130803Smarcel else 1153130803Smarcel return NULL; 1154130803Smarcel s2++; 1155130803Smarcel } 1156130803Smarcel *s1++ = '\0'; 1157130803Smarcel 1158130803Smarcel while (isspace (*s2)) 1159130803Smarcel s2++; 1160130803Smarcel if (found_quote) 1161130803Smarcel { 1162130803Smarcel if (*s2 == '\'') 1163130803Smarcel s2++; 1164130803Smarcel while (isspace (*s2)) 1165130803Smarcel s2++; 1166130803Smarcel } 1167130803Smarcel 1168130803Smarcel if (selector != NULL) 1169130803Smarcel *selector = nselector; 1170130803Smarcel 1171130803Smarcel return s2; 1172130803Smarcel} 1173130803Smarcel 1174130803Smarcelchar * 1175130803Smarcelparse_method (char *method, char *type, char **class, 1176130803Smarcel char **category, char **selector) 1177130803Smarcel{ 1178130803Smarcel char *s1 = NULL; 1179130803Smarcel char *s2 = NULL; 1180130803Smarcel int found_quote = 0; 1181130803Smarcel 1182130803Smarcel char ntype = '\0'; 1183130803Smarcel char *nclass = NULL; 1184130803Smarcel char *ncategory = NULL; 1185130803Smarcel char *nselector = NULL; 1186130803Smarcel 1187130803Smarcel gdb_assert (type != NULL); 1188130803Smarcel gdb_assert (class != NULL); 1189130803Smarcel gdb_assert (category != NULL); 1190130803Smarcel gdb_assert (selector != NULL); 1191130803Smarcel 1192130803Smarcel s1 = method; 1193130803Smarcel 1194130803Smarcel while (isspace (*s1)) 1195130803Smarcel s1++; 1196130803Smarcel if (*s1 == '\'') 1197130803Smarcel { 1198130803Smarcel found_quote = 1; 1199130803Smarcel s1++; 1200130803Smarcel } 1201130803Smarcel while (isspace (*s1)) 1202130803Smarcel s1++; 1203130803Smarcel 1204130803Smarcel if ((s1[0] == '+') || (s1[0] == '-')) 1205130803Smarcel ntype = *s1++; 1206130803Smarcel 1207130803Smarcel while (isspace (*s1)) 1208130803Smarcel s1++; 1209130803Smarcel 1210130803Smarcel if (*s1 != '[') 1211130803Smarcel return NULL; 1212130803Smarcel s1++; 1213130803Smarcel 1214130803Smarcel nclass = s1; 1215130803Smarcel while (isalnum (*s1) || (*s1 == '_')) 1216130803Smarcel s1++; 1217130803Smarcel 1218130803Smarcel s2 = s1; 1219130803Smarcel while (isspace (*s2)) 1220130803Smarcel s2++; 1221130803Smarcel 1222130803Smarcel if (*s2 == '(') 1223130803Smarcel { 1224130803Smarcel s2++; 1225130803Smarcel while (isspace (*s2)) 1226130803Smarcel s2++; 1227130803Smarcel ncategory = s2; 1228130803Smarcel while (isalnum (*s2) || (*s2 == '_')) 1229130803Smarcel s2++; 1230130803Smarcel *s2++ = '\0'; 1231130803Smarcel } 1232130803Smarcel 1233130803Smarcel /* Truncate the class name now that we're not using the open paren. */ 1234130803Smarcel *s1++ = '\0'; 1235130803Smarcel 1236130803Smarcel nselector = s2; 1237130803Smarcel s1 = s2; 1238130803Smarcel 1239130803Smarcel for (;;) { 1240130803Smarcel if (isalnum (*s2) || (*s2 == '_') || (*s2 == ':')) 1241130803Smarcel *s1++ = *s2; 1242130803Smarcel else if (isspace (*s2)) 1243130803Smarcel ; 1244130803Smarcel else if (*s2 == ']') 1245130803Smarcel break; 1246130803Smarcel else 1247130803Smarcel return NULL; 1248130803Smarcel s2++; 1249130803Smarcel } 1250130803Smarcel *s1++ = '\0'; 1251130803Smarcel s2++; 1252130803Smarcel 1253130803Smarcel while (isspace (*s2)) 1254130803Smarcel s2++; 1255130803Smarcel if (found_quote) 1256130803Smarcel { 1257130803Smarcel if (*s2 != '\'') 1258130803Smarcel return NULL; 1259130803Smarcel s2++; 1260130803Smarcel while (isspace (*s2)) 1261130803Smarcel s2++; 1262130803Smarcel } 1263130803Smarcel 1264130803Smarcel if (type != NULL) 1265130803Smarcel *type = ntype; 1266130803Smarcel if (class != NULL) 1267130803Smarcel *class = nclass; 1268130803Smarcel if (category != NULL) 1269130803Smarcel *category = ncategory; 1270130803Smarcel if (selector != NULL) 1271130803Smarcel *selector = nselector; 1272130803Smarcel 1273130803Smarcel return s2; 1274130803Smarcel} 1275130803Smarcel 1276130803Smarcelstatic void 1277130803Smarcelfind_methods (struct symtab *symtab, char type, 1278130803Smarcel const char *class, const char *category, 1279130803Smarcel const char *selector, struct symbol **syms, 1280130803Smarcel unsigned int *nsym, unsigned int *ndebug) 1281130803Smarcel{ 1282130803Smarcel struct objfile *objfile = NULL; 1283130803Smarcel struct minimal_symbol *msymbol = NULL; 1284130803Smarcel struct block *block = NULL; 1285130803Smarcel struct symbol *sym = NULL; 1286130803Smarcel 1287130803Smarcel char *symname = NULL; 1288130803Smarcel 1289130803Smarcel char ntype = '\0'; 1290130803Smarcel char *nclass = NULL; 1291130803Smarcel char *ncategory = NULL; 1292130803Smarcel char *nselector = NULL; 1293130803Smarcel 1294130803Smarcel unsigned int csym = 0; 1295130803Smarcel unsigned int cdebug = 0; 1296130803Smarcel 1297130803Smarcel static char *tmp = NULL; 1298130803Smarcel static unsigned int tmplen = 0; 1299130803Smarcel 1300130803Smarcel gdb_assert (nsym != NULL); 1301130803Smarcel gdb_assert (ndebug != NULL); 1302130803Smarcel 1303130803Smarcel if (symtab) 1304130803Smarcel block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (symtab), STATIC_BLOCK); 1305130803Smarcel 1306130803Smarcel ALL_MSYMBOLS (objfile, msymbol) 1307130803Smarcel { 1308130803Smarcel QUIT; 1309130803Smarcel 1310130803Smarcel if ((msymbol->type != mst_text) && (msymbol->type != mst_file_text)) 1311130803Smarcel /* Not a function or method. */ 1312130803Smarcel continue; 1313130803Smarcel 1314130803Smarcel if (symtab) 1315130803Smarcel if ((SYMBOL_VALUE_ADDRESS (msymbol) < BLOCK_START (block)) || 1316130803Smarcel (SYMBOL_VALUE_ADDRESS (msymbol) >= BLOCK_END (block))) 1317130803Smarcel /* Not in the specified symtab. */ 1318130803Smarcel continue; 1319130803Smarcel 1320130803Smarcel symname = SYMBOL_NATURAL_NAME (msymbol); 1321130803Smarcel if (symname == NULL) 1322130803Smarcel continue; 1323130803Smarcel 1324130803Smarcel if ((symname[0] != '-' && symname[0] != '+') || (symname[1] != '[')) 1325130803Smarcel /* Not a method name. */ 1326130803Smarcel continue; 1327130803Smarcel 1328130803Smarcel while ((strlen (symname) + 1) >= tmplen) 1329130803Smarcel { 1330130803Smarcel tmplen = (tmplen == 0) ? 1024 : tmplen * 2; 1331130803Smarcel tmp = xrealloc (tmp, tmplen); 1332130803Smarcel } 1333130803Smarcel strcpy (tmp, symname); 1334130803Smarcel 1335130803Smarcel if (parse_method (tmp, &ntype, &nclass, &ncategory, &nselector) == NULL) 1336130803Smarcel continue; 1337130803Smarcel 1338130803Smarcel if ((type != '\0') && (ntype != type)) 1339130803Smarcel continue; 1340130803Smarcel 1341130803Smarcel if ((class != NULL) 1342130803Smarcel && ((nclass == NULL) || (strcmp (class, nclass) != 0))) 1343130803Smarcel continue; 1344130803Smarcel 1345130803Smarcel if ((category != NULL) && 1346130803Smarcel ((ncategory == NULL) || (strcmp (category, ncategory) != 0))) 1347130803Smarcel continue; 1348130803Smarcel 1349130803Smarcel if ((selector != NULL) && 1350130803Smarcel ((nselector == NULL) || (strcmp (selector, nselector) != 0))) 1351130803Smarcel continue; 1352130803Smarcel 1353130803Smarcel sym = find_pc_function (SYMBOL_VALUE_ADDRESS (msymbol)); 1354130803Smarcel if (sym != NULL) 1355130803Smarcel { 1356130803Smarcel const char *newsymname = SYMBOL_NATURAL_NAME (sym); 1357130803Smarcel 1358130803Smarcel if (strcmp (symname, newsymname) == 0) 1359130803Smarcel { 1360130803Smarcel /* Found a high-level method sym: swap it into the 1361130803Smarcel lower part of sym_arr (below num_debuggable). */ 1362130803Smarcel if (syms != NULL) 1363130803Smarcel { 1364130803Smarcel syms[csym] = syms[cdebug]; 1365130803Smarcel syms[cdebug] = sym; 1366130803Smarcel } 1367130803Smarcel csym++; 1368130803Smarcel cdebug++; 1369130803Smarcel } 1370130803Smarcel else 1371130803Smarcel { 1372130803Smarcel warning ( 1373130803Smarcel"debugging symbol \"%s\" does not match minimal symbol (\"%s\"); ignoring", 1374130803Smarcel newsymname, symname); 1375130803Smarcel if (syms != NULL) 1376130803Smarcel syms[csym] = (struct symbol *) msymbol; 1377130803Smarcel csym++; 1378130803Smarcel } 1379130803Smarcel } 1380130803Smarcel else 1381130803Smarcel { 1382130803Smarcel /* Found a non-debuggable method symbol. */ 1383130803Smarcel if (syms != NULL) 1384130803Smarcel syms[csym] = (struct symbol *) msymbol; 1385130803Smarcel csym++; 1386130803Smarcel } 1387130803Smarcel } 1388130803Smarcel 1389130803Smarcel if (nsym != NULL) 1390130803Smarcel *nsym = csym; 1391130803Smarcel if (ndebug != NULL) 1392130803Smarcel *ndebug = cdebug; 1393130803Smarcel} 1394130803Smarcel 1395130803Smarcelchar *find_imps (struct symtab *symtab, struct block *block, 1396130803Smarcel char *method, struct symbol **syms, 1397130803Smarcel unsigned int *nsym, unsigned int *ndebug) 1398130803Smarcel{ 1399130803Smarcel char type = '\0'; 1400130803Smarcel char *class = NULL; 1401130803Smarcel char *category = NULL; 1402130803Smarcel char *selector = NULL; 1403130803Smarcel 1404130803Smarcel unsigned int csym = 0; 1405130803Smarcel unsigned int cdebug = 0; 1406130803Smarcel 1407130803Smarcel unsigned int ncsym = 0; 1408130803Smarcel unsigned int ncdebug = 0; 1409130803Smarcel 1410130803Smarcel char *buf = NULL; 1411130803Smarcel char *tmp = NULL; 1412130803Smarcel 1413130803Smarcel gdb_assert (nsym != NULL); 1414130803Smarcel gdb_assert (ndebug != NULL); 1415130803Smarcel 1416130803Smarcel if (nsym != NULL) 1417130803Smarcel *nsym = 0; 1418130803Smarcel if (ndebug != NULL) 1419130803Smarcel *ndebug = 0; 1420130803Smarcel 1421130803Smarcel buf = (char *) alloca (strlen (method) + 1); 1422130803Smarcel strcpy (buf, method); 1423130803Smarcel tmp = parse_method (buf, &type, &class, &category, &selector); 1424130803Smarcel 1425130803Smarcel if (tmp == NULL) { 1426130803Smarcel 1427130803Smarcel struct symbol *sym = NULL; 1428130803Smarcel struct minimal_symbol *msym = NULL; 1429130803Smarcel 1430130803Smarcel strcpy (buf, method); 1431130803Smarcel tmp = parse_selector (buf, &selector); 1432130803Smarcel 1433130803Smarcel if (tmp == NULL) 1434130803Smarcel return NULL; 1435130803Smarcel 1436130803Smarcel sym = lookup_symbol (selector, block, VAR_DOMAIN, 0, NULL); 1437130803Smarcel if (sym != NULL) 1438130803Smarcel { 1439130803Smarcel if (syms) 1440130803Smarcel syms[csym] = sym; 1441130803Smarcel csym++; 1442130803Smarcel cdebug++; 1443130803Smarcel } 1444130803Smarcel 1445130803Smarcel if (sym == NULL) 1446130803Smarcel msym = lookup_minimal_symbol (selector, 0, 0); 1447130803Smarcel 1448130803Smarcel if (msym != NULL) 1449130803Smarcel { 1450130803Smarcel if (syms) 1451130803Smarcel syms[csym] = (struct symbol *)msym; 1452130803Smarcel csym++; 1453130803Smarcel } 1454130803Smarcel } 1455130803Smarcel 1456130803Smarcel if (syms != NULL) 1457130803Smarcel find_methods (symtab, type, class, category, selector, 1458130803Smarcel syms + csym, &ncsym, &ncdebug); 1459130803Smarcel else 1460130803Smarcel find_methods (symtab, type, class, category, selector, 1461130803Smarcel NULL, &ncsym, &ncdebug); 1462130803Smarcel 1463130803Smarcel /* If we didn't find any methods, just return. */ 1464130803Smarcel if (ncsym == 0 && ncdebug == 0) 1465130803Smarcel return method; 1466130803Smarcel 1467130803Smarcel /* Take debug symbols from the second batch of symbols and swap them 1468130803Smarcel * with debug symbols from the first batch. Repeat until either the 1469130803Smarcel * second section is out of debug symbols or the first section is 1470130803Smarcel * full of debug symbols. Either way we have all debug symbols 1471130803Smarcel * packed to the beginning of the buffer. 1472130803Smarcel */ 1473130803Smarcel 1474130803Smarcel if (syms != NULL) 1475130803Smarcel { 1476130803Smarcel while ((cdebug < csym) && (ncdebug > 0)) 1477130803Smarcel { 1478130803Smarcel struct symbol *s = NULL; 1479130803Smarcel /* First non-debugging symbol. */ 1480130803Smarcel unsigned int i = cdebug; 1481130803Smarcel /* Last of second batch of debug symbols. */ 1482130803Smarcel unsigned int j = csym + ncdebug - 1; 1483130803Smarcel 1484130803Smarcel s = syms[j]; 1485130803Smarcel syms[j] = syms[i]; 1486130803Smarcel syms[i] = s; 1487130803Smarcel 1488130803Smarcel /* We've moved a symbol from the second debug section to the 1489130803Smarcel first one. */ 1490130803Smarcel cdebug++; 1491130803Smarcel ncdebug--; 1492130803Smarcel } 1493130803Smarcel } 1494130803Smarcel 1495130803Smarcel csym += ncsym; 1496130803Smarcel cdebug += ncdebug; 1497130803Smarcel 1498130803Smarcel if (nsym != NULL) 1499130803Smarcel *nsym = csym; 1500130803Smarcel if (ndebug != NULL) 1501130803Smarcel *ndebug = cdebug; 1502130803Smarcel 1503130803Smarcel if (syms == NULL) 1504130803Smarcel return method + (tmp - buf); 1505130803Smarcel 1506130803Smarcel if (csym > 1) 1507130803Smarcel { 1508130803Smarcel /* Sort debuggable symbols. */ 1509130803Smarcel if (cdebug > 1) 1510130803Smarcel qsort (syms, cdebug, sizeof (struct minimal_symbol *), 1511130803Smarcel compare_classes); 1512130803Smarcel 1513130803Smarcel /* Sort minimal_symbols. */ 1514130803Smarcel if ((csym - cdebug) > 1) 1515130803Smarcel qsort (&syms[cdebug], csym - cdebug, 1516130803Smarcel sizeof (struct minimal_symbol *), compare_classes); 1517130803Smarcel } 1518130803Smarcel /* Terminate the sym_arr list. */ 1519130803Smarcel syms[csym] = 0; 1520130803Smarcel 1521130803Smarcel return method + (tmp - buf); 1522130803Smarcel} 1523130803Smarcel 1524130803Smarcelstatic void 1525130803Smarcelprint_object_command (char *args, int from_tty) 1526130803Smarcel{ 1527130803Smarcel struct value *object, *function, *description; 1528130803Smarcel CORE_ADDR string_addr, object_addr; 1529130803Smarcel int i = 0; 1530130803Smarcel char c = -1; 1531130803Smarcel 1532130803Smarcel if (!args || !*args) 1533130803Smarcel error ( 1534130803Smarcel"The 'print-object' command requires an argument (an Objective-C object)"); 1535130803Smarcel 1536130803Smarcel { 1537130803Smarcel struct expression *expr = parse_expression (args); 1538130803Smarcel struct cleanup *old_chain = 1539130803Smarcel make_cleanup (free_current_contents, &expr); 1540130803Smarcel int pc = 0; 1541130803Smarcel 1542130803Smarcel object = expr->language_defn->la_exp_desc->evaluate_exp 1543130803Smarcel (builtin_type_void_data_ptr, expr, &pc, EVAL_NORMAL); 1544130803Smarcel do_cleanups (old_chain); 1545130803Smarcel } 1546130803Smarcel 1547130803Smarcel /* Validate the address for sanity. */ 1548130803Smarcel object_addr = value_as_long (object); 1549130803Smarcel read_memory (object_addr, &c, 1); 1550130803Smarcel 1551130803Smarcel function = find_function_in_inferior ("_NSPrintForDebugger"); 1552130803Smarcel if (function == NULL) 1553130803Smarcel error ("Unable to locate _NSPrintForDebugger in child process"); 1554130803Smarcel 1555130803Smarcel description = call_function_by_hand (function, 1, &object); 1556130803Smarcel 1557130803Smarcel string_addr = value_as_long (description); 1558130803Smarcel if (string_addr == 0) 1559130803Smarcel error ("object returns null description"); 1560130803Smarcel 1561130803Smarcel read_memory (string_addr + i++, &c, 1); 1562130803Smarcel if (c != '\0') 1563130803Smarcel do 1564130803Smarcel { /* Read and print characters up to EOS. */ 1565130803Smarcel QUIT; 1566130803Smarcel printf_filtered ("%c", c); 1567130803Smarcel read_memory (string_addr + i++, &c, 1); 1568130803Smarcel } while (c != 0); 1569130803Smarcel else 1570130803Smarcel printf_filtered("<object returns empty description>"); 1571130803Smarcel printf_filtered ("\n"); 1572130803Smarcel} 1573130803Smarcel 1574130803Smarcel/* The data structure 'methcalls' is used to detect method calls (thru 1575130803Smarcel * ObjC runtime lib functions objc_msgSend, objc_msgSendSuper, etc.), 1576130803Smarcel * and ultimately find the method being called. 1577130803Smarcel */ 1578130803Smarcel 1579130803Smarcelstruct objc_methcall { 1580130803Smarcel char *name; 1581130803Smarcel /* Return instance method to be called. */ 1582130803Smarcel int (*stop_at) (CORE_ADDR, CORE_ADDR *); 1583130803Smarcel /* Start of pc range corresponding to method invocation. */ 1584130803Smarcel CORE_ADDR begin; 1585130803Smarcel /* End of pc range corresponding to method invocation. */ 1586130803Smarcel CORE_ADDR end; 1587130803Smarcel}; 1588130803Smarcel 1589130803Smarcelstatic int resolve_msgsend (CORE_ADDR pc, CORE_ADDR *new_pc); 1590130803Smarcelstatic int resolve_msgsend_stret (CORE_ADDR pc, CORE_ADDR *new_pc); 1591130803Smarcelstatic int resolve_msgsend_super (CORE_ADDR pc, CORE_ADDR *new_pc); 1592130803Smarcelstatic int resolve_msgsend_super_stret (CORE_ADDR pc, CORE_ADDR *new_pc); 1593130803Smarcel 1594130803Smarcelstatic struct objc_methcall methcalls[] = { 1595130803Smarcel { "_objc_msgSend", resolve_msgsend, 0, 0}, 1596130803Smarcel { "_objc_msgSend_stret", resolve_msgsend_stret, 0, 0}, 1597130803Smarcel { "_objc_msgSendSuper", resolve_msgsend_super, 0, 0}, 1598130803Smarcel { "_objc_msgSendSuper_stret", resolve_msgsend_super_stret, 0, 0}, 1599130803Smarcel { "_objc_getClass", NULL, 0, 0}, 1600130803Smarcel { "_objc_getMetaClass", NULL, 0, 0} 1601130803Smarcel}; 1602130803Smarcel 1603130803Smarcel#define nmethcalls (sizeof (methcalls) / sizeof (methcalls[0])) 1604130803Smarcel 1605130803Smarcel/* The following function, "find_objc_msgsend", fills in the data 1606130803Smarcel * structure "objc_msgs" by finding the addresses of each of the 1607130803Smarcel * (currently four) functions that it holds (of which objc_msgSend is 1608130803Smarcel * the first). This must be called each time symbols are loaded, in 1609130803Smarcel * case the functions have moved for some reason. 1610130803Smarcel */ 1611130803Smarcel 1612130803Smarcelstatic void 1613130803Smarcelfind_objc_msgsend (void) 1614130803Smarcel{ 1615130803Smarcel unsigned int i; 1616130803Smarcel for (i = 0; i < nmethcalls; i++) { 1617130803Smarcel 1618130803Smarcel struct minimal_symbol *func; 1619130803Smarcel 1620130803Smarcel /* Try both with and without underscore. */ 1621130803Smarcel func = lookup_minimal_symbol (methcalls[i].name, NULL, NULL); 1622130803Smarcel if ((func == NULL) && (methcalls[i].name[0] == '_')) { 1623130803Smarcel func = lookup_minimal_symbol (methcalls[i].name + 1, NULL, NULL); 1624130803Smarcel } 1625130803Smarcel if (func == NULL) { 1626130803Smarcel methcalls[i].begin = 0; 1627130803Smarcel methcalls[i].end = 0; 1628130803Smarcel continue; 1629130803Smarcel } 1630130803Smarcel 1631130803Smarcel methcalls[i].begin = SYMBOL_VALUE_ADDRESS (func); 1632130803Smarcel do { 1633130803Smarcel methcalls[i].end = SYMBOL_VALUE_ADDRESS (++func); 1634130803Smarcel } while (methcalls[i].begin == methcalls[i].end); 1635130803Smarcel } 1636130803Smarcel} 1637130803Smarcel 1638130803Smarcel/* find_objc_msgcall (replaces pc_off_limits) 1639130803Smarcel * 1640130803Smarcel * ALL that this function now does is to determine whether the input 1641130803Smarcel * address ("pc") is the address of one of the Objective-C message 1642130803Smarcel * dispatch functions (mainly objc_msgSend or objc_msgSendSuper), and 1643130803Smarcel * if so, it returns the address of the method that will be called. 1644130803Smarcel * 1645130803Smarcel * The old function "pc_off_limits" used to do a lot of other things 1646130803Smarcel * in addition, such as detecting shared library jump stubs and 1647130803Smarcel * returning the address of the shlib function that would be called. 1648130803Smarcel * That functionality has been moved into the SKIP_TRAMPOLINE_CODE and 1649130803Smarcel * IN_SOLIB_TRAMPOLINE macros, which are resolved in the target- 1650130803Smarcel * dependent modules. 1651130803Smarcel */ 1652130803Smarcel 1653130803Smarcelstruct objc_submethod_helper_data { 1654130803Smarcel int (*f) (CORE_ADDR, CORE_ADDR *); 1655130803Smarcel CORE_ADDR pc; 1656130803Smarcel CORE_ADDR *new_pc; 1657130803Smarcel}; 1658130803Smarcel 1659130803Smarcelstatic int 1660130803Smarcelfind_objc_msgcall_submethod_helper (void * arg) 1661130803Smarcel{ 1662130803Smarcel struct objc_submethod_helper_data *s = 1663130803Smarcel (struct objc_submethod_helper_data *) arg; 1664130803Smarcel 1665130803Smarcel if (s->f (s->pc, s->new_pc) == 0) 1666130803Smarcel return 1; 1667130803Smarcel else 1668130803Smarcel return 0; 1669130803Smarcel} 1670130803Smarcel 1671130803Smarcelstatic int 1672130803Smarcelfind_objc_msgcall_submethod (int (*f) (CORE_ADDR, CORE_ADDR *), 1673130803Smarcel CORE_ADDR pc, 1674130803Smarcel CORE_ADDR *new_pc) 1675130803Smarcel{ 1676130803Smarcel struct objc_submethod_helper_data s; 1677130803Smarcel 1678130803Smarcel s.f = f; 1679130803Smarcel s.pc = pc; 1680130803Smarcel s.new_pc = new_pc; 1681130803Smarcel 1682130803Smarcel if (catch_errors (find_objc_msgcall_submethod_helper, 1683130803Smarcel (void *) &s, 1684130803Smarcel "Unable to determine target of Objective-C method call (ignoring):\n", 1685130803Smarcel RETURN_MASK_ALL) == 0) 1686130803Smarcel return 1; 1687130803Smarcel else 1688130803Smarcel return 0; 1689130803Smarcel} 1690130803Smarcel 1691130803Smarcelint 1692130803Smarcelfind_objc_msgcall (CORE_ADDR pc, CORE_ADDR *new_pc) 1693130803Smarcel{ 1694130803Smarcel unsigned int i; 1695130803Smarcel 1696130803Smarcel find_objc_msgsend (); 1697130803Smarcel if (new_pc != NULL) 1698130803Smarcel { 1699130803Smarcel *new_pc = 0; 1700130803Smarcel } 1701130803Smarcel 1702130803Smarcel for (i = 0; i < nmethcalls; i++) 1703130803Smarcel if ((pc >= methcalls[i].begin) && (pc < methcalls[i].end)) 1704130803Smarcel { 1705130803Smarcel if (methcalls[i].stop_at != NULL) 1706130803Smarcel return find_objc_msgcall_submethod (methcalls[i].stop_at, 1707130803Smarcel pc, new_pc); 1708130803Smarcel else 1709130803Smarcel return 0; 1710130803Smarcel } 1711130803Smarcel 1712130803Smarcel return 0; 1713130803Smarcel} 1714130803Smarcel 1715130803Smarcelextern initialize_file_ftype _initialize_objc_language; /* -Wmissing-prototypes */ 1716130803Smarcel 1717130803Smarcelvoid 1718130803Smarcel_initialize_objc_language (void) 1719130803Smarcel{ 1720130803Smarcel add_language (&objc_language_defn); 1721130803Smarcel add_info ("selectors", selectors_info, /* INFO SELECTORS command. */ 1722130803Smarcel "All Objective-C selectors, or those matching REGEXP."); 1723130803Smarcel add_info ("classes", classes_info, /* INFO CLASSES command. */ 1724130803Smarcel "All Objective-C classes, or those matching REGEXP."); 1725130803Smarcel add_com ("print-object", class_vars, print_object_command, 1726130803Smarcel "Ask an Objective-C object to print itself."); 1727130803Smarcel add_com_alias ("po", "print-object", class_vars, 1); 1728130803Smarcel} 1729130803Smarcel 1730130803Smarcelstatic void 1731130803Smarcelread_objc_method (CORE_ADDR addr, struct objc_method *method) 1732130803Smarcel{ 1733130803Smarcel method->name = read_memory_unsigned_integer (addr + 0, 4); 1734130803Smarcel method->types = read_memory_unsigned_integer (addr + 4, 4); 1735130803Smarcel method->imp = read_memory_unsigned_integer (addr + 8, 4); 1736130803Smarcel} 1737130803Smarcel 1738130803Smarcelstatic 1739130803Smarcelunsigned long read_objc_methlist_nmethods (CORE_ADDR addr) 1740130803Smarcel{ 1741130803Smarcel return read_memory_unsigned_integer (addr + 4, 4); 1742130803Smarcel} 1743130803Smarcel 1744130803Smarcelstatic void 1745130803Smarcelread_objc_methlist_method (CORE_ADDR addr, unsigned long num, 1746130803Smarcel struct objc_method *method) 1747130803Smarcel{ 1748130803Smarcel gdb_assert (num < read_objc_methlist_nmethods (addr)); 1749130803Smarcel read_objc_method (addr + 8 + (12 * num), method); 1750130803Smarcel} 1751130803Smarcel 1752130803Smarcelstatic void 1753130803Smarcelread_objc_object (CORE_ADDR addr, struct objc_object *object) 1754130803Smarcel{ 1755130803Smarcel object->isa = read_memory_unsigned_integer (addr, 4); 1756130803Smarcel} 1757130803Smarcel 1758130803Smarcelstatic void 1759130803Smarcelread_objc_super (CORE_ADDR addr, struct objc_super *super) 1760130803Smarcel{ 1761130803Smarcel super->receiver = read_memory_unsigned_integer (addr, 4); 1762130803Smarcel super->class = read_memory_unsigned_integer (addr + 4, 4); 1763130803Smarcel}; 1764130803Smarcel 1765130803Smarcelstatic void 1766130803Smarcelread_objc_class (CORE_ADDR addr, struct objc_class *class) 1767130803Smarcel{ 1768130803Smarcel class->isa = read_memory_unsigned_integer (addr, 4); 1769130803Smarcel class->super_class = read_memory_unsigned_integer (addr + 4, 4); 1770130803Smarcel class->name = read_memory_unsigned_integer (addr + 8, 4); 1771130803Smarcel class->version = read_memory_unsigned_integer (addr + 12, 4); 1772130803Smarcel class->info = read_memory_unsigned_integer (addr + 16, 4); 1773130803Smarcel class->instance_size = read_memory_unsigned_integer (addr + 18, 4); 1774130803Smarcel class->ivars = read_memory_unsigned_integer (addr + 24, 4); 1775130803Smarcel class->methods = read_memory_unsigned_integer (addr + 28, 4); 1776130803Smarcel class->cache = read_memory_unsigned_integer (addr + 32, 4); 1777130803Smarcel class->protocols = read_memory_unsigned_integer (addr + 36, 4); 1778130803Smarcel} 1779130803Smarcel 1780130803Smarcelstatic CORE_ADDR 1781130803Smarcelfind_implementation_from_class (CORE_ADDR class, CORE_ADDR sel) 1782130803Smarcel{ 1783130803Smarcel CORE_ADDR subclass = class; 1784130803Smarcel 1785130803Smarcel while (subclass != 0) 1786130803Smarcel { 1787130803Smarcel 1788130803Smarcel struct objc_class class_str; 1789130803Smarcel unsigned mlistnum = 0; 1790130803Smarcel 1791130803Smarcel read_objc_class (subclass, &class_str); 1792130803Smarcel 1793130803Smarcel for (;;) 1794130803Smarcel { 1795130803Smarcel CORE_ADDR mlist; 1796130803Smarcel unsigned long nmethods; 1797130803Smarcel unsigned long i; 1798130803Smarcel 1799130803Smarcel mlist = read_memory_unsigned_integer (class_str.methods + 1800130803Smarcel (4 * mlistnum), 4); 1801130803Smarcel if (mlist == 0) 1802130803Smarcel break; 1803130803Smarcel 1804130803Smarcel nmethods = read_objc_methlist_nmethods (mlist); 1805130803Smarcel 1806130803Smarcel for (i = 0; i < nmethods; i++) 1807130803Smarcel { 1808130803Smarcel struct objc_method meth_str; 1809130803Smarcel read_objc_methlist_method (mlist, i, &meth_str); 1810130803Smarcel 1811130803Smarcel#if 0 1812130803Smarcel fprintf (stderr, 1813130803Smarcel "checking method 0x%lx against selector 0x%lx\n", 1814130803Smarcel meth_str.name, sel); 1815130803Smarcel#endif 1816130803Smarcel 1817130803Smarcel if (meth_str.name == sel) 1818130803Smarcel /* FIXME: hppa arch was doing a pointer dereference 1819130803Smarcel here. There needs to be a better way to do that. */ 1820130803Smarcel return meth_str.imp; 1821130803Smarcel } 1822130803Smarcel mlistnum++; 1823130803Smarcel } 1824130803Smarcel subclass = class_str.super_class; 1825130803Smarcel } 1826130803Smarcel 1827130803Smarcel return 0; 1828130803Smarcel} 1829130803Smarcel 1830130803Smarcelstatic CORE_ADDR 1831130803Smarcelfind_implementation (CORE_ADDR object, CORE_ADDR sel) 1832130803Smarcel{ 1833130803Smarcel struct objc_object ostr; 1834130803Smarcel 1835130803Smarcel if (object == 0) 1836130803Smarcel return 0; 1837130803Smarcel read_objc_object (object, &ostr); 1838130803Smarcel if (ostr.isa == 0) 1839130803Smarcel return 0; 1840130803Smarcel 1841130803Smarcel return find_implementation_from_class (ostr.isa, sel); 1842130803Smarcel} 1843130803Smarcel 1844130803Smarcel#define OBJC_FETCH_POINTER_ARGUMENT(argi) \ 1845130803Smarcel FETCH_POINTER_ARGUMENT (get_current_frame (), argi, builtin_type_void_func_ptr) 1846130803Smarcel 1847130803Smarcelstatic int 1848130803Smarcelresolve_msgsend (CORE_ADDR pc, CORE_ADDR *new_pc) 1849130803Smarcel{ 1850130803Smarcel CORE_ADDR object; 1851130803Smarcel CORE_ADDR sel; 1852130803Smarcel CORE_ADDR res; 1853130803Smarcel 1854130803Smarcel object = OBJC_FETCH_POINTER_ARGUMENT (0); 1855130803Smarcel sel = OBJC_FETCH_POINTER_ARGUMENT (1); 1856130803Smarcel 1857130803Smarcel res = find_implementation (object, sel); 1858130803Smarcel if (new_pc != 0) 1859130803Smarcel *new_pc = res; 1860130803Smarcel if (res == 0) 1861130803Smarcel return 1; 1862130803Smarcel return 0; 1863130803Smarcel} 1864130803Smarcel 1865130803Smarcelstatic int 1866130803Smarcelresolve_msgsend_stret (CORE_ADDR pc, CORE_ADDR *new_pc) 1867130803Smarcel{ 1868130803Smarcel CORE_ADDR object; 1869130803Smarcel CORE_ADDR sel; 1870130803Smarcel CORE_ADDR res; 1871130803Smarcel 1872130803Smarcel object = OBJC_FETCH_POINTER_ARGUMENT (1); 1873130803Smarcel sel = OBJC_FETCH_POINTER_ARGUMENT (2); 1874130803Smarcel 1875130803Smarcel res = find_implementation (object, sel); 1876130803Smarcel if (new_pc != 0) 1877130803Smarcel *new_pc = res; 1878130803Smarcel if (res == 0) 1879130803Smarcel return 1; 1880130803Smarcel return 0; 1881130803Smarcel} 1882130803Smarcel 1883130803Smarcelstatic int 1884130803Smarcelresolve_msgsend_super (CORE_ADDR pc, CORE_ADDR *new_pc) 1885130803Smarcel{ 1886130803Smarcel struct objc_super sstr; 1887130803Smarcel 1888130803Smarcel CORE_ADDR super; 1889130803Smarcel CORE_ADDR sel; 1890130803Smarcel CORE_ADDR res; 1891130803Smarcel 1892130803Smarcel super = OBJC_FETCH_POINTER_ARGUMENT (0); 1893130803Smarcel sel = OBJC_FETCH_POINTER_ARGUMENT (1); 1894130803Smarcel 1895130803Smarcel read_objc_super (super, &sstr); 1896130803Smarcel if (sstr.class == 0) 1897130803Smarcel return 0; 1898130803Smarcel 1899130803Smarcel res = find_implementation_from_class (sstr.class, sel); 1900130803Smarcel if (new_pc != 0) 1901130803Smarcel *new_pc = res; 1902130803Smarcel if (res == 0) 1903130803Smarcel return 1; 1904130803Smarcel return 0; 1905130803Smarcel} 1906130803Smarcel 1907130803Smarcelstatic int 1908130803Smarcelresolve_msgsend_super_stret (CORE_ADDR pc, CORE_ADDR *new_pc) 1909130803Smarcel{ 1910130803Smarcel struct objc_super sstr; 1911130803Smarcel 1912130803Smarcel CORE_ADDR super; 1913130803Smarcel CORE_ADDR sel; 1914130803Smarcel CORE_ADDR res; 1915130803Smarcel 1916130803Smarcel super = OBJC_FETCH_POINTER_ARGUMENT (1); 1917130803Smarcel sel = OBJC_FETCH_POINTER_ARGUMENT (2); 1918130803Smarcel 1919130803Smarcel read_objc_super (super, &sstr); 1920130803Smarcel if (sstr.class == 0) 1921130803Smarcel return 0; 1922130803Smarcel 1923130803Smarcel res = find_implementation_from_class (sstr.class, sel); 1924130803Smarcel if (new_pc != 0) 1925130803Smarcel *new_pc = res; 1926130803Smarcel if (res == 0) 1927130803Smarcel return 1; 1928130803Smarcel return 0; 1929130803Smarcel} 1930