Make some fixes to libc and linker to allow environ to be set before initializers run

This commit is contained in:
K. Lange 2018-05-08 17:03:04 +09:00
parent 4818a8cc43
commit b42bec5b70
2 changed files with 27 additions and 9 deletions

View File

@ -52,9 +52,14 @@ DEFN_SYSCALL3(chown, SYS_CHOWN, char *, int, int);
extern void _init();
extern void _fini();
char ** environ;
char ** environ = NULL;
int _environ_size = 0;
char * _argv_0 = NULL;
char ** __argv = NULL;
extern char ** __get_argv(void) {
return __argv;
}
extern void __stdio_init_buffers(void);
@ -65,13 +70,14 @@ void _exit(int val){
__builtin_unreachable();
}
char * _argv_0 = NULL;
__attribute__((constructor))
static void _libc_init(void) {
__stdio_init_buffers();
void pre_main(int (*main)(int,char**), int argc, char * argv[]) {
unsigned int x = 0;
unsigned int nulls = 0;
for (x = 0; 1; ++x) {
if (!argv[x]) {
if (!__get_argv()[x]) {
++nulls;
if (nulls == 2) {
break;
@ -79,12 +85,18 @@ void pre_main(int (*main)(int,char**), int argc, char * argv[]) {
continue;
}
if (nulls == 1) {
environ = &argv[x];
environ = &__get_argv()[x];
break;
}
}
_argv_0 = argv[0];
__stdio_init_buffers();
_argv_0 = __get_argv()[0];
}
void pre_main(int (*main)(int,char**), int argc, char * argv[]) {
if (!__get_argv()) {
__argv = argv;
_libc_init();
}
_init();
_exit(main(argc, argv));
}

View File

@ -368,8 +368,6 @@ static int object_relocate(elf_t * object) {
uintptr_t x = sym->st_value + object->base;
if (need_symbol_for_type(type) || (type == 5)) {
symname = (char *)((uintptr_t)object->dyn_string_table + sym->st_name);
}
if (((sym->st_shndx == 0) && need_symbol_for_type(type)) || (type == 5)) {
if (symname && hashmap_has(dumb_symbol_table, symname)) {
x = (uintptr_t)hashmap_get(dumb_symbol_table, symname);
} else {
@ -554,6 +552,11 @@ static char * dlerror_ld(void) {
return this_error;
}
static void * _argv_value = NULL;
static char * argv_value(void) {
return _argv_value;
}
typedef struct {
char * name;
void * symbol;
@ -563,6 +566,7 @@ ld_exports_t ld_builtin_exports[] = {
{"dlsym", object_find_symbol},
{"dlclose", dlclose_ld},
{"dlerror", dlerror_ld},
{"__get_argv", argv_value},
{NULL, NULL},
};
@ -577,6 +581,8 @@ int main(int argc, char * argv[]) {
file = argv[2];
}
_argv_value = argv+arg_offset;
char * trace_ld_env = getenv("LD_DEBUG");
if ((trace_ld_env && (!strcmp(trace_ld_env,"1") || !strcmp(trace_ld_env,"yes")))) {
__trace_ld = 1;