/* Objective-C language support routines for GDB, the GNU debugger.
- Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011
- Free Software Foundation, Inc.
+ Copyright (C) 2002-2019 Free Software Foundation, Inc.
Contributed by Apple Computer, Inc.
Written by Michael Snyder.
#include "expression.h"
#include "parser-defs.h"
#include "language.h"
+#include "varobj.h"
#include "c-lang.h"
#include "objc-lang.h"
-#include "exceptions.h"
#include "complaints.h"
#include "value.h"
#include "symfile.h"
#include "objfiles.h"
-#include "gdb_string.h" /* for strchr */
#include "target.h" /* for target_has_execution */
#include "gdbcore.h"
#include "gdbcmd.h"
#include "block.h"
#include "infcall.h"
#include "valprint.h"
-#include "gdb_assert.h"
+#include "cli/cli-utils.h"
#include <ctype.h>
+#include <algorithm>
struct objc_object {
CORE_ADDR isa;
struct objc_super {
CORE_ADDR receiver;
- CORE_ADDR class;
+ CORE_ADDR theclass;
};
struct objc_method {
CORE_ADDR imp;
};
-static const struct objfile_data *objc_objfile_data;
+static const struct objfile_key<unsigned int> objc_objfile_data;
/* Lookup a structure type named "struct NAME", visible in lexical
block BLOCK. If NOERR is nonzero, return zero if NAME is not
suitably defined. */
struct symbol *
-lookup_struct_typedef (char *name, struct block *block, int noerr)
+lookup_struct_typedef (const char *name, const struct block *block, int noerr)
{
struct symbol *sym;
- sym = lookup_symbol (name, block, STRUCT_DOMAIN, 0);
+ sym = lookup_symbol (name, block, STRUCT_DOMAIN, 0).symbol;
if (sym == NULL)
{
}
CORE_ADDR
-lookup_objc_class (struct gdbarch *gdbarch, char *classname)
+lookup_objc_class (struct gdbarch *gdbarch, const char *classname)
{
struct type *char_type = builtin_type (gdbarch)->builtin_char;
struct value * function, *classval;
return 0;
}
- if (lookup_minimal_symbol("objc_lookUpClass", 0, 0))
+ if (lookup_minimal_symbol("objc_lookUpClass", 0, 0).minsym)
function = find_function_in_inferior("objc_lookUpClass", NULL);
- else if (lookup_minimal_symbol ("objc_lookup_class", 0, 0))
+ else if (lookup_minimal_symbol ("objc_lookup_class", 0, 0).minsym)
function = find_function_in_inferior("objc_lookup_class", NULL);
else
{
- complaint (&symfile_complaints,
- _("no way to lookup Objective-C classes"));
+ complaint (_("no way to lookup Objective-C classes"));
return 0;
}
classval = value_string (classname, strlen (classname) + 1, char_type);
classval = value_coerce_array (classval);
- return (CORE_ADDR) value_as_long (call_function_by_hand (function,
- 1, &classval));
+ return (CORE_ADDR) value_as_long (call_function_by_hand (function,
+ NULL,
+ classval));
}
CORE_ADDR
-lookup_child_selector (struct gdbarch *gdbarch, char *selname)
+lookup_child_selector (struct gdbarch *gdbarch, const char *selname)
{
struct type *char_type = builtin_type (gdbarch)->builtin_char;
struct value * function, *selstring;
return 0;
}
- if (lookup_minimal_symbol("sel_getUid", 0, 0))
+ if (lookup_minimal_symbol("sel_getUid", 0, 0).minsym)
function = find_function_in_inferior("sel_getUid", NULL);
- else if (lookup_minimal_symbol ("sel_get_any_uid", 0, 0))
+ else if (lookup_minimal_symbol ("sel_get_any_uid", 0, 0).minsym)
function = find_function_in_inferior("sel_get_any_uid", NULL);
else
{
- complaint (&symfile_complaints,
- _("no way to lookup Objective-C selectors"));
+ complaint (_("no way to lookup Objective-C selectors"));
return 0;
}
selstring = value_coerce_array (value_string (selname,
strlen (selname) + 1,
char_type));
- return value_as_long (call_function_by_hand (function, 1, &selstring));
+ return value_as_long (call_function_by_hand (function, NULL, selstring));
}
struct value *
stringValue[2] = value_string(ptr, len, char_type);
stringValue[2] = value_coerce_array(stringValue[2]);
/* _NSNewStringFromCString replaces "istr" after Lantern2A. */
- if (lookup_minimal_symbol("_NSNewStringFromCString", 0, 0))
+ if (lookup_minimal_symbol("_NSNewStringFromCString", 0, 0).minsym)
{
function = find_function_in_inferior("_NSNewStringFromCString", NULL);
- nsstringValue = call_function_by_hand(function, 1, &stringValue[2]);
+ nsstringValue = call_function_by_hand(function, NULL, stringValue[2]);
}
- else if (lookup_minimal_symbol("istr", 0, 0))
+ else if (lookup_minimal_symbol("istr", 0, 0).minsym)
{
function = find_function_in_inferior("istr", NULL);
- nsstringValue = call_function_by_hand(function, 1, &stringValue[2]);
+ nsstringValue = call_function_by_hand(function, NULL, stringValue[2]);
}
- else if (lookup_minimal_symbol("+[NSString stringWithCString:]", 0, 0))
+ else if (lookup_minimal_symbol("+[NSString stringWithCString:]", 0, 0).minsym)
{
function
= find_function_in_inferior("+[NSString stringWithCString:]", NULL);
(type, lookup_objc_class (gdbarch, "NSString"));
stringValue[1] = value_from_longest
(type, lookup_child_selector (gdbarch, "stringWithCString:"));
- nsstringValue = call_function_by_hand(function, 3, &stringValue[0]);
+ nsstringValue = call_function_by_hand(function, NULL, stringValue);
}
else
error (_("NSString: internal error -- no way to create new NSString"));
(mangled[1] == 'i' || mangled[1] == 'c') &&
mangled[2] == '_')
{
- cp = demangled = xmalloc(strlen(mangled) + 2);
+ cp = demangled = (char *) xmalloc (strlen (mangled) + 2);
if (mangled[1] == 'i')
*cp++ = '-'; /* for instance method */
return NULL; /* Not an objc mangled name. */
}
-/* Print the character C on STREAM as part of the contents of a
- literal string whose delimiter is QUOTER. Note that that format
- for printing characters and strings is language specific. */
+/* la_sniff_from_mangled_name for ObjC. */
-static void
-objc_emit_char (int c, struct type *type, struct ui_file *stream, int quoter)
-{
- c &= 0xFF; /* Avoid sign bit follies. */
-
- if (PRINT_LITERAL_FORM (c))
- {
- if (c == '\\' || c == quoter)
- {
- fputs_filtered ("\\", stream);
- }
- fprintf_filtered (stream, "%c", c);
- }
- else
- {
- switch (c)
- {
- case '\n':
- fputs_filtered ("\\n", stream);
- break;
- case '\b':
- fputs_filtered ("\\b", stream);
- break;
- case '\t':
- fputs_filtered ("\\t", stream);
- break;
- case '\f':
- fputs_filtered ("\\f", stream);
- break;
- case '\r':
- fputs_filtered ("\\r", stream);
- break;
- case '\033':
- fputs_filtered ("\\e", stream);
- break;
- case '\007':
- fputs_filtered ("\\a", stream);
- break;
- default:
- fprintf_filtered (stream, "\\%.3o", (unsigned int) c);
- break;
- }
- }
-}
-
-static void
-objc_printchar (int c, struct type *type, struct ui_file *stream)
+static int
+objc_sniff_from_mangled_name (const char *mangled, char **demangled)
{
- fputs_filtered ("'", stream);
- objc_emit_char (c, type, stream, '\'');
- fputs_filtered ("'", stream);
-}
-
-/* Print the character string STRING, printing at most LENGTH
- characters. Printing stops early if the number hits print_max;
- repeat counts are printed as appropriate. Print ellipses at the
- end if we had to stop before printing LENGTH characters, or if
- FORCE_ELLIPSES. */
-
-static void
-objc_printstr (struct ui_file *stream, struct type *type,
- const gdb_byte *string, unsigned int length,
- const char *encoding, int force_ellipses,
- const struct value_print_options *options)
-{
- unsigned int i;
- unsigned int things_printed = 0;
- int in_quotes = 0;
- int need_comma = 0;
-
- /* If the string was not truncated due to `set print elements', and
- the last byte of it is a null, we don't print that, in
- traditional C style. */
- if ((!force_ellipses) && length > 0 && string[length-1] == '\0')
- length--;
-
- if (length == 0)
- {
- fputs_filtered ("\"\"", stream);
- return;
- }
-
- for (i = 0; i < length && things_printed < options->print_max; ++i)
- {
- /* Position of the character we are examining to see whether it
- is repeated. */
- unsigned int rep1;
- /* Number of repetitions we have detected so far. */
- unsigned int reps;
-
- QUIT;
-
- if (need_comma)
- {
- fputs_filtered (", ", stream);
- need_comma = 0;
- }
-
- rep1 = i + 1;
- reps = 1;
- while (rep1 < length && string[rep1] == string[i])
- {
- ++rep1;
- ++reps;
- }
-
- if (reps > options->repeat_count_threshold)
- {
- if (in_quotes)
- {
- if (options->inspect_it)
- fputs_filtered ("\\\", ", stream);
- else
- fputs_filtered ("\", ", stream);
- in_quotes = 0;
- }
- objc_printchar (string[i], type, stream);
- fprintf_filtered (stream, " <repeats %u times>", reps);
- i = rep1 - 1;
- things_printed += options->repeat_count_threshold;
- need_comma = 1;
- }
- else
- {
- if (!in_quotes)
- {
- if (options->inspect_it)
- fputs_filtered ("\\\"", stream);
- else
- fputs_filtered ("\"", stream);
- in_quotes = 1;
- }
- objc_emit_char (string[i], type, stream, '"');
- ++things_printed;
- }
- }
-
- /* Terminate the quotes if necessary. */
- if (in_quotes)
- {
- if (options->inspect_it)
- fputs_filtered ("\\\"", stream);
- else
- fputs_filtered ("\"", stream);
- }
-
- if (force_ellipses || i < length)
- fputs_filtered ("...", stream);
+ *demangled = objc_demangle (mangled, 0);
+ return *demangled != NULL;
}
/* Determine if we are currently in the Objective-C dispatch function.
{NULL, OP_NULL, PREC_NULL, 0}
};
-const struct language_defn objc_language_defn = {
+static const char *objc_extensions[] =
+{
+ ".m", NULL
+};
+
+extern const struct language_defn objc_language_defn = {
"objective-c", /* Language name */
+ "Objective-C",
language_objc,
range_check_off,
- type_check_off,
case_sensitive_on,
array_row_major,
macro_expansion_c,
+ objc_extensions,
&exp_descriptor_standard,
- objc_parse,
- objc_error,
+ c_parse,
null_post_parser,
- objc_printchar, /* Print a character constant */
- objc_printstr, /* Function to print string constant */
- objc_emit_char,
+ c_printchar, /* Print a character constant */
+ c_printstr, /* Function to print string constant */
+ c_emit_char,
c_print_type, /* Print a type using appropriate syntax */
c_print_typedef, /* Print a typedef using appropriate syntax */
c_val_print, /* Print a value using appropriate syntax */
c_value_print, /* Print a top-level value */
+ default_read_var_value, /* la_read_var_value */
objc_skip_trampoline, /* Language specific skip_trampoline */
"self", /* name_of_this */
+ false, /* la_store_sym_names_in_linkage_form_p */
basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
basic_lookup_transparent_type,/* lookup_transparent_type */
objc_demangle, /* Language specific symbol demangler */
+ objc_sniff_from_mangled_name,
NULL, /* Language specific
class_name_from_physname */
objc_op_print_tab, /* Expression operators for printing */
1, /* C-style arrays */
0, /* String lower bound */
default_word_break_characters,
- default_make_symbol_completion_list,
+ default_collect_symbol_completion_matches,
c_language_arch_info,
default_print_array_index,
default_pass_by_reference,
- default_get_string,
- LANG_MAGIC
+ c_watch_location_expression,
+ NULL, /* la_get_symbol_name_matcher */
+ iterate_over_symbols,
+ default_search_name_hash,
+ &default_varobj_ops,
+ NULL,
+ NULL,
+ c_is_string_type_p,
+ "{...}" /* la_struct_too_deep_ellipsis */
};
/*
void
start_msglist(void)
{
- struct selname *new =
- (struct selname *) xmalloc (sizeof (struct selname));
+ struct selname *newobj = XNEW (struct selname);
- new->next = selname_chain;
- new->msglist_len = msglist_len;
- new->msglist_sel = msglist_sel;
+ newobj->next = selname_chain;
+ newobj->msglist_len = msglist_len;
+ newobj->msglist_sel = msglist_sel;
msglist_len = 0;
msglist_sel = (char *)xmalloc(1);
*msglist_sel = 0;
- selname_chain = new;
+ selname_chain = newobj;
}
void
add_msglist(struct stoken *str, int addcolon)
{
- char *s, *p;
+ char *s;
+ const char *p;
int len, plen;
if (str == 0) /* Unnamed arg, or... */
}
int
-end_msglist(void)
+end_msglist (struct parser_state *ps)
{
int val = msglist_len;
struct selname *sel = selname_chain;
selname_chain = sel->next;
msglist_len = sel->msglist_len;
msglist_sel = sel->msglist_sel;
- selid = lookup_child_selector (parse_gdbarch, p);
+ selid = lookup_child_selector (ps->gdbarch (), p);
if (!selid)
error (_("Can't find selector \"%s\""), p);
- write_exp_elt_longcst (selid);
+ write_exp_elt_longcst (ps, selid);
xfree(p);
- write_exp_elt_longcst (val); /* Number of args */
+ write_exp_elt_longcst (ps, val); /* Number of args */
xfree(sel);
return val;
}
/*
- * Function: specialcmp (char *a, char *b)
+ * Function: specialcmp (const char *a, const char *b)
*
* Special strcmp: treats ']' and ' ' as end-of-string.
* Used for qsorting lists of objc methods (either by class or selector).
*/
static int
-specialcmp (char *a, char *b)
+specialcmp (const char *a, const char *b)
{
while (*a && *a != ' ' && *a != ']' && *b && *b != ' ' && *b != ']')
{
static int
compare_selectors (const void *a, const void *b)
{
- char *aname, *bname;
+ const char *aname, *bname;
- aname = SYMBOL_PRINT_NAME (*(struct symbol **) a);
- bname = SYMBOL_PRINT_NAME (*(struct symbol **) b);
+ aname = (*(struct symbol **) a)->print_name ();
+ bname = (*(struct symbol **) b)->print_name ();
if (aname == NULL || bname == NULL)
error (_("internal: compare_selectors(1)"));
*/
static void
-selectors_info (char *regexp, int from_tty)
+info_selectors_command (const char *regexp, int from_tty)
{
- struct objfile *objfile;
- struct minimal_symbol *msymbol;
- char *name;
+ const char *name;
char *val;
int matches = 0;
int maxlen = 0;
}
/* First time thru is JUST to get max length and count. */
- ALL_MSYMBOLS (objfile, msymbol)
+ for (objfile *objfile : current_program_space->objfiles ())
{
- QUIT;
- name = SYMBOL_NATURAL_NAME (msymbol);
- if (name
- && (name[0] == '-' || name[0] == '+')
- && name[1] == '[') /* Got a method name. */
+ for (minimal_symbol *msymbol : objfile->msymbols ())
{
- /* Filter for class/instance methods. */
- if (plusminus && name[0] != plusminus)
- continue;
- /* Find selector part. */
- name = (char *) strchr (name+2, ' ');
- if (regexp == NULL || re_exec(++name) != 0)
- {
- char *mystart = name;
- char *myend = (char *) strchr (mystart, ']');
+ QUIT;
+ name = msymbol->natural_name ();
+ if (name
+ && (name[0] == '-' || name[0] == '+')
+ && name[1] == '[') /* Got a method name. */
+ {
+ /* Filter for class/instance methods. */
+ if (plusminus && name[0] != plusminus)
+ continue;
+ /* Find selector part. */
+ name = (char *) strchr (name+2, ' ');
+ if (name == NULL)
+ {
+ complaint (_("Bad method name '%s'"),
+ msymbol->natural_name ());
+ continue;
+ }
+ if (regexp == NULL || re_exec(++name) != 0)
+ {
+ const char *mystart = name;
+ const char *myend = strchr (mystart, ']');
- if (myend && (myend - mystart > maxlen))
- maxlen = myend - mystart; /* Get longest selector. */
- matches++;
+ if (myend && (myend - mystart > maxlen))
+ maxlen = myend - mystart; /* Get longest selector. */
+ matches++;
+ }
}
}
}
printf_filtered (_("Selectors matching \"%s\":\n\n"),
regexp ? regexp : "*");
- sym_arr = alloca (matches * sizeof (struct symbol *));
+ sym_arr = XALLOCAVEC (struct symbol *, matches);
matches = 0;
- ALL_MSYMBOLS (objfile, msymbol)
+ for (objfile *objfile : current_program_space->objfiles ())
{
- QUIT;
- name = SYMBOL_NATURAL_NAME (msymbol);
- if (name &&
- (name[0] == '-' || name[0] == '+') &&
- name[1] == '[') /* Got a method name. */
+ for (minimal_symbol *msymbol : objfile->msymbols ())
{
- /* Filter for class/instance methods. */
- if (plusminus && name[0] != plusminus)
- continue;
- /* Find selector part. */
- name = (char *) strchr(name+2, ' ');
- if (regexp == NULL || re_exec(++name) != 0)
- sym_arr[matches++] = (struct symbol *) msymbol;
+ QUIT;
+ name = msymbol->natural_name ();
+ if (name &&
+ (name[0] == '-' || name[0] == '+') &&
+ name[1] == '[') /* Got a method name. */
+ {
+ /* Filter for class/instance methods. */
+ if (plusminus && name[0] != plusminus)
+ continue;
+ /* Find selector part. */
+ name = (char *) strchr(name+2, ' ');
+ if (regexp == NULL || re_exec(++name) != 0)
+ sym_arr[matches++] = (struct symbol *) msymbol;
+ }
}
}
char *p = asel;
QUIT;
- name = SYMBOL_NATURAL_NAME (sym_arr[ix]);
+ name = sym_arr[ix]->natural_name ();
name = strchr (name, ' ') + 1;
if (p[0] && specialcmp(name, p) == 0)
continue; /* Seen this one already (not unique). */
static int
compare_classes (const void *a, const void *b)
{
- char *aname, *bname;
+ const char *aname, *bname;
- aname = SYMBOL_PRINT_NAME (*(struct symbol **) a);
- bname = SYMBOL_PRINT_NAME (*(struct symbol **) b);
+ aname = (*(struct symbol **) a)->print_name ();
+ bname = (*(struct symbol **) b)->print_name ();
if (aname == NULL || bname == NULL)
error (_("internal: compare_classes(1)"));
*/
static void
-classes_info (char *regexp, int from_tty)
+info_classes_command (const char *regexp, int from_tty)
{
- struct objfile *objfile;
- struct minimal_symbol *msymbol;
- char *name;
+ const char *name;
char *val;
int matches = 0;
int maxlen = 0;
}
/* First time thru is JUST to get max length and count. */
- ALL_MSYMBOLS (objfile, msymbol)
+ for (objfile *objfile : current_program_space->objfiles ())
{
- QUIT;
- name = SYMBOL_NATURAL_NAME (msymbol);
- if (name &&
- (name[0] == '-' || name[0] == '+') &&
- name[1] == '[') /* Got a method name. */
- if (regexp == NULL || re_exec(name+2) != 0)
- {
- /* Compute length of classname part. */
- char *mystart = name + 2;
- char *myend = (char *) strchr(mystart, ' ');
+ for (minimal_symbol *msymbol : objfile->msymbols ())
+ {
+ QUIT;
+ name = msymbol->natural_name ();
+ if (name &&
+ (name[0] == '-' || name[0] == '+') &&
+ name[1] == '[') /* Got a method name. */
+ if (regexp == NULL || re_exec(name+2) != 0)
+ {
+ /* Compute length of classname part. */
+ const char *mystart = name + 2;
+ const char *myend = strchr (mystart, ' ');
- if (myend && (myend - mystart > maxlen))
- maxlen = myend - mystart;
- matches++;
- }
+ if (myend && (myend - mystart > maxlen))
+ maxlen = myend - mystart;
+ matches++;
+ }
+ }
}
if (matches)
{
printf_filtered (_("Classes matching \"%s\":\n\n"),
regexp ? regexp : "*");
- sym_arr = alloca (matches * sizeof (struct symbol *));
+ sym_arr = XALLOCAVEC (struct symbol *, matches);
matches = 0;
- ALL_MSYMBOLS (objfile, msymbol)
+ for (objfile *objfile : current_program_space->objfiles ())
{
- QUIT;
- name = SYMBOL_NATURAL_NAME (msymbol);
- if (name &&
- (name[0] == '-' || name[0] == '+') &&
- name[1] == '[') /* Got a method name. */
- if (regexp == NULL || re_exec(name+2) != 0)
- sym_arr[matches++] = (struct symbol *) msymbol;
+ for (minimal_symbol *msymbol : objfile->msymbols ())
+ {
+ QUIT;
+ name = msymbol->natural_name ();
+ if (name &&
+ (name[0] == '-' || name[0] == '+') &&
+ name[1] == '[') /* Got a method name. */
+ if (regexp == NULL || re_exec(name+2) != 0)
+ sym_arr[matches++] = (struct symbol *) msymbol;
+ }
}
qsort (sym_arr, matches, sizeof (struct minimal_symbol *),
char *p = aclass;
QUIT;
- name = SYMBOL_NATURAL_NAME (sym_arr[ix]);
+ name = sym_arr[ix]->natural_name ();
name += 2;
if (p[0] && specialcmp(name, p) == 0)
continue; /* Seen this one already (not unique). */
printf_filtered (_("No classes matching \"%s\"\n"), regexp ? regexp : "*");
}
-/*
- * Function: find_imps (char *selector, struct symbol **sym_arr)
- *
- * Input: a string representing a selector
- * a pointer to an array of symbol pointers
- * possibly a pointer to a symbol found by the caller.
- *
- * Output: number of methods that implement that selector. Side
- * effects: The array of symbol pointers is filled with matching syms.
- *
- * By analogy with function "find_methods" (symtab.c), builds a list
- * of symbols matching the ambiguous input, so that "decode_line_2"
- * (symtab.c) can list them and ask the user to choose one or more.
- * In this case the matches are objective c methods
- * ("implementations") matching an objective c selector.
- *
- * Note that it is possible for a normal (c-style) function to have
- * the same name as an objective c selector. To prevent the selector
- * from eclipsing the function, we allow the caller (decode_line_1) to
- * search for such a function first, and if it finds one, pass it in
- * to us. We will then integrate it into the list. We also search
- * for one here, among the minsyms.
- *
- * NOTE: if NUM_DEBUGGABLE is non-zero, the sym_arr will be divided
- * into two parts: debuggable (struct symbol) syms, and
- * non_debuggable (struct minimal_symbol) syms. The debuggable
- * ones will come first, before NUM_DEBUGGABLE (which will thus
- * be the index of the first non-debuggable one).
- */
-
-/*
- * Function: total_number_of_imps (char *selector);
- *
- * Input: a string representing a selector
- * Output: number of methods that implement that selector.
- *
- * By analogy with function "total_number_of_methods", this allows
- * decode_line_1 (symtab.c) to detect if there are objective c methods
- * matching the input, and to allocate an array of pointers to them
- * which can be manipulated by "decode_line_2" (also in symtab.c).
- */
-
-char *
+static char *
parse_selector (char *method, char **selector)
{
char *s1 = NULL;
s1 = method;
- while (isspace (*s1))
- s1++;
+ s1 = skip_spaces (s1);
if (*s1 == '\'')
{
found_quote = 1;
s1++;
}
- while (isspace (*s1))
- s1++;
+ s1 = skip_spaces (s1);
nselector = s1;
s2 = s1;
}
*s1++ = '\0';
- while (isspace (*s2))
- s2++;
+ s2 = skip_spaces (s2);
if (found_quote)
{
if (*s2 == '\'')
s2++;
- while (isspace (*s2))
- s2++;
+ s2 = skip_spaces (s2);
}
if (selector != NULL)
return s2;
}
-char *
-parse_method (char *method, char *type, char **class,
+static char *
+parse_method (char *method, char *type, char **theclass,
char **category, char **selector)
{
char *s1 = NULL;
char *nselector = NULL;
gdb_assert (type != NULL);
- gdb_assert (class != NULL);
+ gdb_assert (theclass != NULL);
gdb_assert (category != NULL);
gdb_assert (selector != NULL);
s1 = method;
- while (isspace (*s1))
- s1++;
+ s1 = skip_spaces (s1);
if (*s1 == '\'')
{
found_quote = 1;
s1++;
}
- while (isspace (*s1))
- s1++;
+ s1 = skip_spaces (s1);
if ((s1[0] == '+') || (s1[0] == '-'))
ntype = *s1++;
- while (isspace (*s1))
- s1++;
+ s1 = skip_spaces (s1);
if (*s1 != '[')
return NULL;
s1++;
s2 = s1;
- while (isspace (*s2))
- s2++;
+ s2 = skip_spaces (s2);
if (*s2 == '(')
{
s2++;
- while (isspace (*s2))
- s2++;
+ s2 = skip_spaces (s2);
ncategory = s2;
while (isalnum (*s2) || (*s2 == '_'))
s2++;
*s1++ = '\0';
s2++;
- while (isspace (*s2))
- s2++;
+ s2 = skip_spaces (s2);
if (found_quote)
{
if (*s2 != '\'')
return NULL;
s2++;
- while (isspace (*s2))
- s2++;
+ s2 = skip_spaces (s2);
}
if (type != NULL)
*type = ntype;
- if (class != NULL)
- *class = nclass;
+ if (theclass != NULL)
+ *theclass = nclass;
if (category != NULL)
*category = ncategory;
if (selector != NULL)
}
static void
-find_methods (struct symtab *symtab, char type,
- const char *class, const char *category,
- const char *selector, struct symbol **syms,
- unsigned int *nsym, unsigned int *ndebug)
+find_methods (char type, const char *theclass, const char *category,
+ const char *selector,
+ std::vector<const char *> *symbol_names)
{
- struct objfile *objfile = NULL;
- struct minimal_symbol *msymbol = NULL;
- struct block *block = NULL;
- struct symbol *sym = NULL;
-
- char *symname = NULL;
+ const char *symname = NULL;
char ntype = '\0';
char *nclass = NULL;
char *ncategory = NULL;
char *nselector = NULL;
- unsigned int csym = 0;
- unsigned int cdebug = 0;
-
static char *tmp = NULL;
static unsigned int tmplen = 0;
- gdb_assert (nsym != NULL);
- gdb_assert (ndebug != NULL);
-
- if (symtab)
- block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (symtab), STATIC_BLOCK);
+ gdb_assert (symbol_names != NULL);
- ALL_OBJFILES (objfile)
+ for (objfile *objfile : current_program_space->objfiles ())
{
unsigned int *objc_csym;
unsigned int objfile_csym = 0;
- objc_csym = objfile_data (objfile, objc_objfile_data);
+ objc_csym = objc_objfile_data.get (objfile);
if (objc_csym != NULL && *objc_csym == 0)
/* There are no ObjC symbols in this objfile. Skip it entirely. */
continue;
- ALL_OBJFILE_MSYMBOLS (objfile, msymbol)
+ for (minimal_symbol *msymbol : objfile->msymbols ())
{
- struct gdbarch *gdbarch = get_objfile_arch (objfile);
- CORE_ADDR pc = SYMBOL_VALUE_ADDRESS (msymbol);
-
QUIT;
/* Check the symbol name first as this can be done entirely without
sending any query to the target. */
- symname = SYMBOL_NATURAL_NAME (msymbol);
+ symname = msymbol->natural_name ();
if (symname == NULL)
continue;
/* Not a method name. */
continue;
- /* The minimal symbol might point to a function descriptor;
- resolve it to the actual code address instead. */
- pc = gdbarch_convert_from_func_ptr_addr (gdbarch, pc,
- ¤t_target);
-
- if (symtab)
- if (pc < BLOCK_START (block) || pc >= BLOCK_END (block))
- /* Not in the specified symtab. */
- continue;
+ objfile_csym++;
/* Now that thinks are a bit sane, clean up the symname. */
while ((strlen (symname) + 1) >= tmplen)
{
tmplen = (tmplen == 0) ? 1024 : tmplen * 2;
- tmp = xrealloc (tmp, tmplen);
+ tmp = (char *) xrealloc (tmp, tmplen);
}
strcpy (tmp, symname);
if (parse_method (tmp, &ntype, &nclass,
&ncategory, &nselector) == NULL)
continue;
-
- objfile_csym++;
if ((type != '\0') && (ntype != type))
continue;
- if ((class != NULL)
- && ((nclass == NULL) || (strcmp (class, nclass) != 0)))
+ if ((theclass != NULL)
+ && ((nclass == NULL) || (strcmp (theclass, nclass) != 0)))
continue;
if ((category != NULL) &&
((nselector == NULL) || (strcmp (selector, nselector) != 0)))
continue;
- sym = find_pc_function (pc);
- if (sym != NULL)
- {
- const char *newsymname = SYMBOL_NATURAL_NAME (sym);
-
- if (strcmp (symname, newsymname) == 0)
- {
- /* Found a high-level method sym: swap it into the
- lower part of sym_arr (below num_debuggable). */
- if (syms != NULL)
- {
- syms[csym] = syms[cdebug];
- syms[cdebug] = sym;
- }
- csym++;
- cdebug++;
- }
- else
- {
- warning (
-"debugging symbol \"%s\" does not match minimal symbol (\"%s\"); ignoring",
- newsymname, symname);
- if (syms != NULL)
- syms[csym] = (struct symbol *) msymbol;
- csym++;
- }
- }
- else
- {
- /* Found a non-debuggable method symbol. */
- if (syms != NULL)
- syms[csym] = (struct symbol *) msymbol;
- csym++;
- }
+ symbol_names->push_back (symname);
}
+
if (objc_csym == NULL)
- {
- objc_csym = obstack_alloc (&objfile->objfile_obstack,
- sizeof (*objc_csym));
- *objc_csym = objfile_csym;
- set_objfile_data (objfile, objc_objfile_data, objc_csym);
- }
+ objc_csym = objc_objfile_data.emplace (objfile, objfile_csym);
else
/* Count of ObjC methods in this objfile should be constant. */
gdb_assert (*objc_csym == objfile_csym);
}
+}
+
+/* Uniquify a vector of strings. */
- if (nsym != NULL)
- *nsym = csym;
- if (ndebug != NULL)
- *ndebug = cdebug;
+static void
+uniquify_strings (std::vector<const char *> *strings)
+{
+ if (strings->empty ())
+ return;
+
+ std::sort (strings->begin (), strings->end (), compare_cstrings);
+ strings->erase (std::unique (strings->begin (), strings->end (), streq),
+ strings->end ());
}
-char *find_imps (struct symtab *symtab, struct block *block,
- char *method, struct symbol **syms,
- unsigned int *nsym, unsigned int *ndebug)
+/*
+ * Function: find_imps (const char *selector, struct symbol **sym_arr)
+ *
+ * Input: a string representing a selector
+ * a pointer to an array of symbol pointers
+ * possibly a pointer to a symbol found by the caller.
+ *
+ * Output: number of methods that implement that selector. Side
+ * effects: The array of symbol pointers is filled with matching syms.
+ *
+ * By analogy with function "find_methods" (symtab.c), builds a list
+ * of symbols matching the ambiguous input, so that "decode_line_2"
+ * (symtab.c) can list them and ask the user to choose one or more.
+ * In this case the matches are objective c methods
+ * ("implementations") matching an objective c selector.
+ *
+ * Note that it is possible for a normal (c-style) function to have
+ * the same name as an objective c selector. To prevent the selector
+ * from eclipsing the function, we allow the caller (decode_line_1) to
+ * search for such a function first, and if it finds one, pass it in
+ * to us. We will then integrate it into the list. We also search
+ * for one here, among the minsyms.
+ *
+ * NOTE: if NUM_DEBUGGABLE is non-zero, the sym_arr will be divided
+ * into two parts: debuggable (struct symbol) syms, and
+ * non_debuggable (struct minimal_symbol) syms. The debuggable
+ * ones will come first, before NUM_DEBUGGABLE (which will thus
+ * be the index of the first non-debuggable one).
+ */
+
+const char *
+find_imps (const char *method, std::vector<const char *> *symbol_names)
{
char type = '\0';
- char *class = NULL;
+ char *theclass = NULL;
char *category = NULL;
char *selector = NULL;
- unsigned int csym = 0;
- unsigned int cdebug = 0;
-
- unsigned int ncsym = 0;
- unsigned int ncdebug = 0;
-
char *buf = NULL;
char *tmp = NULL;
- gdb_assert (nsym != NULL);
- gdb_assert (ndebug != NULL);
+ int selector_case = 0;
- if (nsym != NULL)
- *nsym = 0;
- if (ndebug != NULL)
- *ndebug = 0;
+ gdb_assert (symbol_names != NULL);
buf = (char *) alloca (strlen (method) + 1);
strcpy (buf, method);
- tmp = parse_method (buf, &type, &class, &category, &selector);
+ tmp = parse_method (buf, &type, &theclass, &category, &selector);
if (tmp == NULL)
{
- struct symbol *sym = NULL;
- struct minimal_symbol *msym = NULL;
-
strcpy (buf, method);
tmp = parse_selector (buf, &selector);
if (tmp == NULL)
return NULL;
- sym = lookup_symbol (selector, block, VAR_DOMAIN, 0);
- if (sym != NULL)
- {
- if (syms)
- syms[csym] = sym;
- csym++;
- cdebug++;
- }
-
- if (sym == NULL)
- msym = lookup_minimal_symbol (selector, 0, 0);
-
- if (msym != NULL)
- {
- if (syms)
- syms[csym] = (struct symbol *)msym;
- csym++;
- }
+ selector_case = 1;
}
- if (syms != NULL)
- find_methods (symtab, type, class, category, selector,
- syms + csym, &ncsym, &ncdebug);
- else
- find_methods (symtab, type, class, category, selector,
- NULL, &ncsym, &ncdebug);
-
- /* If we didn't find any methods, just return. */
- if (ncsym == 0 && ncdebug == 0)
- return method;
+ find_methods (type, theclass, category, selector, symbol_names);
- /* Take debug symbols from the second batch of symbols and swap them
- * with debug symbols from the first batch. Repeat until either the
- * second section is out of debug symbols or the first section is
- * full of debug symbols. Either way we have all debug symbols
- * packed to the beginning of the buffer.
- */
-
- if (syms != NULL)
+ /* If we hit the "selector" case, and we found some methods, then
+ add the selector itself as a symbol, if it exists. */
+ if (selector_case && !symbol_names->empty ())
{
- while ((cdebug < csym) && (ncdebug > 0))
+ struct symbol *sym = lookup_symbol (selector, NULL, VAR_DOMAIN,
+ 0).symbol;
+
+ if (sym != NULL)
+ symbol_names->push_back (sym->natural_name ());
+ else
{
- struct symbol *s = NULL;
- /* First non-debugging symbol. */
- unsigned int i = cdebug;
- /* Last of second batch of debug symbols. */
- unsigned int j = csym + ncdebug - 1;
-
- s = syms[j];
- syms[j] = syms[i];
- syms[i] = s;
-
- /* We've moved a symbol from the second debug section to the
- first one. */
- cdebug++;
- ncdebug--;
+ struct bound_minimal_symbol msym
+ = lookup_minimal_symbol (selector, 0, 0);
+
+ if (msym.minsym != NULL)
+ symbol_names->push_back (msym.minsym->natural_name ());
}
}
- csym += ncsym;
- cdebug += ncdebug;
-
- if (nsym != NULL)
- *nsym = csym;
- if (ndebug != NULL)
- *ndebug = cdebug;
-
- if (syms == NULL)
- return method + (tmp - buf);
-
- if (csym > 1)
- {
- /* Sort debuggable symbols. */
- if (cdebug > 1)
- qsort (syms, cdebug, sizeof (struct minimal_symbol *),
- compare_classes);
-
- /* Sort minimal_symbols. */
- if ((csym - cdebug) > 1)
- qsort (&syms[cdebug], csym - cdebug,
- sizeof (struct minimal_symbol *), compare_classes);
- }
- /* Terminate the sym_arr list. */
- syms[csym] = 0;
+ uniquify_strings (symbol_names);
return method + (tmp - buf);
}
static void
-print_object_command (char *args, int from_tty)
+print_object_command (const char *args, int from_tty)
{
struct value *object, *function, *description;
CORE_ADDR string_addr, object_addr;
"The 'print-object' command requires an argument (an Objective-C object)");
{
- struct expression *expr = parse_expression (args);
- struct cleanup *old_chain =
- make_cleanup (free_current_contents, &expr);
+ expression_up expr = parse_expression (args);
int pc = 0;
object = evaluate_subexp (builtin_type (expr->gdbarch)->builtin_data_ptr,
- expr, &pc, EVAL_NORMAL);
- do_cleanups (old_chain);
+ expr.get (), &pc, EVAL_NORMAL);
}
/* Validate the address for sanity. */
if (function == NULL)
error (_("Unable to locate _NSPrintForDebugger in child process"));
- description = call_function_by_hand (function, 1, &object);
+ description = call_function_by_hand (function, NULL, object);
string_addr = value_as_long (description);
if (string_addr == 0)
*/
struct objc_methcall {
- char *name;
+ const char *name;
/* Return instance method to be called. */
int (*stop_at) (CORE_ADDR, CORE_ADDR *);
/* Start of pc range corresponding to method invocation. */
for (i = 0; i < nmethcalls; i++)
{
- struct minimal_symbol *func;
+ struct bound_minimal_symbol func;
/* Try both with and without underscore. */
- func = lookup_minimal_symbol (methcalls[i].name, NULL, NULL);
- if ((func == NULL) && (methcalls[i].name[0] == '_'))
+ func = lookup_bound_minimal_symbol (methcalls[i].name);
+ if ((func.minsym == NULL) && (methcalls[i].name[0] == '_'))
{
- func = lookup_minimal_symbol (methcalls[i].name + 1, NULL, NULL);
+ func = lookup_bound_minimal_symbol (methcalls[i].name + 1);
}
- if (func == NULL)
+ if (func.minsym == NULL)
{
methcalls[i].begin = 0;
methcalls[i].end = 0;
continue;
}
- methcalls[i].begin = SYMBOL_VALUE_ADDRESS (func);
- do {
- methcalls[i].end = SYMBOL_VALUE_ADDRESS (++func);
- } while (methcalls[i].begin == methcalls[i].end);
+ methcalls[i].begin = BMSYMBOL_VALUE_ADDRESS (func);
+ methcalls[i].end = minimal_symbol_upper_bound (func);
}
}
* dependent modules.
*/
-struct objc_submethod_helper_data {
- int (*f) (CORE_ADDR, CORE_ADDR *);
- CORE_ADDR pc;
- CORE_ADDR *new_pc;
-};
-
-static int
-find_objc_msgcall_submethod_helper (void * arg)
-{
- struct objc_submethod_helper_data *s =
- (struct objc_submethod_helper_data *) arg;
-
- if (s->f (s->pc, s->new_pc) == 0)
- return 1;
- else
- return 0;
-}
-
static int
find_objc_msgcall_submethod (int (*f) (CORE_ADDR, CORE_ADDR *),
CORE_ADDR pc,
CORE_ADDR *new_pc)
{
- struct objc_submethod_helper_data s;
-
- s.f = f;
- s.pc = pc;
- s.new_pc = new_pc;
+ try
+ {
+ if (f (pc, new_pc) == 0)
+ return 1;
+ }
+ catch (const gdb_exception &ex)
+ {
+ exception_fprintf (gdb_stderr, ex,
+ "Unable to determine target of "
+ "Objective-C method call (ignoring):\n");
+ }
- if (catch_errors (find_objc_msgcall_submethod_helper,
- (void *) &s,
- "Unable to determine target of "
- "Objective-C method call (ignoring):\n",
- RETURN_MASK_ALL) == 0)
- return 1;
- else
- return 0;
+ return 0;
}
int
return 0;
}
-/* -Wmissing-prototypes */
-extern initialize_file_ftype _initialize_objc_language;
-
void
_initialize_objc_language (void)
{
- add_language (&objc_language_defn);
- add_info ("selectors", selectors_info, /* INFO SELECTORS command. */
+ add_info ("selectors", info_selectors_command,
_("All Objective-C selectors, or those matching REGEXP."));
- add_info ("classes", classes_info, /* INFO CLASSES command. */
+ add_info ("classes", info_classes_command,
_("All Objective-C classes, or those matching REGEXP."));
add_com ("print-object", class_vars, print_object_command,
_("Ask an Objective-C object to print itself."));
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
super->receiver = read_memory_unsigned_integer (addr, 4, byte_order);
- super->class = read_memory_unsigned_integer (addr + 4, 4, byte_order);
+ super->theclass = read_memory_unsigned_integer (addr + 4, 4, byte_order);
};
static void
read_objc_class (struct gdbarch *gdbarch, CORE_ADDR addr,
- struct objc_class *class)
+ struct objc_class *theclass)
{
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- class->isa = read_memory_unsigned_integer (addr, 4, byte_order);
- class->super_class = read_memory_unsigned_integer (addr + 4, 4, byte_order);
- class->name = read_memory_unsigned_integer (addr + 8, 4, byte_order);
- class->version = read_memory_unsigned_integer (addr + 12, 4, byte_order);
- class->info = read_memory_unsigned_integer (addr + 16, 4, byte_order);
- class->instance_size = read_memory_unsigned_integer (addr + 18, 4,
+ theclass->isa = read_memory_unsigned_integer (addr, 4, byte_order);
+ theclass->super_class = read_memory_unsigned_integer (addr + 4, 4, byte_order);
+ theclass->name = read_memory_unsigned_integer (addr + 8, 4, byte_order);
+ theclass->version = read_memory_unsigned_integer (addr + 12, 4, byte_order);
+ theclass->info = read_memory_unsigned_integer (addr + 16, 4, byte_order);
+ theclass->instance_size = read_memory_unsigned_integer (addr + 18, 4,
byte_order);
- class->ivars = read_memory_unsigned_integer (addr + 24, 4, byte_order);
- class->methods = read_memory_unsigned_integer (addr + 28, 4, byte_order);
- class->cache = read_memory_unsigned_integer (addr + 32, 4, byte_order);
- class->protocols = read_memory_unsigned_integer (addr + 36, 4, byte_order);
+ theclass->ivars = read_memory_unsigned_integer (addr + 24, 4, byte_order);
+ theclass->methods = read_memory_unsigned_integer (addr + 28, 4, byte_order);
+ theclass->cache = read_memory_unsigned_integer (addr + 32, 4, byte_order);
+ theclass->protocols = read_memory_unsigned_integer (addr + 36, 4, byte_order);
}
static CORE_ADDR
find_implementation_from_class (struct gdbarch *gdbarch,
- CORE_ADDR class, CORE_ADDR sel)
+ CORE_ADDR theclass, CORE_ADDR sel)
{
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- CORE_ADDR subclass = class;
+ CORE_ADDR subclass = theclass;
while (subclass != 0)
{
struct objc_method meth_str;
read_objc_methlist_method (gdbarch, mlist, i, &meth_str);
-#if 0
- fprintf (stderr,
- "checking method 0x%lx against selector 0x%lx\n",
- meth_str.name, sel);
-#endif
if (meth_str.name == sel)
/* FIXME: hppa arch was doing a pointer dereference
sel = gdbarch_fetch_pointer_argument (gdbarch, frame, 1, ptr_type);
read_objc_super (gdbarch, super, &sstr);
- if (sstr.class == 0)
+ if (sstr.theclass == 0)
return 0;
- res = find_implementation_from_class (gdbarch, sstr.class, sel);
+ res = find_implementation_from_class (gdbarch, sstr.theclass, sel);
if (new_pc != 0)
*new_pc = res;
if (res == 0)
sel = gdbarch_fetch_pointer_argument (gdbarch, frame, 2, ptr_type);
read_objc_super (gdbarch, super, &sstr);
- if (sstr.class == 0)
+ if (sstr.theclass == 0)
return 0;
- res = find_implementation_from_class (gdbarch, sstr.class, sel);
+ res = find_implementation_from_class (gdbarch, sstr.theclass, sel);
if (new_pc != 0)
*new_pc = res;
if (res == 0)
return 1;
return 0;
}
-
-void
-_initialize_objc_lang (void)
-{
- objc_objfile_data = register_objfile_data ();
-}