用于实现偏移量的 gcc 插件



我正在编写一个用于解析结构字段的 gcc 插件。但是我有问题如何获取结构中每个字段的偏移量?就像 gcc 中的偏移宏一样。

我在tree.h中看到DECL_FIELD_OFFSET,但结果似乎不对。

我的代码遵循理查德·W·M·琼斯,https://rwmj.wordpress.com/2016/02/24/playing-with-gcc-plugins/

/* structsizes.cc plugin: public domain example code written by
 * Richard W.M. Jones
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gcc-plugin.h>
#include <tree.h>
#include <print-tree.h>
int plugin_is_GPL_compatible;
static FILE *log_fp;
static void
plugin_finish_type (void *event_data, void *user_data)
{
    tree type = (tree) event_data;
    tree d, sz;
    size_t size;
#if 1
    /* This is useful for working out how to navigate the tree below. */
    debug_tree (type);
#endif
    /* We only care about structs, not any other type definition. */
    if (TREE_CODE (type) == RECORD_TYPE) {
        /* Struct name? */
        tree name_tree = TYPE_NAME (type);
        /* Ignore unnamed structs. */
        if (!name_tree) {
            fprintf (log_fp, "ignoring unnamed structn");
            return;
        }
        const char *name;
        if (TREE_CODE (name_tree) == IDENTIFIER_NODE)
            name = IDENTIFIER_POINTER (name_tree);
        else if (TREE_CODE (name_tree) == TYPE_DECL && DECL_NAME (name_tree))
            name = IDENTIFIER_POINTER (DECL_NAME (name_tree));
        else
            name = "unknown struct name"; /* should never happen? */
        /* If the type is not complete, we can't do anything. */
        if (!COMPLETE_TYPE_P (type)) {
            fprintf (log_fp, "struct '%s' has incomplete typen", name);
            return;
        }

        for (d = TYPE_FIELDS(type); d != 0; d = TREE_CHAIN(d)) {
            tree mtype = TREE_TYPE(d);
            switch (TREE_CODE(d)) {
                case TYPE_DECL:
                    printf("TYPE_DECL %dn", TREE_CODE(d));
                    printf("TREE_TYPE %sn", get_tree_code_name(TREE_CODE(TREE_TYPE(d))));
                    printf("TREE_TYPE %dn", (TREE_CODE(TREE_TYPE(d))));
                    printf("DECL_NAME = %pn", DECL_NAME(d));
                    if (DECL_NAME(d))
                        printf("IDENTIFIER_POINTER = %sn", IDENTIFIER_POINTER(DECL_NAME(d)));
                    break;
                case FIELD_DECL:
                    printf("FIELD_DECL %dn", TREE_CODE(d));
                    printf("TREE_TYPE 1 %sn", get_tree_code_name(TREE_CODE(TREE_TYPE(d))));
                    printf("TREE_TYPE 1 %dn", (TREE_CODE(TREE_TYPE(d))));
                    sz = TYPE_SIZE(mtype);
                    if (TREE_CODE (sz) == INTEGER_CST &&
                            !TYPE_P (sz) && TREE_CONSTANT (sz)) {
                        size = TREE_INT_CST_LOW (sz);
                        printf ("TYPE_SIZE %zu [bits]n", size);
                        sz = TYPE_SIZE_UNIT(mtype);
                        size = TREE_INT_CST_LOW (sz);
                        printf ("TYPE_SIZE_UNIT %zu [bytes]n", size);
                    }
                    else
                        printf ("TYPE_SIZE has non-constant sizen");
                    sz = DECL_FIELD_OFFSET(d);
                    if (TREE_CODE (sz) == INTEGER_CST &&
                            !TYPE_P (sz) && TREE_CONSTANT (sz)) {
                        size = TREE_INT_CST_LOW(sz);
                        printf ("TYPE_OFFSET %zu [bits]n", size);
                    }
                    else
                        printf ("TYPE_OFFSET has non-constant sizen");
                    printf("DECL_NAME = %pn", DECL_NAME(d));
                    if (DECL_NAME(d))
                        printf("IDENTIFIER_POINTER = %sn", IDENTIFIER_POINTER(DECL_NAME(d)));
                    break;
                default:
                    printf("default %dn", TREE_CODE(d));
                    break;
            }
        }

        /* Get the size of the struct that has been defined. */
        tree size_tree = TYPE_SIZE (type);
        if (TREE_CODE (size_tree) == INTEGER_CST &&
                !TYPE_P (size_tree) && TREE_CONSTANT (size_tree)) {
            size = TREE_INT_CST_LOW (size_tree);
            fprintf (log_fp, "struct '%s' has size %zu [bits]n", name, size);
        }
        else
            fprintf (log_fp, "struct '%s' has non-constant sizen", name);
    }
    fflush (log_fp);
}
int
plugin_init (struct plugin_name_args *plugin_info,
        struct plugin_gcc_version *version)
{
    const char *logfile = NULL;
    size_t i;
    /* Open the log file. */
    for (i = 0; i < plugin_info->argc; ++i) {
        if (strcmp (plugin_info->argv[i].key, "log") == 0) {
            logfile = plugin_info->argv[i].value;
        }
    }
    if (!logfile) {
        fprintf (stderr, "structsizes plugin: missing parameter: -fplugin-arg-structsizes-log=<logfile>n");
        exit (EXIT_FAILURE);
    }
    log_fp = fopen (logfile, "a");
    if (log_fp == NULL) {
        perror (logfile);
        exit (EXIT_FAILURE);
    }
    fprintf (log_fp, "Loaded structsizes plugin (GCC %s.%s.%s)n",
            version->basever, version->devphase, version->revision);
    register_callback (plugin_info->base_name, PLUGIN_FINISH_TYPE,
            plugin_finish_type, NULL);
    return 0;
}

测试源文件为:

struct TestType {
    int test1;
    char test2;
    void *test3;
    void *(*test4)(char, int);
    char *test5;
    char test6;
};
int main()
{
    return 0;
}

但偏移量

TYPE_OFFSET 0
TYPE_OFFSET 0
TYPE_OFFSET 0
TYPE_OFFSET 16
TYPE_OFFSET 16
TYPE_OFFSET 32

不是正确的结果:

0
4
8
16
24
32

在询问gcc邮件列表后,Eric Botcazou给了我答案:https://gcc.gnu.org/ml/gcc/2018-02/msg00048.html

函数 bit_position 和 byte_position 可以给出结构中字段的偏移量。它们返回树类型数据结构,以便TREE_INT_CST_LOW可用于将它们转换为整数。

相关内容

  • 没有找到相关文章

最新更新