add: _PrintStackTrace(thread);
context: TeamDebugHandler::_HandleMessage(DebugMessage *message){	// This method is called only for the first message the debugger gets for	// a team. That means only a few messages are actually possible, while	// others wouldn't trigger the debugger in the first place. So we deal with	// all of them the same way, by popping up an alert.	TRACE(("debug_server: TeamDebugHandler::_HandleMessage(): team %ld, code: "		"%ld\n", fTeam, (int32)message->Code()));	thread_id thread = message->Data().origin.thread;	// get some user-readable message	char buffer[512];	switch (message->Code()) {		case B_DEBUGGER_MESSAGE_TEAM_DELETED:			// This shouldn't happen.			printf("debug_server: Got a spurious "				"B_DEBUGGER_MESSAGE_TEAM_DELETED message for team %ld\n",				fTeam);			return true;		case B_DEBUGGER_MESSAGE_EXCEPTION_OCCURRED:			get_debug_exception_string(				message->Data().exception_occurred.exception, buffer,				sizeof(buffer));			break;		case B_DEBUGGER_MESSAGE_DEBUGGER_CALL:		{			// get the debugger() message			void *messageAddress = message->Data().debugger_call.message;			char messageBuffer[128];			status_t error = B_OK;			ssize_t bytesRead = debug_read_string(&fDebugContext,				messageAddress, messageBuffer, sizeof(messageBuffer));			if (bytesRead < 0)				error = bytesRead;			if (error == B_OK) {				sprintf(buffer, "Debugger call: `%s'", messageBuffer);			} else {				snprintf(buffer, sizeof(buffer), "Debugger call: %p "					"(Failed to read message: %s)", messageAddress,					strerror(error));			}			break;		}		default:			get_debug_message_string(message->Code(), buffer, sizeof(buffer));			break;	}	printf("debug_server: Thread %ld entered the debugger: %s\n", thread,		buffer);// TODO: Temporary solution. Remove when attaching gdb is working.#if 1	// print a stacktrace	void *ip = NULL;	void *stackFrameAddress = NULL;	status_t error = debug_get_instruction_pointer(&fDebugContext, thread, &ip,		&stackFrameAddress);	if (error == B_OK) {		printf("stack trace, current PC %p:\n", ip);		for (int32 i = 0; i < 50; i++) {			debug_stack_frame_info stackFrameInfo;			error = debug_get_stack_frame(&fDebugContext, stackFrameAddress,				&stackFrameInfo);			if (error < B_OK || stackFrameInfo.parent_frame == NULL)				break;			// find area containing the IP			team_id team = fTeam;			bool useAreaInfo = false;			area_info info;			int32 cookie = 0;			while (get_next_area_info(team, &cookie, &info) == B_OK) {				if ((addr_t)info.address						<= (addr_t)stackFrameInfo.return_address					&& (addr_t)info.address + info.size						> (addr_t)stackFrameInfo.return_address) {					useAreaInfo = true;					break;				}			}			printf("  (%p)  %p", stackFrameInfo.frame,				stackFrameInfo.return_address);			if (useAreaInfo) {				printf("  (%s + %#lx)\n", info.name,					(addr_t)stackFrameInfo.return_address						- (addr_t)info.address);			} else				putchar('\n');			stackFrameAddress = stackFrameInfo.parent_frame;		}	}#endif	bool kill = true;	// ask the user whether to debug or kill the team	if (_IsGUIServer()) {		// App or input server. If it's the app server, we'll try to debug it.		kill = !(_IsAppServer() && strlen(fExecutablePath) > 0);	} else if (USE_GUI && _AreGUIServersAlive() && _InitGUI() == B_OK) {		// normal app		char buffer[1024];		snprintf(buffer, sizeof(buffer), "The application:\n\n      %s\n\n"			"has encountered an error which prevents it from continuing. Haiku "			"will terminate the application and clean up.", fTeamInfo.args);		if (strlen(fExecutablePath) > 0) {			// we have a usable path, so we can debug the team			BAlert *alert = new BAlert(NULL, buffer, "Debug", "OK", NULL,				B_WIDTH_AS_USUAL, B_WARNING_ALERT);			int32 result = alert->Go();			kill = (result == 1);		} else {			// no usable path			BAlert *alert = new BAlert(NULL, buffer, "OK", NULL, NULL,				B_WIDTH_AS_USUAL, B_WARNING_ALERT);			alert->Go();		}	}	return kill;}