[PATCH] Fix some 64-bit Objective-C bugs

Ulrich Weigand
2003-12-04T20:10:52Z

Hello,

when analysing test suite failures I've noticed a couple of objc
FAILs on s390x that are not backend-related, but in fact caused
but 64-bit unclean code in gdb common objc code. They are
typically caused by converting a target pointer to 'int'.

In particular objc selectors are target pointers, and should
thus be held in variables of type CORE_ADDR, not 'int', on the
host. This patch fixes a couple of occurrances of this problem.

Also, the type information for method pointers was incorrect
when using the GNU runtime, because this involves an additional
indirection step. Due to this, 'call_function_by_hand' would
assume a return type of 'int' in some cases instead of a correct
pointer return type -- this would again incorrectly truncate
the return value.

The patch fixes this problem as well; it also adapts one test
case which actually tested for the incorrect 'int' return value
instead of the correct pointer type.

Tested on s390-ibm-linux and s390x-ibm-linux with no new regressions.
Fixes 4 test case failures on s390x.

Bye,
Ulrich

ChangeLog:

* eval.c (evaluate_subexp_standard, case OP_OBJC_MSGCALL): Use
CORE_ADDR as type for selectors. Correct types for GNU run time
message lookup function to use double indirection.
* objc-lang.c (lookup_child_selector): Use CORE_ADDR as return type.
* objc-lang.h (lookup_child_selector): Adapt prototype.

testsuite/ChangeLog:

* gdb.objc/basicclass.exp: Adapt to fixed return type of printHi.

diff -c -p -r gdb-head/gdb/eval.c gdb-head-new/gdb/eval.c
*** gdb-head/gdb/eval.c Wed Nov 19 22:37:09 2003
--- gdb-head-new/gdb/eval.c Thu Nov 20 00:07:21 2003
*************** evaluate_subexp_standard (struct type *e
*** 697,706 ****
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;
--- 697,706 ----
case OP_OBJC_MSGCALL:
{ /* Objective C message (method) call. */

! static CORE_ADDR responds_selector = 0;
! static CORE_ADDR method_selector = 0;

! CORE_ADDR selector = 0;

int using_gcc = 0;
int struct_return = 0;
*************** evaluate_subexp_standard (struct type *e
*** 750,757 ****
--- 750,768 ----
only). */
if (gnu_runtime)
{
+ struct type *type;
+ type = lookup_pointer_type (builtin_type_void);
+ type = lookup_function_type (type);
+ type = lookup_pointer_type (type);
+ type = lookup_function_type (type);
+ type = lookup_pointer_type (type);
+
msg_send = find_function_in_inferior ("objc_msg_lookup");
msg_send_stret = find_function_in_inferior ("objc_msg_lookup");
+
+ msg_send = value_from_pointer (type, value_as_address (msg_send));
+ msg_send_stret = value_from_pointer (type,
+ value_as_address (msg_send_stret));
}
else
{
*************** evaluate_subexp_standard (struct type *e
*** 936,949 ****

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;
--- 947,959 ----

if (gnu_runtime && (method != NULL))
{
/* Function objc_msg_lookup returns a pointer. */
! VALUE_TYPE (argvec[0]) = lookup_function_type
! (lookup_pointer_type (VALUE_TYPE (argvec[0])));
! argvec[0] = call_function_by_hand (argvec[0], nargs + 2, argvec + 1);
}

+ ret = call_function_by_hand (argvec[0], nargs + 2, argvec + 1);
return ret;
}
break;
diff -c -p -r gdb-head/gdb/objc-lang.c gdb-head-new/gdb/objc-lang.c
*** gdb-head/gdb/objc-lang.c Wed Nov 19 22:37:09 2003
--- gdb-head-new/gdb/objc-lang.c Thu Nov 20 00:07:21 2003
*************** lookup_objc_class (char *classname)
*** 133,139 ****
1, &classval));
}

! int
lookup_child_selector (char *selname)
{
struct value * function, *selstring;
--- 133,139 ----
1, &classval));
}

! CORE_ADDR
lookup_child_selector (char *selname)
{
struct value * function, *selstring;
*************** end_msglist(void)
*** 753,759 ****
int val = msglist_len;
struct selname *sel = selname_chain;
char *p = msglist_sel;
! int selid;

selname_chain = sel->next;
msglist_len = sel->msglist_len;
--- 753,759 ----
int val = msglist_len;
struct selname *sel = selname_chain;
char *p = msglist_sel;
! CORE_ADDR selid;

selname_chain = sel->next;
msglist_len = sel->msglist_len;
diff -c -p -r gdb-head/gdb/objc-lang.h gdb-head-new/gdb/objc-lang.h
*** gdb-head/gdb/objc-lang.h Wed Nov 19 22:37:09 2003
--- gdb-head-new/gdb/objc-lang.h Thu Nov 20 00:07:21 2003
*************** extern int c_value_print (struct value *
*** 39,45 ****
int, enum val_prettyprint);

extern CORE_ADDR lookup_objc_class (char *classname);
! extern int lookup_child_selector (char *methodname);

extern char *objc_demangle (const char *mangled, int options);

--- 39,45 ----
int, enum val_prettyprint);

extern CORE_ADDR lookup_objc_class (char *classname);
! extern CORE_ADDR lookup_child_selector (char *methodname);

extern char *objc_demangle (const char *mangled, int options);

diff -c -p -r gdb-head/gdb/testsuite/gdb.objc/basicclass.exp gdb-head-new/gdb/testsuite/gdb.objc/basicclass.exp
*** gdb-head/gdb/testsuite/gdb.objc/basicclass.exp Wed Nov 19 22:37:09 2003
--- gdb-head-new/gdb/testsuite/gdb.objc/basicclass.exp Thu Nov 20 00:07:21 2003
*************** gdb_test continue \
*** 178,184 ****
# Test calling Objective-C methods
#
gdb_test "print \[self printHi\]" \
! "Hi.*\\$\[0-9\] = -?\[0-9\]+" \
"Call an Objective-C method with no arguments"

gdb_test "print \[self printNumber: 42\]" \
--- 178,184 ----
# Test calling Objective-C methods
#
gdb_test "print \[self printHi\]" \
! "Hi.*\\$\[0-9\] = \\(.*objc_object \\*\\) 0x\[0-9a-f\]+" \
"Call an Objective-C method with no arguments"

gdb_test "print \[self printNumber: 42\]" \
--
Dr. Ulrich Weigand
weigand@informatik.uni-erlangen.de