c - 暂时转义函数范围以在 C 中定义全局符号? (海湾合作委员会)

标签 c gcc macros c-preprocessor gnu-assembler

有没有什么办法,在标准 C 中或使用 gcc/gas/binutils/etc 失败时,使用在函数定义主体的语法范围内编写的代码(可能是宏)来定义全局符号?

没有出现在函数体外部的每个此类符号都需要一个单独的宏?

为了这个目的,如果我必须明确指定 ELF 部分来放入生成的符号,那很好,如果我必须使用像 .pushsection.popsection(如果他们能提供帮助?)等。任何和所有 gcc 扩展都是公平的游戏。

我想做这件疯狂的事情的原因是跟踪点声明(必须出现在函数体中)可以自动生成跟踪工具可以查找的关联元数据。无需单独预先声明跟踪点,即使其尽可能干燥。

伪代码

void foo(void)
{
    normal_app_code();
    MAGICALLY_DEFINE_A_GLOBAL_VARIABLE_SYMBOL(symboltype, symbolname);
    more_normal_app_code();
}

这样编译的结果就像上面写的一样:

symboltype symbolname;

void foo(void)
{
    normal_app_code();
    some_library_function_that_uses(symbolname);
    more_normal_app_code();
}

上下文

我正在研究增强 systemtap/dtrace 跟踪 API 以支持记录数据类型和探测参数名称的想法。

我目前的设计要求应用程序作者在顶级(全局)范围内插入额外的宏来定义 stap 运行时将用于发现名称和 arg 类型的探测器的符号,例如人为的:

STAP_PROBE2_ARGNAMES(myprovider, myprobe, foo, bar);
STAP_PROBE2_ARGTYPES(myprovider, myprobe, const char *, MyDataType*);

void something(const char *foo)
{
    MyDataType *bar = get_bar();
    STAP_PROBE2(myprovider, myprobe, foo, bar);
}

这很不方便,而且容易出错。特别是如果应用程序想要自动生成 STAP_PROBEn(..) 探测点作为它自己的宏的一部分。

我宁愿在同一站点的跟踪点旁边声明 arg 类型和名称信息,使用预处理器字符串化来捕获 arg 名称(当它们是简单的变量名称标记时)和 __typeof__运算符来捕获它们的类型名称,例如:

void something(const char *foo)
{
    MyDataType *bar = get_bar();
    STAP_PROBE2_ARGINFO(myprovider, myprobe, foo, bar);
}

或者对于非简单标记表达式参数,例如:

void something(void)
{
    MyDataTypeHolder *barholder = get_barholder();
    STAP_PROBE2_ARGNAMES(myprovider, myprobe,
        something_global->foo, "foo",
        barholder->bar, "bar");
}

STAP_PROBE2_ARGINFO 的宏扩展负责使用适当的字符串化和 _typeof_ 运算符为全局符号表中的字符数组生成一对单独的符号,例如伪-ish-c:

#define STAP_PROBE2_ARGINFO(myprovider, myprobe, arg1, arg2) \
    STAP_PROBE2(myprovider, myprobe, (arg1), (arg2)) \
    STAP_PROBE2_ARGTYPES(myprovider, myprobe, (arg1), (arg2))
    STAP_PROBE2_ARGNAMES(myprovider, myprobe, (arg1), (arg2))

#define STAP_PROBE2_ARGTYPES(myprovider, myprobe, argname1, argname2) \
    const char _stapargtypes_#myprovider#_#myprobe[2][] = {#argname1, #argname2};

#define STAP_PROBE2_ARGTYPES(myprovider, myprobe, arg1, arg2) \
    const char _stapargtypes_#myprovider#_#myprobe[2][] = {__typeof__((arg1)), __typeof__((arg2))};

... 和 STAP_PROBE2_ARGNAMES 类似的东西,分别提取和存储显式提供的 arg 名称。

目标是结果类似于以下的全局声明:

const char _stapargnames_myprovider_myprobe[2][] = {"foo", "bar"};
const char _stapargtypes_myprovider_myprobe[2][] = {"const char *", "MyDataType*"};

并且还在 STAP_PROBE2_ARGINFO(...) 出现的调用站点发出探测点本身的常用 asm,就好像它是一个普通的 STAP_PROBE2(...).

疯了吗?

可能吗?

最佳答案

我不明白为什么你不能用 __asm__.pushsection 来做到这一点。在 C 中为变量做一个 extern 声明,它在 block 范围内有效,以便它可以从 C 访问,并将其大小作为整数文字操作数传递给 __asm__。在 __asm__ 内部,您可以定义符号,如果您愿意(或不希望)将其设为 .global,并根据传入的大小为其预留空间。

关于c - 暂时转义函数范围以在 C 中定义全局符号? (海湾合作委员会),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59402666/

相关文章:

c - 如何访问 PC 键盘缓冲区以检测多个按键按下和按键释放?

c++ - GCC 中的循环展开行为

c - 如何在 gcc 中正确使用 __attribute__((fallthrough))

C++ 元编程

c - 使用C设置apache环境变量,功能类似PHP apache_setenv函数

c - 如何杀死进程组僵尸

gcc - 如何链接到 gcc 中的 libatomic 库

macros - IntelliJ 宏菜单

visual-studio - Visual Studio 宏 : How to perform "File -> Save All" programatically

c - 回文 - 仅限 C 语言