Implemented tracking image creation/deletion. It's not fully correct

yet, since there's no synchronization of the sample evalution with the
image creation/deletion. That is samples taken before an exec*() could
be evaluated after the new images have already been loaded and could
thus be translated to the wrong functions.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@27651 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2008-09-20 14:10:57 +00:00
parent 4ed8088f9a
commit b533a08728
+145 -15
View File
@@ -18,6 +18,7 @@
#include <debug_support.h> #include <debug_support.h>
#include <ObjectList.h> #include <ObjectList.h>
#include <Referenceable.h>
#include <util/DoublyLinkedList.h> #include <util/DoublyLinkedList.h>
@@ -77,7 +78,7 @@ struct HitSymbol {
}; };
class Image { class Image : public Referenceable {
public: public:
Image(const image_info& info) Image(const image_info& info)
: :
@@ -96,6 +97,11 @@ public:
} }
} }
const image_id ID() const
{
return fInfo.id;
}
const image_info& Info() const const image_info& Info() const
{ {
return fInfo; return fInfo;
@@ -209,6 +215,12 @@ public:
fTotalHits(0), fTotalHits(0),
fMissedTicks(0) fMissedTicks(0)
{ {
fImage->AddReference();
}
~ThreadImage()
{
fImage->RemoveReference();
} }
status_t Init() status_t Init()
@@ -223,6 +235,11 @@ public:
return B_OK; return B_OK;
} }
image_id ID() const
{
return fImage->ID();
}
bool ContainsAddress(addr_t address) const bool ContainsAddress(addr_t address) const
{ {
return fImage->ContainsAddress(address); return fImage->ContainsAddress(address);
@@ -267,7 +284,7 @@ private:
}; };
class Thread { class Thread : public DoublyLinkedListLinkImpl<Thread> {
public: public:
Thread(const thread_info& info, Team* team) Thread(const thread_info& info, Team* team)
: :
@@ -327,6 +344,21 @@ public:
return B_OK; return B_OK;
} }
void ImageRemoved(Image* image)
{
ImageList::Iterator it = fImages.GetIterator();
while (ThreadImage* threadImage = it.Next()) {
if (threadImage->GetImage() == image) {
fImages.Remove(threadImage);
if (threadImage->TotalHits() > 0)
fOldImages.Add(threadImage);
else
delete threadImage;
return;
}
}
}
ThreadImage* FindImage(addr_t address) const ThreadImage* FindImage(addr_t address) const
{ {
ImageList::ConstIterator it = fImages.GetIterator(); ImageList::ConstIterator it = fImages.GetIterator();
@@ -445,6 +477,7 @@ public:
Team() Team()
: :
fNubPort(-1), fNubPort(-1),
fThreads(),
fImages(20, false) fImages(20, false)
{ {
fInfo.team = -1; fInfo.team = -1;
@@ -459,9 +492,8 @@ public:
if (fNubPort >= 0) if (fNubPort >= 0)
remove_team_debugger(fInfo.team); remove_team_debugger(fInfo.team);
// TODO: Just decrement ref-count!
for (int32 i = 0; Image* image = fImages.ItemAt(i); i++) for (int32 i = 0; Image* image = fImages.ItemAt(i); i++)
delete image; image->RemoveReference();
} }
status_t Init(team_id teamID, port_id debuggerPort) status_t Init(team_id teamID, port_id debuggerPort)
@@ -504,7 +536,7 @@ public:
// set team debugging flags // set team debugging flags
int32 teamDebugFlags = B_TEAM_DEBUG_THREADS int32 teamDebugFlags = B_TEAM_DEBUG_THREADS
| B_TEAM_DEBUG_TEAM_CREATION; | B_TEAM_DEBUG_TEAM_CREATION | B_TEAM_DEBUG_IMAGES;
set_team_debugging_flags(fNubPort, teamDebugFlags); set_team_debugging_flags(fNubPort, teamDebugFlags);
return B_OK; return B_OK;
@@ -565,12 +597,65 @@ public:
thread->SetInterval(reply.interval); thread->SetInterval(reply.interval);
//reply.profile_event //reply.profile_event
fThreads.Add(thread);
// resume the target thread to be sure, it's running // resume the target thread to be sure, it's running
resume_thread(thread->ID()); resume_thread(thread->ID());
return B_OK; return B_OK;
} }
void RemoveThread(Thread* thread)
{
fThreads.Remove(thread);
}
void Exec()
{
// remove all images
int32 imageCount = fImages.CountItems();
for (int32 i = imageCount - 1; i >= 0; i--)
_RemoveImage(i);
}
status_t AddImage(const image_info& imageInfo)
{
// create symbol lookup context
debug_symbol_lookup_context* lookupContext;
status_t error = debug_create_symbol_lookup_context(&fDebugContext,
&lookupContext);
if (error != B_OK) {
fprintf(stderr, "%s: Failed to create symbol lookup context for "
"team %ld: %s\n", kCommandName, ID(), strerror(error));
return error;
}
Image* image;
error = _LoadImageSymbols(lookupContext, imageInfo, &image);
debug_delete_symbol_lookup_context(lookupContext);
// TODO: Remove! The threads must be updated lazily.
if (error == B_OK) {
ThreadList::Iterator it = fThreads.GetIterator();
while (Thread* thread = it.Next())
thread->AddImage(image);
}
return error;
}
status_t RemoveImage(const image_info& imageInfo)
{
for (int32 i = 0; Image* image = fImages.ItemAt(i); i++) {
if (image->ID() == imageInfo.id) {
_RemoveImage(i);
return B_OK;
}
}
return B_ENTRY_NOT_FOUND;
}
team_id ID() const team_id ID() const
{ {
return fInfo.team; return fInfo.team;
@@ -583,9 +668,17 @@ private:
image_info imageInfo; image_info imageInfo;
int32 cookie = 0; int32 cookie = 0;
while (get_next_image_info(fInfo.team, &cookie, &imageInfo) == B_OK) { while (get_next_image_info(fInfo.team, &cookie, &imageInfo) == B_OK) {
printf("Loading symbols of image \"%s\" (%ld)...\n", status_t error = _LoadImageSymbols(lookupContext, imageInfo);
imageInfo.name, imageInfo.id); if (error == B_NO_MEMORY)
return error;
}
return B_OK;
}
status_t _LoadImageSymbols(debug_symbol_lookup_context* lookupContext,
const image_info& imageInfo, Image** _image = NULL)
{
Image* image = new(std::nothrow) Image(imageInfo); Image* image = new(std::nothrow) Image(imageInfo);
if (image == NULL) if (image == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
@@ -593,24 +686,41 @@ private:
status_t error = image->LoadSymbols(lookupContext); status_t error = image->LoadSymbols(lookupContext);
if (error != B_OK) { if (error != B_OK) {
delete image; delete image;
if (error == B_NO_MEMORY)
return error; return error;
continue;
} }
if (!fImages.AddItem(image)) { if (!fImages.AddItem(image)) {
delete image; delete image;
return B_NO_MEMORY; return B_NO_MEMORY;
} }
}
if (_image != NULL)
*_image = image;
return B_OK; return B_OK;
} }
void _RemoveImage(int32 index)
{
Image* image = fImages.RemoveItemAt(index);
if (image == NULL)
return;
// notify all threads that the image has been removed
ThreadList::Iterator it = fThreads.GetIterator();
while (Thread* thread = it.Next())
thread->ImageRemoved(image);
image->RemoveReference();
}
private: private:
typedef DoublyLinkedList<Thread> ThreadList;
team_info fInfo; team_info fInfo;
port_id fNubPort; port_id fNubPort;
debug_context fDebugContext; debug_context fDebugContext;
ThreadList fThreads;
BObjectList<Image> fImages; BObjectList<Image> fImages;
}; };
@@ -684,9 +794,11 @@ public:
void RemoveThread(thread_id threadID) void RemoveThread(thread_id threadID)
{ {
if (Thread* thread = FindThread(threadID)) if (Thread* thread = FindThread(threadID)) {
thread->GetTeam()->RemoveThread(thread);
fThreads.RemoveItem(thread, true); fThreads.RemoveItem(thread, true);
} }
}
Team* FindTeam(team_id teamID) const Team* FindTeam(team_id teamID) const
{ {
@@ -856,8 +968,6 @@ main(int argc, const char* const* argv)
switch (code) { switch (code) {
case B_DEBUGGER_MESSAGE_PROFILER_UPDATE: case B_DEBUGGER_MESSAGE_PROFILER_UPDATE:
{ {
debug_printf("B_DEBUGGER_MESSAGE_PROFILER_UPDATE: thread %ld, %ld samples\n",
message.profiler_update.origin.thread, message.profiler_update.sample_count);
Thread* thread = threadManager.FindThread( Thread* thread = threadManager.FindThread(
message.profiler_update.origin.thread); message.profiler_update.origin.thread);
if (thread == NULL) if (thread == NULL)
@@ -883,6 +993,11 @@ message.profiler_update.origin.thread, message.profiler_update.sample_count);
// a debugged team is gone -- quit, if it is our team // a debugged team is gone -- quit, if it is our team
quitLoop = message.origin.team == teamID; quitLoop = message.origin.team == teamID;
break; break;
case B_DEBUGGER_MESSAGE_TEAM_EXEC:
if (Team* team = threadManager.FindTeam(message.origin.team))
team->Exec();
break;
case B_DEBUGGER_MESSAGE_THREAD_CREATED: case B_DEBUGGER_MESSAGE_THREAD_CREATED:
threadManager.AddThread(message.thread_created.new_thread); threadManager.AddThread(message.thread_created.new_thread);
break; break;
@@ -890,6 +1005,23 @@ message.profiler_update.origin.thread, message.profiler_update.sample_count);
threadManager.RemoveThread(message.origin.thread); threadManager.RemoveThread(message.origin.thread);
break; break;
case B_DEBUGGER_MESSAGE_IMAGE_CREATED:
{
const image_info& info = message.image_created.info;
printf("B_DEBUGGER_MESSAGE_IMAGE_CREATED: %s (%ld)\n", info.name, info.id);
if (Team* team = threadManager.FindTeam(message.origin.team))
team->AddImage(message.image_created.info);
break;
}
case B_DEBUGGER_MESSAGE_IMAGE_DELETED:
{
const image_info& info = message.image_deleted.info;
printf("B_DEBUGGER_MESSAGE_IMAGE_DELETED: %s (%ld)\n", info.name, info.id);
if (Team* team = threadManager.FindTeam(message.origin.team))
team->RemoveImage(message.image_deleted.info);
break;
}
case B_DEBUGGER_MESSAGE_POST_SYSCALL: case B_DEBUGGER_MESSAGE_POST_SYSCALL:
case B_DEBUGGER_MESSAGE_SIGNAL_RECEIVED: case B_DEBUGGER_MESSAGE_SIGNAL_RECEIVED:
case B_DEBUGGER_MESSAGE_THREAD_DEBUGGED: case B_DEBUGGER_MESSAGE_THREAD_DEBUGGED:
@@ -899,8 +1031,6 @@ message.profiler_update.origin.thread, message.profiler_update.sample_count);
case B_DEBUGGER_MESSAGE_SINGLE_STEP: case B_DEBUGGER_MESSAGE_SINGLE_STEP:
case B_DEBUGGER_MESSAGE_PRE_SYSCALL: case B_DEBUGGER_MESSAGE_PRE_SYSCALL:
case B_DEBUGGER_MESSAGE_EXCEPTION_OCCURRED: case B_DEBUGGER_MESSAGE_EXCEPTION_OCCURRED:
case B_DEBUGGER_MESSAGE_IMAGE_CREATED:
case B_DEBUGGER_MESSAGE_IMAGE_DELETED:
break; break;
} }