“接头组”关于混合 clang Windows 驱动程序
好吧,这里的情况非常特殊,所以有点恶心,答案可能是否定的。 使用 clang(因为它是 Unix 源代码)将项目编译为 .libs,但与 MSVC++ 链接“/driver”以制作内核组件。
寻找一种处理 Linux MODULE_PARAM()
的方法,其中可以定义 static int tunable;
并使其可以针对内核进行更改。可能会被写入注册表项,这似乎是 Windows 执行 sysctl、kstat 或 /proc 等价操作的方式。
这可以通过“链接器集”轻松处理,使用 SET_ENTRY(tunable)
然后 SET_FOREACH()
循环遍历它们。
我怀疑是因为与 MSVC++ 链接而导致它们工作时遇到一些问题,所以我可能无法使其工作。但也许你们可以想个办法。
使用:
#define __MAKE_SET_CONST const
#define __STRING(x) #x /* stringify without expanding x */
#define __XSTRING(x) __STRING(x) /* expand x, then stringify */
#define __GLOBL(sym) __asm__(".globl " __XSTRING(sym))
#define __WEAK(sym) __asm__(".weak " __XSTRING(sym))
#define __CONCAT1(x, y) x ## y
#define __CONCAT(x, y) __CONCAT1(x, y)
#define __used __attribute__((__used__))
#define __section(x) __attribute__((__section__(x)))
#define __nosanitizeaddress __attribute__((no_sanitize("address")))
#define __weak_symbol __attribute__((__weak__))
#define __MAKE_SET_QV(set, sym, qv) \
__WEAK(__CONCAT(__start_set_,set)); \
__WEAK(__CONCAT(__stop_set_,set)); \
static void const * qv \
__set_##set##_sym_##sym __section("set_" #set) \
__nosanitizeaddress \
__used = &(sym)
#define __MAKE_SET(set, sym) __MAKE_SET_QV(set, sym, __MAKE_SET_CONST)
#define TEXT_SET(set, sym) __MAKE_SET(set, sym)
#define DATA_SET(set, sym) __MAKE_SET(set, sym)
#define DATA_WSET(set, sym) __MAKE_SET_QV(set, sym, )
#define BSS_SET(set, sym) __MAKE_SET(set, sym)
#define ABS_SET(set, sym) __MAKE_SET(set, sym)
#define SET_ENTRY(set, sym) __MAKE_SET(set, sym)
static int settest1 = 58;
static int settest2 = 156;
SET_ENTRY(testset, settest1);
SET_ENTRY(testset, settest2);
#define SET_BEGIN(set) \
(&__CONCAT(__start_set_,set))
#define SET_LIMIT(set) \
(&__CONCAT(__stop_set_,set))
#define SET_DECLARE(set, ptype) \
extern ptype __weak_symbol *__CONCAT(__start_set_,set); \
extern ptype __weak_symbol *__CONCAT(__stop_set_,set)
#define SET_FOREACH(pvar, set) \
for (pvar = SET_BEGIN(set); pvar < SET_LIMIT(set); pvar++)
void
linkersettest(void)
{
SET_DECLARE(testset, int);
int **ptr;
SET_FOREACH(ptr, testset) {
int x = **ptr;
KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL,
"linkerset test: %d\n", x));
}
}
编译(clang)似乎没问题,但是可惜,链接(MSVC++)说:
错误LNK2016:绝对符号'__start_set_testset'用作第0x1节中REL32重定位的目标
OK so very special situation here, so it is somewhat gross and the answer is probably no.
Compiling a project with clang (as it is Unix source) into .libs, but linking with MSVC++ for "/driver" to make the kernel component.
Looking for a way to handle Linux MODULE_PARAM()
where they can define static int tunable;
and have it be changeable for the kernel. Probably to be made into Registry entries, that seems to be how Windows would do the equivalent of sysctl, or kstat, or /proc
This could easily be handled by a "linker set", using SET_ENTRY(tunable)
and then SET_FOREACH()
to loop through them all.
Having some issues to get them to work, I suspect because of linking with MSVC++, so I might not be able to make it work. But maybe you guys can think of a way around.
Using:
#define __MAKE_SET_CONST const
#define __STRING(x) #x /* stringify without expanding x */
#define __XSTRING(x) __STRING(x) /* expand x, then stringify */
#define __GLOBL(sym) __asm__(".globl " __XSTRING(sym))
#define __WEAK(sym) __asm__(".weak " __XSTRING(sym))
#define __CONCAT1(x, y) x ## y
#define __CONCAT(x, y) __CONCAT1(x, y)
#define __used __attribute__((__used__))
#define __section(x) __attribute__((__section__(x)))
#define __nosanitizeaddress __attribute__((no_sanitize("address")))
#define __weak_symbol __attribute__((__weak__))
#define __MAKE_SET_QV(set, sym, qv) \
__WEAK(__CONCAT(__start_set_,set)); \
__WEAK(__CONCAT(__stop_set_,set)); \
static void const * qv \
__set_##set##_sym_##sym __section("set_" #set) \
__nosanitizeaddress \
__used = &(sym)
#define __MAKE_SET(set, sym) __MAKE_SET_QV(set, sym, __MAKE_SET_CONST)
#define TEXT_SET(set, sym) __MAKE_SET(set, sym)
#define DATA_SET(set, sym) __MAKE_SET(set, sym)
#define DATA_WSET(set, sym) __MAKE_SET_QV(set, sym, )
#define BSS_SET(set, sym) __MAKE_SET(set, sym)
#define ABS_SET(set, sym) __MAKE_SET(set, sym)
#define SET_ENTRY(set, sym) __MAKE_SET(set, sym)
static int settest1 = 58;
static int settest2 = 156;
SET_ENTRY(testset, settest1);
SET_ENTRY(testset, settest2);
#define SET_BEGIN(set) \
(&__CONCAT(__start_set_,set))
#define SET_LIMIT(set) \
(&__CONCAT(__stop_set_,set))
#define SET_DECLARE(set, ptype) \
extern ptype __weak_symbol *__CONCAT(__start_set_,set); \
extern ptype __weak_symbol *__CONCAT(__stop_set_,set)
#define SET_FOREACH(pvar, set) \
for (pvar = SET_BEGIN(set); pvar < SET_LIMIT(set); pvar++)
void
linkersettest(void)
{
SET_DECLARE(testset, int);
int **ptr;
SET_FOREACH(ptr, testset) {
int x = **ptr;
KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL,
"linkerset test: %d\n", x));
}
}
Compiling (clang) seems ok, but alas, linking (MSVC++) says:
error LNK2016: absolute symbol '__start_set_testset' used as target of REL32 relocation in section 0x1
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
进行如下更改:
Windows 上的
static
会将其从 .obj 文件中删除。删除static
并使用:获取 .obj 文件中所有预期的定义,包括
__set_testset_sym_settest1
和__start_set_testset
。但它不起作用,因为它似乎根本没有创建链接器部分
set_testset
,并且提到的符号是“随机”的,而不是预期的start、settest1, settest2,停止
。在查看 #pragma section(".CRT$XCU",read,write) 的示例以将构造函数添加到 CRT 的 initterm 时,我遇到了以下代码片段:
这似乎是 Windows 的做法“链接器集”,并且它有效。
如果我将节名称从
set_testset
调整为 Windows 名称,如.mine$
并确保开始/停止为“a”和“z”,则 clang 方式可能会起作用分别。我假设“m”只是任何字符,只要它在“a”和“z”之间即可获得顺序。
.mime$m
的设置前面是否应该有#pragma
行?我还没有看过#pragma section read
行的作用(但没有它也可以工作)。Making changes like:
The
static
here on Windows will drop it from .obj file. Removingstatic
and going with:gets us all the expected defines in the .obj file, including
__set_testset_sym_settest1
and__start_set_testset
.But it doesn't work, in that it does not appear to make a linker section
set_testset
at all, and the mentioned symbols are "randomly" in side, not the expectedstart, settest1, settest2, stop
.While looking around examples of
#pragma section(".CRT$XCU",read,write)
to add constructors to CRT's initterm, I came across this snippet:Which appears to be the way Windows would do "linker-sets", and it works.
Possibly the clang way will work, if I adjust the section name from
set_testset
to a Windows name like.mine$
and ensure start/stop is "a" and "z" respectively.I assume the "m" is just any character, as long as it is between "a" and "z", to get the order.
Should the setting of
.mime$m
be preceded by a#pragma
line? I've not looked at what#pragma section read
line does, yet (but works without it).