OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright (c) 2012 The Native Client Authors. All rights reserved. | |
3 * Use of this source code is governed by a BSD-style license that can be | |
4 * found in the LICENSE file. | |
5 */ | |
6 | |
7 #ifndef NACL_TRUSTED_BUT_NOT_TCB | |
8 #error("This file is not meant for use in the TCB") | |
9 #endif | |
10 | |
11 #include "native_client/src/trusted/validator_x86/ncdis_segments.h" | |
12 | |
13 #include <string.h> | |
14 | |
15 #include "native_client/src/shared/platform/nacl_log.h" | |
16 #include "native_client/src/trusted/validator/x86/decoder/nc_inst_iter.h" | |
17 #include "native_client/src/trusted/validator/x86/decoder/nc_inst_state_internal
.h" | |
18 #include "native_client/src/trusted/validator/x86/decoder/ncop_exps.h" | |
19 #include "native_client/src/trusted/validator_x86/ncdis_decode_tables.h" | |
20 #include "native_client/src/trusted/validator/x86/ncval_reg_sfi/ncval_decode_tab
les.h" | |
21 #include "native_client/src/trusted/validator/x86/ncval_seg_sfi/ncdecode_verbose
.h" | |
22 #include "native_client/src/trusted/validator/x86/nc_segment.h" | |
23 | |
24 /* Returns true if the disassemble flag is in the given flag set. */ | |
25 Bool NaClContainsDisasembleFlag(NaClDisassembleFlags flags, | |
26 NaClDisassembleFlag flag) { | |
27 return NaClHasBit(flags, NACL_DISASSEMBLE_FLAG(flag)) ? TRUE : FALSE; | |
28 } | |
29 | |
30 static const char* kHardCodedMessage = "[hard coded]"; | |
31 | |
32 /* Inspect the parsed instruction to print out the opcode sequence matched. */ | |
33 static void NaClInstPrintOpcodeSeq(struct Gio* gout, | |
34 const NaClInstState* state) { | |
35 size_t count = 0; | |
36 if (state->num_opcode_bytes == 0) { | |
37 /* Hard coded bytes sequence for instruction. */ | |
38 gprintf(gout, " %s", kHardCodedMessage); | |
39 count = strlen(kHardCodedMessage) + 2; | |
40 } else { | |
41 /* Modeled instruction. Pull out parsed opcode bytes from parsed | |
42 * instruction. | |
43 */ | |
44 int i; | |
45 gprintf(gout, " "); | |
46 count = 1; | |
47 | |
48 /* Add prefix selector if applicable. */ | |
49 if (state->opcode_prefix) { | |
50 gprintf(gout, " %02x", state->opcode_prefix); | |
51 count += 3; | |
52 } | |
53 | |
54 /* Add opcode bytes. */ | |
55 for (i = 0; i < state->num_opcode_bytes; ++i) { | |
56 gprintf(gout, " %02x", state->bytes.byte[state->num_prefix_bytes + i]); | |
57 count += 3; | |
58 } | |
59 if (state->inst->flags & NACL_IFLAG(OpcodeInModRm)) { | |
60 gprintf(gout, " / %d", modrm_opcode(state->modrm)); | |
61 count += 4; | |
62 } else if (state->inst->flags & NACL_IFLAG(OpcodePlusR)) { | |
63 gprintf(gout, " - r%d", | |
64 NaClGetOpcodePlusR(state->inst->opcode_ext)); | |
65 count += 5; | |
66 } | |
67 if (state->inst->flags & NACL_IFLAG(OpcodeInModRmRm)) { | |
68 gprintf(gout, " / %d", modrm_rm(state->modrm)); | |
69 count += 4; | |
70 } | |
71 /* Add opcode for 0f0f instructions, where the opcode is the last | |
72 * byte of the instruction. | |
73 */ | |
74 if ((state->num_opcode_bytes >= 2) && | |
75 (0 == (state->inst->flags & NACL_IFLAG(Opcode0F0F))) && | |
76 (0x0F == state->bytes.byte[state->num_prefix_bytes]) && | |
77 (0x0F == state->bytes.byte[state->num_prefix_bytes + 1])) { | |
78 gprintf(gout, " %02x", state->bytes.byte[state->bytes.length - 1]); | |
79 count += 3; | |
80 } | |
81 } | |
82 while (count < 30) { | |
83 gprintf(gout, " "); | |
84 ++count; | |
85 } | |
86 } | |
87 | |
88 /* Disassemble the code segment, using the given decoder tables. | |
89 * Note: The decoder tables specified in the flags argument will | |
90 * be ignored. | |
91 * | |
92 * Parameters: | |
93 * mbase - Memory region containing code segment. | |
94 * vbase - PC address associated with first byte of memory region. | |
95 * size - Number of bytes in memory region. | |
96 * flags - Flags to use when decoding. | |
97 */ | |
98 static void NaClDisassembleSegmentUsingTables( | |
99 uint8_t* mbase, NaClPcAddress vbase, | |
100 NaClMemorySize size, NaClDisassembleFlags flags, | |
101 const struct NaClDecodeTables* decoder_tables) { | |
102 NaClSegment segment; | |
103 NaClInstIter* iter; | |
104 struct Gio* gout = NaClLogGetGio(); | |
105 Bool print_internals = | |
106 NaClHasBit(flags, NACL_DISASSEMBLE_FLAG(NaClDisassembleAddInternals)); | |
107 NaClSegmentInitialize(mbase, vbase, size, &segment); | |
108 iter = NaClInstIterCreate(decoder_tables, &segment); | |
109 if (NULL == iter) { | |
110 gprintf(gout, "Error: not enough memory\n"); | |
111 } else { | |
112 for (; NaClInstIterHasNext(iter); NaClInstIterAdvance(iter)) { | |
113 NaClInstState* state = NaClInstIterGetState(iter); | |
114 NaClInstStateInstPrint(gout, state); | |
115 if (print_internals) { | |
116 NaClInstPrintOpcodeSeq(gout, state); | |
117 NaClInstPrint(gout, state->decoder_tables, NaClInstStateInst(state)); | |
118 NaClExpVectorPrint(gout, state); | |
119 } | |
120 } | |
121 NaClInstIterDestroy(iter); | |
122 } | |
123 } | |
124 | |
125 void NaClDisassembleSegment(uint8_t* mbase, NaClPcAddress vbase, | |
126 NaClMemorySize size, NaClDisassembleFlags flags) { | |
127 if (NaClHasBit(flags, NACL_DISASSEMBLE_FLAG(NaClDisassembleFull))) { | |
128 if (NaClHasBit(flags, | |
129 NACL_DISASSEMBLE_FLAG(NaClDisassembleValidatorDecoder))) { | |
130 gprintf(NaClLogGetGio(), | |
131 "Error: can't specify both full and validator disassembly,\n" | |
132 " assuming full disassembly.\n"); | |
133 } | |
134 NaClDisassembleSegmentUsingTables(mbase, vbase, size, flags, | |
135 kNaClDecoderTables); | |
136 } else if (NaClHasBit | |
137 (flags, | |
138 NACL_DISASSEMBLE_FLAG(NaClDisassembleValidatorDecoder))) { | |
139 if (64 == NACL_TARGET_SUBARCH) { | |
140 NaClDisassembleSegmentUsingTables(mbase, vbase, size, flags, | |
141 kNaClValDecoderTables); | |
142 } else { | |
143 NCDecodeSegment(mbase, vbase, size); | |
144 } | |
145 } else { | |
146 gprintf(NaClLogGetGio(), | |
147 "Error: No decoder tables specified, can't disassemble\n"); | |
148 } | |
149 } | |
OLD | NEW |