/* Objective-C language support routines for GDB, the GNU debugger.
- Copyright 2002 Free Software Foundation, Inc.
+ Copyright 2002, 2003 Free Software Foundation, Inc.
Contributed by Apple Computer, Inc.
Written by Michael Snyder.
#include "value.h"
#include "symfile.h"
#include "objfiles.h"
-#include "string.h" /* for strchr */
+#include "gdb_string.h" /* for strchr */
#include "target.h" /* for target_has_execution */
#include "gdbcore.h"
#include "gdbcmd.h"
#include "frame.h"
#include "gdb_regex.h"
#include "regcache.h"
+#include "block.h"
#include <ctype.h>
/* Complaints about ObjC classes, selectors, etc. */
-static struct complaint noclass_lookup_complaint = {
- "no way to lookup Objective-C classes", 0, 0
-};
-
-static struct complaint nosel_lookup_complaint = {
- "no way to lookup Objective-C selectors", 0, 0
-};
-
-
#if (!defined __GNUC__ || __GNUC__ < 2 || __GNUC_MINOR__ < (defined __cplusplus ? 6 : 4))
#define __CHECK_FUNCTION ((__const char *) 0)
#else
function = find_function_in_inferior("objc_lookup_class");
else
{
- complain (&noclass_lookup_complaint, 0);
+ complaint (&symfile_complaints, "no way to lookup Objective-C classes");
return 0;
}
function = find_function_in_inferior("sel_get_any_uid");
else
{
- complain (&nosel_lookup_complaint, 0);
+ complaint (&symfile_complaints, "no way to lookup Objective-C selectors");
return 0;
}
/* Objective-C name demangling. */
char *
-objc_demangle (const char *mangled)
+objc_demangle (const char *mangled, int options)
{
char *demangled, *cp;
while (*cp && *cp == '_')
cp++; /* skip any initial underbars in class name */
- if (!(cp = strchr(cp, '_'))) /* find first non-initial underbar */
+ cp = strchr(cp, '_');
+ if (!cp) /* find first non-initial underbar */
{
- free(demangled); /* not mangled name */
+ xfree(demangled); /* not mangled name */
return NULL;
}
if (cp[1] == '_') { /* easy case: no category name */
}
else {
*cp++ = '('; /* less easy case: category name */
- if (!(cp = strchr(cp, '_')))
+ cp = strchr(cp, '_');
+ if (!cp)
{
- free(demangled); /* not mangled name */
+ xfree(demangled); /* not mangled name */
return NULL;
}
*cp++ = ')';
static void
objc_printstr (struct ui_file *stream, char *string,
- unsigned int length, int force_ellipses)
+ unsigned int length, int width, int force_ellipses)
{
register unsigned int i;
unsigned int things_printed = 0;
return (type);
}
+/* Determine if we are currently in the Objective-C dispatch function.
+ If so, get the address of the method function that the dispatcher
+ would call and use that as the function to step into instead. Also
+ skip over the trampoline for the function (if any). This is better
+ for the user since they are only interested in stepping into the
+ method function anyway. */
+static CORE_ADDR
+objc_skip_trampoline (CORE_ADDR stop_pc)
+{
+ CORE_ADDR real_stop_pc;
+ CORE_ADDR method_stop_pc;
+
+ real_stop_pc = SKIP_TRAMPOLINE_CODE (stop_pc);
+
+ if (real_stop_pc != 0)
+ find_objc_msgcall (real_stop_pc, &method_stop_pc);
+ else
+ find_objc_msgcall (stop_pc, &method_stop_pc);
+
+ if (method_stop_pc)
+ {
+ real_stop_pc = SKIP_TRAMPOLINE_CODE (method_stop_pc);
+ if (real_stop_pc == 0)
+ real_stop_pc = method_stop_pc;
+ }
+
+ return real_stop_pc;
+}
+
/* Table mapping opcodes into strings for printing operators
and precedences of the operators. */
c_print_type, /* Print a type using appropriate syntax */
c_val_print, /* Print a value using appropriate syntax */
c_value_print, /* Print a top-level value */
+ objc_skip_trampoline, /* Language specific skip_trampoline */
+ objc_demangle, /* Language specific symbol demangler */
{"", "", "", ""}, /* Binary format info */
{"0%lo", "0", "o", ""}, /* Octal format info */
{"%ld", "", "d", ""}, /* Decimal format info */
s = (char *)xmalloc(len);
strcpy(s, msglist_sel);
strncat(s, p, plen);
- free(msglist_sel);
+ xfree(msglist_sel);
msglist_sel = s;
if (addcolon) {
s[len-2] = ':';
if (!selid)
error("Can't find selector \"%s\"", p);
write_exp_elt_longcst (selid);
- free(p);
+ xfree(p);
write_exp_elt_longcst (val); /* Number of args */
- free(sel);
+ xfree(sel);
return val;
}
}
/*
- * Function: compare_selectors (void *, void *)
+ * Function: compare_selectors (const void *, const void *)
*
* Comparison function for use with qsort. Arguments are symbols or
* msymbols Compares selector part of objc method name alphabetically.
*/
static int
-compare_selectors (void *a, void *b)
+compare_selectors (const void *a, const void *b)
{
char *aname, *bname;
- if ((aname = SYMBOL_SOURCE_NAME (*(struct symbol **) a)) == NULL ||
- (bname = SYMBOL_SOURCE_NAME (*(struct symbol **) b)) == NULL)
+ aname = SYMBOL_PRINT_NAME (*(struct symbol **) a);
+ bname = SYMBOL_PRINT_NAME (*(struct symbol **) b);
+ if (aname == NULL || bname == NULL)
error ("internal: compare_selectors(1)");
- if ((aname = strchr(aname, ' ')) == NULL ||
- (bname = strchr(bname, ' ')) == NULL)
+ aname = strchr(aname, ' ');
+ bname = strchr(bname, ' ');
+ if (aname == NULL || bname == NULL)
error ("internal: compare_selectors(2)");
return specialcmp (aname+1, bname+1);
ALL_MSYMBOLS (objfile, msymbol)
{
QUIT;
- if ((name = SYMBOL_DEMANGLED_NAME (msymbol)) == NULL)
- name = SYMBOL_NAME (msymbol);
+ name = SYMBOL_DEMANGLED_NAME (msymbol);
+ if (name == NULL)
+ name = DEPRECATED_SYMBOL_NAME (msymbol);
if (name &&
(name[0] == '-' || name[0] == '+') &&
name[1] == '[') /* Got a method name. */
ALL_MSYMBOLS (objfile, msymbol)
{
QUIT;
- if ((name = SYMBOL_DEMANGLED_NAME (msymbol)) == NULL)
- name = SYMBOL_NAME (msymbol);
+ name = SYMBOL_DEMANGLED_NAME (msymbol);
+ if (name == NULL)
+ name = DEPRECATED_SYMBOL_NAME (msymbol);
if (name &&
(name[0] == '-' || name[0] == '+') &&
name[1] == '[') /* Got a method name. */
char *p = asel;
QUIT;
- if ((name = SYMBOL_DEMANGLED_NAME (sym_arr[ix])) == NULL)
- name = SYMBOL_NAME (sym_arr[ix]);
+ name = SYMBOL_DEMANGLED_NAME (sym_arr[ix]);
+ if (name == NULL)
+ name = DEPRECATED_SYMBOL_NAME (sym_arr[ix]);
name = strchr (name, ' ') + 1;
if (p[0] && specialcmp(name, p) == 0)
continue; /* Seen this one already (not unique). */
}
/*
- * Function: compare_classes (void *, void *)
+ * Function: compare_classes (const void *, const void *)
*
* Comparison function for use with qsort. Arguments are symbols or
* msymbols Compares class part of objc method name alphabetically.
*/
static int
-compare_classes (void *a, void *b)
+compare_classes (const void *a, const void *b)
{
char *aname, *bname;
- if ((aname = SYMBOL_SOURCE_NAME (*(struct symbol **) a)) == NULL ||
- (bname = SYMBOL_SOURCE_NAME (*(struct symbol **) b)) == NULL)
+ aname = SYMBOL_PRINT_NAME (*(struct symbol **) a);
+ bname = SYMBOL_PRINT_NAME (*(struct symbol **) b);
+ if (aname == NULL || bname == NULL)
error ("internal: compare_classes(1)");
return specialcmp (aname+1, bname+1);
ALL_MSYMBOLS (objfile, msymbol)
{
QUIT;
- if ((name = SYMBOL_DEMANGLED_NAME (msymbol)) == NULL)
- name = SYMBOL_NAME (msymbol);
+ name = SYMBOL_DEMANGLED_NAME (msymbol);
+ if (name == NULL)
+ name = DEPRECATED_SYMBOL_NAME (msymbol);
if (name &&
(name[0] == '-' || name[0] == '+') &&
name[1] == '[') /* Got a method name. */
ALL_MSYMBOLS (objfile, msymbol)
{
QUIT;
- if ((name = SYMBOL_DEMANGLED_NAME (msymbol)) == NULL)
- name = SYMBOL_NAME (msymbol);
+ name = SYMBOL_DEMANGLED_NAME (msymbol);
+ if (name == NULL)
+ name = DEPRECATED_SYMBOL_NAME (msymbol);
if (name &&
(name[0] == '-' || name[0] == '+') &&
name[1] == '[') /* Got a method name. */
char *p = aclass;
QUIT;
- if ((name = SYMBOL_DEMANGLED_NAME (sym_arr[ix])) == NULL)
- name = SYMBOL_NAME (sym_arr[ix]);
+ name = SYMBOL_DEMANGLED_NAME (sym_arr[ix]);
+ if (name == NULL)
+ name = DEPRECATED_SYMBOL_NAME (sym_arr[ix]);
name += 2;
if (p[0] && specialcmp(name, p) == 0)
continue; /* Seen this one already (not unique). */
return s2;
}
-void
+static void
find_methods (struct symtab *symtab, char type,
const char *class, const char *category,
const char *selector, struct symbol **syms,
continue;
if (symtab)
- if ((SYMBOL_VALUE_ADDRESS (msymbol) < block->startaddr) ||
- (SYMBOL_VALUE_ADDRESS (msymbol) >= block->endaddr))
+ if ((SYMBOL_VALUE_ADDRESS (msymbol) < BLOCK_START (block)) ||
+ (SYMBOL_VALUE_ADDRESS (msymbol) >= BLOCK_END (block)))
/* Not in the specified symtab. */
continue;
symname = SYMBOL_DEMANGLED_NAME (msymbol);
if (symname == NULL)
- symname = SYMBOL_NAME (msymbol);
+ symname = DEPRECATED_SYMBOL_NAME (msymbol);
if (symname == NULL)
continue;
sym = find_pc_function (SYMBOL_VALUE_ADDRESS (msymbol));
if (sym != NULL)
{
- const char *newsymname = SYMBOL_DEMANGLED_NAME (sym);
+ const char *newsymname = SYMBOL_DEMANGLED_NAME (sym);
if (newsymname == NULL)
- newsymname = SYMBOL_NAME (sym);
+ newsymname = DEPRECATED_SYMBOL_NAME (sym);
if (strcmp (symname, newsymname) == 0)
{
/* Found a high-level method sym: swap it into the
if (msym != NULL)
{
if (syms)
- syms[csym] = msym;
+ syms[csym] = (struct symbol *)msym;
csym++;
}
}
print_object_command (char *args, int from_tty)
{
struct value *object, *function, *description;
- CORE_ADDR string_addr;
+ CORE_ADDR string_addr, object_addr;
int i = 0;
char c = -1;
make_cleanup (free_current_contents, &expr);
int pc = 0;
-#if 1
object = expr->language_defn->evaluate_exp (builtin_type_void_data_ptr,
expr, &pc, EVAL_NORMAL);
-#else
- object = evaluate_subexp (builtin_type_void_data_ptr,
- expr, &pc, EVAL_NORMAL);
-#endif
do_cleanups (old_chain);
}
- if (!(function = find_function_in_inferior ("_NSPrintForDebugger")))
+ /* Validate the address for sanity. */
+ object_addr = value_as_long (object);
+ read_memory (object_addr, &c, 1);
+
+ function = find_function_in_inferior ("_NSPrintForDebugger");
+ if (function == NULL)
error ("Unable to locate _NSPrintForDebugger in child process");
description = call_function_by_hand (function, 1, &object);
- if ((string_addr = value_as_long (description)) == 0)
+ string_addr = value_as_long (description);
+ if (string_addr == 0)
error ("object returns null description");
read_memory (string_addr + i++, &c, 1);
struct objc_methcall {
char *name;
/* Return instance method to be called. */
- CORE_ADDR (*stop_at) (CORE_ADDR);
+ int (*stop_at) (CORE_ADDR, CORE_ADDR *);
/* Start of pc range corresponding to method invocation. */
CORE_ADDR begin;
/* End of pc range corresponding to method invocation. */
*/
struct objc_submethod_helper_data {
- CORE_ADDR (*f) (CORE_ADDR, CORE_ADDR *);
+ int (*f) (CORE_ADDR, CORE_ADDR *);
CORE_ADDR pc;
CORE_ADDR *new_pc;
};
int
-find_objc_msgcall_submethod_helper (PTR arg)
+find_objc_msgcall_submethod_helper (void * arg)
{
struct objc_submethod_helper_data *s =
(struct objc_submethod_helper_data *) arg;
}
int
-find_objc_msgcall_submethod (CORE_ADDR (*f) (CORE_ADDR, CORE_ADDR *),
+find_objc_msgcall_submethod (int (*f) (CORE_ADDR, CORE_ADDR *),
CORE_ADDR pc,
CORE_ADDR *new_pc)
{
s.new_pc = new_pc;
if (catch_errors (find_objc_msgcall_submethod_helper,
- (PTR) &s,
+ (void *) &s,
"Unable to determine target of Objective-C method call (ignoring):\n",
RETURN_MASK_ALL) == 0)
return 1;
add_info ("classes", classes_info, /* 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.\n");
+ "Ask an Objective-C object to print itself.");
add_com_alias ("po", "print-object", class_vars, 1);
}