Segment.c (6993B)
1 /*************************************************************************************************** 2 3 Zyan Disassembler Library (Zydis) 4 5 Original Author : Florian Bernd 6 7 * Permission is hereby granted, free of charge, to any person obtaining a copy 8 * of this software and associated documentation files (the "Software"), to deal 9 * in the Software without restriction, including without limitation the rights 10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 * copies of the Software, and to permit persons to whom the Software is 12 * furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included in all 15 * copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 * SOFTWARE. 24 25 ***************************************************************************************************/ 26 27 #include <Zycore/LibC.h> 28 #include <Zydis/Segment.h> 29 30 /* ============================================================================================== */ 31 /* Exported functions */ 32 /* ============================================================================================== */ 33 34 ZyanStatus ZydisGetInstructionSegments(const ZydisDecodedInstruction* instruction, 35 ZydisInstructionSegments* segments) 36 { 37 if (!instruction || !segments) 38 { 39 return ZYAN_STATUS_INVALID_ARGUMENT; 40 } 41 42 ZYAN_MEMSET(segments, 0, sizeof(*segments)); 43 44 // Legacy prefixes and `REX` 45 if (instruction->raw.prefix_count) 46 { 47 const ZyanU8 rex_offset = (instruction->attributes & ZYDIS_ATTRIB_HAS_REX) ? 1 : 0; 48 if (!rex_offset || (instruction->raw.prefix_count > 1)) 49 { 50 segments->segments[segments->count ].type = ZYDIS_INSTR_SEGMENT_PREFIXES; 51 segments->segments[segments->count ].offset = 0; 52 segments->segments[segments->count++].size = 53 instruction->raw.prefix_count - rex_offset; 54 } 55 if (rex_offset) 56 { 57 segments->segments[segments->count ].type = ZYDIS_INSTR_SEGMENT_REX; 58 segments->segments[segments->count ].offset = 59 instruction->raw.prefix_count - rex_offset; 60 segments->segments[segments->count++].size = 1; 61 } 62 } 63 64 // Encoding prefixes 65 ZydisInstructionSegment segment_type = ZYDIS_INSTR_SEGMENT_NONE; 66 ZyanU8 segment_offset = 0; 67 ZyanU8 segment_size = 0; 68 switch (instruction->encoding) 69 { 70 case ZYDIS_INSTRUCTION_ENCODING_XOP: 71 segment_type = ZYDIS_INSTR_SEGMENT_XOP; 72 segment_offset = instruction->raw.xop.offset; 73 segment_size = 3; 74 break; 75 case ZYDIS_INSTRUCTION_ENCODING_VEX: 76 segment_type = ZYDIS_INSTR_SEGMENT_VEX; 77 segment_offset = instruction->raw.vex.offset; 78 segment_size = instruction->raw.vex.size; 79 break; 80 case ZYDIS_INSTRUCTION_ENCODING_EVEX: 81 segment_type = ZYDIS_INSTR_SEGMENT_EVEX; 82 segment_offset = instruction->raw.evex.offset; 83 segment_size = 4; 84 break; 85 case ZYDIS_INSTRUCTION_ENCODING_MVEX: 86 segment_type = ZYDIS_INSTR_SEGMENT_MVEX; 87 segment_offset = instruction->raw.mvex.offset; 88 segment_size = 4; 89 break; 90 default: 91 break; 92 } 93 if (segment_type) 94 { 95 segments->segments[segments->count ].type = segment_type; 96 segments->segments[segments->count ].offset = segment_offset; 97 segments->segments[segments->count++].size = segment_size; 98 } 99 100 // Opcode 101 segment_size = 1; 102 if ((instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_LEGACY) || 103 (instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_3DNOW)) 104 { 105 switch (instruction->opcode_map) 106 { 107 case ZYDIS_OPCODE_MAP_DEFAULT: 108 break; 109 case ZYDIS_OPCODE_MAP_0F: 110 ZYAN_FALLTHROUGH; 111 case ZYDIS_OPCODE_MAP_0F0F: 112 segment_size = 2; 113 break; 114 case ZYDIS_OPCODE_MAP_0F38: 115 ZYAN_FALLTHROUGH; 116 case ZYDIS_OPCODE_MAP_0F3A: 117 segment_size = 3; 118 break; 119 default: 120 ZYAN_UNREACHABLE; 121 } 122 } 123 segments->segments[segments->count ].type = ZYDIS_INSTR_SEGMENT_OPCODE; 124 if (segments->count) 125 { 126 segments->segments[segments->count].offset = 127 segments->segments[segments->count - 1].offset + 128 segments->segments[segments->count - 1].size; 129 } else 130 { 131 segments->segments[segments->count].offset = 0; 132 } 133 segments->segments[segments->count++].size = segment_size; 134 135 // ModRM 136 if (instruction->attributes & ZYDIS_ATTRIB_HAS_MODRM) 137 { 138 segments->segments[segments->count ].type = ZYDIS_INSTR_SEGMENT_MODRM; 139 segments->segments[segments->count ].offset = instruction->raw.modrm.offset; 140 segments->segments[segments->count++].size = 1; 141 } 142 143 // SIB 144 if (instruction->attributes & ZYDIS_ATTRIB_HAS_SIB) 145 { 146 segments->segments[segments->count ].type = ZYDIS_INSTR_SEGMENT_SIB; 147 segments->segments[segments->count ].offset = instruction->raw.sib.offset; 148 segments->segments[segments->count++].size = 1; 149 } 150 151 // Displacement 152 if (instruction->raw.disp.size) 153 { 154 segments->segments[segments->count ].type = ZYDIS_INSTR_SEGMENT_DISPLACEMENT; 155 segments->segments[segments->count ].offset = instruction->raw.disp.offset; 156 segments->segments[segments->count++].size = instruction->raw.disp.size / 8; 157 } 158 159 // Immediates 160 for (ZyanU8 i = 0; i < 2; ++i) 161 { 162 if (instruction->raw.imm[i].size) 163 { 164 segments->segments[segments->count ].type = ZYDIS_INSTR_SEGMENT_IMMEDIATE; 165 segments->segments[segments->count ].offset = instruction->raw.imm[i].offset; 166 segments->segments[segments->count++].size = instruction->raw.imm[i].size / 8; 167 } 168 } 169 170 if (instruction->encoding == ZYDIS_INSTRUCTION_ENCODING_3DNOW) 171 { 172 segments->segments[segments->count].type = ZYDIS_INSTR_SEGMENT_OPCODE; 173 segments->segments[segments->count].offset = instruction->length -1; 174 segments->segments[segments->count++].size = 1; 175 } 176 177 return ZYAN_STATUS_SUCCESS; 178 } 179 180 /* ---------------------------------------------------------------------------------------------- */ 181 182 /* ============================================================================================== */