[lldb-dev] [RFC] Extend ObjectFile interface.

Greg Clayton gclayton at apple.com
Wed Jan 12 11:07:35 PST 2011

On Jan 11, 2011, at 8:17 PM, Stephen Wilson wrote:

> *,
> I have been prototyping a DynamicLoader plugin for the Linux platform.
> Current state of the effort is available here:
>   https://github.com/eightcien/lldb/tree/lldb-linux
> On ELF platforms there is a "rendezvous" structure in a processes
> address space populated by the runtime linker for use by debuggers.
> This structure provides the address of a function which is called by the
> linker each time a shared object is loaded and unloaded (thus a
> breakpoint at that address will let a debugger intercept such events), a
> list of entries describing the currently loaded shared objects, plus a
> few other things.
> In order to locate this structure one must interrogate the object file
> for the process.  The location of this rendezvous is provided by a
> DT_DEBUG entry in the processes .dynamic section.  The actual address
> must be reaped by looking at the loaded .dynamic section contents of the
> process.
> The first proposal is to add the following method to ObjectFile, which
> allows us to locate the needed information:
>    //------------------------------------------------------------------
>    /// Similar to Process::GetImageInfoAddress().
>    ///
>    /// Some platforms embed auxiliary structures useful to debuggers in the
>    /// address space of the inferior process.  This method returns the address
>    /// of such a structure if the information can be resolved via entries in
>    /// the object file.  ELF, for example, provides a means to hook into the
>    /// runtime linker so that a debugger may monitor the loading and unloading
>    /// of shared libraries.
>    ///
>    /// @return 
>    ///     The address of any auxiliary tables, or an invalid address if this
>    ///     object file format does not support or contain such information.
>    virtual lldb_private::Address
>    GetImageInfoAddress () { return Address(); }
> In my prototype the above method is implemented by ObjectFileELF, and
> Process::GetImageInfoAddress in turn uses this information.
> I use an Address object instead of an lldb::addr_t as it is slightly
> more generic, and perhaps more useful, to represent the info as a
> "section load address + offset".

Yes, this looks fine. The "Address" is the right thing to use since it can point you back to your module.

A quick note to everyone: if you have an Address can you get the module from which is comes which can then get your to your object and symbol files:

Address addr (...);
Module *module = addr.GetModule();
// Check the module in case "addr" was not section/offset (the section might be NULL)
if (module)
    ObjectFile *objfile = module->GetObjectFile();
    SymbolVendor*symbols = module->GetSymbolVendor();

Since addresses are stored as section offset, when shared libraries get loaded, the dynamic loader plug-ins tell the target where each section got loaded. Then we can resolve addresses as needed. 

For example, if you have a PC value 0x100020 that you got from a register in a thread, you can then resolve it:

addr_t pc = 0x100020;
Address pc_addr;
if (thread.GetProcess().GetTarget().GetSectionLoadList().ResolveLoadAddress(pc, pc_addr))
    // The address was successfully resolved and now contains a "Section *" that can point
    // you to the Module/ObjectFile/Symbols...

> The second bit is to provide the DynamicLoader plugin with a method to
> synchronize with the runtime linker.  A simple strategy is to set a
> breakpoint on the entry address for the executable and to parse the
> rendezvous structure after the linker has had a chance to populate it.
> Hence the following addition:
>    //------------------------------------------------------------------
>    /// Returns the virtual address of the entry point for this object 
>    /// file.
>    ///
>    /// @return
>    ///     The virtual address of the entry point or 
>    ///     LLDB_INVALID_ADDRESS if an entry point is not defined.
>    //------------------------------------------------------------------
>    virtual lldb::addr_t
>    GetEntryPoint () const { return LLDB_INVALID_ADDRESS; }
> The above two methods are enough to get a minimal DynamicLoader plugin
> functioning on Linux.  I would very much appreciate any
> feedback/comments on the above.

I would rather see this added as:

   virtual Address
   GetEntryPoint () const { return Address(); }

So that you know what module the entry point came from. The linux dynamic loader would then just know that the file and load addresses for a linux executable (not shared library, just executable files) are the same (is this true? Do the virtual addresses in the ELF file for an executable never change?) and it could get the entry point as an addr_t by doing:

ModuleSP exe_module_sp (target->GetExecutableModule ());
if (exe_module_sp)
	ObjectFile *exe_objfile = exe_module_sp->GetObjectFile();
	if (exe_objfile)
		Address entry_point (exe_objfile->GetEntryPoint());
		addr_t entry_point_load_addr = entry_point.GetFileAddress();

The other thing you might want to do, is in the linix dynamic loader plug-in, if you know that the executable is always at the same address as the virtual addresses in the file, you can automatically register the load address of the sections as soon as you construct the DynamicLoaderLinux object. Because when setting a breakoint, it will eventually turn into a section/offset breakpoint and the breakpoint won't set itself until the section gets loaded.

Let me know if you have any questions on this.

Greg Clayton

More information about the lldb-dev mailing list