I'm writing a device driver in MSVC. As part of design I want to have different modules but have the modules somewhat isolated from each other so that they are interchangeable in the future. My design has a structure with the following declaration
typedef struct tagMODULE_INTERFACE {
NTSTATUS (*initialize)(GLOBAL_DATA *pGD);
NTSTATUS (*shutdown)(void);
NTSTATUS (*sendResponse)(PVOID outBuf, ULONG outBufSz, PULONG outBufLen);
} MODULE_INTERFACE, *PMODULE_INTERFACE;
In the main .c file I have my main array of modules to load at install time. It is defined as such:
MODULE_INTERFACE modules[2] =
{
Module1,
{NULL, NULL, NULL}// terminal entry
};
In my module1.c file I expose the following:
CONST MODULE_INTERFACE Module1 = {initializeModule1, shutdownModule1, sendModule1Response};
In my module1.h file I have:
extern CONST MODULE_INTERFACE Module1;
The idea here is that I don't have to declare initializeModule1, shutdownModule1 and sendModule1Response functions outside of module1.c, but the main.c will have an array of function pointers to use to initialize, shutdown and callback whenever necessary.
My problem is that I'm getting a C2099 "initialize is not a constant" error for the Module1 entry in modules and I'm getting C2078 "too many initializers" for the {NULL, NULL, NULL} entry.
What am I missing here? I thought originally that if I ensured that module1.c compiled ahead of main.c it would solve the first problem, but it didn't.
Any help would be greatly appreciated.
Related
I am trying to compile one driver in VS, but it shows -
Severity Code Description Project File Line Suppression State
Error LNK2019 unresolved external symbol __imp__PsGetProcessWow64Process#4 referenced in function _GetProcessModule#8 Garhal C:\Users\Raitis\source\repos\GarHal_CSGO\Garhal\memory.obj 1
Quickly enough, I found a place, where this PsGetProcessWow64Process is being used https://prnt.sc/uffavf
But it is defined, and it's even an official ntos.h function. Just pressing F12 on it finds it easily - https://prnt.sc/uffbjg
Screenshot from error list - https://prnt.sc/uffc6t
The problem is that this in undocumented functions and the linker is having a hard time finding where is the function to put a pointer to it in the generated binary, so first include ntifs.h before ntddk.h like this
#include <ntifs.h>
#include <ntddk.h>
it must be before ntddk or you will get weird errors
then add this line :
NTKERNELAPI PVOID PsGetProcessWow64Process(__in PEPROCESS Process);
which is the signature of the function and now you are ready to call that function
another way to get it is using function pointers and resolving it at run time
#include <ntddk.h>
typedef struct _PEB32 {
UCHAR InheritedAddressSpace;
UCHAR ReadImageFileExecOptions;
UCHAR BeingDebugged;
UCHAR Spare;
ULONG Mutant;
ULONG ImageBaseAddress;
ULONG/*PPEB_LDR_DATA32*/ Ldr;
} PEB32, *PPEB32;
typedef PPEB32 (NTAPI * pfn_PsGetProcessWow64Process) (PEPROCESS Process);
pfn_PsGetProcessWow64Process PsGetProcessWow64Process = NULL;
RtlInitUnicodeString (&usFunctionName, L"PsGetProcessWow64Process");
PsGetProcessWow64Process = (pfn_PsGetProcessWow64Process) (SIZE_T)MmGetSystemRoutineAddress (&usFunctionName);
pPEB32 = PsGetProcessWow64Process (pEProcess);
I have a 218KB .dll and a 596KB .so file, both with identical names. I want to link to the .dll to avoid the "unresolved external symbol" error that the linker returns, but I can't find a way to link to the DLL file.
According to this Pelles C forum topic, I need to use the .def file to create a .lib... but I don't have a .def file. This forum topic shows how to use polink to create a .lib from the command line, so I ran polink /? to get some more options. I noticed a /MAKEDEF option, but running this with both the .dll and the .so gives a "No library file specified" fatal error.
I have been trying to do this for three hours, and am out of ideas. I have got to the point where my web searches turn up my own help-requests. There must be a way to do this... How can I link to a .dll?
With information found in the header #include and your details, here is a way to replace the missing function by calling them dynamically from your software.
1- the following prototype is in #include :
typedef float (* XPLMFlightLoop_f)(float inElapsedSinceLastCall, float inElapsedTimeSinceLastFlightLoop, int inCounter, void * inRefcon);
2- some const that you can fill as needed:
const char *sDllPathName = "<Your XPLM_API DLL>.dll";
const char *sXPLMRegisterFlightLoopCallbackName = "XPLMRegisterFlightLoopCallback";
In order to confirm the sXPLMRegisterFlightLoopCallbackName, you can
use the freeware Dependency Walker and check name and format of
the exported functions.
3- declare the prototype of the external function:
Be aware to the calling convention __cdecl or __stdcall
In the current case, the keyword XPLM_API is defined in the XPLMDefs.h as follow:
#define XPLM_API __declspec(dllexport) // meaning __cdecl calling convention
typedef void (__cdecl *XPLMRegisterFlightLoopCallback_PROC)(XPLMFlightLoop_f, float, void *);
4- clone the function to call it in your software:
#include <windows.h>
void XPLMRegisterFlightLoopCallback(XPLMFlightLoop_f inFlightLoop, float inInterval, void * inRefcon)
{
HINSTANCE hInstDLL;
XPLMRegisterFlightLoopCallback_PROC pMyDynamicProc = NULL;
// Load your DLL in memory
hInstDLL = LoadLibrary(sDllPathName);
if (hInstDLL!=NULL)
{
// Search for the XPLM Function
pMyDynamicProc = (XPLMRegisterFlightLoopCallback_PROC) GetProcAddress(hInstDLL, sXPLMRegisterFlightLoopCallbackName);
if (pMyDynamicProc != NULL)
{
// Call the XPLM Function with the orignal parameter
(pMyDynamicProc)(inFlightLoop,inInterval,inRefcon);
return;
}
}
// Do something when DLL is missing or function not found
}
5- just add your described call:
...
XPLMRegisterFlightLoopCallback(callbackfunction, 0, NULL);
...
When I try to compile the program below, I get a linker error:
/tmp/ccAikIsV.o undefined reference to uvlc_encode_blockline
I have all the structures video_controller_t .. etc declared and typedefed
int uvlc_encode_blockline(struct video_controller_t* controller, const struct vp_api_picture_t* blockline, bool_t picture_complete );
int uvlc_decode_blockline(struct video_controller_t* controller,struct vp_api_picture_t* picture, bool_t* got_image );
int uvlc_update( struct video_controller_t* controller );
int uvlc_cache( struct video_controller_t* controller,struct video_stream_t* ex_stream);
const uvlc_codec_t uvlc_codec = {
uvlc_encode_blockline,
uvlc_decode_blockline,
uvlc_update,
uvlc_cache,
{ 0 }
};
Please let me know if anyone has any suggestions.
Update
I agree that we should define the function to tell linker to get it and use it. When I did something similar, I did not get any error. I declared function pointer:
typedef C_RESULT (encode_blockline_fc)(struct video_controller_t controller,
const struct vp_api_picture_t* blockline,
bool_t picture_complete);
and used it in struct below:
typedef struct _video_codec_t
{
encode_blockline_fc encode_blockline;
decode_blockline_fc decode_blockline;
update_fc update;
cache_stream_fc cache_stream;
} video_codec_t;
Please let me know if there is anything wrong in the syntax below:
const uvlc_codec_t uvlc_codec = {
uvlc_encode_blockline,
uvlc_decode_blockline,
uvlc_update,
uvlc_cache,
{ 0 }
};
I agree that we should define the function to tell linker to get it and use it. when I did something similar, I did not get any error. I declared function pointer
typedef C_RESULT (encode_blockline_fc)( struct video_controller_t controller, const struct vp_api_picture_t* blockline, bool_t picture_complete );
and used it in struct below
typedef struct _video_codec_t { encode_blockline_fc encode_blockline; decode_blockline_fc decode_blockline; update_fc update; cache_stream_fc cache_stream; }video_codec_t
Please let me know if there is anything wrong in the syntax below:
const uvlc_codec_t uvlc_codec = {
uvlc_encode_blockline,
uvlc_decode_blockline,
uvlc_update,
uvlc_cache,
{ 0 }
};
The linker complains about an unresolved reference to a function, not about the struct. You should pass the linker an object file or a library that contains this function, or define it in the current compilation unit.
There are few possibility of Linker Error-
1- If you fail to include all of the necessary object files in the linking process.
2- If there are more than one definition for a class, function, or variable.
So check it.
You've told the compiler that the function uvlc_encode_blockline() exists somewhere, but when the linker goes to look for it, it can't actually find it — so it complains that it can't find it.
The declaration is enough to let the source file compile to object code. To link the program, you actually have to define the function and link the object file that contains the definition in with the object file that references it.
I'm trying to use gate_desc *idt_table in a kernel module. The set_trap_gate() function defined in desc.h uses this pointer. In desc.h is also a definition : extern gate_desc idt_table[].
I tried different things:
use idt_table in my module without definition or affectation
affect idt_table with my (valid) idt_table address
I get either an id_table undefined warning during compilation or incomplete type for idt_table.
creating a new var named for instance gate_desc *it = (gate_desc *)#; And copy the set_trap_gate, set_gate, write_idt_entry, pack_gate functions from sched.h to my module file (renaming them, and using it instead of idt_table). This compiles fine but when inserting my module I get an unknown symbol in module (ret -1) error.
(there is no reference in my module to idt_table, and the functions I use from sched do use my variable).
I tried to see where in the files included by sched.h was defined idt_table, but couldn't find it!
Does someone know how I could use, the idt_table pointer from sched.h (affecting it with the corrct address) or create a new pointer?
Theoretically, you could implement a non-init-section set_trap_gate() via:
void set_trap_gate(int n, void *addr)
{
struct { uint16_t lim; struct desc_struct *idt_table; }
__attribute__((packed)) idt;
__asm__ ("sidt %0" : : "m"(idt) : "memory");
_set_gate(idt.idt_table + n, 15, 0, addr);
}
But that'd be CPU-local, i.e. it's not guaranteed to modify any other IDT but the one of the CPU it's running on. Also, it might fall foul of writeprotected memory.
What exactly is it you're trying to achieve ?
I have a struct where a constant char string is defined and a pointer to my own string object. The goal is to declare a variable of this struct with the chars set and the txt set t NULL and than during runtime create the MyString object representing the chars. I can not create the MyString during compilation while I use the GLib and this lib first needs the g_type_init to be called.
struct _MyStaticString {
volatile MyString * txt;
const char *chars;
};
A declaration would then look like:
struct _MyStaticString my_test_string = { NULL, "Hello world or foo bar, or a rick roll" };
Then their is a function which is repsonsible for delivering me the MyString object by first checking if txt is NULL, if so create a new MyString object and return this MyString object.
struct _MyString *my_static_string(struct _MyStaticString *a_static) {
printf("a_static=%lx\n", (gulong) a_static);
printf("a_static.chars=%s\n", (char *) a_static->chars);
if (a_static->txt == NULL) {
CatString *result = g_object_new(MY_TYPE_STRING, NULL);
// result->data = (gchar *) a_static->chars;
result->data = strdup((char *) a_static->chars);
result->size = strlen((char *) a_static->chars);
result->hash = 0;
g_object_ref_sink(G_OBJECT(result));
result->parent.ref_count = 1000;
a_static->txt = result;
}
return (struct _MyString *) (a_static->txt);
}
This all works great and I'm so happy, at least when I'm running GCC on Linux. As soon as I start compiling this code on Windows with the help of the MinGW compiler things start going wrong. If I put everything in one project It's still fine but as soon as put the declaration in a .a library and use it elsewhere the field a_static->chars becomes NULL. So I started playing/tweaking/testing: I thought maybe it's the alignment of the data in the Object files and thus added #pragma pack(16). It didn't work. Than I thought maybe there is an attribute which can help me. So I added __attribute__ ((common)). It didn't work. I thought to be smart and separated the string from the structure declaration itself like:
const char helper_txt = "Hello world or foo bar, or a rick roll";
struct _MyStaticString my_test_string = { NULL, helper_txt };
I get compile errors:
error: initializer element is not constant
error: (near initialization for 'field.chars')
Here are my compiler flags
C:\MinGW\bin\gcc.exe
-IC:\MinGW\include
-IC:\GTK_ALL_IN_ONE\include\gtk-2.0
-IC:\GTK_ALL_IN_ONE\lib\gtk-2.0\include
-IC:\GTK_ALL_IN_ONE\include\atk-1.0
-IC:\GTK_ALL_IN_ONE\include\cairo
-IC:\GTK_ALL_IN_ONE\include\gdk-pixbuf-2.0
-IC:\GTK_ALL_IN_ONE\include\pango-1.0
-IC:\GTK_ALL_IN_ONE\include\glib-2.0
-IC:\GTK_ALL_IN_ONE\lib\glib-2.0\include
-IC:\GTK_ALL_IN_ONE\include
-IC:\GTK_ALL_IN_ONE\include\freetype2
-IC:\GTK_ALL_IN_ONE\include\libpng14
-IC:\work\workspace\module-blah\src
-O0 -g3 -Wall -c -fmessage-length=0 -mms-bitfields -DOSWINDOWS
and here is the version
C:\>c:\MinGW\bin\gcc.exe --version
gcc.exe (GCC) 4.5.0
Copyright (C) 2010 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Do I miss some compiler flag or do I need to add an attribute to make sure the const char * string is exported into the .a lib and is their an easy way to check weather a string is in the .a lib? Or is it maybe some linker option ?
My guess is that you've still got what looks like a declaration of the variable that is turning up with NULL value in your project somewhere besides the library (.a file). GCC and the linker sometimes produce code that seems to follow your intentions rather than the strict letter of C when you do things like declare the same variable in more than one .c file (or in a .h file which is included in more than one .c file in the same project). What this should result in is more than one copy of the variable and possibly a linker error telling you that there is more than one object with the same name in your code, but for some reason this doesn't always happen when you are linking together lots of .o files that contain duplications of the same variable.
My guess here is that rather than:
extern struct _MyStaticString a_string;
in a header file you have:
struct _MyStaticString a_string;
and that you had what you consider the real declaration -- the one with the initialization -- in a .c file.
When you moved the real declaration to the library the linker's behavior changed when fulfilling the need for an a_string object. It already had one or more from the .o files from the main program so it didn't bother looking in the library for one. Previously it saw that it had several from the .o files and decided to go with the one that had been initialized to a non-zero or non-NULL value (the default for global or static variables). But without that initialized version of your variable around the linker has already decided to just go with one of the uninitialized versions of the variable before it even looks in the library for the value you wanted it to use.