xref: /haiku/src/kits/debug/debug_support.cpp (revision 0b2dbe7d46ee888392907c60131b7f7652314175)
1 /*
2  * Copyright 2005, Ingo Weinhold, bonefish@users.sf.net.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include <string.h>
8 
9 #include <debug_support.h>
10 
11 #include "arch_debug_support.h"
12 
13 
14 // init_debug_context
15 status_t
16 init_debug_context(debug_context *context, port_id nubPort)
17 {
18 	if (!context || nubPort < 0)
19 		return B_BAD_VALUE;
20 
21 	context->nub_port = nubPort;
22 
23 	// create the reply port
24 	context->reply_port = create_port(1, "debug reply port");
25 	if (context->reply_port < 0)
26 		return context->reply_port;
27 
28 	return B_OK;
29 }
30 
31 // destroy_debug_context
32 void
33 destroy_debug_context(debug_context *context)
34 {
35 	if (context) {
36 		if (context->reply_port >= 0)
37 			delete_port(context->reply_port);
38 	}
39 }
40 
41 // send_debug_message
42 status_t
43 send_debug_message(debug_context *context, int32 messageCode,
44 	const void *message, int32 messageSize, void *reply, int32 replySize)
45 {
46 	if (!context)
47 		return B_BAD_VALUE;
48 
49 	// send message
50 	while (true) {
51 		status_t result = write_port(context->nub_port, messageCode, message,
52 			messageSize);
53 		if (result == B_OK)
54 			break;
55 		if (result != B_INTERRUPTED)
56 			return result;
57 	}
58 
59 	if (!reply)
60 		return B_OK;
61 
62 	// read reply
63 	while (true) {
64 		int32 code;
65 		ssize_t bytesRead = read_port(context->reply_port, &code, reply,
66 			replySize);
67 		if (bytesRead > 0)
68 			return B_OK;
69 		if (bytesRead != B_INTERRUPTED)
70 			return bytesRead;
71 	}
72 }
73 
74 // debug_read_memory_partial
75 ssize_t
76 debug_read_memory_partial(debug_context *context, const void *address,
77 	void *buffer, size_t size)
78 {
79 	if (!context)
80 		return B_BAD_VALUE;
81 
82 	if (size == 0)
83 		return 0;
84 	if (size > B_MAX_READ_WRITE_MEMORY_SIZE)
85 		size = B_MAX_READ_WRITE_MEMORY_SIZE;
86 
87 	// prepare the message
88 	debug_nub_read_memory message;
89 	message.reply_port = context->reply_port;
90 	message.address = (void*)address;
91 	message.size = size;
92 
93 	// send the message
94 	debug_nub_read_memory_reply reply;
95 	status_t error = send_debug_message(context, B_DEBUG_MESSAGE_READ_MEMORY,
96 		&message, sizeof(message), &reply, sizeof(reply));
97 
98 	if (error != B_OK)
99 		return error;
100 	if (reply.error != B_OK)
101 		return reply.error;
102 
103 	// copy the read data
104 	memcpy(buffer, reply.data, reply.size);
105 	return reply.size;
106 }
107 
108 // debug_read_memory
109 ssize_t
110 debug_read_memory(debug_context *context, const void *_address, void *_buffer,
111 	size_t size)
112 {
113 	const char *address = (const char *)_address;
114 	char *buffer = (char*)_buffer;
115 
116 	// check parameters
117 	if (!context || !address || !buffer)
118 		return B_BAD_VALUE;
119 	if (size == 0)
120 		return 0;
121 
122 	// read as long as we can read data
123 	ssize_t sumRead = 0;
124 	while (size > 0) {
125 		ssize_t bytesRead = debug_read_memory_partial(context, address, buffer,
126 			size);
127 		if (bytesRead < 0) {
128 			if (sumRead > 0)
129 				return sumRead;
130 			return bytesRead;
131 		}
132 
133 		address += bytesRead;
134 		buffer += bytesRead;
135 		sumRead += bytesRead;
136 		size -= bytesRead;
137 	}
138 
139 	return sumRead;
140 }
141 
142 // debug_read_string
143 ssize_t
144 debug_read_string(debug_context *context, const void *_address, char *buffer,
145 	size_t size)
146 {
147 	const char *address = (const char *)_address;
148 
149 	// check parameters
150 	if (!context || !address || !buffer || size == 0)
151 		return B_BAD_VALUE;
152 
153 	// read as long as we can read data
154 	ssize_t sumRead = 0;
155 	while (size > 0) {
156 		ssize_t bytesRead = debug_read_memory_partial(context, address, buffer,
157 			size);
158 		if (bytesRead < 0) {
159 			// always null-terminate what we have (even, if it is an empty
160 			// string) and be done
161 			*buffer = '\0';
162 			return (sumRead > 0 ? sumRead : bytesRead);
163 		}
164 
165 		int chunkSize = strnlen(buffer, bytesRead);
166 		if (chunkSize < bytesRead) {
167 			// we found a terminating null
168 			sumRead += chunkSize;
169 			return sumRead;
170 		}
171 
172 		address += bytesRead;
173 		buffer += bytesRead;
174 		sumRead += bytesRead;
175 		size -= bytesRead;
176 	}
177 
178 	// We filled the complete buffer without encountering a terminating null
179 	// replace the last char. But nevertheless return the full size to indicate
180 	// that the buffer was too small.
181 	buffer[-1] = '\0';
182 
183 	return sumRead;
184 }
185 
186 
187 status_t
188 debug_get_cpu_state(debug_context *context, thread_id thread,
189 	debug_debugger_message *messageCode, debug_cpu_state *cpuState)
190 {
191 	if (!context || !cpuState)
192 		return B_BAD_VALUE;
193 
194 	// prepare message
195 	debug_nub_get_cpu_state message;
196 	message.reply_port = context->reply_port;
197 	message.thread = thread;
198 
199 	// send message
200 	debug_nub_get_cpu_state_reply reply;
201 	status_t error = send_debug_message(context, B_DEBUG_MESSAGE_GET_CPU_STATE,
202 		&message, sizeof(message), &reply, sizeof(reply));
203 	if (error == B_OK)
204 		error = reply.error;
205 
206 	// get state
207 	if (error == B_OK) {
208 		*cpuState = reply.cpu_state;
209 		if (messageCode)
210 			*messageCode = reply.message;
211 	}
212 
213 	return error;
214 }
215 
216 
217 status_t
218 debug_get_instruction_pointer(debug_context *context, thread_id thread,
219 	void **ip, void **stackFrameAddress)
220 {
221 	if (!context || !ip || !stackFrameAddress)
222 		return B_BAD_VALUE;
223 
224 	return arch_debug_get_instruction_pointer(context, thread, ip,
225 		stackFrameAddress);
226 }
227 
228 
229 status_t
230 debug_get_stack_frame(debug_context *context, void *stackFrameAddress,
231 	debug_stack_frame_info *stackFrameInfo)
232 {
233 	if (!context || !stackFrameAddress || !stackFrameInfo)
234 		return B_BAD_VALUE;
235 
236 	return arch_debug_get_stack_frame(context, stackFrameAddress,
237 		stackFrameInfo);
238 }
239