* [PATCH] Handle ObjC OPS in eval.c
@ 2003-01-03 20:27 Adam Fedor
2003-01-31 3:07 ` Michael Snyder
0 siblings, 1 reply; 15+ messages in thread
From: Adam Fedor @ 2003-01-03 20:27 UTC (permalink / raw)
To: GDB Patches
[-- Attachment #1: Type: text/plain, Size: 0 bytes --]
[-- Attachment #2: objc21.patch --]
[-- Type: text/plain, Size: 13204 bytes --]
2003-01-02 Adam Fedor <fedor@gnu.org>
* Makefile.in (eval.o): Add $(objc_lang_h)
* eval.c (evaluate_subexp_standard): Handle ObjC ops.
* valops.c (find_function_addr): Make non-static.
* value.h (find_function_addr): Declare.
Index: Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/Makefile.in,v
retrieving revision 1.302
diff -u -p -r1.302 Makefile.in
--- Makefile.in 2 Jan 2003 20:29:15 -0000 1.302
+++ Makefile.in 3 Jan 2003 03:51:46 -0000
@@ -1644,7 +1645,7 @@ elfread.o: elfread.c $(defs_h) $(bfd_h)
environ.o: environ.c $(defs_h) $(environ_h) $(gdb_string_h)
eval.o: eval.c $(defs_h) $(gdb_string_h) $(symtab_h) $(gdbtypes_h) \
$(value_h) $(expression_h) $(target_h) $(frame_h) $(language_h) \
- $(f_lang_h) $(cp_abi_h)
+ $(f_lang_h) $(cp_abi_h) $(objc_lang_h)
event-loop.o: event-loop.c $(defs_h) $(event_loop_h) $(event_top_h) \
$(gdb_string_h)
event-top.o: event-top.c $(defs_h) $(top_h) $(inferior_h) $(target_h) \
Index: eval.c
===================================================================
RCS file: /cvs/src/src/gdb/eval.c,v
retrieving revision 1.26
diff -u -p -r1.26 eval.c
--- eval.c 2 Jan 2003 14:27:26 -0000 1.26
+++ eval.c 3 Jan 2003 20:18:26 -0000
@@ -30,6 +30,7 @@
#include "frame.h"
#include "language.h" /* For CAST_IS_CONVERSION */
#include "f-lang.h" /* for array bound stuff */
+#include "objc-lang.h"
#include "cp-abi.h"
/* Defined in symtab.c */
@@ -470,6 +471,15 @@ evaluate_subexp_standard (struct type *e
goto nosideret;
return value_string (&exp->elts[pc + 2].string, tem);
+ case OP_OBJC_NSSTRING: /* Objective C Foundation Class NSString constant. */
+ tem = longest_to_int (exp->elts[pc + 1].longconst);
+ (*pos) += 3 + BYTES_TO_EXP_ELEM (tem + 1);
+ if (noside == EVAL_SKIP)
+ {
+ goto nosideret;
+ }
+ return (struct value *) value_nsstring (&exp->elts[pc + 2].string, tem + 1);
+
case OP_BITSTRING:
tem = longest_to_int (exp->elts[pc + 1].longconst);
(*pos)
@@ -666,6 +676,297 @@ evaluate_subexp_standard (struct type *e
return arg2;
}
+ case OP_OBJC_SELECTOR:
+ { /* Objective C @selector operator. */
+ char *sel = &exp->elts[pc + 2].string;
+ int len = longest_to_int (exp->elts[pc + 1].longconst);
+
+ (*pos) += 3 + BYTES_TO_EXP_ELEM (len + 1);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+
+ if (sel[len] != 0)
+ sel[len] = 0; /* make sure terminated */
+ return value_from_longest (lookup_pointer_type (builtin_type_void),
+ lookup_child_selector (sel));
+ }
+
+ case OP_OBJC_MSGCALL:
+ { /* Objective C message (method) call. */
+
+ static unsigned long responds_selector = 0;
+ static unsigned long method_selector = 0;
+ static unsigned int selector_generation = 0;
+
+ unsigned long selector = 0;
+
+ int using_gcc = 0;
+ int struct_return = 0;
+ int sub_no_side = 0;
+
+ static struct value *msg_send = NULL;
+ static struct value *msg_send_stret = NULL;
+ static struct value *msg_send_typed = NULL;
+ static int gnu_runtime = 0;
+
+ struct value *target = NULL;
+ struct value *method = NULL;
+ struct value *called_method = NULL;
+
+ struct type *selector_type = NULL;
+
+ struct value *ret = NULL;
+ struct symbol *sym = NULL;
+ CORE_ADDR addr = 0;
+
+ selector = exp->elts[pc + 1].longconst;
+ nargs = exp->elts[pc + 2].longconst;
+ argvec = (struct value **) alloca (sizeof (struct value *)
+ * (nargs + 5));
+
+ (*pos) += 3;
+
+ selector_type = lookup_pointer_type (builtin_type_void);
+ sub_no_side = (noside == EVAL_AVOID_SIDE_EFFECTS)
+ ? EVAL_NORMAL : noside;
+
+ target = evaluate_subexp (selector_type, exp, pos, sub_no_side);
+
+ if (value_as_long (target) == 0)
+ return value_from_longest (builtin_type_long, 0);
+
+ if (lookup_minimal_symbol ("objc_msg_lookup", 0, 0))
+ gnu_runtime = 1;
+
+ if (gnu_runtime)
+ {
+ msg_send = find_function_in_inferior ("objc_msg_lookup");
+ msg_send_stret = find_function_in_inferior ("objc_msg_lookup");
+ msg_send_typed = find_function_in_inferior ("objc_msg_lookup");
+ }
+ else
+ {
+ msg_send = find_function_in_inferior ("objc_msgSend");
+ msg_send_stret = find_function_in_inferior ("objc_msgSend_stret");
+ msg_send_typed = find_function_in_inferior ("objc_msgSend");
+ }
+
+ /* Verify target responds to method selector. This logic needs
+ * work: not sure of GNU variant's name. Must also account for
+ * new (NSObject) and old (Object) worlds
+ */
+
+ if (1)
+ {
+ responds_selector = lookup_child_selector ("respondsToSelector:");
+ if (responds_selector == 0)
+ responds_selector = lookup_child_selector ("respondsTo:");
+
+ if (responds_selector == 0)
+ error ("no 'respondsTo:' or 'respondsToSelector:' method");
+
+ if (gnu_runtime)
+ {
+ method_selector = lookup_child_selector ("methodFor:");
+ if (method_selector == 0)
+ method_selector = lookup_child_selector ("methodForSelector:");
+ }
+ else
+ {
+ method_selector = lookup_child_selector ("methodForSelector:");
+ if (method_selector == 0)
+ method_selector = lookup_child_selector ("methodFor:");
+ }
+
+ if (method_selector == 0)
+ error ("no 'methodFor:' or 'methodForSelector:' method");
+
+ }
+
+ /* call "respondsToSelector:" method, to make sure that
+ * the target class implements the user's desired method selector
+ */
+
+ argvec[0] = msg_send_typed;
+ argvec[1] = target;
+ argvec[2] = value_from_longest (builtin_type_long, responds_selector);
+ argvec[3] = value_from_longest (builtin_type_long, selector);
+ argvec[4] = 0;
+
+ ret = call_function_by_hand (argvec[0], 3, argvec + 1);
+ if (gnu_runtime)
+ {
+ /* objc_msg_lookup returns a pointer */
+ argvec[0] = ret; /* prepare to call the method */
+ ret = call_function_by_hand (argvec[0], 3, argvec + 1);
+ }
+ if (value_as_long (ret) == 0)
+ error ("Target does not respond to this message selector.");
+
+ /* call "methodForSelector:" method, to get the address of a
+ * function method that implements this selector for this class.
+ * If we can find a symbol at that address, then we know the
+ * return type, parameter types etc. (that's a good thing).
+ */
+
+ argvec[0] = msg_send_typed;
+ argvec[1] = target;
+ argvec[2] = value_from_longest (builtin_type_long, method_selector);
+ argvec[3] = value_from_longest (builtin_type_long, selector);
+ argvec[4] = 0;
+
+ ret = call_function_by_hand (argvec[0], 3, argvec + 1);
+ if (gnu_runtime)
+ {
+ argvec[0] = ret; /* prepare to call the method */
+ ret = call_function_by_hand (argvec[0], 3, argvec + 1);
+ }
+
+ /* ret should now be the selector */
+
+ addr = value_as_long (ret);
+ if (addr)
+ {
+ /* is it a high_level symbol? */
+
+#ifdef GDB_TARGET_IS_HPPA
+ CORE_ADDR tmp;
+ /* code and comment lifted from hppa-tdep.c -- unfortunately
+ there is no builtin function to do this for me. */
+ /* If bit 30 (counting from the left) is on, then addr is the
+ address of the PLT entry for this function, not the address
+ of the function itself. Bit 31 has meaning too, but only
+ for MPE. */
+ if (addr & 0x2)
+ addr = (CORE_ADDR) read_memory_unsigned_integer (addr & ~0x3, 4);
+ if (tmp = skip_trampoline_code (addr, 0))
+ addr = tmp; /* in case of trampoline code */
+#endif
+
+ sym = find_pc_function (addr);
+ if (sym != NULL)
+ method = value_of_variable (sym, 0);
+ }
+
+ /* If we found a method with symbol information, check to see
+ * if it returns a struct. Otherwise assume it doesn't.
+ */
+
+ if (method)
+ {
+ struct block *b;
+ CORE_ADDR funaddr;
+ struct type *value_type;
+
+ funaddr = find_function_addr (method, &value_type);
+
+ b = block_for_pc (funaddr);
+
+ /* If compiled without -g, assume GCC 2. */
+ using_gcc = (b == NULL ? 2 : BLOCK_GCC_COMPILED (b));
+
+ CHECK_TYPEDEF (value_type);
+
+ if ((value_type == NULL)
+ || (TYPE_CODE(value_type) == TYPE_CODE_ERROR))
+ {
+ if (expect_type != NULL)
+ value_type = expect_type;
+ }
+
+ struct_return = using_struct_return (method, funaddr, value_type, using_gcc);
+ }
+ else if (expect_type != NULL)
+ {
+ struct_return = using_struct_return (NULL, addr, check_typedef (expect_type), using_gcc);
+ }
+
+ /* Found a function symbol. Now we will substitute its
+ * value in place of the message dispatcher (obj_msgSend),
+ * so that we call the method directly instead of thru
+ * the dispatcher. The main reason for doing this is that
+ * we can now evaluate the return value and parameter values
+ * according to their known data types, in case we need to
+ * do things like promotion, dereferencing, special handling
+ * of structs and doubles, etc.
+ *
+ * We want to use the type signature of 'method', but still
+ * jump to objc_msgSend() or objc_msgSend_stret() to better
+ * mimic the behavior of the runtime.
+ */
+
+ if (method)
+ {
+ if (TYPE_CODE (VALUE_TYPE (method)) != TYPE_CODE_FUNC)
+ error ("method address has symbol information with non-function type; skipping");
+ if (struct_return)
+ VALUE_ADDRESS (method) = value_as_address (msg_send_stret);
+ else
+ VALUE_ADDRESS (method) = value_as_address (msg_send);
+ called_method = method;
+ }
+ else
+ {
+ if (struct_return)
+ called_method = msg_send_stret;
+ else
+ called_method = msg_send;
+ }
+
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+
+ if (noside == EVAL_AVOID_SIDE_EFFECTS)
+ {
+ /* If the return type doesn't look like a function type, call an
+ error. This can happen if somebody tries to turn a variable into
+ a function call. This is here because people often want to
+ call, eg, strcmp, which gdb doesn't know is a function. If
+ gdb isn't asked for it's opinion (ie. through "whatis"),
+ it won't offer it. */
+
+ struct type *type = VALUE_TYPE (called_method);
+ if (type && TYPE_CODE (type) == TYPE_CODE_PTR)
+ type = TYPE_TARGET_TYPE (type);
+ type = TYPE_TARGET_TYPE (type);
+
+ if (type)
+ {
+ if ((TYPE_CODE (type) == TYPE_CODE_ERROR) && expect_type)
+ return allocate_value (expect_type);
+ else
+ return allocate_value (type);
+ }
+ else
+ error ("Expression of type other than \"method returning ...\" used as a method");
+ }
+
+ /* Now depending on whether we found a symbol for the method,
+ * we will either call the runtime dispatcher or the method directly.
+ */
+
+ argvec[0] = called_method;
+ argvec[1] = target;
+ argvec[2] = value_from_longest (builtin_type_long, selector);
+ /* user-supplied arguments */
+ for (tem = 0; tem < nargs; tem++)
+ argvec[tem + 3] = evaluate_subexp_with_coercion (exp, pos, noside);
+ argvec[tem + 3] = 0;
+
+ if (gnu_runtime && (method != NULL))
+ {
+ ret = call_function_by_hand (argvec[0], nargs + 2, argvec + 1);
+ /* objc_msg_lookup returns a pointer */
+ argvec[0] = ret;
+ ret = call_function_by_hand (argvec[0], nargs + 2, argvec + 1);
+ }
+ else
+ ret = call_function_by_hand (argvec[0], nargs + 2, argvec + 1);
+
+ return ret;
+ }
+ break;
+
case OP_FUNCALL:
(*pos) += 2;
op = exp->elts[*pos].opcode;
@@ -1747,6 +2048,10 @@ evaluate_subexp_standard (struct type *e
case OP_THIS:
(*pos) += 1;
return value_of_this (1);
+
+ case OP_OBJC_SELF:
+ (*pos) += 1;
+ return value_of_local ("self", 1);
case OP_TYPE:
error ("Attempt to use a type name as an expression");
Index: valops.c
===================================================================
RCS file: /cvs/src/src/gdb/valops.c,v
retrieving revision 1.85
diff -u -p -r1.85 valops.c
--- valops.c 2 Jan 2003 14:27:27 -0000 1.85
+++ valops.c 3 Jan 2003 03:52:01 -0000
@@ -48,7 +48,6 @@ extern int overload_debug;
static int typecmp (int staticp, int varargs, int nargs,
struct field t1[], struct value *t2[]);
-static CORE_ADDR find_function_addr (struct value *, struct type **);
static struct value *value_arg_coerce (struct value *, struct type *, int);
@@ -1185,7 +1184,7 @@ value_arg_coerce (struct value *arg, str
/* Determine a function's address and its return type from its value.
Calls error() if the function is not valid for calling. */
-static CORE_ADDR
+CORE_ADDR
find_function_addr (struct value *function, struct type **retval_type)
{
register struct type *ftype = check_typedef (VALUE_TYPE (function));
Index: value.h
===================================================================
RCS file: /cvs/src/src/gdb/value.h,v
retrieving revision 1.38
diff -u -p -r1.38 value.h
--- value.h 2 Jan 2003 14:27:27 -0000 1.38
+++ value.h 3 Jan 2003 03:52:02 -0000
@@ -566,6 +566,8 @@ extern CORE_ADDR default_push_arguments
CORE_ADDR sp, int struct_return,
CORE_ADDR struct_addr);
+extern CORE_ADDR find_function_addr (struct value *, struct type **);
+
extern struct value *value_of_local (const char *name, int complain);
#endif /* !defined (VALUE_H) */
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] Handle ObjC OPS in eval.c
2003-01-03 20:27 [PATCH] Handle ObjC OPS in eval.c Adam Fedor
@ 2003-01-31 3:07 ` Michael Snyder
2003-02-07 18:31 ` Adam Fedor
2003-02-13 4:05 ` Adam Fedor
0 siblings, 2 replies; 15+ messages in thread
From: Michael Snyder @ 2003-01-31 3:07 UTC (permalink / raw)
To: Adam Fedor; +Cc: GDB Patches
Adam Fedor wrote:
>
> 2003-01-02 Adam Fedor <fedor@gnu.org>
>
> * Makefile.in (eval.o): Add $(objc_lang_h)
> * eval.c (evaluate_subexp_standard): Handle ObjC ops.
> * valops.c (find_function_addr): Make non-static.
> * value.h (find_function_addr): Declare.
Adam, this is OK in principal, assuming that the objc code
such as value_nsstring is being unconditionally built now.
A few remarks:
>
> + /* Verify target responds to method selector. This logic needs
> + * work: not sure of GNU variant's name. Must also account for
> + * new (NSObject) and old (Object) worlds
> + */
> +
> + if (1)
Is there a reason for this if(1)?
> +
> +#ifdef GDB_TARGET_IS_HPPA
> + CORE_ADDR tmp;
> + /* code and comment lifted from hppa-tdep.c -- unfortunately
> + there is no builtin function to do this for me. */
> + /* If bit 30 (counting from the left) is on, then addr is the
> + address of the PLT entry for this function, not the address
> + of the function itself. Bit 31 has meaning too, but only
> + for MPE. */
> + if (addr & 0x2)
> + addr = (CORE_ADDR) read_memory_unsigned_integer (addr & ~0x3, 4);
> + if (tmp = skip_trampoline_code (addr, 0))
> + addr = tmp; /* in case of trampoline code */
> +#endif
Ifdef gdb_target is a big no-no. Can you use gdbarch for this?
> + if (method)
> + {
> + struct block *b;
> + CORE_ADDR funaddr;
> + struct type *value_type;
> +
> + funaddr = find_function_addr (method, &value_type);
This is surely not the best way to do this. You can get
the address and the type from the symbol. If op_funcall
doesn't need to call it, why does op_objc_msgcall?
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] Handle ObjC OPS in eval.c
2003-01-31 3:07 ` Michael Snyder
@ 2003-02-07 18:31 ` Adam Fedor
2003-02-07 22:04 ` Andrew Cagney
2003-02-13 4:05 ` Adam Fedor
1 sibling, 1 reply; 15+ messages in thread
From: Adam Fedor @ 2003-02-07 18:31 UTC (permalink / raw)
To: Michael Snyder; +Cc: GDB Patches
Michael Snyder wrote:
> Adam Fedor wrote:
>
>>2003-01-02 Adam Fedor <fedor@gnu.org>
>>
>> * Makefile.in (eval.o): Add $(objc_lang_h)
>> * eval.c (evaluate_subexp_standard): Handle ObjC ops.
>> * valops.c (find_function_addr): Make non-static.
>> * value.h (find_function_addr): Declare.
>
>
> Adam, this is OK in principal, assuming that the objc code
> such as value_nsstring is being unconditionally built now.
> A few remarks:
>
>
>>+ /* Verify target responds to method selector. This logic needs
>>+ * work: not sure of GNU variant's name. Must also account for
>>+ * new (NSObject) and old (Object) worlds
>>+ */
>>+
>>+ if (1)
>
>
> Is there a reason for this if(1)?
>
>
Not really. I was trying to maintain a certain compatibility with Apple
source (indentation), but that's probably too much trouble.
>>+
>>+#ifdef GDB_TARGET_IS_HPPA
>>+ CORE_ADDR tmp;
>>+ /* code and comment lifted from hppa-tdep.c -- unfortunately
>>+ there is no builtin function to do this for me. */
>>+ /* If bit 30 (counting from the left) is on, then addr is the
>>+ address of the PLT entry for this function, not the address
>>+ of the function itself. Bit 31 has meaning too, but only
>>+ for MPE. */
>>+ if (addr & 0x2)
>>+ addr = (CORE_ADDR) read_memory_unsigned_integer (addr & ~0x3, 4);
>>+ if (tmp = skip_trampoline_code (addr, 0))
>>+ addr = tmp; /* in case of trampoline code */
>>+#endif
>
>
> Ifdef gdb_target is a big no-no. Can you use gdbarch for this?
>
>
I tried looking at gdbarch, but it's a bit complicated for me so I
couldn't understand much. I saw that OP_FUNCALL was using
if (hp_som_som_object_present)
for a similar type of check. Is that ok to use?
>
>>+ if (method)
>>+ {
>>+ struct block *b;
>>+ CORE_ADDR funaddr;
>>+ struct type *value_type;
>>+
>>+ funaddr = find_function_addr (method, &value_type);
>
>
> This is surely not the best way to do this. You can get
> the address and the type from the symbol. If op_funcall
> doesn't need to call it, why does op_objc_msgcall?
It seems to me that OP_FUNCALL is doing about the same thing (without
having to go through a dispatcher to get the actual function). But
perhaps I'm missing something. Is there a newer way to do this?
--
Adam Fedor, Digital Optics Corp. | I'm glad I hate spinach, because
http://www.doc.com | if I didn't, I'd eat it, and you
| know how I hate the stuff.
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] Handle ObjC OPS in eval.c
2003-02-07 18:31 ` Adam Fedor
@ 2003-02-07 22:04 ` Andrew Cagney
0 siblings, 0 replies; 15+ messages in thread
From: Andrew Cagney @ 2003-02-07 22:04 UTC (permalink / raw)
To: Adam Fedor; +Cc: Michael Snyder, GDB Patches
> +#ifdef GDB_TARGET_IS_HPPA
> + CORE_ADDR tmp;
> + /* code and comment lifted from hppa-tdep.c -- unfortunately
> + there is no builtin function to do this for me. */
> + /* If bit 30 (counting from the left) is on, then addr is the
> + address of the PLT entry for this function, not the address
> + of the function itself. Bit 31 has meaning too, but only
> + for MPE. */
> + if (addr & 0x2)
> + addr = (CORE_ADDR) read_memory_unsigned_integer (addr & ~0x3, 4);
> + if (tmp = skip_trampoline_code (addr, 0))
> + addr = tmp; /* in case of trampoline code */
> +#endif
> I tried looking at gdbarch, but it's a bit complicated for me so I couldn't understand much. I saw that OP_FUNCALL was using
I recommend disabling the above code (perhaps create a bug report to
track this action - you can blame me :-). I don't see Apple objecting
and if someone with a PA ever hits problems, they can fix it :-/
Andrew
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] Handle ObjC OPS in eval.c
2003-01-31 3:07 ` Michael Snyder
2003-02-07 18:31 ` Adam Fedor
@ 2003-02-13 4:05 ` Adam Fedor
2003-02-19 20:05 ` Elena Zannoni
1 sibling, 1 reply; 15+ messages in thread
From: Adam Fedor @ 2003-02-13 4:05 UTC (permalink / raw)
To: Michael Snyder; +Cc: GDB Patches
[-- Attachment #1: Type: text/plain, Size: 608 bytes --]
Michael Snyder wrote:
> Adam Fedor wrote:
>
>>2003-01-02 Adam Fedor <fedor@gnu.org>
>>
>> * Makefile.in (eval.o): Add $(objc_lang_h)
>> * eval.c (evaluate_subexp_standard): Handle ObjC ops.
>> * valops.c (find_function_addr): Make non-static.
>> * value.h (find_function_addr): Declare.
>
>
> Adam, this is OK in principal, assuming that the objc code
> such as value_nsstring is being unconditionally built now.
> A few remarks:
>
I havne't been able to resolve the problem you had with the last part of
the patch, but here is an updated patch with the other changes.
[-- Attachment #2: objc21.patch --]
[-- Type: text/plain, Size: 13233 bytes --]
2003-02-12 Adam Fedor <fedor@gnu.org>
* Makefile.in (eval.o): Add $(objc_lang_h)
* eval.c (evaluate_subexp_standard): Handle ObjC ops.
* valops.c (find_function_addr): Make non-static.
* value.h (find_function_addr): Declare.
Index: Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/Makefile.in,v
retrieving revision 1.329
diff -u -p -r1.329 Makefile.in
--- Makefile.in 11 Feb 2003 16:11:16 -0000 1.329
+++ Makefile.in 13 Feb 2003 02:46:43 -0000
@@ -1641,7 +1642,7 @@ elfread.o: elfread.c $(defs_h) $(bfd_h)
environ.o: environ.c $(defs_h) $(environ_h) $(gdb_string_h)
eval.o: eval.c $(defs_h) $(gdb_string_h) $(symtab_h) $(gdbtypes_h) \
$(value_h) $(expression_h) $(target_h) $(frame_h) $(language_h) \
- $(f_lang_h) $(cp_abi_h)
+ $(f_lang_h) $(cp_abi_h) $(objc_lang_h)
event-loop.o: event-loop.c $(defs_h) $(event_loop_h) $(event_top_h) \
$(gdb_string_h)
event-top.o: event-top.c $(defs_h) $(top_h) $(inferior_h) $(target_h) \
Index: eval.c
===================================================================
RCS file: /cvs/src/src/gdb/eval.c,v
retrieving revision 1.27
diff -u -p -r1.27 eval.c
--- eval.c 14 Jan 2003 00:49:03 -0000 1.27
+++ eval.c 13 Feb 2003 02:46:44 -0000
@@ -31,6 +31,7 @@
#include "frame.h"
#include "language.h" /* For CAST_IS_CONVERSION */
#include "f-lang.h" /* for array bound stuff */
+#include "objc-lang.h"
#include "cp-abi.h"
/* Defined in symtab.c */
@@ -471,6 +472,15 @@ evaluate_subexp_standard (struct type *e
goto nosideret;
return value_string (&exp->elts[pc + 2].string, tem);
+ case OP_OBJC_NSSTRING: /* Objective C Foundation Class NSString constant. */
+ tem = longest_to_int (exp->elts[pc + 1].longconst);
+ (*pos) += 3 + BYTES_TO_EXP_ELEM (tem + 1);
+ if (noside == EVAL_SKIP)
+ {
+ goto nosideret;
+ }
+ return (struct value *) value_nsstring (&exp->elts[pc + 2].string, tem + 1);
+
case OP_BITSTRING:
tem = longest_to_int (exp->elts[pc + 1].longconst);
(*pos)
@@ -667,6 +677,295 @@ evaluate_subexp_standard (struct type *e
return arg2;
}
+ case OP_OBJC_SELECTOR:
+ { /* Objective C @selector operator. */
+ char *sel = &exp->elts[pc + 2].string;
+ int len = longest_to_int (exp->elts[pc + 1].longconst);
+
+ (*pos) += 3 + BYTES_TO_EXP_ELEM (len + 1);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+
+ if (sel[len] != 0)
+ sel[len] = 0; /* Make sure it's terminated. */
+ return value_from_longest (lookup_pointer_type (builtin_type_void),
+ lookup_child_selector (sel));
+ }
+
+ case OP_OBJC_MSGCALL:
+ { /* Objective C message (method) call. */
+
+ static unsigned long responds_selector = 0;
+ static unsigned long method_selector = 0;
+ static unsigned int selector_generation = 0;
+
+ unsigned long selector = 0;
+
+ int using_gcc = 0;
+ int struct_return = 0;
+ int sub_no_side = 0;
+
+ static struct value *msg_send = NULL;
+ static struct value *msg_send_stret = NULL;
+ static struct value *msg_send_typed = NULL;
+ static int gnu_runtime = 0;
+
+ struct value *target = NULL;
+ struct value *method = NULL;
+ struct value *called_method = NULL;
+
+ struct type *selector_type = NULL;
+
+ struct value *ret = NULL;
+ struct symbol *sym = NULL;
+ CORE_ADDR addr = 0;
+
+ selector = exp->elts[pc + 1].longconst;
+ nargs = exp->elts[pc + 2].longconst;
+ argvec = (struct value **) alloca (sizeof (struct value *)
+ * (nargs + 5));
+
+ (*pos) += 3;
+
+ selector_type = lookup_pointer_type (builtin_type_void);
+ sub_no_side = (noside == EVAL_AVOID_SIDE_EFFECTS)
+ ? EVAL_NORMAL : noside;
+
+ target = evaluate_subexp (selector_type, exp, pos, sub_no_side);
+
+ if (value_as_long (target) == 0)
+ return value_from_longest (builtin_type_long, 0);
+
+ if (lookup_minimal_symbol ("objc_msg_lookup", 0, 0))
+ gnu_runtime = 1;
+
+ if (gnu_runtime)
+ {
+ msg_send = find_function_in_inferior ("objc_msg_lookup");
+ msg_send_stret = find_function_in_inferior ("objc_msg_lookup");
+ msg_send_typed = find_function_in_inferior ("objc_msg_lookup");
+ }
+ else
+ {
+ msg_send = find_function_in_inferior ("objc_msgSend");
+ msg_send_stret = find_function_in_inferior ("objc_msgSend_stret");
+ msg_send_typed = find_function_in_inferior ("objc_msgSend");
+ }
+
+ /* Verify target responds to method selector. Must also
+ account for new (NSObject) and old (Object) worlds. */
+
+ responds_selector = lookup_child_selector ("respondsToSelector:");
+ if (responds_selector == 0)
+ responds_selector = lookup_child_selector ("respondsTo:");
+
+ if (responds_selector == 0)
+ error ("no 'respondsTo:' or 'respondsToSelector:' method");
+
+ if (gnu_runtime)
+ {
+ method_selector = lookup_child_selector ("methodFor:");
+ if (method_selector == 0)
+ method_selector = lookup_child_selector ("methodForSelector:");
+ }
+ else
+ {
+ method_selector = lookup_child_selector ("methodForSelector:");
+ if (method_selector == 0)
+ method_selector = lookup_child_selector ("methodFor:");
+ }
+
+ if (method_selector == 0)
+ error ("no 'methodFor:' or 'methodForSelector:' method");
+
+ /* Call "respondsToSelector:" method, to make sure that the
+ target class implements the user's desired method
+ selector. */
+
+ argvec[0] = msg_send_typed;
+ argvec[1] = target;
+ argvec[2] = value_from_longest (builtin_type_long, responds_selector);
+ argvec[3] = value_from_longest (builtin_type_long, selector);
+ argvec[4] = 0;
+
+ ret = call_function_by_hand (argvec[0], 3, argvec + 1);
+ if (gnu_runtime)
+ {
+ /* Function objc_msg_lookup returns a pointer. */
+ argvec[0] = ret;
+ ret = call_function_by_hand (argvec[0], 3, argvec + 1);
+ }
+ if (value_as_long (ret) == 0)
+ error ("Target does not respond to this message selector.");
+
+ /* Call "methodForSelector:" method, to get the address of a
+ function method that implements this selector for this
+ class. If we can find a symbol at that address, then we
+ know the return type, parameter types etc. (that's a good
+ thing). */
+
+ argvec[0] = msg_send_typed;
+ argvec[1] = target;
+ argvec[2] = value_from_longest (builtin_type_long, method_selector);
+ argvec[3] = value_from_longest (builtin_type_long, selector);
+ argvec[4] = 0;
+
+ ret = call_function_by_hand (argvec[0], 3, argvec + 1);
+ if (gnu_runtime)
+ {
+ argvec[0] = ret;
+ ret = call_function_by_hand (argvec[0], 3, argvec + 1);
+ }
+
+ /* ret should now be the selector. */
+
+ addr = value_as_long (ret);
+ if (addr)
+ {
+ /* Is it a high_level symbol? */
+
+#if 0
+ /* Was defined only for HPPA architectures. Commented out
+ since we cannot verify that this works anymore. Anyone
+ experiencing problems on HPPA machines can check this
+ for validity. */
+ CORE_ADDR tmp;
+ /* Code and comment lifted from hppa-tdep.c.
+ Unfortunately there is no builtin function to do
+ this. */
+ /* If bit 30 (counting from the left) is on, then addr
+ is the address of the PLT entry for this function,
+ not the address of the function itself. Bit 31 has
+ meaning too, but only for MPE. */
+ if (addr & 0x2)
+ addr = (CORE_ADDR) read_memory_unsigned_integer (addr & ~0x3, 4);
+ if (tmp = skip_trampoline_code (addr, 0))
+ addr = tmp;
+#endif
+
+ sym = find_pc_function (addr);
+ if (sym != NULL)
+ method = value_of_variable (sym, 0);
+ }
+
+ /* If we found a method with symbol information, check to see
+ if it returns a struct. Otherwise assume it doesn't. */
+
+ if (method)
+ {
+ struct block *b;
+ CORE_ADDR funaddr;
+ struct type *value_type;
+
+ funaddr = find_function_addr (method, &value_type);
+
+ b = block_for_pc (funaddr);
+
+ /* If compiled without -g, assume GCC 2. */
+ using_gcc = (b == NULL ? 2 : BLOCK_GCC_COMPILED (b));
+
+ CHECK_TYPEDEF (value_type);
+
+ if ((value_type == NULL)
+ || (TYPE_CODE(value_type) == TYPE_CODE_ERROR))
+ {
+ if (expect_type != NULL)
+ value_type = expect_type;
+ }
+
+ struct_return = using_struct_return (method, funaddr, value_type, using_gcc);
+ }
+ else if (expect_type != NULL)
+ {
+ struct_return = using_struct_return (NULL, addr, check_typedef (expect_type), using_gcc);
+ }
+
+ /* Found a function symbol. Now we will substitute its
+ value in place of the message dispatcher (obj_msgSend),
+ so that we call the method directly instead of thru
+ the dispatcher. The main reason for doing this is that
+ we can now evaluate the return value and parameter values
+ according to their known data types, in case we need to
+ do things like promotion, dereferencing, special handling
+ of structs and doubles, etc.
+
+ We want to use the type signature of 'method', but still
+ jump to objc_msgSend() or objc_msgSend_stret() to better
+ mimic the behavior of the runtime. */
+
+ if (method)
+ {
+ if (TYPE_CODE (VALUE_TYPE (method)) != TYPE_CODE_FUNC)
+ error ("method address has symbol information with non-function type; skipping");
+ if (struct_return)
+ VALUE_ADDRESS (method) = value_as_address (msg_send_stret);
+ else
+ VALUE_ADDRESS (method) = value_as_address (msg_send);
+ called_method = method;
+ }
+ else
+ {
+ if (struct_return)
+ called_method = msg_send_stret;
+ else
+ called_method = msg_send;
+ }
+
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+
+ if (noside == EVAL_AVOID_SIDE_EFFECTS)
+ {
+ /* If the return type doesn't look like a function type,
+ call an error. This can happen if somebody tries to
+ turn a variable into a function call. This is here
+ because people often want to call, eg, strcmp, which
+ gdb doesn't know is a function. If gdb isn't asked for
+ it's opinion (ie. through "whatis"), it won't offer
+ it. */
+
+ struct type *type = VALUE_TYPE (called_method);
+ if (type && TYPE_CODE (type) == TYPE_CODE_PTR)
+ type = TYPE_TARGET_TYPE (type);
+ type = TYPE_TARGET_TYPE (type);
+
+ if (type)
+ {
+ if ((TYPE_CODE (type) == TYPE_CODE_ERROR) && expect_type)
+ return allocate_value (expect_type);
+ else
+ return allocate_value (type);
+ }
+ else
+ error ("Expression of type other than \"method returning ...\" used as a method");
+ }
+
+ /* Now depending on whether we found a symbol for the method,
+ we will either call the runtime dispatcher or the method
+ directly. */
+
+ argvec[0] = called_method;
+ argvec[1] = target;
+ argvec[2] = value_from_longest (builtin_type_long, selector);
+ /* User-supplied arguments. */
+ for (tem = 0; tem < nargs; tem++)
+ argvec[tem + 3] = evaluate_subexp_with_coercion (exp, pos, noside);
+ argvec[tem + 3] = 0;
+
+ if (gnu_runtime && (method != NULL))
+ {
+ ret = call_function_by_hand (argvec[0], nargs + 2, argvec + 1);
+ /* Function objc_msg_lookup returns a pointer. */
+ argvec[0] = ret;
+ ret = call_function_by_hand (argvec[0], nargs + 2, argvec + 1);
+ }
+ else
+ ret = call_function_by_hand (argvec[0], nargs + 2, argvec + 1);
+
+ return ret;
+ }
+ break;
+
case OP_FUNCALL:
(*pos) += 2;
op = exp->elts[*pos].opcode;
@@ -1748,6 +2047,10 @@ evaluate_subexp_standard (struct type *e
case OP_THIS:
(*pos) += 1;
return value_of_this (1);
+
+ case OP_OBJC_SELF:
+ (*pos) += 1;
+ return value_of_local ("self", 1);
case OP_TYPE:
error ("Attempt to use a type name as an expression");
Index: valops.c
===================================================================
RCS file: /cvs/src/src/gdb/valops.c,v
retrieving revision 1.89
diff -u -p -r1.89 valops.c
--- valops.c 30 Jan 2003 16:44:20 -0000 1.89
+++ valops.c 13 Feb 2003 02:46:52 -0000
@@ -48,7 +48,6 @@ extern int overload_debug;
static int typecmp (int staticp, int varargs, int nargs,
struct field t1[], struct value *t2[]);
-static CORE_ADDR find_function_addr (struct value *, struct type **);
static struct value *value_arg_coerce (struct value *, struct type *, int);
@@ -1172,7 +1171,7 @@ value_arg_coerce (struct value *arg, str
/* Determine a function's address and its return type from its value.
Calls error() if the function is not valid for calling. */
-static CORE_ADDR
+CORE_ADDR
find_function_addr (struct value *function, struct type **retval_type)
{
register struct type *ftype = check_typedef (VALUE_TYPE (function));
Index: value.h
===================================================================
RCS file: /cvs/src/src/gdb/value.h,v
retrieving revision 1.41
diff -u -p -r1.41 value.h
--- value.h 19 Jan 2003 04:06:46 -0000 1.41
+++ value.h 13 Feb 2003 02:46:52 -0000
@@ -563,6 +563,8 @@ extern CORE_ADDR default_push_arguments
CORE_ADDR sp, int struct_return,
CORE_ADDR struct_addr);
+extern CORE_ADDR find_function_addr (struct value *, struct type **);
+
extern struct value *value_of_local (const char *name, int complain);
#endif /* !defined (VALUE_H) */
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] Handle ObjC OPS in eval.c
2003-02-13 4:05 ` Adam Fedor
@ 2003-02-19 20:05 ` Elena Zannoni
2003-03-05 5:06 ` Adam Fedor
0 siblings, 1 reply; 15+ messages in thread
From: Elena Zannoni @ 2003-02-19 20:05 UTC (permalink / raw)
To: Adam Fedor; +Cc: Michael Snyder, GDB Patches
Adam Fedor writes:
>
>
> Michael Snyder wrote:
> > Adam Fedor wrote:
> >
> >>2003-01-02 Adam Fedor <fedor@gnu.org>
> >>
> >> * Makefile.in (eval.o): Add $(objc_lang_h)
> >> * eval.c (evaluate_subexp_standard): Handle ObjC ops.
> >> * valops.c (find_function_addr): Make non-static.
> >> * value.h (find_function_addr): Declare.
> >
> >
> > Adam, this is OK in principal, assuming that the objc code
> > such as value_nsstring is being unconditionally built now.
> > A few remarks:
> >
>
> I havne't been able to resolve the problem you had with the last part of
> the patch, but here is an updated patch with the other changes.
>
a few comments below, from a Objc-naive person.
> 2003-02-12 Adam Fedor <fedor@gnu.org>
>
> * Makefile.in (eval.o): Add $(objc_lang_h)
> * eval.c (evaluate_subexp_standard): Handle ObjC ops.
> * valops.c (find_function_addr): Make non-static.
> * value.h (find_function_addr): Declare.
>
> Index: Makefile.in
> ===================================================================
> RCS file: /cvs/src/src/gdb/Makefile.in,v
> retrieving revision 1.329
> diff -u -p -r1.329 Makefile.in
> --- Makefile.in 11 Feb 2003 16:11:16 -0000 1.329
> +++ Makefile.in 13 Feb 2003 02:46:43 -0000
> @@ -1641,7 +1642,7 @@ elfread.o: elfread.c $(defs_h) $(bfd_h)
> environ.o: environ.c $(defs_h) $(environ_h) $(gdb_string_h)
> eval.o: eval.c $(defs_h) $(gdb_string_h) $(symtab_h) $(gdbtypes_h) \
> $(value_h) $(expression_h) $(target_h) $(frame_h) $(language_h) \
> - $(f_lang_h) $(cp_abi_h)
> + $(f_lang_h) $(cp_abi_h) $(objc_lang_h)
> event-loop.o: event-loop.c $(defs_h) $(event_loop_h) $(event_top_h) \
> $(gdb_string_h)
> event-top.o: event-top.c $(defs_h) $(top_h) $(inferior_h) $(target_h) \
> Index: eval.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/eval.c,v
> retrieving revision 1.27
> diff -u -p -r1.27 eval.c
> --- eval.c 14 Jan 2003 00:49:03 -0000 1.27
> +++ eval.c 13 Feb 2003 02:46:44 -0000
> @@ -31,6 +31,7 @@
> #include "frame.h"
> #include "language.h" /* For CAST_IS_CONVERSION */
> #include "f-lang.h" /* for array bound stuff */
> +#include "objc-lang.h"
> #include "cp-abi.h"
>
> /* Defined in symtab.c */
> @@ -471,6 +472,15 @@ evaluate_subexp_standard (struct type *e
> goto nosideret;
> return value_string (&exp->elts[pc + 2].string, tem);
>
> + case OP_OBJC_NSSTRING: /* Objective C Foundation Class NSString constant. */
> + tem = longest_to_int (exp->elts[pc + 1].longconst);
> + (*pos) += 3 + BYTES_TO_EXP_ELEM (tem + 1);
> + if (noside == EVAL_SKIP)
> + {
> + goto nosideret;
> + }
> + return (struct value *) value_nsstring (&exp->elts[pc + 2].string, tem + 1);
> +
> case OP_BITSTRING:
> tem = longest_to_int (exp->elts[pc + 1].longconst);
> (*pos)
> @@ -667,6 +677,295 @@ evaluate_subexp_standard (struct type *e
> return arg2;
> }
>
> + case OP_OBJC_SELECTOR:
> + { /* Objective C @selector operator. */
> + char *sel = &exp->elts[pc + 2].string;
> + int len = longest_to_int (exp->elts[pc + 1].longconst);
> +
> + (*pos) += 3 + BYTES_TO_EXP_ELEM (len + 1);
> + if (noside == EVAL_SKIP)
> + goto nosideret;
> +
> + if (sel[len] != 0)
> + sel[len] = 0; /* Make sure it's terminated. */
> + return value_from_longest (lookup_pointer_type (builtin_type_void),
> + lookup_child_selector (sel));
> + }
> +
> + case OP_OBJC_MSGCALL:
> + { /* Objective C message (method) call. */
> +
> + static unsigned long responds_selector = 0;
> + static unsigned long method_selector = 0;
> + static unsigned int selector_generation = 0;
> +
> + unsigned long selector = 0;
> +
> + int using_gcc = 0;
> + int struct_return = 0;
> + int sub_no_side = 0;
> +
> + static struct value *msg_send = NULL;
> + static struct value *msg_send_stret = NULL;
> + static struct value *msg_send_typed = NULL;
> + static int gnu_runtime = 0;
> +
> + struct value *target = NULL;
> + struct value *method = NULL;
> + struct value *called_method = NULL;
> +
> + struct type *selector_type = NULL;
> +
> + struct value *ret = NULL;
> + struct symbol *sym = NULL;
> + CORE_ADDR addr = 0;
> +
> + selector = exp->elts[pc + 1].longconst;
> + nargs = exp->elts[pc + 2].longconst;
> + argvec = (struct value **) alloca (sizeof (struct value *)
> + * (nargs + 5));
> +
> + (*pos) += 3;
> +
> + selector_type = lookup_pointer_type (builtin_type_void);
> + sub_no_side = (noside == EVAL_AVOID_SIDE_EFFECTS)
> + ? EVAL_NORMAL : noside;
> +
can you get rid of the conditional expression?
> + target = evaluate_subexp (selector_type, exp, pos, sub_no_side);
> +
> + if (value_as_long (target) == 0)
> + return value_from_longest (builtin_type_long, 0);
> +
> + if (lookup_minimal_symbol ("objc_msg_lookup", 0, 0))
> + gnu_runtime = 1;
> +
> + if (gnu_runtime)
> + {
> + msg_send = find_function_in_inferior ("objc_msg_lookup");
> + msg_send_stret = find_function_in_inferior ("objc_msg_lookup");
> + msg_send_typed = find_function_in_inferior ("objc_msg_lookup");
> + }
> + else
> + {
> + msg_send = find_function_in_inferior ("objc_msgSend");
> + msg_send_stret = find_function_in_inferior ("objc_msgSend_stret");
> + msg_send_typed = find_function_in_inferior ("objc_msgSend");
> + }
> +
I think we need more comments, I guess stret means structure return?
What are these methods used for? Also can you add a high level
description of how these dispatchers get into the picture?
> + /* Verify target responds to method selector. Must also
> + account for new (NSObject) and old (Object) worlds. */
> +
> + responds_selector = lookup_child_selector ("respondsToSelector:");
> + if (responds_selector == 0)
> + responds_selector = lookup_child_selector ("respondsTo:");
> +
> + if (responds_selector == 0)
> + error ("no 'respondsTo:' or 'respondsToSelector:' method");
> +
> + if (gnu_runtime)
> + {
> + method_selector = lookup_child_selector ("methodFor:");
> + if (method_selector == 0)
> + method_selector = lookup_child_selector ("methodForSelector:");
> + }
> + else
> + {
> + method_selector = lookup_child_selector ("methodForSelector:");
> + if (method_selector == 0)
> + method_selector = lookup_child_selector ("methodFor:");
> + }
> +
> + if (method_selector == 0)
> + error ("no 'methodFor:' or 'methodForSelector:' method");
> +
> + /* Call "respondsToSelector:" method, to make sure that the
> + target class implements the user's desired method
> + selector. */
> +
> + argvec[0] = msg_send_typed;
> + argvec[1] = target;
> + argvec[2] = value_from_longest (builtin_type_long, responds_selector);
> + argvec[3] = value_from_longest (builtin_type_long, selector);
> + argvec[4] = 0;
> +
> + ret = call_function_by_hand (argvec[0], 3, argvec + 1);
> + if (gnu_runtime)
> + {
> + /* Function objc_msg_lookup returns a pointer. */
> + argvec[0] = ret;
> + ret = call_function_by_hand (argvec[0], 3, argvec + 1);
> + }
> + if (value_as_long (ret) == 0)
> + error ("Target does not respond to this message selector.");
> +
> + /* Call "methodForSelector:" method, to get the address of a
> + function method that implements this selector for this
> + class. If we can find a symbol at that address, then we
> + know the return type, parameter types etc. (that's a good
> + thing). */
> +
> + argvec[0] = msg_send_typed;
> + argvec[1] = target;
> + argvec[2] = value_from_longest (builtin_type_long, method_selector);
> + argvec[3] = value_from_longest (builtin_type_long, selector);
> + argvec[4] = 0;
> +
> + ret = call_function_by_hand (argvec[0], 3, argvec + 1);
> + if (gnu_runtime)
> + {
> + argvec[0] = ret;
> + ret = call_function_by_hand (argvec[0], 3, argvec + 1);
> + }
> +
> + /* ret should now be the selector. */
> +
> + addr = value_as_long (ret);
> + if (addr)
> + {
> + /* Is it a high_level symbol? */
> +
> +#if 0
> + /* Was defined only for HPPA architectures. Commented out
> + since we cannot verify that this works anymore. Anyone
> + experiencing problems on HPPA machines can check this
> + for validity. */
> + CORE_ADDR tmp;
> + /* Code and comment lifted from hppa-tdep.c.
> + Unfortunately there is no builtin function to do
> + this. */
> + /* If bit 30 (counting from the left) is on, then addr
> + is the address of the PLT entry for this function,
> + not the address of the function itself. Bit 31 has
> + meaning too, but only for MPE. */
> + if (addr & 0x2)
> + addr = (CORE_ADDR) read_memory_unsigned_integer (addr & ~0x3, 4);
> + if (tmp = skip_trampoline_code (addr, 0))
> + addr = tmp;
> +#endif
> +
> + sym = find_pc_function (addr);
> + if (sym != NULL)
> + method = value_of_variable (sym, 0);
> + }
> +
> + /* If we found a method with symbol information, check to see
> + if it returns a struct. Otherwise assume it doesn't. */
> +
> + if (method)
> + {
> + struct block *b;
> + CORE_ADDR funaddr;
> + struct type *value_type;
> +
> + funaddr = find_function_addr (method, &value_type);
> +
> + b = block_for_pc (funaddr);
> +
> + /* If compiled without -g, assume GCC 2. */
> + using_gcc = (b == NULL ? 2 : BLOCK_GCC_COMPILED (b));
> +
> + CHECK_TYPEDEF (value_type);
> +
> + if ((value_type == NULL)
> + || (TYPE_CODE(value_type) == TYPE_CODE_ERROR))
> + {
> + if (expect_type != NULL)
> + value_type = expect_type;
> + }
> +
> + struct_return = using_struct_return (method, funaddr, value_type, using_gcc);
> + }
> + else if (expect_type != NULL)
> + {
> + struct_return = using_struct_return (NULL, addr, check_typedef (expect_type), using_gcc);
> + }
> +
> + /* Found a function symbol. Now we will substitute its
> + value in place of the message dispatcher (obj_msgSend),
> + so that we call the method directly instead of thru
> + the dispatcher. The main reason for doing this is that
> + we can now evaluate the return value and parameter values
> + according to their known data types, in case we need to
> + do things like promotion, dereferencing, special handling
> + of structs and doubles, etc.
> +
> + We want to use the type signature of 'method', but still
> + jump to objc_msgSend() or objc_msgSend_stret() to better
> + mimic the behavior of the runtime. */
> +
> + if (method)
> + {
> + if (TYPE_CODE (VALUE_TYPE (method)) != TYPE_CODE_FUNC)
> + error ("method address has symbol information with non-function type; skipping");
> + if (struct_return)
> + VALUE_ADDRESS (method) = value_as_address (msg_send_stret);
> + else
> + VALUE_ADDRESS (method) = value_as_address (msg_send);
> + called_method = method;
> + }
> + else
> + {
> + if (struct_return)
> + called_method = msg_send_stret;
> + else
> + called_method = msg_send;
> + }
> +
> + if (noside == EVAL_SKIP)
> + goto nosideret;
> +
> + if (noside == EVAL_AVOID_SIDE_EFFECTS)
> + {
> + /* If the return type doesn't look like a function type,
> + call an error. This can happen if somebody tries to
> + turn a variable into a function call. This is here
> + because people often want to call, eg, strcmp, which
> + gdb doesn't know is a function. If gdb isn't asked for
> + it's opinion (ie. through "whatis"), it won't offer
> + it. */
> +
> + struct type *type = VALUE_TYPE (called_method);
> + if (type && TYPE_CODE (type) == TYPE_CODE_PTR)
> + type = TYPE_TARGET_TYPE (type);
> + type = TYPE_TARGET_TYPE (type);
> +
> + if (type)
> + {
> + if ((TYPE_CODE (type) == TYPE_CODE_ERROR) && expect_type)
> + return allocate_value (expect_type);
> + else
> + return allocate_value (type);
> + }
> + else
> + error ("Expression of type other than \"method returning ...\" used as a method");
> + }
> +
> + /* Now depending on whether we found a symbol for the method,
> + we will either call the runtime dispatcher or the method
> + directly. */
> +
> + argvec[0] = called_method;
> + argvec[1] = target;
> + argvec[2] = value_from_longest (builtin_type_long, selector);
> + /* User-supplied arguments. */
> + for (tem = 0; tem < nargs; tem++)
> + argvec[tem + 3] = evaluate_subexp_with_coercion (exp, pos, noside);
> + argvec[tem + 3] = 0;
> +
> + if (gnu_runtime && (method != NULL))
> + {
> + ret = call_function_by_hand (argvec[0], nargs + 2, argvec + 1);
> + /* Function objc_msg_lookup returns a pointer. */
> + argvec[0] = ret;
> + ret = call_function_by_hand (argvec[0], nargs + 2, argvec + 1);
> + }
> + else
> + ret = call_function_by_hand (argvec[0], nargs + 2, argvec + 1);
> +
> + return ret;
> + }
> + break;
> +
> case OP_FUNCALL:
> (*pos) += 2;
> op = exp->elts[*pos].opcode;
> @@ -1748,6 +2047,10 @@ evaluate_subexp_standard (struct type *e
> case OP_THIS:
> (*pos) += 1;
> return value_of_this (1);
> +
> + case OP_OBJC_SELF:
> + (*pos) += 1;
> + return value_of_local ("self", 1);
>
> case OP_TYPE:
> error ("Attempt to use a type name as an expression");
> Index: valops.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/valops.c,v
> retrieving revision 1.89
> diff -u -p -r1.89 valops.c
> --- valops.c 30 Jan 2003 16:44:20 -0000 1.89
> +++ valops.c 13 Feb 2003 02:46:52 -0000
> @@ -48,7 +48,6 @@ extern int overload_debug;
> static int typecmp (int staticp, int varargs, int nargs,
> struct field t1[], struct value *t2[]);
>
> -static CORE_ADDR find_function_addr (struct value *, struct type **);
> static struct value *value_arg_coerce (struct value *, struct type *, int);
>
>
> @@ -1172,7 +1171,7 @@ value_arg_coerce (struct value *arg, str
> /* Determine a function's address and its return type from its value.
> Calls error() if the function is not valid for calling. */
>
> -static CORE_ADDR
> +CORE_ADDR
> find_function_addr (struct value *function, struct type **retval_type)
> {
> register struct type *ftype = check_typedef (VALUE_TYPE (function));
> Index: value.h
> ===================================================================
> RCS file: /cvs/src/src/gdb/value.h,v
> retrieving revision 1.41
> diff -u -p -r1.41 value.h
> --- value.h 19 Jan 2003 04:06:46 -0000 1.41
> +++ value.h 13 Feb 2003 02:46:52 -0000
> @@ -563,6 +563,8 @@ extern CORE_ADDR default_push_arguments
> CORE_ADDR sp, int struct_return,
> CORE_ADDR struct_addr);
>
> +extern CORE_ADDR find_function_addr (struct value *, struct type **);
> +
> extern struct value *value_of_local (const char *name, int complain);
>
> #endif /* !defined (VALUE_H) */
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] Handle ObjC OPS in eval.c
2003-02-19 20:05 ` Elena Zannoni
@ 2003-03-05 5:06 ` Adam Fedor
2003-04-10 21:56 ` Elena Zannoni
0 siblings, 1 reply; 15+ messages in thread
From: Adam Fedor @ 2003-03-05 5:06 UTC (permalink / raw)
To: Elena Zannoni; +Cc: Michael Snyder, GDB Patches
[-- Attachment #1: Type: text/plain, Size: 291 bytes --]
Elena Zannoni wrote:
[...]
>
> I think we need more comments, I guess stret means structure return?
> What are these methods used for? Also can you add a high level
> description of how these dispatchers get into the picture?
>
Here's a better documented and slightly cleaned-up patch.
[-- Attachment #2: objc21.patch --]
[-- Type: text/plain, Size: 13512 bytes --]
2003-03-04 Adam Fedor <fedor@gnu.org>
* Makefile.in (eval.o): Add $(objc_lang_h) (block_h)
* eval.c (evaluate_subexp_standard): Handle ObjC ops.
* valops.c (find_function_addr): Make non-static.
* value.h (find_function_addr): Declare.
Index: Makefile.in
===================================================================
RCS file: /cvs/src/src/gdb/Makefile.in,v
retrieving revision 1.329
diff -u -p -r1.329 Makefile.in
--- Makefile.in 11 Feb 2003 16:11:16 -0000 1.329
+++ Makefile.in 13 Feb 2003 02:46:43 -0000
@@ -1641,7 +1642,7 @@ elfread.o: elfread.c $(defs_h) $(bfd_h)
environ.o: environ.c $(defs_h) $(environ_h) $(gdb_string_h)
eval.o: eval.c $(defs_h) $(gdb_string_h) $(symtab_h) $(gdbtypes_h) \
$(value_h) $(expression_h) $(target_h) $(frame_h) $(language_h) \
- $(f_lang_h) $(cp_abi_h)
+ $(f_lang_h) $(cp_abi_h) $(objc_lang_h) $(block_h)
event-loop.o: event-loop.c $(defs_h) $(event_loop_h) $(event_top_h) \
$(gdb_string_h)
event-top.o: event-top.c $(defs_h) $(top_h) $(inferior_h) $(target_h) \
Index: eval.c
===================================================================
RCS file: /cvs/src/src/gdb/eval.c,v
retrieving revision 1.27
diff -u -p -r1.27 eval.c
--- eval.c 14 Jan 2003 00:49:03 -0000 1.27
+++ eval.c 5 Mar 2003 04:59:34 -0000
@@ -31,7 +31,9 @@
#include "frame.h"
#include "language.h" /* For CAST_IS_CONVERSION */
#include "f-lang.h" /* for array bound stuff */
+#include "objc-lang.h"
#include "cp-abi.h"
+#include "block.h"
/* Defined in symtab.c */
extern int hp_som_som_object_present;
@@ -471,6 +473,15 @@ evaluate_subexp_standard (struct type *e
goto nosideret;
return value_string (&exp->elts[pc + 2].string, tem);
+ case OP_OBJC_NSSTRING: /* Objective C Foundation Class NSString constant. */
+ tem = longest_to_int (exp->elts[pc + 1].longconst);
+ (*pos) += 3 + BYTES_TO_EXP_ELEM (tem + 1);
+ if (noside == EVAL_SKIP)
+ {
+ goto nosideret;
+ }
+ return (struct value *) value_nsstring (&exp->elts[pc + 2].string, tem + 1);
+
case OP_BITSTRING:
tem = longest_to_int (exp->elts[pc + 1].longconst);
(*pos)
@@ -667,6 +678,296 @@ evaluate_subexp_standard (struct type *e
return arg2;
}
+ case OP_OBJC_SELECTOR:
+ { /* Objective C @selector operator. */
+ char *sel = &exp->elts[pc + 2].string;
+ int len = longest_to_int (exp->elts[pc + 1].longconst);
+
+ (*pos) += 3 + BYTES_TO_EXP_ELEM (len + 1);
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+
+ if (sel[len] != 0)
+ sel[len] = 0; /* Make sure it's terminated. */
+ return value_from_longest (lookup_pointer_type (builtin_type_void),
+ lookup_child_selector (sel));
+ }
+
+ case OP_OBJC_MSGCALL:
+ { /* Objective C message (method) call. */
+
+ static unsigned long responds_selector = 0;
+ static unsigned long method_selector = 0;
+
+ unsigned long selector = 0;
+
+ int using_gcc = 0;
+ int struct_return = 0;
+ int sub_no_side = 0;
+
+ static struct value *msg_send = NULL;
+ static struct value *msg_send_stret = NULL;
+ static int gnu_runtime = 0;
+
+ struct value *target = NULL;
+ struct value *method = NULL;
+ struct value *called_method = NULL;
+
+ struct type *selector_type = NULL;
+
+ struct value *ret = NULL;
+ CORE_ADDR addr = 0;
+
+ selector = exp->elts[pc + 1].longconst;
+ nargs = exp->elts[pc + 2].longconst;
+ argvec = (struct value **) alloca (sizeof (struct value *)
+ * (nargs + 5));
+
+ (*pos) += 3;
+
+ selector_type = lookup_pointer_type (builtin_type_void);
+ if (noside == EVAL_AVOID_SIDE_EFFECTS)
+ sub_no_side = EVAL_NORMAL;
+ else
+ sub_no_side = noside;
+
+ target = evaluate_subexp (selector_type, exp, pos, sub_no_side);
+
+ if (value_as_long (target) == 0)
+ return value_from_longest (builtin_type_long, 0);
+
+ if (lookup_minimal_symbol ("objc_msg_lookup", 0, 0))
+ gnu_runtime = 1;
+
+ /* Find the method dispatch (Apple runtime) or method lookup
+ (GNU runtime) function for Objective-C. These will be used
+ to lookup the symbol information for the method. If we
+ can't find any symbol information, then we'll use these to
+ call the method, otherwise we can call the method
+ directly. The msg_send_stret function is used in the special
+ case of a method that returns a structure (Apple runtime
+ only). */
+ if (gnu_runtime)
+ {
+ msg_send = find_function_in_inferior ("objc_msg_lookup");
+ msg_send_stret = find_function_in_inferior ("objc_msg_lookup");
+ }
+ else
+ {
+ msg_send = find_function_in_inferior ("objc_msgSend");
+ /* Special dispatcher for methods returning structs */
+ msg_send_stret = find_function_in_inferior ("objc_msgSend_stret");
+ }
+
+ /* Verify the target object responds to this method. The
+ standard top-level 'Object' class uses a different name for
+ the verification method than the non-standard, but more
+ often used, 'NSObject' class. Make sure we check for both. */
+
+ responds_selector = lookup_child_selector ("respondsToSelector:");
+ if (responds_selector == 0)
+ responds_selector = lookup_child_selector ("respondsTo:");
+
+ if (responds_selector == 0)
+ error ("no 'respondsTo:' or 'respondsToSelector:' method");
+
+ method_selector = lookup_child_selector ("methodForSelector:");
+ if (method_selector == 0)
+ method_selector = lookup_child_selector ("methodFor:");
+
+ if (method_selector == 0)
+ error ("no 'methodFor:' or 'methodForSelector:' method");
+
+ /* Call the verification method, to make sure that the target
+ class implements the desired method. */
+
+ argvec[0] = msg_send;
+ argvec[1] = target;
+ argvec[2] = value_from_longest (builtin_type_long, responds_selector);
+ argvec[3] = value_from_longest (builtin_type_long, selector);
+ argvec[4] = 0;
+
+ ret = call_function_by_hand (argvec[0], 3, argvec + 1);
+ if (gnu_runtime)
+ {
+ /* Function objc_msg_lookup returns a pointer. */
+ argvec[0] = ret;
+ ret = call_function_by_hand (argvec[0], 3, argvec + 1);
+ }
+ if (value_as_long (ret) == 0)
+ error ("Target does not respond to this message selector.");
+
+ /* Call "methodForSelector:" method, to get the address of a
+ function method that implements this selector for this
+ class. If we can find a symbol at that address, then we
+ know the return type, parameter types etc. (that's a good
+ thing). */
+
+ argvec[0] = msg_send;
+ argvec[1] = target;
+ argvec[2] = value_from_longest (builtin_type_long, method_selector);
+ argvec[3] = value_from_longest (builtin_type_long, selector);
+ argvec[4] = 0;
+
+ ret = call_function_by_hand (argvec[0], 3, argvec + 1);
+ if (gnu_runtime)
+ {
+ argvec[0] = ret;
+ ret = call_function_by_hand (argvec[0], 3, argvec + 1);
+ }
+
+ /* ret should now be the selector. */
+
+ addr = value_as_long (ret);
+ if (addr)
+ {
+ struct symbol *sym = NULL;
+ /* Is it a high_level symbol? */
+
+#if 0
+ /* Was defined only for HPPA architectures. Commented out
+ since we cannot verify that this works anymore. Anyone
+ experiencing problems on HPPA machines can check this
+ for validity. */
+ CORE_ADDR tmp;
+ /* Code and comment lifted from hppa-tdep.c.
+ Unfortunately there is no builtin function to do
+ this. */
+ /* If bit 30 (counting from the left) is on, then addr
+ is the address of the PLT entry for this function,
+ not the address of the function itself. Bit 31 has
+ meaning too, but only for MPE. */
+ if (addr & 0x2)
+ addr = (CORE_ADDR) read_memory_unsigned_integer (addr & ~0x3, 4);
+ if (tmp = skip_trampoline_code (addr, 0))
+ addr = tmp;
+#endif
+
+ sym = find_pc_function (addr);
+ if (sym != NULL)
+ method = value_of_variable (sym, 0);
+ }
+
+ /* If we found a method with symbol information, check to see
+ if it returns a struct. Otherwise assume it doesn't. */
+
+ if (method)
+ {
+ struct block *b;
+ CORE_ADDR funaddr;
+ struct type *value_type;
+
+ funaddr = find_function_addr (method, &value_type);
+
+ b = block_for_pc (funaddr);
+
+ /* If compiled without -g, assume GCC 2. */
+ using_gcc = (b == NULL ? 2 : BLOCK_GCC_COMPILED (b));
+
+ CHECK_TYPEDEF (value_type);
+
+ if ((value_type == NULL)
+ || (TYPE_CODE(value_type) == TYPE_CODE_ERROR))
+ {
+ if (expect_type != NULL)
+ value_type = expect_type;
+ }
+
+ struct_return = using_struct_return (method, funaddr, value_type, using_gcc);
+ }
+ else if (expect_type != NULL)
+ {
+ struct_return = using_struct_return (NULL, addr, check_typedef (expect_type), using_gcc);
+ }
+
+ /* Found a function symbol. Now we will substitute its
+ value in place of the message dispatcher (obj_msgSend),
+ so that we call the method directly instead of thru
+ the dispatcher. The main reason for doing this is that
+ we can now evaluate the return value and parameter values
+ according to their known data types, in case we need to
+ do things like promotion, dereferencing, special handling
+ of structs and doubles, etc.
+
+ We want to use the type signature of 'method', but still
+ jump to objc_msgSend() or objc_msgSend_stret() to better
+ mimic the behavior of the runtime. */
+
+ if (method)
+ {
+ if (TYPE_CODE (VALUE_TYPE (method)) != TYPE_CODE_FUNC)
+ error ("method address has symbol information with non-function type; skipping");
+ if (struct_return)
+ VALUE_ADDRESS (method) = value_as_address (msg_send_stret);
+ else
+ VALUE_ADDRESS (method) = value_as_address (msg_send);
+ called_method = method;
+ }
+ else
+ {
+ if (struct_return)
+ called_method = msg_send_stret;
+ else
+ called_method = msg_send;
+ }
+
+ if (noside == EVAL_SKIP)
+ goto nosideret;
+
+ if (noside == EVAL_AVOID_SIDE_EFFECTS)
+ {
+ /* If the return type doesn't look like a function type,
+ call an error. This can happen if somebody tries to
+ turn a variable into a function call. This is here
+ because people often want to call, eg, strcmp, which
+ gdb doesn't know is a function. If gdb isn't asked for
+ it's opinion (ie. through "whatis"), it won't offer
+ it. */
+
+ struct type *type = VALUE_TYPE (called_method);
+ if (type && TYPE_CODE (type) == TYPE_CODE_PTR)
+ type = TYPE_TARGET_TYPE (type);
+ type = TYPE_TARGET_TYPE (type);
+
+ if (type)
+ {
+ if ((TYPE_CODE (type) == TYPE_CODE_ERROR) && expect_type)
+ return allocate_value (expect_type);
+ else
+ return allocate_value (type);
+ }
+ else
+ error ("Expression of type other than \"method returning ...\" used as a method");
+ }
+
+ /* Now depending on whether we found a symbol for the method,
+ we will either call the runtime dispatcher or the method
+ directly. */
+
+ argvec[0] = called_method;
+ argvec[1] = target;
+ argvec[2] = value_from_longest (builtin_type_long, selector);
+ /* User-supplied arguments. */
+ for (tem = 0; tem < nargs; tem++)
+ argvec[tem + 3] = evaluate_subexp_with_coercion (exp, pos, noside);
+ argvec[tem + 3] = 0;
+
+ if (gnu_runtime && (method != NULL))
+ {
+ ret = call_function_by_hand (argvec[0], nargs + 2, argvec + 1);
+ /* Function objc_msg_lookup returns a pointer. */
+ argvec[0] = ret;
+ ret = call_function_by_hand (argvec[0],
+ nargs + 2, argvec + 1);
+ }
+ else
+ ret = call_function_by_hand (argvec[0],
+ nargs + 2, argvec + 1);
+
+ return ret;
+ }
+ break;
+
case OP_FUNCALL:
(*pos) += 2;
op = exp->elts[*pos].opcode;
@@ -1748,6 +2054,10 @@ evaluate_subexp_standard (struct type *e
case OP_THIS:
(*pos) += 1;
return value_of_this (1);
+
+ case OP_OBJC_SELF:
+ (*pos) += 1;
+ return value_of_local ("self", 1);
case OP_TYPE:
error ("Attempt to use a type name as an expression");
Index: valops.c
===================================================================
RCS file: /cvs/src/src/gdb/valops.c,v
retrieving revision 1.89
diff -u -p -r1.89 valops.c
--- valops.c 30 Jan 2003 16:44:20 -0000 1.89
+++ valops.c 13 Feb 2003 02:46:52 -0000
@@ -48,7 +48,6 @@ extern int overload_debug;
static int typecmp (int staticp, int varargs, int nargs,
struct field t1[], struct value *t2[]);
-static CORE_ADDR find_function_addr (struct value *, struct type **);
static struct value *value_arg_coerce (struct value *, struct type *, int);
@@ -1172,7 +1171,7 @@ value_arg_coerce (struct value *arg, str
/* Determine a function's address and its return type from its value.
Calls error() if the function is not valid for calling. */
-static CORE_ADDR
+CORE_ADDR
find_function_addr (struct value *function, struct type **retval_type)
{
register struct type *ftype = check_typedef (VALUE_TYPE (function));
Index: value.h
===================================================================
RCS file: /cvs/src/src/gdb/value.h,v
retrieving revision 1.41
diff -u -p -r1.41 value.h
--- value.h 19 Jan 2003 04:06:46 -0000 1.41
+++ value.h 13 Feb 2003 02:46:52 -0000
@@ -563,6 +563,8 @@ extern CORE_ADDR default_push_arguments
CORE_ADDR sp, int struct_return,
CORE_ADDR struct_addr);
+extern CORE_ADDR find_function_addr (struct value *, struct type **);
+
extern struct value *value_of_local (const char *name, int complain);
#endif /* !defined (VALUE_H) */
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] Handle ObjC OPS in eval.c
2003-03-05 5:06 ` Adam Fedor
@ 2003-04-10 21:56 ` Elena Zannoni
2003-04-20 3:42 ` Adam Fedor
0 siblings, 1 reply; 15+ messages in thread
From: Elena Zannoni @ 2003-04-10 21:56 UTC (permalink / raw)
To: Adam Fedor; +Cc: Elena Zannoni, Michael Snyder, GDB Patches
Adam Fedor writes:
>
>
> Elena Zannoni wrote:
> [...]
> >
> > I think we need more comments, I guess stret means structure return?
> > What are these methods used for? Also can you add a high level
> > description of how these dispatchers get into the picture?
> >
>
> Here's a better documented and slightly cleaned-up patch.
> 2003-03-04 Adam Fedor <fedor@gnu.org>
I think it's ok. Except I don't like to introduce more #if0 code with new code.
Do we really need that part?
elena
>
> * Makefile.in (eval.o): Add $(objc_lang_h) (block_h)
> * eval.c (evaluate_subexp_standard): Handle ObjC ops.
> * valops.c (find_function_addr): Make non-static.
> * value.h (find_function_addr): Declare.
>
> Index: Makefile.in
> ===================================================================
> RCS file: /cvs/src/src/gdb/Makefile.in,v
> retrieving revision 1.329
> diff -u -p -r1.329 Makefile.in
> --- Makefile.in 11 Feb 2003 16:11:16 -0000 1.329
> +++ Makefile.in 13 Feb 2003 02:46:43 -0000
> @@ -1641,7 +1642,7 @@ elfread.o: elfread.c $(defs_h) $(bfd_h)
> environ.o: environ.c $(defs_h) $(environ_h) $(gdb_string_h)
> eval.o: eval.c $(defs_h) $(gdb_string_h) $(symtab_h) $(gdbtypes_h) \
> $(value_h) $(expression_h) $(target_h) $(frame_h) $(language_h) \
> - $(f_lang_h) $(cp_abi_h)
> + $(f_lang_h) $(cp_abi_h) $(objc_lang_h) $(block_h)
> event-loop.o: event-loop.c $(defs_h) $(event_loop_h) $(event_top_h) \
> $(gdb_string_h)
> event-top.o: event-top.c $(defs_h) $(top_h) $(inferior_h) $(target_h) \
> Index: eval.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/eval.c,v
> retrieving revision 1.27
> diff -u -p -r1.27 eval.c
> --- eval.c 14 Jan 2003 00:49:03 -0000 1.27
> +++ eval.c 5 Mar 2003 04:59:34 -0000
> @@ -31,7 +31,9 @@
> #include "frame.h"
> #include "language.h" /* For CAST_IS_CONVERSION */
> #include "f-lang.h" /* for array bound stuff */
> +#include "objc-lang.h"
> #include "cp-abi.h"
> +#include "block.h"
>
> /* Defined in symtab.c */
> extern int hp_som_som_object_present;
> @@ -471,6 +473,15 @@ evaluate_subexp_standard (struct type *e
> goto nosideret;
> return value_string (&exp->elts[pc + 2].string, tem);
>
> + case OP_OBJC_NSSTRING: /* Objective C Foundation Class NSString constant. */
> + tem = longest_to_int (exp->elts[pc + 1].longconst);
> + (*pos) += 3 + BYTES_TO_EXP_ELEM (tem + 1);
> + if (noside == EVAL_SKIP)
> + {
> + goto nosideret;
> + }
> + return (struct value *) value_nsstring (&exp->elts[pc + 2].string, tem + 1);
> +
> case OP_BITSTRING:
> tem = longest_to_int (exp->elts[pc + 1].longconst);
> (*pos)
> @@ -667,6 +678,296 @@ evaluate_subexp_standard (struct type *e
> return arg2;
> }
>
> + case OP_OBJC_SELECTOR:
> + { /* Objective C @selector operator. */
> + char *sel = &exp->elts[pc + 2].string;
> + int len = longest_to_int (exp->elts[pc + 1].longconst);
> +
> + (*pos) += 3 + BYTES_TO_EXP_ELEM (len + 1);
> + if (noside == EVAL_SKIP)
> + goto nosideret;
> +
> + if (sel[len] != 0)
> + sel[len] = 0; /* Make sure it's terminated. */
> + return value_from_longest (lookup_pointer_type (builtin_type_void),
> + lookup_child_selector (sel));
> + }
> +
> + case OP_OBJC_MSGCALL:
> + { /* Objective C message (method) call. */
> +
> + static unsigned long responds_selector = 0;
> + static unsigned long method_selector = 0;
> +
> + unsigned long selector = 0;
> +
> + int using_gcc = 0;
> + int struct_return = 0;
> + int sub_no_side = 0;
> +
> + static struct value *msg_send = NULL;
> + static struct value *msg_send_stret = NULL;
> + static int gnu_runtime = 0;
> +
> + struct value *target = NULL;
> + struct value *method = NULL;
> + struct value *called_method = NULL;
> +
> + struct type *selector_type = NULL;
> +
> + struct value *ret = NULL;
> + CORE_ADDR addr = 0;
> +
> + selector = exp->elts[pc + 1].longconst;
> + nargs = exp->elts[pc + 2].longconst;
> + argvec = (struct value **) alloca (sizeof (struct value *)
> + * (nargs + 5));
> +
> + (*pos) += 3;
> +
> + selector_type = lookup_pointer_type (builtin_type_void);
> + if (noside == EVAL_AVOID_SIDE_EFFECTS)
> + sub_no_side = EVAL_NORMAL;
> + else
> + sub_no_side = noside;
> +
> + target = evaluate_subexp (selector_type, exp, pos, sub_no_side);
> +
> + if (value_as_long (target) == 0)
> + return value_from_longest (builtin_type_long, 0);
> +
> + if (lookup_minimal_symbol ("objc_msg_lookup", 0, 0))
> + gnu_runtime = 1;
> +
> + /* Find the method dispatch (Apple runtime) or method lookup
> + (GNU runtime) function for Objective-C. These will be used
> + to lookup the symbol information for the method. If we
> + can't find any symbol information, then we'll use these to
> + call the method, otherwise we can call the method
> + directly. The msg_send_stret function is used in the special
> + case of a method that returns a structure (Apple runtime
> + only). */
> + if (gnu_runtime)
> + {
> + msg_send = find_function_in_inferior ("objc_msg_lookup");
> + msg_send_stret = find_function_in_inferior ("objc_msg_lookup");
> + }
> + else
> + {
> + msg_send = find_function_in_inferior ("objc_msgSend");
> + /* Special dispatcher for methods returning structs */
> + msg_send_stret = find_function_in_inferior ("objc_msgSend_stret");
> + }
> +
> + /* Verify the target object responds to this method. The
> + standard top-level 'Object' class uses a different name for
> + the verification method than the non-standard, but more
> + often used, 'NSObject' class. Make sure we check for both. */
> +
> + responds_selector = lookup_child_selector ("respondsToSelector:");
> + if (responds_selector == 0)
> + responds_selector = lookup_child_selector ("respondsTo:");
> +
> + if (responds_selector == 0)
> + error ("no 'respondsTo:' or 'respondsToSelector:' method");
> +
> + method_selector = lookup_child_selector ("methodForSelector:");
> + if (method_selector == 0)
> + method_selector = lookup_child_selector ("methodFor:");
> +
> + if (method_selector == 0)
> + error ("no 'methodFor:' or 'methodForSelector:' method");
> +
> + /* Call the verification method, to make sure that the target
> + class implements the desired method. */
> +
> + argvec[0] = msg_send;
> + argvec[1] = target;
> + argvec[2] = value_from_longest (builtin_type_long, responds_selector);
> + argvec[3] = value_from_longest (builtin_type_long, selector);
> + argvec[4] = 0;
> +
> + ret = call_function_by_hand (argvec[0], 3, argvec + 1);
> + if (gnu_runtime)
> + {
> + /* Function objc_msg_lookup returns a pointer. */
> + argvec[0] = ret;
> + ret = call_function_by_hand (argvec[0], 3, argvec + 1);
> + }
> + if (value_as_long (ret) == 0)
> + error ("Target does not respond to this message selector.");
> +
> + /* Call "methodForSelector:" method, to get the address of a
> + function method that implements this selector for this
> + class. If we can find a symbol at that address, then we
> + know the return type, parameter types etc. (that's a good
> + thing). */
> +
> + argvec[0] = msg_send;
> + argvec[1] = target;
> + argvec[2] = value_from_longest (builtin_type_long, method_selector);
> + argvec[3] = value_from_longest (builtin_type_long, selector);
> + argvec[4] = 0;
> +
> + ret = call_function_by_hand (argvec[0], 3, argvec + 1);
> + if (gnu_runtime)
> + {
> + argvec[0] = ret;
> + ret = call_function_by_hand (argvec[0], 3, argvec + 1);
> + }
> +
> + /* ret should now be the selector. */
> +
> + addr = value_as_long (ret);
> + if (addr)
> + {
> + struct symbol *sym = NULL;
> + /* Is it a high_level symbol? */
> +
> +#if 0
> + /* Was defined only for HPPA architectures. Commented out
> + since we cannot verify that this works anymore. Anyone
> + experiencing problems on HPPA machines can check this
> + for validity. */
> + CORE_ADDR tmp;
> + /* Code and comment lifted from hppa-tdep.c.
> + Unfortunately there is no builtin function to do
> + this. */
> + /* If bit 30 (counting from the left) is on, then addr
> + is the address of the PLT entry for this function,
> + not the address of the function itself. Bit 31 has
> + meaning too, but only for MPE. */
> + if (addr & 0x2)
> + addr = (CORE_ADDR) read_memory_unsigned_integer (addr & ~0x3, 4);
> + if (tmp = skip_trampoline_code (addr, 0))
> + addr = tmp;
> +#endif
> +
> + sym = find_pc_function (addr);
> + if (sym != NULL)
> + method = value_of_variable (sym, 0);
> + }
> +
> + /* If we found a method with symbol information, check to see
> + if it returns a struct. Otherwise assume it doesn't. */
> +
> + if (method)
> + {
> + struct block *b;
> + CORE_ADDR funaddr;
> + struct type *value_type;
> +
> + funaddr = find_function_addr (method, &value_type);
> +
> + b = block_for_pc (funaddr);
> +
> + /* If compiled without -g, assume GCC 2. */
> + using_gcc = (b == NULL ? 2 : BLOCK_GCC_COMPILED (b));
> +
> + CHECK_TYPEDEF (value_type);
> +
> + if ((value_type == NULL)
> + || (TYPE_CODE(value_type) == TYPE_CODE_ERROR))
> + {
> + if (expect_type != NULL)
> + value_type = expect_type;
> + }
> +
> + struct_return = using_struct_return (method, funaddr, value_type, using_gcc);
> + }
> + else if (expect_type != NULL)
> + {
> + struct_return = using_struct_return (NULL, addr, check_typedef (expect_type), using_gcc);
> + }
> +
> + /* Found a function symbol. Now we will substitute its
> + value in place of the message dispatcher (obj_msgSend),
> + so that we call the method directly instead of thru
> + the dispatcher. The main reason for doing this is that
> + we can now evaluate the return value and parameter values
> + according to their known data types, in case we need to
> + do things like promotion, dereferencing, special handling
> + of structs and doubles, etc.
> +
> + We want to use the type signature of 'method', but still
> + jump to objc_msgSend() or objc_msgSend_stret() to better
> + mimic the behavior of the runtime. */
> +
> + if (method)
> + {
> + if (TYPE_CODE (VALUE_TYPE (method)) != TYPE_CODE_FUNC)
> + error ("method address has symbol information with non-function type; skipping");
> + if (struct_return)
> + VALUE_ADDRESS (method) = value_as_address (msg_send_stret);
> + else
> + VALUE_ADDRESS (method) = value_as_address (msg_send);
> + called_method = method;
> + }
> + else
> + {
> + if (struct_return)
> + called_method = msg_send_stret;
> + else
> + called_method = msg_send;
> + }
> +
> + if (noside == EVAL_SKIP)
> + goto nosideret;
> +
> + if (noside == EVAL_AVOID_SIDE_EFFECTS)
> + {
> + /* If the return type doesn't look like a function type,
> + call an error. This can happen if somebody tries to
> + turn a variable into a function call. This is here
> + because people often want to call, eg, strcmp, which
> + gdb doesn't know is a function. If gdb isn't asked for
> + it's opinion (ie. through "whatis"), it won't offer
> + it. */
> +
> + struct type *type = VALUE_TYPE (called_method);
> + if (type && TYPE_CODE (type) == TYPE_CODE_PTR)
> + type = TYPE_TARGET_TYPE (type);
> + type = TYPE_TARGET_TYPE (type);
> +
> + if (type)
> + {
> + if ((TYPE_CODE (type) == TYPE_CODE_ERROR) && expect_type)
> + return allocate_value (expect_type);
> + else
> + return allocate_value (type);
> + }
> + else
> + error ("Expression of type other than \"method returning ...\" used as a method");
> + }
> +
> + /* Now depending on whether we found a symbol for the method,
> + we will either call the runtime dispatcher or the method
> + directly. */
> +
> + argvec[0] = called_method;
> + argvec[1] = target;
> + argvec[2] = value_from_longest (builtin_type_long, selector);
> + /* User-supplied arguments. */
> + for (tem = 0; tem < nargs; tem++)
> + argvec[tem + 3] = evaluate_subexp_with_coercion (exp, pos, noside);
> + argvec[tem + 3] = 0;
> +
> + if (gnu_runtime && (method != NULL))
> + {
> + ret = call_function_by_hand (argvec[0], nargs + 2, argvec + 1);
> + /* Function objc_msg_lookup returns a pointer. */
> + argvec[0] = ret;
> + ret = call_function_by_hand (argvec[0],
> + nargs + 2, argvec + 1);
> + }
> + else
> + ret = call_function_by_hand (argvec[0],
> + nargs + 2, argvec + 1);
> +
> + return ret;
> + }
> + break;
> +
> case OP_FUNCALL:
> (*pos) += 2;
> op = exp->elts[*pos].opcode;
> @@ -1748,6 +2054,10 @@ evaluate_subexp_standard (struct type *e
> case OP_THIS:
> (*pos) += 1;
> return value_of_this (1);
> +
> + case OP_OBJC_SELF:
> + (*pos) += 1;
> + return value_of_local ("self", 1);
>
> case OP_TYPE:
> error ("Attempt to use a type name as an expression");
> Index: valops.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/valops.c,v
> retrieving revision 1.89
> diff -u -p -r1.89 valops.c
> --- valops.c 30 Jan 2003 16:44:20 -0000 1.89
> +++ valops.c 13 Feb 2003 02:46:52 -0000
> @@ -48,7 +48,6 @@ extern int overload_debug;
> static int typecmp (int staticp, int varargs, int nargs,
> struct field t1[], struct value *t2[]);
>
> -static CORE_ADDR find_function_addr (struct value *, struct type **);
> static struct value *value_arg_coerce (struct value *, struct type *, int);
>
>
> @@ -1172,7 +1171,7 @@ value_arg_coerce (struct value *arg, str
> /* Determine a function's address and its return type from its value.
> Calls error() if the function is not valid for calling. */
>
> -static CORE_ADDR
> +CORE_ADDR
> find_function_addr (struct value *function, struct type **retval_type)
> {
> register struct type *ftype = check_typedef (VALUE_TYPE (function));
> Index: value.h
> ===================================================================
> RCS file: /cvs/src/src/gdb/value.h,v
> retrieving revision 1.41
> diff -u -p -r1.41 value.h
> --- value.h 19 Jan 2003 04:06:46 -0000 1.41
> +++ value.h 13 Feb 2003 02:46:52 -0000
> @@ -563,6 +563,8 @@ extern CORE_ADDR default_push_arguments
> CORE_ADDR sp, int struct_return,
> CORE_ADDR struct_addr);
>
> +extern CORE_ADDR find_function_addr (struct value *, struct type **);
> +
> extern struct value *value_of_local (const char *name, int complain);
>
> #endif /* !defined (VALUE_H) */
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] Handle ObjC OPS in eval.c
2003-04-10 21:56 ` Elena Zannoni
@ 2003-04-20 3:42 ` Adam Fedor
2003-04-21 4:14 ` Daniel Jacobowitz
0 siblings, 1 reply; 15+ messages in thread
From: Adam Fedor @ 2003-04-20 3:42 UTC (permalink / raw)
To: Elena Zannoni; +Cc: Michael Snyder, GDB Patches
Elena Zannoni wrote:
> Adam Fedor writes:
> >
> >
> > Elena Zannoni wrote:
> > [...]
> > >
> > > I think we need more comments, I guess stret means structure return?
> > > What are these methods used for? Also can you add a high level
> > > description of how these dispatchers get into the picture?
> > >
> >
> > Here's a better documented and slightly cleaned-up patch.
> > 2003-03-04 Adam Fedor <fedor@gnu.org>
>
> I think it's ok. Except I don't like to introduce more #if0 code with new code.
> Do we really need that part?
>
I bet no one would complain if I took it out.
The larger problem I have, though, is changing the patch so that I can
call the objc-lang functions indirectly, so that objc-lang.o does not
have to be linked in. That seems like a pain.
I think it would be easier to split objc-lang.c into two parts. One that
is architecture independant that I could link in now, and the other
acitecture dependant part (which is already handled via the language
vector). Anything wrong with that?
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] Handle ObjC OPS in eval.c
2003-04-20 3:42 ` Adam Fedor
@ 2003-04-21 4:14 ` Daniel Jacobowitz
2003-04-21 16:26 ` Elena Zannoni
2003-04-21 16:47 ` Adam Fedor
0 siblings, 2 replies; 15+ messages in thread
From: Daniel Jacobowitz @ 2003-04-21 4:14 UTC (permalink / raw)
To: Adam Fedor; +Cc: Elena Zannoni, Michael Snyder, GDB Patches
On Sat, Apr 19, 2003 at 09:42:49PM -0600, Adam Fedor wrote:
>
>
> Elena Zannoni wrote:
> >Adam Fedor writes:
> > >
> > >
> > > Elena Zannoni wrote:
> > > [...]
> > > >
> > > > I think we need more comments, I guess stret means structure return?
> > > > What are these methods used for? Also can you add a high level
> > > > description of how these dispatchers get into the picture?
> > > >
> > >
> > > Here's a better documented and slightly cleaned-up patch.
> > > 2003-03-04 Adam Fedor <fedor@gnu.org>
> >
> >I think it's ok. Except I don't like to introduce more #if0 code with new
> >code.
> >Do we really need that part?
> >
>
> I bet no one would complain if I took it out.
>
> The larger problem I have, though, is changing the patch so that I can
> call the objc-lang functions indirectly, so that objc-lang.o does not
> have to be linked in. That seems like a pain.
>
> I think it would be easier to split objc-lang.c into two parts. One that
> is architecture independant that I could link in now, and the other
> acitecture dependant part (which is already handled via the language
> vector). Anything wrong with that?
What would go in the architecture dependant part? That shouldn't
involve te _language_ vector, it should involve the _gdbarch_ vector,
and go in the already-existing arch files. I think.
--
Daniel Jacobowitz
MontaVista Software Debian GNU/Linux Developer
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] Handle ObjC OPS in eval.c
2003-04-21 4:14 ` Daniel Jacobowitz
@ 2003-04-21 16:26 ` Elena Zannoni
2003-04-21 16:47 ` Adam Fedor
1 sibling, 0 replies; 15+ messages in thread
From: Elena Zannoni @ 2003-04-21 16:26 UTC (permalink / raw)
To: fedor; +Cc: drow, Elena Zannoni, Michael Snyder, GDB Patches
Daniel Jacobowitz writes:
> On Sat, Apr 19, 2003 at 09:42:49PM -0600, Adam Fedor wrote:
> >
> >
> > Elena Zannoni wrote:
> > >Adam Fedor writes:
> > > >
> > > >
> > > > Elena Zannoni wrote:
> > > > [...]
> > > > >
> > > > > I think we need more comments, I guess stret means structure return?
> > > > > What are these methods used for? Also can you add a high level
> > > > > description of how these dispatchers get into the picture?
> > > > >
> > > >
> > > > Here's a better documented and slightly cleaned-up patch.
> > > > 2003-03-04 Adam Fedor <fedor@gnu.org>
> > >
> > >I think it's ok. Except I don't like to introduce more #if0 code with new
> > >code.
> > >Do we really need that part?
> > >
> >
> > I bet no one would complain if I took it out.
> >
> > The larger problem I have, though, is changing the patch so that I can
> > call the objc-lang functions indirectly, so that objc-lang.o does not
> > have to be linked in. That seems like a pain.
> >
> > I think it would be easier to split objc-lang.c into two parts. One that
> > is architecture independant that I could link in now, and the other
> > acitecture dependant part (which is already handled via the language
> > vector). Anything wrong with that?
>
> What would go in the architecture dependant part? That shouldn't
> involve te _language_ vector, it should involve the _gdbarch_ vector,
> and go in the already-existing arch files. I think.
>
Yes, I don't think I understand what you mean by splitting objc-lang.c
in two parts.
elena
> --
> Daniel Jacobowitz
> MontaVista Software Debian GNU/Linux Developer
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] Handle ObjC OPS in eval.c
2003-04-21 4:14 ` Daniel Jacobowitz
2003-04-21 16:26 ` Elena Zannoni
@ 2003-04-21 16:47 ` Adam Fedor
2003-04-21 16:51 ` Daniel Jacobowitz
2003-04-21 17:09 ` Elena Zannoni
1 sibling, 2 replies; 15+ messages in thread
From: Adam Fedor @ 2003-04-21 16:47 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: Elena Zannoni, Michael Snyder, GDB Patches
On Sunday, April 20, 2003, at 10:13 PM, Daniel Jacobowitz wrote:
> On Sat, Apr 19, 2003 at 09:42:49PM -0600, Adam Fedor wrote:
>>
>> The larger problem I have, though, is changing the patch so that I can
>> call the objc-lang functions indirectly, so that objc-lang.o does not
>> have to be linked in. That seems like a pain.
>>
>> I think it would be easier to split objc-lang.c into two parts. One
>> that
>> is architecture independant that I could link in now, and the other
>> acitecture dependant part (which is already handled via the language
>> vector). Anything wrong with that?
>
> What would go in the architecture dependant part? That shouldn't
> involve te _language_ vector, it should involve the _gdbarch_ vector,
> and go in the already-existing arch files. I think.
>
>
Currently, objc-lang.c has code for determining if an address is the
address of one of the Objective-C method dispatch functions. It
currently depends on some code that has only been implemented on a few
architectures (Aside: This code is only used if gdb is debugging an
Objective-C program using the Apple runtime not the GNU runtime, so
it's basically only useful on MacOSX/Darwin).
Andrew had suggested that we put the objc language calls in the
language vector so that we could conditionally compile in objc-lang.o
on certain architectures until the architecture dependant code gets
fixed (or ported?). Basically it's just a temporary solution to get
Objective-C support into gdb. I've already put the architecture
dependant calls in the language vector (skip_language_trampoline).
I'm not positive what Andrew had intended, but I guess I would have to
put all the other Objective-C language functions in a vector as well.
However, I think it would be easier just to separate out the
architecture dependant part which is, again, conditionally compiled in,
while the rest of objc-lang.c is compiled in by default.
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] Handle ObjC OPS in eval.c
2003-04-21 16:47 ` Adam Fedor
@ 2003-04-21 16:51 ` Daniel Jacobowitz
2003-04-21 17:09 ` Elena Zannoni
1 sibling, 0 replies; 15+ messages in thread
From: Daniel Jacobowitz @ 2003-04-21 16:51 UTC (permalink / raw)
To: Adam Fedor; +Cc: Elena Zannoni, Michael Snyder, GDB Patches
On Mon, Apr 21, 2003 at 10:47:07AM -0600, Adam Fedor wrote:
>
> On Sunday, April 20, 2003, at 10:13 PM, Daniel Jacobowitz wrote:
>
> >On Sat, Apr 19, 2003 at 09:42:49PM -0600, Adam Fedor wrote:
> >>
> >>The larger problem I have, though, is changing the patch so that I can
> >>call the objc-lang functions indirectly, so that objc-lang.o does not
> >>have to be linked in. That seems like a pain.
> >>
> >>I think it would be easier to split objc-lang.c into two parts. One
> >>that
> >>is architecture independant that I could link in now, and the other
> >>acitecture dependant part (which is already handled via the language
> >>vector). Anything wrong with that?
> >
> >What would go in the architecture dependant part? That shouldn't
> >involve te _language_ vector, it should involve the _gdbarch_ vector,
> >and go in the already-existing arch files. I think.
> >
> >
>
> Currently, objc-lang.c has code for determining if an address is the
> address of one of the Objective-C method dispatch functions. It
> currently depends on some code that has only been implemented on a few
> architectures (Aside: This code is only used if gdb is debugging an
> Objective-C program using the Apple runtime not the GNU runtime, so
> it's basically only useful on MacOSX/Darwin).
>
> Andrew had suggested that we put the objc language calls in the
> language vector so that we could conditionally compile in objc-lang.o
> on certain architectures until the architecture dependant code gets
> fixed (or ported?). Basically it's just a temporary solution to get
> Objective-C support into gdb. I've already put the architecture
> dependant calls in the language vector (skip_language_trampoline).
>
> I'm not positive what Andrew had intended, but I guess I would have to
> put all the other Objective-C language functions in a vector as well.
> However, I think it would be easier just to separate out the
> architecture dependant part which is, again, conditionally compiled in,
> while the rest of objc-lang.c is compiled in by default.
This is FETCH_ARGUMENT and friends. They should go in the gdbarch
vector, and nothing objc-related at all. As we discussed, it should
probably become FETCH_POINTER_ARGUMENT also.
--
Daniel Jacobowitz
MontaVista Software Debian GNU/Linux Developer
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] Handle ObjC OPS in eval.c
2003-04-21 16:47 ` Adam Fedor
2003-04-21 16:51 ` Daniel Jacobowitz
@ 2003-04-21 17:09 ` Elena Zannoni
2003-04-21 18:23 ` Adam Fedor
1 sibling, 1 reply; 15+ messages in thread
From: Elena Zannoni @ 2003-04-21 17:09 UTC (permalink / raw)
To: Adam Fedor; +Cc: Daniel Jacobowitz, Elena Zannoni, Michael Snyder, GDB Patches
Adam Fedor writes:
>
> On Sunday, April 20, 2003, at 10:13 PM, Daniel Jacobowitz wrote:
>
> > On Sat, Apr 19, 2003 at 09:42:49PM -0600, Adam Fedor wrote:
> >>
> >> The larger problem I have, though, is changing the patch so that I can
> >> call the objc-lang functions indirectly, so that objc-lang.o does not
> >> have to be linked in. That seems like a pain.
> >>
> >> I think it would be easier to split objc-lang.c into two parts. One
> >> that
> >> is architecture independant that I could link in now, and the other
> >> acitecture dependant part (which is already handled via the language
> >> vector). Anything wrong with that?
> >
> > What would go in the architecture dependant part? That shouldn't
> > involve te _language_ vector, it should involve the _gdbarch_ vector,
> > and go in the already-existing arch files. I think.
> >
> >
>
> Currently, objc-lang.c has code for determining if an address is the
> address of one of the Objective-C method dispatch functions. It
> currently depends on some code that has only been implemented on a few
> architectures (Aside: This code is only used if gdb is debugging an
> Objective-C program using the Apple runtime not the GNU runtime, so
> it's basically only useful on MacOSX/Darwin).
>
> Andrew had suggested that we put the objc language calls in the
> language vector so that we could conditionally compile in objc-lang.o
> on certain architectures until the architecture dependant code gets
> fixed (or ported?). Basically it's just a temporary solution to get
> Objective-C support into gdb. I've already put the architecture
> dependant calls in the language vector (skip_language_trampoline).
>
> I'm not positive what Andrew had intended, but I guess I would have to
> put all the other Objective-C language functions in a vector as well.
> However, I think it would be easier just to separate out the
> architecture dependant part which is, again, conditionally compiled in,
> while the rest of objc-lang.c is compiled in by default.
Ah, that. Ok, but this has nothing to do with the patch in this thread.
You can commit this patch omitting the if0-ed part.
elena
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH] Handle ObjC OPS in eval.c
2003-04-21 17:09 ` Elena Zannoni
@ 2003-04-21 18:23 ` Adam Fedor
0 siblings, 0 replies; 15+ messages in thread
From: Adam Fedor @ 2003-04-21 18:23 UTC (permalink / raw)
To: Elena Zannoni; +Cc: Daniel Jacobowitz, Michael Snyder, GDB Patches
On Monday, April 21, 2003, at 11:13 AM, Elena Zannoni wrote:
> Adam Fedor writes:
>>
>> On Sunday, April 20, 2003, at 10:13 PM, Daniel Jacobowitz wrote:
>>
>>> On Sat, Apr 19, 2003 at 09:42:49PM -0600, Adam Fedor wrote:
>>>>
>>>> The larger problem I have, though, is changing the patch so that I
>>>> can
>>>> call the objc-lang functions indirectly, so that objc-lang.o does
>>>> not
>>>> have to be linked in. That seems like a pain.
>>>>
>>>> I think it would be easier to split objc-lang.c into two parts. One
>>>> that
>>>> is architecture independant that I could link in now, and the other
>>>> acitecture dependant part (which is already handled via the language
>>>> vector). Anything wrong with that?
>>>
>>> What would go in the architecture dependant part? That shouldn't
>>> involve te _language_ vector, it should involve the _gdbarch_ vector,
>>> and go in the already-existing arch files. I think.
>>>
>>>
>>
>> Currently, objc-lang.c has code for determining if an address is the
>> address of one of the Objective-C method dispatch functions. It
>> currently depends on some code that has only been implemented on a few
>> architectures (Aside: This code is only used if gdb is debugging an
>> Objective-C program using the Apple runtime not the GNU runtime, so
>> it's basically only useful on MacOSX/Darwin).
>>
>> Andrew had suggested that we put the objc language calls in the
>> language vector so that we could conditionally compile in objc-lang.o
>> on certain architectures until the architecture dependant code gets
>> fixed (or ported?). Basically it's just a temporary solution to get
>> Objective-C support into gdb. I've already put the architecture
>> dependant calls in the language vector (skip_language_trampoline).
>>
>> I'm not positive what Andrew had intended, but I guess I would have to
>> put all the other Objective-C language functions in a vector as well.
>> However, I think it would be easier just to separate out the
>> architecture dependant part which is, again, conditionally compiled
>> in,
>> while the rest of objc-lang.c is compiled in by default.
>
> Ah, that. Ok, but this has nothing to do with the patch in this thread.
> You can commit this patch omitting the if0-ed part.
>
No. gdb won't link with the patch included without objc-lang.o linked
in.
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2003-04-21 18:23 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-01-03 20:27 [PATCH] Handle ObjC OPS in eval.c Adam Fedor
2003-01-31 3:07 ` Michael Snyder
2003-02-07 18:31 ` Adam Fedor
2003-02-07 22:04 ` Andrew Cagney
2003-02-13 4:05 ` Adam Fedor
2003-02-19 20:05 ` Elena Zannoni
2003-03-05 5:06 ` Adam Fedor
2003-04-10 21:56 ` Elena Zannoni
2003-04-20 3:42 ` Adam Fedor
2003-04-21 4:14 ` Daniel Jacobowitz
2003-04-21 16:26 ` Elena Zannoni
2003-04-21 16:47 ` Adam Fedor
2003-04-21 16:51 ` Daniel Jacobowitz
2003-04-21 17:09 ` Elena Zannoni
2003-04-21 18:23 ` Adam Fedor
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox