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
CodePudding user response:
Making changes like:
static void const * qv \
__set_##set##_sym_##sym __section("set_" #set) \
The static
here on Windows will drop it from .obj file. Removing static
and going with:
__declspec(dllexport) void const * qv \
__set_##set##_sym_##sym __section("set_" #set) \
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 expected start, 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:
typedef void(__cdecl* PF)(void);
#pragma section(".mine$a", read)
__declspec(allocate(".mine$a")) const PF InitSegStart = (PF)1;
#pragma section(".mine$z",read)
__declspec(allocate(".mine$z")) const PF InitSegEnd = (PF)1;
__declspec(allocate(".mine$m")) const PF __set_settest1 = (PF)&settest1;
__declspec(allocate(".mine$m")) const PF __set_settest2 = (PF)&settest2;
void
linkersettest(void)
{
const PF* x = &InitSegStart;
DbgBreakPoint();
for ( x; x < &InitSegEnd; x)
KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL,
"linkerset test: %p %p %d\n", x, *x, *(int *)*x ));
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).