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@lists.llvm.org> wrote:

>
> > On Mar 4, 2016, at 8:08 AM, Paul Peet via lldb-dev <
> lldb-dev@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 <lab...@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 <lab...@google.com> wrote:
> >>> Thanks for the explanation. I'll look this over tomorrow.
> >>>
> >>> cheers,
> >>> pl
> >>>
> >>> On 3 March 2016 at 15:23, Paul Peet <paulpee...@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 <lab...@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@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 <gclay...@apple.com>:
> >>>>>>>
> >>>>>>>> On Feb 28, 2016, at 2:17 PM, Paul Peet <paulpee...@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@lists.llvm.org
> >>>>>> http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev
> > _______________________________________________
> > lldb-dev mailing list
> > lldb-dev@lists.llvm.org
> > http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev
>
> _______________________________________________
> lldb-dev mailing list
> lldb-dev@lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev
>
//===-- SBAddress.h ---------------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef LLDB_SBAddress_h_
#define LLDB_SBAddress_h_

#include "lldb/API/SBDefines.h"
#include "lldb/API/SBModule.h"

namespace lldb {

class LLDB_API SBAddress
{
public:

    SBAddress ();

    SBAddress (const lldb::SBAddress &rhs);

    SBAddress (lldb::SBSection section, lldb::addr_t offset);

    // Create an address by resolving a load address using the supplied target
    SBAddress (lldb::addr_t load_addr, lldb::SBTarget &target);

    ~SBAddress ();

    const lldb::SBAddress &
    operator = (const lldb::SBAddress &rhs);

    //------------------------------------------------------------------
    /// @return
    ///     true if the object is valid.  If the object is invalid, it is
    ///     not safe to call any other methods.
    //------------------------------------------------------------------
    bool
    IsValid () const;

    //------------------------------------------------------------------
    /// Clears the address.  The object is no longer valid.
    //------------------------------------------------------------------
    void
    Clear ();

    //------------------------------------------------------------------
    /// Get the file address.
    ///
    /// If an address comes from a file on disk that has section
    /// relative addresses, then it has a virtual address that is
    /// relative to a unique section in the object file.
    ///
    /// @return
    ///     The valid file virtual address, or LLDB_INVALID_ADDRESS if
    ///     the address doesn't have a file virtual address (image is
    ///     from memory only with no representation on disk).
    //------------------------------------------------------------------
    addr_t
    GetFileAddress () const;

    //------------------------------------------------------------------
    /// Get the load address.
    ///
    /// If an address comes from a file on disk that has section
    /// relative addresses, then it has a virtual address that is
    /// relative to a unique section in the object file. Sections
    /// get resolved at runtime by DynamicLoader plug-ins as images
    /// (executables and shared libraries) get loaded/unloaded. If a
    /// section is loaded, then the load address can be resolved.
    ///
    /// @param[in] target
    ///     The target in which to search.
    ///
    /// @return
    ///     The valid load virtual address, or LLDB_INVALID_ADDRESS if
    ///     the address is currently not loaded.
    //------------------------------------------------------------------
    addr_t
    GetLoadAddress (const lldb::SBTarget &target) const;

    //------------------------------------------------------------------
    /// Set the section and address within the section.  If it succeeds,
    /// the object becomes valid.
    ///
    /// @param[in] section
    ///     A lldb::SBSection object to use as the section base.
    ///
    /// @param[in] offset
    ///     A new offset value for this object.
    //------------------------------------------------------------------
    void
    SetAddress (lldb::SBSection section, lldb::addr_t offset);

    //------------------------------------------------------------------
    /// Tries to resolve the address within the target.  If this fails,
    /// assumes the address is absolute, e.g., on the stack or heap.  If it
    /// succeeds, the object becomes valid.
    ///
    /// @param[in] load_addr
    ///     A new offset value for this object.
    ///
    /// @param[in] target
    ///     The target within which the offset is valid.
    //------------------------------------------------------------------
    void
    SetLoadAddress (lldb::addr_t load_addr, 
                    lldb::SBTarget &target);

    //------------------------------------------------------------------
    /// Set the offset for this address, relative to the current section,
    /// if any.
    ///
    /// @param[in] offset
    ///     A new offset value for this object.
    //------------------------------------------------------------------
    // FIXME:  Should this be SetOffsetAddress?
    bool
    OffsetAddress (addr_t offset);

    //------------------------------------------------------------------
    /// Dump a description of this object to the given lldb::SBStream.
    ///
    /// @param[in] description
    ///     The stream to which to dump the object description.
    //------------------------------------------------------------------
    bool
    GetDescription (lldb::SBStream &description);

    //------------------------------------------------------------------
    /// Lookup symbol information for this address.  An address might
    /// refer to code or data from an existing module, or it might refer to
    /// something on the stack or heap. This function will only return
    /// valid values if the address has been resolved to a code or data
    /// address using "void SBAddress::SetLoadAddress(...)" or
    /// "lldb::SBAddress SBTarget::ResolveLoadAddress (...)".
    ///
    /// @param[in] resolve_scope
    ///     lldb::SymbolContextItem value specifying the scope in which to
    ///     resolve this address.
    ///
    /// @return
    ///     lldb::SBSymbolContext with the result.
    //------------------------------------------------------------------
    lldb::SBSymbolContext
    GetSymbolContext (uint32_t resolve_scope);

    // The following functions grab individual objects for a given address and
    // are less efficient if you want more than one symbol related objects. 
    // Use one of the following when you want multiple debug symbol related 
    // objects for an address:
    //    lldb::SBSymbolContext SBAddress::GetSymbolContext (uint32_t resolve_scope);
    //    lldb::SBSymbolContext SBTarget::ResolveSymbolContextForAddress (const SBAddress &addr, uint32_t resolve_scope);
    // One or more bits from the SymbolContextItem enumerations can be logically
    // OR'ed together to more efficiently retrieve multiple symbol objects.

    //------------------------------------------------------------------
    /// @return section
    ///     The lldb::SBSection containing this address.
    //------------------------------------------------------------------
    lldb::SBSection
    GetSection ();

    //------------------------------------------------------------------
    /// @return section
    ///     The offset for this address, relative to the section.
    //------------------------------------------------------------------
    lldb::addr_t
    GetOffset ();

    //------------------------------------------------------------------
    /// @return section
    ///     The module containing this address.
    //------------------------------------------------------------------
    lldb::SBModule
    GetModule ();
    
    //------------------------------------------------------------------
    /// @return section
    ///     The compile unit containing this address.
    //------------------------------------------------------------------
    lldb::SBCompileUnit
    GetCompileUnit ();

    //------------------------------------------------------------------
    /// @return section
    ///     The function containing this address.
    //------------------------------------------------------------------
    lldb::SBFunction
    GetFunction ();

    //------------------------------------------------------------------
    /// @return section
    ///     The block containing this address.
    //------------------------------------------------------------------
    lldb::SBBlock
    GetBlock ();

    //------------------------------------------------------------------
    /// @return section
    ///     The symbol at this address.
    //------------------------------------------------------------------
    lldb::SBSymbol
    GetSymbol ();

    //------------------------------------------------------------------
    /// @return section
    ///     The lldb::SBLineEntry specifying the file location that
    ///     corresponds to this address.
    //------------------------------------------------------------------
    lldb::SBLineEntry
    GetLineEntry ();
    
    //------------------------------------------------------------------
    /// @return section
    ///     The classification for this address.
    //------------------------------------------------------------------
    lldb::AddressClass
    GetAddressClass ();

protected:

    friend class SBBlock;
    friend class SBBreakpointLocation;
    friend class SBFrame;
    friend class SBFunction;
    friend class SBLineEntry;
    friend class SBInstruction;
    friend class SBModule;
    friend class SBSection;
    friend class SBSymbol;
    friend class SBSymbolContext;
    friend class SBTarget;
    friend class SBThread;
    friend class SBThreadPlan;
    friend class SBValue;
    friend class SBQueueItem;

    lldb_private::Address *
    operator->();

    const lldb_private::Address *
    operator->() const;

    lldb_private::Address *
    get ();

    lldb_private::Address &
    ref();

    const lldb_private::Address &
    ref() const;

    SBAddress (const lldb_private::Address *lldb_object_ptr);

    void
    SetAddress (const lldb_private::Address *lldb_object_ptr);

private:

    std::unique_ptr<lldb_private::Address> m_opaque_ap;
};


} // namespace lldb

#endif // LLDB_SBAddress_h_
_______________________________________________
lldb-dev mailing list
lldb-dev@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev

Reply via email to