/* * Copyright 2005-2011, Ingo Weinhold, ingo_weinhold@gmx.de. * Distributed under the terms of the MIT License. */ #include #include #include #include #include "MemoryReader.h" MemoryReader::MemoryReader() : fNubPort(-1), fReplyPort(-1) { } MemoryReader::~MemoryReader() { if (fReplyPort >= 0) delete_port(fReplyPort); } status_t MemoryReader::Init(port_id nubPort) { if (fReplyPort >= 0) delete_port(fReplyPort); fNubPort = nubPort; fReplyPort = create_port(1, "memory reader reply"); if (fReplyPort < 0) { fprintf(stderr, "Failed to create memory reader reply port: %s\n", strerror(fReplyPort)); return fReplyPort; } return B_OK; } status_t MemoryReader::Read(void *_address, void *_buffer, int32 size, int32 &bytesRead) { char *address = (char*)_address; char *buffer = (char*)_buffer; bytesRead = 0; while (size > 0) { int32 toRead = size; if (toRead > B_MAX_READ_WRITE_MEMORY_SIZE) toRead = B_MAX_READ_WRITE_MEMORY_SIZE; int32 actuallyRead = 0; status_t error = _Read(address, buffer, toRead, actuallyRead); // If reading fails, we only fail, if we haven't read anything yet. if (error != B_OK) { if (bytesRead > 0) return B_OK; return error; } bytesRead += actuallyRead; address += actuallyRead; buffer += actuallyRead; size -= actuallyRead; } return B_OK; } status_t MemoryReader::_Read(void *address, void *buffer, int32 size, int32 &bytesRead) { // prepare message debug_nub_read_memory message; message.reply_port = fReplyPort; message.address = address; message.size = size; // send message while (true) { status_t error = write_port(fNubPort, B_DEBUG_MESSAGE_READ_MEMORY, &message, sizeof(message)); if (error == B_OK) break; if (error != B_INTERRUPTED) return error; } // get reply int32 code; debug_nub_read_memory_reply reply; while (true) { ssize_t bytesRead = read_port(fReplyPort, &code, &reply, sizeof(reply)); if (bytesRead > 0) break; if (bytesRead != B_INTERRUPTED) return bytesRead; } if (reply.error != B_OK) return reply.error; bytesRead = reply.size; memcpy(buffer, reply.data, bytesRead); return B_OK; }