From a0320c161dfcfd5fcfcd5c79c56e534d19b897f4 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Wed, 15 Apr 2009 15:14:24 +0000 Subject: [PATCH] Darn, should have been part of r30170 already. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@30173 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/bin/debug/profile/SharedImage.cpp | 161 ++++++++++++++++++++++++++ src/bin/debug/profile/SharedImage.h | 114 ++++++++++++++++++ 2 files changed, 275 insertions(+) create mode 100644 src/bin/debug/profile/SharedImage.cpp create mode 100644 src/bin/debug/profile/SharedImage.h diff --git a/src/bin/debug/profile/SharedImage.cpp b/src/bin/debug/profile/SharedImage.cpp new file mode 100644 index 0000000000..54b5380582 --- /dev/null +++ b/src/bin/debug/profile/SharedImage.cpp @@ -0,0 +1,161 @@ +/* + * Copyright 2008-2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ + +#include "SharedImage.h" + +#include + +#include +#include + +#include +#include + +#include "Options.h" + + +SharedImage::SharedImage() + : + fSymbols(NULL), + fSymbolCount(0) +{ +} + + +SharedImage::~SharedImage() +{ + if (fSymbols != NULL) { + for (int32 i = 0; i < fSymbolCount; i++) + delete fSymbols[i]; + delete[] fSymbols; + } +} + + +status_t +SharedImage::Init(team_id owner, image_id imageID) +{ + // we need a temporary 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; + } + // TODO: Creating a symbol lookup just for loading the symbols of a single + // image is unnecessarily expensive. + + // create a symbol iterator + debug_symbol_iterator* iterator; + error = debug_create_image_symbol_iterator(lookupContext, imageID, + &iterator); + if (error != B_OK) { + fprintf(stderr, "Failed to init symbol iterator: %s\n", + strerror(error)); + debug_delete_symbol_iterator(iterator); + return error; + } + + // init + error = _Init(iterator); + + // cleanup + debug_delete_symbol_iterator(iterator); + debug_delete_symbol_lookup_context(lookupContext); + + return error; +} + + +status_t +SharedImage::Init(const char* path) +{ + // create a symbol iterator + debug_symbol_iterator* iterator; + status_t error = debug_create_file_symbol_iterator(path, &iterator); + if (error != B_OK) { + fprintf(stderr, "Failed to init symbol iterator: %s\n", + strerror(error)); + return error; + } + + error = _Init(iterator); + + debug_delete_symbol_iterator(iterator); + + return error; +} + + +int32 +SharedImage::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; +} + + +status_t +SharedImage::_Init(debug_symbol_iterator* iterator) +{ + // get an image info + status_t error = debug_get_symbol_iterator_image_info(iterator, &fInfo); + if (error != B_OK) + 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; + } + } + } + + // 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; +} diff --git a/src/bin/debug/profile/SharedImage.h b/src/bin/debug/profile/SharedImage.h new file mode 100644 index 0000000000..38a2ab0a85 --- /dev/null +++ b/src/bin/debug/profile/SharedImage.h @@ -0,0 +1,114 @@ +/* + * Copyright 2008-2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ +#ifndef SHARED_IMAGE_H +#define SHARED_IMAGE_H + +#include +#include +#include + +#include "Referenceable.h" + + +class debug_symbol_iterator; +class debug_symbol_lookup_context; +class SharedImage; + + +class Symbol { +public: + Symbol(SharedImage* 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(); } + + SharedImage* 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 SharedImage : public Referenceable { +public: + SharedImage(); + ~SharedImage(); + + status_t Init(team_id owner, image_id imageID); + status_t Init(const char* path); + + inline const char* Name() const; + inline const image_info& Info() const; + + inline Symbol** Symbols() const; + inline int32 SymbolCount() const; + + inline bool ContainsAddress(addr_t address) const; + int32 FindSymbol(addr_t address) const; + +private: + status_t _Init(debug_symbol_iterator* iterator); + +private: + image_info fInfo; + Symbol** fSymbols; + int32 fSymbolCount; +}; + + +// #pragma mark - + + +const char* +SharedImage::Name() const +{ + return fInfo.name; +} + + +const image_info& +SharedImage::Info() const +{ + return fInfo; +} + + +Symbol** +SharedImage::Symbols() const +{ + return fSymbols; +} + + +int32 +SharedImage::SymbolCount() const +{ + return fSymbolCount; +} + + +bool +SharedImage::ContainsAddress(addr_t address) const +{ + return address >= (addr_t)fInfo.text + && address <= (addr_t)fInfo.data + fInfo.data_size - 1; +} + + +#endif // SHARED_IMAGE_H