1 #include <linux/kernel.h>
3 static const char jumplen
[256] = {
22 [0xe8] = 4, /* call */
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]))
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 */
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 */
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 */
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 */
72 0x66, 0x90), /* xchg %ax,%ax */
75 0x66, 0x90), /* xchg %ax,%ax */
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) */
95 0x66, 0x2e, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00),
96 /* nopw %cs:0L(%[re]ax,%[re]ax,1) */
99 0x66, 0x2e, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00),
100 /* nopw %cs:0L(%[re]ax,%[re]ax,1) */
104 0x66, 0x2e, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00),
105 /* nopw %cs:0L(%[re]ax,%[re]ax,1) */
110 0x66, 0x2e, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00),
111 /* nopw %cs:0L(%[re]ax,%[re]ax,1) */
117 0x66, 0x2e, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00),
118 /* nopw %cs:0L(%[re]ax,%[re]ax,1) */
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) */
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
,
145 int run_o
= 0, pre_o
= 0, lenient
= 0;
146 unsigned char run
, pre
;
147 struct reloc_addrmap
*map
;
152 while (run_o
< size
&& pre_o
< size
) {
156 if (!virtual_address_mapped(run_addr
+ run_o
))
159 map
= find_addrmap(pack
, pre_addr
+ pre_o
);
161 if (handle_myst_reloc
162 (pre_addr
, &pre_o
, run_addr
, &run_o
, map
,
168 if (match_nop(run_addr
, &run_o
) || match_nop(pre_addr
, &pre_o
))
171 run
= *(unsigned char *)(run_addr
+ run_o
);
172 pre
= *(unsigned char *)(pre_addr
+ pre_o
);
175 printk("%02x/%02x ", run
, pre
);
179 lenient
= max(jumplen
[pre
] + 1, lenient
);
184 if (jumplen
[run
] && jumplen
[pre
]) {
185 run_o
+= 1 + jumplen
[run
];
186 pre_o
+= 1 + jumplen
[pre
];
194 printk("[p_o=%08x] ! %02x/%02x %02x/%02x",
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));
205 static int match_nop(long addr
, int *o
)
209 for (i
= NUM_NOPS
- 1; i
>= 0; i
--) {
211 for (j
= 0; j
< nop
->len
; j
++) {
212 if (!virtual_address_mapped(addr
+ *o
+ j
))
214 if (*(unsigned char *)(addr
+ *o
+ j
) != nop
->data
[j
])