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