How to define offsetof() macro in GDB

一个人想着一个人 提交于 2020-12-02 07:15:17

问题


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:

  1. A type such as struct node will be splitted into Struct and node, so $arg0 = Struct, $arg1 = node.
  2. I am not sure if gdb's command can return a value.

Can anyone give me a hand?


回答1:


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.




回答2:


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.



来源:https://stackoverflow.com/questions/39607565/how-to-define-offsetof-macro-in-gdb

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!