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