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
15int
16disasm_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
87static status_t
88std_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
117static 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
130module_info *modules[] = {
131	(module_info *)&sModuleInfo,
132	NULL
133};
134