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

John Lindal via lldb-dev lldb-dev at lists.llvm.org
Mon Mar 7 13:45:51 PST 2016


I was planning to take a stab at writing documentation, since I just
finished my own C++ app on top of lldb.  (Code Medic)

Attached is my attempt to add docs to SBAddress.  Am I on the right track?
If so, I'll tackle additional files.

Thanks,
John

On Mon, Mar 7, 2016 at 10:56 AM, Greg Clayton via lldb-dev <
lldb-dev at lists.llvm.org> wrote:

>
> > 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
>
> _______________________________________________
> lldb-dev mailing list
> lldb-dev at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/lldb-dev/attachments/20160307/696bb8a0/attachment-0001.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: SBAddress.h
Type: text/x-chdr
Size: 9715 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/lldb-dev/attachments/20160307/696bb8a0/attachment-0001.h>


More information about the lldb-dev mailing list