从复合C结构中提取变量名称和偏移量

时间:2018-01-09 23:26:22

标签: c variables struct wireshark

我正在开发一个Wireshark插件,它必须解码通过将结构写入数据包而创建的大数据包。如果我能够知道原始结构的变量名称和偏移量,那么我将能够解码数据而不考虑原始编译器。结构很大(> 650字节)并包含复合元素和typedef。

结构的构造根据生成数据的软件版本而变化。我可以访问原始头文件和用于创建软件的编译器,因此我可以创建一个框架来提取我需要在Wireshark中使用的细节。

我已成功手动编码解码所需的一些变量和偏移量,但结构的大小和复杂性需要比我手工完成的更多自动化。

关于如何做到这一点的任何建议都是非常受欢迎的。

1 个答案:

答案 0 :(得分:0)

免责声明:除了你在这里看到的,我自己并没有使用过这个,特别是在复杂的情况下;我只是将此作为答案发布,因为它比当前的答案缺乏更好,但如果这个答案中缺少更好的选项或关键信息,请不要感到惊讶。

使用-g标志进行编译时,看起来调试信息中提供了所需的所有信息。您可以使用

以接近原始的格式查看它
objdump -Wi object_file.o

这不是最有用的格式,有些工具可以为您分析。其中一个是paholesourcesLWN articleman 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 */
};