diff --git a/src/bin/debug/profile/BasicThreadProfileResult.cpp b/src/bin/debug/profile/BasicThreadProfileResult.cpp index f12d664fb7..a04257fcde 100644 --- a/src/bin/debug/profile/BasicThreadProfileResult.cpp +++ b/src/bin/debug/profile/BasicThreadProfileResult.cpp @@ -14,8 +14,9 @@ struct HitSymbol { - int64 hits; - Symbol* symbol; + int64 hits; + Symbol* symbol; + image_id imageID; inline bool operator<(const HitSymbol& other) const { @@ -146,6 +147,7 @@ BasicThreadProfileResult::PrintResults() HitSymbol& hitSymbol = hitSymbols[hitSymbolCount++]; hitSymbol.hits = symbolHits[i]; hitSymbol.symbol = symbols[i]; + hitSymbol.imageID = image->ID(); } } } @@ -180,10 +182,9 @@ BasicThreadProfileResult::PrintResults() "---------------------------------------\n"); for (int32 k = 0; k < imageCount; k++) { BasicThreadImage* image = images[k]; - const image_info& imageInfo = image->GetImage()->Info(); fprintf(gOptions.output, " %10lld %10lld %7ld %s\n", - image->TotalHits(), image->UnknownHits(), imageInfo.id, - imageInfo.name); + image->TotalHits(), image->UnknownHits(), + image->GetImage()->ID(), image->GetImage()->Name()); } } @@ -198,7 +199,7 @@ BasicThreadProfileResult::PrintResults() const Symbol* symbol = hitSymbol.symbol; fprintf(gOptions.output, " %10lld %10lld %6.2f %6ld %s\n", hitSymbol.hits, hitSymbol.hits * fInterval, - 100.0 * hitSymbol.hits / totalTicks, symbol->image->ID(), + 100.0 * hitSymbol.hits / totalTicks, hitSymbol.imageID, symbol->Name()); } } else diff --git a/src/bin/debug/profile/CallgrindThreadProfileResult.cpp b/src/bin/debug/profile/CallgrindThreadProfileResult.cpp index dce9bcb3cb..e38b45931c 100644 --- a/src/bin/debug/profile/CallgrindThreadProfileResult.cpp +++ b/src/bin/debug/profile/CallgrindThreadProfileResult.cpp @@ -271,7 +271,7 @@ CallgrindThreadProfileResult::_PrintFunction(FILE* out, int32 index = fNextImageOutputIndex++; image->SetOutputIndex(index); fprintf(out, "%sob=(%ld) %s:%ld\n", called ? "c" : "", index, - image->GetImage()->Info().name, image->ID()); + image->GetImage()->Name(), image->ID()); } else { // image is already known // TODO: We may not need to print it at all! diff --git a/src/bin/debug/profile/Image.cpp b/src/bin/debug/profile/Image.cpp index 2d1b051bbf..3e93b6262d 100644 --- a/src/bin/debug/profile/Image.cpp +++ b/src/bin/debug/profile/Image.cpp @@ -5,115 +5,22 @@ #include "Image.h" -#include -#include -#include - -#include -#include - -#include "Options.h" - - -Image::Image(const image_info& info, team_id owner, int32 creationEvent) +Image::Image(SharedImage* image, const image_info& info, team_id owner, + int32 creationEvent) : - fInfo(info), + fImage(image), + fID(info.id), fOwner(owner), - fSymbols(NULL), - fSymbolCount(0), + fLoadDelta((addr_t)info.text - (addr_t)image->Info().text), fCreationEvent(creationEvent), fDeletionEvent(-1) { + fImage->AddReference(); } Image::~Image() { - if (fSymbols != NULL) { - 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 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; + fImage->RemoveReference(); } diff --git a/src/bin/debug/profile/Image.h b/src/bin/debug/profile/Image.h index 530b77cbc8..97c6b18f4c 100644 --- a/src/bin/debug/profile/Image.h +++ b/src/bin/debug/profile/Image.h @@ -5,73 +5,35 @@ #ifndef IMAGE_H #define IMAGE_H -#include -#include -#include - -#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; - } -}; +#include "SharedImage.h" class Image : public Referenceable { public: - Image(const image_info& info, team_id owner, + Image(SharedImage* image, + const image_info& info, team_id owner, int32 creationEvent); ~Image(); inline const image_id ID() const; - inline const image_info& Info() const; + inline const char* Name() const; inline team_id Owner() const; inline int32 CreationEvent() const; inline int32 DeletionEvent() const; inline void SetDeletionEvent(int32 event); - status_t LoadSymbols( - debug_symbol_lookup_context* lookupContext); - inline Symbol** Symbols() const; inline int32 SymbolCount() const; inline bool ContainsAddress(addr_t address) const; - int32 FindSymbol(addr_t address) const; + inline int32 FindSymbol(addr_t address) const; private: - image_info fInfo; + SharedImage* fImage; + image_id fID; team_id fOwner; - Symbol** fSymbols; - int32 fSymbolCount; + addr_t fLoadDelta; int32 fCreationEvent; int32 fDeletionEvent; }; @@ -83,14 +45,14 @@ private: const image_id Image::ID() const { - return fInfo.id; + return fID; } -const image_info& -Image::Info() const +const char* +Image::Name() const { - return fInfo; + return fImage->Name(); } @@ -125,22 +87,28 @@ Image::SetDeletionEvent(int32 event) Symbol** Image::Symbols() const { - return fSymbols; + return fImage->Symbols(); } int32 Image::SymbolCount() const { - return fSymbolCount; + return fImage->SymbolCount(); } bool Image::ContainsAddress(addr_t address) const { - return address >= (addr_t)fInfo.text - && address <= (addr_t)fInfo.data + fInfo.data_size - 1; + return fImage->ContainsAddress(address - fLoadDelta); +} + + +int32 +Image::FindSymbol(addr_t address) const +{ + return fImage->FindSymbol(address - fLoadDelta); } diff --git a/src/bin/debug/profile/Jamfile b/src/bin/debug/profile/Jamfile index c5bb6f1aec..72d47fba64 100644 --- a/src/bin/debug/profile/Jamfile +++ b/src/bin/debug/profile/Jamfile @@ -13,6 +13,7 @@ BinCommand profile BasicThreadProfileResult.cpp CallgrindThreadProfileResult.cpp Image.cpp + SharedImage.cpp Team.cpp Thread.cpp profile.cpp diff --git a/src/bin/debug/profile/Team.cpp b/src/bin/debug/profile/Team.cpp index 1efb342e00..ef403ea2bd 100644 --- a/src/bin/debug/profile/Team.cpp +++ b/src/bin/debug/profile/Team.cpp @@ -78,37 +78,6 @@ Team::Init(team_id teamID, port_id debuggerPort) 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 int32 teamDebugFlags = B_TEAM_DEBUG_THREADS | B_TEAM_DEBUG_TEAM_CREATION | B_TEAM_DEBUG_IMAGES; @@ -230,32 +199,28 @@ Team::Exec(int32 event) 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 - debug_symbol_lookup_context* 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, owner, strerror(error)); - return error; - } + // create the image + Image* image = new(std::nothrow) Image(sharedImage, imageInfo, owner, + event); + if (image == NULL) + return B_NO_MEMORY; - Image* image; - error = _LoadImageSymbols(lookupContext, imageInfo, owner, event, - &image); - debug_delete_symbol_lookup_context(lookupContext); + if (!fImages.AddItem(image)) { + delete image; + return B_NO_MEMORY; + } // Although we generally synchronize the threads' images lazily, we have // to add new images at least, since otherwise images could be added // and removed again, and the hits inbetween could never be matched. - if (error == B_OK) { - ThreadList::Iterator it = fThreads.GetIterator(); - while (Thread* thread = it.Next()) - thread->AddImage(image); - } + ThreadList::Iterator it = fThreads.GetIterator(); + while (Thread* thread = it.Next()) + 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 Team::_RemoveImage(int32 index, int32 event) { diff --git a/src/bin/debug/profile/Team.h b/src/bin/debug/profile/Team.h index 60773ad4a4..304abf8a8c 100644 --- a/src/bin/debug/profile/Team.h +++ b/src/bin/debug/profile/Team.h @@ -28,8 +28,9 @@ public: void Exec(int32 event); - status_t AddImage(const image_info& imageInfo, - team_id owner, int32 event); + status_t AddImage(SharedImage* sharedImage, + const image_info& imageInfo, team_id owner, + int32 event); status_t RemoveImage(image_id imageID, int32 event); inline const BObjectList& Images() const; @@ -38,13 +39,6 @@ public: inline team_id ID() const; 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); bool _SynchronousProfiling() const diff --git a/src/bin/debug/profile/profile.cpp b/src/bin/debug/profile/profile.cpp index 918c69ed41..16434eeff5 100644 --- a/src/bin/debug/profile/profile.cpp +++ b/src/bin/debug/profile/profile.cpp @@ -11,7 +11,9 @@ #include #include +#include #include +#include #include #include @@ -20,6 +22,7 @@ #include #include +#include #include #include #include @@ -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) { return _AddTeam(teamID, NULL, _team); @@ -186,16 +196,24 @@ public: 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) { // 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); + for (int32 i = 0; i < count; i++) { + fTeams.ItemAt(i)->AddImage(sharedImage, imageInfo, teamID, + event); + } } // a userland team image -- add it to that image if (Team* team = FindTeam(teamID)) - return team->AddImage(imageInfo, teamID, event); + return team->AddImage(sharedImage, imageInfo, teamID, event); return B_BAD_TEAM_ID; } @@ -227,7 +245,7 @@ private: status_t error = addedInfo != NULL ? team->Init(addedInfo) - : team->Init(teamID, fDebuggerPort); + : _InitDebuggedTeam(team, teamID); if (error != B_OK) { delete team; return error; @@ -241,6 +259,43 @@ private: 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) { ThreadProfileResult* profileResult; @@ -264,9 +319,47 @@ private: 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 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 ImageMap; + private: BObjectList fTeams; BObjectList fThreads; + ImageMap fImages; port_id fDebuggerPort; }; @@ -433,7 +526,8 @@ profile_all() // 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); + B_ANY_ADDRESS, PROFILE_ALL_SAMPLE_AREA_SIZE, B_NO_LOCK, + B_READ_AREA | B_WRITE_AREA); if (area < 0) { fprintf(stderr, "%s: Failed to create sample area: %s\n", kCommandName, strerror(area));