有没有办法,在标准 C 中或使用 gcc/gas/binutils/etc 失败时,使用在函数定义体的语法范围内编写的代码(可能是宏)来定义全局符号?
如果没有 ,是否需要为出现在函数体外部的每个此类符号单独设置宏?
为此,如果我必须明确指定 ELF 部分来放置生成的符号,那很好,如果我必须使用 .pushsection
和 .popsection
等 asm 功能(如果它们可以提供帮助?) .
我想做这件疯狂事情的原因是,跟踪点声明(必须出现在函数体中)可以自动生成跟踪工具可以查找的关联元数据。无需单独预先声明跟踪点,即使其尽可能干燥。
伪代码
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);
}
或者对于非简单 token 表达式参数,例如:
void something(void)
{
MyDataTypeHolder *barholder = get_barholder();
STAP_PROBE2_ARGNAMES(myprovider, myprobe,
something_global->foo, "foo",
barholder->bar, "bar");
}
STAP_PROBE2_ARGINFO
的宏扩展负责使用适当的字符串化和 _typeof_
运算符,例如,在全局符号表中为 char-array-array 生成一对单独的符号。伪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
声明,它在块范围内有效,以便它可以从 C 访问,并将其大小作为整数文字操作数传递给 __asm__
。在 __asm__
内部,您可以定义符号,如果您愿意(或不愿意),可以将其设为 .global
,并根据传入的大小为其预留空间。
关于c - 临时转义函数范围以在 C 中定义全局符号? (海合会),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/59402666/