make forced_exit work regardless of loader name
[ginge.git] / loader / patches.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 #include <stdio.h>
8
9 #include "header.h"
10 #include "sys_cacheflush.h"
11
12 #include "override.c"
13
14 // note: first mask must be always full for search algo
15 static const unsigned int sig_mask_all[] = {
16   0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
17   0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff
18 };
19
20 static const unsigned int sig_open[] = {
21   0xe59cc000, 0xe33c0000, 0x1a000003, 0xef900005
22 };
23 #define sig_mask_open sig_mask_all
24
25 static const unsigned int sig_mmap[] = {
26   0xe92d000f, 0xe1a0000d, 0xef90005a, 0xe28dd010
27 };
28 #define sig_mask_mmap sig_mask_all
29
30 static const unsigned int sig_mmap2[] = {
31   0xe52d5004, 0xe59d5008, 0xe52d4004, 0xe59d4008,
32   0xe1b0ca05, 0x1a000006, 0xe1a05625, 0xef9000c0
33 };
34 #define sig_mask_mmap2 sig_mask_all
35
36 static const unsigned int sig_read[] = {
37   0xe59fc080, 0xe59cc000, 0xe33c0000, 0x1a000003, 0xef900003
38 };
39 #define sig_mask_read sig_mask_all
40
41 static const unsigned int sig_ioctl[] = {
42   0xef900036, 0xe3700a01, 0x312fff1e
43 };
44 #define sig_mask_ioctl sig_mask_all
45
46 static const unsigned int sig_sigaction[] = {
47   0xe59f300c, 0xe3530000, 0x0a000000, 0xea000000, 0xea000000
48 };
49 static const unsigned int sig_mask_sigaction[] = {
50   0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000
51 };
52
53 static const unsigned int sig_execve[] = {
54   0xef90000b, 0xe1a04000, 0xe3700a01
55 };
56 #define sig_mask_execve sig_mask_all
57
58 static const unsigned int sig_execve2[] = {
59   0xef90000b, 0xe3700a01, 0xe1a04000
60 };
61 #define sig_mask_execve2 sig_mask_all
62
63 static const unsigned int sig_chdir[] = {
64   0xef90000c, 0xe3700a01, 0x312fff1e, 0xea0004bb
65 };
66 static const unsigned int sig_mask_chdir[] = {
67   0xffffffff, 0xffffffff, 0xffffffff, 0xff000000
68 };
69
70 #define PATCH_(f,p) { sig_##p, sig_mask_##p, ARRAY_SIZE(sig_##p), w_##f }
71 #define PATCH(f) PATCH_(f,f)
72
73 static const struct {
74   const unsigned int *sig;
75   const unsigned int *sig_mask;
76   size_t sig_cnt;
77   void *func;
78 } patches[] = {
79   PATCH(open),
80   PATCH(mmap),
81   PATCH(mmap2), // mmap2 syscall
82   PATCH(read),
83   PATCH(ioctl),
84   PATCH(sigaction),
85 //  PATCH_(execve, execve2), // hangs
86   PATCH(chdir),
87 };
88
89 void do_patches(void *ptr, unsigned int size)
90 {
91   int i, s;
92
93   for (i = 0; i < ARRAY_SIZE(patches); i++) {
94     const unsigned int *sig = patches[i].sig;
95     const unsigned int *sig_mask = patches[i].sig_mask;
96     unsigned int *seg = (void *)(((long)ptr + 3) & ~3);
97     unsigned int *seg_end = seg + size / 4;
98     unsigned int sig0 = sig[0];
99
100     for (; seg < seg_end; seg++) {
101       if (*seg != sig0)
102         continue;
103
104       for (s = 1; s < patches[i].sig_cnt; s++)
105         if ((seg[s] ^ sig[s]) & sig_mask[s])
106           break;
107
108       if (s == patches[i].sig_cnt)
109         goto found;
110     }
111     continue;
112
113 found:
114     dbg("  patch #%i @ %08x\n", i, (int)seg);
115     seg[0] = 0xe59ff000; // ldr pc, [pc]
116     seg[1] = 0;
117     seg[2] = (unsigned int)patches[i].func;
118   }
119
120   sys_cacheflush(ptr, (char *)ptr + size);
121 }
122
123 // vim:shiftwidth=2:expandtab