diff --git a/headers/private/debug/DebugEventStream.h b/headers/private/debug/DebugEventStream.h new file mode 100644 index 0000000000..1ebed27719 --- /dev/null +++ b/headers/private/debug/DebugEventStream.h @@ -0,0 +1,83 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef _DEBUG_EVENT_STREAM_H +#define _DEBUG_EVENT_STREAM_H + +#include + +#include + + +class BDataIO; + + +struct debug_event_stream_header { + char signature[32]; + uint32 version; + uint32 flags; + uint32 event_mask; +}; + + +// signature and version +#define B_DEBUG_EVENT_STREAM_SIGNATURE "Haiku debug events" +#define B_DEBUG_EVENT_STREAM_VERSION 1 + + +// flags +enum { + B_DEBUG_EVENT_STREAM_FLAG_HOST_ENDIAN = 0x00000001, + B_DEBUG_EVENT_STREAM_FLAG_SWAPPED_ENDIAN = 0x01000000, + + B_DEBUG_EVENT_STREAM_FLAG_ZIPPED = 0x00000002 +}; + + +class BDebugEventInputStream { +public: + BDebugEventInputStream(); + ~BDebugEventInputStream(); + + status_t SetTo(BDataIO* stream); + void Unset(); + + ssize_t ReadNextEvent( + const system_profiler_event_header** + _header); + +private: + ssize_t _Read(void* buffer, size_t size); + status_t _GetData(size_t size); + +private: + BDataIO* fStream; + uint32 fFlags; + uint32 fEventMask; + uint8* fBuffer; + size_t fBufferCapacity; + size_t fBufferSize; + size_t fBufferPosition; +}; + + +class BDebugEventOutputStream { +public: + BDebugEventOutputStream(); + ~BDebugEventOutputStream(); + + status_t SetTo(BDataIO* stream, uint32 flags, + uint32 eventMask); + void Unset(); + + status_t Write(const void* buffer, size_t size); + status_t Flush(); + +private: + BDataIO* fStream; + uint32 fFlags; +}; + + +#endif // _DEBUG_EVENT_STREAM_H diff --git a/src/kits/debug/DebugEventStream.cpp b/src/kits/debug/DebugEventStream.cpp new file mode 100644 index 0000000000..e4a25481c7 --- /dev/null +++ b/src/kits/debug/DebugEventStream.cpp @@ -0,0 +1,269 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + +#include + +#include +#include + +#include + + +#define INPUT_BUFFER_SIZE (128 * 1024) + + +BDebugEventInputStream::BDebugEventInputStream() + : + fStream(NULL), + fFlags(0), + fEventMask(0), + fBuffer(NULL), + fBufferCapacity(0), + fBufferSize(0), + fBufferPosition(0) +{ +} + + +BDebugEventInputStream::~BDebugEventInputStream() +{ + Unset(); + + free(fBuffer); +} + + +status_t +BDebugEventInputStream::SetTo(BDataIO* stream) +{ + Unset(); + + // set the new values + if (stream == NULL) + return B_BAD_VALUE; + + fStream = stream; + + // allocate a buffer + if (fBuffer == NULL) { + fBuffer = (uint8*)malloc(INPUT_BUFFER_SIZE); + if (fBuffer == NULL) { + Unset(); + return B_NO_MEMORY; + } + + fBufferCapacity = INPUT_BUFFER_SIZE; + fBufferSize = 0; + } + + fBufferPosition = 0; + + // read the header + debug_event_stream_header header; + ssize_t bytesRead = _Read(&header, sizeof(header)); + if (bytesRead < 0) { + Unset(); + return bytesRead; + } + if ((size_t)bytesRead != sizeof(header)) { + Unset(); + return B_BAD_DATA; + } + + // check the header + if (strlcpy(header.signature, B_DEBUG_EVENT_STREAM_SIGNATURE, + sizeof(header.signature)) != 0 + || header.version != B_DEBUG_EVENT_STREAM_VERSION + || (header.flags & B_DEBUG_EVENT_STREAM_FLAG_HOST_ENDIAN) == 0) { + // TODO: Support non-host endianess! + Unset(); + return B_BAD_DATA; + } + + fFlags = header.flags; + fEventMask = header.event_mask; + + return B_OK; +} + + +void +BDebugEventInputStream::Unset() +{ + fStream = NULL; + fFlags = 0; + fEventMask = 0; +} + + +ssize_t +BDebugEventInputStream::ReadNextEvent( + const system_profiler_event_header** _header) +{ + // get the next header + status_t error = _GetData(sizeof(system_profiler_event_header)); + if (error != B_OK) { + if (error == B_BAD_DATA && fBufferSize == 0) + return B_ENTRY_NOT_FOUND; + return error; + } + + system_profiler_event_header* header + = (system_profiler_event_header*)(fBuffer + fBufferPosition); + + // get the data + size_t size = header->size; + size_t totalSize = sizeof(system_profiler_event_header) + size; + if (header->size > 0) { + error = _GetData(totalSize); + if (error != B_OK) + return error; + } + + // header might have moved when getting the data + header = (system_profiler_event_header*)(fBuffer + fBufferPosition); + + // skip the event in the buffer + fBufferSize -= totalSize; + fBufferPosition += totalSize; + + *_header = header; + return size; +} + + +ssize_t +BDebugEventInputStream::_Read(void* _buffer, size_t size) +{ + uint8* buffer = (uint8*)_buffer; + size_t totalBytesRead = 0; + ssize_t bytesRead = 0; + + while (size > 0 && (bytesRead = fStream->Read(buffer, size)) > 0) { + totalBytesRead += bytesRead; + buffer += bytesRead; + size -= bytesRead; + } + + if (bytesRead < 0) + return bytesRead; + + return totalBytesRead; +} + + +status_t +BDebugEventInputStream::_GetData(size_t size) +{ + if (fBufferSize >= size) + return B_OK; + + if (size > fBufferCapacity) + return B_BUFFER_OVERFLOW; + + // move remaining data to the start of the buffer + if (fBufferSize > 0 && fBufferPosition > 0) { + memmove(fBuffer, fBuffer + fBufferPosition, fBufferSize); + fBufferPosition = 0; + } + + // read more data + ssize_t bytesRead = _Read(fBuffer + fBufferPosition, + fBufferCapacity - fBufferSize); + if (bytesRead < 0) + return bytesRead; + + fBufferSize += bytesRead; + + return fBufferSize >= size ? B_OK : B_BAD_DATA; +} + + +// #pragma mark - BDebugEventOutputStream + + +BDebugEventOutputStream::BDebugEventOutputStream() + : + fStream(NULL), + fFlags(0) +{ +} + + +BDebugEventOutputStream::~BDebugEventOutputStream() +{ + Unset(); +} + + +status_t +BDebugEventOutputStream::SetTo(BDataIO* stream, uint32 flags, uint32 eventMask) +{ + Unset(); + + // set the new values + if (stream == NULL) + return B_BAD_VALUE; + + fStream = stream; + fFlags = /*(flags & B_DEBUG_EVENT_STREAM_FLAG_ZIPPED) + |*/ B_DEBUG_EVENT_STREAM_FLAG_HOST_ENDIAN; + // TODO: Support zipped data! + + // init and write the header + debug_event_stream_header header; + memset(header.signature, 0, sizeof(header.signature)); + strlcpy(header.signature, B_DEBUG_EVENT_STREAM_SIGNATURE, + sizeof(header.signature)); + header.version = B_DEBUG_EVENT_STREAM_VERSION; + header.flags = fFlags; + header.event_mask = eventMask; + + ssize_t written = fStream->Write(&header, sizeof(header)); + if (written < 0) { + Unset(); + return written; + } + if ((size_t)written != sizeof(header)) { + Unset(); + return B_FILE_ERROR; + } + + return B_OK; +} + + +void +BDebugEventOutputStream::Unset() +{ + Flush(); + fStream = NULL; + fFlags = 0; +} + + +status_t +BDebugEventOutputStream::Write(const void* buffer, size_t size) +{ + if (size == 0) + return B_OK; + if (buffer == NULL) + return B_BAD_VALUE; + + ssize_t written = fStream->Write(buffer, size); + if (written < 0) + return written; + if ((size_t)written != size) + return B_FILE_ERROR; + + return B_OK; +} + + +status_t +BDebugEventOutputStream::Flush() +{ + return B_OK; +} diff --git a/src/kits/debug/Jamfile b/src/kits/debug/Jamfile index ef904024cb..8440c5de2e 100644 --- a/src/kits/debug/Jamfile +++ b/src/kits/debug/Jamfile @@ -12,9 +12,12 @@ SEARCH_SOURCE += [ FDirName $(SUBDIR) arch $(TARGET_ARCH) ] ; SharedLibrary libdebug.so : debug_support.cpp + DebugEventStream.cpp Image.cpp SymbolLookup.cpp # architecture specific arch_debug_support.cpp + + : be ;