Skip to content

Instantly share code, notes, and snippets.

@xusheng6
Created May 20, 2022 02:25
Show Gist options
  • Save xusheng6/c400695c84a81b07cb34ebebbeced880 to your computer and use it in GitHub Desktop.
Save xusheng6/c400695c84a81b07cb34ebebbeced880 to your computer and use it in GitHub Desktop.
script to troubleshoot LLDDB hang
#include <iostream>
#include <thread>
#include "lldb/API/LLDB.h"
using namespace std;
using namespace lldb;
class Debugger
{
public:
std::string path;
SBDebugger debugger;
SBTarget target;
SBProcess process;
bool stopped = false;
Debugger(const std::string& p): path(p) {}
~Debugger();
void EventListener();
void Run();
void Reset();
};
Debugger::~Debugger()
{
cout << "~Debugger()" << endl;
Reset();
}
void Debugger::Reset()
{
cout << "cleaning up" << endl;
process.Destroy();
SBDebugger::Destroy(debugger);
}
void Debugger::EventListener()
{
SBEvent event;
SBListener listener = SBListener("listener");
listener.StartListeningForEventClass(debugger, SBProcess::GetBroadcasterClassName(),
lldb::SBProcess::eBroadcastBitStateChanged);
process.GetBroadcaster().AddListener(listener, lldb::SBProcess::eBroadcastBitStateChanged);
bool done = false;
while (!done)
{
if (!listener.WaitForEvent(1, event))
continue;
uint32_t event_type = event.GetType();
if (lldb::SBProcess::EventIsProcessEvent(event))
{
if (event_type & lldb::SBProcess::eBroadcastBitStateChanged)
{
StateType state = SBProcess::GetStateFromEvent(event);
switch (state)
{
case lldb::eStateStopped:
{
cout << "eStateStopped" << endl;
stopped = true;
done = true;
break;
}
case lldb::eStateExited:
{
cout << "eStateExited" << endl;
stopped = true;
done = true;
break;
}
default:
break;
}
}
}
}
listener.StopListeningForEventClass(debugger, SBProcess::GetBroadcasterClassName(),
lldb::SBProcess::eBroadcastBitStateChanged);
process.GetBroadcaster().RemoveListener(listener, lldb::SBProcess::eBroadcastBitStateChanged);
// Reset();
}
void Debugger::Run()
{
SBDebugger::Initialize();
debugger = SBDebugger::Create();
if (!debugger.IsValid())
cout << "invalid debugger" << endl;
debugger.SetAsync(false);
std::thread thread([&](){ EventListener(); });
thread.detach();
target = debugger.CreateTarget(path.c_str());
if (!target.IsValid())
{
cout << "invalid target" << endl;
return;
}
// auto bp = target.BreakpointCreateByName("main");
SBCommandReturnObject result;
debugger.GetCommandInterpreter().HandleCommand("b main", result);
if (result.IsValid())
{
cout << "output: " << result.GetOutput() << endl;
}
else
{
cout << "command failed" << endl;
}
const char** argsArray = new const char*[2];
argsArray[0] = "";
argsArray[1] = nullptr;
SBLaunchInfo info(argsArray);
info.SetLaunchFlags(lldb::eLaunchFlagStopAtEntry);
SBError error;
process = target.Launch(info, error);
if (!(process.IsValid() && error.Success()))
{
cout << "fail to launch: " << error.GetCString() << endl;
return;
}
debugger.SetAsync(true);
error = process.Continue();
if (!error.Success())
{
cout << "fail to resume the target:" << error.GetCString() << endl;
}
while (!stopped)
{
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
int main(int argc, char** argv)
{
if (argc < 2)
{
cout << "specify one executable path" << endl;
return -1;
}
auto path = argv[1];
for (size_t i = 0; i < 300; i++)
{
auto* debugger = new Debugger(path);
debugger->Run();
delete debugger;
}
cout << "exiting" << endl;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment