1/*
2 * Copyright 2012, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
4 */
5
6
7#include "CliStackTraceCommand.h"
8
9#include <stdio.h>
10
11#include <AutoLocker.h>
12
13#include "CliContext.h"
14#include "StackTrace.h"
15#include "Team.h"
16#include "UiUtils.h"
17
18
19CliStackTraceCommand::CliStackTraceCommand()
20	:
21	CliCommand("print a stack trace of the current thread",
22		"%s\n"
23		"Prints a stack trace for the current thread.")
24{
25}
26
27
28void
29CliStackTraceCommand::Execute(int argc, const char* const* argv,
30	CliContext& context)
31{
32	// get the current thread
33	Team* team = context.GetTeam();
34	AutoLocker<Team> teamLocker(team);
35	Thread* thread = context.CurrentThread();
36	if (thread == NULL) {
37		printf("no current thread\n");
38		return;
39	}
40
41	if (thread->State() != THREAD_STATE_STOPPED) {
42		printf("Current thread is not stopped. Can't get stack trace.\n");
43		return;
44	}
45
46	// get its stack trace
47	StackTrace* stackTrace = thread->GetStackTrace();
48	while (stackTrace == NULL) {
49		context.WaitForEvent(CliContext::MSG_THREAD_STACK_TRACE_CHANGED);
50		if (context.IsTerminating())
51			return;
52		stackTrace = thread->GetStackTrace();
53	}
54	BReference<StackTrace> stackTraceReference(stackTrace);
55		// hold a reference until we're done
56
57	teamLocker.Unlock();
58
59	// print the stack trace
60	int32 frameCount = stackTrace->CountFrames();
61	for (int32 i = 0; i < frameCount; i++) {
62		StackFrame* frame = stackTrace->FrameAt(i);
63		printf("%3" B_PRId32 "  %#" B_PRIx64 "  %#" B_PRIx64, i,
64			(uint64)frame->FrameAddress(), (uint64)frame->InstructionPointer());
65
66		char functionName[512];
67		UiUtils::FunctionNameForFrame(frame, functionName,
68			sizeof(functionName));
69		printf("  %s\n", functionName);
70	}
71}
72