#include "CoreFileDebuggerInterface.h"
#include <algorithm>
#include <new>
#include <errno.h>
#include <AutoDeleter.h>
#include "ArchitectureX86.h"
#include "ArchitectureX8664.h"
#include "CoreFile.h"
#include "ElfSymbolLookup.h"
#include "ImageInfo.h"
#include "TeamInfo.h"
#include "ThreadInfo.h"
#include "Tracing.h"
CoreFileDebuggerInterface::CoreFileDebuggerInterface(CoreFile* coreFile)
:
fCoreFile(coreFile),
fArchitecture(NULL)
{
}
CoreFileDebuggerInterface::~CoreFileDebuggerInterface()
{
if (fArchitecture != NULL)
fArchitecture->ReleaseReference();
delete fCoreFile;
}
status_t
CoreFileDebuggerInterface::Init()
{
uint16 machine = fCoreFile->GetElfFile().Machine();
switch (machine) {
case EM_386:
fArchitecture = new(std::nothrow) ArchitectureX86(this);
break;
case EM_X86_64:
fArchitecture = new(std::nothrow) ArchitectureX8664(this);
break;
default:
WARNING("Unsupported core file machine (%u)\n", machine);
return B_UNSUPPORTED;
}
if (fArchitecture == NULL)
return B_NO_MEMORY;
return fArchitecture->Init();
}
void
CoreFileDebuggerInterface::Close(bool killTeam)
{
}
bool
CoreFileDebuggerInterface::Connected() const
{
return true;
}
bool
CoreFileDebuggerInterface::IsPostMortem() const
{
return true;
}
team_id
CoreFileDebuggerInterface::TeamID() const
{
return fCoreFile->GetTeamInfo().Id();
}
Architecture*
CoreFileDebuggerInterface::GetArchitecture() const
{
return fArchitecture;
}
status_t
CoreFileDebuggerInterface::GetNextDebugEvent(DebugEvent*& _event)
{
return B_UNSUPPORTED;
}
status_t
CoreFileDebuggerInterface::SetTeamDebuggingFlags(uint32 flags)
{
return B_UNSUPPORTED;
}
status_t
CoreFileDebuggerInterface::ContinueThread(thread_id thread)
{
return B_UNSUPPORTED;
}
status_t
CoreFileDebuggerInterface::StopThread(thread_id thread)
{
return B_UNSUPPORTED;
}
status_t
CoreFileDebuggerInterface::SingleStepThread(thread_id thread)
{
return B_UNSUPPORTED;
}
status_t
CoreFileDebuggerInterface::InstallBreakpoint(target_addr_t address)
{
return B_UNSUPPORTED;
}
status_t
CoreFileDebuggerInterface::UninstallBreakpoint(target_addr_t address)
{
return B_UNSUPPORTED;
}
status_t
CoreFileDebuggerInterface::InstallWatchpoint(target_addr_t address, uint32 type,
int32 length)
{
return B_UNSUPPORTED;
}
status_t
CoreFileDebuggerInterface::UninstallWatchpoint(target_addr_t address)
{
return B_UNSUPPORTED;
}
status_t
CoreFileDebuggerInterface::GetSystemInfo(SystemInfo& info)
{
return B_UNSUPPORTED;
}
status_t
CoreFileDebuggerInterface::GetTeamInfo(TeamInfo& info)
{
const CoreFileTeamInfo& coreInfo = fCoreFile->GetTeamInfo();
info.SetTo(coreInfo.Id(), coreInfo.Arguments());
return B_OK;
}
status_t
CoreFileDebuggerInterface::GetThreadInfos(BObjectList<ThreadInfo, true>& infos)
{
int32 count = fCoreFile->CountThreadInfos();
for (int32 i = 0; i < count; i++) {
const CoreFileThreadInfo* coreInfo = fCoreFile->ThreadInfoAt(i);
ThreadInfo* info = new(std::nothrow) ThreadInfo;
if (info == NULL || !infos.AddItem(info)) {
delete info;
return B_NO_MEMORY;
}
_GetThreadInfo(*coreInfo, *info);
}
return B_OK;
}
status_t
CoreFileDebuggerInterface::GetImageInfos(BObjectList<ImageInfo, true>& infos)
{
int32 count = fCoreFile->CountImageInfos();
for (int32 i = 0; i < count; i++) {
const CoreFileImageInfo* coreInfo = fCoreFile->ImageInfoAt(i);
ImageInfo* info = new(std::nothrow) ImageInfo;
if (info == NULL || !infos.AddItem(info)) {
delete info;
return B_NO_MEMORY;
}
info->SetTo(TeamID(), coreInfo->Id(), coreInfo->Name(),
(image_type)coreInfo->Type(), coreInfo->TextBase(),
coreInfo->TextSize(), coreInfo->DataBase(), coreInfo->DataSize());
}
return B_OK;
}
status_t
CoreFileDebuggerInterface::GetAreaInfos(BObjectList<AreaInfo, true>& infos)
{
return B_UNSUPPORTED;
}
status_t
CoreFileDebuggerInterface::GetSemaphoreInfos(BObjectList<SemaphoreInfo, true>& infos)
{
return B_UNSUPPORTED;
}
status_t
CoreFileDebuggerInterface::GetSymbolInfos(team_id team, image_id image,
BObjectList<SymbolInfo, true>& infos)
{
const CoreFileImageInfo* imageInfo = fCoreFile->ImageInfoForId(image);
if (imageInfo == NULL)
return B_BAD_IMAGE_ID;
if (const CoreFileSymbolsInfo* symbolsInfo = imageInfo->SymbolsInfo()) {
return GetElfSymbols(symbolsInfo->SymbolTable(),
symbolsInfo->SymbolCount(), symbolsInfo->SymbolTableEntrySize(),
symbolsInfo->StringTable(), symbolsInfo->StringTableSize(),
fCoreFile->GetElfFile().Is64Bit(),
fCoreFile->GetElfFile().IsByteOrderSwapped(),
imageInfo->TextDelta(), infos);
}
status_t error = GetElfSymbols(imageInfo->Name(), imageInfo->TextDelta(),
infos);
if (error == B_OK)
return error;
ElfSymbolLookup* symbolLookup;
error = fCoreFile->CreateSymbolLookup(imageInfo, symbolLookup);
if (error != B_OK) {
WARNING("Failed to create symbol lookup for image (%" B_PRId32
"): %s\n", image, strerror(error));
return error;
}
ObjectDeleter<ElfSymbolLookup> symbolLookupDeleter(symbolLookup);
return GetElfSymbols(symbolLookup, infos);
}
status_t
CoreFileDebuggerInterface::GetSymbolInfo(team_id team, image_id image,
const char* name, int32 symbolType, SymbolInfo& info)
{
return B_UNSUPPORTED;
}
status_t
CoreFileDebuggerInterface::GetThreadInfo(thread_id thread, ThreadInfo& info)
{
const CoreFileThreadInfo* coreInfo = fCoreFile->ThreadInfoForId(thread);
if (coreInfo == NULL)
return B_BAD_THREAD_ID;
_GetThreadInfo(*coreInfo, info);
return B_OK;
}
status_t
CoreFileDebuggerInterface::GetCpuState(thread_id thread, CpuState*& _state)
{
const CoreFileThreadInfo* coreInfo = fCoreFile->ThreadInfoForId(thread);
if (coreInfo == NULL)
return B_BAD_THREAD_ID;
return fArchitecture->CreateCpuState(coreInfo->GetCpuState(),
coreInfo->CpuStateSize(), _state);
}
status_t
CoreFileDebuggerInterface::SetCpuState(thread_id thread, const CpuState* state)
{
return B_UNSUPPORTED;
}
status_t
CoreFileDebuggerInterface::GetCpuFeatures(uint32& flags)
{
return fArchitecture->GetCpuFeatures(flags);
}
status_t
CoreFileDebuggerInterface::WriteCoreFile(const char* path)
{
return B_NOT_SUPPORTED;
}
status_t
CoreFileDebuggerInterface::GetMemoryProperties(target_addr_t address,
uint32& protection, uint32& locking)
{
const CoreFileAreaInfo* info = fCoreFile->AreaInfoForAddress(address);
if (info == NULL)
return B_BAD_ADDRESS;
protection = info->Protection() & ~(uint32)B_WRITE_AREA;
locking = info->Locking();
return B_OK;
}
ssize_t
CoreFileDebuggerInterface::ReadMemory(target_addr_t address, void* _buffer,
size_t size)
{
if (size == 0)
return B_OK;
ssize_t totalRead = 0;
uint8* buffer = (uint8*)_buffer;
while (size > 0) {
const CoreFileAreaInfo* info = fCoreFile->AreaInfoForAddress(address);
if (info == NULL)
return totalRead > 0 ? totalRead : B_BAD_ADDRESS;
ElfSegment* segment = info->Segment();
uint64 offset = address - segment->LoadAddress();
if (offset >= segment->FileSize())
return totalRead > 0 ? totalRead : B_BAD_ADDRESS;
size_t toRead = (size_t)std::min((uint64)size,
segment->FileSize() - offset);
ssize_t bytesRead = pread(fCoreFile->GetElfFile().FD(), buffer, toRead,
segment->FileOffset() + offset);
if (bytesRead <= 0) {
status_t error = bytesRead == 0 ? B_IO_ERROR : errno;
return totalRead > 0 ? totalRead : error;
}
buffer += bytesRead;
size -= bytesRead;
totalRead += bytesRead;
}
return totalRead;
}
ssize_t
CoreFileDebuggerInterface::WriteMemory(target_addr_t address, void* buffer,
size_t size)
{
return B_UNSUPPORTED;
}
void
CoreFileDebuggerInterface::_GetThreadInfo(const CoreFileThreadInfo& coreInfo,
ThreadInfo& info)
{
info.SetTo(TeamID(), coreInfo.Id(), coreInfo.Name());
}