* Moved strace source into separate subdirectory.

* Now syscall names and parameters are printed. const char* parameters
  and return values are retrieved from the client and printed as string.
* Missing are still color output (does consoled support that?) and
  searching for given commands in the PATH. Nothing besides the standard
  mode has been tested yet, so it's probably not working.


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@11345 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2005-02-11 05:09:36 +00:00
parent 20be402385
commit 39c9d198ea
8 changed files with 1135 additions and 0 deletions
+33
View File
@@ -0,0 +1,33 @@
SubDir OBOS_TOP src apps bin strace ;
# We need our objects dir in the include paths.
SetupObjectsDir ;
UseArchHeaders $(OBOS_ARCH) ;
UsePrivateHeaders kernel ;
UsePrivateHeaders shared ;
local straceSources = strace.cpp MemoryReader.cpp TypeHandler.cpp ;
local straceSyscallsIndices
= 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ;
local straceSyscallsSource = [ FGristFiles strace_syscalls.cpp ] ;
local straceSyscallsObjects ;
local i ;
for i in $(straceSyscallsIndices) {
local object = [ FGristFiles strace_syscalls$(i).o ] ;
straceSyscallsObjects += $(object) ;
Object $(object) : $(straceSyscallsSource) ;
ObjectDefines $(object)
: GET_SYSCALLS=get_syscalls$(i) SYSCALLS_CHUNK_$(i) ;
}
BinCommand strace : $(straceSources)
: $(straceSyscallsObjects) libroot.so libstdc++.r4.so ;
# We need to specify the dependency on the generated syscalls file explicitly.
Includes $(straceSyscallsSource) : <syscalls>strace_syscalls.h ;
+105
View File
@@ -0,0 +1,105 @@
/*
* Copyright 2005, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#include <stdio.h>
#include <string.h>
#include <debugger.h>
#include "MemoryReader.h"
// constructor
MemoryReader::MemoryReader(port_id nubPort)
: fNubPort(nubPort),
fReplyPort(-1)
{
fReplyPort = create_port(1, "memory reader reply");
if (fReplyPort < 0) {
fprintf(stderr, "Failed to create memory reader reply port: %s\n",
strerror(fReplyPort));
exit(1);
}
}
// constructor
MemoryReader::~MemoryReader()
{
if (fReplyPort >= 0)
delete_port(fReplyPort);
}
// Read
status_t
MemoryReader::Read(void *_address, void *_buffer, int32 size, int32 &bytesRead)
{
char *address = (char*)_address;
char *buffer = (char*)_buffer;
bytesRead = 0;
// If the region to be read crosses page boundaries, we split it up into
// smaller chunks.
while (size > 0) {
int32 toRead = size;
if (toRead > B_MAX_READ_WRITE_MEMORY_SIZE)
toRead = B_MAX_READ_WRITE_MEMORY_SIZE;
if ((uint32)address % B_PAGE_SIZE + toRead > B_PAGE_SIZE)
toRead = B_PAGE_SIZE - (uint32)address % B_PAGE_SIZE;
status_t error = _Read(address, buffer, toRead);
// If reading fails, we only fail, if we haven't read something yet.
if (error != B_OK) {
if (bytesRead > 0)
return B_OK;
return error;
}
bytesRead += toRead;
address += toRead;
buffer += toRead;
size -= toRead;
}
return B_OK;
}
// _Read
status_t
MemoryReader::_Read(void *address, void *buffer, int32 size)
{
// 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;
memcpy(buffer, reply.data, size);
return B_OK;
}
+25
View File
@@ -0,0 +1,25 @@
/*
* Copyright 2005, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef STRACE_MEMORY_READER_H
#define STRACE_MEMORY_READER_H
#include <OS.h>
class MemoryReader {
public:
MemoryReader(port_id nubPort);
~MemoryReader();
status_t Read(void *address, void *buffer, int32 size, int32 &bytesRead);
private:
status_t _Read(void *address, void *buffer, int32 size);
port_id fNubPort;
port_id fReplyPort;
};
#endif // STRACE_MEMORY_READER_H
+104
View File
@@ -0,0 +1,104 @@
/*
* Copyright 2005, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef STRACE_SYSCALL_H
#define STRACE_SYSCALL_H
#include <string>
#include <vector>
#include <SupportDefs.h>
#include "TypeHandler.h"
// Type
class Type {
public:
Type(TypeHandler *handler) : fHandler(handler) {}
void SetHandler(TypeHandler *handler)
{
delete fHandler;
fHandler = handler;
}
TypeHandler *Handler() const { return fHandler; }
private:
TypeHandler *fHandler;
};
// Parameter
class Parameter : public Type {
public:
Parameter(string name, int32 offset, TypeHandler *handler)
: Type(handler),
fName(name),
fOffset(offset)
{
}
const string &Name() const { return fName; }
int32 Offset() const { return fOffset; }
private:
string fName;
int32 fOffset;
};
// Syscall
class Syscall {
public:
Syscall(string name, TypeHandler *returnTypeHandler)
: fName(name), fReturnType(new Type(returnTypeHandler)) {}
const string &Name() const
{
return fName;
}
Type *ReturnType() const
{
return fReturnType;
}
void AddParameter(Parameter *parameter)
{
fParameters.push_back(parameter);
}
void AddParameter(string name, int32 offset, TypeHandler *handler)
{
AddParameter(new Parameter(name, offset, handler));
}
int32 CountParameters() const
{
return fParameters.size();
}
Parameter *ParameterAt(int32 index) const
{
return fParameters[index];
}
Parameter *GetParameter(string name) const
{
int32 count = CountParameters();
for (int32 i = 0; i < count; i++) {
Parameter *parameter = ParameterAt(i);
if (parameter->Name() == name)
return parameter;
}
return NULL;
}
private:
string fName;
Type *fReturnType;
vector<Parameter*> fParameters;
};
#endif // STRACE_SYSCALL_H
+251
View File
@@ -0,0 +1,251 @@
/*
* Copyright 2005, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#include "MemoryReader.h"
#include "TypeHandler.h"
// complete specializations
// void
template<>
string
TypeHandlerImpl<void>::GetParameterValue(const void *address, bool getContents,
MemoryReader &reader)
{
return "void";
}
template<>
string
TypeHandlerImpl<void>::GetReturnValue(uint64 value, bool getContents,
MemoryReader &reader)
{
return "";
}
// bool
template<>
string
TypeHandlerImpl<bool>::GetParameterValue(const void *address, bool getContents,
MemoryReader &reader)
{
return (*(align_t*)address ? "true" : "false");
}
template<>
string
TypeHandlerImpl<bool>::GetReturnValue(uint64 value, bool getContents,
MemoryReader &reader)
{
return (value ? "true" : "false");
}
// char
template<>
string
TypeHandlerImpl<char>::GetParameterValue(const void *address, bool getContents,
MemoryReader &reader)
{
return get_number_value<char>(address, "0x%x");
}
template<>
string
TypeHandlerImpl<char>::GetReturnValue(uint64 value, bool getContents,
MemoryReader &reader)
{
return get_number_value<char>(value, "0x%x");
}
// short
template<>
string
TypeHandlerImpl<short>::GetParameterValue(const void *address, bool getContents,
MemoryReader &reader)
{
return get_number_value<short>(address, "0x%x");
}
template<>
string
TypeHandlerImpl<short>::GetReturnValue(uint64 value, bool getContents,
MemoryReader &reader)
{
return get_number_value<short>(value, "0x%x");
}
// unsigned short
template<>
string
TypeHandlerImpl<unsigned short>::GetParameterValue(const void *address,
bool getContents, MemoryReader &reader)
{
return get_number_value<unsigned short>(address, "0x%x");
}
template<>
string
TypeHandlerImpl<unsigned short>::GetReturnValue(uint64 value, bool getContents,
MemoryReader &reader)
{
return get_number_value<unsigned short>(value, "0x%x");
}
// int
template<>
string
TypeHandlerImpl<int>::GetParameterValue(const void *address, bool getContents,
MemoryReader &reader)
{
return get_number_value<int>(address, "0x%x");
}
template<>
string
TypeHandlerImpl<int>::GetReturnValue(uint64 value, bool getContents,
MemoryReader &reader)
{
return get_number_value<int>(value, "0x%x");
}
// unsigned int
template<>
string
TypeHandlerImpl<unsigned int>::GetParameterValue(const void *address,
bool getContents, MemoryReader &reader)
{
return get_number_value<unsigned int>(address, "0x%x");
}
template<>
string
TypeHandlerImpl<unsigned int>::GetReturnValue(uint64 value, bool getContents,
MemoryReader &reader)
{
return get_number_value<unsigned int>(value, "0x%x");
}
// long
template<>
string
TypeHandlerImpl<long>::GetParameterValue(const void *address, bool getContents,
MemoryReader &reader)
{
return get_number_value<long>(address, "0x%lx");
}
template<>
string
TypeHandlerImpl<long>::GetReturnValue(uint64 value, bool getContents,
MemoryReader &reader)
{
return get_number_value<long>(value, "0x%lx");
}
// unsigned long
template<>
string
TypeHandlerImpl<unsigned long>::GetParameterValue(const void *address,
bool getContents, MemoryReader &reader)
{
return get_number_value<unsigned long>(address, "0x%lx");
}
template<>
string
TypeHandlerImpl<unsigned long>::GetReturnValue(uint64 value, bool getContents,
MemoryReader &reader)
{
return get_number_value<unsigned long>(value, "0x%lx");
}
// long long
template<>
string
TypeHandlerImpl<long long>::GetParameterValue(const void *address,
bool getContents, MemoryReader &reader)
{
return get_number_value<long long>(address, "0x%llx");
}
template<>
string
TypeHandlerImpl<long long>::GetReturnValue(uint64 value, bool getContents,
MemoryReader &reader)
{
return get_number_value<long long>(value, "0x%llx");
}
// unsigned long
template<>
string
TypeHandlerImpl<unsigned long long>::GetParameterValue(const void *address,
bool getContents, MemoryReader &reader)
{
return get_number_value<unsigned long>(address, "0x%llx");
}
template<>
string
TypeHandlerImpl<unsigned long long>::GetReturnValue(uint64 value,
bool getContents, MemoryReader &reader)
{
return get_number_value<unsigned long long>(value, "0x%llx");
}
// read_string
static
string
read_string(MemoryReader &reader, void *data)
{
char buffer[256];
int32 bytesRead;
status_t error = reader.Read(data, buffer, sizeof(buffer), bytesRead);
if (error == B_OK) {
// return string("\"") + string(buffer, bytesRead) + "\"";
//string result("\"");
//result += string(buffer, bytesRead);
//result += "\"";
//return result;
// TODO: Unless I'm missing something obvious, our STL string class is broken.
// The appended "\"" doesn't appear in either of the above cases.
int32 len = strnlen(buffer, sizeof(buffer));
char largeBuffer[259];
largeBuffer[0] = '"';
memcpy(largeBuffer + 1, buffer, len);
largeBuffer[len + 1] = '"';
largeBuffer[len + 2] = '\0';
return largeBuffer;
}
return get_pointer_value(&data) + " (" + strerror(error) + ")";
}
// const char*
template<>
string
TypeHandlerImpl<const char*>::GetParameterValue(const void *address,
bool getContents, MemoryReader &reader)
{
void *data = *(void**)address;
if (getContents && data)
return read_string(reader, data);
return get_pointer_value(&data);
}
template<>
string
TypeHandlerImpl<const char*>::GetReturnValue(uint64 value,
bool getContents, MemoryReader &reader)
{
void *data = (void*)value;
if (getContents && data)
return read_string(reader, data);
return get_pointer_value(&data);
}
+124
View File
@@ -0,0 +1,124 @@
/*
* Copyright 2005, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef STRACE_TYPE_HANDLER_H
#define STRACE_TYPE_HANDLER_H
#include <string>
#include <arch_config.h>
#include <SupportDefs.h>
class MemoryReader;
typedef FUNCTION_CALL_PARAMETER_ALIGNMENT_TYPE align_t;
// TypeHandler
class TypeHandler {
public:
TypeHandler() {}
virtual ~TypeHandler() {}
virtual string GetParameterValue(const void *address, bool getContents,
MemoryReader &reader) = 0;
virtual string GetReturnValue(uint64 value, bool getContents,
MemoryReader &reader) = 0;
};
// TypeHandlerImpl
template<typename Type>
class TypeHandlerImpl : public TypeHandler {
public:
virtual string GetParameterValue(const void *address, bool getContents,
MemoryReader &reader);
virtual string GetReturnValue(uint64 value, bool getContents,
MemoryReader &reader);
};
// TypeHandlerImpl
template<typename Type>
class TypeHandlerImpl<Type*> : public TypeHandler {
public:
virtual string GetParameterValue(const void *address, bool getContents,
MemoryReader &reader);
virtual string GetReturnValue(uint64 value, bool getContents,
MemoryReader &reader);
};
//// TypeHandlerImpl
//template<>
//class TypeHandlerImpl<const char*> : public TypeHandler {
//public:
// virtual string GetParameterValue(const void *address, bool getContents,
// MemoryReader &reader);
//
// virtual string GetReturnValue(uint64 value, bool getContents,
// MemoryReader &reader);
//};
// get_number_value
template<typename value_t>
static inline
string
get_number_value(const void *address, const char *format)
{
if (sizeof(align_t) > sizeof(value_t))
return get_number_value<value_t>(value_t(*(align_t*)address), format);
else
return get_number_value<value_t>(*(value_t*)address, format);
}
// get_number_value
template<typename value_t>
static inline
string
get_number_value(value_t value, const char *format)
{
char buffer[32];
sprintf(buffer, format, value);
return buffer;
}
// get_pointer_value
static inline
string
get_pointer_value(const void *address)
{
char buffer[32];
sprintf(buffer, "%p", *(void **)address);
return buffer;
}
// get_pointer_value
static inline
string
get_pointer_value(uint64 value)
{
char buffer[32];
sprintf(buffer, "%p", (void*)value);
return buffer;
}
// generic pointer
template<typename Type>
string
TypeHandlerImpl<Type*>::GetParameterValue(const void *address, bool getContents,
MemoryReader &reader)
{
return get_pointer_value(address);
}
template<typename Type>
string
TypeHandlerImpl<Type*>::GetReturnValue(uint64 value, bool getContents,
MemoryReader &reader)
{
return get_pointer_value(value);
}
#endif // STRACE_TYPE_HANDLER_H
+480
View File
@@ -0,0 +1,480 @@
/*
* Copyright 2005, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <map>
#include <string>
#include <vector>
#include <debugger.h>
#include <image.h>
#include "MemoryReader.h"
#include "Syscall.h"
#include "TypeHandler.h"
extern void get_syscalls0(vector<Syscall*> &syscalls);
extern void get_syscalls1(vector<Syscall*> &syscalls);
extern void get_syscalls2(vector<Syscall*> &syscalls);
extern void get_syscalls3(vector<Syscall*> &syscalls);
extern void get_syscalls4(vector<Syscall*> &syscalls);
extern void get_syscalls5(vector<Syscall*> &syscalls);
extern void get_syscalls6(vector<Syscall*> &syscalls);
extern void get_syscalls7(vector<Syscall*> &syscalls);
extern void get_syscalls8(vector<Syscall*> &syscalls);
extern void get_syscalls9(vector<Syscall*> &syscalls);
extern void get_syscalls10(vector<Syscall*> &syscalls);
extern void get_syscalls11(vector<Syscall*> &syscalls);
extern void get_syscalls12(vector<Syscall*> &syscalls);
extern void get_syscalls13(vector<Syscall*> &syscalls);
extern void get_syscalls14(vector<Syscall*> &syscalls);
extern void get_syscalls15(vector<Syscall*> &syscalls);
extern void get_syscalls16(vector<Syscall*> &syscalls);
extern void get_syscalls17(vector<Syscall*> &syscalls);
extern void get_syscalls18(vector<Syscall*> &syscalls);
extern void get_syscalls19(vector<Syscall*> &syscalls);
static const char *kDefaultCommandName = "strace";
// usage
static const char *kUsage =
"Usage: %s [ <options> ] [ <thread or team ID> | <executable with args> ]\n"
"\n"
"Traces the the syscalls of a thread or a team. If an executable with\n"
"arguments is supplied, it is loaded and it's main thread traced.\n"
"\n"
"Options:\n"
" -a - Don't print syscall arguments.\n"
" -c - Don't colorize output.\n"
" -f - Fast mode. Syscall arguments contents aren't retrieved.\n"
" -h, --help - Print this text.\n"
" -r - Don't print syscall return values.\n"
" -s - Also trace all threads spawned by the supplied thread,\n"
" respectively the loaded executable's main thread.\n"
" -T - Trace all threads of the supplied or loaded executable's\n"
" team. If an ID is supplied, it is interpreted as a team\n"
" ID."
;
// command line args
static int sArgc;
static const char *const *sArgv;
// syscalls
static vector<Syscall*> sSyscallVector;
static map<string, Syscall*> sSyscallMap;
// print_usage
void
print_usage(bool error)
{
// get nice program name
const char *programName = (sArgc > 0 ? sArgv[0] : kDefaultCommandName);
if (const char *lastSlash = strrchr(programName, '/'))
programName = lastSlash + 1;
// print usage
fprintf((error ? stderr : stdout), kUsage, programName);
}
// print_usage_and_exit
static
void
print_usage_and_exit(bool error)
{
print_usage(error);
exit(error ? 1 : 0);
}
// get_id
static
bool
get_id(const char *str, int32 &id)
{
int32 len = strlen(str);
for (int32 i = 0; i < len; i++) {
if (!isdigit(str[i]))
return false;
}
id = atol(str);
return true;
}
// load_program
thread_id
load_program(const char *const *args, int32 argCount)
{
// TODO: We need to find the program in the PATH, if no absolute or relative
// path has been given (i.e. only a name).
return load_image(argCount, (const char**)args, (const char**)environ);
}
// set_team_debugging_flags
static
void
set_team_debugging_flags(port_id nubPort, int32 flags)
{
debug_nub_set_team_flags message;
message.flags = flags;
while (true) {
status_t error = write_port(nubPort, B_DEBUG_MESSAGE_SET_TEAM_FLAGS,
&message, sizeof(message));
if (error == B_OK)
return;
if (error != B_INTERRUPTED) {
fprintf(stderr, "Failed to set team debug flags: %s\n",
strerror(error));
exit(1);
}
}
}
// set_thread_debugging_flags
static
void
set_thread_debugging_flags(port_id nubPort, thread_id thread, int32 flags)
{
debug_nub_set_thread_flags message;
message.thread = thread;
message.flags = flags;
while (true) {
status_t error = write_port(nubPort, B_DEBUG_MESSAGE_SET_THREAD_FLAGS,
&message, sizeof(message));
if (error == B_OK)
return;
if (error != B_INTERRUPTED) {
fprintf(stderr, "Failed to set thread debug flags: %s\n",
strerror(error));
exit(1);
}
}
}
// run_thread
static
void
run_thread(port_id nubPort, thread_id thread)
{
debug_nub_run_thread message;
message.thread = thread;
while (true) {
status_t error = write_port(nubPort, B_DEBUG_MESSAGE_RUN_THREAD,
&message, sizeof(message));
if (error == B_OK)
return;
if (error != B_INTERRUPTED) {
fprintf(stderr, "Failed to run thread %ld: %s\n",
thread, strerror(error));
exit(1);
}
}
}
// init_syscalls
static
void
init_syscalls()
{
// init the syscall vector
get_syscalls0(sSyscallVector);
get_syscalls1(sSyscallVector);
get_syscalls2(sSyscallVector);
get_syscalls3(sSyscallVector);
get_syscalls4(sSyscallVector);
get_syscalls5(sSyscallVector);
get_syscalls6(sSyscallVector);
get_syscalls7(sSyscallVector);
get_syscalls8(sSyscallVector);
get_syscalls9(sSyscallVector);
get_syscalls10(sSyscallVector);
get_syscalls11(sSyscallVector);
get_syscalls12(sSyscallVector);
get_syscalls13(sSyscallVector);
get_syscalls14(sSyscallVector);
get_syscalls15(sSyscallVector);
get_syscalls16(sSyscallVector);
get_syscalls17(sSyscallVector);
get_syscalls18(sSyscallVector);
get_syscalls19(sSyscallVector);
// init the syscall map
int32 count = sSyscallVector.size();
for (int32 i = 0; i < count; i++) {
Syscall *syscall = sSyscallVector[i];
sSyscallMap[syscall->Name()] = syscall;
}
}
// print_syscall
static
void
print_syscall(debug_pre_syscall &message, MemoryReader &memoryReader,
bool printArguments, bool getContents, bool printReturnValue,
bool colorize)
{
int32 syscallNumber = message.syscall;
Syscall *syscall = sSyscallVector[syscallNumber];
// print syscall name
printf("[%6ld] %s(", message.thread, syscall->Name().c_str());
// print arguments
if (printArguments) {
int32 count = syscall->CountParameters();
for (int32 i = 0; i < count; i++) {
// get the value
Parameter *parameter = syscall->ParameterAt(i);
TypeHandler *handler = parameter->Handler();
string value = handler->GetParameterValue(
(char*)message.args + parameter->Offset(), getContents,
memoryReader);
printf((i > 0 ? ", %s" : "%s"), value.c_str());
}
}
printf(") pre\n");
}
// print_syscall
static
void
print_syscall(debug_post_syscall &message, MemoryReader &memoryReader,
bool printArguments, bool getContents, bool printReturnValue,
bool colorize)
{
// TODO: colorize support
int32 syscallNumber = message.syscall;
Syscall *syscall = sSyscallVector[syscallNumber];
// print syscall name
printf("[%6ld] %s(", message.thread, syscall->Name().c_str());
// print arguments
if (printArguments) {
int32 count = syscall->CountParameters();
for (int32 i = 0; i < count; i++) {
// get the value
Parameter *parameter = syscall->ParameterAt(i);
TypeHandler *handler = parameter->Handler();
string value = handler->GetParameterValue(
(char*)message.args + parameter->Offset(), getContents,
memoryReader);
printf((i > 0 ? ", %s" : "%s"), value.c_str());
}
}
printf(")");
// print return value
if (printReturnValue) {
TypeHandler *handler = syscall->ReturnType()->Handler();
string value = handler->GetReturnValue(message.return_value,
getContents, memoryReader);
if (value.length() > 0)
printf(" = %s", value.c_str());
// TODO: If the return value is a status_t, print the error code.
}
printf(" (%lld us)\n", message.end_time - message.start_time);
//for (int32 i = 0; i < 16; i++) {
// if (i % 4 == 0) {
// if (i > 0)
// printf("\n");
// printf(" ");
// } else
// printf(" ");
// printf("%08lx", message.args[i]);
//}
//printf("\n");
}
// main
int
main(int argc, const char *const *argv)
{
sArgc = argc;
sArgv = argv;
// parameters
const char *const *programArgs = NULL;
int32 programArgCount = 0;
bool printArguments = true;
bool colorize = true;
bool fastMode = false;
bool printReturnValues = true;
bool traceChildThreads = false;
bool traceTeam = false;
// parse arguments
for (int argi = 1; argi < argc; argi++) {
const char *arg = argv[argi];
if (arg[0] == '-') {
if (strcmp(arg, "-h") == 0 || strcmp(arg, "--help") == 0) {
print_usage_and_exit(false);
} else if (strcmp(arg, "-a") == 0) {
printArguments = false;
} else if (strcmp(arg, "-c") == 0) {
colorize = false;
} else if (strcmp(arg, "-f") == 0) {
fastMode = true;
} else if (strcmp(arg, "-r") == 0) {
printReturnValues = false;
} else if (strcmp(arg, "-s") == 0) {
traceChildThreads = true;
} else if (strcmp(arg, "-T") == 0) {
traceTeam = true;
} else {
print_usage_and_exit(true);
}
} else {
programArgs = argv + argi;
programArgCount = argc - argi;
break;
}
}
// check parameters
if (!programArgs)
print_usage_and_exit(true);
// initialize our syscalls vector and map
init_syscalls();
// get thread/team to be debugged
thread_id thread = -1;
team_id team = -1;
if (programArgCount > 1
|| !get_id(*programArgs, (traceTeam ? team : thread))) {
// we've been given an executable and need to load it
thread = load_program(programArgs, programArgCount);
}
// get the team ID, if we have none yet
if (team < 0) {
thread_info threadInfo;
status_t error = get_thread_info(thread, &threadInfo);
if (error != B_OK) {
fprintf(stderr, "Failed to get info for thread %ld: %s\n", thread,
strerror(error));
exit(1);
}
team = threadInfo.team;
}
// create a debugger port
port_id debuggerPort = create_port(10, "debugger port");
if (debuggerPort < 0) {
fprintf(stderr, "Failed to create debugger port: %s\n",
strerror(debuggerPort));
exit(1);
}
// install ourselves as the team debugger
port_id nubPort = install_team_debugger(team, debuggerPort);
if (nubPort < 0) {
fprintf(stderr, "Failed to install team debugger: %s\n",
strerror(nubPort));
exit(1);
}
// set team debugging flags
int32 teamDebugFlags
= (printArguments ? 0 : B_TEAM_DEBUG_SYSCALL_FAST_TRACE)
| (traceTeam ? B_TEAM_DEBUG_POST_SYSCALL : 0);
set_team_debugging_flags(nubPort, teamDebugFlags);
// set thread debugging flags
if (thread >= 0) {
int32 threadDebugFlags = 0;
if (!traceTeam) {
threadDebugFlags = B_THREAD_DEBUG_POST_SYSCALL
| (traceChildThreads
? B_THREAD_DEBUG_SYSCALL_TRACE_CHILD_THREADS : 0);
}
set_thread_debugging_flags(nubPort, thread, threadDebugFlags);
// resume the target thread to be sure, it's running
resume_thread(thread);
}
MemoryReader memoryReader(nubPort);
// debug loop
while (true) {
int32 code;
debug_debugger_message_data message;
ssize_t messageSize = read_port(debuggerPort, &code, &message,
sizeof(message));
if (messageSize < 0) {
if (messageSize == B_INTERRUPTED)
continue;
fprintf(stderr, "Reading from debugger port failed: %s\n",
strerror(messageSize));
exit(1);
}
thread_id concernedThread = -1;
switch (code) {
case B_DEBUGGER_MESSAGE_THREAD_STOPPED:
concernedThread = message.thread_stopped.thread;
printf("B_DEBUGGER_MESSAGE_THREAD_STOPPED: thread: %ld\n", concernedThread);
break;
case B_DEBUGGER_MESSAGE_PRE_SYSCALL:
{
concernedThread = message.pre_syscall.thread;
//printf("B_DEBUGGER_MESSAGE_PRE_SYSCALL: thread: %ld\n", concernedThread);
print_syscall(message.pre_syscall, memoryReader,
printArguments, !fastMode, printReturnValues, colorize);
break;
}
case B_DEBUGGER_MESSAGE_SIGNAL_RECEIVED:
concernedThread = message.signal_received.thread;
printf("B_DEBUGGER_MESSAGE_SIGNAL_RECEIVED: thread: %ld\n", concernedThread);
break;
case B_DEBUGGER_MESSAGE_POST_SYSCALL:
{
concernedThread = message.post_syscall.thread;
print_syscall(message.post_syscall, memoryReader,
printArguments, !fastMode, printReturnValues, colorize);
break;
}
case B_DEBUGGER_MESSAGE_TEAM_DELETED:
{
printf("B_DEBUGGER_MESSAGE_TEAM_DELETED: team: %ld\n",
message.team_deleted.team);
exit(0);
}
}
// tell the thread to continue
if (concernedThread >= 0) {
run_thread(nubPort, concernedThread);
}
}
return 0;
}
+13
View File
@@ -0,0 +1,13 @@
/*
* Copyright 2005, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#include <syscalls.h>
#include "Syscall.h"
#include "TypeHandler.h"
#include "strace_syscalls.h"
// generated by gensyscalls