fix controls regression on _dyn
[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   unsigned int lowest_segment = (unsigned int)-1;
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_segment = start;
54
55   // assume first entry lists program's text section.
56   // unprotect it in case we need some patching.
57   ret = mprotect((void *)start, end - start, PROT_READ|PROT_WRITE|PROT_EXEC);
58   if (ret != 0)
59     perror("warning: mprotect");
60
61   while (1) {
62     next_line(f);
63
64     ret = fscanf(f, "%x-%*s %*s %*s %*s %*s %*s\n", &start);
65     if (ret <= 0)
66       break;
67
68     if (start < lowest_segment)
69       lowest_segment = start;
70   }
71
72 #if 0
73   rewind(f);
74   char buff[256];
75   while (fgets(buff, sizeof(buff), f))
76     fputs(buff, stdout);
77 #endif
78   fclose(f);
79
80   // remove self from preload, further commands (from system() and such)
81   // will be handled by ginge_prep.
82   unsetenv("LD_PRELOAD");
83   unsetenv("LD_LIBRARY_PATH");
84
85   emu_init((void *)lowest_segment);
86 }
87
88 // vim:shiftwidth=2:expandtab