xref: /haiku/src/add-ons/kernel/debugger/disasm/x86/disasm_arch.cpp (revision bddcee2a27042b4d8d6b0142b466f30abc886648)
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 "elf.h"
13 #include "udis86.h"
14 
15 
16 static ud_t sUDState;
17 static addr_t sCurrentReadAddress;
18 static void (*sSyntax)(ud_t *) = UD_SYN_ATT;
19 static unsigned int sVendor = UD_VENDOR_INTEL;
20 
21 
22 static int
23 read_next_byte(struct ud*)
24 {
25 	uint8_t buffer;
26 	if (debug_memcpy(B_CURRENT_TEAM, &buffer, (void*)sCurrentReadAddress, 1)
27 			!= B_OK) {
28 		kprintf("<read fault>\n");
29 		return UD_EOI;
30 	}
31 
32 	sCurrentReadAddress++;
33 	return buffer;
34 }
35 
36 
37 static const char*
38 resolve_symbol(struct ud*, uint64_t address, int64_t* offset)
39 {
40 	const char* symbolName;
41 	addr_t baseAddress;
42 	status_t error;
43 
44 	if (IS_KERNEL_ADDRESS(address)) {
45 		error = elf_debug_lookup_symbol_address(address, &baseAddress,
46 			&symbolName, NULL, NULL);
47 	} else {
48 		error = elf_debug_lookup_user_symbol_address(
49 			debug_get_debugged_thread()->team, address, &baseAddress,
50 			&symbolName, NULL, NULL);
51 	}
52 
53 	if (error != B_OK)
54 		return NULL;
55 
56 	*offset = address - baseAddress;
57 	return symbolName;
58 }
59 
60 
61 static void
62 setup_disassembler(addr_t where)
63 {
64 	ud_set_input_hook(&sUDState, &read_next_byte);
65 	sCurrentReadAddress	= where;
66 #ifdef __x86_64__
67 	ud_set_mode(&sUDState, 64);
68 #else
69 	ud_set_mode(&sUDState, 32);
70 #endif
71 	ud_set_pc(&sUDState, (uint64_t)where);
72 	ud_set_syntax(&sUDState, sSyntax);
73 	ud_set_vendor(&sUDState, sVendor);
74 	ud_set_sym_resolver(&sUDState, resolve_symbol);
75 }
76 
77 
78 extern "C" void
79 disasm_arch_assert(const char *condition)
80 {
81 	kprintf("assert: %s\n", condition);
82 }
83 
84 
85 status_t
86 disasm_arch_dump_insns(addr_t where, int count, addr_t baseAddress,
87 	int backCount)
88 {
89 	int skipCount = 0;
90 
91 	if (backCount > 0) {
92 		// count the instructions from base address to start address
93 		setup_disassembler(baseAddress);
94 		addr_t address = baseAddress;
95 		int baseCount = 0;
96 		int len;
97 		while (address < where && (len = ud_disassemble(&sUDState)) >= 1) {
98 			address += len;
99 			baseCount++;
100 		}
101 
102 		if (address == where) {
103 			if (baseCount > backCount)
104 				skipCount = baseCount - backCount;
105 			count += baseCount;
106 		} else
107 			baseAddress = where;
108 	} else
109 		baseAddress = where;
110 
111 	setup_disassembler(baseAddress);
112 
113 	for (int i = 0; i < count; i++) {
114 		int ret;
115 		ret = ud_disassemble(&sUDState);
116 		if (ret < 1)
117 			break;
118 
119 		if (skipCount > 0) {
120 			skipCount--;
121 			continue;
122 		}
123 
124 		addr_t address = (addr_t)ud_insn_off(&sUDState);
125 		if (address == where)
126 			kprintf("\x1b[34m");
127 
128 		// TODO: dig operands and lookup symbols
129 		kprintf("0x%08lx: %16.16s\t%s\n", address, ud_insn_hex(&sUDState),
130 			ud_insn_asm(&sUDState));
131 
132 		if (address == where)
133 			kprintf("\x1b[m");
134 	}
135 	return B_OK;
136 }
137 
138 
139 status_t
140 disasm_arch_init()
141 {
142 	ud_init(&sUDState);
143 	// XXX: check for AMD and set sVendor;
144 	return B_OK;
145 }
146 
147 
148 status_t
149 disasm_arch_fini()
150 {
151 	return B_OK;
152 }
153 
154 
155