Commit bef09697 authored by Alexandre Julliard's avatar Alexandre Julliard

ntdll: Move the .so module initialization to winecrt0.

Use new ELF tag ids to avoid breaking backwards compatibility.
parent c20741b3
......@@ -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 );
}
/*
* 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 );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment