xref: /haiku/src/apps/debugger/user_interface/cli/commands/CliDumpMemoryCommand.cpp (revision a5a3b2d9a3d95cbae71eaf371708c73a1780ac0d)
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-2014, 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 	fLanguage = new(std::nothrow) CppLanguage();
36 }
37 
38 
39 CliDumpMemoryCommand::~CliDumpMemoryCommand()
40 {
41 	if (fLanguage != NULL)
42 		fLanguage->ReleaseReference();
43 }
44 
45 
46 void
47 CliDumpMemoryCommand::Execute(int argc, const char* const* argv,
48 	CliContext& context)
49 {
50 	if (argc < 2) {
51 		PrintUsage(argv[0]);
52 		return;
53 	}
54 
55 	if (fLanguage == NULL) {
56 		printf("Unable to evaluate expression: %s\n", strerror(B_NO_MEMORY));
57 		return;
58 	}
59 
60 	ExpressionInfo* info = context.GetExpressionInfo();
61 
62 	target_addr_t address = 0;
63 	info->SetTo(argv[1]);
64 
65 	context.GetUserInterfaceListener()->ExpressionEvaluationRequested(
66 		fLanguage, info);
67 	context.WaitForEvents(CliContext::EVENT_EXPRESSION_EVALUATED);
68 	if (context.IsTerminating())
69 		return;
70 
71 	BString errorMessage;
72 	ExpressionResult* result = context.GetExpressionValue();
73 	if (result != NULL) {
74 		if (result->Kind() == EXPRESSION_RESULT_KIND_PRIMITIVE) {
75 			Value* value = result->PrimitiveValue();
76 			BVariant variantValue;
77 			value->ToVariant(variantValue);
78 			if (variantValue.Type() == B_STRING_TYPE)
79 				errorMessage.SetTo(variantValue.ToString());
80 			else
81 				address = variantValue.ToUInt64();
82 		}
83 	} else
84 		errorMessage = strerror(context.GetExpressionResult());
85 
86 	if (!errorMessage.IsEmpty()) {
87 		printf("Unable to evaluate expression: %s\n",
88 			errorMessage.String());
89 		return;
90 	}
91 
92 	int32 itemSize = 0;
93 	int32 displayWidth = 0;
94 
95 	// build the format string
96 	if (strcmp(argv[0], "db") == 0) {
97 		itemSize = 1;
98 		displayWidth = 16;
99 	} else if (strcmp(argv[0], "ds") == 0) {
100 		itemSize = 2;
101 		displayWidth = 8;
102 	} else if (strcmp(argv[0], "dw") == 0) {
103 		itemSize = 4;
104 		displayWidth = 4;
105 	} else if (strcmp(argv[0], "dl") == 0) {
106 		itemSize = 8;
107 		displayWidth = 2;
108 	} else if (strcmp(argv[0], "string") == 0) {
109 		itemSize = 1;
110 		displayWidth = -1;
111 	} else {
112 		printf("dump called in an invalid way!\n");
113 		return;
114 	}
115 
116 	int32 num = 0;
117 	if (argc == 3) {
118 		char *remainder;
119 		num = strtol(argv[2], &remainder, 0);
120 		if (*remainder != '\0') {
121 			printf("Error: invalid parameter \"%s\"\n", argv[2]);
122 		}
123 	}
124 
125 	if (num <= 0)
126 		num = displayWidth;
127 
128 	TeamMemoryBlock* block = context.CurrentBlock();
129 	if (block == NULL || !block->Contains(address)) {
130 		context.GetUserInterfaceListener()->InspectRequested(address,
131 			&context);
132 		context.WaitForEvents(CliContext::EVENT_TEAM_MEMORY_BLOCK_RETRIEVED);
133 		if (context.IsTerminating())
134 			return;
135 		block = context.CurrentBlock();
136 	}
137 
138 	if (!strcmp(argv[0], "string")) {
139 		printf("%p \"", (char*)address);
140 
141 		target_addr_t offset = address;
142 		char c;
143 		while (block->Contains(offset)) {
144 			c = *(block->Data() + offset - block->BaseAddress());
145 
146 			if (c == '\0')
147 				break;
148 			if (c == '\n')
149 				printf("\\n");
150 			else if (c == '\t')
151 				printf("\\t");
152 			else {
153 				if (!isprint(c))
154 					c = '.';
155 
156 				printf("%c", c);
157 			}
158 			++offset;
159 		}
160 
161 		printf("\"\n");
162 	} else {
163 		BString output;
164 		UiUtils::DumpMemory(output, 0, block, address, itemSize, displayWidth,
165 			num);
166 		printf("%s\n", output.String());
167 	}
168 }
169