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