[lldb-dev] How to use the C++ API? No useful documentation?
Greg Clayton via lldb-dev
lldb-dev at lists.llvm.org
Mon Mar 7 10:56:42 PST 2016
> On Mar 4, 2016, at 8:08 AM, Paul Peet via lldb-dev <lldb-dev at lists.llvm.org> wrote:
>
> Hi Pavel,
>
> First of all, thank you for looking into this. I really appreciate it.
> Secondly, the check with GetRestartedFromEvent did the trick.
> I am finally getting correct information. Thank You very much.
I would like to note that the initial Python implementation I pointed you at does check the restarted bit. Glad this fixes your issues.
>
> About the documentation, I really think it can be much better and I
> would also help in this case but my english isn't my first language as
> I am also not good at expressing the intention of every lldb feature
> because obviously I am also just a beginner.
>
> Although I think it would be helpful for other users, that if there
> would have been a valid C++ debugging example like my issue
> reproduction code.
We, and by we I mean Jim Ingham and myself, need to document this better. If you have a summary of the issues you ran into and what wasn't clear about the APIs, please let us know so we don't miss something when we write up the documentation.
Greg Clayton
> :)
>
> ~Paul
>
>
>
> 2016-03-04 13:09 GMT+01:00 Pavel Labath <labath at google.com>:
>> Hi Paul,
>>
>> I believe you are experiencing the same problem as a couple of other
>> people before you (see
>> <http://lists.llvm.org/pipermail/lldb-dev/2016-January/009293.html>,
>> <http://lists.llvm.org/pipermail/lldb-dev/2016-January/009453.html>).
>> Basically, you need to ignore the events with the "restarted" flag by
>> checking the GetRestartedFromEvent value for Stopped events. Linux
>> broadcasts this event on initial start, but other targets don't. This
>> is not a particularly well documented feature, and we would welcome
>> any improvements to the documentation. :)
>>
>> Let me know if you still have problems after adding the check for the
>> restarted flag.
>>
>> cheers,
>> pl
>>
>>
>> On 3 March 2016 at 15:26, Pavel Labath <labath at google.com> wrote:
>>> Thanks for the explanation. I'll look this over tomorrow.
>>>
>>> cheers,
>>> pl
>>>
>>> On 3 March 2016 at 15:23, Paul Peet <paulpeet17 at gmail.com> wrote:
>>>> Hi Pavel,
>>>>
>>>> This is the code:
>>>>
>>>> int main() {
>>>> using namespace lldb;
>>>>
>>>> SBDebugger::Initialize();
>>>> SBDebugger debugger = SBDebugger::Create(true);
>>>>
>>>> if(!debugger.IsValid()) {
>>>> return 1;
>>>> }
>>>>
>>>> SBTarget target = debugger.CreateTarget("/home/cynecx/dev/helloWorld/main");
>>>>
>>>> if(!target.IsValid()) {
>>>> return 1;
>>>> }
>>>>
>>>> SBBreakpoint bp1 = target.BreakpointCreateByLocation(
>>>> "/home/cynecx/dev/helloWorld/main.cpp", 7);
>>>>
>>>> if(!bp1.IsValid()) {
>>>> return 1;
>>>> }
>>>>
>>>> bp1.SetEnabled(true);
>>>>
>>>> const char* args[] = { "/home/cynecx/dev/helloWorld/main", 0 };
>>>> const char* env[] = { 0 };
>>>>
>>>> SBLaunchInfo launch_info(args);
>>>> launch_info.SetEnvironmentEntries(env, true);
>>>> launch_info.SetWorkingDirectory("/home/cynecx/dev/helloWorld");
>>>> launch_info.SetLaunchFlags(eLaunchFlagStopAtEntry);
>>>>
>>>> SBError error;
>>>> SBProcess process = target.Launch(launch_info, error);
>>>>
>>>> if(!process.IsValid() || !error.Success()) {
>>>> return 1;
>>>> }
>>>>
>>>> error = process.Continue();
>>>> if(!error.Success()) {
>>>> return 1;
>>>> }
>>>>
>>>> while(true) {
>>>> SBEvent event;
>>>> SBListener listener = debugger.GetListener();
>>>>
>>>> if(listener.WaitForEvent(6, event)) {
>>>> if(!event.IsValid()) {
>>>> break;
>>>> }
>>>>
>>>> const uint32_t event_type = event.GetType();
>>>>
>>>> if (!SBProcess::EventIsProcessEvent(event)) {
>>>> continue;
>>>> }
>>>>
>>>> if(event_type == SBProcess::eBroadcastBitStateChanged) {
>>>> const StateType state = SBProcess::GetStateFromEvent(event);
>>>>
>>>> switch(state) {
>>>> default:
>>>> continue;
>>>> case eStateStopped: {
>>>> // static bool runOnce = false;
>>>> //
>>>> // if(runOnce == false) {
>>>> // sleep(1);
>>>> // runOnce = true;
>>>> // }
>>>>
>>>> SBThread thread = process.GetThreadAtIndex(0);
>>>> SBStream stream;
>>>>
>>>> thread.GetStatus(stream);
>>>> event.GetDescription(stream);
>>>>
>>>> std::cout << stream.GetData() << std::endl;
>>>>
>>>> auto threadStopReason = thread.GetStopReason();
>>>> if(threadStopReason == eStopReasonBreakpoint) {
>>>> uint64_t bpId = thread.GetStopReasonDataAtIndex(0);
>>>>
>>>> if(bpId == static_cast<uint64_t>(bp1.GetID())) {
>>>> std::cout << "Stopped at breakpoint" << std::endl;
>>>> thread.StepOver();
>>>> }
>>>> } else if (threadStopReason == eStopReasonPlanComplete) {
>>>> std::cout << "Stopped at step" << std::endl;
>>>> }
>>>>
>>>> break;
>>>> }
>>>> }
>>>> } else if (SBProcess::eBroadcastBitSTDOUT) {
>>>> char buffer[1024];
>>>> size_t num_bytes = 0;
>>>> do
>>>> {
>>>> num_bytes = process.GetSTDOUT(buffer, sizeof(buffer));
>>>> if (num_bytes > 0)
>>>> printf("%*s", (int)num_bytes, buffer);
>>>> } while (num_bytes == sizeof(buffer));
>>>> }
>>>>
>>>> std::cout << "----------" << std::endl;
>>>> } else {
>>>> break;
>>>> }
>>>> }
>>>>
>>>> SBDebugger::Terminate();
>>>>
>>>> return 0;
>>>> }
>>>>
>>>> main.cpp:
>>>>
>>>> #include <cstddef>
>>>> #include <cstdint>
>>>> #include <iostream>
>>>>
>>>> int main() {
>>>>
>>>> std::cout << "Hello World" << std::endl;
>>>>
>>>> int i = 0;
>>>> std::cin >> i;
>>>>
>>>> if (i == 1) {
>>>> return 1;
>>>> }
>>>>
>>>> return 0;
>>>> }
>>>>
>>>>
>>>> So the problem is that I am not getting correct thread information
>>>> when receiving an eStateStopped event. It kinda seems that when
>>>> "thread.GetStatus(stream);", the thread hasn't stopped yet so I always
>>>> getting non-determine thread information.
>>>> I found out that on my linux vm, it works properly so I thought it
>>>> might be an issue with the kernel and stuff but I kinda found a
>>>> workaround by simply putting a sleep(1) before querying the thread
>>>> information. As expected it gave me correct thread information, also
>>>> the step-over worked properly because the thread plan used correct
>>>> line information.
>>>>
>>>> To compare both outputs:
>>>>
>>>> Correct one (with sleep(1)):
>>>>
>>>> * thread #1: tid = 5862, 0x0000000000400953 main`main + 35 at
>>>> main.cpp:7, name = 'main', stop reason = breakpoint 1.1
>>>> frame #0: 0x0000000000400953 main`main + 35 at main.cpp:7
>>>> 4
>>>> 5 int main() {
>>>> 6
>>>> -> 7 std::cout << "Hello World" << std::endl;
>>>> 8
>>>> 9 int i = 0;
>>>> 10 std::cin >> i;
>>>> 0x7f1dc4000930 Event: broadcaster = 0x55da93268068 (lldb.process),
>>>> type = 0x00000001 (state-changed), data = { process = 0x55da93268030
>>>> (pid = 5862), state = stopped}
>>>> ----------
>>>> * thread #1: tid = 5862, 0x0000000000400953 main`main + 35 at
>>>> main.cpp:7, name = 'main', stop reason = breakpoint 1.1
>>>> frame #0: 0x0000000000400953 main`main + 35 at main.cpp:7
>>>> 4
>>>> 5 int main() {
>>>> 6
>>>> -> 7 std::cout << "Hello World" << std::endl;
>>>> 8
>>>> 9 int i = 0;
>>>> 10 std::cin >> i;
>>>> 0x7f1dc4001640 Event: broadcaster = 0x55da93268068 (lldb.process),
>>>> type = 0x00000001 (state-changed), data = { process = 0x55da93268030
>>>> (pid = 5862), state = stopped}
>>>> Stopped at breakpoint
>>>> ----------
>>>> Hello World
>>>> ----------
>>>> * thread #1: tid = 5862, 0x0000000000400978 main`main + 72 at
>>>> main.cpp:9, name = 'main', stop reason = step over
>>>> frame #0: 0x0000000000400978 main`main + 72 at main.cpp:9
>>>> 6
>>>> 7 std::cout << "Hello World" << std::endl;
>>>> 8
>>>> -> 9 int i = 0;
>>>> 10 std::cin >> i;
>>>> 11
>>>> 12 if (i == 1) {
>>>> 0x7f1dc4003ae0 Event: broadcaster = 0x55da93268068 (lldb.process),
>>>> type = 0x00000001 (state-changed), data = { process = 0x55da93268030
>>>> (pid = 5862), state = stopped}
>>>> Stopped at step
>>>> ----------
>>>>
>>>> And the one with non-determinism:
>>>>
>>>> * thread #1: tid = 9097, 0x0000000000400830 main`_start, name = 'main'
>>>> frame #0: 0x0000000000400830 main`_start
>>>> main`_start:
>>>> 0x400830 <+0>: xorl %ebp, %ebp
>>>> 0x400832 <+2>: movq %rdx, %r9
>>>> 0x400835 <+5>: popq %rsi
>>>> 0x400836 <+6>: movq %rsp, %rdx
>>>> 0x7fbdd0000930 Event: broadcaster = 0x564549feffa8 (lldb.process),
>>>> type = 0x00000001 (state-changed), data = { process = 0x564549feff70
>>>> (pid = 9097), state = stopped}
>>>> ----------
>>>> * thread #1: tid = 9097, 0x0000000000400830 main`_start, name =
>>>> 'main', stop reason = breakpoint 1.1
>>>> frame #0: 0x0000000000400830 main`_start
>>>> main`_start:
>>>> 0x400830 <+0>: xorl %ebp, %ebp
>>>> 0x400832 <+2>: movq %rdx, %r9
>>>> 0x400835 <+5>: popq %rsi
>>>> 0x400836 <+6>: movq %rsp, %rdx
>>>> 0x7fbdd0001640 Event: broadcaster = 0x564549feffa8 (lldb.process),
>>>> type = 0x00000001 (state-changed), data = { process = 0x564549feff70
>>>> (pid = 9097), state = stopped}
>>>> Stopped at breakpoint
>>>> ----------
>>>> Hello World
>>>> ----------
>>>>
>>>> 2016-03-03 14:57 GMT+01:00 Pavel Labath <labath at google.com>:
>>>>> Hi Paul,
>>>>>
>>>>> I haven't followed this discussion from the start, and I am now having
>>>>> trouble understanding what is the issue at hand here. Could you just
>>>>> briefly repeat what is the problem, and maybe send the code for
>>>>> reproducing the problem again? Maybe I'll be able to help...
>>>>>
>>>>> pl
>>>>>
>>>>> On 3 March 2016 at 13:04, Paul Peet via lldb-dev
>>>>> <lldb-dev at lists.llvm.org> wrote:
>>>>>> Sorry to bring this up again, but I am not sure if this is really a
>>>>>> linux kernel issue anymore, see the following code:
>>>>>>
>>>>>> if(event_type == SBProcess::eBroadcastBitStateChanged) {
>>>>>> const StateType state = SBProcess::GetStateFromEvent(event);
>>>>>>
>>>>>> switch(state) {
>>>>>> default:
>>>>>> continue;
>>>>>> case eStateStopped: {
>>>>>> static bool runOnce = false;
>>>>>> if(runOnce == false) {
>>>>>> sleep(1); // sleep a second
>>>>>> runOnce = true;
>>>>>> }
>>>>>>
>>>>>> SBThread thread = process.GetThreadAtIndex(0);
>>>>>> SBStream stream;
>>>>>>
>>>>>> As I said before that strangely it worked on the vm with kernel 4.4 so
>>>>>> I tried using kernel 4.4 and it still didn't work.
>>>>>>
>>>>>> Next thing I did was enabling lldb's logging and what I noticed was
>>>>>> that when the first thread plan is being made it had wrong instruction
>>>>>> information that's probably because the thread was still running. So
>>>>>> what I tried was this runOnce with a sleep(1) and the result was as I
>>>>>> expected, the thread plan contained the correct instruction
>>>>>> information and the following breakpoints and step-overs were
>>>>>> correctly made.
>>>>>>
>>>>>> Any chance that this issue lies deep in lldb? Would the lldb log help
>>>>>> to trace back the issue?
>>>>>>
>>>>>> 2016-02-29 19:58 GMT+01:00 Greg Clayton <gclayton at apple.com>:
>>>>>>>
>>>>>>>> On Feb 28, 2016, at 2:17 PM, Paul Peet <paulpeet17 at gmail.com> wrote:
>>>>>>>>
>>>>>>>> Hey,
>>>>>>>>
>>>>>>>> Just to let you know that I think I made some progress in determine the problem.
>>>>>>>> I've basically setup an vm (archlinux, linux 4.4, lldb 3.7.1) and
>>>>>>>> tried the code on it. To my surprise it gave me proper output without
>>>>>>>> non-determinism. YEY.
>>>>>>>> I still don't have any idea why it's not working on my host system. I
>>>>>>>> might try testing linux 4.4 like I did on the vm.
>>>>>>>>
>>>>>>>> Do you have any idea/suspicion why it might not work on my system. (I
>>>>>>>> can provide additional information if needed).
>>>>>>>
>>>>>>> I don't. Maybe some of the linux experts out there might be able to help you. Are are working with top of tree LLDB sources right? You might post the exact linux setup you have in case that might allow people to help you out...
>>>>>>>
>>>>>>> Greg
>>>>>>>
>>>>>>>
>>>>>> _______________________________________________
>>>>>> lldb-dev mailing list
>>>>>> lldb-dev at lists.llvm.org
>>>>>> http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev
> _______________________________________________
> lldb-dev mailing list
> lldb-dev at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev
More information about the lldb-dev
mailing list