I want to define some auxiliary marcos in GDB for convenience, one of them is the offsetof()
macro.
I tried
define offsetof
if $argc == 2
(int)(&((($arg0 *)0)->$arg1))
end
end
It doesn't work because:
struct node
will be splitted into Struct
and node
, so $arg0 = Struct
, $arg1 = node
.Can anyone give me a hand?
The offsetof() macro is an ANSI -required macro that should be found in stddef. h. Simply put, the offsetof() macro returns the number of bytes of offset before a particular element of a struct or union. The declaration of the macro varies from vendor to vendor and depends upon the processor architecture.
If there is a current stack frame, GDB uses the macros in scope at that frame's source code line. Otherwise, GDB uses the macros in scope at the current listing location; see List. Whenever GDB evaluates an expression, it always expands any macro invocations present in the expression.
Use offsetof() to find the offset from the start of z or from the start of x . #include <stddef. h> size_t offsetof(type, member); offsetof() returns the offset of the field member from the start of the structure type.
C library macro - offsetof() The C library macro offsetof(type, member-designator) results in a constant integer of type size_t which is the offset in bytes of a structure member from the beginning of the structure. The member is given by member-designator, and the name of the structure is given in type.
Rather than define offsetof
as a command, I think it's better to define it as a function. That way you can use it in expressions; and if you just want to see the offset you can always just use print
.
There are two ways to define offsetof
as a function.
If you are debugging C or C++, you can simply define it as a macro:
(gdb) macro define offsetof(t, f) &((t *) 0)->f
So given:
struct x {
int a;
long b;
};
On my machine I get:
(gdb) p offsetof(struct x, a)
$1 = (int *) 0x0
(gdb) p offsetof(struct x, b)
$2 = (long *) 0x8
The reason for the "C or C++" restriction above is that other languages don't run their expressions through gdb's built-in preprocessor.
If you want it to work in other languages, then the answer is to write a new convenience function in Python. This is a bit more involved, but see the gdb documentation for gdb.Function
.
If you use python to define offsetof
, you might begin with something like this:
import gdb
class offsetof(gdb.Command):
def invoke(self, args, from_tty):
value, name = args.split()
struct = gdb.parse_and_eval(value)
fields = { field.name: field for field in struct.type.fields() }
gdb.write("{} offset: {} bits\n".format(name, fields[name].bitpos))
offsetof("offsetof", gdb.COMMAND_USER)
If you save that to a file, and insure that the directory where you save it is in sys.path
, you can import it. For example, if you save it to your home directory, you might do something along these lines:
(gdb) pi
>>> import os
>>> sys.path.insert(0, os.getenv('HOME'))
>>> import offsetof
>>>
(gdb)
If your gdb has no pi
command you can prepend python
to each command following a >>>
prompt.
If gdb imports offsetof
with no complaint, you should then be able to invoke offsetof
as a gdb command. As written it expects two arguments (space separated), a value, and a name. If the value is a struct with a field having the provided name, it will report the offset in bits (not bytes, because the underlying python code can handle bitfields).
The code here can be improved. It has no real error handling beyond what it inherits from the code it calls, and as written it doesn't handle pointers.
This page describes some of the underlying code used in that example; the target
method it mentions might provide the beginnings of handling pointers (or you can just dereference pointers in the values you pass in, i.e. you might specify *this
rather than this
as the first parameter). The section on Type.fields()
mentions other attributes besides bitpos
which might also be of interest if you want to report other details about struct layout.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With