xref: /haiku/src/apps/debugger/user_interface/cli/commands/CliDumpMemoryCommand.cpp (revision b08627f310bb2e80bca50176e7a758182384735a)
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 
29 CliDumpMemoryCommand::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 
41 CliDumpMemoryCommand::~CliDumpMemoryCommand()
42 {
43 	if (fLanguage != NULL)
44 		fLanguage->ReleaseReference();
45 }
46 
47 
48 void
49 CliDumpMemoryCommand::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