[lldb-dev] process calling lldb to symbolicate its own backtrace

Greg Clayton gclayton at apple.com
Tue Sep 24 14:00:53 PDT 2013


If you do follow my steps 1 - 4, you just need to be able to set the section load locations correctly. "info->dlpi_addr" will either be a slide, or an absolute address which you can then use in either the slide or section setting code. If you read up on the dl_iterate_phdr() function you should be able to determine which it is.

So yes, you should be able to do this as long as you can get the section load addresses for each module.

Greg


On Sep 24, 2013, at 1:47 PM, Timothee Cour <timothee.cour2 at gmail.com> wrote:

> 
> 
> 
> On Tue, Sep 24, 2013 at 1:05 PM, Greg Clayton <gclayton at apple.com> wrote:
> 
> On Sep 24, 2013, at 12:03 PM, Timothee Cour <timothee.cour2 at gmail.com> wrote:
> 
> > Thanks for your answer, I understand all the steps except for how to determine slide address or load address. The docs in http://lldb.llvm.org/symbolication.html weren't very helpful for determining that (eg --slide 0x123000 : not sure where to determine that).
> 
> In order to make sense of your backtraces, you will need to have access to the shared library load locations. The symbolication steps I outlined were for having a backtrace from a binary that is no longer running and you are later trying to symbolicate things. In order to do this, you need to have access to the load locations of the binaries (MacOSX crash logs have all of this information).
> 
> 
> You don't need to do any of the steps 1 - 4 if you are attaching to a process. If you can attach to the process, get the target and this target will automatically have a complete list of loaded shared libraries already slid around and ready to start doing lookups (resolve the SBAddress from a load address, then resolve the symbol context).
> 
> So it really depends on where you are getting the addresses that you want to symbolicate. If you get a backtrace, wait for a while, then attach to a process so you can symbolicate, the process might have loaded/unloaded one or more shared libraries in the time gap since the backtrace was taken and there are no guarantees that the addresses will resolve to the right symbols.
> 
> If you are trying to use LLDB within your process, you won't be able to attach to yourself. We also don't have a mode where LLDB attaches for viewing only (not for debugging).
> 
> Is there any plan to support that? Or is that not needed?
>  
> This kind of viewing only attach would then allow LLDB to attach to the process in which it is running. If you want to use LLDB for this kind of scenario, you will need to save the stack backtraces and also find a way to save all of the shared library load locations so you can later symbolicate with a separate process.
> 
> In my case, I want to be able to symbolicate (with lldb) stacktrace of my currently running process while the process is running (ie not after it died), and with minimal overhead. Are you sure there is no way to achieve that?
> 
> For example, I'm thinking of using dl_iterate_phdr(callback, context):
> foreach section in  module.GetSections
>       addr_t start = (addr_t)info->dlpi_addr + sect.GetFileAddress();
>       ctx->target.SetSectionLoadAddress(sect, start);
> 
> eg: something similar to here:
> http://data-race-test.googlecode.com/svn-history/r3966/trunk/v2/tsan/tsan_symbolize_lldb_linux.cc
>  
> 
> Could something like that work?
> 
> Otherwise : 
> * launching from A a process B that attaches to A and then computes symbolication of A's backtrace and returning it to A is what I did, but this is too slow.
> 
> * Related question: can we launch a new thread instead of starting a new process to achieve this?
> 
> 
> 
> 
> 
> >
> >
> > On Tue, Sep 24, 2013 at 10:10 AM, Greg Clayton <gclayton at apple.com> wrote:
> > In order to symbolicate here are the steps:
> >
> > 1 - Create debugger
> > 2 - Create target with the following call:
> >
> > lldb::SBTarget
> > SBDebugger::CreateTarget (const char *filename,
> >                           const char *target_triple,
> >                           const char *platform_name,
> >                           bool add_dependent_modules,
> >                           lldb::SBError& sb_error)
> >
> > You can specify NULL for platform if it is the local host platform, else specify a valid platform name ("remote-linux", "remote-macosx", etc).
> >
> > Specify "false" for "add_dependent_modules. This will make a target that _only_ loads the files you add to it.
> >
> > 3 - Load an additional modules (shared libraries) you need to do your symbolication with:
> >
> > lldb::SBModule
> > SBTarget::AddModule (const char *path,
> >                      const char *triple,
> >                      const char *uuid_cstr,
> >                      const char *symfile)
> >
> > Lets say you have "/tmp/a.so" which doesn't contain debug symbols, but "/tmp/debug/a.so" does and is a separate stand alone debug info file, you would specify "/tmp/a.so" for "path" and "/tmp/debug/a.so" for "symfile". Specify NULL for "uuid_cstr" unless you have a crash log that has the UUID information for each module in it. Use the same "triple" as you did for the target create.
> >
> > 4 - Specify the load locations for the sections you care about for each module
> >
> > First find the module:
> >
> > SBFileSpec module_path("/tmp/a.so");
> > SBModule module = target.FindModule(module_path);
> > if (module.IsValid())
> > {
> >
> > Now you need to decide if you want to rigidly slide your executables, or set the load address of sections individually. If you know the slide of your library and all sections should be slid by a fixed amount, figure out the slide and slide it:
> >
> >     int64_t slide = ...
> >     target.SetModuleLoadAddress (module, slide);
> >
> > Or, you can lookup the sections and set the load addresses individually:
> >
> >     lldb::addr_t text_load_address = ...;
> >     SBSection section = module.FindSection(".text")
> >     target.SetSectionLoadAddress(section, text_load_address);
> >
> > When setting the load address of sections, you don't need to compute a slide, you just need to set the actual address itself for the base of the section.
> >
> > Repeat this for all modules so they all have load locations and now you are ready to do lookups:
> >
> >     lldb::addr_t lookup_addr = ...;
> >
> >     lldb::SBAddress addr = target.ResolveLoadAddress (lookup_addr);
> >     if (addr.GetSection())
> >     {
> >         // If we have a valid section, then we can symbolicate
> >         SBSymbolContext sc = target.ResolveSymbolContextForAddress (addr, lldb::eSymbolContextEverything);
> >
> > Now you have a symbol context "sc" which has everything filled in. The symbol context has accessors for everything you need:
> >
> >     lldb::SBModule        GetModule ();
> >     lldb::SBCompileUnit   GetCompileUnit ();
> >     lldb::SBFunction      GetFunction ();
> >     lldb::SBBlock         GetBlock ();
> >     lldb::SBLineEntry     GetLineEntry ();
> >     lldb::SBSymbol        GetSymbol ();
> >
> > Each of these objects could be valid, or could be invalid. Test each one with "IsValid()":
> >
> >     if (GetFunction().IsValid())
> >     {
> >     }
> >     else if (GetSymbol().IsValid())
> >     {
> >     }
> >
> >
> > Now you have the deepest most scope for the address you have looked up. You might want to figure out if there are any inlined functions. For this you can use:
> >
> >     SBSymbolContext
> >     SBSymbolContext::GetParentOfInlinedScope (const SBAddress &curr_frame_pc,
> >                                               SBAddress &parent_frame_addr) const;
> >
> >
> > For example, we already have "addr" from above which is a SBAddress:
> >
> >     SBAddress curr_addr(addr);
> >
> >     while (1)
> >     {
> >         SBAddress parent_addr;
> >         SBSymbolContext parent_sc = sc.GetParentOfInlinedScope(curr_addr, parent_addr);
> >         if (!parent_sc.IsValid())
> >             break;
> >         // Print out frame info in "parent_addr" and "parent_sc"
> >
> >
> >     }
> >
> > There are more basics on our website:
> >
> > http://lldb.llvm.org/symbolication.html
> >
> >
> > On Sep 24, 2013, at 12:32 AM, Timothee Cour <timothee.cour2 at gmail.com> wrote:
> >
> > > I'm trying to get complete stacktraces from C/C++ (backtrace/backtrace_symbols has issues, eg line numbers are often wrong and file name omits full path), and want to use lldb for that.
> > >
> > > from the main process A (with pidA), I tried calling lldb in a separate process that attaches to pidA and then prints the backtrace; that works but is slow.
> > >
> > > So I'd like A to directly call lldb (via the C++ api) without having to launch a separate process, but can't make it work so far:
> > >
> > > SBDebugger.Create (works)
> > > CreateTargetWithFileAndArch (works)
> > >
> > > * FindFunctions (works but then GetContextAtIndex(0).GetLineEntry is invalid)
> > > * I also tried using ResolveFileAddress but that didn't work; not sure if it's because I need to set the load address somehow.
> > >
> > > Note that all the above work when calling a separate process.
> > >
> > > Is there some example code snippet for doing that?
> > >
> > > _______________________________________________
> > > lldb-dev mailing list
> > > lldb-dev at cs.uiuc.edu
> > > http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev
> >
> >
> 
> 




More information about the lldb-dev mailing list