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