Jeremy White wrote:
>
> Gav sparked me to go look and see how I could pull argc/argv
> out during the constructor phase of library load,
> and I believe I have found a method that should work,
> at least for elf/glibc implementations.
I'm glad I sparked some investigation, but on further reflection and
looking at code, I'm not sure that this is actually possible.
> The good news is that _init is passed argc, argv, and environp.
The glibc source code certainly seems to assume that this is the
case, but I've been looking at the ld-linux sources, and I don't
see the mechanism it uses to do this:
The code in question (in d-link/boot1.c) looks like this:
for(tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next)
{
/* Apparently crt1 for the application is responsible for handling this.
* We only need to run the init/fini for shared libraries
*/
if (tpnt->libtype == program_interpreter ||
tpnt->libtype == elf_executable) continue;
if (tpnt->init_flag & INIT_FUNCS_CALLED) continue;
tpnt->init_flag |= INIT_FUNCS_CALLED;
if(tpnt->dynamic_info[DT_INIT]) {
_dl_elf_init = (int (*)(void)) (tpnt->loadaddr +
tpnt->dynamic_info[DT_INIT]);
(*_dl_elf_init)();
}
.
.
.
It doesn't appear to be able to pass argc and argv until it actually
loads the executable start code:
/* OK we are done here. Turn out the lights, and lock up. */
_dl_elf_main = (int (*)(int, char**, char**)) dl_data[AT_ENTRY];
/*
* Transfer control to the application.
*/
START();
Where START() is a macro that cleans up the the local stack for
the boot function, leaving the stack with the arguments passed
from the kernel.
To further confound things though, when I actually tried making
a simple shared lib with an _init function, it *did* get argc
and argv, but as you suggested, libc then went wonky because
it didn't get initialized properly - note the line above that reads:
tpnt->init_flag |= INIT_FUNCS_CALLED;
This is what's causing it to stop once it's run one _init function.
I also just tried getting the address for the libc _init function
from dlsym and calling through to that from the test library,
but that didn't seem to work, though I did see it travel down
into the bowels of glibc initialization.
> The one thing I can't clearly assess is whether this method
> is portable to all of the platforms we care about.
The _init thing is I believe fairly gcc/ELF centric. It works
because the linker twigs that it needs to put a DT_INIT tag into
the ELF headers, pointed to that function.
> One advantage to Alexandre's method (let Wine run, do
> a LoadLibrary(), GetProcAddress("WinMain"), start the app),
> is that it is more portable.
I suppose - but it feels wrong to build a winelib app foo, and
end up with a 'foo' and a 'foo.so', where there's no real code in
'foo'.
-Gav
--
Gavriel State
CEO
TransGaming Technologies Inc.
[EMAIL PROTECTED]