ntdll: Move the .so module initialization to winecrt0.
Use new ELF tag ids to avoid breaking backwards compatibility.
This commit is contained in:
parent
c20741b33a
commit
bef0969722
14 changed files with 143 additions and 95 deletions
6
configure
vendored
6
configure
vendored
|
@ -19795,6 +19795,12 @@ fi
|
|||
|
||||
ac_wine_check_funcs_save_LIBS="$LIBS"
|
||||
LIBS="$LIBS $DL_LIBS"
|
||||
ac_fn_c_check_func "$LINENO" "dladdr1" "ac_cv_func_dladdr1"
|
||||
if test "x$ac_cv_func_dladdr1" = xyes
|
||||
then :
|
||||
printf "%s\n" "#define HAVE_DLADDR1 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
ac_fn_c_check_func "$LINENO" "dlinfo" "ac_cv_func_dlinfo"
|
||||
if test "x$ac_cv_func_dlinfo" = xyes
|
||||
then :
|
||||
|
|
|
@ -2025,7 +2025,7 @@ CFLAGS="$ac_save_CFLAGS"
|
|||
|
||||
dnl Check for -ldl
|
||||
AC_SEARCH_LIBS(dlopen, dl)
|
||||
WINE_CHECK_LIB_FUNCS(dlinfo,[$DL_LIBS])
|
||||
WINE_CHECK_LIB_FUNCS(dladdr1 dlinfo,[$DL_LIBS])
|
||||
|
||||
dnl Check for -lnsl for Solaris
|
||||
AC_SEARCH_LIBS(gethostbyname, nsl)
|
||||
|
|
|
@ -1573,8 +1573,6 @@ static NTSTATUS MODULE_InitDLL( WINE_MODREF *wm, UINT reason, LPVOID lpReserved
|
|||
|
||||
if (wm->ldr.Flags & LDR_DONT_RESOLVE_REFS) return STATUS_SUCCESS;
|
||||
if (wm->ldr.TlsIndex != -1) call_tls_callbacks( wm->ldr.DllBase, reason );
|
||||
if (wm->ldr.Flags & LDR_WINE_INTERNAL && reason == DLL_PROCESS_ATTACH)
|
||||
NTDLL_UNIX_CALL( init_builtin_dll, wm->ldr.DllBase );
|
||||
if (!entry) return STATUS_SUCCESS;
|
||||
|
||||
if (TRACE_ON(relay))
|
||||
|
@ -4218,7 +4216,6 @@ void WINAPI LdrInitializeThunk( CONTEXT *context, ULONG_PTR unknown2, ULONG_PTR
|
|||
}
|
||||
release_address_space();
|
||||
if (wm->ldr.TlsIndex != -1) call_tls_callbacks( wm->ldr.DllBase, DLL_PROCESS_ATTACH );
|
||||
if (wm->ldr.Flags & LDR_WINE_INTERNAL) NTDLL_UNIX_CALL( init_builtin_dll, wm->ldr.DllBase );
|
||||
if (wm->ldr.ActivationContext) RtlDeactivateActivationContext( 0, cookie );
|
||||
process_breakpoint();
|
||||
}
|
||||
|
|
|
@ -1872,88 +1872,6 @@ NTSTATUS load_start_exe( WCHAR **image, void **module )
|
|||
}
|
||||
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
/* The PT_LOAD segments are sorted in increasing order, and the first
|
||||
* starts at the beginning of the ELF file. By parsing the file, we can
|
||||
* find that first PT_LOAD segment, from which we can find the base
|
||||
* address it wanted, and knowing mapbase where the binary was actually
|
||||
* loaded, use them to work out the relocbase offset. */
|
||||
static BOOL get_relocbase(caddr_t mapbase, caddr_t *relocbase)
|
||||
{
|
||||
Elf_Half i;
|
||||
#ifdef _WIN64
|
||||
const Elf64_Ehdr *elf_header = (Elf64_Ehdr*) mapbase;
|
||||
#else
|
||||
const Elf32_Ehdr *elf_header = (Elf32_Ehdr*) mapbase;
|
||||
#endif
|
||||
const Elf_Phdr *prog_header = (const Elf_Phdr *)(mapbase + elf_header->e_phoff);
|
||||
|
||||
for (i = 0; i < elf_header->e_phnum; i++)
|
||||
{
|
||||
if (prog_header->p_type == PT_LOAD)
|
||||
{
|
||||
caddr_t desired_base = (caddr_t)((prog_header->p_vaddr / prog_header->p_align) * prog_header->p_align);
|
||||
*relocbase = (caddr_t) (mapbase - desired_base);
|
||||
return TRUE;
|
||||
}
|
||||
prog_header++;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*************************************************************************
|
||||
* init_builtin_dll
|
||||
*/
|
||||
static NTSTATUS init_builtin_dll( void *module )
|
||||
{
|
||||
#ifdef HAVE_DLINFO
|
||||
void *handle = NULL;
|
||||
struct link_map *map;
|
||||
void (*init_func)(int, char **, char **) = NULL;
|
||||
void (**init_array)(int, char **, char **) = NULL;
|
||||
ULONG_PTR i, init_arraysz = 0;
|
||||
#ifdef _WIN64
|
||||
const Elf64_Dyn *dyn;
|
||||
#else
|
||||
const Elf32_Dyn *dyn;
|
||||
#endif
|
||||
|
||||
if (!(handle = get_builtin_so_handle( module ))) return STATUS_SUCCESS;
|
||||
if (dlinfo( handle, RTLD_DI_LINKMAP, &map )) map = NULL;
|
||||
release_builtin_module( module );
|
||||
if (!map) return STATUS_SUCCESS;
|
||||
|
||||
for (dyn = map->l_ld; dyn->d_tag; dyn++)
|
||||
{
|
||||
caddr_t relocbase = (caddr_t)map->l_addr;
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
/* On older FreeBSD versions, l_addr was the absolute load address, now it's the relocation offset. */
|
||||
if (offsetof(struct link_map, l_addr) == 0)
|
||||
if (!get_relocbase(map->l_addr, &relocbase))
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
#endif
|
||||
switch (dyn->d_tag)
|
||||
{
|
||||
case 0x60009990: init_array = (void *)(relocbase + dyn->d_un.d_val); break;
|
||||
case 0x60009991: init_arraysz = dyn->d_un.d_val; break;
|
||||
case 0x60009992: init_func = (void *)(relocbase + dyn->d_un.d_val); break;
|
||||
}
|
||||
}
|
||||
|
||||
TRACE( "%p: got init_func %p init_array %p %lu\n", module, init_func, init_array, init_arraysz );
|
||||
|
||||
if (init_func) init_func( main_argc, main_argv, main_envp );
|
||||
|
||||
if (init_array)
|
||||
for (i = 0; i < init_arraysz / sizeof(*init_array); i++)
|
||||
init_array[i]( main_argc, main_argv, main_envp );
|
||||
#endif
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* load_ntdll
|
||||
*/
|
||||
|
@ -2130,7 +2048,6 @@ static ULONG_PTR get_image_address(void)
|
|||
const unixlib_entry_t __wine_unix_call_funcs[] =
|
||||
{
|
||||
load_so_dll,
|
||||
init_builtin_dll,
|
||||
unwind_builtin_dll,
|
||||
system_time_precise,
|
||||
};
|
||||
|
@ -2139,7 +2056,6 @@ const unixlib_entry_t __wine_unix_call_funcs[] =
|
|||
#ifdef _WIN64
|
||||
|
||||
static NTSTATUS wow64_load_so_dll( void *args ) { return STATUS_INVALID_IMAGE_FORMAT; }
|
||||
static NTSTATUS wow64_init_builtin_dll( void *args ) { return STATUS_UNSUCCESSFUL; }
|
||||
static NTSTATUS wow64_unwind_builtin_dll( void *args ) { return STATUS_UNSUCCESSFUL; }
|
||||
|
||||
/***********************************************************************
|
||||
|
@ -2148,7 +2064,6 @@ static NTSTATUS wow64_unwind_builtin_dll( void *args ) { return STATUS_UNSUCCESS
|
|||
const unixlib_entry_t __wine_unix_call_wow64_funcs[] =
|
||||
{
|
||||
wow64_load_so_dll,
|
||||
wow64_init_builtin_dll,
|
||||
wow64_unwind_builtin_dll,
|
||||
system_time_precise,
|
||||
};
|
||||
|
|
|
@ -225,7 +225,6 @@ extern void virtual_set_force_exec( BOOL enable ) DECLSPEC_HIDDEN;
|
|||
extern void virtual_set_large_address_space(void) DECLSPEC_HIDDEN;
|
||||
extern void virtual_fill_image_information( const pe_image_info_t *pe_info,
|
||||
SECTION_IMAGE_INFORMATION *info ) DECLSPEC_HIDDEN;
|
||||
extern void release_builtin_module( void *module ) DECLSPEC_HIDDEN;
|
||||
extern void *get_builtin_so_handle( void *module ) DECLSPEC_HIDDEN;
|
||||
extern NTSTATUS load_builtin_unixlib( void *module, const char *name ) DECLSPEC_HIDDEN;
|
||||
extern NTSTATUS unwind_builtin_dll( void *args ) DECLSPEC_HIDDEN;
|
||||
|
|
|
@ -593,7 +593,7 @@ static void add_builtin_module( void *module, void *handle )
|
|||
/***********************************************************************
|
||||
* release_builtin_module
|
||||
*/
|
||||
void release_builtin_module( void *module )
|
||||
static void release_builtin_module( void *module )
|
||||
{
|
||||
struct builtin_module *builtin;
|
||||
|
||||
|
|
|
@ -41,7 +41,6 @@ struct unwind_builtin_dll_params
|
|||
enum ntdll_unix_funcs
|
||||
{
|
||||
unix_load_so_dll,
|
||||
unix_init_builtin_dll,
|
||||
unix_unwind_builtin_dll,
|
||||
unix_system_time_precise,
|
||||
};
|
||||
|
|
|
@ -9,6 +9,7 @@ C_SRCS = \
|
|||
dll_entry.c \
|
||||
dll_main.c \
|
||||
dll_register.c \
|
||||
dll_soinit.c \
|
||||
exception.c \
|
||||
exe16_entry.c \
|
||||
exe_entry.c \
|
||||
|
|
|
@ -29,7 +29,10 @@
|
|||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
|
||||
extern void __wine_init_so_dll(void) DECLSPEC_HIDDEN;
|
||||
|
||||
BOOL WINAPI DECLSPEC_HIDDEN __wine_spec_dll_entry( HINSTANCE inst, DWORD reason, LPVOID reserved )
|
||||
{
|
||||
if (reason == DLL_PROCESS_ATTACH) __wine_init_so_dll();
|
||||
return DllMain( inst, reason, reserved );
|
||||
}
|
||||
|
|
121
dlls/winecrt0/dll_soinit.c
Normal file
121
dlls/winecrt0/dll_soinit.c
Normal file
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* Initialization code for .so modules
|
||||
*
|
||||
* Copyright (C) 2020 Alexandre Julliard
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#if 0
|
||||
#pragma makedep unix
|
||||
#endif
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <dlfcn.h>
|
||||
#ifdef HAVE_ELF_H
|
||||
# include <elf.h>
|
||||
#endif
|
||||
#ifdef HAVE_LINK_H
|
||||
# include <link.h>
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
/* The PT_LOAD segments are sorted in increasing order, and the first
|
||||
* starts at the beginning of the ELF file. By parsing the file, we can
|
||||
* find that first PT_LOAD segment, from which we can find the base
|
||||
* address it wanted, and knowing mapbase where the binary was actually
|
||||
* loaded, use them to work out the relocbase offset. */
|
||||
static BOOL get_relocbase(caddr_t mapbase, caddr_t *relocbase)
|
||||
{
|
||||
Elf_Half i;
|
||||
#ifdef _WIN64
|
||||
const Elf64_Ehdr *elf_header = (Elf64_Ehdr*) mapbase;
|
||||
#else
|
||||
const Elf32_Ehdr *elf_header = (Elf32_Ehdr*) mapbase;
|
||||
#endif
|
||||
const Elf_Phdr *prog_header = (const Elf_Phdr *)(mapbase + elf_header->e_phoff);
|
||||
|
||||
for (i = 0; i < elf_header->e_phnum; i++)
|
||||
{
|
||||
if (prog_header->p_type == PT_LOAD)
|
||||
{
|
||||
caddr_t desired_base = (caddr_t)((prog_header->p_vaddr / prog_header->p_align) * prog_header->p_align);
|
||||
*relocbase = (caddr_t) (mapbase - desired_base);
|
||||
return TRUE;
|
||||
}
|
||||
prog_header++;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* __wine_init_so_dll
|
||||
*/
|
||||
void __wine_init_so_dll(void)
|
||||
{
|
||||
#if defined(HAVE_DLADDR1) || defined(HAVE_DLINFO)
|
||||
struct link_map *map;
|
||||
void (*init_func)(int, char **, char **) = NULL;
|
||||
void (**init_array)(int, char **, char **) = NULL;
|
||||
long i, init_arraysz = 0;
|
||||
#ifdef _WIN64
|
||||
const Elf64_Dyn *dyn;
|
||||
#else
|
||||
const Elf32_Dyn *dyn;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DLADDR1
|
||||
Dl_info info;
|
||||
if (!dladdr1( __wine_init_so_dll, &info, (void **)&map, RTLD_DL_LINKMAP )) return;
|
||||
#else
|
||||
if (dlinfo( RTLD_SELF, RTLD_DI_LINKMAP, &map )) return;
|
||||
#endif
|
||||
|
||||
for (dyn = map->l_ld; dyn->d_tag; dyn++)
|
||||
{
|
||||
caddr_t relocbase = (caddr_t)map->l_addr;
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
/* On older FreeBSD versions, l_addr was the absolute load address, now it's the relocation offset. */
|
||||
if (offsetof(struct link_map, l_addr) == 0)
|
||||
if (!get_relocbase(map->l_addr, &relocbase))
|
||||
return;
|
||||
#endif
|
||||
switch (dyn->d_tag)
|
||||
{
|
||||
case 0x60009994: init_array = (void *)(relocbase + dyn->d_un.d_val); break;
|
||||
case 0x60009995: init_arraysz = dyn->d_un.d_val; break;
|
||||
case 0x60009996: init_func = (void *)(relocbase + dyn->d_un.d_val); break;
|
||||
}
|
||||
}
|
||||
|
||||
if (init_func) init_func( 0, NULL, NULL );
|
||||
|
||||
if (init_array)
|
||||
for (i = 0; i < init_arraysz / sizeof(*init_array); i++)
|
||||
init_array[i]( 0, NULL, NULL );
|
||||
#endif
|
||||
}
|
|
@ -31,6 +31,7 @@
|
|||
#include "winternl.h"
|
||||
|
||||
extern int main( int argc, char *argv[] );
|
||||
extern void __wine_init_so_dll(void) DECLSPEC_HIDDEN;
|
||||
|
||||
static char **build_argv( const char *src, int *ret_argc )
|
||||
{
|
||||
|
@ -100,5 +101,6 @@ DWORD WINAPI DECLSPEC_HIDDEN __wine_spec_exe_entry( PEB *peb )
|
|||
int argc;
|
||||
char **argv = build_argv( GetCommandLineA(), &argc );
|
||||
|
||||
__wine_init_so_dll();
|
||||
ExitProcess( main( argc, argv ));
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "winternl.h"
|
||||
|
||||
extern int wmain( int argc, WCHAR *argv[] );
|
||||
extern void __wine_init_so_dll(void) DECLSPEC_HIDDEN;
|
||||
|
||||
static WCHAR **build_argv( const WCHAR *src, int *ret_argc )
|
||||
{
|
||||
|
@ -100,5 +101,6 @@ DWORD WINAPI DECLSPEC_HIDDEN __wine_spec_exe_wentry( PEB *peb )
|
|||
int argc;
|
||||
WCHAR **argv = build_argv( GetCommandLineW(), &argc );
|
||||
|
||||
__wine_init_so_dll();
|
||||
ExitProcess( wmain( argc, argv ));
|
||||
}
|
||||
|
|
|
@ -33,6 +33,9 @@
|
|||
/* Define to 1 if you have the <cups/ppd.h> header file. */
|
||||
#undef HAVE_CUPS_PPD_H
|
||||
|
||||
/* Define to 1 if you have the `dladdr1' function. */
|
||||
#undef HAVE_DLADDR1
|
||||
|
||||
/* Define to 1 if you have the `dlinfo' function. */
|
||||
#undef HAVE_DLINFO
|
||||
|
||||
|
|
|
@ -1448,9 +1448,9 @@ static void fixup_elf32( const char *name, int fd, void *header, size_t header_s
|
|||
{
|
||||
switch (dyn[i].d_tag)
|
||||
{
|
||||
case 25: dyn[i].d_tag = 0x60009990; break; /* DT_INIT_ARRAY */
|
||||
case 27: dyn[i].d_tag = 0x60009991; break; /* DT_INIT_ARRAYSZ */
|
||||
case 12: dyn[i].d_tag = 0x60009992; break; /* DT_INIT */
|
||||
case 25: dyn[i].d_tag = 0x60009994; break; /* DT_INIT_ARRAY */
|
||||
case 27: dyn[i].d_tag = 0x60009995; break; /* DT_INIT_ARRAYSZ */
|
||||
case 12: dyn[i].d_tag = 0x60009996; break; /* DT_INIT */
|
||||
}
|
||||
}
|
||||
lseek( fd, phdr->p_offset, SEEK_SET );
|
||||
|
|
Loading…
Add table
Reference in a new issue