winebuild: Add --fixup-ctors option to allow intercepting constructors in .so files.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
3935acd4da
commit
6c4046fef1
|
@ -321,6 +321,7 @@ extern void output_fake_module16( DLLSPEC *spec16 );
|
|||
extern void output_res_o_file( DLLSPEC *spec );
|
||||
extern void output_asm_relays16(void);
|
||||
extern void make_builtin_files( char *argv[] );
|
||||
extern void fixup_constructors( char *argv[] );
|
||||
|
||||
extern void add_16bit_exports( DLLSPEC *spec32, DLLSPEC *spec16 );
|
||||
extern int parse_spec_file( FILE *file, DLLSPEC *spec );
|
||||
|
|
|
@ -115,6 +115,7 @@ enum exec_mode_values
|
|||
MODE_IMPLIB,
|
||||
MODE_STATICLIB,
|
||||
MODE_BUILTIN,
|
||||
MODE_FIXUP_CTORS,
|
||||
MODE_RESOURCES
|
||||
};
|
||||
|
||||
|
@ -301,8 +302,9 @@ static const char usage_str[] =
|
|||
" --exe Build an executable from object files\n"
|
||||
" --implib Build an import library\n"
|
||||
" --staticlib Build a static library\n"
|
||||
" --builtin Mark a library as a Wine builtin\n"
|
||||
" --resources Build a .o or .res file for the resource files\n\n"
|
||||
" --builtin Mark a library as a Wine builtin\n"
|
||||
" --fixup-ctors Fixup the constructors data after the module has been built\n"
|
||||
"The mode options are mutually exclusive; you must specify one and only one.\n\n";
|
||||
|
||||
enum long_options_values
|
||||
|
@ -316,6 +318,7 @@ enum long_options_values
|
|||
LONG_OPT_CCCMD,
|
||||
LONG_OPT_EXTERNAL_SYMS,
|
||||
LONG_OPT_FAKE_MODULE,
|
||||
LONG_OPT_FIXUP_CTORS,
|
||||
LONG_OPT_LARGE_ADDRESS_AWARE,
|
||||
LONG_OPT_LDCMD,
|
||||
LONG_OPT_NMCMD,
|
||||
|
@ -341,6 +344,7 @@ static const struct option long_options[] =
|
|||
{ "cc-cmd", 1, 0, LONG_OPT_CCCMD },
|
||||
{ "external-symbols", 0, 0, LONG_OPT_EXTERNAL_SYMS },
|
||||
{ "fake-module", 0, 0, LONG_OPT_FAKE_MODULE },
|
||||
{ "fixup-ctors", 0, 0, LONG_OPT_FIXUP_CTORS },
|
||||
{ "large-address-aware", 0, 0, LONG_OPT_LARGE_ADDRESS_AWARE },
|
||||
{ "ld-cmd", 1, 0, LONG_OPT_LDCMD },
|
||||
{ "nm-cmd", 1, 0, LONG_OPT_NMCMD },
|
||||
|
@ -511,6 +515,9 @@ static char **parse_options( int argc, char **argv, DLLSPEC *spec )
|
|||
case LONG_OPT_BUILTIN:
|
||||
set_exec_mode( MODE_BUILTIN );
|
||||
break;
|
||||
case LONG_OPT_FIXUP_CTORS:
|
||||
set_exec_mode( MODE_FIXUP_CTORS );
|
||||
break;
|
||||
case LONG_OPT_ASCMD:
|
||||
as_command = strarray_fromstring( optarg, " " );
|
||||
break;
|
||||
|
@ -701,6 +708,10 @@ int main(int argc, char **argv)
|
|||
if (!argv[0]) fatal_error( "missing file argument for --builtin option\n" );
|
||||
make_builtin_files( argv );
|
||||
break;
|
||||
case MODE_FIXUP_CTORS:
|
||||
if (!argv[0]) fatal_error( "missing file argument for --fixup-ctors option\n" );
|
||||
fixup_constructors( argv );
|
||||
break;
|
||||
case MODE_RESOURCES:
|
||||
load_resources( argv, spec );
|
||||
output_res_o_file( spec );
|
||||
|
|
|
@ -1095,3 +1095,162 @@ void make_builtin_files( char *argv[] )
|
|||
close( fd );
|
||||
}
|
||||
}
|
||||
|
||||
static void fixup_elf32( const char *name, int fd, void *header, size_t header_size )
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned char e_ident[16];
|
||||
unsigned short e_type;
|
||||
unsigned short e_machine;
|
||||
unsigned int e_version;
|
||||
unsigned int e_entry;
|
||||
unsigned int e_phoff;
|
||||
unsigned int e_shoff;
|
||||
unsigned int e_flags;
|
||||
unsigned short e_ehsize;
|
||||
unsigned short e_phentsize;
|
||||
unsigned short e_phnum;
|
||||
unsigned short e_shentsize;
|
||||
unsigned short e_shnum;
|
||||
unsigned short e_shstrndx;
|
||||
} *elf = header;
|
||||
struct
|
||||
{
|
||||
unsigned int p_type;
|
||||
unsigned int p_offset;
|
||||
unsigned int p_vaddr;
|
||||
unsigned int p_paddr;
|
||||
unsigned int p_filesz;
|
||||
unsigned int p_memsz;
|
||||
unsigned int p_flags;
|
||||
unsigned int p_align;
|
||||
} *phdr;
|
||||
struct
|
||||
{
|
||||
unsigned int d_tag;
|
||||
unsigned int d_val;
|
||||
} *dyn;
|
||||
|
||||
unsigned int i, size;
|
||||
|
||||
if (header_size < sizeof(*elf)) return;
|
||||
if (elf->e_ident[6] != 1 /* EV_CURRENT */) return;
|
||||
|
||||
size = elf->e_phnum * elf->e_phentsize;
|
||||
phdr = xmalloc( size );
|
||||
lseek( fd, elf->e_phoff, SEEK_SET );
|
||||
if (read( fd, phdr, size ) != size) return;
|
||||
|
||||
for (i = 0; i < elf->e_phnum; i++)
|
||||
{
|
||||
if (phdr->p_type == 2 /* PT_DYNAMIC */ ) break;
|
||||
phdr = (void *)((char *)phdr + elf->e_phentsize);
|
||||
}
|
||||
if (i == elf->e_phnum) return;
|
||||
|
||||
dyn = xmalloc( phdr->p_filesz );
|
||||
lseek( fd, phdr->p_offset, SEEK_SET );
|
||||
if (read( fd, dyn, phdr->p_filesz ) != phdr->p_filesz) return;
|
||||
for (i = 0; i < phdr->p_filesz / sizeof(*dyn) && dyn[i].d_tag; i++)
|
||||
{
|
||||
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 */
|
||||
}
|
||||
}
|
||||
lseek( fd, phdr->p_offset, SEEK_SET );
|
||||
write( fd, dyn, phdr->p_filesz );
|
||||
}
|
||||
|
||||
static void fixup_elf64( const char *name, int fd, void *header, size_t header_size )
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned char e_ident[16];
|
||||
unsigned short e_type;
|
||||
unsigned short e_machine;
|
||||
unsigned int e_version;
|
||||
unsigned __int64 e_entry;
|
||||
unsigned __int64 e_phoff;
|
||||
unsigned __int64 e_shoff;
|
||||
unsigned int e_flags;
|
||||
unsigned short e_ehsize;
|
||||
unsigned short e_phentsize;
|
||||
unsigned short e_phnum;
|
||||
unsigned short e_shentsize;
|
||||
unsigned short e_shnum;
|
||||
unsigned short e_shstrndx;
|
||||
} *elf = header;
|
||||
struct
|
||||
{
|
||||
unsigned int p_type;
|
||||
unsigned int p_flags;
|
||||
unsigned __int64 p_offset;
|
||||
unsigned __int64 p_vaddr;
|
||||
unsigned __int64 p_paddr;
|
||||
unsigned __int64 p_filesz;
|
||||
unsigned __int64 p_memsz;
|
||||
unsigned __int64 p_align;
|
||||
} *phdr;
|
||||
struct
|
||||
{
|
||||
unsigned __int64 d_tag;
|
||||
unsigned __int64 d_val;
|
||||
} *dyn;
|
||||
|
||||
unsigned int i, size;
|
||||
|
||||
if (header_size < sizeof(*elf)) return;
|
||||
if (elf->e_ident[6] != 1 /* EV_CURRENT */) return;
|
||||
|
||||
size = elf->e_phnum * elf->e_phentsize;
|
||||
phdr = xmalloc( size );
|
||||
lseek( fd, elf->e_phoff, SEEK_SET );
|
||||
if (read( fd, phdr, size ) != size) return;
|
||||
|
||||
for (i = 0; i < elf->e_phnum; i++)
|
||||
{
|
||||
if (phdr->p_type == 2 /* PT_DYNAMIC */ ) break;
|
||||
phdr = (void *)((char *)phdr + elf->e_phentsize);
|
||||
}
|
||||
if (i == elf->e_phnum) return;
|
||||
|
||||
dyn = xmalloc( phdr->p_filesz );
|
||||
lseek( fd, phdr->p_offset, SEEK_SET );
|
||||
if (read( fd, dyn, phdr->p_filesz ) != phdr->p_filesz) return;
|
||||
for (i = 0; i < phdr->p_filesz / sizeof(*dyn) && dyn[i].d_tag; i++)
|
||||
{
|
||||
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 */
|
||||
}
|
||||
}
|
||||
lseek( fd, phdr->p_offset, SEEK_SET );
|
||||
write( fd, dyn, phdr->p_filesz );
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
* fixup_constructors
|
||||
*/
|
||||
void fixup_constructors( char *argv[] )
|
||||
{
|
||||
int i, fd, size;
|
||||
unsigned int header[64];
|
||||
|
||||
for (i = 0; argv[i]; i++)
|
||||
{
|
||||
if ((fd = open( argv[i], O_RDWR | O_BINARY )) == -1) fatal_perror( "Cannot open %s", argv[i] );
|
||||
size = read( fd, &header, sizeof(header) );
|
||||
if (size > 5)
|
||||
{
|
||||
if (!memcmp( header, "\177ELF\001", 5 )) fixup_elf32( argv[i], fd, header, size );
|
||||
else if (!memcmp( header, "\177ELF\002", 5 )) fixup_elf64( argv[i], fd, header, size );
|
||||
}
|
||||
close( fd );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,16 +54,22 @@ in .delay.a, a delayed import library is built.
|
|||
.BI \--staticlib
|
||||
Build a .a static library from object files.
|
||||
.TP
|
||||
.BI \--builtin
|
||||
Mark a PE module as a Wine builtin module, by adding the "Wine builtin
|
||||
DLL" signature string after the DOS header.
|
||||
.TP
|
||||
.B \--resources
|
||||
Generate a .o file containing all the input resources. This is useful
|
||||
when building with a PE compiler, since the PE binutils cannot handle
|
||||
multiple resource files as input. For a standard Unix build, the
|
||||
resource files are automatically included when building the spec file,
|
||||
so there's no need for an intermediate .o file.
|
||||
.TP
|
||||
.BI \--builtin
|
||||
Mark a PE module as a Wine builtin module, by adding the "Wine builtin
|
||||
DLL" signature string after the DOS header.
|
||||
.TP
|
||||
.BI \--fixup-ctors
|
||||
Fixup constructors after a module has been built. This should be done
|
||||
on the final .so module if its code contains constructors, to ensure
|
||||
that Wine has a chance to initialize the module before the
|
||||
constructors are executed.
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
.BI \--as-cmd= as-command
|
||||
|
|
Loading…
Reference in New Issue