[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