xref: /haiku/src/add-ons/kernel/debugger/disasm/x86/disasm_arch.cpp (revision 220d04022750f40f8bac8f01fa551211e28d04f2)
1 /*
2  * Copyright 2008, François Revol, revol@free.fr
3  * Distributed under the terms of the MIT License.
4  */
5 
6 #include <OS.h>
7 #include <KernelExport.h>
8 
9 #include <debug.h>
10 
11 #include "disasm_arch.h"
12 #include "udis86.h"
13 
14 
15 static ud_t sUDState;
16 static addr_t sCurrentReadAddress;
17 static void (*sSyntax)(ud_t *) = UD_SYN_ATT;
18 static unsigned int sVendor = UD_VENDOR_INTEL;
19 
20 
21 static int
22 read_next_byte(struct ud*)
23 {
24 	uint8_t buffer;
25 	if (debug_memcpy(B_CURRENT_TEAM, &buffer, (void*)sCurrentReadAddress, 1)
26 			!= B_OK) {
27 		kprintf("<read fault>\n");
28 		return UD_EOI;
29 	}
30 
31 	sCurrentReadAddress++;
32 	return buffer;
33 }
34 
35 
36 static void
37 setup_disassembler(addr_t where)
38 {
39 	ud_set_input_hook(&sUDState, &read_next_byte);
40 	sCurrentReadAddress	= where;
41 	ud_set_mode(&sUDState, 32);
42 	ud_set_pc(&sUDState, (uint64_t)where);
43 	ud_set_syntax(&sUDState, sSyntax);
44 	ud_set_vendor(&sUDState, sVendor);
45 }
46 
47 
48 extern "C" void
49 disasm_arch_assert(const char *condition)
50 {
51 	kprintf("assert: %s\n", condition);
52 }
53 
54 
55 status_t
56 disasm_arch_dump_insns(addr_t where, int count, addr_t baseAddress,
57 	int backCount)
58 {
59 	int skipCount = 0;
60 
61 	if (backCount > 0) {
62 		// count the instructions from base address to start address
63 		setup_disassembler(baseAddress);
64 		addr_t address = baseAddress;
65 		int baseCount = 0;
66 		int len;
67 		while (address < where && (len = ud_disassemble(&sUDState)) >= 1) {
68 			address += len;
69 			baseCount++;
70 		}
71 
72 		if (address == where) {
73 			if (baseCount > backCount)
74 				skipCount = baseCount - backCount;
75 			count += baseCount;
76 		} else
77 			baseAddress = where;
78 	} else
79 		baseAddress = where;
80 
81 	setup_disassembler(baseAddress);
82 
83 	for (int i = 0; i < count; i++) {
84 		int ret;
85 		ret = ud_disassemble(&sUDState);
86 		if (ret < 1)
87 			break;
88 
89 		if (skipCount > 0) {
90 			skipCount--;
91 			continue;
92 		}
93 
94 		addr_t address = (addr_t)ud_insn_off(&sUDState);
95 		if (address == where)
96 			kprintf("\x1b[34m");
97 
98 		// TODO: dig operands and lookup symbols
99 		kprintf("0x%08lx: %16.16s\t%s\n", address, ud_insn_hex(&sUDState),
100 			ud_insn_asm(&sUDState));
101 
102 		if (address == where)
103 			kprintf("\x1b[m");
104 	}
105 	return B_OK;
106 }
107 
108 
109 status_t
110 disasm_arch_init()
111 {
112 	ud_init(&sUDState);
113 	// XXX: check for AMD and set sVendor;
114 	return B_OK;
115 }
116 
117 status_t
118 disasm_arch_fini()
119 {
120 	return B_OK;
121 }
122 
123 
124