该坚持的时候坚持,该妥协的时候妥协,该放弃的时候放弃
分类: C/C++
2014-09-09 22:23:49
wld_start
/*
* wld_start
*
* Repeat the actions the kernel would do when loading a dynamically linked .so
* Load the binary and then its ELF interpreter.
* Note, we assume that the binary is a dynamically linked ELF shared object.
*/
void* wld_start( void **stack )
{
long i, *pargc;
char **argv, **p;
char *interp, *reserve = NULL;
struct wld_auxv new_av[12], delete_av[3], *av;
struct wld_link_map main_binary_map, ld_so_map;
struct wine_preload_info **wine_main_preload_info;
pargc = *stack; = (long int *) 0xbffff320
argv = (char **)pargc + 1; = (char **) 0xbffff324
if (*pargc < 2) fatal_error( "Usage: %s wine_binary [args]\n", argv[0] ); ×pargc =3
/* skip over the parameters */
p = argv + *pargc + 1; = (char **) 0xbffff334
遍历了系统的环境,看有没有匹配的
/* skip over the environment */
while (*p)
{
static const char res[] = "WINEPRELOADRESERVE=";
if (!wld_strncmp( *p, res, sizeof(res)-1 )) reserve = *p + sizeof(res) - 1;
p++;
}
一直到*p为0,p+1是第二个p结构,av是在p后面的struct wld_auxv *
av = (struct wld_auxv *)(p+1); = (struct wld_auxv *) 0xbffff3e8
page_size = get_auxiliary( av, AT_PAGESZ, 4096 ); = 4096
page_mask = page_size - 1; = 4095
设置起始和结束地址
preloader_start = (char *)_start - ((unsigned long)_start & page_mask);
preloader_end = (char *)((unsigned long)(_end + page_mask) & ~page_mask);
没用到
#ifdef DUMP_AUX_INFO
wld_printf( "stack = %p\n", *stack );
for( i = 0; i < *pargc; i++ ) wld_printf("argv[%lx] = %s\n", i, argv[i]);
dump_auxiliary( av );
#endif
第一次= {{addr = 0x0, size = 65536}, {addr = 0x10000, size = 1048576}, {
addr = 0x110000, size = 1743716352}, {addr = 0x7f000000, size = 50331648},
{addr = 0x0, size = 0}, {addr = 0x0, size = 0}}
保留wine的存储需要,把一些空间移去。然后保留了原来的空间
/* reserve memory that Wine needs */
if (reserve) preload_reserve( reserve ); =0
for (i = 0; preload_info[i].size; i++)
{
if ((char *)av >= (char *)preload_info[i].addr &&
(char *)pargc <= (char *)preload_info[i].addr + preload_info[i].size)
{
remove_preload_range( i );
i--;
}
else if (wld_mmap( preload_info[i].addr, preload_info[i].size, PROT_NONE,
MAP_FIXED | MAP_PRIVATE | MAP_ANON | MAP_NORESERVE, -1, 0 ) == (void *)-1)
{
这里addr第一次为0
/* don't warn for low 64k */
if (preload_info[i].addr >= (void *)0x10000)
wld_printf( "preloader: Warning: failed to reserve range %p-%p\n",
preload_info[i].addr, (char *)preload_info[i].addr + preload_info[i].size );
把preload_info的内容整体往移了
remove_preload_range( i );
i--;
}
}
/* add an executable page at the top of the address space to defeat
* broken no-exec protections that play with the code selector limit */
if (is_addr_reserved( (char *)0x80000000 - page_size ))
wld_mprotect( (char *)0x80000000 - page_size, page_size, PROT_EXEC | PROT_READ );
/* load the main binary */
map_so_lib( argv[1], &main_binary_map );
/* load the ELF interpreter */
interp = (char *)main_binary_map.l_addr + main_binary_map.l_interp;
map_so_lib( interp, &ld_so_map );
/* store pointer to the preload info into the appropriate main binary variable */
wine_main_preload_info = find_symbol( main_binary_map.l_phdr, main_binary_map.l_phnum,
"wine_main_preload_info", STT_OBJECT );
if (wine_main_preload_info) *wine_main_preload_info = preload_info;
else wld_printf( "wine_main_preload_info 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)) );
SET_NEW_AV( 2, AT_PHNUM, main_binary_map.l_phnum );
SET_NEW_AV( 3, AT_PAGESZ, page_size );
SET_NEW_AV( 4, AT_BASE, ld_so_map.l_addr );
SET_NEW_AV( 5, AT_FLAGS, get_auxiliary( av, AT_FLAGS, 0 ) );
SET_NEW_AV( 6, AT_ENTRY, main_binary_map.l_entry );
SET_NEW_AV( 7, AT_UID, get_auxiliary( av, AT_UID, wld_getuid() ) );
SET_NEW_AV( 8, AT_EUID, get_auxiliary( av, AT_EUID, wld_geteuid() ) );
SET_NEW_AV( 9, AT_GID, get_auxiliary( av, AT_GID, wld_getgid() ) );
SET_NEW_AV(10, AT_EGID, get_auxiliary( av, AT_EGID, wld_getegid() ) );
SET_NEW_AV(11, AT_NULL, 0 );
#undef SET_NEW_AV
i = 0;
/* delete sysinfo values if addresses conflict */
if (is_in_preload_range( av, AT_SYSINFO ) || is_in_preload_range( av, AT_SYSINFO_EHDR ))
{
delete_av[i++].a_type = AT_SYSINFO;
delete_av[i++].a_type = AT_SYSINFO_EHDR;
}
delete_av[i].a_type = AT_NULL;
/* get rid of first argument */
set_process_name( *pargc, argv );
pargc[1] = pargc[0] - 1;
*stack = pargc + 1;
set_auxiliary_values( av, new_av, delete_av, stack );
#ifdef DUMP_AUX_INFO
wld_printf("new stack = %p\n", *stack);
wld_printf("jumping to %p\n", (void *)ld_so_map.l_entry);
#endif
返回ld-linux.so.2的程序入口地址
return (void *)ld_so_map.l_entry;
}