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