1 /* 2 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Copyright 2010-2017, Rene Gollent, rene@gollent.com. 4 * Distributed under the terms of the MIT License. 5 */ 6 7 #include "ImageDebugInfo.h" 8 9 #include <new> 10 11 #include "DebuggerInterface.h" 12 #include "FunctionDebugInfo.h" 13 #include "FunctionInstance.h" 14 #include "SpecificImageDebugInfo.h" 15 #include "SymbolInfo.h" 16 17 18 ImageDebugInfo::ImageDebugInfo(const ImageInfo& imageInfo) 19 : 20 fImageInfo(imageInfo), 21 fMainFunction(NULL) 22 { 23 } 24 25 26 ImageDebugInfo::~ImageDebugInfo() 27 { 28 for (int32 i = 0; FunctionInstance* function = fFunctions.ItemAt(i); i++) 29 function->ReleaseReference(); 30 31 for (int32 i = 0; SpecificImageDebugInfo* info = fSpecificInfos.ItemAt(i); 32 i++) { 33 info->ReleaseReference(); 34 } 35 } 36 37 38 bool 39 ImageDebugInfo::AddSpecificInfo(SpecificImageDebugInfo* info) 40 { 41 // NB: on success we take over the caller's reference to the info object 42 return fSpecificInfos.AddItem(info); 43 } 44 45 46 status_t 47 ImageDebugInfo::FinishInit(DebuggerInterface* interface) 48 { 49 BObjectList<SymbolInfo> symbols(50, true); 50 status_t error = interface->GetSymbolInfos(fImageInfo.TeamID(), 51 fImageInfo.ImageID(), symbols); 52 if (error != B_OK) 53 return error; 54 symbols.SortItems(&_CompareSymbols); 55 56 // get functions -- get them from most expressive debug info first and add 57 // missing functions from less expressive debug infos 58 for (int32 i = 0; SpecificImageDebugInfo* specificInfo 59 = fSpecificInfos.ItemAt(i); i++) { 60 BObjectList<FunctionDebugInfo> functions; 61 error = specificInfo->GetFunctions(symbols, functions); 62 if (error != B_OK) 63 return error; 64 65 for (int32 k = 0; FunctionDebugInfo* function = functions.ItemAt(k); 66 k++) { 67 if (FunctionAtAddress(function->Address()) != NULL) 68 continue; 69 70 FunctionInstance* instance = new(std::nothrow) FunctionInstance( 71 this, function); 72 if (instance == NULL 73 || !fFunctions.BinaryInsert(instance, &_CompareFunctions)) { 74 delete instance; 75 error = B_NO_MEMORY; 76 break; 77 } 78 79 if (function->IsMain()) 80 fMainFunction = instance; 81 } 82 83 // Remove references returned by the specific debug info -- the 84 // FunctionInstance objects have references, now. 85 for (int32 k = 0; FunctionDebugInfo* function = functions.ItemAt(k); 86 k++) { 87 function->ReleaseReference(); 88 } 89 90 if (error != B_OK) 91 return error; 92 } 93 94 return B_OK; 95 } 96 97 98 status_t 99 ImageDebugInfo::GetType(GlobalTypeCache* cache, const BString& name, 100 const TypeLookupConstraints& constraints, Type*& _type) 101 { 102 for (int32 i = 0; SpecificImageDebugInfo* specificInfo 103 = fSpecificInfos.ItemAt(i); i++) { 104 status_t error = specificInfo->GetType(cache, name, constraints, 105 _type); 106 if (error == B_OK || error == B_NO_MEMORY) 107 return error; 108 } 109 110 return B_ENTRY_NOT_FOUND; 111 } 112 113 114 bool 115 ImageDebugInfo::HasType(const BString& name, 116 const TypeLookupConstraints& constraints) const 117 { 118 for (int32 i = 0; SpecificImageDebugInfo* specificInfo 119 = fSpecificInfos.ItemAt(i); i++) { 120 if (specificInfo->HasType(name, constraints)) 121 return true; 122 } 123 124 return false; 125 } 126 127 128 AddressSectionType 129 ImageDebugInfo::GetAddressSectionType(target_addr_t address) const 130 { 131 AddressSectionType type = ADDRESS_SECTION_TYPE_UNKNOWN; 132 for (int32 i = 0; SpecificImageDebugInfo* specificInfo 133 = fSpecificInfos.ItemAt(i); i++) { 134 type = specificInfo->GetAddressSectionType(address); 135 if (type != ADDRESS_SECTION_TYPE_UNKNOWN) 136 break; 137 } 138 139 return type; 140 } 141 142 143 int32 144 ImageDebugInfo::CountFunctions() const 145 { 146 return fFunctions.CountItems(); 147 } 148 149 150 FunctionInstance* 151 ImageDebugInfo::FunctionAt(int32 index) const 152 { 153 return fFunctions.ItemAt(index); 154 } 155 156 157 FunctionInstance* 158 ImageDebugInfo::FunctionAtAddress(target_addr_t address) const 159 { 160 return fFunctions.BinarySearchByKey(address, &_CompareAddressFunction); 161 } 162 163 164 FunctionInstance* 165 ImageDebugInfo::FunctionByName(const char* name) const 166 { 167 // TODO: Not really optimal. 168 for (int32 i = 0; FunctionInstance* function = fFunctions.ItemAt(i); i++) { 169 if (function->Name() == name) 170 return function; 171 } 172 173 return NULL; 174 } 175 176 177 status_t 178 ImageDebugInfo::AddSourceCodeInfo(LocatableFile* file, 179 FileSourceCode* sourceCode) const 180 { 181 bool addedAny = false; 182 for (int32 i = 0; SpecificImageDebugInfo* specificInfo 183 = fSpecificInfos.ItemAt(i); i++) { 184 status_t error = specificInfo->AddSourceCodeInfo(file, sourceCode); 185 if (error == B_NO_MEMORY) 186 return error; 187 addedAny |= error == B_OK; 188 } 189 190 return addedAny ? B_OK : B_ENTRY_NOT_FOUND; 191 } 192 193 194 /*static*/ int 195 ImageDebugInfo::_CompareFunctions(const FunctionInstance* a, 196 const FunctionInstance* b) 197 { 198 return a->Address() < b->Address() 199 ? -1 : (a->Address() == b->Address() ? 0 : 1); 200 } 201 202 203 /*static*/ int 204 ImageDebugInfo::_CompareAddressFunction(const target_addr_t* address, 205 const FunctionInstance* function) 206 { 207 if (*address < function->Address()) 208 return -1; 209 return *address < function->Address() + function->Size() ? 0 : 1; 210 } 211 212 213 /*static*/ int 214 ImageDebugInfo::_CompareSymbols(const SymbolInfo* a, const SymbolInfo* b) 215 { 216 return a->Address() < b->Address() 217 ? -1 : (a->Address() == b->Address() ? 0 : 1); 218 } 219