xref: /haiku/src/bin/debug/strace/MemoryReader.cpp (revision 83b1a68c52ba3e0e8796282759f694b7fdddf06d)
1 /*
2  * Copyright 2005-2011, Ingo Weinhold, ingo_weinhold@gmx.de.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 
11 #include <debugger.h>
12 
13 #include "MemoryReader.h"
14 
15 
16 MemoryReader::MemoryReader()
17 	:
18 	fNubPort(-1),
19 	fReplyPort(-1)
20 {
21 }
22 
23 
24 MemoryReader::~MemoryReader()
25 {
26 	if (fReplyPort >= 0)
27 		delete_port(fReplyPort);
28 }
29 
30 
31 status_t
32 MemoryReader::Init(port_id nubPort)
33 {
34 	if (fReplyPort >= 0)
35 		delete_port(fReplyPort);
36 
37 	fNubPort = nubPort;
38 
39 	fReplyPort = create_port(1, "memory reader reply");
40 	if (fReplyPort < 0) {
41 		fprintf(stderr, "Failed to create memory reader reply port: %s\n",
42 			strerror(fReplyPort));
43 		return fReplyPort;
44 	}
45 
46 	return B_OK;
47 }
48 
49 
50 status_t
51 MemoryReader::Read(void *_address, void *_buffer, int32 size, int32 &bytesRead)
52 {
53 	char *address = (char*)_address;
54 	char *buffer = (char*)_buffer;
55 	bytesRead = 0;
56 
57 	while (size > 0) {
58 		int32 toRead = size;
59 		if (toRead > B_MAX_READ_WRITE_MEMORY_SIZE)
60 			toRead = B_MAX_READ_WRITE_MEMORY_SIZE;
61 
62 		int32 actuallyRead = 0;
63 		status_t error = _Read(address, buffer, toRead, actuallyRead);
64 
65 		// If reading fails, we only fail, if we haven't read anything yet.
66 		if (error != B_OK) {
67 			if (bytesRead > 0)
68 				return B_OK;
69 			return error;
70 		}
71 
72 		bytesRead += actuallyRead;
73 		address += actuallyRead;
74 		buffer += actuallyRead;
75 		size -= actuallyRead;
76 	}
77 
78 	return B_OK;
79 }
80 
81 
82 status_t
83 MemoryReader::_Read(void *address, void *buffer, int32 size, int32 &bytesRead)
84 {
85 	// prepare message
86 	debug_nub_read_memory message;
87 	message.reply_port = fReplyPort;
88 	message.address = address;
89 	message.size = size;
90 
91 	// send message
92 	while (true) {
93 		status_t error = write_port(fNubPort, B_DEBUG_MESSAGE_READ_MEMORY,
94 			&message, sizeof(message));
95 		if (error == B_OK)
96 			break;
97 		if (error != B_INTERRUPTED)
98 			return error;
99 	}
100 
101 	// get reply
102 	int32 code;
103 	debug_nub_read_memory_reply reply;
104 	while (true) {
105 		ssize_t bytesRead = read_port(fReplyPort, &code, &reply, sizeof(reply));
106 		if (bytesRead > 0)
107 			break;
108 		if (bytesRead != B_INTERRUPTED)
109 			return bytesRead;
110 	}
111 
112 	if (reply.error != B_OK)
113 		return reply.error;
114 
115 	bytesRead = reply.size;
116 	memcpy(buffer, reply.data, bytesRead);
117 
118 	return B_OK;
119 }
120