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
18ImageDebugInfo::ImageDebugInfo(const ImageInfo& imageInfo)
19	:
20	fImageInfo(imageInfo),
21	fMainFunction(NULL)
22{
23}
24
25
26ImageDebugInfo::~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
38bool
39ImageDebugInfo::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
46status_t
47ImageDebugInfo::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
98status_t
99ImageDebugInfo::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
114bool
115ImageDebugInfo::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
128AddressSectionType
129ImageDebugInfo::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
143int32
144ImageDebugInfo::CountFunctions() const
145{
146	return fFunctions.CountItems();
147}
148
149
150FunctionInstance*
151ImageDebugInfo::FunctionAt(int32 index) const
152{
153	return fFunctions.ItemAt(index);
154}
155
156
157FunctionInstance*
158ImageDebugInfo::FunctionAtAddress(target_addr_t address) const
159{
160	return fFunctions.BinarySearchByKey(address, &_CompareAddressFunction);
161}
162
163
164FunctionInstance*
165ImageDebugInfo::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
177status_t
178ImageDebugInfo::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
195ImageDebugInfo::_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
204ImageDebugInfo::_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
214ImageDebugInfo::_CompareSymbols(const SymbolInfo* a, const SymbolInfo* b)
215{
216	return a->Address() < b->Address()
217		? -1 : (a->Address() == b->Address() ? 0 : 1);
218}
219