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
16MemoryReader::MemoryReader()
17	:
18	fNubPort(-1),
19	fReplyPort(-1)
20{
21}
22
23
24MemoryReader::~MemoryReader()
25{
26	if (fReplyPort >= 0)
27		delete_port(fReplyPort);
28}
29
30
31status_t
32MemoryReader::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
50status_t
51MemoryReader::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
82status_t
83MemoryReader::_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