loader: better system() path handling
[ginge.git] / loader / dl.c
1 // vim:shiftwidth=2:expandtab
2 #define _GNU_SOURCE
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <sys/mman.h>
6 #include <dlfcn.h>
7 #include "header.h"
8
9 #define DL
10 #include "override.c"
11
12 static void next_line(FILE *f)
13 {
14   int c;
15   do {
16     c = fgetc(f);
17   } while (c != EOF && c != '\n');
18 }
19
20 __attribute__((constructor))
21 static void ginge_init(void)
22 {
23   unsigned int lowest_segment = (unsigned int)-1;
24   unsigned int start, end;
25   int i, ret;
26   FILE *f;
27
28   for (i = 0; i < ARRAY_SIZE(real_funcs_np); i++) {
29     *real_funcs_np[i].func_ptr = dlsym(RTLD_NEXT, real_funcs_np[i].name);
30     if (*real_funcs_np[i].func_ptr == NULL) {
31       fprintf(stderr, "dlsym %s: %s\n", real_funcs_np[i].name, dlerror());
32       exit(1);
33     }
34     // dbg("%p %s\n", *real_funcs_np[i].func_ptr, real_funcs_np[i].name);
35   }
36
37   f = fopen("/proc/self/maps", "r");
38   if (f == NULL) {
39     perror("open /proc/self/maps");
40     exit(1);
41   }
42
43   ret = fscanf(f, "%x-%x ", &start, &end);
44   if (ret != 2) {
45     perror("parse maps");
46     exit(1);
47   }
48   lowest_segment = start;
49
50   // assume first entry lists program's text section.
51   // unprotect it in case we need some patching.
52   ret = mprotect((void *)start, end - start, PROT_READ|PROT_WRITE|PROT_EXEC);
53   if (ret != 0)
54     perror("warning: mprotect");
55
56   while (1) {
57     next_line(f);
58
59     ret = fscanf(f, "%x-%*s %*s %*s %*s %*s %*s\n", &start);
60     if (ret <= 0)
61       break;
62
63     if (start < lowest_segment)
64       lowest_segment = start;
65   }
66
67 #if 0
68   rewind(f);
69   char buff[256];
70   while (fgets(buff, sizeof(buff), f))
71     fputs(buff, stdout);
72 #endif
73   fclose(f);
74
75   // remove self from preload, further commands (from system() and such)
76   // will be handled by ginge_prep.
77   unsetenv("LD_PRELOAD");
78   unsetenv("LD_LIBRARY_PATH");
79
80   emu_init((void *)lowest_segment);
81 }
82