unset ld env before running command
[ginge.git] / loader / dl.c
1 /*
2  * GINGE - GINGE Is Not Gp2x Emulator
3  * (C) notaz, 2010-2011
4  *
5  * This work is licensed under the MAME license, see COPYING file for details.
6  */
7 #define _GNU_SOURCE
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <sys/mman.h>
11 #include <dlfcn.h>
12 #include "header.h"
13
14 #define DL
15 #include "override.c"
16
17 static void next_line(FILE *f)
18 {
19   int c;
20   do {
21     c = fgetc(f);
22   } while (c != EOF && c != '\n');
23 }
24
25 __attribute__((constructor))
26 static void ginge_init(void)
27 {
28   void *lowest_segments[2] = { NULL, NULL };
29   unsigned int start, end;
30   int i, ret;
31   FILE *f;
32
33   for (i = 0; i < ARRAY_SIZE(real_funcs_np); i++) {
34     *real_funcs_np[i].func_ptr = dlsym(RTLD_NEXT, real_funcs_np[i].name);
35     if (*real_funcs_np[i].func_ptr == NULL) {
36       fprintf(stderr, "dlsym %s: %s\n", real_funcs_np[i].name, dlerror());
37       exit(1);
38     }
39     // dbg("%p %s\n", *real_funcs_np[i].func_ptr, real_funcs_np[i].name);
40   }
41
42   f = fopen("/proc/self/maps", "r");
43   if (f == NULL) {
44     perror("open /proc/self/maps");
45     exit(1);
46   }
47
48   ret = fscanf(f, "%x-%x ", &start, &end);
49   if (ret != 2) {
50     perror("parse maps");
51     exit(1);
52   }
53   lowest_segments[0] = (void *)start;
54
55   while (1) {
56     next_line(f);
57
58     ret = fscanf(f, "%x-%*s %*s %*s %*s %*s %*s\n", &start);
59     if (ret <= 0)
60       break;
61
62     if (lowest_segments[0] == NULL || (void *)start < lowest_segments[0])
63       lowest_segments[0] = (void *)start;
64     else if (lowest_segments[1] == NULL
65              && (char *)start - (char *)lowest_segments[0] > 0x800000)
66     {
67       // an offset is needed because ld-linux also
68       // tends to put stuff here
69       lowest_segments[1] = (void *)(start - 0x20000);
70     }
71   }
72
73 #if 0
74   rewind(f);
75   char buff[256];
76   while (fgets(buff, sizeof(buff), f))
77     fputs(buff, stdout);
78 #endif
79   fclose(f);
80
81   // remove self from preload, further commands (from system() and such)
82   // will be handled by ginge_prep.
83   unsetenv("LD_PRELOAD");
84   unsetenv("LD_LIBRARY_PATH");
85
86   emu_init(lowest_segments, 1);
87 }
88
89 // vim:shiftwidth=2:expandtab