Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
[platform/kernel/linux-rpi.git] / tools / objtool / arch / x86 / decode.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (C) 2015 Josh Poimboeuf <jpoimboe@redhat.com>
4  */
5
6 #include <stdio.h>
7 #include <stdlib.h>
8
9 #define unlikely(cond) (cond)
10 #include <asm/insn.h>
11 #include "../../../arch/x86/lib/inat.c"
12 #include "../../../arch/x86/lib/insn.c"
13
14 #include "../../elf.h"
15 #include "../../arch.h"
16 #include "../../warn.h"
17
18 static unsigned char op_to_cfi_reg[][2] = {
19         {CFI_AX, CFI_R8},
20         {CFI_CX, CFI_R9},
21         {CFI_DX, CFI_R10},
22         {CFI_BX, CFI_R11},
23         {CFI_SP, CFI_R12},
24         {CFI_BP, CFI_R13},
25         {CFI_SI, CFI_R14},
26         {CFI_DI, CFI_R15},
27 };
28
29 static int is_x86_64(struct elf *elf)
30 {
31         switch (elf->ehdr.e_machine) {
32         case EM_X86_64:
33                 return 1;
34         case EM_386:
35                 return 0;
36         default:
37                 WARN("unexpected ELF machine type %d", elf->ehdr.e_machine);
38                 return -1;
39         }
40 }
41
42 bool arch_callee_saved_reg(unsigned char reg)
43 {
44         switch (reg) {
45         case CFI_BP:
46         case CFI_BX:
47         case CFI_R12:
48         case CFI_R13:
49         case CFI_R14:
50         case CFI_R15:
51                 return true;
52
53         case CFI_AX:
54         case CFI_CX:
55         case CFI_DX:
56         case CFI_SI:
57         case CFI_DI:
58         case CFI_SP:
59         case CFI_R8:
60         case CFI_R9:
61         case CFI_R10:
62         case CFI_R11:
63         case CFI_RA:
64         default:
65                 return false;
66         }
67 }
68
69 int arch_decode_instruction(struct elf *elf, struct section *sec,
70                             unsigned long offset, unsigned int maxlen,
71                             unsigned int *len, enum insn_type *type,
72                             unsigned long *immediate, struct stack_op *op)
73 {
74         struct insn insn;
75         int x86_64, sign;
76         unsigned char op1, op2, rex = 0, rex_b = 0, rex_r = 0, rex_w = 0,
77                       rex_x = 0, modrm = 0, modrm_mod = 0, modrm_rm = 0,
78                       modrm_reg = 0, sib = 0;
79
80         x86_64 = is_x86_64(elf);
81         if (x86_64 == -1)
82                 return -1;
83
84         insn_init(&insn, sec->data->d_buf + offset, maxlen, x86_64);
85         insn_get_length(&insn);
86
87         if (!insn_complete(&insn)) {
88                 WARN_FUNC("can't decode instruction", sec, offset);
89                 return -1;
90         }
91
92         *len = insn.length;
93         *type = INSN_OTHER;
94
95         if (insn.vex_prefix.nbytes)
96                 return 0;
97
98         op1 = insn.opcode.bytes[0];
99         op2 = insn.opcode.bytes[1];
100
101         if (insn.rex_prefix.nbytes) {
102                 rex = insn.rex_prefix.bytes[0];
103                 rex_w = X86_REX_W(rex) >> 3;
104                 rex_r = X86_REX_R(rex) >> 2;
105                 rex_x = X86_REX_X(rex) >> 1;
106                 rex_b = X86_REX_B(rex);
107         }
108
109         if (insn.modrm.nbytes) {
110                 modrm = insn.modrm.bytes[0];
111                 modrm_mod = X86_MODRM_MOD(modrm);
112                 modrm_reg = X86_MODRM_REG(modrm);
113                 modrm_rm = X86_MODRM_RM(modrm);
114         }
115
116         if (insn.sib.nbytes)
117                 sib = insn.sib.bytes[0];
118
119         switch (op1) {
120
121         case 0x1:
122         case 0x29:
123                 if (rex_w && !rex_b && modrm_mod == 3 && modrm_rm == 4) {
124
125                         /* add/sub reg, %rsp */
126                         *type = INSN_STACK;
127                         op->src.type = OP_SRC_ADD;
128                         op->src.reg = op_to_cfi_reg[modrm_reg][rex_r];
129                         op->dest.type = OP_DEST_REG;
130                         op->dest.reg = CFI_SP;
131                 }
132                 break;
133
134         case 0x50 ... 0x57:
135
136                 /* push reg */
137                 *type = INSN_STACK;
138                 op->src.type = OP_SRC_REG;
139                 op->src.reg = op_to_cfi_reg[op1 & 0x7][rex_b];
140                 op->dest.type = OP_DEST_PUSH;
141
142                 break;
143
144         case 0x58 ... 0x5f:
145
146                 /* pop reg */
147                 *type = INSN_STACK;
148                 op->src.type = OP_SRC_POP;
149                 op->dest.type = OP_DEST_REG;
150                 op->dest.reg = op_to_cfi_reg[op1 & 0x7][rex_b];
151
152                 break;
153
154         case 0x68:
155         case 0x6a:
156                 /* push immediate */
157                 *type = INSN_STACK;
158                 op->src.type = OP_SRC_CONST;
159                 op->dest.type = OP_DEST_PUSH;
160                 break;
161
162         case 0x70 ... 0x7f:
163                 *type = INSN_JUMP_CONDITIONAL;
164                 break;
165
166         case 0x81:
167         case 0x83:
168                 if (rex != 0x48)
169                         break;
170
171                 if (modrm == 0xe4) {
172                         /* and imm, %rsp */
173                         *type = INSN_STACK;
174                         op->src.type = OP_SRC_AND;
175                         op->src.reg = CFI_SP;
176                         op->src.offset = insn.immediate.value;
177                         op->dest.type = OP_DEST_REG;
178                         op->dest.reg = CFI_SP;
179                         break;
180                 }
181
182                 if (modrm == 0xc4)
183                         sign = 1;
184                 else if (modrm == 0xec)
185                         sign = -1;
186                 else
187                         break;
188
189                 /* add/sub imm, %rsp */
190                 *type = INSN_STACK;
191                 op->src.type = OP_SRC_ADD;
192                 op->src.reg = CFI_SP;
193                 op->src.offset = insn.immediate.value * sign;
194                 op->dest.type = OP_DEST_REG;
195                 op->dest.reg = CFI_SP;
196                 break;
197
198         case 0x89:
199                 if (rex_w && !rex_r && modrm_mod == 3 && modrm_reg == 4) {
200
201                         /* mov %rsp, reg */
202                         *type = INSN_STACK;
203                         op->src.type = OP_SRC_REG;
204                         op->src.reg = CFI_SP;
205                         op->dest.type = OP_DEST_REG;
206                         op->dest.reg = op_to_cfi_reg[modrm_rm][rex_b];
207                         break;
208                 }
209
210                 if (rex_w && !rex_b && modrm_mod == 3 && modrm_rm == 4) {
211
212                         /* mov reg, %rsp */
213                         *type = INSN_STACK;
214                         op->src.type = OP_SRC_REG;
215                         op->src.reg = op_to_cfi_reg[modrm_reg][rex_r];
216                         op->dest.type = OP_DEST_REG;
217                         op->dest.reg = CFI_SP;
218                         break;
219                 }
220
221                 /* fallthrough */
222         case 0x88:
223                 if (!rex_b &&
224                     (modrm_mod == 1 || modrm_mod == 2) && modrm_rm == 5) {
225
226                         /* mov reg, disp(%rbp) */
227                         *type = INSN_STACK;
228                         op->src.type = OP_SRC_REG;
229                         op->src.reg = op_to_cfi_reg[modrm_reg][rex_r];
230                         op->dest.type = OP_DEST_REG_INDIRECT;
231                         op->dest.reg = CFI_BP;
232                         op->dest.offset = insn.displacement.value;
233
234                 } else if (rex_w && !rex_b && modrm_rm == 4 && sib == 0x24) {
235
236                         /* mov reg, disp(%rsp) */
237                         *type = INSN_STACK;
238                         op->src.type = OP_SRC_REG;
239                         op->src.reg = op_to_cfi_reg[modrm_reg][rex_r];
240                         op->dest.type = OP_DEST_REG_INDIRECT;
241                         op->dest.reg = CFI_SP;
242                         op->dest.offset = insn.displacement.value;
243                 }
244
245                 break;
246
247         case 0x8b:
248                 if (rex_w && !rex_b && modrm_mod == 1 && modrm_rm == 5) {
249
250                         /* mov disp(%rbp), reg */
251                         *type = INSN_STACK;
252                         op->src.type = OP_SRC_REG_INDIRECT;
253                         op->src.reg = CFI_BP;
254                         op->src.offset = insn.displacement.value;
255                         op->dest.type = OP_DEST_REG;
256                         op->dest.reg = op_to_cfi_reg[modrm_reg][rex_r];
257
258                 } else if (rex_w && !rex_b && sib == 0x24 &&
259                            modrm_mod != 3 && modrm_rm == 4) {
260
261                         /* mov disp(%rsp), reg */
262                         *type = INSN_STACK;
263                         op->src.type = OP_SRC_REG_INDIRECT;
264                         op->src.reg = CFI_SP;
265                         op->src.offset = insn.displacement.value;
266                         op->dest.type = OP_DEST_REG;
267                         op->dest.reg = op_to_cfi_reg[modrm_reg][rex_r];
268                 }
269
270                 break;
271
272         case 0x8d:
273                 if (sib == 0x24 && rex_w && !rex_b && !rex_x) {
274
275                         *type = INSN_STACK;
276                         if (!insn.displacement.value) {
277                                 /* lea (%rsp), reg */
278                                 op->src.type = OP_SRC_REG;
279                         } else {
280                                 /* lea disp(%rsp), reg */
281                                 op->src.type = OP_SRC_ADD;
282                                 op->src.offset = insn.displacement.value;
283                         }
284                         op->src.reg = CFI_SP;
285                         op->dest.type = OP_DEST_REG;
286                         op->dest.reg = op_to_cfi_reg[modrm_reg][rex_r];
287
288                 } else if (rex == 0x48 && modrm == 0x65) {
289
290                         /* lea disp(%rbp), %rsp */
291                         *type = INSN_STACK;
292                         op->src.type = OP_SRC_ADD;
293                         op->src.reg = CFI_BP;
294                         op->src.offset = insn.displacement.value;
295                         op->dest.type = OP_DEST_REG;
296                         op->dest.reg = CFI_SP;
297
298                 } else if (rex == 0x49 && modrm == 0x62 &&
299                            insn.displacement.value == -8) {
300
301                         /*
302                          * lea -0x8(%r10), %rsp
303                          *
304                          * Restoring rsp back to its original value after a
305                          * stack realignment.
306                          */
307                         *type = INSN_STACK;
308                         op->src.type = OP_SRC_ADD;
309                         op->src.reg = CFI_R10;
310                         op->src.offset = -8;
311                         op->dest.type = OP_DEST_REG;
312                         op->dest.reg = CFI_SP;
313
314                 } else if (rex == 0x49 && modrm == 0x65 &&
315                            insn.displacement.value == -16) {
316
317                         /*
318                          * lea -0x10(%r13), %rsp
319                          *
320                          * Restoring rsp back to its original value after a
321                          * stack realignment.
322                          */
323                         *type = INSN_STACK;
324                         op->src.type = OP_SRC_ADD;
325                         op->src.reg = CFI_R13;
326                         op->src.offset = -16;
327                         op->dest.type = OP_DEST_REG;
328                         op->dest.reg = CFI_SP;
329                 }
330
331                 break;
332
333         case 0x8f:
334                 /* pop to mem */
335                 *type = INSN_STACK;
336                 op->src.type = OP_SRC_POP;
337                 op->dest.type = OP_DEST_MEM;
338                 break;
339
340         case 0x90:
341                 *type = INSN_NOP;
342                 break;
343
344         case 0x9c:
345                 /* pushf */
346                 *type = INSN_STACK;
347                 op->src.type = OP_SRC_CONST;
348                 op->dest.type = OP_DEST_PUSHF;
349                 break;
350
351         case 0x9d:
352                 /* popf */
353                 *type = INSN_STACK;
354                 op->src.type = OP_SRC_POPF;
355                 op->dest.type = OP_DEST_MEM;
356                 break;
357
358         case 0x0f:
359
360                 if (op2 == 0x01) {
361
362                         if (modrm == 0xca)
363                                 *type = INSN_CLAC;
364                         else if (modrm == 0xcb)
365                                 *type = INSN_STAC;
366
367                 } else if (op2 >= 0x80 && op2 <= 0x8f) {
368
369                         *type = INSN_JUMP_CONDITIONAL;
370
371                 } else if (op2 == 0x05 || op2 == 0x07 || op2 == 0x34 ||
372                            op2 == 0x35) {
373
374                         /* sysenter, sysret */
375                         *type = INSN_CONTEXT_SWITCH;
376
377                 } else if (op2 == 0x0b || op2 == 0xb9) {
378
379                         /* ud2 */
380                         *type = INSN_BUG;
381
382                 } else if (op2 == 0x0d || op2 == 0x1f) {
383
384                         /* nopl/nopw */
385                         *type = INSN_NOP;
386
387                 } else if (op2 == 0xa0 || op2 == 0xa8) {
388
389                         /* push fs/gs */
390                         *type = INSN_STACK;
391                         op->src.type = OP_SRC_CONST;
392                         op->dest.type = OP_DEST_PUSH;
393
394                 } else if (op2 == 0xa1 || op2 == 0xa9) {
395
396                         /* pop fs/gs */
397                         *type = INSN_STACK;
398                         op->src.type = OP_SRC_POP;
399                         op->dest.type = OP_DEST_MEM;
400                 }
401
402                 break;
403
404         case 0xc9:
405                 /*
406                  * leave
407                  *
408                  * equivalent to:
409                  * mov bp, sp
410                  * pop bp
411                  */
412                 *type = INSN_STACK;
413                 op->dest.type = OP_DEST_LEAVE;
414
415                 break;
416
417         case 0xe3:
418                 /* jecxz/jrcxz */
419                 *type = INSN_JUMP_CONDITIONAL;
420                 break;
421
422         case 0xe9:
423         case 0xeb:
424                 *type = INSN_JUMP_UNCONDITIONAL;
425                 break;
426
427         case 0xc2:
428         case 0xc3:
429                 *type = INSN_RETURN;
430                 break;
431
432         case 0xca: /* retf */
433         case 0xcb: /* retf */
434         case 0xcf: /* iret */
435                 *type = INSN_CONTEXT_SWITCH;
436                 break;
437
438         case 0xe8:
439                 *type = INSN_CALL;
440                 break;
441
442         case 0xfc:
443                 *type = INSN_CLD;
444                 break;
445
446         case 0xfd:
447                 *type = INSN_STD;
448                 break;
449
450         case 0xff:
451                 if (modrm_reg == 2 || modrm_reg == 3)
452
453                         *type = INSN_CALL_DYNAMIC;
454
455                 else if (modrm_reg == 4)
456
457                         *type = INSN_JUMP_DYNAMIC;
458
459                 else if (modrm_reg == 5)
460
461                         /* jmpf */
462                         *type = INSN_CONTEXT_SWITCH;
463
464                 else if (modrm_reg == 6) {
465
466                         /* push from mem */
467                         *type = INSN_STACK;
468                         op->src.type = OP_SRC_CONST;
469                         op->dest.type = OP_DEST_PUSH;
470                 }
471
472                 break;
473
474         default:
475                 break;
476         }
477
478         *immediate = insn.immediate.nbytes ? insn.immediate.value : 0;
479
480         return 0;
481 }
482
483 void arch_initial_func_cfi_state(struct cfi_state *state)
484 {
485         int i;
486
487         for (i = 0; i < CFI_NUM_REGS; i++) {
488                 state->regs[i].base = CFI_UNDEFINED;
489                 state->regs[i].offset = 0;
490         }
491
492         /* initial CFA (call frame address) */
493         state->cfa.base = CFI_SP;
494         state->cfa.offset = 8;
495
496         /* initial RA (return address) */
497         state->regs[16].base = CFI_CFA;
498         state->regs[16].offset = -8;
499 }