* debug_create_symbol_lookup_context() gets a team ID instead of a

debug context now. That's all it needs.
* Added the option "-a" to the profile command line tool. It triggers profiling
  of the whole system. There are still some issues, particularly image related
  ones.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@30129 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold 2009-04-11 22:59:31 +00:00
parent 2ad2768adc
commit 0f37915687
9 changed files with 481 additions and 118 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright 2005, Ingo Weinhold, bonefish@users.sf.net.
* Copyright 2005-2009, Ingo Weinhold, bonefish@users.sf.net.
* Distributed under the terms of the MIT License.
*/
#ifndef _DEBUG_SUPPORT_H
@ -57,7 +57,7 @@ status_t debug_get_stack_frame(debug_context *context,
typedef struct debug_symbol_lookup_context debug_symbol_lookup_context;
typedef struct debug_symbol_iterator debug_symbol_iterator;
status_t debug_create_symbol_lookup_context(debug_context *debugContext,
status_t debug_create_symbol_lookup_context(team_id team,
debug_symbol_lookup_context **lookupContext);
void debug_delete_symbol_lookup_context(
debug_symbol_lookup_context *lookupContext);

View File

@ -1,5 +1,5 @@
/*
* Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2008-2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef OPTIONS_H
@ -17,6 +17,7 @@ struct Options {
stack_depth(5),
output(NULL),
callgrind_directory(NULL),
profile_all(false),
profile_kernel(true),
profile_loading(false),
profile_teams(true),
@ -29,6 +30,7 @@ struct Options {
int32 stack_depth;
FILE* output;
const char* callgrind_directory;
bool profile_all;
bool profile_kernel;
bool profile_loading;
bool profile_teams;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2008-2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
@ -10,12 +10,21 @@
#include <image.h>
#include <debug_support.h>
#include <system_profiler_defs.h>
#include "debug_utils.h"
#include "Options.h"
//#define TRACE_PROFILE_TEAM
#ifdef TRACE_PROFILE_TEAM
# define TRACE(x...) printf(x)
#else
# define TRACE(x...) do {} while(false)
#endif
enum {
SAMPLE_AREA_SIZE = 128 * 1024,
};
@ -71,8 +80,7 @@ Team::Init(team_id teamID, port_id debuggerPort)
// create symbol lookup context
debug_symbol_lookup_context* lookupContext;
error = debug_create_symbol_lookup_context(&fDebugContext,
&lookupContext);
error = debug_create_symbol_lookup_context(ID(), &lookupContext);
if (error != B_OK) {
fprintf(stderr, "%s: Failed to create symbol lookup context for "
"team %ld: %s\n", kCommandName, teamID, strerror(error));
@ -87,14 +95,8 @@ Team::Init(team_id teamID, port_id debuggerPort)
// also try to load the kernel images and symbols
if (gOptions.profile_kernel) {
// fake a debug context -- it's not really needed anyway
debug_context debugContext;
debugContext.team = B_SYSTEM_TEAM;
debugContext.nub_port = -1;
debugContext.reply_port = -1;
// create symbol lookup context
error = debug_create_symbol_lookup_context(&debugContext,
error = debug_create_symbol_lookup_context(B_SYSTEM_TEAM,
&lookupContext);
if (error != B_OK) {
fprintf(stderr, "%s: Failed to create symbol lookup context "
@ -116,9 +118,20 @@ Team::Init(team_id teamID, port_id debuggerPort)
}
status_t
Team::Init(system_profiler_team_added* addedInfo)
{
fInfo.team = addedInfo->team;
return B_OK;
}
status_t
Team::InitThread(Thread* thread)
{
// The thread
thread->ProfileResult()->SetLazyImages(!_SynchronousProfiling());
// create the sample area
char areaName[B_OS_NAME_LENGTH];
snprintf(areaName, sizeof(areaName), "profiling samples %ld",
@ -142,41 +155,47 @@ Team::InitThread(Thread* thread)
return error;
}
// set thread debugging flags and start profiling
int32 threadDebugFlags = 0;
// if (!traceTeam) {
// threadDebugFlags = B_THREAD_DEBUG_POST_SYSCALL
// | (traceChildThreads
// ? B_THREAD_DEBUG_SYSCALL_TRACE_CHILD_THREADS : 0);
// }
set_thread_debugging_flags(fNubPort, thread->ID(), threadDebugFlags);
if (!_SynchronousProfiling()) {
// set thread debugging flags and start profiling
int32 threadDebugFlags = 0;
// if (!traceTeam) {
// threadDebugFlags = B_THREAD_DEBUG_POST_SYSCALL
// | (traceChildThreads
// ? B_THREAD_DEBUG_SYSCALL_TRACE_CHILD_THREADS : 0);
// }
set_thread_debugging_flags(fNubPort, thread->ID(), threadDebugFlags);
// start profiling
debug_nub_start_profiler message;
message.reply_port = fDebugContext.reply_port;
message.thread = thread->ID();
message.interval = gOptions.interval;
message.sample_area = sampleArea;
message.stack_depth = gOptions.stack_depth;
message.variable_stack_depth = gOptions.analyze_full_stack;
// start profiling
debug_nub_start_profiler message;
message.reply_port = fDebugContext.reply_port;
message.thread = thread->ID();
message.interval = gOptions.interval;
message.sample_area = sampleArea;
message.stack_depth = gOptions.stack_depth;
message.variable_stack_depth = gOptions.analyze_full_stack;
debug_nub_start_profiler_reply reply;
status_t error = send_debug_message(&fDebugContext,
B_DEBUG_START_PROFILER, &message, sizeof(message), &reply,
sizeof(reply));
if (error != B_OK || (error = reply.error) != B_OK) {
fprintf(stderr, "%s: Failed to start profiler for thread %ld: %s\n",
kCommandName, thread->ID(), strerror(error));
return error;
debug_nub_start_profiler_reply reply;
status_t error = send_debug_message(&fDebugContext,
B_DEBUG_START_PROFILER, &message, sizeof(message), &reply,
sizeof(reply));
if (error != B_OK || (error = reply.error) != B_OK) {
fprintf(stderr, "%s: Failed to start profiler for thread %ld: %s\n",
kCommandName, thread->ID(), strerror(error));
return error;
}
thread->SetInterval(reply.interval);
fThreads.Add(thread);
// resume the target thread to be sure, it's running
resume_thread(thread->ID());
} else {
// debugger-less profiling
thread->SetInterval(gOptions.interval);
fThreads.Add(thread);
}
thread->SetInterval(reply.interval);
fThreads.Add(thread);
// resume the target thread to be sure, it's running
resume_thread(thread->ID());
return B_OK;
}
@ -211,20 +230,19 @@ Team::Exec(int32 event)
status_t
Team::AddImage(const image_info& imageInfo, int32 event)
Team::AddImage(const image_info& imageInfo, team_id owner, int32 event)
{
// create symbol lookup context
debug_symbol_lookup_context* lookupContext;
status_t error = debug_create_symbol_lookup_context(&fDebugContext,
&lookupContext);
status_t error = debug_create_symbol_lookup_context(owner, &lookupContext);
if (error != B_OK) {
fprintf(stderr, "%s: Failed to create symbol lookup context for "
"team %ld: %s\n", kCommandName, ID(), strerror(error));
"team %ld: %s\n", kCommandName, owner, strerror(error));
return error;
}
Image* image;
error = _LoadImageSymbols(lookupContext, imageInfo, ID(), event,
error = _LoadImageSymbols(lookupContext, imageInfo, owner, event,
&image);
debug_delete_symbol_lookup_context(lookupContext);
@ -242,10 +260,10 @@ Team::AddImage(const image_info& imageInfo, int32 event)
status_t
Team::RemoveImage(const image_info& imageInfo, int32 event)
Team::RemoveImage(image_id imageID, int32 event)
{
for (int32 i = 0; Image* image = fImages.ItemAt(i); i++) {
if (image->ID() == imageInfo.id) {
if (image->ID() == imageID) {
_RemoveImage(i, event);
return B_OK;
}
@ -295,10 +313,14 @@ Team::_LoadImageSymbols(debug_symbol_lookup_context* lookupContext,
status_t error = image->LoadSymbols(lookupContext);
if (error != B_OK) {
TRACE("Failed to load symbols of image %ld: %s\n", image->ID(),
strerror(error));
delete image;
return error;
}
TRACE("image %ld: loaded %ld symbols\n", image->ID(), image->SymbolCount());
if (!fImages.AddItem(image)) {
delete image;
return B_NO_MEMORY;
@ -318,10 +340,16 @@ Team::_RemoveImage(int32 index, int32 event)
if (image == NULL)
return;
// Note: We don't tell the threads that the image has been removed. They
// will be updated lazily when their next profiler update arrives. This
// is necessary, since the update might contain samples hitting that
// image.
if (_SynchronousProfiling()) {
ThreadList::Iterator it = fThreads.GetIterator();
while (Thread* thread = it.Next())
thread->ProfileResult()->RemoveImage(image);
} else {
// Note: We don't tell the threads that the image has been removed. They
// will be updated lazily when their next profiler update arrives. This
// is necessary, since the update might contain samples hitting that
// image.
}
image->SetDeletionEvent(event);
image->RemoveReference();

View File

@ -1,5 +1,5 @@
/*
* Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2008-2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef TEAM_H
@ -12,12 +12,16 @@
#include "Thread.h"
struct system_profiler_team_added;
class Team {
public:
Team();
~Team();
status_t Init(team_id teamID, port_id debuggerPort);
status_t Init(system_profiler_team_added* addedInfo);
status_t InitThread(Thread* thread);
void RemoveThread(Thread* thread);
@ -25,9 +29,8 @@ public:
void Exec(int32 event);
status_t AddImage(const image_info& imageInfo,
int32 event);
status_t RemoveImage(const image_info& imageInfo,
int32 event);
team_id owner, int32 event);
status_t RemoveImage(image_id imageID, int32 event);
inline const BObjectList<Image>& Images() const;
Image* FindImage(image_id id) const;
@ -44,6 +47,9 @@ private:
int32 event, Image** _image = NULL);
void _RemoveImage(int32 index, int32 event);
bool _SynchronousProfiling() const
{ return fDebugContext.nub_port < 0; }
private:
typedef DoublyLinkedList<Thread> ThreadList;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2008-2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
@ -96,13 +96,6 @@ Thread::SetInterval(bigtime_t interval)
}
status_t
Thread::AddImage(Image* image)
{
return fProfileResult->AddImage(image);
}
void
Thread::AddSamples(int32 count, int32 dropped, int32 stackDepth,
bool variableStackDepth, int32 event)
@ -146,6 +139,13 @@ Thread::AddSamples(int32 count, int32 dropped, int32 stackDepth,
}
void
Thread::AddSamples(addr_t* samples, int32 sampleCount)
{
fProfileResult->AddSamples(samples, sampleCount);
}
void
Thread::PrintResults() const
{

View File

@ -1,5 +1,5 @@
/*
* Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2008-2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef THREAD_H
@ -53,11 +53,13 @@ public:
void SetSampleArea(area_id area, addr_t* samples);
void SetInterval(bigtime_t interval);
status_t AddImage(Image* image);
inline status_t AddImage(Image* image);
inline void RemoveImage(Image* image);
void AddSamples(int32 count, int32 dropped,
int32 stackDepth, bool variableStackDepth,
int32 event);
void AddSamples(addr_t* samples, int32 sampleCount);
void PrintResults() const;
private:
@ -81,7 +83,10 @@ public:
void SetInterval(bigtime_t interval);
virtual void SetLazyImages(bool lazy) = 0;
virtual status_t AddImage(Image* image) = 0;
virtual void RemoveImage(Image* image) = 0;
virtual void SynchronizeImages(int32 event) = 0;
virtual void AddSamples(addr_t* samples,
@ -101,7 +106,10 @@ public:
AbstractThreadProfileResult();
virtual ~AbstractThreadProfileResult();
virtual void SetLazyImages(bool lazy);
virtual status_t AddImage(Image* image);
virtual void RemoveImage(Image* image);
virtual void SynchronizeImages(int32 event);
ThreadImageType* FindImage(addr_t address) const;
@ -120,6 +128,7 @@ protected:
ImageList fImages;
ImageList fNewImages;
ImageList fOldImages;
bool fLazyImages;
};
@ -192,6 +201,20 @@ Thread::ProfileResult() const
}
status_t
Thread::AddImage(Image* image)
{
return fProfileResult->AddImage(image);
}
void
Thread::RemoveImage(Image* image)
{
fProfileResult->RemoveImage(image);
}
// #pragma mark - AbstractThreadProfileResult
@ -200,7 +223,8 @@ AbstractThreadProfileResult<ThreadImageType>::AbstractThreadProfileResult()
:
fImages(),
fNewImages(),
fOldImages()
fOldImages(),
fLazyImages(true)
{
}
@ -215,6 +239,14 @@ AbstractThreadProfileResult<ThreadImageType>::~AbstractThreadProfileResult()
}
template<typename ThreadImageType>
void
AbstractThreadProfileResult<ThreadImageType>::SetLazyImages(bool lazy)
{
fLazyImages = lazy;
}
template<typename ThreadImageType>
status_t
AbstractThreadProfileResult<ThreadImageType>::AddImage(Image* image)
@ -229,12 +261,33 @@ AbstractThreadProfileResult<ThreadImageType>::AddImage(Image* image)
return error;
}
fNewImages.Add(threadImage);
if (fLazyImages)
fNewImages.Add(threadImage);
else
fImages.Add(threadImage);
return B_OK;
}
template<typename ThreadImageType>
void
AbstractThreadProfileResult<ThreadImageType>::RemoveImage(Image* image)
{
typename ImageList::Iterator it = fImages.GetIterator();
while (ThreadImageType* threadImage = it.Next()) {
if (threadImage->GetImage() == image) {
it.Remove();
if (threadImage->TotalHits() > 0)
fOldImages.Add(threadImage);
else
delete threadImage;
break;
}
}
}
template<typename ThreadImageType>
void
AbstractThreadProfileResult<ThreadImageType>::SynchronizeImages(int32 event)

View File

@ -1,5 +1,5 @@
/*
* Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2008-2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
@ -17,6 +17,9 @@
#include <OS.h>
#include <String.h>
#include <syscalls.h>
#include <system_profiler_defs.h>
#include <debug_support.h>
#include <ObjectList.h>
#include <Referenceable.h>
@ -31,6 +34,10 @@
#include "Team.h"
// size of the sample buffer area for system profiling
#define PROFILE_ALL_SAMPLE_AREA_SIZE (4 * 1024 * 1024)
extern const char* __progname;
const char* kCommandName = __progname;
@ -41,12 +48,15 @@ class Thread;
static const char* kUsage =
"Usage: %s [ <options> ] <command line>\n"
"Executes the given command line <command line> and periodically samples\n"
"all started threads' program counters. When a thread terminates, a list\n"
"of the functions where the thread was encountered is printed.\n"
"Usage: %s [ <options> ] [ <command line> ]\n"
"Profiles threads by periodically sampling the program counter. There are\n"
"two different modes: One profiles the complete system. The other starts\n"
"a program and profiles that and (optionally) its children. When a thread\n"
"terminates, a list of the functions where the thread was encountered is\n"
"printed.\n"
"\n"
"Options:\n"
" -a, --all - Profile all teams.\n"
" -c - Don't profile child threads. Default is to\n"
" recursively profile all threads created by a profiled\n"
" thread.\n"
@ -75,6 +85,8 @@ static const char* kUsage =
Options gOptions;
static bool sCaughtDeadlySignal = false;
class ThreadManager {
public:
@ -88,25 +100,12 @@ public:
status_t AddTeam(team_id teamID, Team** _team = NULL)
{
if (FindTeam(teamID) != NULL)
return B_BAD_VALUE;
return _AddTeam(teamID, NULL, _team);
}
Team* team = new(std::nothrow) Team;
if (team == NULL)
return B_NO_MEMORY;
status_t error = team->Init(teamID, fDebuggerPort);
if (error != B_OK) {
delete team;
return error;
}
fTeams.AddItem(team);
if (_team != NULL)
*_team = team;
return B_OK;
status_t AddTeam(system_profiler_team_added* addedInfo, Team** _team = NULL)
{
return _AddTeam(addedInfo->team, addedInfo, _team);
}
status_t AddThread(thread_id threadID)
@ -175,7 +174,73 @@ public:
return NULL;
}
int32 CountThreads() const
{
return fThreads.CountItems();
}
Thread* ThreadAt(int32 index) const
{
return fThreads.ItemAt(index);
}
status_t AddImage(team_id teamID, const image_info& imageInfo, int32 event)
{
if (teamID == B_SYSTEM_TEAM) {
// a kernel image -- add it to all teams
int32 count = fTeams.CountItems();
for (int32 i = 0; i < count; i++)
fTeams.ItemAt(i)->AddImage(imageInfo, teamID, event);
}
// a userland team image -- add it to that image
if (Team* team = FindTeam(teamID))
return team->AddImage(imageInfo, teamID, event);
return B_BAD_TEAM_ID;
}
void RemoveImage(team_id teamID, image_id imageID, int32 event)
{
if (teamID == B_SYSTEM_TEAM) {
// a kernel image -- remove it from all teams
int32 count = fTeams.CountItems();
for (int32 i = 0; i < count; i++)
fTeams.ItemAt(i)->RemoveImage(imageID, event);
} else {
// a userland team image -- add it to that image
if (Team* team = FindTeam(teamID))
team->RemoveImage(imageID, event);
}
}
private:
status_t _AddTeam(team_id teamID, system_profiler_team_added* addedInfo,
Team** _team = NULL)
{
if (FindTeam(teamID) != NULL)
return B_BAD_VALUE;
Team* team = new(std::nothrow) Team;
if (team == NULL)
return B_NO_MEMORY;
status_t error = addedInfo != NULL
? team->Init(addedInfo)
: team->Init(teamID, fDebuggerPort);
if (error != B_OK) {
delete team;
return error;
}
fTeams.AddItem(team);
if (_team != NULL)
*_team = team;
return B_OK;
}
status_t _CreateThreadProfileResult(Thread* thread)
{
ThreadProfileResult* profileResult;
@ -231,6 +296,211 @@ get_id(const char *str, int32 &id)
*/
static void
process_event_buffer(ThreadManager& threadManager, uint8* buffer,
size_t bufferSize)
{
//printf("process_event_buffer(%p, %lu)\n", buffer, bufferSize);
const uint8* bufferEnd = buffer + bufferSize;
while (buffer < bufferEnd) {
system_profiler_event_header* header
= (system_profiler_event_header*)buffer;
buffer += sizeof(system_profiler_event_header);
switch (header->event) {
case B_SYSTEM_PROFILER_TEAM_ADDED:
{
system_profiler_team_added* event
= (system_profiler_team_added*)buffer;
threadManager.AddTeam(event);
// TODO: ATM we're not adding kernel images to the team, if this is a team
// created after we started profiling!
break;
}
case B_SYSTEM_PROFILER_TEAM_REMOVED:
{
system_profiler_team_removed* event
= (system_profiler_team_removed*)buffer;
// TODO: Print results!
threadManager.RemoveTeam(event->team);
break;
}
case B_SYSTEM_PROFILER_TEAM_EXEC:
{
system_profiler_team_exec* event
= (system_profiler_team_exec*)event;
if (Team* team = threadManager.FindTeam(event->team))
team->Exec(0);
break;
}
case B_SYSTEM_PROFILER_THREAD_ADDED:
{
system_profiler_thread_added* event
= (system_profiler_thread_added*)buffer;
threadManager.AddThread(event->thread);
break;
}
case B_SYSTEM_PROFILER_THREAD_REMOVED:
{
system_profiler_thread_removed* event
= (system_profiler_thread_removed*)buffer;
if (Thread* thread = threadManager.FindThread(event->thread)) {
thread->PrintResults();
threadManager.RemoveThread(event->thread);
}
break;
}
case B_SYSTEM_PROFILER_IMAGE_ADDED:
{
system_profiler_image_added* event
= (system_profiler_image_added*)buffer;
threadManager.AddImage(event->team, event->info, 0);
break;
}
case B_SYSTEM_PROFILER_IMAGE_REMOVED:
{
system_profiler_image_removed* event
= (system_profiler_image_removed*)buffer;
threadManager.RemoveImage(event->team, event->image, 0);
break;
}
case B_SYSTEM_PROFILER_SAMPLES:
{
system_profiler_samples* event
= (system_profiler_samples*)buffer;
Thread* thread = threadManager.FindThread(event->thread);
if (thread != NULL) {
thread->AddSamples(event->samples,
(addr_t*)(buffer + header->size) - event->samples);
}
break;
}
case B_SYSTEM_PROFILER_SAMPLES_END:
{
// Marks the end of the ring buffer -- we need to ignore the
// remaining bytes.
return;
}
}
buffer += header->size;
}
}
static void
signal_handler(int signal, void* data)
{
sCaughtDeadlySignal = true;
}
static void
profile_all()
{
// install signal handlers so we can exit gracefully
struct sigaction action;
action.sa_handler = (sighandler_t)signal_handler;
sigemptyset(&action.sa_mask);
action.sa_userdata = NULL;
if (sigaction(SIGHUP, &action, NULL) < 0
|| sigaction(SIGINT, &action, NULL) < 0
|| sigaction(SIGQUIT, &action, NULL) < 0) {
fprintf(stderr, "%s: Failed to install signal handlers: %s\n",
kCommandName, strerror(errno));
exit(1);
}
// create and area for the sample buffer
system_profiler_buffer_header* bufferHeader;
area_id area = create_area("profiling buffer", (void**)&bufferHeader,
B_ANY_ADDRESS, PROFILE_ALL_SAMPLE_AREA_SIZE, B_NO_LOCK, B_READ_AREA);
if (area < 0) {
fprintf(stderr, "%s: Failed to create sample area: %s\n", kCommandName,
strerror(area));
exit(1);
}
uint8* bufferBase = (uint8*)(bufferHeader + 1);
size_t totalBufferSize = PROFILE_ALL_SAMPLE_AREA_SIZE
- (bufferBase - (uint8*)bufferHeader);
// create a thread manager
ThreadManager threadManager(-1); // TODO: We don't need a debugger port!
// start profiling
status_t error = _kern_system_profiler_start(area, gOptions.interval,
gOptions.stack_depth);
if (error != B_OK) {
fprintf(stderr, "%s: Failed to start profiling: %s\n", kCommandName,
strerror(error));
exit(1);
}
// main event loop
while (true) {
// get the current buffer
size_t bufferStart = bufferHeader->start;
size_t bufferSize = bufferHeader->size;
uint8* buffer = bufferBase + bufferStart;
//printf("processing buffer of size %lu bytes\n", bufferSize);
if (bufferStart + bufferSize <= totalBufferSize) {
process_event_buffer(threadManager, buffer, bufferSize);
} else {
size_t remainingSize = bufferStart + bufferSize - totalBufferSize;
process_event_buffer(threadManager, buffer,
bufferSize - remainingSize);
process_event_buffer(threadManager, bufferBase, remainingSize);
}
// get next buffer
error = _kern_system_profiler_next_buffer(bufferSize);
if (error != B_OK) {
if (error == B_INTERRUPTED) {
if (sCaughtDeadlySignal)
break;
continue;
}
fprintf(stderr, "%s: Failed to get next sample buffer: %s\n",
kCommandName, strerror(error));
break;
}
}
// stop profiling
_kern_system_profiler_stop();
// print results
int32 threadCount = threadManager.CountThreads();
for (int32 i = 0; i < threadCount; i++) {
Thread* thread = threadManager.ThreadAt(i);
thread->PrintResults();
}
}
int
main(int argc, const char* const* argv)
{
@ -239,17 +509,21 @@ main(int argc, const char* const* argv)
while (true) {
static struct option sLongOptions[] = {
{ "all", no_argument, 0, 'a' },
{ "help", no_argument, 0, 'h' },
{ 0, 0, 0, 0 }
};
opterr = 0; // don't print errors
int c = getopt_long(argc, (char**)argv, "+cCfhi:klo:s:v:", sLongOptions,
NULL);
int c = getopt_long(argc, (char**)argv, "+acCfhi:klo:s:v:",
sLongOptions, NULL);
if (c == -1)
break;
switch (c) {
case 'a':
gOptions.profile_all = true;
break;
case 'c':
gOptions.profile_threads = false;
break;
@ -289,15 +563,12 @@ main(int argc, const char* const* argv)
}
}
if (optind >= argc)
if (!gOptions.profile_all && optind >= argc)
print_usage_and_exit(true);
if (stackDepth != 0)
gOptions.stack_depth = stackDepth;
const char* const* programArgs = argv + optind;
int programArgCount = argc - optind;
if (outputFile != NULL) {
gOptions.output = fopen(outputFile, "w+");
if (gOptions.output == NULL) {
@ -308,6 +579,14 @@ main(int argc, const char* const* argv)
} else
gOptions.output = stdout;
if (gOptions.profile_all) {
profile_all();
return 0;
}
const char* const* programArgs = argv + optind;
int programArgCount = argc - optind;
// get thread/team to be debugged
thread_id threadID = -1;
team_id teamID = -1;
@ -417,16 +696,14 @@ main(int argc, const char* const* argv)
break;
case B_DEBUGGER_MESSAGE_IMAGE_CREATED:
if (Team* team = threadManager.FindTeam(message.origin.team)) {
team->AddImage(message.image_created.info,
message.image_created.image_event);
}
threadManager.AddImage(message.origin.team,
message.image_created.info,
message.image_created.image_event);
break;
case B_DEBUGGER_MESSAGE_IMAGE_DELETED:
if (Team* team = threadManager.FindTeam(message.origin.team)) {
team->RemoveImage(message.image_deleted.info,
message.image_deleted.image_event);
}
threadManager.RemoveImage(message.origin.team,
message.image_deleted.info.id,
message.image_deleted.image_event);
break;
case B_DEBUGGER_MESSAGE_POST_SYSCALL:

View File

@ -1,5 +1,5 @@
/*
* Copyright 2005-2008, Ingo Weinhold, ingo_weinhold@gmx.de.
* Copyright 2005-2009, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
@ -18,8 +18,7 @@ using std::nothrow;
struct debug_symbol_lookup_context {
debug_context context;
SymbolLookup *lookup;
SymbolLookup* lookup;
};
struct debug_symbol_iterator : BPrivate::SymbolIterator {
@ -266,20 +265,19 @@ debug_get_stack_frame(debug_context *context, void *stackFrameAddress,
// debug_create_symbol_lookup_context
status_t
debug_create_symbol_lookup_context(debug_context *debugContext,
debug_create_symbol_lookup_context(team_id team,
debug_symbol_lookup_context **_lookupContext)
{
if (!debugContext || !_lookupContext)
if (team < 0 || !_lookupContext)
return B_BAD_VALUE;
// create the lookup context
debug_symbol_lookup_context *lookupContext
= new(nothrow) debug_symbol_lookup_context;
lookupContext->context = *debugContext;
ObjectDeleter<debug_symbol_lookup_context> contextDeleter(lookupContext);
// create and init symbol lookup
SymbolLookup *lookup = new(nothrow) SymbolLookup(debugContext->team);
SymbolLookup *lookup = new(nothrow) SymbolLookup(team);
if (!lookup)
return B_NO_MEMORY;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2005-2006, Ingo Weinhold, bonefish@users.sf.net.
* Copyright 2005-2009, Ingo Weinhold, bonefish@users.sf.net.
* Distributed under the terms of the MIT License.
*/
@ -644,8 +644,7 @@ TeamDebugHandler::_PrintStackTrace(thread_id thread)
if (error == B_OK) {
// create a symbol lookup context
debug_symbol_lookup_context *lookupContext = NULL;
error = debug_create_symbol_lookup_context(&fDebugContext,
&lookupContext);
error = debug_create_symbol_lookup_context(fTeam, &lookupContext);
if (error != B_OK) {
debug_printf("debug_server: Failed to create symbol lookup "
"context: %s\n", strerror(error));