(examples have been tested with gcc-2.6.3 and gdb-4.13. )
ObjC-source> Class1 anObject;
can be inspected by:
gdb> p *anObject;
However, if the type is not declared or the object stored in the variable is not anymore of the declared type, you have to find out the class of the Object and then tell gdb to inspect the object like you would as gdb to inspect a structure.
ObjC-source> id foo2; // has a single instance var called `a'
you get the Class of this Object like this (gdb's answer inserted):
gdb> call _i_Object__name(foo2,"") // NEW // answer> $31 = (unsigned char *) 0x10000b1c "Foo0"
You know then the Class is `Foo0' and can use the class name to inspect foo2:
gdb> p (struct Foo0)*foo2 answer> $32 = {isa = 0x10000244, a = 0, aid = 0x10005590}
Message Name Mangling
goes as follows: The method of `MyClass' named `-do:with:' looks like this in gdb:
_i_MyClass__do_with_
The method of `MyClass' named `-done' looks like this in gdb:
_i_MyClass__done
Factory methods have a _c_ at the beginning instead of _i_ The method of `MyClass' named `+version' looks like this in gdb:
_c_MyClass__version.
To be exact: Every method starts with either `_i_' or `_c_'. The name of the Class follows. Them come two `_', for Methods that are not part of Categories. The `__' turns to `_categoryName_' then. The parts of the method name are appended, substituting each `:' with a `_'. // NEW //
gdb> b _i_MyClass__done
You can call methods in one of two ways:
1. Calling using the mangled name
You can use the mangled name to call a message. The first parameter to a message is the object, the receiver. The second argument is the selector. When you use the mangled names in gdb, you don't need the selector normally. However, the message to be called may explicitly reference it (not common). The rest of the arguments are the arguments for the message.
An example. Here are some message calls in ObjC:
ObjC-Source 1> id foo1; ObjC-Source 2> ObjC-Source 3> [foo1 do: "Text" with: 4]; ObjC-Source 4> [foo1 eat: "Hamburger"]; ObjC-Source 5> [foo1 done];
First you must find out what the class of foo1 is and construct the mangled name as show above. Assuming the Class is `Class1':
_i_Class1__do_with_ _i_Class1__eat _i_Class1__done
The calls in the code example may be done like this in gdb , assuming that Object foo1 already exists (that means, execution of the program already passed line 1).
gdb> call _i_Class1__do_with_(foo1,"","Text",4) gdb> call _i_Class1__eat_(foo1,"","Hamburger") gdb> call _i_Class1__done(foo1,"")
Note that I inserted a dummy string for the selector, assuming that the messages doesn't explicitly accesses it. A selector is not a string, but since this call doesn't provide the correct selector anyway, I inserted the pointer that is most easily created in gdb, an empty string. // NEW //
2. Calling with message name as string using a compiled function
Insert the following function in your progran. Thanks to Kresten Krap Thorup.
#include#include int method_get_sizeof_arguments (Method*); // Missing in objc/*.h volatile retval_t ocs(id object, char *opname, ...) { SEL op = sel_get_uid (opname); Method* m = class_get_instance_method(object->class_pointer, op); IMP imp; arglist_t args; retval_t result; if (!m) { fprintf(stderr,"Error in message call\n"); return ((void *)0); } imp = objc_msg_lookup (object, op); args = __builtin_apply_args(); result = __builtin_apply((apply_t)imp, args, method_get_sizeof_arguments (m)); __builtin_return (result); }
Now you can do the message calls of the previous examples like this:
gdb> call ocs(foo1,"do:with:","Text",4) gdb> call ocs(foo1,"eat:","Hamburger") gdb> call ocs(foo1,"done")
Please note that error handling is rare. You'll see the error message when you type in a message that is not understood by the object.
Both solutions (mangled message names or string-converting function) will break the program with a segmentation fault when you pass something that is not an ObjC-Object as first parameter.
The first solution has the disadvantage that you must know the exact class of the object (and the category the message is defined in, if any // NEW //) to determine the mangled name of the right message. The second solution does this automatically for you, but has the disadvantage that return values are interpreted as pointers in any case. For example, if the message returns the integer value `5', gdb will answer:
$3 = (void *) 0x5
non-32-bit data types like double or char will become unreadable then.
A better solution to prevent the type of the return value if it is a low-level type would be a simple text substitution to determine the right mangled name automatically in gdb
[leaving out the `:'of message name and categories] gdb> objc-call foo2 do "Text" with 4
could be translated to (using UNIX shell syntax):
gdb> call _i_`call _i_Object__name($1)`__$2_$4_($1,"dummy",$3,$5)
Maybe this is easy to do with tcl/expect. There's no solution for this yet and I think it is more likely that gdb will be extended to understand [foo2 do: "Text" with: 4] directly.
The different return type handling of the two calling conventions doesn't matter if the return value is an ObjC object. You'll get a pointer to it and then can operate on this pointer, ask for the class etc.
gdb> call ocs(foo2,"getaid") answer> $9 =(void *) 0x100055b0
or
gdb> call _i_Foo0__getaid(foo2,"") answer> $10 = (struct objc_object *) 0x100055b0
return pointers to an Object. You can then do:
gdb> call _i_Object__name((void *) 0x100055b0) answer> $2 = (unsigned char *) 0x10000b34 "Inti" gdb> p (struct Inti)*0x10000b34 answer> $3 = {isa = 0x496e7469, a = 0}