1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
11 #define CONVERT_FROM_SIGN_EXTENDED(offset) ((ULONG_PTR)(offset))
13 ULONG g_currentThreadIndex = -1;
14 ULONG g_currentThreadSystemId = -1;
15 char *g_coreclrDirectory;
17 LLDBServices::LLDBServices(lldb::SBDebugger &debugger, lldb::SBCommandReturnObject &returnObject, lldb::SBProcess *process, lldb::SBThread *thread) :
20 m_returnObject(returnObject),
21 m_currentProcess(process),
22 m_currentThread(thread)
24 returnObject.SetStatus(lldb::eReturnStatusSuccessFinishResult);
27 LLDBServices::~LLDBServices()
31 //----------------------------------------------------------------------------
33 //----------------------------------------------------------------------------
36 LLDBServices::QueryInterface(
41 if (InterfaceId == __uuidof(IUnknown) ||
42 InterfaceId == __uuidof(ILLDBServices))
44 *Interface = (ILLDBServices*)this;
56 LLDBServices::AddRef()
58 LONG ref = InterlockedIncrement(&m_ref);
63 LLDBServices::Release()
65 LONG ref = InterlockedDecrement(&m_ref);
73 //----------------------------------------------------------------------------
75 //----------------------------------------------------------------------------
78 LLDBServices::GetCoreClrDirectory()
80 return g_coreclrDirectory;
84 LLDBServices::GetExpression(
92 lldb::SBFrame frame = GetCurrentFrame();
102 // To be compatible with windbg/dbgeng, we need to emulate the default
103 // hex radix (because sos prints addresses and other hex values without
104 // the 0x) by first prepending 0x and if that fails use the actual
105 // undecorated expression.
109 result = GetExpression(frame, error, str.c_str());
112 result = GetExpression(frame, error, exp);
120 LLDBServices::GetExpression(
121 /* const */ lldb::SBFrame& frame,
122 lldb::SBError& error,
125 DWORD_PTR result = 0;
127 lldb::SBValue value = frame.EvaluateExpression(exp, lldb::eNoDynamicValues);
130 result = value.GetValueAsUnsigned(error);
137 // lldb doesn't have a way or API to unwind an arbitrary context (IP, SP)
138 // and return the next frame so we have to stick with the native frames
139 // lldb has found and find the closest frame to the incoming context SP.
142 LLDBServices::VirtualUnwind(
147 lldb::SBProcess process;
148 lldb::SBThread thread;
150 if (context == NULL || contextSize < sizeof(DT_CONTEXT))
155 process = GetCurrentProcess();
156 if (!process.IsValid())
161 thread = process.GetThreadByID(threadID);
162 if (!thread.IsValid())
167 DT_CONTEXT *dtcontext = (DT_CONTEXT*)context;
168 lldb::SBFrame frameFound;
170 #ifdef DBG_TARGET_AMD64
171 DWORD64 spToFind = dtcontext->Rsp;
173 DWORD spToFind = dtcontext->Esp;
175 DWORD spToFind = dtcontext->Sp;
176 #elif DBG_TARGET_ARM64
177 DWORD64 spToFind = dtcontext->Sp;
179 #error "spToFind undefined for this platform"
182 int numFrames = thread.GetNumFrames();
183 for (int i = 0; i < numFrames; i++)
185 lldb::SBFrame frame = thread.GetFrameAtIndex(i);
186 if (!frame.IsValid())
190 lldb::addr_t sp = frame.GetSP();
192 if ((i + 1) < numFrames)
194 lldb::SBFrame frameNext = thread.GetFrameAtIndex(i + 1);
195 if (frameNext.IsValid())
197 lldb::addr_t spNext = frameNext.GetSP();
199 // An exact match of the current frame's SP would be nice
200 // but sometimes the incoming context is between lldb frames
201 if (spToFind >= sp && spToFind < spNext)
203 frameFound = frameNext;
210 if (!frameFound.IsValid())
215 GetContextFromFrame(frameFound, dtcontext);
221 ExceptionBreakpointCallback(
223 lldb::SBProcess &process,
224 lldb::SBThread &thread,
225 lldb::SBBreakpointLocation &location)
227 lldb::SBDebugger debugger = process.GetTarget().GetDebugger();
229 // Send the normal and error output to stdout/stderr since we
230 // don't have a return object from the command interpreter.
231 lldb::SBCommandReturnObject result;
232 result.SetImmediateOutputFile(stdout);
233 result.SetImmediateErrorFile(stderr);
235 // Save the process and thread to be used by the current process/thread
237 LLDBServices* client = new LLDBServices(debugger, result, &process, &thread);
238 return ((PFN_EXCEPTION_CALLBACK)baton)(client) == S_OK;
241 lldb::SBBreakpoint g_exceptionbp;
244 LLDBServices::SetExceptionCallback(
245 PFN_EXCEPTION_CALLBACK callback)
247 if (!g_exceptionbp.IsValid())
249 lldb::SBTarget target = m_debugger.GetSelectedTarget();
250 if (!target.IsValid())
254 lldb::SBBreakpoint exceptionbp = target.BreakpointCreateForException(lldb::LanguageType::eLanguageTypeC_plus_plus, false, true);
255 if (!exceptionbp.IsValid())
259 #ifdef FLAGS_ANONYMOUS_ENUM
260 exceptionbp.AddName("DoNotDeleteOrDisable");
262 exceptionbp.SetCallback(ExceptionBreakpointCallback, (void *)callback);
263 g_exceptionbp = exceptionbp;
269 LLDBServices::ClearExceptionCallback()
271 if (g_exceptionbp.IsValid())
273 lldb::SBTarget target = m_debugger.GetSelectedTarget();
274 if (!target.IsValid())
278 target.BreakpointDelete(g_exceptionbp.GetID());
279 g_exceptionbp = lldb::SBBreakpoint();
284 //----------------------------------------------------------------------------
286 //----------------------------------------------------------------------------
288 // Checks for a user interrupt, such a Ctrl-C
290 // This method is reentrant.
292 LLDBServices::GetInterrupt()
297 // Sends output through clients
298 // output callbacks if the mask is allowed
299 // by the current output control mask and
300 // according to the output distribution
303 LLDBServices::Output(
309 va_start (args, format);
310 HRESULT result = OutputVaList(mask, format, args);
316 LLDBServices::OutputVaList(
321 HRESULT result = S_OK;
325 va_copy (args_copy, args);
327 // Try and format our string into a fixed buffer first and see if it fits
328 size_t length = ::vsnprintf(str, sizeof(str), format, args);
329 if (length < sizeof(str))
331 OutputString(mask, str);
335 // Our stack buffer wasn't big enough to contain the entire formatted
336 // string, so lets let vasprintf create the string for us!
337 char *str_ptr = nullptr;
338 length = ::vasprintf(&str_ptr, format, args_copy);
341 OutputString(mask, str_ptr);
355 // The following methods allow direct control
356 // over the distribution of the given output
357 // for situations where something other than
358 // the default is desired. These methods require
359 // extra work in the engine so they should
360 // only be used when necessary.
362 LLDBServices::ControlledOutput(
369 va_start (args, format);
370 HRESULT result = ControlledOutputVaList(outputControl, mask, format, args);
376 LLDBServices::ControlledOutputVaList(
382 return OutputVaList(mask, format, args);
385 // Returns information about the debuggee such
386 // as user vs. kernel, dump vs. live, etc.
388 LLDBServices::GetDebuggeeType(
392 *debugClass = DEBUG_CLASS_USER_WINDOWS;
397 // Returns the page size for the currently executing
398 // processor context. The page size may vary between
401 LLDBServices::GetPageSize(
409 LLDBServices::GetExecutingProcessorType(
412 #ifdef DBG_TARGET_AMD64
413 *type = IMAGE_FILE_MACHINE_AMD64;
415 *type = IMAGE_FILE_MACHINE_ARMNT;
416 #elif DBG_TARGET_ARM64
417 *type = IMAGE_FILE_MACHINE_ARM64;
419 *type = IMAGE_FILE_MACHINE_I386;
421 #error "Unsupported target"
427 LLDBServices::Execute(
432 lldb::SBCommandInterpreter interpreter = m_debugger.GetCommandInterpreter();
434 lldb::SBCommandReturnObject result;
435 lldb::ReturnStatus status = interpreter.HandleCommand(command, result);
437 return status <= lldb::eReturnStatusSuccessContinuingResult ? S_OK : E_FAIL;
440 // PAL raise exception function and exception record pointer variable name
441 // See coreclr\src\pal\src\exception\seh-unwind.cpp for the details. This
442 // function depends on RtlpRaisException not being inlined or optimized.
443 #define FUNCTION_NAME "RtlpRaiseException"
444 #define VARIABLE_NAME "ExceptionRecord"
447 LLDBServices::GetLastEventInformation(
451 PVOID extraInformation,
452 ULONG extraInformationSize,
453 PULONG extraInformationUsed,
455 ULONG descriptionSize,
456 PULONG descriptionUsed)
458 if (extraInformationSize < sizeof(DEBUG_LAST_EVENT_INFO_EXCEPTION) ||
459 type == NULL || processId == NULL || threadId == NULL || extraInformationUsed == NULL)
464 *type = DEBUG_EVENT_EXCEPTION;
467 *extraInformationUsed = sizeof(DEBUG_LAST_EVENT_INFO_EXCEPTION);
469 DEBUG_LAST_EVENT_INFO_EXCEPTION *pdle = (DEBUG_LAST_EVENT_INFO_EXCEPTION *)extraInformation;
470 pdle->FirstChance = 1;
472 lldb::SBProcess process = GetCurrentProcess();
473 if (!process.IsValid())
477 lldb::SBThread thread = GetCurrentThread();
478 if (!thread.IsValid())
483 *processId = process.GetProcessID();
484 *threadId = thread.GetThreadID();
486 // Enumerate each stack frame at the special "throw"
487 // breakpoint and find the raise exception function
488 // with the exception record parameter.
489 int numFrames = thread.GetNumFrames();
490 for (int i = 0; i < numFrames; i++)
492 lldb::SBFrame frame = thread.GetFrameAtIndex(i);
493 if (!frame.IsValid())
498 const char *functionName = frame.GetFunctionName();
499 if (functionName == NULL || strncmp(functionName, FUNCTION_NAME, sizeof(FUNCTION_NAME) - 1) != 0)
504 lldb::SBValue exValue = frame.FindVariable(VARIABLE_NAME);
505 if (!exValue.IsValid())
511 ULONG64 pExceptionRecord = exValue.GetValueAsUnsigned(error);
517 process.ReadMemory(pExceptionRecord, &pdle->ExceptionRecord, sizeof(pdle->ExceptionRecord), error);
530 LLDBServices::Disassemble(
535 PULONG disassemblySize,
538 lldb::SBInstruction instruction;
539 lldb::SBInstructionList list;
540 lldb::SBTarget target;
541 lldb::SBAddress address;
550 // lldb doesn't expect sign-extended address
551 offset = CONVERT_FROM_SIGN_EXTENDED(offset);
560 target = m_debugger.GetSelectedTarget();
561 if (!target.IsValid())
566 address = target.ResolveLoadAddress(offset);
567 if (!address.IsValid())
572 list = target.ReadInstructions(address, 1, "intel");
578 instruction = list.GetInstructionAtIndex(0);
579 if (!instruction.IsValid())
584 cch = snprintf(buffer, bufferSize, "%016llx ", (unsigned long long)offset);
588 size = instruction.GetByteSize();
589 data = instruction.GetData(target);
590 for (int i = 0; i < size && bufferSize > 0; i++)
592 byte = data.GetUnsignedInt8(error, i);
598 cch = snprintf(buffer, bufferSize, "%02x", byte);
602 // Pad the data bytes to 16 chars
604 while (bufferSize > 0)
612 cch = snprintf(buffer, bufferSize, "%s", instruction.GetMnemonic(target));
616 // Pad the mnemonic to 8 chars
617 while (bufferSize > 0)
624 snprintf(buffer, bufferSize, "%s\n", instruction.GetOperands(target));
627 if (disassemblySize != NULL)
629 *disassemblySize = size;
631 if (endOffset != NULL)
633 *endOffset = offset + size;
638 // Internal output string function
640 LLDBServices::OutputString(
644 if (mask == DEBUG_OUTPUT_ERROR)
646 m_returnObject.SetStatus(lldb::eReturnStatusFailed);
648 // Can not use AppendMessage or AppendWarning because they add a newline. SetError
649 // can not be used for DEBUG_OUTPUT_ERROR mask because it caches the error strings
650 // seperately from the normal output so error/normal texts are not intermixed
652 m_returnObject.Printf("%s", str);
655 //----------------------------------------------------------------------------
657 //----------------------------------------------------------------------------
660 LLDBServices::GetContextStackTrace(
662 ULONG startContextSize,
663 PDEBUG_STACK_FRAME frames,
666 ULONG frameContextsSize,
667 ULONG frameContextsEntrySize,
670 DT_CONTEXT *currentContext = (DT_CONTEXT*)frameContexts;
671 PDEBUG_STACK_FRAME currentFrame = frames;
672 lldb::SBThread thread;
677 // Doesn't support a starting context
678 if (startContext != NULL || frames == NULL || frameContexts == NULL || frameContextsEntrySize != sizeof(DT_CONTEXT))
684 thread = GetCurrentThread();
685 if (!thread.IsValid())
691 frame = thread.GetFrameAtIndex(0);
692 for (int i = 0; i < thread.GetNumFrames(); i++)
694 if (!frame.IsValid() || (cFrames > framesSize) || ((char *)currentContext > ((char *)frameContexts + frameContextsSize)))
698 lldb::SBFrame framePrevious;
699 lldb::SBFrame frameNext;
701 currentFrame->InstructionOffset = frame.GetPC();
702 currentFrame->StackOffset = frame.GetSP();
704 currentFrame->FuncTableEntry = 0;
705 currentFrame->Params[0] = 0;
706 currentFrame->Params[1] = 0;
707 currentFrame->Params[2] = 0;
708 currentFrame->Params[3] = 0;
709 currentFrame->Virtual = i == 0 ? TRUE : FALSE;
710 currentFrame->FrameNumber = frame.GetFrameID();
712 frameNext = thread.GetFrameAtIndex(i + 1);
713 if (frameNext.IsValid())
715 currentFrame->ReturnOffset = frameNext.GetPC();
718 if (framePrevious.IsValid())
720 currentFrame->FrameOffset = framePrevious.GetSP();
724 currentFrame->FrameOffset = frame.GetSP();
727 GetContextFromFrame(frame, currentContext);
729 framePrevious = frame;
737 if (framesFilled != NULL)
739 *framesFilled = cFrames;
744 //----------------------------------------------------------------------------
746 //----------------------------------------------------------------------------
749 LLDBServices::ReadVirtual(
758 // lldb doesn't expect sign-extended address
759 offset = CONVERT_FROM_SIGN_EXTENDED(offset);
761 lldb::SBProcess process = GetCurrentProcess();
762 if (!process.IsValid())
767 read = process.ReadMemory(offset, buffer, bufferSize, error);
774 return error.Success() || (read != 0) ? S_OK : E_FAIL;
778 LLDBServices::WriteVirtual(
787 // lldb doesn't expect sign-extended address
788 offset = CONVERT_FROM_SIGN_EXTENDED(offset);
790 lldb::SBProcess process = GetCurrentProcess();
791 if (!process.IsValid())
796 written = process.WriteMemory(offset, buffer, bufferSize, error);
801 *bytesWritten = written;
803 return error.Success() || (written != 0) ? S_OK : E_FAIL;
806 //----------------------------------------------------------------------------
808 //----------------------------------------------------------------------------
811 LLDBServices::GetSymbolOptions(
814 *options = SYMOPT_LOAD_LINES;
819 LLDBServices::GetNameByOffset(
822 ULONG nameBufferSize,
824 PULONG64 displacement)
826 ULONG64 disp = DEBUG_INVALID_OFFSET;
829 lldb::SBTarget target;
830 lldb::SBAddress address;
831 lldb::SBModule module;
832 lldb::SBFileSpec file;
833 lldb::SBSymbol symbol;
836 // lldb doesn't expect sign-extended address
837 offset = CONVERT_FROM_SIGN_EXTENDED(offset);
839 target = m_debugger.GetSelectedTarget();
840 if (!target.IsValid())
846 address = target.ResolveLoadAddress(offset);
847 if (!address.IsValid())
853 module = address.GetModule();
854 if (!module.IsValid())
860 file = module.GetFileSpec();
863 str.append(file.GetFilename());
866 symbol = address.GetSymbol();
867 if (symbol.IsValid())
869 lldb::SBAddress startAddress = symbol.GetStartAddress();
870 disp = address.GetOffset() - startAddress.GetOffset();
872 const char *name = symbol.GetName();
888 *nameSize = str.length();
892 str.copy(nameBuffer, nameBufferSize);
896 *displacement = disp;
902 LLDBServices::GetNumberModules(
906 ULONG numModules = 0;
909 lldb::SBTarget target = m_debugger.GetSelectedTarget();
910 if (!target.IsValid())
916 numModules = target.GetNumModules();
921 *loaded = numModules;
930 HRESULT LLDBServices::GetModuleByIndex(
934 ULONG64 moduleBase = UINT64_MAX;
936 lldb::SBTarget target;
937 lldb::SBModule module;
939 target = m_debugger.GetSelectedTarget();
940 if (!target.IsValid())
945 module = target.GetModuleAtIndex(index);
946 if (!module.IsValid())
951 moduleBase = GetModuleBase(target, module);
958 return moduleBase == UINT64_MAX ? E_FAIL : S_OK;
962 LLDBServices::GetModuleByModuleName(
968 ULONG64 moduleBase = UINT64_MAX;
969 ULONG moduleIndex = UINT32_MAX;
971 lldb::SBTarget target;
972 lldb::SBModule module;
973 lldb::SBFileSpec fileSpec;
974 fileSpec.SetFilename(name);
976 target = m_debugger.GetSelectedTarget();
977 if (!target.IsValid())
982 module = target.FindModule(fileSpec);
983 if (!module.IsValid())
988 moduleBase = GetModuleBase(target, module);
992 int numModules = target.GetNumModules();
993 for (int mi = startIndex; mi < numModules; mi++)
995 lldb::SBModule mod = target.GetModuleAtIndex(mi);
1007 *index = moduleIndex;
1013 return moduleBase == UINT64_MAX ? E_FAIL : S_OK;
1017 LLDBServices::GetModuleByOffset(
1023 ULONG64 moduleBase = UINT64_MAX;
1024 ULONG moduleIndex = UINT32_MAX;
1026 lldb::SBTarget target;
1029 // lldb doesn't expect sign-extended address
1030 offset = CONVERT_FROM_SIGN_EXTENDED(offset);
1032 target = m_debugger.GetSelectedTarget();
1033 if (!target.IsValid())
1038 numModules = target.GetNumModules();
1039 for (int mi = startIndex; mi < numModules; mi++)
1041 lldb::SBModule module = target.GetModuleAtIndex(mi);
1043 int numSections = module.GetNumSections();
1044 for (int si = 0; si < numSections; si++)
1046 lldb::SBSection section = module.GetSectionAtIndex(si);
1047 if (section.IsValid())
1049 lldb::addr_t baseAddress = section.GetLoadAddress(target);
1050 if (baseAddress != LLDB_INVALID_ADDRESS)
1052 if (offset > baseAddress)
1054 if ((offset - baseAddress) < section.GetByteSize())
1057 moduleBase = baseAddress - section.GetFileOffset();
1069 *index = moduleIndex;
1075 return moduleBase == UINT64_MAX ? E_FAIL : S_OK;
1079 LLDBServices::GetModuleNames(
1082 PSTR imageNameBuffer,
1083 ULONG imageNameBufferSize,
1084 PULONG imageNameSize,
1085 PSTR moduleNameBuffer,
1086 ULONG moduleNameBufferSize,
1087 PULONG moduleNameSize,
1088 PSTR loadedImageNameBuffer,
1089 ULONG loadedImageNameBufferSize,
1090 PULONG loadedImageNameSize)
1092 lldb::SBTarget target;
1093 lldb::SBFileSpec fileSpec;
1096 // lldb doesn't expect sign-extended address
1097 base = CONVERT_FROM_SIGN_EXTENDED(base);
1099 target = m_debugger.GetSelectedTarget();
1100 if (!target.IsValid())
1106 if (index != DEBUG_ANY_ID)
1108 lldb::SBModule module = target.GetModuleAtIndex(index);
1109 if (module.IsValid())
1111 fileSpec = module.GetFileSpec();
1116 int numModules = target.GetNumModules();
1117 for (int mi = 0; mi < numModules; mi++)
1119 lldb::SBModule module = target.GetModuleAtIndex(mi);
1120 if (module.IsValid())
1122 ULONG64 moduleBase = GetModuleBase(target, module);
1123 if (base == moduleBase)
1125 fileSpec = module.GetFileSpec();
1132 if (!fileSpec.IsValid())
1139 if (imageNameBuffer)
1141 int size = fileSpec.GetPath(imageNameBuffer, imageNameBufferSize);
1144 *imageNameSize = size;
1147 if (moduleNameBuffer)
1149 const char *fileName = fileSpec.GetFilename();
1150 if (fileName == NULL)
1154 stpncpy(moduleNameBuffer, fileName, moduleNameBufferSize);
1157 *moduleNameSize = strlen(fileName);
1160 if (loadedImageNameBuffer)
1162 int size = fileSpec.GetPath(loadedImageNameBuffer, loadedImageNameBufferSize);
1163 if (loadedImageNameSize)
1165 *loadedImageNameSize = size;
1172 LLDBServices::GetLineByOffset(
1176 ULONG fileBufferSize,
1178 PULONG64 displacement)
1180 ULONG64 disp = DEBUG_INVALID_OFFSET;
1184 lldb::SBTarget target;
1185 lldb::SBAddress address;
1186 lldb::SBFileSpec file;
1187 lldb::SBLineEntry lineEntry;
1190 // lldb doesn't expect sign-extended address
1191 offset = CONVERT_FROM_SIGN_EXTENDED(offset);
1193 target = m_debugger.GetSelectedTarget();
1194 if (!target.IsValid())
1200 address = target.ResolveLoadAddress(offset);
1201 if (!address.IsValid())
1209 lldb::SBSymbol symbol = address.GetSymbol();
1210 if (symbol.IsValid())
1212 lldb::SBAddress startAddress = symbol.GetStartAddress();
1213 disp = address.GetOffset() - startAddress.GetOffset();
1217 lineEntry = address.GetLineEntry();
1218 if (!lineEntry.IsValid())
1224 line = lineEntry.GetLine();
1225 file = lineEntry.GetFileSpec();
1228 str.append(file.GetDirectory());
1230 str.append(file.GetFilename());
1233 str.append(1, '\0');
1242 *fileSize = str.length();
1246 str.copy(fileBuffer, fileBufferSize);
1250 *displacement = disp;
1256 LLDBServices::GetSourceFileLineOffsets(
1262 if (fileLines != NULL)
1264 *fileLines = (ULONG)-1;
1270 LLDBServices::FindSourceFile(
1274 PULONG foundElement,
1282 // Internal functions
1284 LLDBServices::GetModuleDirectory(
1287 lldb::SBTarget target = m_debugger.GetSelectedTarget();
1288 if (!target.IsValid())
1293 lldb::SBFileSpec fileSpec;
1294 fileSpec.SetFilename(name);
1296 lldb::SBModule module = target.FindModule(fileSpec);
1297 if (!module.IsValid())
1302 return module.GetFileSpec().GetDirectory();
1306 LLDBServices::GetModuleBase(
1307 /* const */ lldb::SBTarget& target,
1308 /* const */ lldb::SBModule& module)
1310 // Find the first section with an valid base address
1311 int numSections = module.GetNumSections();
1312 for (int si = 0; si < numSections; si++)
1314 lldb::SBSection section = module.GetSectionAtIndex(si);
1315 if (section.IsValid())
1317 lldb::addr_t baseAddress = section.GetLoadAddress(target);
1318 if (baseAddress != LLDB_INVALID_ADDRESS)
1320 return baseAddress - section.GetFileOffset();
1328 //----------------------------------------------------------------------------
1329 // IDebugSystemObjects
1330 //----------------------------------------------------------------------------
1333 LLDBServices::GetCurrentProcessId(
1338 return E_INVALIDARG;
1341 lldb::SBProcess process = GetCurrentProcess();
1342 if (!process.IsValid())
1348 *id = process.GetProcessID();
1353 LLDBServices::GetCurrentThreadId(
1358 return E_INVALIDARG;
1361 lldb::SBThread thread = GetCurrentThread();
1362 if (!thread.IsValid())
1368 // This is allow the a valid current TID to be returned to
1369 // workaround a bug in lldb on core dumps.
1370 if (g_currentThreadIndex != -1)
1372 *id = g_currentThreadIndex;
1376 *id = thread.GetIndexID();
1381 LLDBServices::SetCurrentThreadId(
1384 lldb::SBProcess process = GetCurrentProcess();
1385 if (!process.IsValid())
1390 if (!process.SetSelectedThreadByIndexID(id))
1399 LLDBServices::GetCurrentThreadSystemId(
1404 return E_INVALIDARG;
1407 lldb::SBThread thread = GetCurrentThread();
1408 if (!thread.IsValid())
1414 // This is allow the a valid current TID to be returned to
1415 // workaround a bug in lldb on core dumps.
1416 if (g_currentThreadSystemId != -1)
1418 *sysId = g_currentThreadSystemId;
1422 *sysId = thread.GetThreadID();
1427 LLDBServices::GetThreadIdBySystemId(
1431 HRESULT hr = E_FAIL;
1434 lldb::SBProcess process;
1435 lldb::SBThread thread;
1437 if (threadId == NULL)
1439 return E_INVALIDARG;
1442 process = GetCurrentProcess();
1443 if (!process.IsValid())
1448 // If we have a "fake" thread OS (system) id and a fake thread index,
1449 // we need to return fake thread index.
1450 if (g_currentThreadSystemId == sysId && g_currentThreadIndex != -1)
1452 id = g_currentThreadIndex;
1456 thread = process.GetThreadByID(sysId);
1457 if (!thread.IsValid())
1462 id = thread.GetIndexID();
1472 LLDBServices::GetThreadContextById(
1473 /* in */ ULONG32 threadID,
1474 /* in */ ULONG32 contextFlags,
1475 /* in */ ULONG32 contextSize,
1476 /* out */ PBYTE context)
1478 lldb::SBProcess process;
1479 lldb::SBThread thread;
1480 lldb::SBFrame frame;
1481 DT_CONTEXT *dtcontext;
1482 HRESULT hr = E_FAIL;
1484 if (context == NULL || contextSize < sizeof(DT_CONTEXT))
1488 memset(context, 0, contextSize);
1490 process = GetCurrentProcess();
1491 if (!process.IsValid())
1496 // If we have a "fake" thread OS (system) id and a fake thread index,
1497 // use the fake thread index to get the context.
1498 if (g_currentThreadSystemId == threadID && g_currentThreadIndex != -1)
1500 thread = process.GetThreadByIndexID(g_currentThreadIndex);
1504 thread = process.GetThreadByID(threadID);
1507 if (!thread.IsValid())
1512 frame = thread.GetFrameAtIndex(0);
1513 if (!frame.IsValid())
1518 dtcontext = (DT_CONTEXT*)context;
1519 dtcontext->ContextFlags = contextFlags;
1521 GetContextFromFrame(frame, dtcontext);
1528 // Internal function
1530 LLDBServices::GetContextFromFrame(
1531 /* const */ lldb::SBFrame& frame,
1532 DT_CONTEXT *dtcontext)
1534 #ifdef DBG_TARGET_AMD64
1535 dtcontext->Rip = frame.GetPC();
1536 dtcontext->Rsp = frame.GetSP();
1537 dtcontext->Rbp = frame.GetFP();
1538 dtcontext->EFlags = GetRegister(frame, "rflags");
1540 dtcontext->Rax = GetRegister(frame, "rax");
1541 dtcontext->Rbx = GetRegister(frame, "rbx");
1542 dtcontext->Rcx = GetRegister(frame, "rcx");
1543 dtcontext->Rdx = GetRegister(frame, "rdx");
1544 dtcontext->Rsi = GetRegister(frame, "rsi");
1545 dtcontext->Rdi = GetRegister(frame, "rdi");
1546 dtcontext->R8 = GetRegister(frame, "r8");
1547 dtcontext->R9 = GetRegister(frame, "r9");
1548 dtcontext->R10 = GetRegister(frame, "r10");
1549 dtcontext->R11 = GetRegister(frame, "r11");
1550 dtcontext->R12 = GetRegister(frame, "r12");
1551 dtcontext->R13 = GetRegister(frame, "r13");
1552 dtcontext->R14 = GetRegister(frame, "r14");
1553 dtcontext->R15 = GetRegister(frame, "r15");
1555 dtcontext->SegCs = GetRegister(frame, "cs");
1556 dtcontext->SegSs = GetRegister(frame, "ss");
1557 dtcontext->SegDs = GetRegister(frame, "ds");
1558 dtcontext->SegEs = GetRegister(frame, "es");
1559 dtcontext->SegFs = GetRegister(frame, "fs");
1560 dtcontext->SegGs = GetRegister(frame, "gs");
1561 #elif DBG_TARGET_ARM
1562 dtcontext->Pc = frame.GetPC();
1563 dtcontext->Sp = frame.GetSP();
1564 dtcontext->Lr = GetRegister(frame, "lr");
1565 dtcontext->Cpsr = GetRegister(frame, "cpsr");
1567 dtcontext->R0 = GetRegister(frame, "r0");
1568 dtcontext->R1 = GetRegister(frame, "r1");
1569 dtcontext->R2 = GetRegister(frame, "r2");
1570 dtcontext->R3 = GetRegister(frame, "r3");
1571 dtcontext->R4 = GetRegister(frame, "r4");
1572 dtcontext->R5 = GetRegister(frame, "r5");
1573 dtcontext->R6 = GetRegister(frame, "r6");
1574 dtcontext->R7 = GetRegister(frame, "r7");
1575 dtcontext->R8 = GetRegister(frame, "r8");
1576 dtcontext->R9 = GetRegister(frame, "r9");
1577 dtcontext->R10 = GetRegister(frame, "r10");
1578 dtcontext->R11 = GetRegister(frame, "r11");
1579 dtcontext->R12 = GetRegister(frame, "r12");
1580 #elif DBG_TARGET_X86
1581 dtcontext->Eip = frame.GetPC();
1582 dtcontext->Esp = frame.GetSP();
1583 dtcontext->Ebp = frame.GetFP();
1584 dtcontext->EFlags = GetRegister(frame, "eflags");
1586 dtcontext->Edi = GetRegister(frame, "edi");
1587 dtcontext->Esi = GetRegister(frame, "esi");
1588 dtcontext->Ebx = GetRegister(frame, "ebx");
1589 dtcontext->Edx = GetRegister(frame, "edx");
1590 dtcontext->Ecx = GetRegister(frame, "ecx");
1591 dtcontext->Eax = GetRegister(frame, "eax");
1593 dtcontext->SegCs = GetRegister(frame, "cs");
1594 dtcontext->SegSs = GetRegister(frame, "ss");
1595 dtcontext->SegDs = GetRegister(frame, "ds");
1596 dtcontext->SegEs = GetRegister(frame, "es");
1597 dtcontext->SegFs = GetRegister(frame, "fs");
1598 dtcontext->SegGs = GetRegister(frame, "gs");
1602 // Internal function
1604 LLDBServices::GetRegister(
1605 /* const */ lldb::SBFrame& frame,
1608 lldb::SBValue regValue = frame.FindRegister(name);
1610 lldb::SBError error;
1611 DWORD_PTR result = regValue.GetValueAsUnsigned(error);
1616 //----------------------------------------------------------------------------
1618 //----------------------------------------------------------------------------
1621 LLDBServices::GetValueByName(
1623 PDWORD_PTR debugValue)
1625 lldb::SBFrame frame = GetCurrentFrame();
1626 if (!frame.IsValid())
1632 lldb::SBValue value = frame.FindRegister(name);
1633 if (!value.IsValid())
1639 *debugValue = value.GetValueAsUnsigned();
1644 LLDBServices::GetInstructionOffset(
1647 lldb::SBFrame frame = GetCurrentFrame();
1648 if (!frame.IsValid())
1654 *offset = frame.GetPC();
1659 LLDBServices::GetStackOffset(
1662 lldb::SBFrame frame = GetCurrentFrame();
1663 if (!frame.IsValid())
1669 *offset = frame.GetSP();
1674 LLDBServices::GetFrameOffset(
1677 lldb::SBFrame frame = GetCurrentFrame();
1678 if (!frame.IsValid())
1684 *offset = frame.GetFP();
1688 //----------------------------------------------------------------------------
1690 //----------------------------------------------------------------------------
1693 LLDBServices::GetCurrentProcess()
1695 lldb::SBProcess process;
1697 if (m_currentProcess == nullptr)
1699 lldb::SBTarget target = m_debugger.GetSelectedTarget();
1700 if (target.IsValid())
1702 process = target.GetProcess();
1707 process = *m_currentProcess;
1714 LLDBServices::GetCurrentThread()
1716 lldb::SBThread thread;
1718 if (m_currentThread == nullptr)
1720 lldb::SBProcess process = GetCurrentProcess();
1721 if (process.IsValid())
1723 thread = process.GetSelectedThread();
1728 thread = *m_currentThread;
1735 LLDBServices::GetCurrentFrame()
1737 lldb::SBFrame frame;
1739 lldb::SBThread thread = GetCurrentThread();
1740 if (thread.IsValid())
1742 frame = thread.GetSelectedFrame();