我們正在研究在Linux下用arm-eabi-gcc編譯的C程序。如何獲取結構轉儲中字段的相對地址。 [C]
我們正在使用大型結構的轉儲,並且我們在確定在哪個地址應該讀取我們結構的各個字段(如其中的50個)時存在問題(存儲器對齊和填充不太可預測我)。
有什麼辦法可以獲得我們的編譯器生成的結構的內存映射。 gdb中的選項?或者任何幫助我們找到字段和地址之間的對應關係的工具?
我們正在研究在Linux下用arm-eabi-gcc編譯的C程序。如何獲取結構轉儲中字段的相對地址。 [C]
我們正在使用大型結構的轉儲,並且我們在確定在哪個地址應該讀取我們結構的各個字段(如其中的50個)時存在問題(存儲器對齊和填充不太可預測我)。
有什麼辦法可以獲得我們的編譯器生成的結構的內存映射。 gdb中的選項?或者任何幫助我們找到字段和地址之間的對應關係的工具?
您可以使用gdb
。在gdb
struct A {
int a;
char b;
short c;
};
int main() {
struct A a;
}
加載了二進制:作爲一個例子,我將使用這個源
(gdb) print (int)&((struct A*)0)->a
$1 = 0
(gdb) print (int)&((struct A*)0)->b
$2 = 4
(gdb) print (int)&((struct A*)0)->c
$3 = 6
UPDATE:
如果你需要做的大量那麼你可能會發現使用GDB新的python界面很方便(你需要最新版本的GDB來使用它,我使用的是7.4)。我創建offsets.py:
import gdb
class Offsets(gdb.Command):
def __init__(self):
super (Offsets, self).__init__ ('offsets-of', gdb.COMMAND_DATA)
def invoke(self, arg, from_tty):
argv = gdb.string_to_argv(arg)
if len(argv) != 1:
raise gdb.GdbError('offsets-of takes exactly 1 argument.')
stype = gdb.lookup_type(argv[0])
print argv[0], '{'
for field in stype.fields():
print ' %s => %d' % (field.name, field.bitpos//8)
print '}'
Offsets()
然後,您可以添加到您的.gdbinit:
python
sys.path.insert(0, '/path/to/script/dir')
import offsets
end
然後用它在GDB,如:
(gdb) offsets-of "struct A"
struct A {
a => 0
b => 4
c => 6
}
這個腳本使得一些簡化的假設,就像你不使用位域一樣,它不會挖掘嵌套的結構,但如果你需要它們,那些變化是相當簡單的。
我承諾,但我希望列出其中的50個所需字段。 – Akhneyzar 2012-03-20 14:44:18
我做了一個更完整的版本,感謝靈感。 [Clicky](https://github.com/Craxic/PyGDBOffsets/blob/master/offsets.py) – AStupidNoob 2014-11-08 09:21:17
你的'.gdbinit'看起來很奇怪。爲什麼不''source/path/to/script/dir/offsets.py' – zhangyoufu 2015-06-11 02:32:10
在我看來,你可以寫一點像這樣的代碼爲必填字段
struct MyStruct S;
int Offset_of_X=((long)&(S.X))-((long)&S);
來計算這個編譯形勢字節偏移量。
這應該說明編譯器有任何對齊問題。
但它缺少50個或更多字段的效率。 – Akhneyzar 2012-03-20 14:45:04
這不會編譯:指針算術不允許您從X指針中減去指向S的指針。 – 2012-03-20 14:50:15
您可以使用標準offsetof()
宏(在stddef.h
中定義)在C程序中執行此操作。不過,我不確定這是你想要的,因爲你可能無法運行它(在主機上編譯它可能會返回錯誤的偏移量)。
#include <stdio.h>
#include <stddef.h>
struct A {
int a;
char b;
short c;
};
int main() {
printf("Offset of b in A is %zu\n", offsetof(struct A, b));
return 0;
}
但是,您可能會使用一些hack從編譯的二進制獲得偏移量而不執行它。也許分配一個靜態變量的偏移值,並找到一些方法來獲得它的價值。
我可能在這裏丟失了一些明顯的東西,但是如果你有一個被聲明爲結構實例(或者結構體指針)的變量(比如'x'),那麼你應該只需要鍵入'在gdb中打印x'(或'print * x',如果是指針)來轉儲所有成員。 – 2012-03-20 15:34:04
我不是想要獲得我想要轉儲的地址。我已經有了轉儲,需要所有成員的相對地址。 – Akhneyzar 2012-05-04 15:19:30