【问题标题】:Extract variable names and offsets from a compound C struct从复合 C 结构中提取变量名和偏移量
【发布时间】:2018-01-09 23:26:21
【问题描述】:

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

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

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

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

【问题讨论】:

  • 建议:“结构很大(> 650 字节)并且包含复合元素和类型定义。” --> 发布该结构(或它的副本)将提高答案的质量。发布“我将能够解码数据”的示例代码也有助于阐明您的编码目标。
  • 对于偏移量,offsetof 可以提供帮助。不仅如此,我还要检查编译器是否提供了一个 API 来访问这些信息;我知道 Clang 会,而且我很确定 GCC 会。正在使用什么编译器。
  • "不考虑原编译器":不同的编译器和不同的编译器设置,对数据的对齐方式会有所不同。这听起来比你想象的要复杂?
  • 我希望正确的答案是使用调试信息进行编译并以某种方式从中提取。我对各种调试信息标准知之甚少,无法帮助解决这个问题,但如果某些标准工具可以做到这一点,我不会感到惊讶。
  • 使用的编译器是 32 位 linux 中的 gcc。我知道我可以使用offset 来获得我需要的东西,但我希望有某种自动化脚本或代码可以列出所有结构元素和类型,然后使用它来循环生成的列表并使用offset 来获取所需信息。

标签: c variables struct wireshark


【解决方案1】:

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


当您使用-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 */
};

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多