Defined a simple file format to store debug event streams as generated by the

system profiling interface and added classes BDebugEvent{Input,Ouput}Stream for
reading/writing those files.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@30244 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold 2009-04-18 17:38:21 +00:00
parent 5b2f0f33f9
commit 4db202f5f4
3 changed files with 355 additions and 0 deletions

View File

@ -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 <SupportDefs.h>
#include <system_profiler_defs.h>
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

View File

@ -0,0 +1,269 @@
/*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include <DebugEventStream.h>
#include <stdlib.h>
#include <string.h>
#include <DataIO.h>
#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;
}

View File

@ -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
;