[lldb-dev] How to use the C++ API? No useful documentation?

Pavel Labath via lldb-dev lldb-dev at lists.llvm.org
Fri Mar 4 04:09:55 PST 2016


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


More information about the lldb-dev mailing list