xref: /haiku/src/libs/zydis/Zydis/Disassembler.c (revision 909af08f4328301fbdef1ffb41f566c3b5bec0c7)
1 /***************************************************************************************************
2 
3   Zyan Disassembler Library (Zydis)
4 
5   Original Author : Joel Hoener
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 <Zydis/Disassembler.h>
28 #include <Zycore/LibC.h>
29 
30 /* ============================================================================================== */
31 /* Internal helpers                                                                               */
32 /* ============================================================================================== */
33 
34 static ZyanStatus ZydisDisassemble(ZydisMachineMode machine_mode,
35     ZyanU64 runtime_address, const void* buffer, ZyanUSize length,
36     ZydisDisassembledInstruction *instruction, ZydisFormatterStyle style)
37 {
38     if (!buffer || !instruction)
39     {
40         return ZYAN_STATUS_INVALID_ARGUMENT;
41     }
42 
43     *instruction = (ZydisDisassembledInstruction)
44     {
45       .runtime_address = runtime_address
46     };
47 
48     // Derive the stack width from the address width.
49     ZydisStackWidth stack_width;
50     switch (machine_mode)
51     {
52     case ZYDIS_MACHINE_MODE_LONG_64:
53         stack_width = ZYDIS_STACK_WIDTH_64;
54         break;
55     case ZYDIS_MACHINE_MODE_LONG_COMPAT_32:
56     case ZYDIS_MACHINE_MODE_LEGACY_32:
57         stack_width = ZYDIS_STACK_WIDTH_32;
58         break;
59     case ZYDIS_MACHINE_MODE_LONG_COMPAT_16:
60     case ZYDIS_MACHINE_MODE_LEGACY_16:
61     case ZYDIS_MACHINE_MODE_REAL_16:
62         stack_width = ZYDIS_STACK_WIDTH_16;
63         break;
64     default:
65         return ZYAN_STATUS_INVALID_ARGUMENT;
66     }
67 
68     ZydisDecoder decoder;
69     ZYAN_CHECK(ZydisDecoderInit(&decoder, machine_mode, stack_width));
70 
71     ZydisDecoderContext ctx;
72     ZYAN_CHECK(ZydisDecoderDecodeInstruction(&decoder, &ctx, buffer, length, &instruction->info));
73     ZYAN_CHECK(ZydisDecoderDecodeOperands(&decoder, &ctx, &instruction->info,
74         instruction->operands, instruction->info.operand_count));
75 
76     ZydisFormatter formatter;
77     ZYAN_CHECK(ZydisFormatterInit(&formatter, style));
78     ZYAN_CHECK(ZydisFormatterFormatInstruction(&formatter, &instruction->info,
79         instruction->operands, instruction->info.operand_count_visible, instruction->text,
80         sizeof(instruction->text), runtime_address, ZYAN_NULL));
81 
82     return ZYAN_STATUS_SUCCESS;
83 }
84 
85 /* ============================================================================================== */
86 /* Public functions                                                                               */
87 /* ============================================================================================== */
88 
89 ZyanStatus ZydisDisassembleIntel(ZydisMachineMode machine_mode,
90     ZyanU64 runtime_address, const void* buffer, ZyanUSize length,
91     ZydisDisassembledInstruction *instruction)
92 {
93     return ZydisDisassemble(machine_mode, runtime_address, buffer, length, instruction,
94         ZYDIS_FORMATTER_STYLE_INTEL);
95 }
96 
97 ZyanStatus ZydisDisassembleATT(ZydisMachineMode machine_mode,
98     ZyanU64 runtime_address, const void* buffer, ZyanUSize length,
99     ZydisDisassembledInstruction *instruction)
100 {
101     return ZydisDisassemble(machine_mode, runtime_address, buffer, length, instruction,
102         ZYDIS_FORMATTER_STYLE_ATT);
103 }
104 
105 /* ============================================================================================== */
106