brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.9 KiB · ef3a73c Raw
231 lines · cpp
1//===-- ThreadTest.cpp ------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "lldb/Target/Thread.h"10#include "Plugins/Platform/Linux/PlatformLinux.h"11#include <thread>12#ifdef _WIN3213#include "lldb/Host/windows/HostThreadWindows.h"14#include "lldb/Host/windows/windows.h"15 16#include "Plugins/Platform/Windows/PlatformWindows.h"17#include "Plugins/Process/Windows/Common/LocalDebugDelegate.h"18#include "Plugins/Process/Windows/Common/ProcessWindows.h"19#include "Plugins/Process/Windows/Common/TargetThreadWindows.h"20#endif21#include "lldb/Core/Debugger.h"22#include "lldb/Host/FileSystem.h"23#include "lldb/Host/HostInfo.h"24#include "lldb/Host/HostThread.h"25#include "lldb/Target/Process.h"26#include "lldb/Target/StopInfo.h"27#include "lldb/Utility/ArchSpec.h"28#include "gtest/gtest.h"29 30using namespace lldb_private;31using namespace lldb;32 33namespace {34 35#ifdef _WIN3236using SetThreadDescriptionFunctionPtr =37    HRESULT(WINAPI *)(HANDLE hThread, PCWSTR lpThreadDescription);38 39static SetThreadDescriptionFunctionPtr SetThreadName;40#endif41 42class ThreadTest : public ::testing::Test {43public:44  void SetUp() override {45    FileSystem::Initialize();46    HostInfo::Initialize();47#ifdef _WIN3248    HMODULE hModule = ::LoadLibraryW(L"Kernel32.dll");49    if (hModule) {50      SetThreadName = reinterpret_cast<SetThreadDescriptionFunctionPtr>(51          (void *)::GetProcAddress(hModule, "SetThreadDescription"));52    }53    PlatformWindows::Initialize();54#endif55    platform_linux::PlatformLinux::Initialize();56  }57  void TearDown() override {58#ifdef _WIN3259    PlatformWindows::Terminate();60#endif61    platform_linux::PlatformLinux::Terminate();62    HostInfo::Terminate();63    FileSystem::Terminate();64  }65};66 67class DummyProcess : public Process {68public:69  DummyProcess(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp)70      : Process(target_sp, listener_sp) {}71 72  bool CanDebug(lldb::TargetSP target, bool plugin_specified_by_name) override {73    return true;74  }75  Status DoDestroy() override { return {}; }76  void RefreshStateAfterStop() override {}77  size_t DoReadMemory(lldb::addr_t vm_addr, void *buf, size_t size,78                      Status &error) override {79    return 0;80  }81  bool DoUpdateThreadList(ThreadList &old_thread_list,82                          ThreadList &new_thread_list) override {83    return false;84  }85  llvm::StringRef GetPluginName() override { return "Dummy"; }86 87  ProcessModID &GetModIDNonConstRef() { return m_mod_id; }88};89 90class DummyThread : public Thread {91public:92  using Thread::Thread;93 94  ~DummyThread() override { DestroyThread(); }95 96  void RefreshStateAfterStop() override {}97 98  lldb::RegisterContextSP GetRegisterContext() override { return nullptr; }99 100  lldb::RegisterContextSP101  CreateRegisterContextForFrame(StackFrame *frame) override {102    return nullptr;103  }104 105  bool CalculateStopInfo() override { return false; }106 107  bool IsStillAtLastBreakpointHit() override { return true; }108};109} // namespace110 111TargetSP CreateTarget(DebuggerSP &debugger_sp, ArchSpec &arch) {112  PlatformSP platform_sp;113  TargetSP target_sp;114  debugger_sp->GetTargetList().CreateTarget(115      *debugger_sp, "", arch, eLoadDependentsNo, platform_sp, target_sp);116 117  return target_sp;118}119 120#ifdef _WIN32121std::shared_ptr<TargetThreadWindows>122CreateWindowsThread(const ProcessWindowsSP &process_sp, std::thread &t) {123  HostThread host_thread((lldb::thread_t)t.native_handle());124  ThreadSP thread_sp =125      std::make_shared<TargetThreadWindows>(*process_sp.get(), host_thread);126  return std::static_pointer_cast<TargetThreadWindows>(thread_sp);127}128 129TEST_F(ThreadTest, GetThreadDescription) {130  if (!SetThreadName)131    return;132 133  ArchSpec arch(HostInfo::GetArchitecture());134  Platform::SetHostPlatform(PlatformWindows::CreateInstance(true, &arch));135 136  DebuggerSP debugger_sp = Debugger::CreateInstance();137  ASSERT_TRUE(debugger_sp);138 139  TargetSP target_sp = CreateTarget(debugger_sp, arch);140  ASSERT_TRUE(target_sp);141 142  ListenerSP listener_sp(Listener::MakeListener("dummy"));143  auto process_sp = std::static_pointer_cast<ProcessWindows>(144      ProcessWindows::CreateInstance(target_sp, listener_sp, nullptr, false));145  ASSERT_TRUE(process_sp);146 147  std::thread t([]() {});148  auto thread_sp = CreateWindowsThread(process_sp, t);149  DWORD tid = thread_sp->GetHostThread().GetNativeThread().GetThreadId();150  HANDLE hThread = ::OpenThread(THREAD_SET_LIMITED_INFORMATION, FALSE, tid);151  ASSERT_TRUE(hThread);152 153  SetThreadName(hThread, L"thread name");154  ::CloseHandle(hThread);155  ASSERT_STREQ(thread_sp->GetName(), "thread name");156 157  t.join();158}159#endif160 161TEST_F(ThreadTest, SetStopInfo) {162  ArchSpec arch("powerpc64-pc-linux");163 164  Platform::SetHostPlatform(165      platform_linux::PlatformLinux::CreateInstance(true, &arch));166 167  DebuggerSP debugger_sp = Debugger::CreateInstance();168  ASSERT_TRUE(debugger_sp);169 170  TargetSP target_sp = CreateTarget(debugger_sp, arch);171  ASSERT_TRUE(target_sp);172 173  ListenerSP listener_sp(Listener::MakeListener("dummy"));174  ProcessSP process_sp = std::make_shared<DummyProcess>(target_sp, listener_sp);175  ASSERT_TRUE(process_sp);176 177  DummyProcess *process = static_cast<DummyProcess *>(process_sp.get());178 179  ThreadSP thread_sp = std::make_shared<DummyThread>(*process_sp.get(), 0);180  ASSERT_TRUE(thread_sp);181 182  StopInfoSP stopinfo_sp =183      StopInfo::CreateStopReasonWithBreakpointSiteID(*thread_sp.get(), 0);184  ASSERT_TRUE(stopinfo_sp->IsValid() == true);185 186  /*187   Should make stopinfo valid.188   */189  process->GetModIDNonConstRef().BumpStopID();190  ASSERT_TRUE(stopinfo_sp->IsValid() == false);191 192  thread_sp->SetStopInfo(stopinfo_sp);193  ASSERT_TRUE(stopinfo_sp->IsValid() == true);194}195 196TEST_F(ThreadTest, GetPrivateStopInfo) {197  ArchSpec arch("powerpc64-pc-linux");198 199  Platform::SetHostPlatform(200      platform_linux::PlatformLinux::CreateInstance(true, &arch));201 202  DebuggerSP debugger_sp = Debugger::CreateInstance();203  ASSERT_TRUE(debugger_sp);204 205  TargetSP target_sp = CreateTarget(debugger_sp, arch);206  ASSERT_TRUE(target_sp);207 208  ListenerSP listener_sp(Listener::MakeListener("dummy"));209  ProcessSP process_sp = std::make_shared<DummyProcess>(target_sp, listener_sp);210  ASSERT_TRUE(process_sp);211 212  DummyProcess *process = static_cast<DummyProcess *>(process_sp.get());213 214  ThreadSP thread_sp = std::make_shared<DummyThread>(*process_sp.get(), 0);215  ASSERT_TRUE(thread_sp);216 217  StopInfoSP stopinfo_sp =218      StopInfo::CreateStopReasonWithBreakpointSiteID(*thread_sp.get(), 0);219  ASSERT_TRUE(stopinfo_sp);220 221  thread_sp->SetStopInfo(stopinfo_sp);222 223  /*224   Should make stopinfo valid if thread is at last breakpoint hit.225   */226  process->GetModIDNonConstRef().BumpStopID();227  ASSERT_TRUE(stopinfo_sp->IsValid() == false);228  StopInfoSP new_stopinfo_sp = thread_sp->GetPrivateStopInfo();229  ASSERT_TRUE(new_stopinfo_sp && stopinfo_sp->IsValid() == true);230}231