When getauxval isn't available we can read the auxillary vector after environment pointers according to System V ABI.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com ---
I'm not sure if this is very useful, but some runtimes (steamrt for instance) have old glibc where getauxval isn't available and it then causes SymInitializeW to fail because of NULL process image addresses.
dlls/ntdll/unix/loader.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+)
diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c index bd3a0958757..02ffc0ca775 100644 --- a/dlls/ntdll/unix/loader.c +++ b/dlls/ntdll/unix/loader.c @@ -1343,6 +1343,27 @@ ULONG_PTR get_image_address(void)
if (task_info(mach_task_self(), TASK_DYLD_INFO, (task_info_t)&dyld_info, &size) == KERN_SUCCESS) return dyld_info.all_image_info_addr; +#elif defined(__linux__) + ULONG_PTR size, num, phdr_addr; + ElfW(Phdr) *phdr; + Elf64_auxv_t *auxp; + char **envp = main_envp; + while (*envp++ != NULL); + + for (auxp = (Elf64_auxv_t *)envp; auxp->a_type != 0; auxp++) + { + if (auxp->a_type == AT_PHDR) phdr_addr = auxp->a_un.a_val; + if (auxp->a_type == AT_PHENT) size = auxp->a_un.a_val; + if (auxp->a_type == AT_PHNUM) num = auxp->a_un.a_val; + } + + if (!phdr_addr) return 0; + phdr = (ElfW(Phdr) *)phdr_addr; + while (num--) + { + if (phdr->p_type == PT_PHDR) return phdr_addr - phdr->p_offset; + phdr = (ElfW(Phdr) *)((char *)phdr + size); + } #endif return 0; }