Puntatore della funzione
Non ho trovato modo di usare Env nella fase iniziale legalmente. La funzione Resolver funziona in Linker anche prima, rispetto alle funzioni preinit_array. L'unico modo legale per risolverlo è utilizzare il puntatore della funzione e decidere quale funzione utilizzare in funzione della sezione .preinit_array:
extern char** environ;
int(*f)();
void preinit(int argc, char **argv, char **envp) {
f = f1;
environ = envp; // actually, it is done a bit later
char *v = getenv("TOTO");
if (v && strcmp(v, "ok") == 0) {
f = f2;
}
}
__attribute__((section(".preinit_array"))) typeof(preinit) *__preinit = preinit;
Ifunc & Gnu LD Inners
Linker di GLIBC LD contiene un simbolo locale _environ Ed è inizializzato, ma è piuttosto difficile estrarlo. C'è un altro modo in cui ho trovato, ma è un po 'complicato e piuttosto inaffidabile.
Al punto di ingresso di Linker _inizio Solo lo stack è inizializzato. Gli argomenti del programma e i valori ambientali vengono inviati al processo tramite Stack. Gli argomenti sono archiviati nel seguente ordine:
argc, argv, argv + 1, ..., argv + argc - 1, null, env ...
Linker LD condivide un simbolo globale _dl_argv, che indica questo posto sullo stack. Con l'aiuto possiamo estrarre tutte le variabili necessarie:
extern char** environ;
extern char **_dl_argv;
char** get_environ() {
int argc = *(int*)(_dl_argv - 1);
char **my_environ = (char**)(_dl_argv + argc + 1);
return my_environ;
}
typeof(f1) * resolve_f() {
environ = get_environ();
const char *var = getenv("TOTO");
if (var && strcmp(var, "ok") == 0) {
return f2;
}
return f1;
}
int f() __attribute__((ifunc("resolve_f")));