有没有什么办法,在标准 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/