Remove the unneeded c3, 5b hack for detecting end of function.
[ksplice.git] / kmodsrc / ksplice-run-pre.h
blobe0eb3babe8b336007bdb34377668f6897e3c591c
1 #include <linux/kernel.h>
3 static const char jumplen[256] = {[0x0f] = 5, /* je */
4 [0x70] = 1, /* jo */
5 [0x71] = 1, /* jno */
6 [0x72] = 1, /* jb */
7 [0x73] = 1, /* jnb */
8 [0x74] = 1, /* jc */
9 [0x75] = 1, /* jne */
10 [0x76] = 1, /* jbe */
11 [0x77] = 1, /* ja */
12 [0x78] = 1, /* js */
13 [0x79] = 1, /* jns */
14 [0x7a] = 1, /* jp */
15 [0x7b] = 1, /* jnp */
16 [0x7c] = 1, /* jl */
17 [0x7d] = 1, /* jge */
18 [0x7e] = 1, /* jle */
19 [0x7f] = 1, /* jg */
20 [0xe9] = 4, /* jmp */
21 [0xe8] = 4, /* call */
22 [0xeb] = 1, /* jmp */
25 /* Various efficient no-op patterns for aligning code labels.
26 Note: Don't try to assemble the instructions in the comments.
27 0L and 0w are not legal. */
29 #define NUM_NOPS (sizeof(nops) / sizeof(nops[0]))
30 struct insn {
31 size_t len;
32 unsigned char *data;
35 /* *INDENT-OFF* */
36 #define I(...) { \
37 .len = sizeof((unsigned char []){__VA_ARGS__}), \
38 .data = ((unsigned char []){__VA_ARGS__}), \
40 static struct insn nops[] = {
41 /* GNU assembler no-op patterns from
42 binutils-2.17/gas/config/tc-i386.c line 500 */
43 I(0x90), /* nop */
44 I(0x89, 0xf6), /* movl %esi,%esi */
45 I(0x8d, 0x76, 0x00), /* leal 0(%esi),%esi */
46 I(0x8d, 0x74, 0x26, 0x00), /* leal 0(%esi,1),%esi */
47 I(0x90, /* nop */
48 0x8d, 0x74, 0x26, 0x00), /* leal 0(%esi,1),%esi */
49 I(0x8d, 0xb6, 0x00, 0x00, 0x00, 0x00), /* leal 0L(%esi),%esi */
50 I(0x8d, 0xb4, 0x26, 0x00, 0x00, 0x00, 0x00), /* leal 0L(%esi,1),%esi */
51 I(0x90, /* nop */
52 0x8d, 0xb4, 0x26, 0x00, 0x00, 0x00, 0x00), /* leal 0L(%esi,1),%esi */
53 I(0x89, 0xf6, /* movl %esi,%esi */
54 0x8d, 0xbc, 0x27, 0x00, 0x00, 0x00, 0x00), /* leal 0L(%edi,1),%edi */
55 I(0x8d, 0x76, 0x00, /* leal 0(%esi),%esi */
56 0x8d, 0xbc, 0x27, 0x00, 0x00, 0x00, 0x00), /* leal 0L(%edi,1),%edi */
57 I(0x8d, 0x74, 0x26, 0x00, /* leal 0(%esi,1),%esi */
58 0x8d, 0xbc, 0x27, 0x00, 0x00, 0x00, 0x00), /* leal 0L(%edi,1),%edi */
59 I(0x8d, 0xb6, 0x00, 0x00, 0x00, 0x00, /* leal 0L(%esi),%esi */
60 0x8d, 0xbf, 0x00, 0x00, 0x00, 0x00), /* leal 0L(%edi),%edi */
61 I(0x8d, 0xb6, 0x00, 0x00, 0x00, 0x00, /* leal 0L(%esi),%esi */
62 0x8d, 0xbc, 0x27, 0x00, 0x00, 0x00, 0x00), /* leal 0L(%edi,1),%edi */
63 I(0x8d, 0xb4, 0x26, 0x00, 0x00, 0x00, 0x00, /* leal 0L(%esi,1),%esi */
64 0x8d, 0xbc, 0x27, 0x00, 0x00, 0x00, 0x00), /* leal 0L(%edi,1),%edi */
65 I(0xeb, 0x0d, 0x90, 0x90, 0x90, 0x90, 0x90, /* jmp .+15; lotsa nops */
66 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90),
68 /* binutils-2.17/gas/config/tc-i386.c line 570 */
69 I(0x66, 0x90), /* xchg %ax,%ax */
70 I(0x66, /* data16 */
71 0x66, 0x90), /* xchg %ax,%ax */
72 I(0x66, /* data16 */
73 0x66, /* data16 */
74 0x66, 0x90), /* xchg %ax,%ax */
75 I(0x66, /* data16 */
76 0x66, /* data16 */
77 0x66, /* data16 */
78 0x66, 0x90), /* xchg %ax,%ax */
80 /* binutils-2.18/gas/config/tc-i386.c line 572 */
81 I(0x0f, 0x1f, 0x00), /* nopl (%[re]ax) */
82 I(0x0f, 0x1f, 0x40, 0x00), /* nopl 0(%[re]ax) */
83 I(0x0f, 0x1f, 0x44, 0x00, 0x00), /* nopl 0(%[re]ax,%[re]ax,1) */
84 I(0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00), /* nopw 0(%[re]ax,%[re]ax,1) */
85 I(0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00),
86 /* nopw 0(%[re]ax,%[re]ax,1) */
87 I(0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00),
88 /* nopl 0L(%[re]ax,%[re]ax,1) */
89 I(0x66, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00),
90 /* nopw 0L(%[re]ax,%[re]ax,1) */
91 I(0x66, 0x2e, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00),
92 /* nopw %cs:0L(%[re]ax,%[re]ax,1) */
93 I(0x66, /* data16 */
94 0x66, 0x2e, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00),
95 /* nopw %cs:0L(%[re]ax,%[re]ax,1) */
96 I(0x66, /* data16 */
97 0x66, /* data16 */
98 0x66, 0x2e, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00),
99 /* nopw %cs:0L(%[re]ax,%[re]ax,1) */
100 I(0x66, /* data16 */
101 0x66, /* data16 */
102 0x66, /* data16 */
103 0x66, 0x2e, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00),
104 /* nopw %cs:0L(%[re]ax,%[re]ax,1) */
105 I(0x66, /* data16 */
106 0x66, /* data16 */
107 0x66, /* data16 */
108 0x66, /* data16 */
109 0x66, 0x2e, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00),
110 /* nopw %cs:0L(%[re]ax,%[re]ax,1) */
111 I(0x66, /* data16 */
112 0x66, /* data16 */
113 0x66, /* data16 */
114 0x66, /* data16 */
115 0x66, /* data16 */
116 0x66, 0x2e, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00),
117 /* nopw %cs:0L(%[re]ax,%[re]ax,1) */
118 I(0x66, /* data16 */
119 0x66, /* data16 */
120 0x66, /* data16 */
121 0x66, /* data16 */
122 0x66, /* data16 */
123 0x66, 0x2e, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00),
124 /* nopw %cs:0L(%[re]ax,%[re]ax,1) */
125 I(0x0f, 0x1f, 0x44, 0x00, 0x00, /* nopl 0(%[re]ax,%[re]ax,1) */
126 0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00), /* nopw 0(%[re]ax,%[re]ax,1) */
127 I(0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00, /* nopw 0(%[re]ax,%[re]ax,1) */
128 0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00), /* nopw 0(%[re]ax,%[re]ax,1) */
129 I(0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00, /* nopw 0(%[re]ax,%[re]ax,1) */
130 0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00), /* nopl 0L(%[re]ax) */
131 I(0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00, /* nopl 0L(%[re]ax) */
132 0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00), /* nopl 0L(%[re]ax) */
133 I(0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00, /* nopl 0L(%[re]ax) */
134 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00),
135 /* nopl 0L(%[re]ax,%[re]ax,1) */
137 /* *INDENT-ON* */
139 static int match_nop(long addr, int *o);
141 static int run_pre_cmp(struct module_pack *pack, long run_addr, long pre_addr,
142 int size, int rerun)
144 int run_o = 0, pre_o = 0, lenient = 0;
145 unsigned char run, pre;
146 struct reloc_addrmap *map;
148 if (size == 0)
149 return 1;
151 while (run_o < size && pre_o < size) {
152 if (lenient > 0)
153 lenient--;
155 if (!virtual_address_mapped(run_addr + run_o))
156 return 1;
158 map = find_addrmap(pack, pre_addr + pre_o);
159 if (map != NULL) {
160 if (handle_myst_reloc
161 (pre_addr, &pre_o, run_addr, &run_o, map,
162 rerun) == 1)
163 return 1;
164 continue;
167 if (match_nop(run_addr, &run_o) || match_nop(pre_addr, &pre_o))
168 continue;
170 run = *(unsigned char *)(run_addr + run_o);
171 pre = *(unsigned char *)(pre_addr + pre_o);
173 if (rerun)
174 printk("%02x/%02x ", run, pre);
176 if (run == pre) {
177 if (jumplen[pre])
178 lenient = max(jumplen[pre] + 1, lenient);
179 pre_o++, run_o++;
180 continue;
183 if (jumplen[run] && jumplen[pre]) {
184 run_o += 1 + jumplen[run];
185 pre_o += 1 + jumplen[pre];
186 continue;
188 if (lenient) {
189 pre_o++, run_o++;
190 continue;
192 if (rerun)
193 printk("[p_o=%08x] ! %02x/%02x %02x/%02x",
194 pre_o,
195 *(unsigned char *)(run_addr + run_o + 1),
196 *(unsigned char *)(pre_addr + pre_o + 1),
197 *(unsigned char *)(run_addr + run_o + 2),
198 *(unsigned char *)(pre_addr + pre_o + 2));
199 return 1;
201 return 0;
204 static int match_nop(long addr, int *o)
206 int i, j;
207 struct insn *nop;
208 for (i = NUM_NOPS - 1; i >= 0; i--) {
209 nop = &nops[i];
210 for (j = 0; j < nop->len; j++) {
211 if (!virtual_address_mapped(addr + *o + j))
212 break;
213 if (*(unsigned char *)(addr + *o + j) != nop->data[j])
214 break;
216 if (j == nop->len) {
217 *o += j;
218 return 1;
222 return 0;