1/*
2 * Copyright 2009-2012, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Copyright 2010-2016, Rene Gollent, rene@gollent.com.
4 * Distributed under the terms of the MIT License.
5 */
6
7#include "LocalDebuggerInterface.h"
8
9#include <new>
10
11#include <stdio.h>
12
13#include <Locker.h>
14
15#include <AutoLocker.h>
16#include <memory_private.h>
17#include <OS.h>
18#include <system_info.h>
19#include <util/DoublyLinkedList.h>
20#include <util/KMessage.h>
21
22#include "debug_utils.h"
23
24#include "ArchitectureX86.h"
25#include "ArchitectureX8664.h"
26#include "AreaInfo.h"
27#include "AutoDeleter.h"
28#include "CpuState.h"
29#include "DebugEvent.h"
30#include "ImageInfo.h"
31#include "SemaphoreInfo.h"
32#include "SymbolInfo.h"
33#include "SystemInfo.h"
34#include "TeamInfo.h"
35#include "ThreadInfo.h"
36
37
38// number of debug contexts the pool does initially create
39static const int kInitialDebugContextCount = 3;
40
41// maximum number of debug contexts in the pool
42static const int kMaxDebugContextCount = 10;
43
44
45// #pragma mark - LocalDebuggerInterface::DebugContext
46
47struct LocalDebuggerInterface::DebugContext : debug_context,
48		DoublyLinkedListLinkImpl<DebugContext> {
49	DebugContext()
50	{
51		team = -1;
52		nub_port = -1;
53		reply_port = -1;
54	}
55
56	~DebugContext()
57	{
58		if (reply_port >= 0)
59			destroy_debug_context(this);
60	}
61
62	status_t Init(team_id team, port_id nubPort)
63	{
64		return init_debug_context(this, team, nubPort);
65	}
66
67	void Close()
68	{
69		if (reply_port >= 0) {
70			destroy_debug_context(this);
71			team = -1;
72			nub_port = -1;
73			reply_port = -1;
74		}
75	}
76};
77
78// #pragma mark - LocalDebuggerInterface::DebugContextPool
79
80struct LocalDebuggerInterface::DebugContextPool {
81	DebugContextPool(team_id team, port_id nubPort)
82		:
83		fLock("debug context pool"),
84		fTeam(team),
85		fNubPort(nubPort),
86		fBlockSem(-1),
87		fContextCount(0),
88		fWaiterCount(0),
89		fClosed(false)
90	{
91	}
92
93	~DebugContextPool()
94	{
95		AutoLocker<BLocker> locker(fLock);
96
97		while (DebugContext* context = fFreeContexts.RemoveHead())
98			delete context;
99
100		if (fBlockSem >= 0)
101			delete_sem(fBlockSem);
102	}
103
104	status_t Init()
105	{
106		status_t error = fLock.InitCheck();
107		if (error != B_OK)
108			return error;
109
110		fBlockSem = create_sem(0, "debug context pool block");
111		if (fBlockSem < 0)
112			return fBlockSem;
113
114		for (int i = 0; i < kInitialDebugContextCount; i++) {
115			DebugContext* context;
116			error = _CreateDebugContext(context);
117			if (error != B_OK)
118				return error;
119
120			fFreeContexts.Add(context);
121		}
122
123		return B_OK;
124	}
125
126	void Close()
127	{
128		AutoLocker<BLocker> locker(fLock);
129		fClosed = true;
130
131		for (DebugContextList::Iterator it = fFreeContexts.GetIterator();
132				DebugContext* context = it.Next();) {
133			context->Close();
134		}
135
136		for (DebugContextList::Iterator it = fUsedContexts.GetIterator();
137				DebugContext* context = it.Next();) {
138			context->Close();
139		}
140	}
141
142	DebugContext* GetContext()
143	{
144		AutoLocker<BLocker> locker(fLock);
145		DebugContext* context = fFreeContexts.RemoveHead();
146
147		if (context == NULL) {
148			if (fContextCount >= kMaxDebugContextCount
149				|| _CreateDebugContext(context) != B_OK) {
150				// wait for a free context
151				while (context == NULL) {
152					fWaiterCount++;
153					locker.Unlock();
154					while (acquire_sem(fBlockSem) != B_OK);
155					locker.Lock();
156					context = fFreeContexts.RemoveHead();
157				}
158			}
159		}
160
161		fUsedContexts.Add(context);
162
163		return context;
164	}
165
166	void PutContext(DebugContext* context)
167	{
168		AutoLocker<BLocker> locker(fLock);
169		fUsedContexts.Remove(context);
170		fFreeContexts.Add(context);
171
172		if (fWaiterCount > 0)
173			release_sem(fBlockSem);
174	}
175
176private:
177	typedef DoublyLinkedList<DebugContext> DebugContextList;
178
179private:
180	status_t _CreateDebugContext(DebugContext*& _context)
181	{
182		DebugContext* context = new(std::nothrow) DebugContext;
183		if (context == NULL)
184			return B_NO_MEMORY;
185
186		if (!fClosed) {
187			status_t error = context->Init(fTeam, fNubPort);
188			if (error != B_OK) {
189				delete context;
190				return error;
191			}
192		}
193
194		fContextCount++;
195
196		_context = context;
197		return B_OK;
198	}
199
200private:
201	BLocker				fLock;
202	team_id				fTeam;
203	port_id				fNubPort;
204	sem_id				fBlockSem;
205	int32				fContextCount;
206	int32				fWaiterCount;
207	DebugContextList	fFreeContexts;
208	DebugContextList	fUsedContexts;
209	bool				fClosed;
210};
211
212
213struct LocalDebuggerInterface::DebugContextGetter {
214	DebugContextGetter(DebugContextPool* pool)
215		:
216		fPool(pool),
217		fContext(pool->GetContext())
218	{
219	}
220
221	~DebugContextGetter()
222	{
223		fPool->PutContext(fContext);
224	}
225
226	DebugContext* Context() const
227	{
228		return fContext;
229	}
230
231private:
232	DebugContextPool*	fPool;
233	DebugContext*		fContext;
234};
235
236// #pragma mark - LocalDebuggerInterface
237
238LocalDebuggerInterface::LocalDebuggerInterface(team_id team)
239	:
240	DebuggerInterface(),
241	fTeamID(team),
242	fDebuggerPort(-1),
243	fNubPort(-1),
244	fDebugContextPool(NULL),
245	fArchitecture(NULL)
246{
247}
248
249
250LocalDebuggerInterface::~LocalDebuggerInterface()
251{
252	if (fArchitecture != NULL)
253		fArchitecture->ReleaseReference();
254
255	Close(false);
256
257	delete fDebugContextPool;
258}
259
260
261status_t
262LocalDebuggerInterface::Init()
263{
264	// create the architecture
265#if defined(ARCH_x86)
266	fArchitecture = new(std::nothrow) ArchitectureX86(this);
267#elif defined(ARCH_x86_64)
268	fArchitecture = new(std::nothrow) ArchitectureX8664(this);
269#else
270	return B_UNSUPPORTED;
271#endif
272
273	if (fArchitecture == NULL)
274		return B_NO_MEMORY;
275
276	status_t error = fArchitecture->Init();
277	if (error != B_OK)
278		return error;
279
280	// create debugger port
281	char buffer[128];
282	snprintf(buffer, sizeof(buffer), "team %" B_PRId32 " debugger", fTeamID);
283	fDebuggerPort = create_port(100, buffer);
284	if (fDebuggerPort < 0)
285		return fDebuggerPort;
286
287	// install as team debugger
288	fNubPort = install_team_debugger(fTeamID, fDebuggerPort);
289	if (fNubPort < 0)
290		return fNubPort;
291
292	error = __start_watching_system(fTeamID, B_WATCH_SYSTEM_THREAD_PROPERTIES,
293		fDebuggerPort, 0);
294	if (error != B_OK)
295		return error;
296
297	// create debug context pool
298	fDebugContextPool = new(std::nothrow) DebugContextPool(fTeamID, fNubPort);
299	if (fDebugContextPool == NULL)
300		return B_NO_MEMORY;
301
302	error = fDebugContextPool->Init();
303	if (error != B_OK)
304		return error;
305
306	return B_OK;
307}
308
309
310void
311LocalDebuggerInterface::Close(bool killTeam)
312{
313	if (killTeam)
314		kill_team(fTeamID);
315	else if (fNubPort >= 0)
316		remove_team_debugger(fTeamID);
317
318	if (fDebuggerPort >= 0) {
319		__stop_watching_system(fTeamID, B_WATCH_SYSTEM_THREAD_PROPERTIES,
320			fDebuggerPort, 0);
321		delete_port(fDebuggerPort);
322	}
323
324	fNubPort = -1;
325	fDebuggerPort = -1;
326}
327
328
329bool
330LocalDebuggerInterface::Connected() const
331{
332	return fNubPort >= 0;
333}
334
335
336team_id
337LocalDebuggerInterface::TeamID() const
338{
339	return fTeamID;
340}
341
342
343Architecture*
344LocalDebuggerInterface::GetArchitecture() const
345{
346	return fArchitecture;
347}
348
349
350status_t
351LocalDebuggerInterface::GetNextDebugEvent(DebugEvent*& _event)
352{
353	while (true) {
354		char buffer[2048];
355		int32 messageCode;
356		ssize_t size = read_port(fDebuggerPort, &messageCode, buffer,
357			sizeof(buffer));
358		if (size < 0) {
359			if (size == B_INTERRUPTED)
360				continue;
361
362			return size;
363		}
364
365		if (messageCode <= B_DEBUGGER_MESSAGE_HANDED_OVER) {
366 			debug_debugger_message_data message;
367			memcpy(&message, buffer, size);
368			if (message.origin.team != fTeamID)
369				continue;
370
371			bool ignore = false;
372			status_t error = _CreateDebugEvent(messageCode, message, ignore,
373				_event);
374			if (error != B_OK)
375				return error;
376
377			if (ignore) {
378				if (message.origin.thread >= 0 && message.origin.nub_port >= 0)
379					error = continue_thread(message.origin.nub_port,
380						message.origin.thread);
381				if (error != B_OK)
382					return error;
383				continue;
384			}
385
386			return B_OK;
387		}
388
389		KMessage message;
390		size = message.SetTo(buffer);
391		if (size != B_OK)
392			return size;
393		return _GetNextSystemWatchEvent(_event, message);
394	}
395
396	return B_OK;
397}
398
399
400status_t
401LocalDebuggerInterface::SetTeamDebuggingFlags(uint32 flags)
402{
403	return set_team_debugging_flags(fNubPort, flags);
404}
405
406
407status_t
408LocalDebuggerInterface::ContinueThread(thread_id thread)
409{
410	return continue_thread(fNubPort, thread);
411}
412
413
414status_t
415LocalDebuggerInterface::StopThread(thread_id thread)
416{
417	return debug_thread(thread);
418}
419
420
421status_t
422LocalDebuggerInterface::SingleStepThread(thread_id thread)
423{
424	debug_nub_continue_thread continueMessage;
425	continueMessage.thread = thread;
426	continueMessage.handle_event = B_THREAD_DEBUG_HANDLE_EVENT;
427	continueMessage.single_step = true;
428
429	return write_port(fNubPort, B_DEBUG_MESSAGE_CONTINUE_THREAD,
430		&continueMessage, sizeof(continueMessage));
431}
432
433
434status_t
435LocalDebuggerInterface::InstallBreakpoint(target_addr_t address)
436{
437	DebugContextGetter contextGetter(fDebugContextPool);
438
439	debug_nub_set_breakpoint message;
440	message.reply_port = contextGetter.Context()->reply_port;
441	message.address = (void*)(addr_t)address;
442
443	debug_nub_set_breakpoint_reply reply;
444
445	status_t error = send_debug_message(contextGetter.Context(),
446		B_DEBUG_MESSAGE_SET_BREAKPOINT, &message, sizeof(message), &reply,
447		sizeof(reply));
448	return error == B_OK ? reply.error : error;
449}
450
451
452status_t
453LocalDebuggerInterface::UninstallBreakpoint(target_addr_t address)
454{
455	debug_nub_clear_breakpoint message;
456	message.address = (void*)(addr_t)address;
457
458	return write_port(fNubPort, B_DEBUG_MESSAGE_CLEAR_BREAKPOINT,
459		&message, sizeof(message));
460}
461
462
463status_t
464LocalDebuggerInterface::InstallWatchpoint(target_addr_t address, uint32 type,
465	int32 length)
466{
467	DebugContextGetter contextGetter(fDebugContextPool);
468
469	debug_nub_set_watchpoint message;
470	message.reply_port = contextGetter.Context()->reply_port;
471	message.address = (void*)(addr_t)address;
472	message.type = type;
473	message.length = length;
474
475	debug_nub_set_watchpoint_reply reply;
476
477	status_t error = send_debug_message(contextGetter.Context(),
478		B_DEBUG_MESSAGE_SET_WATCHPOINT, &message, sizeof(message), &reply,
479		sizeof(reply));
480	return error == B_OK ? reply.error : error;
481}
482
483
484status_t
485LocalDebuggerInterface::UninstallWatchpoint(target_addr_t address)
486{
487	DebugContextGetter contextGetter(fDebugContextPool);
488
489	debug_nub_clear_watchpoint message;
490	message.address = (void*)(addr_t)address;
491
492	return write_port(fNubPort, B_DEBUG_MESSAGE_CLEAR_WATCHPOINT,
493		&message, sizeof(message));
494}
495
496
497status_t
498LocalDebuggerInterface::GetSystemInfo(SystemInfo& info)
499{
500	system_info sysInfo;
501	status_t result = get_system_info(&sysInfo);
502	if (result != B_OK)
503		return result;
504
505	utsname name;
506	result = uname(&name);
507	if (result != B_OK)
508		return result;
509
510	info.SetTo(fTeamID, sysInfo, name);
511	return B_OK;
512}
513
514
515status_t
516LocalDebuggerInterface::GetTeamInfo(TeamInfo& info)
517{
518	team_info teamInfo;
519	status_t result = get_team_info(fTeamID, &teamInfo);
520	if (result != B_OK)
521		return result;
522
523	info.SetTo(fTeamID, teamInfo);
524	return B_OK;
525}
526
527
528status_t
529LocalDebuggerInterface::GetThreadInfos(BObjectList<ThreadInfo>& infos)
530{
531	thread_info threadInfo;
532	int32 cookie = 0;
533	while (get_next_thread_info(fTeamID, &cookie, &threadInfo) == B_OK) {
534		ThreadInfo* info = new(std::nothrow) ThreadInfo(threadInfo.team,
535			threadInfo.thread, threadInfo.name);
536		if (info == NULL || !infos.AddItem(info)) {
537			delete info;
538			return B_NO_MEMORY;
539		}
540	}
541
542	return B_OK;
543}
544
545
546status_t
547LocalDebuggerInterface::GetImageInfos(BObjectList<ImageInfo>& infos)
548{
549	// get the team's images
550	image_info imageInfo;
551	int32 cookie = 0;
552	while (get_next_image_info(fTeamID, &cookie, &imageInfo) == B_OK) {
553		ImageInfo* info = new(std::nothrow) ImageInfo(fTeamID, imageInfo.id,
554			imageInfo.name, imageInfo.type, (addr_t)imageInfo.text,
555			imageInfo.text_size, (addr_t)imageInfo.data, imageInfo.data_size);
556		if (info == NULL || !infos.AddItem(info)) {
557			delete info;
558			return B_NO_MEMORY;
559		}
560	}
561
562	return B_OK;
563}
564
565
566status_t
567LocalDebuggerInterface::GetAreaInfos(BObjectList<AreaInfo>& infos)
568{
569	// get the team's areas
570	area_info areaInfo;
571	ssize_t cookie = 0;
572	while (get_next_area_info(fTeamID, &cookie, &areaInfo) == B_OK) {
573		AreaInfo* info = new(std::nothrow) AreaInfo(fTeamID, areaInfo.area,
574			areaInfo.name, (addr_t)areaInfo.address, areaInfo.size,
575			areaInfo.ram_size, areaInfo.lock, areaInfo.protection);
576		if (info == NULL || !infos.AddItem(info)) {
577			delete info;
578			return B_NO_MEMORY;
579		}
580	}
581
582	return B_OK;
583}
584
585
586status_t
587LocalDebuggerInterface::GetSemaphoreInfos(BObjectList<SemaphoreInfo>& infos)
588{
589	// get the team's semaphores
590	sem_info semInfo;
591	int32 cookie = 0;
592	while (get_next_sem_info(fTeamID, &cookie, &semInfo) == B_OK) {
593		SemaphoreInfo* info = new(std::nothrow) SemaphoreInfo(fTeamID,
594			semInfo.sem, semInfo.name, semInfo.count, semInfo.latest_holder);
595		if (info == NULL || !infos.AddItem(info)) {
596			delete info;
597			return B_NO_MEMORY;
598		}
599	}
600
601	return B_OK;
602}
603
604
605status_t
606LocalDebuggerInterface::GetSymbolInfos(team_id team, image_id image,
607	BObjectList<SymbolInfo>& infos)
608{
609	// create a lookup context
610	debug_symbol_lookup_context* lookupContext;
611	status_t error = debug_create_symbol_lookup_context(team, image,
612		&lookupContext);
613	if (error != B_OK)
614		return error;
615
616	// create a symbol iterator
617	debug_symbol_iterator* iterator;
618	error = debug_create_image_symbol_iterator(
619		lookupContext, image, &iterator);
620	if (error != B_OK) {
621		debug_delete_symbol_lookup_context(lookupContext);
622		return error;
623	}
624
625	// get the symbols
626	char name[1024];
627	int32 type;
628	void* address;
629	size_t size;
630	while (debug_next_image_symbol(iterator, name, sizeof(name), &type,
631			&address, &size) == B_OK) {
632		SymbolInfo* info = new(std::nothrow) SymbolInfo(
633			(target_addr_t)(addr_t)address, size, type, name);
634		if (info == NULL)
635			break;
636		if (!infos.AddItem(info)) {
637			delete info;
638			break;
639		}
640	}
641
642	// delete the symbol iterator and lookup context
643	debug_delete_symbol_iterator(iterator);
644	debug_delete_symbol_lookup_context(lookupContext);
645
646	return B_OK;
647}
648
649
650status_t
651LocalDebuggerInterface::GetSymbolInfo(team_id team, image_id image, const char* name,
652	int32 symbolType, SymbolInfo& info)
653{
654	// create a lookup context
655	debug_symbol_lookup_context* lookupContext;
656	status_t error = debug_create_symbol_lookup_context(team, image,
657		&lookupContext);
658	if (error != B_OK)
659		return error;
660
661	// try to get the symbol
662	void* foundAddress;
663	size_t foundSize;
664	int32 foundType;
665	error = debug_get_symbol(lookupContext, image, name, symbolType,
666		&foundAddress, &foundSize, &foundType);
667	if (error == B_OK) {
668		info.SetTo((target_addr_t)(addr_t)foundAddress, foundSize, foundType,
669			name);
670	}
671
672	// delete the lookup context
673	debug_delete_symbol_lookup_context(lookupContext);
674
675	return error;
676}
677
678
679status_t
680LocalDebuggerInterface::GetThreadInfo(thread_id thread, ThreadInfo& info)
681{
682	thread_info threadInfo;
683	status_t error = get_thread_info(thread, &threadInfo);
684	if (error != B_OK)
685		return error;
686
687	info.SetTo(threadInfo.team, threadInfo.thread, threadInfo.name);
688	return B_OK;
689}
690
691
692status_t
693LocalDebuggerInterface::GetCpuState(thread_id thread, CpuState*& _state)
694{
695	debug_cpu_state debugState;
696	status_t error = _GetDebugCpuState(thread, debugState);
697	if (error != B_OK)
698		return error;
699	return fArchitecture->CreateCpuState(&debugState, sizeof(debug_cpu_state),
700		_state);
701}
702
703
704status_t
705LocalDebuggerInterface::SetCpuState(thread_id thread, const CpuState* state)
706{
707	debug_cpu_state debugState;
708	status_t error = _GetDebugCpuState(thread, debugState);
709	if (error != B_OK)
710		return error;
711
712	DebugContextGetter contextGetter(fDebugContextPool);
713
714	error = state->UpdateDebugState(&debugState, sizeof(debugState));
715	if (error != B_OK)
716		return error;
717
718	debug_nub_set_cpu_state message;
719	message.thread = thread;
720
721	memcpy(&message.cpu_state, &debugState, sizeof(debugState));
722
723	return send_debug_message(contextGetter.Context(),
724		B_DEBUG_MESSAGE_SET_CPU_STATE, &message, sizeof(message), NULL,
725		0);
726}
727
728
729status_t
730LocalDebuggerInterface::GetCpuFeatures(uint32& flags)
731{
732	return fArchitecture->GetCpuFeatures(flags);
733}
734
735
736status_t
737LocalDebuggerInterface::WriteCoreFile(const char* path)
738{
739	DebugContextGetter contextGetter(fDebugContextPool);
740
741	debug_nub_write_core_file_reply reply;
742
743	debug_nub_write_core_file message;
744	message.reply_port = contextGetter.Context()->reply_port;
745	strlcpy(message.path, path, sizeof(message.path));
746
747	status_t error = send_debug_message(contextGetter.Context(),
748		B_DEBUG_WRITE_CORE_FILE, &message, sizeof(message), &reply,
749		sizeof(reply));
750	if (error == B_OK)
751		error = reply.error;
752
753	return error;
754}
755
756
757status_t
758LocalDebuggerInterface::GetMemoryProperties(target_addr_t address,
759	uint32& protection, uint32& locking)
760{
761	return get_memory_properties(fTeamID, (const void *)address,
762		&protection, &locking);
763}
764
765
766ssize_t
767LocalDebuggerInterface::ReadMemory(target_addr_t address, void* buffer, size_t size)
768{
769	DebugContextGetter contextGetter(fDebugContextPool);
770
771	return debug_read_memory(contextGetter.Context(),
772		(const void*)(addr_t)address, buffer, size);
773}
774
775
776ssize_t
777LocalDebuggerInterface::WriteMemory(target_addr_t address, void* buffer,
778	size_t size)
779{
780	DebugContextGetter contextGetter(fDebugContextPool);
781
782	return debug_write_memory(contextGetter.Context(),
783		(const void*)address, buffer, size);
784}
785
786
787status_t
788LocalDebuggerInterface::_CreateDebugEvent(int32 messageCode,
789	const debug_debugger_message_data& message, bool& _ignore,
790	DebugEvent*& _event)
791{
792	DebugEvent* event = NULL;
793
794	switch (messageCode) {
795		case B_DEBUGGER_MESSAGE_THREAD_DEBUGGED:
796			event = new(std::nothrow) ThreadDebuggedEvent(message.origin.team,
797				message.origin.thread);
798			break;
799		case B_DEBUGGER_MESSAGE_DEBUGGER_CALL:
800			event = new(std::nothrow) DebuggerCallEvent(message.origin.team,
801				message.origin.thread,
802				(target_addr_t)message.debugger_call.message);
803			break;
804		case B_DEBUGGER_MESSAGE_BREAKPOINT_HIT:
805		{
806			CpuState* state = NULL;
807			status_t error = fArchitecture->CreateCpuState(
808				&message.breakpoint_hit.cpu_state,
809				sizeof(debug_cpu_state), state);
810			if (error != B_OK)
811				return error;
812
813			event = new(std::nothrow) BreakpointHitEvent(message.origin.team,
814				message.origin.thread, state);
815			state->ReleaseReference();
816			break;
817		}
818		case B_DEBUGGER_MESSAGE_WATCHPOINT_HIT:
819		{
820			CpuState* state = NULL;
821			status_t error = fArchitecture->CreateCpuState(
822				&message.watchpoint_hit.cpu_state,
823				sizeof(debug_cpu_state), state);
824			if (error != B_OK)
825				return error;
826
827			event = new(std::nothrow) WatchpointHitEvent(message.origin.team,
828				message.origin.thread, state);
829			state->ReleaseReference();
830			break;
831		}
832		case B_DEBUGGER_MESSAGE_SINGLE_STEP:
833		{
834			CpuState* state = NULL;
835			status_t error = fArchitecture->CreateCpuState(
836				&message.single_step.cpu_state,
837				sizeof(debug_cpu_state), state);
838			if (error != B_OK)
839				return error;
840
841			event = new(std::nothrow) SingleStepEvent(message.origin.team,
842				message.origin.thread, state);
843			state->ReleaseReference();
844			break;
845		}
846		case B_DEBUGGER_MESSAGE_EXCEPTION_OCCURRED:
847			event = new(std::nothrow) ExceptionOccurredEvent(
848				message.origin.team, message.origin.thread,
849				message.exception_occurred.exception);
850			break;
851		case B_DEBUGGER_MESSAGE_TEAM_DELETED:
852			if (message.origin.team != fTeamID) {
853				_ignore = true;
854				return B_OK;
855			}
856			event = new(std::nothrow) TeamDeletedEvent(message.origin.team,
857				message.origin.thread);
858			break;
859		case B_DEBUGGER_MESSAGE_TEAM_EXEC:
860			if (message.origin.team != fTeamID) {
861				_ignore = true;
862				return B_OK;
863			}
864			event = new(std::nothrow) TeamExecEvent(message.origin.team,
865				message.origin.thread);
866			break;
867		case B_DEBUGGER_MESSAGE_THREAD_CREATED:
868			event = new(std::nothrow) ThreadCreatedEvent(message.origin.team,
869				message.origin.thread, message.thread_created.new_thread);
870			break;
871		case B_DEBUGGER_MESSAGE_THREAD_DELETED:
872			event = new(std::nothrow) ThreadDeletedEvent(message.origin.team,
873				message.origin.thread);
874			break;
875		case B_DEBUGGER_MESSAGE_IMAGE_CREATED:
876		{
877			const image_info& info = message.image_created.info;
878			event = new(std::nothrow) ImageCreatedEvent(message.origin.team,
879				message.origin.thread,
880				ImageInfo(fTeamID, info.id, info.name, info.type,
881					(addr_t)info.text, info.text_size, (addr_t)info.data,
882					info.data_size));
883			break;
884		}
885		case B_DEBUGGER_MESSAGE_IMAGE_DELETED:
886		{
887			const image_info& info = message.image_deleted.info;
888			event = new(std::nothrow) ImageDeletedEvent(message.origin.team,
889				message.origin.thread,
890				ImageInfo(fTeamID, info.id, info.name, info.type,
891					(addr_t)info.text, info.text_size, (addr_t)info.data,
892					info.data_size));
893			break;
894		}
895		case B_DEBUGGER_MESSAGE_POST_SYSCALL:
896		{
897			event = new(std::nothrow) PostSyscallEvent(message.origin.team,
898				message.origin.thread,
899				SyscallInfo(message.post_syscall.start_time,
900					message.post_syscall.end_time,
901					message.post_syscall.return_value,
902					message.post_syscall.syscall, message.post_syscall.args));
903			break;
904		}
905		case B_DEBUGGER_MESSAGE_SIGNAL_RECEIVED:
906		{
907			event = new(std::nothrow) SignalReceivedEvent(message.origin.team,
908				message.origin.thread,
909				SignalInfo(message.signal_received.signal,
910					message.signal_received.handler,
911					message.signal_received.deadly));
912			break;
913		}
914		default:
915			printf("DebuggerInterface for team %" B_PRId32 ": unknown message "
916				"from kernel: %" B_PRId32 "\n", fTeamID, messageCode);
917			// fall through...
918		case B_DEBUGGER_MESSAGE_TEAM_CREATED:
919		case B_DEBUGGER_MESSAGE_PRE_SYSCALL:
920		case B_DEBUGGER_MESSAGE_PROFILER_UPDATE:
921		case B_DEBUGGER_MESSAGE_HANDED_OVER:
922			_ignore = true;
923			return B_OK;
924	}
925
926	if (event == NULL)
927		return B_NO_MEMORY;
928
929	if (message.origin.thread >= 0 && message.origin.nub_port >= 0)
930		event->SetThreadStopped(true);
931
932	_ignore = false;
933	_event = event;
934
935	return B_OK;
936}
937
938
939status_t
940LocalDebuggerInterface::_GetNextSystemWatchEvent(DebugEvent*& _event,
941	KMessage& message)
942{
943	status_t error = B_OK;
944	if (message.What() != B_SYSTEM_OBJECT_UPDATE)
945		return B_BAD_DATA;
946
947	int32 opcode = 0;
948	if (message.FindInt32("opcode", &opcode) != B_OK)
949		return B_BAD_DATA;
950
951	DebugEvent* event = NULL;
952	switch (opcode)
953	{
954		case B_THREAD_NAME_CHANGED:
955		{
956			int32 threadID = -1;
957			if (message.FindInt32("thread", &threadID) != B_OK)
958				break;
959
960			thread_info info;
961			error = get_thread_info(threadID, &info);
962			if (error != B_OK)
963				break;
964
965			event = new(std::nothrow) ThreadRenamedEvent(fTeamID,
966				threadID, threadID, info.name);
967			break;
968		}
969
970		default:
971		{
972			error = B_BAD_DATA;
973			break;
974		}
975	}
976
977	if (event != NULL)
978		_event = event;
979
980	return error;
981}
982
983
984status_t
985LocalDebuggerInterface::_GetDebugCpuState(thread_id thread, debug_cpu_state& _state)
986{
987	DebugContextGetter contextGetter(fDebugContextPool);
988
989	debug_nub_get_cpu_state message;
990	message.reply_port = contextGetter.Context()->reply_port;
991	message.thread = thread;
992
993	debug_nub_get_cpu_state_reply reply;
994
995	status_t error = send_debug_message(contextGetter.Context(),
996		B_DEBUG_MESSAGE_GET_CPU_STATE, &message, sizeof(message), &reply,
997		sizeof(reply));
998	if (error != B_OK)
999		return error;
1000	if (reply.error != B_OK)
1001		return reply.error;
1002
1003	memcpy(&_state, &reply.cpu_state, sizeof(debug_cpu_state));
1004
1005	return B_OK;
1006}
1007