MCPcopy Create free account
hub / github.com/GJDuck/e9patch / e9init

Function e9init

src/e9patch/e9loader_elf.cpp:337–451  ·  view source on GitHub ↗

* Loader initialization code. */

Source from the content-addressed store, hash-verified

335 * Loader initialization code.
336 */
337void *e9init(int argc, char **argv, char **envp, const e9_config_s *config)
338{
339 // Step (0): Sanity checks & initialization:
340 if (config->magic[0] != 'E' || config->magic[1] != '9' ||
341 config->magic[2] != 'P' || config->magic[3] != 'A' ||
342 config->magic[4] != 'T' || config->magic[5] != 'C' ||
343 config->magic[6] != 'H' || config->magic[7] != '\0')
344 e9panic("missing \"E9PATCH\" magic number");
345 const uint8_t *loader_base = (const uint8_t *)config;
346 const uint8_t *loader_end = loader_base + config->size;
347 const uint8_t *elf_base = loader_base - config->base;
348 const void *dynamic = NULL;
349 const struct e9_config_elf_s *config_elf =
350 (const struct e9_config_elf_s *)(config + 1);
351 if (config_elf->dynamic != 0x0)
352 dynamic = (const void *)(elf_base + config_elf->dynamic);
353
354 // Step (1): Call the pre-initialization routine:
355 const uint32_t *preinits =
356 (const uint32_t *)(loader_base + config->preinits);
357 for (uint32_t i = 0; i < config->num_preinits; i++)
358 {
359 init_t preinit = (init_t)(loader_base + preinits[i]);
360 preinit(argc, argv, envp, dynamic, config);
361 }
362
363 // Step (2): Find & open the binary:
364 char buf[BUFSIZ];
365 const char *path = "/proc/self/exe";
366 if ((config->flags & E9_FLAG_EXE) == 0)
367 {
368 // This is a shared object, so use the /proc/self/map_files/
369 // method to find the binary.
370 char *str = buf;
371 str = e9write_format(str, "/proc/self/map_files/%X-%X", loader_base,
372 loader_end);
373 str = e9write_char(str, '\0');
374 path = buf;
375 }
376 ssize_t len = (ssize_t)e9syscall(SYS_readlink, path, buf, sizeof(buf));
377 if (len < 0)
378 e9panic("readlink(path=\"%s\") failed (errno=%u)", buf, -len);
379 buf[len] = '\0';
380 int fd = (int)e9syscall(SYS_open, buf, O_RDONLY, 0);
381 if (fd < 0)
382 e9panic("open(path=\"%s\") failed (errno=%u)", buf, -fd);
383
384 // Step (3): Setup dummy TLS (if necessary):
385 struct e9scratch_s *scratch = NULL;
386 uintptr_t tls = 0x0;
387 intptr_t r = e9syscall(SYS_arch_prctl, ARCH_GET_FS, &tls);
388 if (r < 0)
389 e9panic("arch_prctl() failed (errno=%u)", -r);
390 if (tls == 0x0)
391 {
392 // No libc == no tls:
393 scratch = e9scratch(config, /*alloc=*/true);
394 tls = (uintptr_t)&scratch->tls;

Callers

nothing calls this directly

Calls 8

e9write_formatFunction · 0.85
e9write_charFunction · 0.85
e9scratchFunction · 0.85
e9load_mapsFunction · 0.85
e9addrFunction · 0.85
e9filterFunction · 0.85
e9panicFunction · 0.70
initFunction · 0.50

Tested by

no test coverage detected