Commit 6c4046fe authored by Alexandre Julliard's avatar Alexandre Julliard

winebuild: Add --fixup-ctors option to allow intercepting constructors in .so files.

parent 3935acd4
...@@ -321,6 +321,7 @@ extern void output_fake_module16( DLLSPEC *spec16 ); ...@@ -321,6 +321,7 @@ extern void output_fake_module16( DLLSPEC *spec16 );
extern void output_res_o_file( DLLSPEC *spec ); extern void output_res_o_file( DLLSPEC *spec );
extern void output_asm_relays16(void); extern void output_asm_relays16(void);
extern void make_builtin_files( char *argv[] ); extern void make_builtin_files( char *argv[] );
extern void fixup_constructors( char *argv[] );
extern void add_16bit_exports( DLLSPEC *spec32, DLLSPEC *spec16 ); extern void add_16bit_exports( DLLSPEC *spec32, DLLSPEC *spec16 );
extern int parse_spec_file( FILE *file, DLLSPEC *spec ); extern int parse_spec_file( FILE *file, DLLSPEC *spec );
......
...@@ -115,6 +115,7 @@ enum exec_mode_values ...@@ -115,6 +115,7 @@ enum exec_mode_values
MODE_IMPLIB, MODE_IMPLIB,
MODE_STATICLIB, MODE_STATICLIB,
MODE_BUILTIN, MODE_BUILTIN,
MODE_FIXUP_CTORS,
MODE_RESOURCES MODE_RESOURCES
}; };
...@@ -301,8 +302,9 @@ static const char usage_str[] = ...@@ -301,8 +302,9 @@ static const char usage_str[] =
" --exe Build an executable from object files\n" " --exe Build an executable from object files\n"
" --implib Build an import library\n" " --implib Build an import library\n"
" --staticlib Build a static 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" " --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"; "The mode options are mutually exclusive; you must specify one and only one.\n\n";
enum long_options_values enum long_options_values
...@@ -316,6 +318,7 @@ enum long_options_values ...@@ -316,6 +318,7 @@ enum long_options_values
LONG_OPT_CCCMD, LONG_OPT_CCCMD,
LONG_OPT_EXTERNAL_SYMS, LONG_OPT_EXTERNAL_SYMS,
LONG_OPT_FAKE_MODULE, LONG_OPT_FAKE_MODULE,
LONG_OPT_FIXUP_CTORS,
LONG_OPT_LARGE_ADDRESS_AWARE, LONG_OPT_LARGE_ADDRESS_AWARE,
LONG_OPT_LDCMD, LONG_OPT_LDCMD,
LONG_OPT_NMCMD, LONG_OPT_NMCMD,
...@@ -341,6 +344,7 @@ static const struct option long_options[] = ...@@ -341,6 +344,7 @@ static const struct option long_options[] =
{ "cc-cmd", 1, 0, LONG_OPT_CCCMD }, { "cc-cmd", 1, 0, LONG_OPT_CCCMD },
{ "external-symbols", 0, 0, LONG_OPT_EXTERNAL_SYMS }, { "external-symbols", 0, 0, LONG_OPT_EXTERNAL_SYMS },
{ "fake-module", 0, 0, LONG_OPT_FAKE_MODULE }, { "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 }, { "large-address-aware", 0, 0, LONG_OPT_LARGE_ADDRESS_AWARE },
{ "ld-cmd", 1, 0, LONG_OPT_LDCMD }, { "ld-cmd", 1, 0, LONG_OPT_LDCMD },
{ "nm-cmd", 1, 0, LONG_OPT_NMCMD }, { "nm-cmd", 1, 0, LONG_OPT_NMCMD },
...@@ -511,6 +515,9 @@ static char **parse_options( int argc, char **argv, DLLSPEC *spec ) ...@@ -511,6 +515,9 @@ static char **parse_options( int argc, char **argv, DLLSPEC *spec )
case LONG_OPT_BUILTIN: case LONG_OPT_BUILTIN:
set_exec_mode( MODE_BUILTIN ); set_exec_mode( MODE_BUILTIN );
break; break;
case LONG_OPT_FIXUP_CTORS:
set_exec_mode( MODE_FIXUP_CTORS );
break;
case LONG_OPT_ASCMD: case LONG_OPT_ASCMD:
as_command = strarray_fromstring( optarg, " " ); as_command = strarray_fromstring( optarg, " " );
break; break;
...@@ -701,6 +708,10 @@ int main(int argc, char **argv) ...@@ -701,6 +708,10 @@ int main(int argc, char **argv)
if (!argv[0]) fatal_error( "missing file argument for --builtin option\n" ); if (!argv[0]) fatal_error( "missing file argument for --builtin option\n" );
make_builtin_files( argv ); make_builtin_files( argv );
break; 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: case MODE_RESOURCES:
load_resources( argv, spec ); load_resources( argv, spec );
output_res_o_file( spec ); output_res_o_file( spec );
......
...@@ -1095,3 +1095,162 @@ void make_builtin_files( char *argv[] ) ...@@ -1095,3 +1095,162 @@ void make_builtin_files( char *argv[] )
close( fd ); 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. ...@@ -54,16 +54,22 @@ in .delay.a, a delayed import library is built.
.BI \--staticlib .BI \--staticlib
Build a .a static library from object files. Build a .a static library from object files.
.TP .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 .B \--resources
Generate a .o file containing all the input resources. This is useful Generate a .o file containing all the input resources. This is useful
when building with a PE compiler, since the PE binutils cannot handle when building with a PE compiler, since the PE binutils cannot handle
multiple resource files as input. For a standard Unix build, the multiple resource files as input. For a standard Unix build, the
resource files are automatically included when building the spec file, resource files are automatically included when building the spec file,
so there's no need for an intermediate .o 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 .SH OPTIONS
.TP .TP
.BI \--as-cmd= as-command .BI \--as-cmd= as-command
......
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