xref: /haiku/src/kits/debugger/debug_info/ImageDebugInfo.cpp (revision 1a76488fc88584bf66b9751d7fb9b6527ac20d87)
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