* Reorganized the image management. Introduced a SharedImage which knows the
symbols and is identified by name. Image does still represent a team-bound image, but it refers to a SharedImage for the symbols, now. This allows us to load the symbols for a shared object only once and share the data for all teams referring to it. * Made the area used for system profiling writable. "-a -f" would segfault since the return addresses are sorted in-place. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@30170 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -14,8 +14,9 @@
|
|||||||
|
|
||||||
|
|
||||||
struct HitSymbol {
|
struct HitSymbol {
|
||||||
int64 hits;
|
int64 hits;
|
||||||
Symbol* symbol;
|
Symbol* symbol;
|
||||||
|
image_id imageID;
|
||||||
|
|
||||||
inline bool operator<(const HitSymbol& other) const
|
inline bool operator<(const HitSymbol& other) const
|
||||||
{
|
{
|
||||||
@@ -146,6 +147,7 @@ BasicThreadProfileResult::PrintResults()
|
|||||||
HitSymbol& hitSymbol = hitSymbols[hitSymbolCount++];
|
HitSymbol& hitSymbol = hitSymbols[hitSymbolCount++];
|
||||||
hitSymbol.hits = symbolHits[i];
|
hitSymbol.hits = symbolHits[i];
|
||||||
hitSymbol.symbol = symbols[i];
|
hitSymbol.symbol = symbols[i];
|
||||||
|
hitSymbol.imageID = image->ID();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -180,10 +182,9 @@ BasicThreadProfileResult::PrintResults()
|
|||||||
"---------------------------------------\n");
|
"---------------------------------------\n");
|
||||||
for (int32 k = 0; k < imageCount; k++) {
|
for (int32 k = 0; k < imageCount; k++) {
|
||||||
BasicThreadImage* image = images[k];
|
BasicThreadImage* image = images[k];
|
||||||
const image_info& imageInfo = image->GetImage()->Info();
|
|
||||||
fprintf(gOptions.output, " %10lld %10lld %7ld %s\n",
|
fprintf(gOptions.output, " %10lld %10lld %7ld %s\n",
|
||||||
image->TotalHits(), image->UnknownHits(), imageInfo.id,
|
image->TotalHits(), image->UnknownHits(),
|
||||||
imageInfo.name);
|
image->GetImage()->ID(), image->GetImage()->Name());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,7 +199,7 @@ BasicThreadProfileResult::PrintResults()
|
|||||||
const Symbol* symbol = hitSymbol.symbol;
|
const Symbol* symbol = hitSymbol.symbol;
|
||||||
fprintf(gOptions.output, " %10lld %10lld %6.2f %6ld %s\n",
|
fprintf(gOptions.output, " %10lld %10lld %6.2f %6ld %s\n",
|
||||||
hitSymbol.hits, hitSymbol.hits * fInterval,
|
hitSymbol.hits, hitSymbol.hits * fInterval,
|
||||||
100.0 * hitSymbol.hits / totalTicks, symbol->image->ID(),
|
100.0 * hitSymbol.hits / totalTicks, hitSymbol.imageID,
|
||||||
symbol->Name());
|
symbol->Name());
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
|
|||||||
@@ -271,7 +271,7 @@ CallgrindThreadProfileResult::_PrintFunction(FILE* out,
|
|||||||
int32 index = fNextImageOutputIndex++;
|
int32 index = fNextImageOutputIndex++;
|
||||||
image->SetOutputIndex(index);
|
image->SetOutputIndex(index);
|
||||||
fprintf(out, "%sob=(%ld) %s:%ld\n", called ? "c" : "", index,
|
fprintf(out, "%sob=(%ld) %s:%ld\n", called ? "c" : "", index,
|
||||||
image->GetImage()->Info().name, image->ID());
|
image->GetImage()->Name(), image->ID());
|
||||||
} else {
|
} else {
|
||||||
// image is already known
|
// image is already known
|
||||||
// TODO: We may not need to print it at all!
|
// TODO: We may not need to print it at all!
|
||||||
|
|||||||
@@ -5,115 +5,22 @@
|
|||||||
|
|
||||||
#include "Image.h"
|
#include "Image.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include <algorithm>
|
Image::Image(SharedImage* image, const image_info& info, team_id owner,
|
||||||
#include <new>
|
int32 creationEvent)
|
||||||
|
|
||||||
#include <debug_support.h>
|
|
||||||
#include <ObjectList.h>
|
|
||||||
|
|
||||||
#include "Options.h"
|
|
||||||
|
|
||||||
|
|
||||||
Image::Image(const image_info& info, team_id owner, int32 creationEvent)
|
|
||||||
:
|
:
|
||||||
fInfo(info),
|
fImage(image),
|
||||||
|
fID(info.id),
|
||||||
fOwner(owner),
|
fOwner(owner),
|
||||||
fSymbols(NULL),
|
fLoadDelta((addr_t)info.text - (addr_t)image->Info().text),
|
||||||
fSymbolCount(0),
|
|
||||||
fCreationEvent(creationEvent),
|
fCreationEvent(creationEvent),
|
||||||
fDeletionEvent(-1)
|
fDeletionEvent(-1)
|
||||||
{
|
{
|
||||||
|
fImage->AddReference();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Image::~Image()
|
Image::~Image()
|
||||||
{
|
{
|
||||||
if (fSymbols != NULL) {
|
fImage->RemoveReference();
|
||||||
for (int32 i = 0; i < fSymbolCount; i++)
|
|
||||||
delete fSymbols[i];
|
|
||||||
delete[] fSymbols;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
Image::LoadSymbols(debug_symbol_lookup_context* lookupContext)
|
|
||||||
{
|
|
||||||
// fprintf(sOptions.output, "Loading symbols of image \"%s\" (%ld)...\n",
|
|
||||||
// fInfo.name, fInfo.id);
|
|
||||||
|
|
||||||
// create symbol iterator
|
|
||||||
debug_symbol_iterator* iterator;
|
|
||||||
status_t error = debug_create_image_symbol_iterator(lookupContext,
|
|
||||||
fInfo.id, &iterator);
|
|
||||||
if (error != B_OK) {
|
|
||||||
fprintf(stderr, "Failed to init symbol iterator: %s\n",
|
|
||||||
strerror(error));
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
// iterate through the symbols
|
|
||||||
BObjectList<Symbol> symbols(512, true);
|
|
||||||
char symbolName[1024];
|
|
||||||
int32 symbolType;
|
|
||||||
void* symbolLocation;
|
|
||||||
size_t symbolSize;
|
|
||||||
while (debug_next_image_symbol(iterator, symbolName, sizeof(symbolName),
|
|
||||||
&symbolType, &symbolLocation, &symbolSize) == B_OK) {
|
|
||||||
// printf(" %s %p (%6lu) %s\n",
|
|
||||||
// symbolType == B_SYMBOL_TYPE_TEXT ? "text" : "data",
|
|
||||||
// symbolLocation, symbolSize, symbolName);
|
|
||||||
if (symbolSize > 0 && symbolType == B_SYMBOL_TYPE_TEXT) {
|
|
||||||
Symbol* symbol = new(std::nothrow) Symbol(this,
|
|
||||||
(addr_t)symbolLocation, symbolSize, symbolName);
|
|
||||||
if (symbol == NULL || !symbols.AddItem(symbol)) {
|
|
||||||
delete symbol;
|
|
||||||
fprintf(stderr, "%s: Out of memory\n", kCommandName);
|
|
||||||
debug_delete_symbol_iterator(iterator);
|
|
||||||
return B_NO_MEMORY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
debug_delete_symbol_iterator(iterator);
|
|
||||||
|
|
||||||
// sort the symbols
|
|
||||||
fSymbolCount = symbols.CountItems();
|
|
||||||
fSymbols = new(std::nothrow) Symbol*[fSymbolCount];
|
|
||||||
if (fSymbols == NULL)
|
|
||||||
return B_NO_MEMORY;
|
|
||||||
|
|
||||||
for (int32 i = fSymbolCount - 1; i >= 0 ; i--)
|
|
||||||
fSymbols[i] = symbols.RemoveItemAt(i);
|
|
||||||
|
|
||||||
std::sort(fSymbols, fSymbols + fSymbolCount, SymbolComparator());
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int32
|
|
||||||
Image::FindSymbol(addr_t address) const
|
|
||||||
{
|
|
||||||
// binary search the function
|
|
||||||
int32 lower = 0;
|
|
||||||
int32 upper = fSymbolCount;
|
|
||||||
|
|
||||||
while (lower < upper) {
|
|
||||||
int32 mid = (lower + upper) / 2;
|
|
||||||
if (address >= fSymbols[mid]->base + fSymbols[mid]->size)
|
|
||||||
lower = mid + 1;
|
|
||||||
else
|
|
||||||
upper = mid;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lower == fSymbolCount)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
const Symbol* symbol = fSymbols[lower];
|
|
||||||
if (address >= symbol->base && address < symbol->base + symbol->size)
|
|
||||||
return lower;
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,73 +5,35 @@
|
|||||||
#ifndef IMAGE_H
|
#ifndef IMAGE_H
|
||||||
#define IMAGE_H
|
#define IMAGE_H
|
||||||
|
|
||||||
#include <image.h>
|
#include "SharedImage.h"
|
||||||
#include <OS.h>
|
|
||||||
#include <String.h>
|
|
||||||
|
|
||||||
#include "Referenceable.h"
|
|
||||||
|
|
||||||
|
|
||||||
class debug_symbol_lookup_context;
|
|
||||||
class Image;
|
|
||||||
|
|
||||||
|
|
||||||
class Symbol {
|
|
||||||
public:
|
|
||||||
Symbol(Image* image, addr_t base, size_t size, const char* name)
|
|
||||||
:
|
|
||||||
image(image),
|
|
||||||
base(base),
|
|
||||||
size(size),
|
|
||||||
name(name)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* Name() const { return name.String(); }
|
|
||||||
|
|
||||||
Image* image;
|
|
||||||
addr_t base;
|
|
||||||
size_t size;
|
|
||||||
BString name;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct SymbolComparator {
|
|
||||||
inline bool operator()(const Symbol* a, const Symbol* b) const
|
|
||||||
{
|
|
||||||
return a->base < b->base;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class Image : public Referenceable {
|
class Image : public Referenceable {
|
||||||
public:
|
public:
|
||||||
Image(const image_info& info, team_id owner,
|
Image(SharedImage* image,
|
||||||
|
const image_info& info, team_id owner,
|
||||||
int32 creationEvent);
|
int32 creationEvent);
|
||||||
~Image();
|
~Image();
|
||||||
|
|
||||||
inline const image_id ID() const;
|
inline const image_id ID() const;
|
||||||
inline const image_info& Info() const;
|
inline const char* Name() const;
|
||||||
inline team_id Owner() const;
|
inline team_id Owner() const;
|
||||||
|
|
||||||
inline int32 CreationEvent() const;
|
inline int32 CreationEvent() const;
|
||||||
inline int32 DeletionEvent() const;
|
inline int32 DeletionEvent() const;
|
||||||
inline void SetDeletionEvent(int32 event);
|
inline void SetDeletionEvent(int32 event);
|
||||||
|
|
||||||
status_t LoadSymbols(
|
|
||||||
debug_symbol_lookup_context* lookupContext);
|
|
||||||
|
|
||||||
inline Symbol** Symbols() const;
|
inline Symbol** Symbols() const;
|
||||||
inline int32 SymbolCount() const;
|
inline int32 SymbolCount() const;
|
||||||
|
|
||||||
inline bool ContainsAddress(addr_t address) const;
|
inline bool ContainsAddress(addr_t address) const;
|
||||||
int32 FindSymbol(addr_t address) const;
|
inline int32 FindSymbol(addr_t address) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
image_info fInfo;
|
SharedImage* fImage;
|
||||||
|
image_id fID;
|
||||||
team_id fOwner;
|
team_id fOwner;
|
||||||
Symbol** fSymbols;
|
addr_t fLoadDelta;
|
||||||
int32 fSymbolCount;
|
|
||||||
int32 fCreationEvent;
|
int32 fCreationEvent;
|
||||||
int32 fDeletionEvent;
|
int32 fDeletionEvent;
|
||||||
};
|
};
|
||||||
@@ -83,14 +45,14 @@ private:
|
|||||||
const image_id
|
const image_id
|
||||||
Image::ID() const
|
Image::ID() const
|
||||||
{
|
{
|
||||||
return fInfo.id;
|
return fID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const image_info&
|
const char*
|
||||||
Image::Info() const
|
Image::Name() const
|
||||||
{
|
{
|
||||||
return fInfo;
|
return fImage->Name();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -125,22 +87,28 @@ Image::SetDeletionEvent(int32 event)
|
|||||||
Symbol**
|
Symbol**
|
||||||
Image::Symbols() const
|
Image::Symbols() const
|
||||||
{
|
{
|
||||||
return fSymbols;
|
return fImage->Symbols();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int32
|
int32
|
||||||
Image::SymbolCount() const
|
Image::SymbolCount() const
|
||||||
{
|
{
|
||||||
return fSymbolCount;
|
return fImage->SymbolCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Image::ContainsAddress(addr_t address) const
|
Image::ContainsAddress(addr_t address) const
|
||||||
{
|
{
|
||||||
return address >= (addr_t)fInfo.text
|
return fImage->ContainsAddress(address - fLoadDelta);
|
||||||
&& address <= (addr_t)fInfo.data + fInfo.data_size - 1;
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32
|
||||||
|
Image::FindSymbol(addr_t address) const
|
||||||
|
{
|
||||||
|
return fImage->FindSymbol(address - fLoadDelta);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ BinCommand profile
|
|||||||
BasicThreadProfileResult.cpp
|
BasicThreadProfileResult.cpp
|
||||||
CallgrindThreadProfileResult.cpp
|
CallgrindThreadProfileResult.cpp
|
||||||
Image.cpp
|
Image.cpp
|
||||||
|
SharedImage.cpp
|
||||||
Team.cpp
|
Team.cpp
|
||||||
Thread.cpp
|
Thread.cpp
|
||||||
profile.cpp
|
profile.cpp
|
||||||
|
|||||||
@@ -78,37 +78,6 @@ Team::Init(team_id teamID, port_id debuggerPort)
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
// create symbol lookup context
|
|
||||||
debug_symbol_lookup_context* 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));
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
// load the team's images and their symbols
|
|
||||||
error = _LoadSymbols(lookupContext, ID());
|
|
||||||
debug_delete_symbol_lookup_context(lookupContext);
|
|
||||||
if (error != B_OK)
|
|
||||||
return error;
|
|
||||||
|
|
||||||
// also try to load the kernel images and symbols
|
|
||||||
if (gOptions.profile_kernel) {
|
|
||||||
// create symbol lookup context
|
|
||||||
error = debug_create_symbol_lookup_context(B_SYSTEM_TEAM,
|
|
||||||
&lookupContext);
|
|
||||||
if (error != B_OK) {
|
|
||||||
fprintf(stderr, "%s: Failed to create symbol lookup context "
|
|
||||||
"for the kernel team: %s\n", kCommandName, strerror(error));
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
// load the kernel's images and their symbols
|
|
||||||
_LoadSymbols(lookupContext, B_SYSTEM_TEAM);
|
|
||||||
debug_delete_symbol_lookup_context(lookupContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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_IMAGES;
|
| B_TEAM_DEBUG_TEAM_CREATION | B_TEAM_DEBUG_IMAGES;
|
||||||
@@ -230,32 +199,28 @@ Team::Exec(int32 event)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
Team::AddImage(const image_info& imageInfo, team_id owner, int32 event)
|
Team::AddImage(SharedImage* sharedImage, const image_info& imageInfo,
|
||||||
|
team_id owner, int32 event)
|
||||||
{
|
{
|
||||||
// create symbol lookup context
|
// create the image
|
||||||
debug_symbol_lookup_context* lookupContext;
|
Image* image = new(std::nothrow) Image(sharedImage, imageInfo, owner,
|
||||||
status_t error = debug_create_symbol_lookup_context(owner, &lookupContext);
|
event);
|
||||||
if (error != B_OK) {
|
if (image == NULL)
|
||||||
fprintf(stderr, "%s: Failed to create symbol lookup context for "
|
return B_NO_MEMORY;
|
||||||
"team %ld: %s\n", kCommandName, owner, strerror(error));
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
Image* image;
|
if (!fImages.AddItem(image)) {
|
||||||
error = _LoadImageSymbols(lookupContext, imageInfo, owner, event,
|
delete image;
|
||||||
&image);
|
return B_NO_MEMORY;
|
||||||
debug_delete_symbol_lookup_context(lookupContext);
|
}
|
||||||
|
|
||||||
// Although we generally synchronize the threads' images lazily, we have
|
// Although we generally synchronize the threads' images lazily, we have
|
||||||
// to add new images at least, since otherwise images could be added
|
// to add new images at least, since otherwise images could be added
|
||||||
// and removed again, and the hits inbetween could never be matched.
|
// and removed again, and the hits inbetween could never be matched.
|
||||||
if (error == B_OK) {
|
ThreadList::Iterator it = fThreads.GetIterator();
|
||||||
ThreadList::Iterator it = fThreads.GetIterator();
|
while (Thread* thread = it.Next())
|
||||||
while (Thread* thread = it.Next())
|
thread->AddImage(image);
|
||||||
thread->AddImage(image);
|
|
||||||
}
|
|
||||||
|
|
||||||
return error;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -285,54 +250,6 @@ Team::FindImage(image_id id) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
Team::_LoadSymbols(debug_symbol_lookup_context* lookupContext,
|
|
||||||
team_id owner)
|
|
||||||
{
|
|
||||||
// iterate through the team's images and collect the symbols
|
|
||||||
image_info imageInfo;
|
|
||||||
int32 cookie = 0;
|
|
||||||
while (get_next_image_info(owner, &cookie, &imageInfo) == B_OK) {
|
|
||||||
status_t error = _LoadImageSymbols(lookupContext, imageInfo,
|
|
||||||
owner, 0);
|
|
||||||
if (error == B_NO_MEMORY)
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
Team::_LoadImageSymbols(debug_symbol_lookup_context* lookupContext,
|
|
||||||
const image_info& imageInfo, team_id owner, int32 event, Image** _image)
|
|
||||||
{
|
|
||||||
Image* image = new(std::nothrow) Image(imageInfo, owner, event);
|
|
||||||
if (image == NULL)
|
|
||||||
return B_NO_MEMORY;
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_image != NULL)
|
|
||||||
*_image = image;
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Team::_RemoveImage(int32 index, int32 event)
|
Team::_RemoveImage(int32 index, int32 event)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -28,8 +28,9 @@ public:
|
|||||||
|
|
||||||
void Exec(int32 event);
|
void Exec(int32 event);
|
||||||
|
|
||||||
status_t AddImage(const image_info& imageInfo,
|
status_t AddImage(SharedImage* sharedImage,
|
||||||
team_id owner, int32 event);
|
const image_info& imageInfo, team_id owner,
|
||||||
|
int32 event);
|
||||||
status_t RemoveImage(image_id imageID, int32 event);
|
status_t RemoveImage(image_id imageID, int32 event);
|
||||||
|
|
||||||
inline const BObjectList<Image>& Images() const;
|
inline const BObjectList<Image>& Images() const;
|
||||||
@@ -38,13 +39,6 @@ public:
|
|||||||
inline team_id ID() const;
|
inline team_id ID() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
status_t _LoadSymbols(
|
|
||||||
debug_symbol_lookup_context* lookupContext,
|
|
||||||
team_id owner);
|
|
||||||
status_t _LoadImageSymbols(
|
|
||||||
debug_symbol_lookup_context* lookupContext,
|
|
||||||
const image_info& imageInfo, team_id owner,
|
|
||||||
int32 event, Image** _image = NULL);
|
|
||||||
void _RemoveImage(int32 index, int32 event);
|
void _RemoveImage(int32 index, int32 event);
|
||||||
|
|
||||||
bool _SynchronousProfiling() const
|
bool _SynchronousProfiling() const
|
||||||
|
|||||||
@@ -11,7 +11,9 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <map>
|
||||||
#include <new>
|
#include <new>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include <debugger.h>
|
#include <debugger.h>
|
||||||
#include <OS.h>
|
#include <OS.h>
|
||||||
@@ -20,6 +22,7 @@
|
|||||||
#include <syscalls.h>
|
#include <syscalls.h>
|
||||||
#include <system_profiler_defs.h>
|
#include <system_profiler_defs.h>
|
||||||
|
|
||||||
|
#include <AutoDeleter.h>
|
||||||
#include <debug_support.h>
|
#include <debug_support.h>
|
||||||
#include <ObjectList.h>
|
#include <ObjectList.h>
|
||||||
#include <Referenceable.h>
|
#include <Referenceable.h>
|
||||||
@@ -98,6 +101,13 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~ThreadManager()
|
||||||
|
{
|
||||||
|
// release image references
|
||||||
|
for (ImageMap::iterator it = fImages.begin(); it != fImages.end(); ++it)
|
||||||
|
it->second->RemoveReference();
|
||||||
|
}
|
||||||
|
|
||||||
status_t AddTeam(team_id teamID, Team** _team = NULL)
|
status_t AddTeam(team_id teamID, Team** _team = NULL)
|
||||||
{
|
{
|
||||||
return _AddTeam(teamID, NULL, _team);
|
return _AddTeam(teamID, NULL, _team);
|
||||||
@@ -186,16 +196,24 @@ public:
|
|||||||
|
|
||||||
status_t AddImage(team_id teamID, const image_info& imageInfo, int32 event)
|
status_t AddImage(team_id teamID, const image_info& imageInfo, int32 event)
|
||||||
{
|
{
|
||||||
|
// get a shared image
|
||||||
|
SharedImage* sharedImage;
|
||||||
|
status_t error = _GetSharedImage(teamID, imageInfo, &sharedImage);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
if (teamID == B_SYSTEM_TEAM) {
|
if (teamID == B_SYSTEM_TEAM) {
|
||||||
// a kernel image -- add it to all teams
|
// a kernel image -- add it to all teams
|
||||||
int32 count = fTeams.CountItems();
|
int32 count = fTeams.CountItems();
|
||||||
for (int32 i = 0; i < count; i++)
|
for (int32 i = 0; i < count; i++) {
|
||||||
fTeams.ItemAt(i)->AddImage(imageInfo, teamID, event);
|
fTeams.ItemAt(i)->AddImage(sharedImage, imageInfo, teamID,
|
||||||
|
event);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// a userland team image -- add it to that image
|
// a userland team image -- add it to that image
|
||||||
if (Team* team = FindTeam(teamID))
|
if (Team* team = FindTeam(teamID))
|
||||||
return team->AddImage(imageInfo, teamID, event);
|
return team->AddImage(sharedImage, imageInfo, teamID, event);
|
||||||
|
|
||||||
return B_BAD_TEAM_ID;
|
return B_BAD_TEAM_ID;
|
||||||
}
|
}
|
||||||
@@ -227,7 +245,7 @@ private:
|
|||||||
|
|
||||||
status_t error = addedInfo != NULL
|
status_t error = addedInfo != NULL
|
||||||
? team->Init(addedInfo)
|
? team->Init(addedInfo)
|
||||||
: team->Init(teamID, fDebuggerPort);
|
: _InitDebuggedTeam(team, teamID);
|
||||||
if (error != B_OK) {
|
if (error != B_OK) {
|
||||||
delete team;
|
delete team;
|
||||||
return error;
|
return error;
|
||||||
@@ -241,6 +259,43 @@ private:
|
|||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
status_t _InitDebuggedTeam(Team* team, team_id teamID)
|
||||||
|
{
|
||||||
|
// init the team
|
||||||
|
status_t error = team->Init(teamID, fDebuggerPort);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
// add the team's images
|
||||||
|
error = _LoadTeamImages(team, teamID);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
// add the kernel images
|
||||||
|
return _LoadTeamImages(team, B_SYSTEM_TEAM);
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t _LoadTeamImages(Team* team, team_id teamID)
|
||||||
|
{
|
||||||
|
// iterate through the team's images and collect the symbols
|
||||||
|
image_info imageInfo;
|
||||||
|
int32 cookie = 0;
|
||||||
|
while (get_next_image_info(teamID, &cookie, &imageInfo) == B_OK) {
|
||||||
|
// get a shared image
|
||||||
|
SharedImage* sharedImage;
|
||||||
|
status_t error = _GetSharedImage(teamID, imageInfo, &sharedImage);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
// add the image to the team
|
||||||
|
error = team->AddImage(sharedImage, imageInfo, teamID, 0);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
status_t _CreateThreadProfileResult(Thread* thread)
|
status_t _CreateThreadProfileResult(Thread* thread)
|
||||||
{
|
{
|
||||||
ThreadProfileResult* profileResult;
|
ThreadProfileResult* profileResult;
|
||||||
@@ -264,9 +319,47 @@ private:
|
|||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
status_t _GetSharedImage(team_id teamID, const image_info& imageInfo,
|
||||||
|
SharedImage** _sharedImage)
|
||||||
|
{
|
||||||
|
// check whether the image has already been loaded
|
||||||
|
ImageMap::iterator it = fImages.find(imageInfo.name);
|
||||||
|
if (it != fImages.end()) {
|
||||||
|
*_sharedImage = it->second;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create the shared image
|
||||||
|
SharedImage* sharedImage = new(std::nothrow) SharedImage;
|
||||||
|
if (sharedImage == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
ObjectDeleter<SharedImage> imageDeleter(sharedImage);
|
||||||
|
|
||||||
|
// load the symbols
|
||||||
|
status_t error = teamID == B_SYSTEM_TEAM
|
||||||
|
? sharedImage->Init(teamID, imageInfo.id)
|
||||||
|
: sharedImage->Init(imageInfo.name);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
try {
|
||||||
|
fImages[sharedImage->Name()] = sharedImage;
|
||||||
|
} catch (std::bad_alloc) {
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
imageDeleter.Detach();
|
||||||
|
*_sharedImage = sharedImage;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
typedef std::map<string, SharedImage*> ImageMap;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BObjectList<Team> fTeams;
|
BObjectList<Team> fTeams;
|
||||||
BObjectList<Thread> fThreads;
|
BObjectList<Thread> fThreads;
|
||||||
|
ImageMap fImages;
|
||||||
port_id fDebuggerPort;
|
port_id fDebuggerPort;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -433,7 +526,8 @@ profile_all()
|
|||||||
// create and area for the sample buffer
|
// create and area for the sample buffer
|
||||||
system_profiler_buffer_header* bufferHeader;
|
system_profiler_buffer_header* bufferHeader;
|
||||||
area_id area = create_area("profiling buffer", (void**)&bufferHeader,
|
area_id area = create_area("profiling buffer", (void**)&bufferHeader,
|
||||||
B_ANY_ADDRESS, PROFILE_ALL_SAMPLE_AREA_SIZE, B_NO_LOCK, B_READ_AREA);
|
B_ANY_ADDRESS, PROFILE_ALL_SAMPLE_AREA_SIZE, B_NO_LOCK,
|
||||||
|
B_READ_AREA | B_WRITE_AREA);
|
||||||
if (area < 0) {
|
if (area < 0) {
|
||||||
fprintf(stderr, "%s: Failed to create sample area: %s\n", kCommandName,
|
fprintf(stderr, "%s: Failed to create sample area: %s\n", kCommandName,
|
||||||
strerror(area));
|
strerror(area));
|
||||||
|
|||||||
Reference in New Issue
Block a user