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 <
[email protected]> wrote:
>
> > On Mar 4, 2016, at 8:08 AM, Paul Peet via lldb-dev <
> [email protected]> 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 <[email protected]>:
> >> 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 <[email protected]> wrote:
> >>> Thanks for the explanation. I'll look this over tomorrow.
> >>>
> >>> cheers,
> >>> pl
> >>>
> >>> On 3 March 2016 at 15:23, Paul Peet <[email protected]> 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 <[email protected]>:
> >>>>> 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
> >>>>> <[email protected]> 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 <[email protected]>:
> >>>>>>>
> >>>>>>>> On Feb 28, 2016, at 2:17 PM, Paul Peet <[email protected]>
> 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
> >>>>>> [email protected]
> >>>>>> http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev
> > _______________________________________________
> > lldb-dev mailing list
> > [email protected]
> > http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev
>
> _______________________________________________
> lldb-dev mailing list
> [email protected]
> 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
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-dev