* Copyright 2010, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include <TeamDebugger.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <string.h>
#include <Path.h>
#include <String.h>
#include <libroot_private.h>
#include <syscalls.h>
#include <syscall_load_image.h>
BTeamDebugger::BTeamDebugger()
:
fDebuggerPort(-1)
{
}
BTeamDebugger::~BTeamDebugger()
{
Uninstall();
}
status_t
BTeamDebugger::Install(team_id team)
{
Uninstall();
char name[B_OS_NAME_LENGTH];
snprintf(name, sizeof(name), "debugger for team %" B_PRId32, team);
fDebuggerPort = create_port(100, name);
if (fDebuggerPort < 0)
return fDebuggerPort;
port_id nubPort = install_team_debugger(team, fDebuggerPort);
if (nubPort < 0) {
delete_port(fDebuggerPort);
fDebuggerPort = -1;
return nubPort;
}
status_t error = BDebugContext::Init(team, nubPort);
if (error != B_OK) {
remove_team_debugger(team);
delete_port(fDebuggerPort);
fDebuggerPort = -1;
return error;
}
return B_OK;
}
status_t
BTeamDebugger::Uninstall()
{
if (Team() < 0)
return B_BAD_VALUE;
remove_team_debugger(Team());
delete_port(fDebuggerPort);
BDebugContext::Uninit();
fDebuggerPort = -1;
return B_OK;
}
status_t
BTeamDebugger::LoadProgram(const char* const* args, int32 argCount,
bool traceLoading)
{
thread_id thread = _LoadProgram(args, argCount, traceLoading);
if (thread < 0)
return thread;
status_t error = Install(thread);
if (error != B_OK) {
kill_team(thread);
return error;
}
return B_OK;
}
status_t
BTeamDebugger::ReadDebugMessage(int32& _messageCode,
debug_debugger_message_data& messageBuffer)
{
ssize_t bytesRead = read_port(fDebuggerPort, &_messageCode, &messageBuffer,
sizeof(messageBuffer));
if (bytesRead < 0)
return bytesRead;
return B_OK;
}
thread_id
BTeamDebugger::_LoadProgram(const char* const* args, int32 argCount,
bool traceLoading)
{
const char** mutableArgs = new const char*[argCount];
for (int i = 0; i < argCount; i++)
mutableArgs[i] = args[i];
BPath programPath;
status_t error = _FindProgram(args[0], programPath);
if (error != B_OK) {
delete[] mutableArgs;
return error;
}
mutableArgs[0] = programPath.Path();
int32 envCount = 0;
while (environ[envCount] != NULL)
envCount++;
char** flatArgs = NULL;
size_t flatArgsSize;
error = __flatten_process_args(mutableArgs, argCount, environ, &envCount,
mutableArgs[0], &flatArgs, &flatArgsSize);
thread_id thread;
if (error == B_OK) {
thread = _kern_load_image(flatArgs, flatArgsSize, argCount, envCount,
B_NORMAL_PRIORITY, (traceLoading ? 0 : B_WAIT_TILL_LOADED), -1, 0);
free(flatArgs);
} else
thread = error;
delete[] mutableArgs;
return thread;
}
status_t
BTeamDebugger::_FindProgram(const char* programName, BPath& resolvedPath)
{
if (*programName == '/' || strchr(programName, '/'))
return resolvedPath.SetTo(programName);
const char* paths = getenv("PATH");
if (!paths)
return B_ENTRY_NOT_FOUND;
do {
const char* pathEnd = strchr(paths, ':');
int pathLen = (pathEnd ? pathEnd - paths : strlen(paths));
if (pathLen > 0) {
BString directory(paths, pathLen);
if (directory.Length() == 0)
return B_NO_MEMORY;
BPath path;
status_t error = path.SetTo(directory, programName);
if (error != B_OK)
continue;
struct stat st;
if (stat(path.Path(), &st) == 0 && S_ISREG(st.st_mode)) {
resolvedPath = path;
return B_OK;
}
}
paths = (pathEnd ? pathEnd + 1 : NULL);
} while (paths);
return B_ENTRY_NOT_FOUND;
}