From: Rémi Bernon rbernon@codeweavers.com
--- loader/main.c | 18 ++++++++++++++++++ loader/preloader.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+)
diff --git a/loader/main.c b/loader/main.c index cd741ab945d..1652f740fd0 100644 --- a/loader/main.c +++ b/loader/main.c @@ -55,7 +55,15 @@ extern char **environ;
/* the preloader will set these variables */ typedef void (*rtld_init_func)( struct link_map *map ); +typedef void (*rtld_map_start_func)(void); +typedef void (*rtld_map_complete_func)(void); +typedef void (*rtld_unmap_start_func)(void); +typedef void (*rtld_unmap_complete_func)(void); __attribute((visibility("default"))) rtld_init_func wine_rtld_init = NULL; +__attribute((visibility("default"))) rtld_map_start_func wine_rtld_map_start = NULL; +__attribute((visibility("default"))) rtld_map_complete_func wine_rtld_map_complete = NULL; +__attribute((visibility("default"))) rtld_unmap_start_func wine_rtld_unmap_start = NULL; +__attribute((visibility("default"))) rtld_unmap_complete_func wine_rtld_unmap_complete = NULL; const __attribute((visibility("default"))) struct wine_preload_info *wine_main_preload_info = NULL;
#ifdef __linux__ @@ -172,6 +180,9 @@ __attribute((visibility("default"))) void wine_gdb_dll_loaded( const void *modul else entry->map.l_addr = offset;
+ if (wine_rtld_map_start) wine_rtld_map_start(); + if (wine_rtld_map_complete) wine_rtld_map_complete(); + pthread_mutex_unlock( &link_map_lock ); }
@@ -195,6 +206,9 @@ __attribute((visibility("default"))) void wine_gdb_dll_unload( const void *modul if ((prev = entry->map.l_prev)) prev->l_next = entry->map.l_next; if ((next = entry->map.l_next)) next->l_prev = entry->map.l_prev;
+ if (wine_rtld_unmap_start) wine_rtld_unmap_start(); + if (wine_rtld_unmap_complete) wine_rtld_unmap_complete(); + pthread_mutex_unlock( &link_map_lock );
free( entry->map.l_name ); @@ -211,7 +225,9 @@ __attribute((visibility("default"))) void *dlopen( const char *file, int mode ) if (!rtld_dlopen) rtld_dlopen = dlsym( RTLD_NEXT, "dlopen" ); ret = rtld_dlopen( file, mode );
+ if (wine_rtld_map_start) wine_rtld_map_start(); sync_wine_link_map(); + if (wine_rtld_map_complete) wine_rtld_map_complete();
pthread_mutex_unlock( &link_map_lock );
@@ -228,7 +244,9 @@ __attribute((visibility("default"))) int dlclose( void *handle ) if (!rtld_dlclose) rtld_dlclose = dlsym( RTLD_NEXT, "dlclose" ); ret = rtld_dlclose( handle );
+ if (wine_rtld_unmap_start) wine_rtld_unmap_start(); sync_wine_link_map(); + if (wine_rtld_unmap_complete) wine_rtld_unmap_complete();
pthread_mutex_unlock( &link_map_lock );
diff --git a/loader/preloader.c b/loader/preloader.c index 8201b12c7d9..e8b9dec5ade 100644 --- a/loader/preloader.c +++ b/loader/preloader.c @@ -85,6 +85,12 @@ #ifdef HAVE_SYS_LINK_H # include <sys/link.h> #endif +#ifdef HAVE_SYS_SDT_H +# include <sys/sdt.h> +#else +# define STAP_PROBE2(a,b,c,d) +# define STAP_PROBE3(a,b,c,d,e) +#endif
#include "wine/asm.h" #include "main.h" @@ -1415,7 +1421,33 @@ static void init_r_debug( struct wld_auxv *av )
static void rtld_init( struct link_map *map ) { + STAP_PROBE2( rtld, init_start, LM_ID_BASE, &_r_debug ); _r_debug.r_map = map; + STAP_PROBE2( rtld, init_complete, LM_ID_BASE, &_r_debug ); + _dl_debug_state(); +} + +static void rtld_map_start(void) +{ + STAP_PROBE2( rtld, map_start, LM_ID_BASE, &_r_debug ); +} + +static void rtld_map_complete(void) +{ + STAP_PROBE3( rtld, map_complete, LM_ID_BASE, &_r_debug, NULL ); + STAP_PROBE2( rtld, reloc_start, LM_ID_BASE, &_r_debug ); + STAP_PROBE3( rtld, reloc_complete, LM_ID_BASE, &_r_debug, NULL ); + _dl_debug_state(); +} + +static void rtld_unmap_start(void) +{ + STAP_PROBE2( rtld, unmap_start, LM_ID_BASE, &_r_debug ); +} + +static void rtld_unmap_complete(void) +{ + STAP_PROBE2( rtld, unmap_complete, LM_ID_BASE, &_r_debug ); _dl_debug_state(); }
@@ -1513,6 +1545,20 @@ void* wld_start( void **stack ) if (rtld_probe) *rtld_probe = rtld_init; else wld_printf( "wine_rtld_init not found\n" );
+ rtld_probe = find_symbol( &main_binary_map, "wine_rtld_map_start", STT_OBJECT ); + if (rtld_probe) *rtld_probe = rtld_map_start; + else wld_printf( "wine_rtld_map_start not found\n" ); + rtld_probe = find_symbol( &main_binary_map, "wine_rtld_map_complete", STT_OBJECT ); + if (rtld_probe) *rtld_probe = rtld_map_complete; + else wld_printf( "wine_rtld_map_complete not found\n" ); + + rtld_probe = find_symbol( &main_binary_map, "wine_rtld_unmap_start", STT_OBJECT ); + if (rtld_probe) *rtld_probe = rtld_unmap_start; + else wld_printf( "wine_rtld_unmap_start not found\n" ); + rtld_probe = find_symbol( &main_binary_map, "wine_rtld_unmap_complete", STT_OBJECT ); + if (rtld_probe) *rtld_probe = rtld_unmap_complete; + else wld_printf( "wine_rtld_unmap_complete not found\n" ); + #define SET_NEW_AV(n,type,val) new_av[n].a_type = (type); new_av[n].a_un.a_val = (val); SET_NEW_AV( 0, AT_PHDR, (unsigned long)main_binary_map.l_phdr ); SET_NEW_AV( 1, AT_PHENT, sizeof(ElfW(Phdr)) );