ufrisk / MemProcFS

MemProcFS
GNU Affero General Public License v3.0
2.8k stars 352 forks source link

Linux GCC/Clang inline semantics #268

Closed ajkhoury closed 4 months ago

ajkhoury commented 4 months ago

Even when targeting C11, GCC and Clang use C99 inline semantics in which the inline directs the compiler to expect an external definition in a separate translation unit. Due to the behavior of the C99 inline semantics, the following errors occur when statically linking:

/usr/bin/ld: libvmm.a(vmmlog.c.o): in function `VmmLog_Close':
/Source/MemProcFS/vmm/vmmlog.c:70: undefined reference to `VmmLog_GetModuleInfo'
/usr/bin/ld: libvmm.a(vmmlog.c.o): in function `VmmLog_LevelGet':
/Source/MemProcFS/vmm/vmmlog.c:92: undefined reference to `VmmLog_GetModuleInfo'
/usr/bin/ld: libvmm.a(vmmlog.c.o): in function `VmmLog_LevelSet':
/Source/MemProcFS/vmm/vmmlog.c:114: undefined reference to `VmmLog_GetModuleInfo'

Please consider using static inline semantics, or force inlining. Below is a small patch that force inlines the violating functions by adding a __forceinline macro to vmm/oscompatibility.h when targeting linux:

diff --git a/vmm/ob/ob.h b/vmm/ob/ob.h
index 2005987..1d3eef3 100644
--- a/vmm/ob/ob.h
+++ b/vmm/ob/ob.h
@@ -100,7 +100,7 @@ PVOID Ob_AllocEx(_In_opt_ VMM_HANDLE H, _In_ DWORD tag, _In_ UINT uFlags, _In_ S
 * -- pfnRef_1 = optional callback for when object reach refcount = 1 at DECREF.
 * -- return = allocated object on success, with refcount = 1, - NULL on fail.
 */
-inline PVOID Ob_Alloc(_In_ DWORD tag, _In_ UINT uFlags, _In_ SIZE_T uBytes, _In_opt_ OB_CLEANUP_CB pfnRef_0, _In_opt_ OB_CLEANUP_CB pfnRef_1)
+__forceinline PVOID Ob_Alloc(_In_ DWORD tag, _In_ UINT uFlags, _In_ SIZE_T uBytes, _In_opt_ OB_CLEANUP_CB pfnRef_0, _In_opt_ OB_CLEANUP_CB pfnRef_1)
 {
     return Ob_AllocEx(NULL, tag, uFlags, uBytes, pfnRef_0, pfnRef_1);
 }
diff --git a/vmm/oscompatibility.h b/vmm/oscompatibility.h
index 0e168dd..c740624 100644
--- a/vmm/oscompatibility.h
+++ b/vmm/oscompatibility.h
@@ -70,6 +70,7 @@ typedef struct tdSID                        { BYTE pb[12]; } SID, *PSID;
 typedef DWORD(*PTHREAD_START_ROUTINE)(PVOID);
 typedef DWORD(*LPTHREAD_START_ROUTINE)(PVOID);
 typedef int(*_CoreCrtNonSecureSearchSortCompareFunction)(void const *, void const *);
+#define __forceinline                       inline __attribute__((__always_inline__))
 #define WINAPI
 #define errno_t                             int
 #define CONST                               const
diff --git a/vmm/vmmlog.c b/vmm/vmmlog.c
index caa91b4..02c0419 100644
--- a/vmm/vmmlog.c
+++ b/vmm/vmmlog.c
@@ -41,7 +41,7 @@ typedef struct tdVMMLOG_CONTEXT {
 /*
 * Helper function to get a log module info object.
 */
-inline PVMMLOG_CONTEXT_MODULEINFO VmmLog_GetModuleInfo(_In_ VMM_HANDLE H, _In_ VMM_MODULE_ID MID)
+__forceinline PVMMLOG_CONTEXT_MODULEINFO VmmLog_GetModuleInfo(_In_ VMM_HANDLE H, _In_ VMM_MODULE_ID MID)
 {
     PVMMLOG_CONTEXT ctxLog = H->log;
     if(!ctxLog) { return NULL; }
diff --git a/vmm/vmmwinpool.c b/vmm/vmmwinpool.c
index a27faa7..bc272ef 100644
--- a/vmm/vmmwinpool.c
+++ b/vmm/vmmwinpool.c
@@ -31,7 +31,7 @@
 * -- dwPoolType
 * -- return
 */
-inline VMM_MAP_POOL_TP VmmWinPool_PoolTypeConvert(_In_ DWORD dwPoolType)
+__forceinline VMM_MAP_POOL_TP VmmWinPool_PoolTypeConvert(_In_ DWORD dwPoolType)
 {
     if(dwPoolType & 1) {
         return VMM_MAP_POOL_TP_PagedPool;
ufrisk commented 4 months ago

Can you check if the latest release just published fixes this issue?

ajkhoury commented 4 months ago

Yes all fixed, thanks!