1/*
2 * Copyright 2016, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
4 */
5
6
7#include "CoreFileDebuggerInterface.h"
8
9#include <algorithm>
10#include <new>
11
12#include <errno.h>
13
14#include <AutoDeleter.h>
15
16#include "ArchitectureX86.h"
17#include "ArchitectureX8664.h"
18#include "CoreFile.h"
19#include "ElfSymbolLookup.h"
20#include "ImageInfo.h"
21#include "TeamInfo.h"
22#include "ThreadInfo.h"
23#include "Tracing.h"
24
25
26CoreFileDebuggerInterface::CoreFileDebuggerInterface(CoreFile* coreFile)
27	:
28	fCoreFile(coreFile),
29	fArchitecture(NULL)
30{
31}
32
33
34CoreFileDebuggerInterface::~CoreFileDebuggerInterface()
35{
36	if (fArchitecture != NULL)
37		fArchitecture->ReleaseReference();
38
39	delete fCoreFile;
40}
41
42
43status_t
44CoreFileDebuggerInterface::Init()
45{
46	// create the Architecture object
47	uint16 machine = fCoreFile->GetElfFile().Machine();
48	switch (machine) {
49		case EM_386:
50			fArchitecture = new(std::nothrow) ArchitectureX86(this);
51			break;
52		case EM_X86_64:
53			fArchitecture = new(std::nothrow) ArchitectureX8664(this);
54			break;
55		default:
56			WARNING("Unsupported core file machine (%u)\n", machine);
57			return B_UNSUPPORTED;
58	}
59
60	if (fArchitecture == NULL)
61		return B_NO_MEMORY;
62
63	return fArchitecture->Init();
64}
65
66
67void
68CoreFileDebuggerInterface::Close(bool killTeam)
69{
70}
71
72
73bool
74CoreFileDebuggerInterface::Connected() const
75{
76	return true;
77}
78
79
80bool
81CoreFileDebuggerInterface::IsPostMortem() const
82{
83	return true;
84}
85
86
87team_id
88CoreFileDebuggerInterface::TeamID() const
89{
90	return fCoreFile->GetTeamInfo().Id();
91}
92
93
94Architecture*
95CoreFileDebuggerInterface::GetArchitecture() const
96{
97	return fArchitecture;
98}
99
100
101status_t
102CoreFileDebuggerInterface::GetNextDebugEvent(DebugEvent*& _event)
103{
104	return B_UNSUPPORTED;
105}
106
107
108status_t
109CoreFileDebuggerInterface::SetTeamDebuggingFlags(uint32 flags)
110{
111	return B_UNSUPPORTED;
112}
113
114
115status_t
116CoreFileDebuggerInterface::ContinueThread(thread_id thread)
117{
118	return B_UNSUPPORTED;
119}
120
121
122status_t
123CoreFileDebuggerInterface::StopThread(thread_id thread)
124{
125	return B_UNSUPPORTED;
126}
127
128
129status_t
130CoreFileDebuggerInterface::SingleStepThread(thread_id thread)
131{
132	return B_UNSUPPORTED;
133}
134
135
136status_t
137CoreFileDebuggerInterface::InstallBreakpoint(target_addr_t address)
138{
139	return B_UNSUPPORTED;
140}
141
142
143status_t
144CoreFileDebuggerInterface::UninstallBreakpoint(target_addr_t address)
145{
146	return B_UNSUPPORTED;
147}
148
149
150status_t
151CoreFileDebuggerInterface::InstallWatchpoint(target_addr_t address, uint32 type,
152	int32 length)
153{
154	return B_UNSUPPORTED;
155}
156
157
158status_t
159CoreFileDebuggerInterface::UninstallWatchpoint(target_addr_t address)
160{
161	return B_UNSUPPORTED;
162}
163
164
165status_t
166CoreFileDebuggerInterface::GetSystemInfo(SystemInfo& info)
167{
168	return B_UNSUPPORTED;
169}
170
171
172status_t
173CoreFileDebuggerInterface::GetTeamInfo(TeamInfo& info)
174{
175	const CoreFileTeamInfo& coreInfo = fCoreFile->GetTeamInfo();
176	info.SetTo(coreInfo.Id(), coreInfo.Arguments());
177	return B_OK;
178}
179
180
181status_t
182CoreFileDebuggerInterface::GetThreadInfos(BObjectList<ThreadInfo>& infos)
183{
184	int32 count = fCoreFile->CountThreadInfos();
185	for (int32 i = 0; i < count; i++) {
186		const CoreFileThreadInfo* coreInfo = fCoreFile->ThreadInfoAt(i);
187		ThreadInfo* info = new(std::nothrow) ThreadInfo;
188		if (info == NULL || !infos.AddItem(info)) {
189			delete info;
190			return B_NO_MEMORY;
191		}
192
193		_GetThreadInfo(*coreInfo, *info);
194	}
195
196	return B_OK;
197}
198
199
200status_t
201CoreFileDebuggerInterface::GetImageInfos(BObjectList<ImageInfo>& infos)
202{
203	int32 count = fCoreFile->CountImageInfos();
204	for (int32 i = 0; i < count; i++) {
205		const CoreFileImageInfo* coreInfo = fCoreFile->ImageInfoAt(i);
206		ImageInfo* info = new(std::nothrow) ImageInfo;
207		if (info == NULL || !infos.AddItem(info)) {
208			delete info;
209			return B_NO_MEMORY;
210		}
211
212		info->SetTo(TeamID(), coreInfo->Id(), coreInfo->Name(),
213			(image_type)coreInfo->Type(), coreInfo->TextBase(),
214			coreInfo->TextSize(), coreInfo->DataBase(), coreInfo->DataSize());
215	}
216
217	return B_OK;
218}
219
220
221status_t
222CoreFileDebuggerInterface::GetAreaInfos(BObjectList<AreaInfo>& infos)
223{
224	return B_UNSUPPORTED;
225}
226
227
228status_t
229CoreFileDebuggerInterface::GetSemaphoreInfos(BObjectList<SemaphoreInfo>& infos)
230{
231	return B_UNSUPPORTED;
232}
233
234
235status_t
236CoreFileDebuggerInterface::GetSymbolInfos(team_id team, image_id image,
237	BObjectList<SymbolInfo>& infos)
238{
239	// get the image info
240	const CoreFileImageInfo* imageInfo = fCoreFile->ImageInfoForId(image);
241	if (imageInfo == NULL)
242		return B_BAD_IMAGE_ID;
243
244	if (const CoreFileSymbolsInfo* symbolsInfo = imageInfo->SymbolsInfo()) {
245		return GetElfSymbols(symbolsInfo->SymbolTable(),
246			symbolsInfo->SymbolCount(), symbolsInfo->SymbolTableEntrySize(),
247			symbolsInfo->StringTable(), symbolsInfo->StringTableSize(),
248			fCoreFile->GetElfFile().Is64Bit(),
249			fCoreFile->GetElfFile().IsByteOrderSwapped(),
250			imageInfo->TextDelta(), infos);
251	}
252
253	// get the symbols from the ELF file, if possible
254	status_t error = GetElfSymbols(imageInfo->Name(), imageInfo->TextDelta(),
255		infos);
256	if (error == B_OK)
257		return error;
258
259	// get the symbols from the core file, if possible
260	ElfSymbolLookup* symbolLookup;
261	error = fCoreFile->CreateSymbolLookup(imageInfo, symbolLookup);
262	if (error != B_OK) {
263		WARNING("Failed to create symbol lookup for image (%" B_PRId32
264			"): %s\n", image, strerror(error));
265		return error;
266	}
267
268	ObjectDeleter<ElfSymbolLookup> symbolLookupDeleter(symbolLookup);
269
270	return GetElfSymbols(symbolLookup, infos);
271}
272
273
274status_t
275CoreFileDebuggerInterface::GetSymbolInfo(team_id team, image_id image,
276	const char* name, int32 symbolType, SymbolInfo& info)
277{
278	// TODO:...
279	return B_UNSUPPORTED;
280}
281
282
283status_t
284CoreFileDebuggerInterface::GetThreadInfo(thread_id thread, ThreadInfo& info)
285{
286	const CoreFileThreadInfo* coreInfo = fCoreFile->ThreadInfoForId(thread);
287	if (coreInfo == NULL)
288		return B_BAD_THREAD_ID;
289
290	_GetThreadInfo(*coreInfo, info);
291	return B_OK;
292}
293
294
295status_t
296CoreFileDebuggerInterface::GetCpuState(thread_id thread, CpuState*& _state)
297{
298	const CoreFileThreadInfo* coreInfo = fCoreFile->ThreadInfoForId(thread);
299	if (coreInfo == NULL)
300		return B_BAD_THREAD_ID;
301
302	return fArchitecture->CreateCpuState(coreInfo->GetCpuState(),
303		coreInfo->CpuStateSize(), _state);
304}
305
306
307status_t
308CoreFileDebuggerInterface::SetCpuState(thread_id thread, const CpuState* state)
309{
310	return B_UNSUPPORTED;
311}
312
313
314status_t
315CoreFileDebuggerInterface::GetCpuFeatures(uint32& flags)
316{
317	return fArchitecture->GetCpuFeatures(flags);
318}
319
320
321status_t
322CoreFileDebuggerInterface::WriteCoreFile(const char* path)
323{
324	return B_NOT_SUPPORTED;
325}
326
327
328status_t
329CoreFileDebuggerInterface::GetMemoryProperties(target_addr_t address,
330	uint32& protection, uint32& locking)
331{
332	const CoreFileAreaInfo* info = fCoreFile->AreaInfoForAddress(address);
333	if (info == NULL)
334		return B_BAD_ADDRESS;
335
336	protection = info->Protection() & ~(uint32)B_WRITE_AREA;
337		// Filter out write protection, since we don't support writing memory.
338	locking = info->Locking();
339	return B_OK;
340}
341
342
343ssize_t
344CoreFileDebuggerInterface::ReadMemory(target_addr_t address, void* _buffer,
345	size_t size)
346{
347	if (size == 0)
348		return B_OK;
349
350	ssize_t totalRead = 0;
351	uint8* buffer = (uint8*)_buffer;
352
353	while (size > 0) {
354		const CoreFileAreaInfo* info = fCoreFile->AreaInfoForAddress(address);
355		if (info == NULL)
356			return totalRead > 0 ? totalRead : B_BAD_ADDRESS;
357
358		ElfSegment* segment = info->Segment();
359		uint64 offset = address - segment->LoadAddress();
360		if (offset >= segment->FileSize())
361			return totalRead > 0 ? totalRead : B_BAD_ADDRESS;
362
363		size_t toRead = (size_t)std::min((uint64)size,
364			segment->FileSize() - offset);
365		ssize_t bytesRead = pread(fCoreFile->GetElfFile().FD(), buffer, toRead,
366			segment->FileOffset() + offset);
367		if (bytesRead <= 0) {
368			status_t error = bytesRead == 0 ? B_IO_ERROR : errno;
369			return totalRead > 0 ? totalRead : error;
370		}
371
372		buffer += bytesRead;
373		size -= bytesRead;
374		totalRead += bytesRead;
375	}
376
377	return totalRead;
378}
379
380
381ssize_t
382CoreFileDebuggerInterface::WriteMemory(target_addr_t address, void* buffer,
383	size_t size)
384{
385	return B_UNSUPPORTED;
386}
387
388
389void
390CoreFileDebuggerInterface::_GetThreadInfo(const CoreFileThreadInfo& coreInfo,
391	ThreadInfo& info)
392{
393	info.SetTo(TeamID(), coreInfo.Id(), coreInfo.Name());
394}
395