1/*
2 * Copyright 2009-2011, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Copyright 2002-2010, Axel Dörfler, axeld@pinc-software.de.
4 * Copyright 2012-2016, Rene Gollent, rene@gollent.com.
5 * Distributed under the terms of the MIT License.
6 *
7 * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
8 * Distributed under the terms of the NewOS License.
9 */
10
11
12#include "CliDumpMemoryCommand.h"
13
14#include <ctype.h>
15#include <stdio.h>
16
17#include <AutoLocker.h>
18
19#include "CliContext.h"
20#include "CppLanguage.h"
21#include "Team.h"
22#include "TeamMemoryBlock.h"
23#include "UiUtils.h"
24#include "UserInterface.h"
25#include "Value.h"
26#include "Variable.h"
27
28
29CliDumpMemoryCommand::CliDumpMemoryCommand()
30	:
31	CliCommand("dump contents of debugged team's memory",
32		"%s [\"]address|expression[\"] [num]\n"
33		"Reads and displays the contents of memory at the target address.")
34{
35	// TODO: this should be retrieved via some indirect helper rather
36	// than instantiating the specific language directly.
37	fLanguage = new(std::nothrow) CppLanguage();
38}
39
40
41CliDumpMemoryCommand::~CliDumpMemoryCommand()
42{
43	if (fLanguage != NULL)
44		fLanguage->ReleaseReference();
45}
46
47
48void
49CliDumpMemoryCommand::Execute(int argc, const char* const* argv,
50	CliContext& context)
51{
52	if (argc < 2) {
53		PrintUsage(argv[0]);
54		return;
55	}
56
57	if (fLanguage == NULL) {
58		printf("Unable to evaluate expression: %s\n", strerror(B_NO_MEMORY));
59		return;
60	}
61
62	ExpressionInfo* info = context.GetExpressionInfo();
63
64	target_addr_t address = 0;
65	info->SetTo(argv[1]);
66
67	context.GetUserInterfaceListener()->ExpressionEvaluationRequested(
68		fLanguage, info);
69	context.WaitForEvents(CliContext::EVENT_EXPRESSION_EVALUATED);
70	if (context.IsTerminating())
71		return;
72
73	BString errorMessage;
74	ExpressionResult* result = context.GetExpressionValue();
75	if (result != NULL) {
76		if (result->Kind() == EXPRESSION_RESULT_KIND_PRIMITIVE) {
77			Value* value = result->PrimitiveValue();
78			BVariant variantValue;
79			value->ToVariant(variantValue);
80			if (variantValue.Type() == B_STRING_TYPE)
81				errorMessage.SetTo(variantValue.ToString());
82			else
83				address = variantValue.ToUInt64();
84		}
85	} else
86		errorMessage = strerror(context.GetExpressionResult());
87
88	if (!errorMessage.IsEmpty()) {
89		printf("Unable to evaluate expression: %s\n",
90			errorMessage.String());
91		return;
92	}
93
94	int32 itemSize = 0;
95	int32 displayWidth = 0;
96
97	// build the format string
98	if (strcmp(argv[0], "db") == 0) {
99		itemSize = 1;
100		displayWidth = 16;
101	} else if (strcmp(argv[0], "ds") == 0) {
102		itemSize = 2;
103		displayWidth = 8;
104	} else if (strcmp(argv[0], "dw") == 0) {
105		itemSize = 4;
106		displayWidth = 4;
107	} else if (strcmp(argv[0], "dl") == 0) {
108		itemSize = 8;
109		displayWidth = 2;
110	} else if (strcmp(argv[0], "string") == 0) {
111		itemSize = 1;
112		displayWidth = -1;
113	} else {
114		printf("dump called in an invalid way!\n");
115		return;
116	}
117
118	int32 num = 0;
119	if (argc == 3) {
120		char *remainder;
121		num = strtol(argv[2], &remainder, 0);
122		if (*remainder != '\0') {
123			printf("Error: invalid parameter \"%s\"\n", argv[2]);
124		}
125	}
126
127	if (num <= 0)
128		num = displayWidth;
129
130	TeamMemoryBlock* block = context.CurrentBlock();
131	if (block == NULL || !block->Contains(address)) {
132		context.GetUserInterfaceListener()->InspectRequested(address,
133			&context);
134		context.WaitForEvents(CliContext::EVENT_TEAM_MEMORY_BLOCK_RETRIEVED);
135		if (context.IsTerminating())
136			return;
137		block = context.CurrentBlock();
138	}
139
140	if (!strcmp(argv[0], "string")) {
141		printf("%p \"", (char*)address);
142
143		target_addr_t offset = address;
144		char c;
145		while (block->Contains(offset)) {
146			c = *(block->Data() + offset - block->BaseAddress());
147
148			if (c == '\0')
149				break;
150			if (c == '\n')
151				printf("\\n");
152			else if (c == '\t')
153				printf("\\t");
154			else {
155				if (!isprint(c))
156					c = '.';
157
158				printf("%c", c);
159			}
160			++offset;
161		}
162
163		printf("\"\n");
164	} else {
165		BString output;
166		UiUtils::DumpMemory(output, 0, block, address, itemSize, displayWidth,
167			num);
168		printf("%s\n", output.String());
169	}
170}
171