The new function call_constructors in dlls/ntdll/loader.c introduced via
081c8e1c73bb8d79a060da7816b5c429180b35b7 Author: Alexandre Julliard julliard@winehq.org Date: Thu Apr 16 12:22:24 2020 +0200
ntdll: Execute .so constructors during module initialization.
breaks the build on FreeBSD and presumably others. Specifically,
struct link_map *map; : if (dlinfo( wm->so_handle, RTLD_DI_LINKMAP, &map ) == -1) return; while (map->l_ld->d_tag) :
fails to compile:
loader.c: In function ‘call_constructors’: loader.c:1329:21: warning: dereferencing ‘void *’ pointer 1329 | while (map->l_ld->d_tag) | ^~ loader.c:1329:21: error: request for member ‘d_tag’ in something not a structure or union
This is due to /usr/include/link.h (via /usr/include/sys/link_elf.h) defining link_map.l_ld as a void* as opposed to a more specific type like on Linux:
typedef struct link_map { caddr_t l_addr; /* Base Address of library */ #ifdef __mips__ caddr_t l_offs; /* Load Offset of library */ #endif const char *l_name; /* Absolute Path to Library */ const void *l_ld; /* Pointer to .dynamic in memory */ struct link_map *l_next, *l_prev; /* linked list of of mapped libs */ } Link_map;
Luckily FreeBSD does feature Elf64_Dyn and Elf32_Dyn which do match their Linux equivalents, so introducing a new variable holding a pointer to one of those and using implicit type conversions with void* addresses this.
If further platforms require similar adjustments, this should now be a question of extending one condition or adding two lines.
Gerald
Signed-off-by: Gerald Pfeifer gerald@pfeifer.com --- dlls/ntdll/loader.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-)
diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index c713a5d0a6..e9140145e1 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -1324,17 +1324,25 @@ static void call_constructors( WINE_MODREF *wm ) void (*init_func)(int, char **, char **) = NULL; void (**init_array)(int, char **, char **) = NULL; ULONG_PTR i, init_arraysz = 0; +#if defined (__FreeBSD__) && defined (__LP64__) + const Elf64_Dyn *l_ld; +#elif defined (__FreeBSD__) + const Elf32_Dyn *l_ld; +#else + const ElfW(Dyn) *l_ld; +#endif
if (dlinfo( wm->so_handle, RTLD_DI_LINKMAP, &map ) == -1) return; - while (map->l_ld->d_tag) + l_ld = map->l_ld; + while (l_ld->d_tag) { - switch (map->l_ld->d_tag) + switch (l_ld->d_tag) { - case 0x60009990: init_array = (void *)((char *)map->l_addr + map->l_ld->d_un.d_val); break; - case 0x60009991: init_arraysz = map->l_ld->d_un.d_val; break; - case 0x60009992: init_func = (void *)((char *)map->l_addr + map->l_ld->d_un.d_val); break; + case 0x60009990: init_array = (void *)((char *)map->l_addr + l_ld->d_un.d_val); break; + case 0x60009991: init_arraysz = l_ld->d_un.d_val; break; + case 0x60009992: init_func = (void *)((char *)map->l_addr + l_ld->d_un.d_val); break; } - map->l_ld++; + l_ld++; }
TRACE( "%s: got init_func %p init_array %p %lu\n", debugstr_us( &wm->ldr.BaseDllName ),