[lldb-dev] Development of a Plugin to be loaded in LLDB from external library

Abhishek Aggarwal via lldb-dev lldb-dev at lists.llvm.org
Wed Apr 27 03:13:06 PDT 2016

Hi Greg

My comments are inlined.

On Tue, Apr 26, 2016 at 7:03 PM, Greg Clayton <gclayton at apple.com> wrote:

> > On Apr 26, 2016, at 1:50 AM, Abhishek Aggarwal via lldb-dev <
> lldb-dev at lists.llvm.org> wrote:
> >
> > Hi everyone
> >
> > There has been previous discussions in this mailing list regarding
> Enabling Intel(R) Processor Trace collection in LLDB. A new APIs are being
> developed to be added to SB APIs that will provide raw traces (collected on
> lldb-server side). These APIs are Trace technology independent and hence
> can work for other Tracing technologies also. The decoding of the raw
> traces can be done outside LLDB. For details you can refer to the thread
> with the subject "Review of API and remote packets" started on March 31,
> 2016.
> >
> > I am working on developing a Plugin that will use these new APIs to
> enable Intel(R) Processor Trace technology and collect raw trace data for
> the inferior being debugged by LLDB. The plugin will perform decoding on
> the trace data to present it as a meaningful information to the user of
> LLDB Debugger. I want to use this plugin through LLDB CLI. I have few
> questions regarding development of this plugin:
> >
> > 1. What is the best way to develop this plugin? Should it be done as
> shown in "examples/plugins/commands/fooplugin.cpp" ( i.e. a C++ based
> solution and using 'plugin load <path_of_shared_lib>' command) or should I
> go for Python based solution to add new commands using Python functions?
> I personally would add a new folder for all trace plug-ins:
> $(trunk)/source/Plugins/Trace
> Then add one for the Intel trace:
> $(trunk)/source/Plugins/Trace/Intel
> We should then add a new "trace" multi-word command into that would get
> added into our commands in CommandInterpreter::LoadCommandDictionary():
>     m_command_dict["trace"] = CommandObjectSP (new
> CommandObjectMultiwordTrace (*this));
> This command would then have sub commands like "start", "stop", and any
> other commands we would need in order to display trace data.
Probably, I shouldn't have used the word 'Plugin'. I want to develop an
external 'tool' that will link to liblldb.so just to extract the raw trace
data using SB API of LLDB (SBProcess::StartTrace (SBTraceOptions &options))
for the debugged inferior. The tool will then process this raw data to
convert and show it as a meaningful information to the user. I am planning
to keep it external without compiling it into LLDB (the decision of keeping
it external resulted in from the previous discussions on this mailing list
as people were skeptical of compiling it into LLDB because of its
dependency on Intel(R) 'Processor Trace Decoding Library'). Making this
tool as a part of LLDB repository but not compiling into LLDB will enable
users of this tool to compile it separately and use it without affecting
anyone who doesn't want to use it.

I want to enable the user of this tool to use it through LLDB CLI. For this
purpose, I will have to provide some user-defined commands once this tool
is loaded in LLDB externally via 'plugin load <shared_lib_path>' command. I
am referring to $(trunk)/examples/plugins/commands/fooplugin.cpp file for
the implementation.

The function lldb::PluginInitialize (lldb::SBDebugger debugger) will look
something like this:
    lldb::SBCommandInterpreter interpreter =
    lldb::SBCommand processor-trace =
interpreter.AddMultiwordCommand("processor-trace",NULL);    // replaced
'foo' by 'processor-trace' in fooplugin.cpp
    processor-trace.AddCommand ("start", new StartCommand (), "configures
intel processor trace & start tracing the inferior");   // replaced 'child'
by 'start'

interpreter.AddMultiwordCommand("processor-trace",NULL) will add
'processor-trace' multiword Command Object via
CommandInterpreter::AddUserCommand() in
'm_user_dict' data member like this:    m_user_dict ["processor-trace"] =

In order to load this tool externally (as a shared library) in LLDB, I
believe the user-defined commands will go to 'm_user_dict' and not
'm_command_dict' as m_command_dict represents basic built-in commands of

> > 2. I am planning to upstream this developed plugin in LLDB public
> repository once the development is finished. Any user that wants to use
> Intel(R) Processor Trace will be able to do so by compiling this plugin and
> loading it via LLDB CLI as an external library. What should be the ideal
> location to place this plugin in LLDB repository? I could think of the
> 'tools' folder.
> All plug-ins right now are all internal to LLDB and are currently
> developed in the "$(trunk)/source/Plugins" and compiled into LLDB right
> now. We don't currently have a model where plug-ins can be externally
> loaded into LLDB as most of the plug-ins use the lldb_private APIs. This is
> mostly due to C++ and the fragility of exporting classes that could be
> inherited from. Our public API (anything in the "lldb" namespace is
> designed to be exported from the LLDB shared library) follows some rules:
> 1 - No inheritance
> 2 - No virtual functions
> 3 - Fixed instance variables that never change (usually a single
> shared_ptr, unique_ptr or just plain pointer)
If the above approach is followed then we don't have to compile the tool
into LLDB. Also, the tool will not use any lldb_private APIs. It will
purely use SB APIs of LLDB.
e.g. lldb::SBCommandPluginInterface class will be inherited to define
StartCommand class in above example:

class StartCommand : public lldb::SBCommandPluginInterface {

> This isn't to say we can't start to develop a way to do external plug-ins,
> but if we do, this will be new work and will involve a lot of thought to
> ensure that plug-ins will be able to be loaded by current and future
> versions of LLDB.
> The Intel trace plug-in is going to require very close integration with
> the ProcessGDBRemote if the pluig-in design stays on the course of adding
> packets to a GDB server so I don't see how you would make a plug-in that
> can live on the public API and be external.

I hope the above explanation answers this question. It is possible to
develop this tool using only public APIs of LLDB and be kept external at
the same time without compiling it into LLDB. In my opinion, the best place
to keep this tool will be $(trunk)/tools/trace/intel-pt folder.

> If you go the route of using expressions in order to enable the gathering
> and do everything by just using what is available in the public API, this
> can work as a plug-in, but it then loses the ability to add functions to
> the public LLDB API like we spoke about ( lldb::SBTrace
> lldb::SBProcess::StartTrace(lldb::SBTraceOptions &options) ).
> Greg Clayton
Please let me know if I couldn't explain myself properly or I missed some
crucial points here. Thanks for your feedback.

- Abhishek Aggarwal
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/lldb-dev/attachments/20160427/9a8f6557/attachment-0001.html>

More information about the lldb-dev mailing list