1/* 2 * Copyright 2016, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7#include "CoreFileDebuggerInterface.h" 8 9#include <algorithm> 10#include <new> 11 12#include <errno.h> 13 14#include <AutoDeleter.h> 15 16#include "ArchitectureX86.h" 17#include "ArchitectureX8664.h" 18#include "CoreFile.h" 19#include "ElfSymbolLookup.h" 20#include "ImageInfo.h" 21#include "TeamInfo.h" 22#include "ThreadInfo.h" 23#include "Tracing.h" 24 25 26CoreFileDebuggerInterface::CoreFileDebuggerInterface(CoreFile* coreFile) 27 : 28 fCoreFile(coreFile), 29 fArchitecture(NULL) 30{ 31} 32 33 34CoreFileDebuggerInterface::~CoreFileDebuggerInterface() 35{ 36 if (fArchitecture != NULL) 37 fArchitecture->ReleaseReference(); 38 39 delete fCoreFile; 40} 41 42 43status_t 44CoreFileDebuggerInterface::Init() 45{ 46 // create the Architecture object 47 uint16 machine = fCoreFile->GetElfFile().Machine(); 48 switch (machine) { 49 case EM_386: 50 fArchitecture = new(std::nothrow) ArchitectureX86(this); 51 break; 52 case EM_X86_64: 53 fArchitecture = new(std::nothrow) ArchitectureX8664(this); 54 break; 55 default: 56 WARNING("Unsupported core file machine (%u)\n", machine); 57 return B_UNSUPPORTED; 58 } 59 60 if (fArchitecture == NULL) 61 return B_NO_MEMORY; 62 63 return fArchitecture->Init(); 64} 65 66 67void 68CoreFileDebuggerInterface::Close(bool killTeam) 69{ 70} 71 72 73bool 74CoreFileDebuggerInterface::Connected() const 75{ 76 return true; 77} 78 79 80bool 81CoreFileDebuggerInterface::IsPostMortem() const 82{ 83 return true; 84} 85 86 87team_id 88CoreFileDebuggerInterface::TeamID() const 89{ 90 return fCoreFile->GetTeamInfo().Id(); 91} 92 93 94Architecture* 95CoreFileDebuggerInterface::GetArchitecture() const 96{ 97 return fArchitecture; 98} 99 100 101status_t 102CoreFileDebuggerInterface::GetNextDebugEvent(DebugEvent*& _event) 103{ 104 return B_UNSUPPORTED; 105} 106 107 108status_t 109CoreFileDebuggerInterface::SetTeamDebuggingFlags(uint32 flags) 110{ 111 return B_UNSUPPORTED; 112} 113 114 115status_t 116CoreFileDebuggerInterface::ContinueThread(thread_id thread) 117{ 118 return B_UNSUPPORTED; 119} 120 121 122status_t 123CoreFileDebuggerInterface::StopThread(thread_id thread) 124{ 125 return B_UNSUPPORTED; 126} 127 128 129status_t 130CoreFileDebuggerInterface::SingleStepThread(thread_id thread) 131{ 132 return B_UNSUPPORTED; 133} 134 135 136status_t 137CoreFileDebuggerInterface::InstallBreakpoint(target_addr_t address) 138{ 139 return B_UNSUPPORTED; 140} 141 142 143status_t 144CoreFileDebuggerInterface::UninstallBreakpoint(target_addr_t address) 145{ 146 return B_UNSUPPORTED; 147} 148 149 150status_t 151CoreFileDebuggerInterface::InstallWatchpoint(target_addr_t address, uint32 type, 152 int32 length) 153{ 154 return B_UNSUPPORTED; 155} 156 157 158status_t 159CoreFileDebuggerInterface::UninstallWatchpoint(target_addr_t address) 160{ 161 return B_UNSUPPORTED; 162} 163 164 165status_t 166CoreFileDebuggerInterface::GetSystemInfo(SystemInfo& info) 167{ 168 return B_UNSUPPORTED; 169} 170 171 172status_t 173CoreFileDebuggerInterface::GetTeamInfo(TeamInfo& info) 174{ 175 const CoreFileTeamInfo& coreInfo = fCoreFile->GetTeamInfo(); 176 info.SetTo(coreInfo.Id(), coreInfo.Arguments()); 177 return B_OK; 178} 179 180 181status_t 182CoreFileDebuggerInterface::GetThreadInfos(BObjectList<ThreadInfo>& infos) 183{ 184 int32 count = fCoreFile->CountThreadInfos(); 185 for (int32 i = 0; i < count; i++) { 186 const CoreFileThreadInfo* coreInfo = fCoreFile->ThreadInfoAt(i); 187 ThreadInfo* info = new(std::nothrow) ThreadInfo; 188 if (info == NULL || !infos.AddItem(info)) { 189 delete info; 190 return B_NO_MEMORY; 191 } 192 193 _GetThreadInfo(*coreInfo, *info); 194 } 195 196 return B_OK; 197} 198 199 200status_t 201CoreFileDebuggerInterface::GetImageInfos(BObjectList<ImageInfo>& infos) 202{ 203 int32 count = fCoreFile->CountImageInfos(); 204 for (int32 i = 0; i < count; i++) { 205 const CoreFileImageInfo* coreInfo = fCoreFile->ImageInfoAt(i); 206 ImageInfo* info = new(std::nothrow) ImageInfo; 207 if (info == NULL || !infos.AddItem(info)) { 208 delete info; 209 return B_NO_MEMORY; 210 } 211 212 info->SetTo(TeamID(), coreInfo->Id(), coreInfo->Name(), 213 (image_type)coreInfo->Type(), coreInfo->TextBase(), 214 coreInfo->TextSize(), coreInfo->DataBase(), coreInfo->DataSize()); 215 } 216 217 return B_OK; 218} 219 220 221status_t 222CoreFileDebuggerInterface::GetAreaInfos(BObjectList<AreaInfo>& infos) 223{ 224 return B_UNSUPPORTED; 225} 226 227 228status_t 229CoreFileDebuggerInterface::GetSemaphoreInfos(BObjectList<SemaphoreInfo>& infos) 230{ 231 return B_UNSUPPORTED; 232} 233 234 235status_t 236CoreFileDebuggerInterface::GetSymbolInfos(team_id team, image_id image, 237 BObjectList<SymbolInfo>& infos) 238{ 239 // get the image info 240 const CoreFileImageInfo* imageInfo = fCoreFile->ImageInfoForId(image); 241 if (imageInfo == NULL) 242 return B_BAD_IMAGE_ID; 243 244 if (const CoreFileSymbolsInfo* symbolsInfo = imageInfo->SymbolsInfo()) { 245 return GetElfSymbols(symbolsInfo->SymbolTable(), 246 symbolsInfo->SymbolCount(), symbolsInfo->SymbolTableEntrySize(), 247 symbolsInfo->StringTable(), symbolsInfo->StringTableSize(), 248 fCoreFile->GetElfFile().Is64Bit(), 249 fCoreFile->GetElfFile().IsByteOrderSwapped(), 250 imageInfo->TextDelta(), infos); 251 } 252 253 // get the symbols from the ELF file, if possible 254 status_t error = GetElfSymbols(imageInfo->Name(), imageInfo->TextDelta(), 255 infos); 256 if (error == B_OK) 257 return error; 258 259 // get the symbols from the core file, if possible 260 ElfSymbolLookup* symbolLookup; 261 error = fCoreFile->CreateSymbolLookup(imageInfo, symbolLookup); 262 if (error != B_OK) { 263 WARNING("Failed to create symbol lookup for image (%" B_PRId32 264 "): %s\n", image, strerror(error)); 265 return error; 266 } 267 268 ObjectDeleter<ElfSymbolLookup> symbolLookupDeleter(symbolLookup); 269 270 return GetElfSymbols(symbolLookup, infos); 271} 272 273 274status_t 275CoreFileDebuggerInterface::GetSymbolInfo(team_id team, image_id image, 276 const char* name, int32 symbolType, SymbolInfo& info) 277{ 278 // TODO:... 279 return B_UNSUPPORTED; 280} 281 282 283status_t 284CoreFileDebuggerInterface::GetThreadInfo(thread_id thread, ThreadInfo& info) 285{ 286 const CoreFileThreadInfo* coreInfo = fCoreFile->ThreadInfoForId(thread); 287 if (coreInfo == NULL) 288 return B_BAD_THREAD_ID; 289 290 _GetThreadInfo(*coreInfo, info); 291 return B_OK; 292} 293 294 295status_t 296CoreFileDebuggerInterface::GetCpuState(thread_id thread, CpuState*& _state) 297{ 298 const CoreFileThreadInfo* coreInfo = fCoreFile->ThreadInfoForId(thread); 299 if (coreInfo == NULL) 300 return B_BAD_THREAD_ID; 301 302 return fArchitecture->CreateCpuState(coreInfo->GetCpuState(), 303 coreInfo->CpuStateSize(), _state); 304} 305 306 307status_t 308CoreFileDebuggerInterface::SetCpuState(thread_id thread, const CpuState* state) 309{ 310 return B_UNSUPPORTED; 311} 312 313 314status_t 315CoreFileDebuggerInterface::GetCpuFeatures(uint32& flags) 316{ 317 return fArchitecture->GetCpuFeatures(flags); 318} 319 320 321status_t 322CoreFileDebuggerInterface::WriteCoreFile(const char* path) 323{ 324 return B_NOT_SUPPORTED; 325} 326 327 328status_t 329CoreFileDebuggerInterface::GetMemoryProperties(target_addr_t address, 330 uint32& protection, uint32& locking) 331{ 332 const CoreFileAreaInfo* info = fCoreFile->AreaInfoForAddress(address); 333 if (info == NULL) 334 return B_BAD_ADDRESS; 335 336 protection = info->Protection() & ~(uint32)B_WRITE_AREA; 337 // Filter out write protection, since we don't support writing memory. 338 locking = info->Locking(); 339 return B_OK; 340} 341 342 343ssize_t 344CoreFileDebuggerInterface::ReadMemory(target_addr_t address, void* _buffer, 345 size_t size) 346{ 347 if (size == 0) 348 return B_OK; 349 350 ssize_t totalRead = 0; 351 uint8* buffer = (uint8*)_buffer; 352 353 while (size > 0) { 354 const CoreFileAreaInfo* info = fCoreFile->AreaInfoForAddress(address); 355 if (info == NULL) 356 return totalRead > 0 ? totalRead : B_BAD_ADDRESS; 357 358 ElfSegment* segment = info->Segment(); 359 uint64 offset = address - segment->LoadAddress(); 360 if (offset >= segment->FileSize()) 361 return totalRead > 0 ? totalRead : B_BAD_ADDRESS; 362 363 size_t toRead = (size_t)std::min((uint64)size, 364 segment->FileSize() - offset); 365 ssize_t bytesRead = pread(fCoreFile->GetElfFile().FD(), buffer, toRead, 366 segment->FileOffset() + offset); 367 if (bytesRead <= 0) { 368 status_t error = bytesRead == 0 ? B_IO_ERROR : errno; 369 return totalRead > 0 ? totalRead : error; 370 } 371 372 buffer += bytesRead; 373 size -= bytesRead; 374 totalRead += bytesRead; 375 } 376 377 return totalRead; 378} 379 380 381ssize_t 382CoreFileDebuggerInterface::WriteMemory(target_addr_t address, void* buffer, 383 size_t size) 384{ 385 return B_UNSUPPORTED; 386} 387 388 389void 390CoreFileDebuggerInterface::_GetThreadInfo(const CoreFileThreadInfo& coreInfo, 391 ThreadInfo& info) 392{ 393 info.SetTo(TeamID(), coreInfo.Id(), coreInfo.Name()); 394} 395