xref: /haiku/src/add-ons/kernel/debugger/disasm/disasm.cpp (revision fce4895d1884da5ae6fb299d23c735c598e690b1)
1 /*
2  * Copyright 2008, François Revol, revol@free.fr
3  * Distributed under the terms of the MIT License.
4  */
5 
6 #include <arch/debug.h>
7 #include <debug.h>
8 #include <elf.h>
9 #include <kernel.h>
10 #include <signal.h>
11 
12 #include "disasm_arch.h"
13 
14 
15 int
16 disasm_command(int argc, char **argv)
17 {
18 	int argi = 1;
19 
20 	// get back count
21 	uint64 backCount = 0;
22 	if (argi < argc && strcmp(argv[argi], "-b") == 0) {
23 		if (++argi >= argc) {
24 			print_debugger_command_usage(argv[0]);
25 			return 0;
26 		}
27 
28 		if (!evaluate_debug_expression(argv[argi++], &backCount, false))
29 			return 0;
30 	}
31 
32 	if (argi + 2 < argc) {
33 		print_debugger_command_usage(argv[0]);
34 		return 0;
35 	}
36 
37 	// get PC
38 	uint64 pc;
39 	if (argi < argc) {
40 		if (!evaluate_debug_expression(argv[argi++], &pc, false))
41 			return 0;
42 	} else {
43 		pc = (addr_t)arch_debug_get_interrupt_pc(NULL);
44 		if (pc == 0) {
45 			kprintf("Failed to get current PC!\n");
46 			return 0;
47 		}
48 	}
49 
50 	// get count
51 	uint64 count = 10;
52 	if (argi < argc) {
53 		if (!evaluate_debug_expression(argv[argi++], &count, false))
54 			return 0;
55 	}
56 
57 	// TODO: autoincrement
58 
59 	// if back count is given, compute base address
60 	addr_t baseAddress = 0;
61 	if (backCount > 0) {
62 		status_t error;
63 		const char *symbol;
64 		const char *imageName;
65 		bool exactMatch;
66 
67 		if (IS_KERNEL_ADDRESS(pc)) {
68 			error = elf_debug_lookup_symbol_address(pc, &baseAddress, &symbol,
69 				&imageName, &exactMatch);
70 		} else {
71 			error = elf_debug_lookup_user_symbol_address(
72 				debug_get_debugged_thread()->team, pc, &baseAddress, &symbol,
73 				&imageName, &exactMatch);
74 		}
75 
76 		if (error != B_OK) {
77 			baseAddress = 0;
78 			backCount = 0;
79 		}
80 	}
81 
82 	disasm_arch_dump_insns((addr_t)pc, count, baseAddress, backCount);
83 	return 0;
84 }
85 
86 
87 static status_t
88 std_ops(int32 op, ...)
89 {
90 	if (op == B_MODULE_INIT) {
91 		status_t err = disasm_arch_init();
92 		if (err != B_OK)
93 			return err;
94 
95 		err = add_debugger_command_etc("dis", disasm_command,
96 			"Print disassembly at address",
97 			"[ -b <back count> ] [ <address>  [ <count> ] ]\n"
98 			"Prints disassembly at address.\n"
99 			"  <address>        - Address at which to start disassembling\n"
100 			"                     (defaults to current PC).\n"
101 			"  <count>          - Number of instructions to disassemble\n"
102 			"                     starting at <address>.\n"
103 			"  -b <back count>  - Number of instruction to disassemble before\n"
104 			"                     <address>.\n", 0);
105 		if (err != B_OK)
106 			disasm_arch_fini();
107 		return err;
108 	} else if (op == B_MODULE_UNINIT) {
109 		remove_debugger_command("dis", disasm_command);
110 		return disasm_arch_fini();
111 	}
112 
113 	return B_BAD_VALUE;
114 }
115 
116 
117 static struct debugger_module_info sModuleInfo = {
118 	{
119 		"debugger/disasm/v1",
120 		B_KEEP_LOADED,
121 		&std_ops
122 	},
123 
124 	NULL,
125 	NULL,
126 	NULL,
127 	NULL
128 };
129 
130 module_info *modules[] = {
131 	(module_info *)&sModuleInfo,
132 	NULL
133 };
134