免责声明:除了您在此处看到的内容之外,我自己并没有使用过这个,尤其是在复杂的情况下;我只是将其作为答案发布,因为它比当前缺少答案更好,但如果此答案中缺少更好的选项或关键信息,请不要感到惊讶。
当您使用-g 标志编译时,您需要的所有信息似乎都在调试信息中可用。您可以使用接近原始格式查看它
objdump -Wi object_file.o
这不是最有用的格式,有工具可以为您分析它。其中之一是pahole(sources,LWN article,man page);我没有足够用它来推荐它,但它似乎至少值得进一步研究。它可能位于 dwarves 或您的包管理器中,因为它是用于处理 DWARF 调试信息的相关工具集合的一部分。
它似乎准确地输出了您想要的信息,并带有一些标志。解析原始 C 更容易,但它看起来仍然更像是为人类设计的,而不是用于计算机解析的;我还没有找到一个看起来纯粹用于机器解析的标志。这是一个示例pahole 运行:
输入struct.c
#include <stdint.h>
struct simple {
int32_t i32;
char c;
uint64_t u64;
} simple_object;
struct complicated {
struct simple nested_simple;
union {
float union_float;
uint32_t union_int;
} nested_union;
struct {
double d;
char c;
} nested_struct;
char some_chars[5];
struct simple_packed nested_simple_packed;
enum {COMPLICATED_ENUM1, COMPLICATED_ENUM2, COMPLICATED_ENUM3} enumeration;
} complicated_object;
运行后
gcc -g structs.c -c -o structs.o
pahole --expand_types structs.o
你得到
struct simple {
/* typedef int32_t -> __int32_t */ int i32; /* 0 4 */
char c; /* 4 1 */
/* XXX 3 bytes hole, try to pack */
/* typedef uint64_t -> __uint64_t */ long unsigned int u64; /* 8 8 */
/* size: 16, cachelines: 1, members: 3 */
/* sum members: 13, holes: 1, sum holes: 3 */
/* last cacheline: 16 bytes */
};
struct complicated {
struct simple {
/* typedef int32_t -> __int32_t */ int i32; /* 0 4 */
char c; /* 4 1 */
/* XXX 3 bytes hole, try to pack */
/* typedef uint64_t -> __uint64_t */ long unsigned int u64; /* 8 8 */
} nested_simple; /* 0 16 */
union {
float union_float; /* 4 */
/* typedef uint32_t -> __uint32_t */ unsigned int union_int; /* 4 */
} nested_union; /* 16 4 */
/* XXX 4 bytes hole, try to pack */
struct {
double d; /* 24 8 */
char c; /* 32 1 */
} nested_struct; /* 24 16 */
char some_chars[5]; /* 40 5 */
/* XXX 3 bytes hole, try to pack */
enum {
COMPLICATED_ENUM1 = 0,
COMPLICATED_ENUM2 = 1,
COMPLICATED_ENUM3 = 2,
} enumeration; /* 48 4 */
/* size: 56, cachelines: 1, members: 5 */
/* sum members: 45, holes: 2, sum holes: 7 */
/* padding: 4 */
/* last cacheline: 56 bytes */
};