1 /* 2 * Copyright 2008-2009, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include "SharedImage.h" 8 9 #include <stdio.h> 10 11 #include <algorithm> 12 #include <new> 13 14 #include <debug_support.h> 15 #include <ObjectList.h> 16 17 #include "Options.h" 18 19 20 SharedImage::SharedImage() 21 : 22 fSymbols(NULL), 23 fSymbolCount(0) 24 { 25 } 26 27 28 SharedImage::~SharedImage() 29 { 30 if (fSymbols != NULL) { 31 for (int32 i = 0; i < fSymbolCount; i++) 32 delete fSymbols[i]; 33 delete[] fSymbols; 34 } 35 } 36 37 38 status_t 39 SharedImage::Init(team_id owner, image_id imageID) 40 { 41 // we need a temporary symbol lookup context 42 debug_symbol_lookup_context* lookupContext; 43 status_t error = debug_create_symbol_lookup_context(owner, imageID, 44 &lookupContext); 45 if (error != B_OK) { 46 fprintf(stderr, "%s: Failed to create symbol lookup context " 47 "for team %" B_PRId32 ": %s\n", 48 kCommandName, owner, strerror(error)); 49 return error; 50 } 51 52 // TODO: Creating a symbol lookup just for loading the symbols of a single 53 // image is unnecessarily expensive. 54 55 // create a symbol iterator 56 debug_symbol_iterator* iterator; 57 error = debug_create_image_symbol_iterator(lookupContext, imageID, 58 &iterator); 59 if (error != B_OK) { 60 fprintf(stderr, 61 "Failed to init symbol iterator for image %" B_PRId32 ": %s\n", 62 imageID, strerror(error)); 63 debug_delete_symbol_lookup_context(lookupContext); 64 return error; 65 } 66 67 // init 68 error = _Init(iterator); 69 70 // cleanup 71 debug_delete_symbol_iterator(iterator); 72 debug_delete_symbol_lookup_context(lookupContext); 73 74 return error; 75 } 76 77 78 status_t 79 SharedImage::Init(const char* path) 80 { 81 // create a symbol iterator 82 debug_symbol_iterator* iterator; 83 status_t error = debug_create_file_symbol_iterator(path, &iterator); 84 if (error != B_OK) { 85 fprintf(stderr, "Failed to init symbol iterator for \"%s\": %s\n", 86 path, strerror(error)); 87 return error; 88 } 89 90 error = _Init(iterator); 91 92 debug_delete_symbol_iterator(iterator); 93 94 return error; 95 } 96 97 98 int32 99 SharedImage::FindSymbol(addr_t address) const 100 { 101 // binary search the function 102 int32 lower = 0; 103 int32 upper = fSymbolCount; 104 105 while (lower < upper) { 106 int32 mid = (lower + upper) / 2; 107 if (address >= fSymbols[mid]->base + fSymbols[mid]->size) 108 lower = mid + 1; 109 else 110 upper = mid; 111 } 112 113 if (lower == fSymbolCount) 114 return -1; 115 116 const Symbol* symbol = fSymbols[lower]; 117 if (address >= symbol->base && address < symbol->base + symbol->size) 118 return lower; 119 return -1; 120 } 121 122 123 status_t 124 SharedImage::_Init(debug_symbol_iterator* iterator) 125 { 126 // get an image info 127 status_t error = debug_get_symbol_iterator_image_info(iterator, &fInfo); 128 if (error != B_OK) 129 return error; 130 131 // iterate through the symbols 132 BObjectList<Symbol> symbols(512, true); 133 char symbolName[1024]; 134 int32 symbolType; 135 void* symbolLocation; 136 size_t symbolSize; 137 while (debug_next_image_symbol(iterator, symbolName, sizeof(symbolName), 138 &symbolType, &symbolLocation, &symbolSize) == B_OK) { 139 // printf(" %s %p (%6lu) %s\n", 140 // symbolType == B_SYMBOL_TYPE_TEXT ? "text" : "data", 141 // symbolLocation, symbolSize, symbolName); 142 if (symbolSize > 0 && symbolType == B_SYMBOL_TYPE_TEXT) { 143 Symbol* symbol = new(std::nothrow) Symbol(this, 144 (addr_t)symbolLocation, symbolSize, symbolName); 145 if (symbol == NULL || !symbols.AddItem(symbol)) { 146 delete symbol; 147 fprintf(stderr, "%s: Out of memory\n", kCommandName); 148 return B_NO_MEMORY; 149 } 150 } 151 } 152 153 // sort the symbols 154 fSymbolCount = symbols.CountItems(); 155 fSymbols = new(std::nothrow) Symbol*[fSymbolCount]; 156 if (fSymbols == NULL) 157 return B_NO_MEMORY; 158 159 for (int32 i = fSymbolCount - 1; i >= 0 ; i--) 160 fSymbols[i] = symbols.RemoveItemAt(i); 161 162 std::sort(fSymbols, fSymbols + fSymbolCount, SymbolComparator()); 163 164 return B_OK; 165 } 166