abhishek.aggarwal updated this revision to Diff 103924.
abhishek.aggarwal added a comment.

Changes after feedback

- Created static libs for each hardware feature to combine it to generate 
single shared library
- Removed error codes decoding logic and directly using error strings


https://reviews.llvm.org/D33035

Files:
  tools/CMakeLists.txt
  tools/intel-features/CMakeLists.txt
  tools/intel-features/README.txt
  tools/intel-features/cli-wrapper.cpp
  tools/intel-features/intel-mpx/CMakeLists.txt
  tools/intel-features/intel-mpx/cli-wrapper-mpxtable.cpp
  tools/intel-features/intel-mpx/cli-wrapper-mpxtable.h
  tools/intel-features/intel-mpx/test/Makefile
  tools/intel-features/intel-mpx/test/README.txt
  tools/intel-features/intel-mpx/test/TestMPXTable.py
  tools/intel-features/intel-mpx/test/main.cpp
  tools/intel-features/intel-pt/CMakeLists.txt
  tools/intel-features/intel-pt/Decoder.cpp
  tools/intel-features/intel-pt/Decoder.h
  tools/intel-features/intel-pt/PTDecoder.cpp
  tools/intel-features/intel-pt/PTDecoder.h
  tools/intel-features/intel-pt/README_CLI.txt
  tools/intel-features/intel-pt/README_TOOL.txt
  tools/intel-features/intel-pt/interface/PTDecoder.i
  tools/intel-features/scripts/CMakeLists.txt
  tools/intel-features/scripts/lldb-intel-features.swig
  tools/intel-features/scripts/python-typemaps.txt
  tools/intel-mpx/CMakeLists.txt
  tools/intel-mpx/IntelMPXTablePlugin.cpp
  tools/intel-mpx/test/Makefile
  tools/intel-mpx/test/README.txt
  tools/intel-mpx/test/TestMPXTable.py
  tools/intel-mpx/test/main.cpp

Index: tools/intel-mpx/CMakeLists.txt
===================================================================
--- tools/intel-mpx/CMakeLists.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-if (NOT CMAKE_SYSTEM_NAME MATCHES "Linux")
-  return ()
-endif ()
-
-include(${LLDB_PROJECT_ROOT}/cmake/LLDBDependencies.cmake)
-
-add_library(lldb-intel-mpxtable SHARED
-  IntelMPXTablePlugin.cpp
-  )
-
-target_link_libraries(lldb-intel-mpxtable
-                      PUBLIC liblldb LLVMSupport)
-
-install(TARGETS lldb-intel-mpxtable
-  LIBRARY DESTINATION bin)
Index: tools/intel-features/scripts/python-typemaps.txt
===================================================================
--- /dev/null
+++ tools/intel-features/scripts/python-typemaps.txt
@@ -0,0 +1,15 @@
+/* Typemap definitions to allow SWIG to properly handle some data types */
+
+// typemap for a char buffer
+%typemap(in) (char *dst, size_t dst_len) {
+   if (!PyInt_Check($input)) {
+       PyErr_SetString(PyExc_ValueError, "Expecting an integer");
+       return NULL;
+   }
+   $2 = PyInt_AsLong($input);
+   if ($2 <= 0) {
+       PyErr_SetString(PyExc_ValueError, "Positive integer expected");
+       return NULL;
+   }
+   $1 = (char *) malloc($2);
+}
Index: tools/intel-features/scripts/lldb-intel-features.swig
===================================================================
--- /dev/null
+++ tools/intel-features/scripts/lldb-intel-features.swig
@@ -0,0 +1,18 @@
+%module lldbIntelFeatures
+
+%{
+#include "lldb/lldb-public.h"
+#include "intel-pt/PTDecoder.h"
+using namespace ptdecoder;
+%}
+
+/* Various liblldb typedefs that SWIG needs to know about.*/
+#define __extension__ /* Undefine GCC keyword to make Swig happy when
+                         processing glibc's stdint.h. */
+/* The ISO C99 standard specifies that in C++ implementations limit macros such
+   as INT32_MAX should only be defined if __STDC_LIMIT_MACROS is. */
+#define __STDC_LIMIT_MACROS
+%include "python-typemaps.txt"
+
+/* Feature specific python interface files*/
+%include "../intel-pt/interface/PTDecoder.i"
Index: tools/intel-features/scripts/CMakeLists.txt
===================================================================
--- /dev/null
+++ tools/intel-features/scripts/CMakeLists.txt
@@ -0,0 +1,37 @@
+file(GLOB_RECURSE SWIG_SOURCES *.swig)
+
+set(FLAGS
+  -c++
+  -shadow
+  -python
+  -D__STDC_LIMIT_MACROS
+  -D__STDC_CONSTANT_MACROS
+  )
+
+set(INCLUDES
+  -I${LLDB_SOURCE_DIR}/include
+  -I${LLDB_SOURCE_DIR}/tools/intel-features/intel-pt
+  )
+
+set(OUTPUT_PYTHON_WRAPPER
+  ${CMAKE_CURRENT_BINARY_DIR}/IntelFeaturesPythonWrap.cpp
+  )
+
+set(OUTPUT_PYTHON_SCRIPT_DIR
+  ${CMAKE_CURRENT_BINARY_DIR}
+  )
+
+find_package(SWIG REQUIRED)
+add_custom_command(
+  OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/IntelFeaturesPythonWrap.cpp
+  OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/lldbIntelFeatures.py
+  DEPENDS ${SWIG_SOURCES}
+  COMMAND ${SWIG_EXECUTABLE} ${FLAGS} ${INCLUDES} -o ${OUTPUT_PYTHON_WRAPPER} -outdir ${OUTPUT_PYTHON_SCRIPT_DIR} ${SWIG_SOURCES}
+  COMMENT "Generating python wrapper for features library")
+
+set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/IntelFeaturesPythonWrap.cpp PROPERTIES GENERATED 1)
+set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/lldbIntelFeatures.py PROPERTIES GENERATED 1)
+
+add_custom_target(intel-features-swig_wrapper ALL
+  DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/IntelFeaturesPythonWrap.cpp
+  )
Index: tools/intel-features/intel-pt/interface/PTDecoder.i
===================================================================
--- /dev/null
+++ tools/intel-features/intel-pt/interface/PTDecoder.i
@@ -0,0 +1,13 @@
+%include "stdint.i"
+%include "std_string.i"
+%include "std_vector.i"
+
+%include "lldb/lldb-defines.h"
+%include "lldb/lldb-enumerations.h"
+%include "lldb/lldb-forward.h"
+%include "lldb/lldb-types.h"
+
+%include "lldb/API/SBDefines.h"
+
+%include "../PTDecoder.h"
+%template(PTInstructions) std::vector<ptdecoder::PTInstruction>;
Index: tools/intel-features/intel-pt/README_TOOL.txt
===================================================================
--- /dev/null
+++ tools/intel-features/intel-pt/README_TOOL.txt
@@ -0,0 +1,305 @@
+*******************************************************************************
+*                            README                                           *
+*                                                                             *
+* This file provides all the information regarding Intel(R) Processor Trace   *
+* Tool. It consists explanation about how Tool internally works, its hardware *
+* and software dependencies, build procedure and usage of the API.            *
+*******************************************************************************
+
+
+
+============
+Introduction
+============
+The Intel(R) Processor Trace Tool is developed on top of LLDB and provides its
+its users execution trace of the debugged applications. Tool makes use of
+Intel(R) Processor Trace hardware feature implementation inside LLDB for this
+purpose. This hardware feature generates a set of trace packets that
+encapsulates program flow information. These trace packets along with the binary
+of the application can be decoded with the help of a software decoder to
+construct the execution trace of the application.
+
+More information about Intel(R) Processor Trace feature can be obtained from
+website: https://software.intel.com/en-us/blogs/2013/09/18/processor-tracing
+
+
+
+
+=========
+Details
+=========
+The functionality of the Tool consists three parts:
+
+1. Raw Trace Collection from LLDB
+      With the help of API of this Tool (given below), Intel(R) Processor Trace
+      can be started on the application being debugged with LLDB. The generated
+      trace of the application is gathered inside LLDB and is collected by the
+      Tool from LLDB through LLDB's public API.
+
+2. Raw Trace Decoding
+      For decoding the raw trace data, the Tool makes use of "libipt", an
+      Intel(R) Processor Trace Decoder Library. The library needs binary of
+      the application and information about the cpu on which the application is
+      running in order to decode the raw trace. The Tool gathers this
+      information from LLDB public API and provide it to "libipt". More
+      information about "libipt" can be found at:
+      https://software.intel.com/en-us/blogs/2013/09/18/processor-tracing and
+      https://github.com/01org/processor-trace
+
+3. Decoded Trace Post-processing
+      The decoded trace is post-processed to reconstruct the execution flow of
+      the application. The execution flow contains the list of assembly
+      instructions (called instruction log hereafter).
+
+
+
+
+=============
+Dependencies
+=============
+The Tool has following hardware and software dependencies:
+
+  - Hardware dependency: The Tool makes use of this hardware feature to capture
+    raw trace of an application from LLDB. This hardware feature may not be
+    present in all processors. The hardware feature is supported on Broadwell
+    and other succeeding CPUs such as Skylake etc. In order for Tool to provide
+    something meaningful, the target machine on which the application is running
+    should have this feature.
+
+  - Software dependency: The Tool has an indirect dependency on the Operating
+    System level software support for Intel(R) Processor Trace on the target
+    machine where the application is running and being debugged by LLDB. This
+    support is required to enable raw trace generation on the target machine.
+    Currently, the Tool works for applications running on Linux OS as till now
+    the Operating System level support for the feature is present only in Linux
+    (more specifically starting from the 4.1 kernel). In Linux, this feature is
+    implemented in perf_events subsystem and is usable through perf_event_open
+    system call. In the User space level, the Tool has a direct dependency on
+    "libipt" to decode the captured raw trace. This library might be
+    pre-installed on host systems. If not then the library can be built from
+    its sources (available at): https://github.com/01org/processor-trace
+
+
+
+
+============
+How to Build
+============
+The Tool has a cmake based build and can be built by specifying some extra flags
+while building LLDB with cmake. The following cmake flags need to be provided to
+build the Tool:
+
+  - LIBIPT_INCLUDE_PATH - The flag specifies the directory where the header
+    file of "libipt" resides. If the library is not pre-installed on the host
+    system and is built directly from "libipt" project sources then this file
+    may either come as a part of the sources itself or will be generated in
+    build folder while building library.
+
+  - LIBIPT_LIBRARY_PATH - The flag points to the location of "libipt" shared
+    library.
+
+The Tool currently works successfully with following versions of this library:
+  - v1.4, v1.5, v1.6
+
+
+
+============
+How to Use
+============
+The Tool's API are exposed as a C++ object oriented interface (file PTDecoder.h)
+in a shared library. The main class that implements the whole functionality is
+PTDecoder. This class makes use of 2 other classes, one to return instruction
+log (class PTInstruction) and the other to return trace specific information
+(class PTTraceOptions). The users can use these API to develop their own products. All
+API are also available as python functions through a script bridging interface,
+allowing them to be used directly from python either interactively or to build
+python apps.
+
+Currently, cli wrapper has been developed on top of the Tool to use it through
+LLDB's command line. Please refer to README_CLI.txt file for command line usage.
+
+
+A brief introduction about the classes and their API are given below.
+
+  class PTDecoder
+  ===============
+    This class makes use of Intel(R) Processor Trace hardware feature
+    (implemented inside LLDB) to gather trace data for an inferior (being
+    debugged with LLDB) to provide meaningful information out of it. Currently
+    the meaningful information comprises of the execution flow of the inferior
+    (in terms of assembly instructions executed). The class enables user to:
+
+    - start the trace with configuration options for a thread/process,
+    - stop the trace for a thread/process,
+    - get the execution flow (assembly instructions) for a thread and
+    - get trace specific information for a thread
+
+    Corresponding API are explained below:
+    a) void StartProcessorTrace(lldb::SBProcess &sbprocess,
+                                lldb::SBTraceOptions &sbtraceoptions,
+                                lldb::SBError &sberror)
+       ------------------------------------------------------------------------
+           This API allows the user to start trace on a particular thread or on
+           the whole process with Intel(R) Processor Trace specific
+           configuration options.
+
+           @param[in] sbprocess      : A valid process on which this operation
+               will be performed. An error is returned in case of an invalid
+               process.
+
+           @param[out] sberror       : An error with the failure reason if API
+               fails. Else success.
+
+           @param[in] sbtraceoptions : Contains thread id information and
+               configuration options:
+               For tracing a single thread, provide a valid thread id. If
+               sbprocess doesn't contain this thread id, error will be returned.
+               For tracing complete process, set to lldb::LLDB_INVALID_THREAD_ID
+               Configuration options comprises of:
+                - trace buffer size, meta data buffer size, TraceType and
+                - All other possible Intel(R) Processor Trace specific
+                  configuration options (hereafter collectively referred as
+                  CUSTOM_OPTIONS)
+
+                Trace buffer, meant to store the trace data read from target
+                machine, inside LLDB is configured as a cyclic buffer. Hence,
+                depending upon the trace buffer size provided here, buffer
+                overwrites may happen while LLDB writes trace data into it.
+                CUSTOM_OPTIONS are formatted as json text i.e. {"Name":Value,
+                "Name":Value,...} inside sbtraceoptions, where "Value" should be
+                a 64-bit unsigned integer in hex format. For information
+                regarding what all configuration options are currently supported
+                by LLDB and detailed information about CUSTOM_OPTIONS usage,
+                please refer to SBProcess::StartTrace() API description. An
+                overview of some of the various CUSTOM_OPTIONS are briefly given
+                below. Please refer to "Intel(R) 64 and IA-32 Architectures
+                Software Developer's Manual" for more details about them.
+                  - CYCEn       Enable/Disable Cycle Count Packet (CYC) Packet
+                  - OS          Packet generation enabled/disabled if
+                                Current Privilege Level (CPL)=0
+                  - User        Packet generation enabled/disabled if CPL>0
+                  - CR3Filter   Enable/Disable CR3 Filtering
+                  - MTCEn       Enable/disable MTC packets
+                  - TSCEn       Enable/disable TSC packets
+                  - DisRETC     Enable/disable RET Compression
+                  - BranchEn    Enable/disable COFI-based packets
+                  - MTCFreq     Defines MTC Packet Frequency
+                  - CycThresh   CYC Packet threshold
+                  - PSBFreq     Frequency of PSB Packets
+
+                TraceType should be set to
+                lldb::TraceType::eTraceTypeProcessorTrace, else error is
+                returned. To find out any other requirement to start tracing
+                successfully, refer to SBProcess::StartTrace() API description.
+                LLDB's current implementation of Intel(R) Processor Trace
+                feature may round off invalid values for configuration options.
+                Therefore, the configuration options with which the trace was
+                actually started, might be different to the ones with which
+                trace was asked to be started by user. The actual used
+                configuration options can be obtained from
+                GetProcessorTraceInfo() API.
+
+
+
+    b) void StopProcessorTrace(lldb::SBProcess &sbprocess,
+                               lldb::SBError &sberror,
+                               lldb::tid_t tid = LLDB_INVALID_THREAD_ID)
+       ------------------------------------------------------------------------
+           This API allows the user to Stop trace on a particular thread or on
+           the whole process.
+
+           @param[in] sbprocess : A valid process on which this operation will
+               be performed. An error is returned in case of an invalid process.
+
+           @param[in] tid       : To stop tracing a single thread, provide a
+               valid thread id. If sbprocess doesn't contain the thread tid,
+               error will be returned. To stop tracing complete process, use
+               lldb::LLDB_INVALID_THREAD_ID
+
+           @param[out] sberror  : An error with the failure reason if API fails.
+               Else success
+
+
+
+    c) void GetInstructionLogAtOffset(lldb::SBProcess &sbprocess, lldb::tid_t tid,
+                                      uint32_t offset, uint32_t count,
+                                      std::vector<PTInstruction> &result_list,
+                                      lldb::SBError &sberror)
+       ------------------------------------------------------------------------
+           This API provides instruction log that contains the execution flow
+           for a thread of a process in terms of assembly instruction executed.
+           The API works on only 1 thread at a time. To gather this information
+           for whole process, this API needs to be called for each thread.
+
+           @param[in] sbprocess    : A valid process on which this operation
+               will be performed. An error is returned in case of an invalid
+               process.
+
+           @param[in] tid          : A valid thread id of the thread for which
+               instruction log is desired. If sbprocess doesn't contain the
+               thread tid, error will be returned.
+
+           @param[in] count        : Number of instructions requested by the
+               user to be returned from the complete instruction log. Complete
+               instruction log refers to all the assembly instructions obtained
+               after decoding the complete raw trace data obtained from LLDB.
+               The length of the complete instruction log is dependent on the
+               trace buffer size with which processor tracing was started for
+               this thread.
+               The number of instructions actually returned are dependent on
+               'count' and 'offset' parameters of this API.
+
+           @param[in] offset       : The offset in the complete instruction log
+               from where 'count' number of instructions are requested by the
+               user. offset is counted from the end of of this complete
+               instruction log (which means the last executed instruction
+               is at offset 0 (zero)).
+
+           @param[out] result_list : Depending upon 'count' and 'offset' values,
+               instructions will be appended to the end of this list.
+
+           @param[out] sberror     : An error with the failure reason if API
+               fails. Else success
+
+
+
+    d) void GetProcessorTraceInfo(lldb::SBProcess &sbprocess, lldb::tid_t tid,
+                                  PTTraceOptions &options, lldb::SBError &sberror)
+       ------------------------------------------------------------------------
+           This API provides Intel(R) Processor Trace specific information for
+           a thread of a process. The API works on only 1 thread at a time. To
+           gather this information for whole process, this API needs to be
+           called for each thread. The information contains the actual
+           configuration options with which the trace was started for this
+           thread.
+
+           @param[in] sbprocess  : The valid process on which this operation
+               will be performed. An error is returned in case of an invalid
+               process.
+
+           @param[in] tid        : A valid thread id of the thread for which the
+               trace specific information is required. If sbprocess doesn't
+               contain the thread tid, an error will be returned.
+
+           @param[out] options   : Contains actual configuration options (they
+               may be different to the ones with which tracing was asked to be
+               started for this thread during StartProcessorTrace() API call).
+
+           @param[out] sberror   : An error with the failure reason if API
+               fails. Else success
+
+
+  class PTInstruction
+  =================
+      This class represents an assembly instruction containing raw instruction
+      bytes, instruction address along with execution flow context and
+      Intel(R) Processor Trace context. For more details, please refer to
+      PTDecoder.h file.
+
+
+  class PTTraceOptions
+  ============
+      This class provides Intel(R) Processor Trace specific configuration
+      options like trace type, trace buffer size, meta data buffer size along
+      with other trace specific options. For more details, please refer to
+      PTDecoder.h file.
Index: tools/intel-features/intel-pt/README_CLI.txt
===================================================================
--- /dev/null
+++ tools/intel-features/intel-pt/README_CLI.txt
@@ -0,0 +1,123 @@
+****************************************************************************
+*                            README                                        *
+*                                                                          *
+* This file provides all the information regarding 4 new CLI commands that *
+* enable using Intel(R) Processor Trace Tool from LLDB's CLI.              *
+****************************************************************************
+
+
+============
+Introduction
+============
+A C++ based cli wrapper has been developed to use Intel(R) Processor Trace Tool
+through LLDB's command line. This also provides an idea to all developers on how
+to integrate the Tool into various IDEs providing LLDB as a debugger.
+
+
+
+============
+How to Build
+============
+The wrapper cli-wrapper-pt.cpp needs to be compiled and linked with the shared
+library of the Intel(R) Processor Trace Tool in order to be used through LLDB's
+CLI. The procedure to build shared library of the Intel(R) Processor Trace Tool
+is given in README_TOOL.txt file.
+
+
+
+============
+How to Use
+============
+All these commands are available via shared library (lldbIntelFeatures)
+obtained after building intel-features folder from top. Please refer to
+cli-wrapper.cpp and README files of "intel-features" folder for this purpose.
+
+
+
+============
+Description
+============
+4 CLI commands have been designed keeping the LLDB's existing CLI command syntax
+in mind.
+
+   1) processor-trace start [-b <buffer-size>] [<thread-index>]
+
+      Start Intel(R) Processor Trace on a specific thread or on the whole process
+
+      Syntax: processor-trace start  <cmd-options>
+
+      cmd-options Usage:
+        processor-trace start [-b <buffer-size>] [<thread-index>]
+
+          -b <buffer-size>
+             size of the trace buffer to store the trace data. If not specified
+             then a default value (=4KB) will be taken
+
+          <thread-index>
+             thread index of the thread. If no threads are specified, currently
+             selected thread is taken. Use the thread-index 'all' to start
+             tracing the whole process
+
+
+
+   2) processor-trace stop [<thread-index>]
+
+      Stop Intel(R) Processor Trace on a specific thread or on the whole process
+
+      Syntax: processor-trace stop  <cmd-options>
+
+      cmd-options Usage:
+      processor-trace stop [<thread-index>]
+
+          <thread-index>
+             thread index of the thread. If no threads are specified, currently
+             selected thread is taken. Use the thread-index 'all' to stop
+             tracing the whole process
+
+
+
+   3) processor-trace show-trace-options [<thread-index>]
+
+      Display all the information regarding Intel(R) Processor Trace for a specific
+      thread or for the whole process. The information contains trace buffer
+      size and configuration options of Intel(R) Processor Trace.
+
+      Syntax: processor-trace show-trace-options <cmd-options>
+
+      cmd-options Usage:
+        processor-trace show-trace-options [<thread-index>]
+
+          <thread-index>
+             thread index of the thread. If no threads are specified, currently
+             selected thread is taken. Use the thread-index 'all' to display
+             information for all threads of the process
+
+
+
+   4) processor-trace show-instr-log [-o <offset>] [-c <count>] [<thread-index>]
+
+      Display a log of assembly instructions executed for a specific thread or
+      for the whole process. The length of the log to be displayed and the
+      offset in the whole instruction log from where the log needs to be
+      displayed can also be provided. The offset is counted from the end of this
+      whole instruction log which means the last executed instruction is at
+      offset 0 (zero).
+
+      Syntax: processor-trace show-instr-log  <cmd-options>
+
+      cmd-options Usage:
+        processor-trace show-instr-log [-o <offset>] [-c <count>] [<thread-index>]
+
+          -c <count>
+             number of instructions to be displayed. If not specified then a
+             default value (=10) will be taken
+
+          -o <offset>
+             offset in the whole instruction log from where the log will be
+             displayed. If not specified then default value is calculated as
+             offset = count -1
+
+          <thread-index>
+             thread index of the thread. If no threads are specified, currently
+             selected thread is taken. Use the thread-index 'all' to show
+             instruction log for all the threads of the process
Index: tools/intel-features/intel-pt/PTDecoder.h
===================================================================
--- /dev/null
+++ tools/intel-features/intel-pt/PTDecoder.h
@@ -0,0 +1,264 @@
+//===-- PTDecoder.h ---------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef PTDecoder_h_
+#define PTDecoder_h_
+
+// C/C++ Includes
+#include <vector>
+
+// Project includes, Other libraries and framework includes
+#include "lldb/API/SBDebugger.h"
+#include "lldb/API/SBError.h"
+#include "lldb/API/SBProcess.h"
+#include "lldb/API/SBStructuredData.h"
+#include "lldb/API/SBTraceOptions.h"
+#include "lldb/lldb-enumerations.h"
+#include "lldb/lldb-types.h"
+
+namespace ptdecoder_private {
+class Instruction;
+class TraceOptions;
+class Decoder;
+} // namespace ptdecoder_private
+
+namespace ptdecoder {
+//----------------------------------------------------------------------
+/// @class PTInstruction
+/// @brief Represents an assembly instruction containing raw
+///     instruction bytes, instruction address along with information
+///     regarding execution flow context and Intel(R) Processor Trace
+///     context.
+//----------------------------------------------------------------------
+class PTInstruction {
+public:
+  PTInstruction();
+
+  PTInstruction(const PTInstruction &insn);
+
+  PTInstruction(const std::shared_ptr<ptdecoder_private::Instruction> &ptr);
+
+  ~PTInstruction();
+
+  // Get instruction address in inferior's memory image
+  uint64_t GetInsnAddress() const;
+
+  // Get raw bytes of the instruction
+  const uint8_t *GetRawBytes() const;
+
+  // Get size of raw bytes of the instruction
+  uint8_t GetRawBytesSize() const;
+
+  // Get error string if it represents an invalid instruction. For a valid
+  // instruction, an empty string is returned
+  std::string GetError() const;
+
+  // Instruction was executed speculatively or not
+  bool GetSpeculative() const;
+
+private:
+  std::shared_ptr<ptdecoder_private::Instruction> m_opaque_sp;
+};
+
+//----------------------------------------------------------------------
+/// @class PTTraceOptions
+/// @brief Provides configuration options like trace type, trace buffer size,
+///     meta data buffer size along with other Intel(R) Processor Trace
+///     specific options.
+//----------------------------------------------------------------------
+class PTTraceOptions {
+public:
+  PTTraceOptions();
+
+  PTTraceOptions(const PTTraceOptions &options);
+
+  ~PTTraceOptions();
+
+  lldb::TraceType GetType() const;
+
+  uint64_t GetTraceBufferSize() const;
+
+  uint64_t GetMetaDataBufferSize() const;
+
+  //------------------------------------------------------------------
+  /// Get Intel(R) Processor Trace specific configuration options (apart from
+  /// trace buffer size, meta data buffer size and TraceType) formatted as json
+  /// text i.e. {"Name":Value,"Name":Value} pairs, where "Value" is a 64-bit
+  /// unsigned integer in hex format. For "Name", please refer to
+  /// SBProcess::StartTrace API description for setting SBTraceOptions.
+  ///
+  /// @return
+  ///     A string formatted as json text {"Name":Value,"Name":Value}
+  //------------------------------------------------------------------
+  lldb::SBStructuredData GetTraceParams(lldb::SBError &error);
+
+private:
+  friend class PTDecoder;
+
+  void SetSP(const std::shared_ptr<ptdecoder_private::TraceOptions> &ptr);
+
+  std::shared_ptr<ptdecoder_private::TraceOptions> m_opaque_sp;
+};
+
+//----------------------------------------------------------------------
+/// @class PTDecoder
+/// @brief This class makes use of Intel(R) Processor Trace hardware feature
+///     (implememted inside LLDB) to gather trace data for an inferior (being
+///     debugged with LLDB) to provide meaningful information out of it.
+///
+///     Currently the meaningful information comprises of the execution flow
+///     of the inferior (in terms of assembly instructions executed). The class
+///     enables user to:
+///     - start the trace with configuration options for a thread/process,
+///     - stop the trace for a thread/process,
+///     - get the execution flow (assembly instructions) for a thread and
+///     - get trace specific information for a thread
+//----------------------------------------------------------------------
+class PTDecoder {
+public:
+  PTDecoder(lldb::SBDebugger &sbdebugger);
+
+  PTDecoder(const PTDecoder &ptdecoder);
+
+  ~PTDecoder();
+
+  //------------------------------------------------------------------
+  /// Start Intel(R) Processor Trace on a thread or complete process with
+  /// Intel(R) Processor Trace specific configuration options
+  ///
+  /// @param[in] sbprocess
+  ///     A valid process on which this operation will be performed. An error is
+  ///     returned in case of an invalid process.
+  ///
+  /// @param[in] sbtraceoptions
+  ///     Contains thread id information and configuration options:
+  ///
+  ///     For tracing a single thread, provide a valid thread id. If sbprocess
+  ///     doesn't contain this thread id, error will be returned. For tracing
+  ///     complete process, set it to lldb::LLDB_INVALID_THREAD_ID
+  ///     Configuration options comprises of:
+  ///     a) trace buffer size, meta data buffer size, TraceType and
+  ///     b) All other possible Intel(R) Processor Trace specific configuration
+  ///     options (hereafter collectively referred as CUSTOM_OPTIONS), formatted
+  ///     as json text i.e. {"Name":Value,"Name":Value,..} inside
+  ///     sbtraceoptions, where "Value" should be a 64-bit unsigned integer in
+  ///     hex format. For information regarding what all configuration options
+  ///     are currently supported by LLDB and detailed information about
+  ///     CUSTOM_OPTIONS usage, please refer to SBProcess::StartTrace() API
+  ///     description. To know about all possible configuration options of
+  ///     Intel(R) Processor Trace, please refer to Intel(R) 64 and IA-32
+  ///     Architectures Software Developer's Manual.
+  ///
+  ///     TraceType should be set to lldb::TraceType::eTraceTypeProcessorTrace,
+  ///     else error is returned. To find out any other requirement to start
+  ///     tracing successfully, please refer to SBProcess::StartTrace() API
+  ///     description. LLDB's current implementation of Intel(R) Processor Trace
+  ///     feature may round off invalid values for configuration options.
+  ///     Therefore, the configuration options with which the trace was actually
+  ///     started, might be different to the ones with which trace was asked to
+  ///     be started by user. The actual used configuration options can be
+  ///     obtained from GetProcessorTraceInfo() API.
+  ///
+  /// @param[out] sberror
+  ///     An error with the failure reason if API fails. Else success.
+  //------------------------------------------------------------------
+  void StartProcessorTrace(lldb::SBProcess &sbprocess,
+                           lldb::SBTraceOptions &sbtraceoptions,
+                           lldb::SBError &sberror);
+
+  //------------------------------------------------------------------
+  /// Stop Intel(R) Processor Trace on a thread or complete process.
+  ///
+  /// @param[in] sbprocess
+  ///     A valid process on which this operation will be performed. An error is
+  ///     returned in case of an invalid process.
+  ///
+  /// @param[in] tid
+  ///     Case 1: To stop tracing a single thread, provide a valid thread id. If
+  ///     sbprocess doesn't contain the thread tid, error will be returned.
+  ///     Case 2: To stop tracing complete process, use
+  ///     lldb::LLDB_INVALID_THREAD_ID.
+  ///
+  /// @param[out] sberror
+  ///     An error with the failure reason if API fails. Else success.
+  //------------------------------------------------------------------
+  void StopProcessorTrace(lldb::SBProcess &sbprocess, lldb::SBError &sberror,
+                          lldb::tid_t tid = LLDB_INVALID_THREAD_ID);
+
+  //------------------------------------------------------------------
+  /// Get instruction log containing the execution flow for a thread of a
+  /// process in terms of assembly instructions executed.
+  ///
+  /// @param[in] sbprocess
+  ///     A valid process on which this operation will be performed. An error is
+  ///     returned in case of an invalid process.
+  ///
+  /// @param[in] tid
+  ///     A valid thread id of the thread for which instruction log is desired.
+  ///     If sbprocess doesn't contain the thread tid, error will be returned.
+  ///
+  /// @param[in] count
+  ///     The number of instructions requested by the user to be returned from
+  ///     the complete instruction log. Complete instruction log refers to all
+  ///     the assembly instructions obtained after decoding the complete raw
+  ///     trace data obtained from LLDB. The length of the complete instruction
+  ///     log is dependent on the trace buffer size with which processor tracing
+  ///     was started for this thread.
+  ///     The number of instructions actually returned are dependent on 'count'
+  ///     and 'offset' parameters of this API.
+  ///
+  /// @param[in] offset
+  ///     The offset in the complete instruction log from where 'count' number
+  ///     of instructions are requested by the user. offset is counted from the
+  ///     end of of this complete instruction log (which means the last executed
+  ///     instruction is at offset 0 (zero)).
+  ///
+  /// @param[out] result_list
+  ///     Depending upon 'count' and 'offset' values, instructions will be
+  ///     appended to the end of this list.
+  ///
+  /// @param[out] sberror
+  ///     An error with the failure reason if API fails. Else success.
+  //------------------------------------------------------------------
+  void GetInstructionLogAtOffset(lldb::SBProcess &sbprocess, lldb::tid_t tid,
+                                 uint32_t offset, uint32_t count,
+                                 std::vector<PTInstruction> &result_list,
+                                 lldb::SBError &sberror);
+
+  //------------------------------------------------------------------
+  /// Get Intel(R) Processor Trace specific information for a thread of a
+  /// process. The information contains the actual configuration options with
+  /// which the trace was started for this thread.
+  ///
+  /// @param[in] sbprocess
+  ///     A valid process on which this operation will be performed. An error is
+  ///     returned in case of an invalid process.
+  ///
+  /// @param[in] tid
+  ///     A valid thread id of the thread for which the trace specific
+  ///     information is required. If sbprocess doesn't contain the thread tid,
+  ///     an error will be returned.
+  ///
+  /// @param[out] options
+  ///     Contains actual configuration options (they may be different to the
+  ///     ones with which tracing was asked to be started for this thread during
+  ///     StartProcessorTrace() API call).
+  ///
+  /// @param[out] sberror
+  ///     An error with the failure reason if API fails. Else success.
+  //------------------------------------------------------------------
+  void GetProcessorTraceInfo(lldb::SBProcess &sbprocess, lldb::tid_t tid,
+                             PTTraceOptions &options, lldb::SBError &sberror);
+
+private:
+  std::shared_ptr<ptdecoder_private::Decoder> m_opaque_sp;
+};
+
+} // namespace ptdecoder
+#endif // PTDecoder_h_
Index: tools/intel-features/intel-pt/PTDecoder.cpp
===================================================================
--- /dev/null
+++ tools/intel-features/intel-pt/PTDecoder.cpp
@@ -0,0 +1,154 @@
+//===-- PTDecoder.cpp -------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <stdexcept>
+// Project includes
+#include "Decoder.h"
+#include "PTDecoder.h"
+
+using namespace ptdecoder;
+using namespace ptdecoder_private;
+
+// PTInstruction class member functions definitions
+PTInstruction::PTInstruction() : m_opaque_sp() {}
+
+PTInstruction::PTInstruction(const PTInstruction &insn)
+    : m_opaque_sp(insn.m_opaque_sp) {}
+
+PTInstruction::PTInstruction(
+    const std::shared_ptr<ptdecoder_private::Instruction> &ptr)
+    : m_opaque_sp(ptr) {}
+
+PTInstruction::~PTInstruction() {}
+
+uint64_t PTInstruction::GetInsnAddress() const {
+  return (m_opaque_sp ? m_opaque_sp->GetInsnAddress() : 0);
+}
+
+const uint8_t *PTInstruction::GetRawBytes() const {
+  return (m_opaque_sp ? m_opaque_sp->GetRawBytes() : nullptr);
+}
+
+uint8_t PTInstruction::GetRawBytesSize() const {
+  return (m_opaque_sp ? m_opaque_sp->GetRawBytesSize() : 0);
+}
+
+std::string PTInstruction::GetError() const {
+  return (m_opaque_sp ? m_opaque_sp->GetError() : "null pointer");
+}
+
+bool PTInstruction::GetSpeculative() const {
+  return (m_opaque_sp ? m_opaque_sp->GetSpeculative() : 0);
+}
+
+// PTTraceOptions class member functions definitions
+PTTraceOptions::PTTraceOptions() : m_opaque_sp() {}
+
+PTTraceOptions::PTTraceOptions(const PTTraceOptions &options)
+    : m_opaque_sp(options.m_opaque_sp) {}
+
+PTTraceOptions::~PTTraceOptions() {}
+
+lldb::TraceType PTTraceOptions::GetType() const {
+  return (m_opaque_sp ? m_opaque_sp->getType()
+                      : lldb::TraceType::eTraceTypeNone);
+}
+
+uint64_t PTTraceOptions::GetTraceBufferSize() const {
+  return (m_opaque_sp ? m_opaque_sp->getTraceBufferSize() : 0);
+}
+
+uint64_t PTTraceOptions::GetMetaDataBufferSize() const {
+  return (m_opaque_sp ? m_opaque_sp->getMetaDataBufferSize() : 0);
+}
+
+lldb::SBStructuredData PTTraceOptions::GetTraceParams(lldb::SBError &error) {
+  if (!m_opaque_sp)
+    error.SetErrorString("null pointer");
+  return (m_opaque_sp ? m_opaque_sp->getTraceParams(error)
+                      : lldb::SBStructuredData());
+}
+
+void PTTraceOptions::SetSP(
+    const std::shared_ptr<ptdecoder_private::TraceOptions> &ptr) {
+  m_opaque_sp = ptr;
+}
+
+// PTDecoder class member functions definitions
+PTDecoder::PTDecoder(lldb::SBDebugger &sbdebugger)
+    : m_opaque_sp(new ptdecoder_private::Decoder(sbdebugger)) {}
+
+PTDecoder::PTDecoder(const PTDecoder &ptdecoder)
+    : m_opaque_sp(ptdecoder.m_opaque_sp) {}
+
+PTDecoder::~PTDecoder() {}
+
+void PTDecoder::StartProcessorTrace(lldb::SBProcess &sbprocess,
+                                    lldb::SBTraceOptions &sbtraceoptions,
+                                    lldb::SBError &sberror) {
+  if (m_opaque_sp == nullptr) {
+    sberror.SetErrorStringWithFormat("invalid PTDecoder instance");
+    return;
+  }
+
+  m_opaque_sp->StartProcessorTrace(sbprocess, sbtraceoptions, sberror);
+}
+
+void PTDecoder::StopProcessorTrace(lldb::SBProcess &sbprocess,
+                                   lldb::SBError &sberror, lldb::tid_t tid) {
+  if (m_opaque_sp == nullptr) {
+    sberror.SetErrorStringWithFormat("invalid PTDecoder instance");
+    return;
+  }
+
+  m_opaque_sp->StopProcessorTrace(sbprocess, sberror, tid);
+}
+
+void PTDecoder::GetInstructionLogAtOffset(
+    lldb::SBProcess &sbprocess, lldb::tid_t tid, uint32_t offset,
+    uint32_t count, std::vector<PTInstruction> &result_list,
+    lldb::SBError &sberror) {
+  if (m_opaque_sp == nullptr) {
+    sberror.SetErrorStringWithFormat("invalid PTDecoder instance");
+    return;
+  }
+
+  std::vector<std::shared_ptr<ptdecoder_private::Instruction>> vec_insn_ptr;
+  m_opaque_sp->GetInstructionLogAtOffset(sbprocess, tid, offset, count,
+                                         vec_insn_ptr, sberror);
+  if (!sberror.Success())
+    return;
+
+  for (auto &i : vec_insn_ptr) {
+    try {
+      result_list.emplace_back(
+          std::shared_ptr<ptdecoder_private::Instruction>(i));
+    } catch (const std::bad_alloc &le) {
+      return;
+    }
+  }
+}
+
+void PTDecoder::GetProcessorTraceInfo(lldb::SBProcess &sbprocess,
+                                      lldb::tid_t tid, PTTraceOptions &options,
+                                      lldb::SBError &sberror) {
+  if (m_opaque_sp == nullptr) {
+    sberror.SetErrorStringWithFormat("invalid PTDecoder instance");
+    return;
+  }
+
+  std::shared_ptr<ptdecoder_private::TraceOptions> trace_options_ptr(
+      new TraceOptions());
+  m_opaque_sp->GetProcessorTraceInfo(sbprocess, tid, *trace_options_ptr,
+                                     sberror);
+  if (!sberror.Success())
+    return;
+
+  options.SetSP(trace_options_ptr);
+}
Index: tools/intel-features/intel-pt/Decoder.h
===================================================================
--- /dev/null
+++ tools/intel-features/intel-pt/Decoder.h
@@ -0,0 +1,292 @@
+//===-- Decoder.h -----------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef Decoder_h_
+#define Decoder_h_
+
+// C/C++ Includes
+#include <map>
+#include <mutex>
+#include <string>
+#include <vector>
+
+// Project includes, Other libraries and framework includes
+#include "lldb/API/SBDebugger.h"
+#include "lldb/API/SBError.h"
+#include "lldb/API/SBProcess.h"
+#include "lldb/API/SBStream.h"
+#include "lldb/API/SBStructuredData.h"
+#include "lldb/API/SBTarget.h"
+#include "lldb/API/SBTrace.h"
+#include "lldb/API/SBTraceOptions.h"
+#include "lldb/lldb-enumerations.h"
+#include "lldb/lldb-types.h"
+
+#include "intel-pt.h"
+
+namespace ptdecoder_private {
+//----------------------------------------------------------------------
+/// @class Instruction
+/// @brief Represents an assembly instruction containing raw
+///     instruction bytes, instruction address along with information
+///     regarding execution flow context and Intel(R) Processor Trace
+///     context.
+//----------------------------------------------------------------------
+class Instruction {
+public:
+  Instruction() : ip(0), data(), error(), iclass(ptic_error), speculative(0) {}
+
+  Instruction(const Instruction &insn) = default;
+
+  Instruction(const struct pt_insn &insn)
+      : ip(insn.ip), data(), error(insn.size == 0 ? "invalid instruction" : ""),
+        iclass(insn.iclass), speculative(insn.speculative) {
+    if (insn.size != 0)
+      data.assign(insn.raw, insn.raw + insn.size);
+  }
+
+  Instruction(const char *err)
+      : ip(0), data(), error(err ? err : "unknown error"), iclass(ptic_error),
+        speculative(0) {}
+
+  ~Instruction() {}
+
+  uint64_t GetInsnAddress() const { return ip; }
+
+  const uint8_t *GetRawBytes() const { return data.data(); }
+
+  uint8_t GetRawBytesSize() const { return data.size(); }
+
+  const std::string &GetError() const { return error; }
+
+  bool GetSpeculative() const { return speculative; }
+
+private:
+  uint64_t ip;               // instruction address in inferior's memory image
+  std::vector<uint8_t> data; // raw bytes
+  std::string error;         // Error string if instruction is invalid
+  enum pt_insn_class iclass; // classification of the instruction
+  // A collection of flags giving additional information about instruction
+  uint32_t speculative : 1; // Instruction was executed speculatively or not
+};
+
+//----------------------------------------------------------------------
+/// @class TraceOptions
+/// @brief Provides Intel(R) Processor Trace specific configuration options and
+///     other information obtained by decoding and post-processing the trace
+///     data. Currently, this information comprises of the total number of
+///     assembly instructions executed for an inferior.
+//----------------------------------------------------------------------
+class TraceOptions : public lldb::SBTraceOptions {
+public:
+  TraceOptions() : lldb::SBTraceOptions(), m_insn_log_size(0) {}
+
+  ~TraceOptions() {}
+
+  //------------------------------------------------------------------
+  /// Get total number of assembly instructions obtained after decoding the
+  /// complete Intel(R) Processor Trace data obtained from LLDB.
+  ///
+  /// @return
+  ///     Total number of instructions.
+  //------------------------------------------------------------------
+  uint32_t getInstructionLogSize() const { return m_insn_log_size; }
+
+  //------------------------------------------------------------------
+  /// Set total number of assembly instructions.
+  ///
+  /// @param[in] size
+  ///     Value to be set.
+  //------------------------------------------------------------------
+  void setInstructionLogSize(uint32_t size) { m_insn_log_size = size; }
+
+private:
+  uint32_t m_insn_log_size;
+};
+
+//----------------------------------------------------------------------
+/// @class Decoder
+/// @brief This class makes use of Intel(R) Processor Trace hardware feature
+///     (implememted inside LLDB) to gather trace data for an inferior (being
+///     debugged with LLDB) to provide meaningful information out of it.
+///
+///     Currently the meaningful information comprises of the execution flow
+///     of the inferior (in terms of assembly instructions executed). The class
+///     enables user to:
+///     - start the trace with configuration options for a thread/process,
+///     - stop the trace for a thread/process,
+///     - get the execution flow (assembly instructions) for a thread and
+///     - get trace specific information for a thread
+//----------------------------------------------------------------------
+class Decoder {
+public:
+  typedef std::vector<Instruction> Instructions;
+
+  Decoder(lldb::SBDebugger &sbdebugger)
+      : m_mapProcessUID_mapThreadID_TraceInfo_mutex(),
+        m_mapProcessUID_mapThreadID_TraceInfo(),
+        m_debugger_user_id(sbdebugger.GetID()) {}
+
+  ~Decoder() {}
+
+  void StartProcessorTrace(lldb::SBProcess &sbprocess,
+                           lldb::SBTraceOptions &sbtraceoptions,
+                           lldb::SBError &sberror);
+
+  void StopProcessorTrace(lldb::SBProcess &sbprocess, lldb::SBError &sberror,
+                          lldb::tid_t tid = LLDB_INVALID_THREAD_ID);
+
+  void GetInstructionLogAtOffset(
+      lldb::SBProcess &sbprocess, lldb::tid_t tid, uint32_t offset,
+      uint32_t count, std::vector<std::shared_ptr<Instruction>> &result_list,
+      lldb::SBError &sberror);
+
+  void GetProcessorTraceInfo(lldb::SBProcess &sbprocess, lldb::tid_t tid,
+                             TraceOptions &traceinfo, lldb::SBError &sberror);
+
+private:
+  class ThreadTraceInfo;
+  typedef std::vector<uint8_t> Buffer;
+
+  // internal class to manage inferior's read-execute section information
+  class ReadExecuteSectionInfo {
+  public:
+    uint64_t load_address;
+    uint64_t file_offset;
+    uint64_t size;
+    std::string image_path;
+
+    ReadExecuteSectionInfo(const uint64_t addr, const uint64_t offset,
+                           const uint64_t sz, const std::string &path)
+        : load_address(addr), file_offset(offset), size(sz), image_path(path) {}
+
+    ReadExecuteSectionInfo(const ReadExecuteSectionInfo &rxsection) = default;
+  };
+
+  typedef struct pt_cpu CPUInfo;
+  typedef std::vector<ReadExecuteSectionInfo> ReadExecuteSectionInfos;
+
+  // Check whether the provided SBProcess belongs to the same SBDebugger with
+  // which Decoder class instance was constructed.
+  void CheckDebuggerID(lldb::SBProcess &sbprocess, lldb::SBError &sberror);
+
+  // Function to remove entries of finished processes/threads in the class
+  void RemoveDeadProcessesAndThreads(lldb::SBProcess &sbprocess);
+
+  // Parse cpu information from trace configuration received from LLDB
+  void ParseCPUInfo(CPUInfo &pt_cpu, lldb::SBStructuredData &s,
+                    lldb::SBError &sberror);
+
+  ///------------------------------------------------------------------------
+  /// Function performs following tasks for a given process and thread:
+  ///  - Checks if the given thread is registered in the class or not. If not
+  ///  then tries to register it if trace was ever started on the entire
+  ///  process. Else returns error.
+  ///  - fetches trace and other necessary information from LLDB (using
+  ///  ReadTraceDataAndImageInfo()) and decodes the trace (using
+  ///  DecodeProcessorTrace())
+  ///------------------------------------------------------------------------
+  void FetchAndDecode(lldb::SBProcess &sbprocess, lldb::tid_t tid,
+                      lldb::SBError &sberror,
+                      ThreadTraceInfo **threadTraceInfo);
+
+  // Helper function of FetchAndDecode() to get raw trace data and memory image
+  // info of inferior from LLDB
+  void ReadTraceDataAndImageInfo(lldb::SBProcess &sbprocess, lldb::tid_t tid,
+                                 lldb::SBError &sberror,
+                                 ThreadTraceInfo &threadTraceInfo);
+
+  // Helper function of FetchAndDecode() to initialize raw trace decoder and
+  // start trace decoding
+  void DecodeProcessorTrace(lldb::SBProcess &sbprocess, lldb::tid_t tid,
+                            lldb::SBError &sberror,
+                            ThreadTraceInfo &threadTraceInfo);
+
+  // Helper function of ReadTraceDataAndImageInfo() function for gathering
+  // inferior's memory image info along with all dynamic libraries linked with
+  // it
+  void GetTargetModulesInfo(lldb::SBTarget &sbtarget,
+                            ReadExecuteSectionInfos &readExecuteSectionInfos,
+                            lldb::SBError &sberror);
+
+  ///------------------------------------------------------------------------
+  /// Helper functions of DecodeProcessorTrace() function for:
+  ///  - initializing raw trace decoder (provided by Intel(R) Processor Trace
+  ///    Decoding library)
+  ///  - start trace decoding
+  ///------------------------------------------------------------------------
+  void InitializePTInstDecoder(
+      struct pt_insn_decoder **decoder, struct pt_config *config,
+      const CPUInfo &pt_cpu, Buffer &pt_buffer,
+      const ReadExecuteSectionInfos &readExecuteSectionInfos,
+      lldb::SBError &sberror) const;
+  void DecodeTrace(struct pt_insn_decoder *decoder,
+                   Instructions &instruction_list, lldb::SBError &sberror);
+
+  // Function to diagnose and indicate errors during raw trace decoding
+  void Diagnose(struct pt_insn_decoder *decoder, int errcode,
+                lldb::SBError &sberror, const struct pt_insn *insn = nullptr);
+
+  class ThreadTraceInfo {
+  public:
+    ThreadTraceInfo()
+        : m_pt_buffer(), m_readExecuteSectionInfos(), m_thread_stop_id(0),
+          m_trace(), m_pt_cpu(), m_instruction_log() {}
+
+    ThreadTraceInfo(const ThreadTraceInfo &trace_info) = default;
+
+    ~ThreadTraceInfo() {}
+
+    Buffer &GetPTBuffer() { return m_pt_buffer; }
+
+    void AllocatePTBuffer(uint64_t size) { m_pt_buffer.assign(size, 0); }
+
+    ReadExecuteSectionInfos &GetReadExecuteSectionInfos() {
+      return m_readExecuteSectionInfos;
+    }
+
+    CPUInfo &GetCPUInfo() { return m_pt_cpu; }
+
+    Instructions &GetInstructionLog() { return m_instruction_log; }
+
+    uint32_t GetStopID() const { return m_thread_stop_id; }
+
+    void SetStopID(uint32_t stop_id) { m_thread_stop_id = stop_id; }
+
+    lldb::SBTrace &GetUniqueTraceInstance() { return m_trace; }
+
+    void SetUniqueTraceInstance(lldb::SBTrace &trace) { m_trace = trace; }
+
+    friend class Decoder;
+
+  private:
+    Buffer m_pt_buffer; // raw trace buffer
+    ReadExecuteSectionInfos
+        m_readExecuteSectionInfos; // inferior's memory image info
+    uint32_t m_thread_stop_id;     // stop id for thread
+    lldb::SBTrace m_trace; // unique tracing instance of a thread/process
+    CPUInfo m_pt_cpu; // cpu info of the target on which inferior is running
+    Instructions m_instruction_log; // complete instruction log
+  };
+
+  typedef std::map<lldb::user_id_t, ThreadTraceInfo> MapThreadID_TraceInfo;
+  typedef std::map<uint32_t, MapThreadID_TraceInfo>
+      MapProcessUID_MapThreadID_TraceInfo;
+
+  std::mutex m_mapProcessUID_mapThreadID_TraceInfo_mutex;
+  MapProcessUID_MapThreadID_TraceInfo
+      m_mapProcessUID_mapThreadID_TraceInfo; // to store trace information for
+                                             // each process and its associated
+                                             // threads
+  lldb::user_id_t m_debugger_user_id; // SBDebugger instance which is associated
+                                      // to this Decoder instance
+};
+
+} // namespace ptdecoder_private
+#endif // Decoder_h_
Index: tools/intel-features/intel-pt/Decoder.cpp
===================================================================
--- /dev/null
+++ tools/intel-features/intel-pt/Decoder.cpp
@@ -0,0 +1,938 @@
+//===-- Decoder.cpp ---------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// Project includes
+#include "Decoder.h"
+
+// C/C++ Includes
+#include <cinttypes>
+#include <cstring>
+#include <stdexcept>
+
+// Other libraries and framework includes
+#include "lldb/API/SBModule.h"
+#include "lldb/API/SBProcess.h"
+#include "lldb/API/SBThread.h"
+
+using namespace ptdecoder_private;
+
+// This function removes entries of all the processes/threads which were once
+// registered in the class but are not alive anymore because they died or
+// finished executing.
+void Decoder::RemoveDeadProcessesAndThreads(lldb::SBProcess &sbprocess) {
+  lldb::SBTarget sbtarget = sbprocess.GetTarget();
+  lldb::SBDebugger sbdebugger = sbtarget.GetDebugger();
+  uint32_t num_targets = sbdebugger.GetNumTargets();
+
+  auto itr_process = m_mapProcessUID_mapThreadID_TraceInfo.begin();
+  while (itr_process != m_mapProcessUID_mapThreadID_TraceInfo.end()) {
+    bool process_found = false;
+    lldb::SBTarget target;
+    lldb::SBProcess process;
+    for (uint32_t i = 0; i < num_targets; i++) {
+      target = sbdebugger.GetTargetAtIndex(i);
+      process = target.GetProcess();
+      if (process.GetUniqueID() == itr_process->first) {
+        process_found = true;
+        break;
+      }
+    }
+
+    // Remove the process's entry if it was not found in SBDebugger
+    if (!process_found) {
+      itr_process = m_mapProcessUID_mapThreadID_TraceInfo.erase(itr_process);
+      continue;
+    }
+
+    // If the state of the process is exited or detached then remove process's
+    // entry. If not then remove entry for all those registered threads of this
+    // process that are not alive anymore.
+    lldb::StateType state = process.GetState();
+    if ((state == lldb::StateType::eStateDetached) ||
+        (state == lldb::StateType::eStateExited))
+      itr_process = m_mapProcessUID_mapThreadID_TraceInfo.erase(itr_process);
+    else {
+      auto itr_thread = itr_process->second.begin();
+      while (itr_thread != itr_process->second.end()) {
+        if (itr_thread->first == LLDB_INVALID_THREAD_ID) {
+          ++itr_thread;
+          continue;
+        }
+
+        lldb::SBThread thread = process.GetThreadByID(itr_thread->first);
+        if (!thread.IsValid())
+          itr_thread = itr_process->second.erase(itr_thread);
+        else
+          ++itr_thread;
+      }
+      ++itr_process;
+    }
+  }
+}
+
+void Decoder::StartProcessorTrace(lldb::SBProcess &sbprocess,
+                                  lldb::SBTraceOptions &sbtraceoptions,
+                                  lldb::SBError &sberror) {
+  sberror.Clear();
+  CheckDebuggerID(sbprocess, sberror);
+  if (!sberror.Success())
+    return;
+
+  std::lock_guard<std::mutex> guard(
+      m_mapProcessUID_mapThreadID_TraceInfo_mutex);
+  RemoveDeadProcessesAndThreads(sbprocess);
+
+  if (sbtraceoptions.getType() != lldb::TraceType::eTraceTypeProcessorTrace) {
+    sberror.SetErrorStringWithFormat("SBTraceOptions::TraceType not set to "
+                                     "eTraceTypeProcessorTrace; ProcessID = "
+                                     "%" PRIu64,
+                                     sbprocess.GetProcessID());
+    return;
+  }
+  lldb::SBStructuredData sbstructdata = sbtraceoptions.getTraceParams(sberror);
+  if (!sberror.Success())
+    return;
+
+  const char *trace_tech_key = "trace-tech";
+  std::string trace_tech_value("intel-pt");
+  lldb::SBStructuredData value = sbstructdata.GetValueForKey(trace_tech_key);
+  if (!value.IsValid()) {
+    sberror.SetErrorStringWithFormat(
+        "key \"%s\" not set in custom trace parameters", trace_tech_key);
+    return;
+  }
+
+  char string_value[9];
+  size_t bytes_written = value.GetStringValue(
+      string_value, sizeof(string_value) / sizeof(*string_value));
+  if (!bytes_written ||
+      (bytes_written > (sizeof(string_value) / sizeof(*string_value)))) {
+    sberror.SetErrorStringWithFormat(
+        "key \"%s\" not set in custom trace parameters", trace_tech_key);
+    return;
+  }
+
+  std::size_t pos =
+      trace_tech_value.find((const char *)string_value, 0, bytes_written);
+  if ((pos == std::string::npos)) {
+    sberror.SetErrorStringWithFormat(
+        "key \"%s\" not set to \"%s\" in custom trace parameters",
+        trace_tech_key, trace_tech_value.c_str());
+    return;
+  }
+
+  // Start Tracing
+  lldb::SBError error;
+  uint32_t unique_id = sbprocess.GetUniqueID();
+  lldb::tid_t tid = sbtraceoptions.getThreadID();
+  lldb::SBTrace trace = sbprocess.StartTrace(sbtraceoptions, error);
+  if (!error.Success()) {
+    if (tid == LLDB_INVALID_THREAD_ID)
+      sberror.SetErrorStringWithFormat("%s; ProcessID = %" PRIu64,
+                                       error.GetCString(),
+                                       sbprocess.GetProcessID());
+    else
+      sberror.SetErrorStringWithFormat(
+          "%s; thread_id = %" PRIu64 ", ProcessID = %" PRIu64,
+          error.GetCString(), tid, sbprocess.GetProcessID());
+    return;
+  }
+
+  MapThreadID_TraceInfo &mapThreadID_TraceInfo =
+      m_mapProcessUID_mapThreadID_TraceInfo[unique_id];
+  ThreadTraceInfo &trace_info = mapThreadID_TraceInfo[tid];
+  trace_info.SetUniqueTraceInstance(trace);
+  trace_info.SetStopID(sbprocess.GetStopID());
+}
+
+void Decoder::StopProcessorTrace(lldb::SBProcess &sbprocess,
+                                 lldb::SBError &sberror, lldb::tid_t tid) {
+  sberror.Clear();
+  CheckDebuggerID(sbprocess, sberror);
+  if (!sberror.Success()) {
+    return;
+  }
+
+  std::lock_guard<std::mutex> guard(
+      m_mapProcessUID_mapThreadID_TraceInfo_mutex);
+  RemoveDeadProcessesAndThreads(sbprocess);
+
+  uint32_t unique_id = sbprocess.GetUniqueID();
+  auto itr_process = m_mapProcessUID_mapThreadID_TraceInfo.find(unique_id);
+  if (itr_process == m_mapProcessUID_mapThreadID_TraceInfo.end()) {
+    sberror.SetErrorStringWithFormat(
+        "tracing not active for this process; ProcessID = %" PRIu64,
+        sbprocess.GetProcessID());
+    return;
+  }
+
+  lldb::SBError error;
+  if (tid == LLDB_INVALID_THREAD_ID) {
+    // This implies to stop tracing on the whole process
+    lldb::user_id_t id_to_be_ignored = LLDB_INVALID_UID;
+    auto itr_thread = itr_process->second.begin();
+    while (itr_thread != itr_process->second.end()) {
+      // In the case when user started trace on the entire process and then
+      // registered newly spawned threads of this process in the class later,
+      // these newly spawned threads will have same trace id. If we stopped
+      // trace on the entire process then tracing stops automatically for these
+      // newly spawned registered threads. Stopping trace on them again will
+      // return error and therefore we need to skip stopping trace on them
+      // again.
+      lldb::SBTrace &trace = itr_thread->second.GetUniqueTraceInstance();
+      lldb::user_id_t lldb_pt_user_id = trace.GetTraceUID();
+      if (lldb_pt_user_id != id_to_be_ignored) {
+        trace.StopTrace(error, itr_thread->first);
+        if (!error.Success()) {
+          std::string error_string(error.GetCString());
+          if ((error_string.find("tracing not active for this process") ==
+               std::string::npos) &&
+              (error_string.find("tracing not active for this thread") ==
+               std::string::npos)) {
+            sberror.SetErrorStringWithFormat(
+                "%s; thread id=%" PRIu64 ", ProcessID = %" PRIu64,
+                error_string.c_str(), itr_thread->first,
+                sbprocess.GetProcessID());
+            return;
+          }
+        }
+
+        if (itr_thread->first == LLDB_INVALID_THREAD_ID)
+          id_to_be_ignored = lldb_pt_user_id;
+      }
+      itr_thread = itr_process->second.erase(itr_thread);
+    }
+    m_mapProcessUID_mapThreadID_TraceInfo.erase(itr_process);
+  } else {
+    // This implies to stop tracing on a single thread.
+    // if 'tid' is registered in the class then get the trace id and stop trace
+    // on it. If it is not then check if tracing was ever started on the entire
+    // process (because there is a possibility that trace is still running for
+    // 'tid' but it was not registered in the class because user had started
+    // trace on the whole process and 'tid' spawned later). In that case, get
+    // the trace id of the process trace instance and stop trace on this thread.
+    // If tracing was never started on the entire process then return error
+    // because there is no way tracing is active on 'tid'.
+    MapThreadID_TraceInfo &mapThreadID_TraceInfo = itr_process->second;
+    lldb::SBTrace trace;
+    auto itr = mapThreadID_TraceInfo.find(tid);
+    if (itr != mapThreadID_TraceInfo.end()) {
+      trace = itr->second.GetUniqueTraceInstance();
+    } else {
+      auto itr = mapThreadID_TraceInfo.find(LLDB_INVALID_THREAD_ID);
+      if (itr != mapThreadID_TraceInfo.end()) {
+        trace = itr->second.GetUniqueTraceInstance();
+      } else {
+        sberror.SetErrorStringWithFormat(
+            "tracing not active for this thread; thread id=%" PRIu64
+            ", ProcessID = %" PRIu64,
+            tid, sbprocess.GetProcessID());
+        return;
+      }
+    }
+
+    // Stop Tracing
+    trace.StopTrace(error, tid);
+    if (!error.Success()) {
+      std::string error_string(error.GetCString());
+      sberror.SetErrorStringWithFormat(
+          "%s; thread id=%" PRIu64 ", ProcessID = %" PRIu64,
+          error_string.c_str(), tid, sbprocess.GetProcessID());
+      if (error_string.find("tracing not active") == std::string::npos)
+        return;
+    }
+    // Delete the entry of 'tid' from this class (if any)
+    mapThreadID_TraceInfo.erase(tid);
+  }
+}
+
+void Decoder::ReadTraceDataAndImageInfo(lldb::SBProcess &sbprocess,
+                                        lldb::tid_t tid, lldb::SBError &sberror,
+                                        ThreadTraceInfo &threadTraceInfo) {
+  // Allocate trace data buffer and parse cpu info for 'tid' if it is registered
+  // for the first time in class
+  lldb::SBTrace &trace = threadTraceInfo.GetUniqueTraceInstance();
+  Buffer &pt_buffer = threadTraceInfo.GetPTBuffer();
+  lldb::SBError error;
+  if (pt_buffer.size() == 0) {
+    lldb::SBTraceOptions traceoptions;
+    traceoptions.setThreadID(tid);
+    trace.GetTraceConfig(traceoptions, error);
+    if (!error.Success()) {
+      sberror.SetErrorStringWithFormat("%s; ProcessID = %" PRIu64,
+                                       error.GetCString(),
+                                       sbprocess.GetProcessID());
+      return;
+    }
+    if (traceoptions.getType() != lldb::TraceType::eTraceTypeProcessorTrace) {
+      sberror.SetErrorStringWithFormat("invalid TraceType received from LLDB "
+                                       "for this thread; thread id=%" PRIu64
+                                       ", ProcessID = %" PRIu64,
+                                       tid, sbprocess.GetProcessID());
+      return;
+    }
+
+    threadTraceInfo.AllocatePTBuffer(traceoptions.getTraceBufferSize());
+    lldb::SBStructuredData sbstructdata = traceoptions.getTraceParams(sberror);
+    if (!sberror.Success())
+      return;
+    CPUInfo &pt_cpu = threadTraceInfo.GetCPUInfo();
+    ParseCPUInfo(pt_cpu, sbstructdata, sberror);
+    if (!sberror.Success())
+      return;
+  }
+
+  // Call LLDB API to get raw trace data for this thread
+  size_t bytes_written = trace.GetTraceData(error, (void *)pt_buffer.data(),
+                                            pt_buffer.size(), 0, tid);
+  if (!error.Success()) {
+    sberror.SetErrorStringWithFormat(
+        "%s; thread_id = %" PRIu64 ",  ProcessID = %" PRIu64,
+        error.GetCString(), tid, sbprocess.GetProcessID());
+    return;
+  }
+  std::fill(pt_buffer.begin() + bytes_written, pt_buffer.end(), 0);
+
+  // Get information of all the modules of the inferior
+  lldb::SBTarget sbtarget = sbprocess.GetTarget();
+  ReadExecuteSectionInfos &readExecuteSectionInfos =
+      threadTraceInfo.GetReadExecuteSectionInfos();
+  GetTargetModulesInfo(sbtarget, readExecuteSectionInfos, sberror);
+  if (!sberror.Success())
+    return;
+}
+
+void Decoder::DecodeProcessorTrace(lldb::SBProcess &sbprocess, lldb::tid_t tid,
+                                   lldb::SBError &sberror,
+                                   ThreadTraceInfo &threadTraceInfo) {
+  // Initialize instruction decoder
+  struct pt_insn_decoder *decoder = nullptr;
+  struct pt_config config;
+  Buffer &pt_buffer = threadTraceInfo.GetPTBuffer();
+  CPUInfo &pt_cpu = threadTraceInfo.GetCPUInfo();
+  ReadExecuteSectionInfos &readExecuteSectionInfos =
+      threadTraceInfo.GetReadExecuteSectionInfos();
+
+  InitializePTInstDecoder(&decoder, &config, pt_cpu, pt_buffer,
+                          readExecuteSectionInfos, sberror);
+  if (!sberror.Success())
+    return;
+
+  // Start raw trace decoding
+  Instructions &instruction_list = threadTraceInfo.GetInstructionLog();
+  instruction_list.clear();
+  DecodeTrace(decoder, instruction_list, sberror);
+}
+
+// Raw trace decoding requires information of Read & Execute sections of each
+// module of the inferior. This function updates internal state of the class to
+// store this information.
+void Decoder::GetTargetModulesInfo(
+    lldb::SBTarget &sbtarget, ReadExecuteSectionInfos &readExecuteSectionInfos,
+    lldb::SBError &sberror) {
+  if (!sbtarget.IsValid()) {
+    sberror.SetErrorStringWithFormat("Can't get target's modules info from "
+                                     "LLDB; process has an invalid target");
+    return;
+  }
+
+  lldb::SBFileSpec target_file_spec = sbtarget.GetExecutable();
+  if (!target_file_spec.IsValid()) {
+    sberror.SetErrorStringWithFormat("Target has an invalid file spec");
+    return;
+  }
+
+  uint32_t num_modules = sbtarget.GetNumModules();
+  readExecuteSectionInfos.clear();
+
+  // Store information of all RX sections of each module of inferior
+  for (uint32_t i = 0; i < num_modules; i++) {
+    lldb::SBModule module = sbtarget.GetModuleAtIndex(i);
+    if (!module.IsValid()) {
+      sberror.SetErrorStringWithFormat(
+          "Can't get module info [ %" PRIu32
+          " ] of target \"%s\" from LLDB, invalid module",
+          i, target_file_spec.GetFilename());
+      return;
+    }
+
+    lldb::SBFileSpec module_file_spec = module.GetPlatformFileSpec();
+    if (!module_file_spec.IsValid()) {
+      sberror.SetErrorStringWithFormat(
+          "Can't get module info [ %" PRIu32
+          " ] of target \"%s\" from LLDB, invalid file spec",
+          i, target_file_spec.GetFilename());
+      return;
+    }
+
+    const char *image(module_file_spec.GetFilename());
+    lldb::SBError error;
+    char image_complete_path[1024];
+    uint32_t path_length = module_file_spec.GetPath(
+        image_complete_path, sizeof(image_complete_path));
+    size_t num_sections = module.GetNumSections();
+
+    // Store information of only RX sections
+    for (size_t idx = 0; idx < num_sections; idx++) {
+      lldb::SBSection section = module.GetSectionAtIndex(idx);
+      uint32_t section_permission = section.GetPermissions();
+      if ((section_permission & lldb::Permissions::ePermissionsReadable) &&
+          (section_permission & lldb::Permissions::ePermissionsExecutable)) {
+        lldb::SBData section_data = section.GetSectionData();
+        if (!section_data.IsValid()) {
+          sberror.SetErrorStringWithFormat(
+              "Can't get module info [ %" PRIu32 " ]   \"%s\"  of target "
+              "\"%s\" from LLDB, invalid "
+              "data in \"%s\" section",
+              i, image, target_file_spec.GetFilename(), section.GetName());
+          return;
+        }
+
+        // In case section has no data, skip it.
+        if (section_data.GetByteSize() == 0)
+          continue;
+
+        if (!path_length) {
+          sberror.SetErrorStringWithFormat(
+              "Can't get module info [ %" PRIu32 " ]   \"%s\"  of target "
+              "\"%s\" from LLDB, module "
+              "has an invalid path length",
+              i, image, target_file_spec.GetFilename());
+          return;
+        }
+
+        std::string image_path(image_complete_path, path_length);
+        try {
+          readExecuteSectionInfos.emplace_back(
+              section.GetLoadAddress(sbtarget), section.GetFileOffset(),
+              section_data.GetByteSize(), image_path);
+        } catch (const std::bad_alloc &le) {
+          continue;
+        }
+      }
+    }
+  }
+}
+
+// Raw trace decoding requires information of the target cpu on which inferior
+// is running. This function gets the Trace Configuration from LLDB, parses it
+// for cpu model, family, stepping and vendor id info and updates the internal
+// state of the class to store this information.
+void Decoder::ParseCPUInfo(CPUInfo &pt_cpu, lldb::SBStructuredData &s,
+                           lldb::SBError &sberror) {
+  lldb::SBStructuredData custom_trace_params = s.GetValueForKey("intel-pt");
+  if (!custom_trace_params.IsValid()) {
+    sberror.SetErrorStringWithFormat("lldb couldn't provide cpuinfo");
+    return;
+  }
+
+  uint64_t family = 0, model = 0, stepping = 0;
+  char vendor[32];
+  const char *key_family = "cpu_family";
+  const char *key_model = "cpu_model";
+  const char *key_stepping = "cpu_stepping";
+  const char *key_vendor = "cpu_vendor";
+
+  // parse family
+  lldb::SBStructuredData struct_family =
+      custom_trace_params.GetValueForKey(key_family);
+  if (!struct_family.IsValid()) {
+    sberror.SetErrorStringWithFormat(
+        "%s info missing in custom trace parameters", key_family);
+    return;
+  }
+  family = struct_family.GetIntegerValue(0x10000);
+  if (family > UINT16_MAX) {
+    sberror.SetErrorStringWithFormat(
+        "invalid CPU family value extracted from custom trace parameters");
+    return;
+  }
+  pt_cpu.family = (uint16_t)family;
+
+  // parse model
+  lldb::SBStructuredData struct_model =
+      custom_trace_params.GetValueForKey(key_model);
+  if (!struct_model.IsValid()) {
+    sberror.SetErrorStringWithFormat(
+        "%s info missing in custom trace parameters; family=%" PRIu16,
+        key_model, pt_cpu.family);
+    return;
+  }
+  model = struct_model.GetIntegerValue(0x100);
+  if (model > UINT8_MAX) {
+    sberror.SetErrorStringWithFormat("invalid CPU model value extracted from "
+                                     "custom trace parameters; family=%" PRIu16,
+                                     pt_cpu.family);
+    return;
+  }
+  pt_cpu.model = (uint8_t)model;
+
+  // parse stepping
+  lldb::SBStructuredData struct_stepping =
+      custom_trace_params.GetValueForKey(key_stepping);
+  if (!struct_stepping.IsValid()) {
+    sberror.SetErrorStringWithFormat(
+        "%s info missing in custom trace parameters; family=%" PRIu16
+        ", model=%" PRIu8,
+        key_stepping, pt_cpu.family, pt_cpu.model);
+    return;
+  }
+  stepping = struct_stepping.GetIntegerValue(0x100);
+  if (stepping > UINT8_MAX) {
+    sberror.SetErrorStringWithFormat("invalid CPU stepping value extracted "
+                                     "from custom trace parameters; "
+                                     "family=%" PRIu16 ", model=%" PRIu8,
+                                     pt_cpu.family, pt_cpu.model);
+    return;
+  }
+  pt_cpu.stepping = (uint8_t)stepping;
+
+  // parse vendor info
+  pt_cpu.vendor = pcv_unknown;
+  lldb::SBStructuredData struct_vendor =
+      custom_trace_params.GetValueForKey(key_vendor);
+  if (!struct_vendor.IsValid()) {
+    sberror.SetErrorStringWithFormat(
+        "%s info missing in custom trace parameters; family=%" PRIu16
+        ", model=%" PRIu8 ", stepping=%" PRIu8,
+        key_vendor, pt_cpu.family, pt_cpu.model, pt_cpu.stepping);
+    return;
+  }
+  auto length = struct_vendor.GetStringValue(vendor, sizeof(vendor));
+  if (length && strstr(vendor, "GenuineIntel"))
+    pt_cpu.vendor = pcv_intel;
+}
+
+// Initialize trace decoder with pt_config structure and populate its image
+// structure with inferior's memory image information. pt_config structure is
+// initialized with trace buffer and cpu info of the inferior before storing it
+// in trace decoder.
+void Decoder::InitializePTInstDecoder(
+    struct pt_insn_decoder **decoder, struct pt_config *config,
+    const CPUInfo &pt_cpu, Buffer &pt_buffer,
+    const ReadExecuteSectionInfos &readExecuteSectionInfos,
+    lldb::SBError &sberror) const {
+  if (!decoder || !config) {
+    sberror.SetErrorStringWithFormat("internal error");
+    return;
+  }
+
+  // Load cpu info of inferior's target in pt_config struct
+  pt_config_init(config);
+  config->cpu = pt_cpu;
+  int errcode = pt_cpu_errata(&(config->errata), &(config->cpu));
+  if (errcode < 0) {
+    sberror.SetErrorStringWithFormat("processor trace decoding library: "
+                                     "pt_cpu_errata() failed with error: "
+                                     "\"%s\"",
+                                     pt_errstr(pt_errcode(errcode)));
+    return;
+  }
+
+  // Load trace buffer's starting and end address in pt_config struct
+  config->begin = pt_buffer.data();
+  config->end = pt_buffer.data() + pt_buffer.size();
+
+  // Fill trace decoder with pt_config struct
+  *decoder = pt_insn_alloc_decoder(config);
+  if (*decoder == nullptr) {
+    sberror.SetErrorStringWithFormat("processor trace decoding library:  "
+                                     "pt_insn_alloc_decoder() returned null "
+                                     "pointer");
+    return;
+  }
+
+  // Fill trace decoder's image with inferior's memory image information
+  struct pt_image *image = pt_insn_get_image(*decoder);
+  if (!image) {
+    sberror.SetErrorStringWithFormat("processor trace decoding library:  "
+                                     "pt_insn_get_image() returned null "
+                                     "pointer");
+    pt_insn_free_decoder(*decoder);
+    return;
+  }
+
+  for (auto &itr : readExecuteSectionInfos) {
+    errcode = pt_image_add_file(image, itr.image_path.c_str(), itr.file_offset,
+                                itr.size, nullptr, itr.load_address);
+    if (errcode < 0) {
+      sberror.SetErrorStringWithFormat("processor trace decoding library:  "
+                                       "pt_image_add_file() failed with error: "
+                                       "\"%s\"",
+                                       pt_errstr(pt_errcode(errcode)));
+      pt_insn_free_decoder(*decoder);
+      return;
+    }
+  }
+}
+
+// Start actual decoding of raw trace
+void Decoder::DecodeTrace(struct pt_insn_decoder *decoder,
+                          Instructions &instruction_list,
+                          lldb::SBError &sberror) {
+  uint64_t decoder_offset = 0;
+
+  while (1) {
+    struct pt_insn insn;
+
+    // Try to sync the decoder. If it fails then get the decoder_offset and try
+    // to sync again. If the new_decoder_offset is same as decoder_offset then
+    // we will not succeed in syncing for any number of pt_insn_sync_forward()
+    // operations. Return in that case. Else keep resyncing until either end of
+    // trace stream is reached or pt_insn_sync_forward() passes.
+    int errcode = pt_insn_sync_forward(decoder);
+    if (errcode < 0) {
+      if (errcode == -pte_eos)
+        return;
+
+      int errcode_off = pt_insn_get_offset(decoder, &decoder_offset);
+      if (errcode_off < 0) {
+        sberror.SetErrorStringWithFormat(
+            "processor trace decoding library: \"%s\"",
+            pt_errstr(pt_errcode(errcode)));
+        try {
+          instruction_list.emplace_back(sberror.GetCString());
+        } catch (const std::bad_alloc &le) {
+        }
+        return;
+      }
+
+      sberror.SetErrorStringWithFormat(
+          "processor trace decoding library: \"%s\"  [decoder_offset] => "
+          "[0x%" PRIu64 "]",
+          pt_errstr(pt_errcode(errcode)), decoder_offset);
+      try {
+        instruction_list.emplace_back(sberror.GetCString());
+      } catch (const std::bad_alloc &le) {
+        return;
+      }
+      while (1) {
+        errcode = pt_insn_sync_forward(decoder);
+        if (errcode >= 0)
+          break;
+
+        if (errcode == -pte_eos)
+          return;
+
+        uint64_t new_decoder_offset = 0;
+        errcode_off = pt_insn_get_offset(decoder, &new_decoder_offset);
+        if (errcode_off < 0) {
+          sberror.SetErrorStringWithFormat(
+              "processor trace decoding library: \"%s\"",
+              pt_errstr(pt_errcode(errcode)));
+          try {
+            instruction_list.emplace_back(sberror.GetCString());
+          } catch (const std::bad_alloc &le) {
+          }
+          return;
+        } else if (new_decoder_offset <= decoder_offset) {
+          // We tried resyncing the decoder and decoder didn't make any
+          // progress because the offset didn't change. We will not make any
+          // progress further. Hence, returning in this situation.
+          return;
+        }
+        sberror.SetErrorStringWithFormat(
+            "processor trace decoding library: \"%s\"  [decoder_offset] => "
+            "[0x%" PRIu64 "]",
+            pt_errstr(pt_errcode(errcode)), new_decoder_offset);
+        try {
+          instruction_list.emplace_back(sberror.GetCString());
+        } catch (const std::bad_alloc &le) {
+        }
+        decoder_offset = new_decoder_offset;
+      }
+    }
+
+    while (1) {
+      errcode = pt_insn_next(decoder, &insn, sizeof(insn));
+      if (errcode < 0) {
+        if (insn.iclass == ptic_error)
+          break;
+
+        try {
+          instruction_list.emplace_back(insn);
+        } catch (const std::bad_alloc &le) {
+          return;
+        }
+
+        if (errcode == -pte_eos)
+          return;
+
+        Diagnose(decoder, errcode, sberror, &insn);
+        try {
+          instruction_list.emplace_back(sberror.GetCString());
+        } catch (const std::bad_alloc &le) {
+          return;
+        }
+        break;
+      }
+      try {
+        instruction_list.emplace_back(insn);
+      } catch (const std::bad_alloc &le) {
+        return;
+      }
+      if (errcode & pts_eos)
+        return;
+    }
+  }
+}
+
+// Function to diagnose and indicate errors during raw trace decoding
+void Decoder::Diagnose(struct pt_insn_decoder *decoder, int decode_error,
+                       lldb::SBError &sberror, const struct pt_insn *insn) {
+  int errcode;
+  uint64_t offset;
+
+  errcode = pt_insn_get_offset(decoder, &offset);
+  if (insn) {
+    if (errcode < 0)
+      sberror.SetErrorStringWithFormat(
+          "processor trace decoding library: \"%s\"  [decoder_offset, "
+          "last_successful_decoded_ip] => [?, 0x%" PRIu64 "]",
+          pt_errstr(pt_errcode(decode_error)), insn->ip);
+    else
+      sberror.SetErrorStringWithFormat(
+          "processor trace decoding library: \"%s\"  [decoder_offset, "
+          "last_successful_decoded_ip] => [0x%" PRIu64 ", 0x%" PRIu64 "]",
+          pt_errstr(pt_errcode(decode_error)), offset, insn->ip);
+  } else {
+    if (errcode < 0)
+      sberror.SetErrorStringWithFormat(
+          "processor trace decoding library: \"%s\"",
+          pt_errstr(pt_errcode(decode_error)));
+    else
+      sberror.SetErrorStringWithFormat(
+          "processor trace decoding library: \"%s\"  [decoder_offset] => "
+          "[0x%" PRIu64 "]",
+          pt_errstr(pt_errcode(decode_error)), offset);
+  }
+}
+
+void Decoder::GetInstructionLogAtOffset(
+    lldb::SBProcess &sbprocess, lldb::tid_t tid, uint32_t offset,
+    uint32_t count, std::vector<std::shared_ptr<Instruction>> &result_list,
+    lldb::SBError &sberror) {
+  sberror.Clear();
+  CheckDebuggerID(sbprocess, sberror);
+  if (!sberror.Success()) {
+    return;
+  }
+
+  std::lock_guard<std::mutex> guard(
+      m_mapProcessUID_mapThreadID_TraceInfo_mutex);
+  RemoveDeadProcessesAndThreads(sbprocess);
+
+  ThreadTraceInfo *threadTraceInfo = nullptr;
+  FetchAndDecode(sbprocess, tid, sberror, &threadTraceInfo);
+  if (!sberror.Success()) {
+    return;
+  }
+  if (threadTraceInfo == nullptr) {
+    sberror.SetErrorStringWithFormat("internal error");
+    return;
+  }
+
+  // Return instruction log by populating 'result_list'
+  Instructions &insn_list = threadTraceInfo->GetInstructionLog();
+  uint64_t sum = (uint64_t)offset + 1;
+  if (((insn_list.size() <= offset) && (count <= sum) &&
+       ((sum - count) >= insn_list.size())) ||
+      (count < 1)) {
+    sberror.SetErrorStringWithFormat(
+        "Instruction Log not available for offset=%" PRIu32
+        " and count=%" PRIu32 ", ProcessID = %" PRIu64,
+        offset, count, sbprocess.GetProcessID());
+    return;
+  }
+
+  Instructions::iterator itr_first =
+      (insn_list.size() <= offset) ? insn_list.begin()
+                                   : insn_list.begin() + insn_list.size() - sum;
+  Instructions::iterator itr_last =
+      (count <= sum) ? insn_list.begin() + insn_list.size() - (sum - count)
+                     : insn_list.end();
+  Instructions::iterator itr = itr_first;
+  while (itr != itr_last) {
+    try {
+      result_list.push_back(
+          std::shared_ptr<Instruction>(new Instruction(*itr)));
+    } catch (const std::bad_alloc &le) {
+      return;
+    }
+    ++itr;
+  }
+}
+
+void Decoder::GetProcessorTraceInfo(lldb::SBProcess &sbprocess, lldb::tid_t tid,
+                                    TraceOptions &options,
+                                    lldb::SBError &sberror) {
+  sberror.Clear();
+  CheckDebuggerID(sbprocess, sberror);
+  if (!sberror.Success()) {
+    return;
+  }
+
+  std::lock_guard<std::mutex> guard(
+      m_mapProcessUID_mapThreadID_TraceInfo_mutex);
+  RemoveDeadProcessesAndThreads(sbprocess);
+
+  ThreadTraceInfo *threadTraceInfo = nullptr;
+  FetchAndDecode(sbprocess, tid, sberror, &threadTraceInfo);
+  if (!sberror.Success()) {
+    return;
+  }
+  if (threadTraceInfo == nullptr) {
+    sberror.SetErrorStringWithFormat("internal error");
+    return;
+  }
+
+  // Get SBTraceOptions from LLDB for 'tid', populate 'traceoptions' with it
+  lldb::SBTrace &trace = threadTraceInfo->GetUniqueTraceInstance();
+  lldb::SBTraceOptions traceoptions;
+  lldb::SBError error;
+  traceoptions.setThreadID(tid);
+  trace.GetTraceConfig(traceoptions, error);
+  if (!error.Success()) {
+    std::string error_string(error.GetCString());
+    if (error_string.find("tracing not active") != std::string::npos) {
+      uint32_t unique_id = sbprocess.GetUniqueID();
+      auto itr_process = m_mapProcessUID_mapThreadID_TraceInfo.find(unique_id);
+      if (itr_process == m_mapProcessUID_mapThreadID_TraceInfo.end())
+        return;
+      itr_process->second.erase(tid);
+    }
+    sberror.SetErrorStringWithFormat("%s; ProcessID = %" PRIu64,
+                                     error_string.c_str(),
+                                     sbprocess.GetProcessID());
+    return;
+  }
+  if (traceoptions.getType() != lldb::TraceType::eTraceTypeProcessorTrace) {
+    sberror.SetErrorStringWithFormat("invalid TraceType received from LLDB "
+                                     "for this thread; thread id=%" PRIu64
+                                     ", ProcessID = %" PRIu64,
+                                     tid, sbprocess.GetProcessID());
+    return;
+  }
+  options.setType(traceoptions.getType());
+  options.setTraceBufferSize(traceoptions.getTraceBufferSize());
+  options.setMetaDataBufferSize(traceoptions.getMetaDataBufferSize());
+  lldb::SBStructuredData sbstructdata = traceoptions.getTraceParams(sberror);
+  if (!sberror.Success())
+    return;
+  options.setTraceParams(sbstructdata);
+  options.setInstructionLogSize(threadTraceInfo->GetInstructionLog().size());
+}
+
+void Decoder::FetchAndDecode(lldb::SBProcess &sbprocess, lldb::tid_t tid,
+                             lldb::SBError &sberror,
+                             ThreadTraceInfo **threadTraceInfo) {
+  // Return with error if 'sbprocess' is not registered in the class
+  uint32_t unique_id = sbprocess.GetUniqueID();
+  auto itr_process = m_mapProcessUID_mapThreadID_TraceInfo.find(unique_id);
+  if (itr_process == m_mapProcessUID_mapThreadID_TraceInfo.end()) {
+    sberror.SetErrorStringWithFormat(
+        "tracing not active for this process; ProcessID = %" PRIu64,
+        sbprocess.GetProcessID());
+    return;
+  }
+
+  if (tid == LLDB_INVALID_THREAD_ID) {
+    sberror.SetErrorStringWithFormat(
+        "invalid thread id provided; thread_id = %" PRIu64
+        ", ProcessID = %" PRIu64,
+        tid, sbprocess.GetProcessID());
+    return;
+  }
+
+  // Check whether 'tid' thread is registered in the class. If it is then in
+  // case StopID didn't change then return without doing anything (no need to
+  // read and decode trace data then). Otherwise, save new StopID and proceed
+  // with reading and decoding trace.
+  if (threadTraceInfo == nullptr) {
+    sberror.SetErrorStringWithFormat("internal error");
+    return;
+  }
+
+  MapThreadID_TraceInfo &mapThreadID_TraceInfo = itr_process->second;
+  auto itr_thread = mapThreadID_TraceInfo.find(tid);
+  if (itr_thread != mapThreadID_TraceInfo.end()) {
+    if (itr_thread->second.GetStopID() == sbprocess.GetStopID()) {
+      *threadTraceInfo = &(itr_thread->second);
+      return;
+    }
+    itr_thread->second.SetStopID(sbprocess.GetStopID());
+  } else {
+    // Implies 'tid' is not registered in the class. If tracing was never
+    // started on the entire process then return an error. Else try to register
+    // this thread and proceed with reading and decoding trace.
+    lldb::SBError error;
+    itr_thread = mapThreadID_TraceInfo.find(LLDB_INVALID_THREAD_ID);
+    if (itr_thread == mapThreadID_TraceInfo.end()) {
+      sberror.SetErrorStringWithFormat(
+          "tracing not active for this thread; ProcessID = %" PRIu64,
+          sbprocess.GetProcessID());
+      return;
+    }
+
+    lldb::SBTrace &trace = itr_thread->second.GetUniqueTraceInstance();
+    ThreadTraceInfo &trace_info = mapThreadID_TraceInfo[tid];
+    trace_info.SetUniqueTraceInstance(trace);
+    trace_info.SetStopID(sbprocess.GetStopID());
+    itr_thread = mapThreadID_TraceInfo.find(tid);
+  }
+
+  // Get raw trace data and inferior image from LLDB for the registered thread
+  ReadTraceDataAndImageInfo(sbprocess, tid, sberror, itr_thread->second);
+  if (!sberror.Success()) {
+    std::string error_string(sberror.GetCString());
+    if (error_string.find("tracing not active") != std::string::npos)
+      mapThreadID_TraceInfo.erase(itr_thread);
+    return;
+  }
+  // Decode raw trace data
+  DecodeProcessorTrace(sbprocess, tid, sberror, itr_thread->second);
+  if (!sberror.Success()) {
+    return;
+  }
+  *threadTraceInfo = &(itr_thread->second);
+}
+
+// This function checks whether the provided SBProcess instance belongs to same
+// SBDebugger with which this tool instance is associated.
+void Decoder::CheckDebuggerID(lldb::SBProcess &sbprocess,
+                              lldb::SBError &sberror) {
+  if (!sbprocess.IsValid()) {
+    sberror.SetErrorStringWithFormat("invalid process instance");
+    return;
+  }
+
+  lldb::SBTarget sbtarget = sbprocess.GetTarget();
+  if (!sbtarget.IsValid()) {
+    sberror.SetErrorStringWithFormat(
+        "process contains an invalid target; ProcessID = %" PRIu64,
+        sbprocess.GetProcessID());
+    return;
+  }
+
+  lldb::SBDebugger sbdebugger = sbtarget.GetDebugger();
+  if (!sbdebugger.IsValid()) {
+    sberror.SetErrorStringWithFormat("process's target contains an invalid "
+                                     "debugger instance; ProcessID = %" PRIu64,
+                                     sbprocess.GetProcessID());
+    return;
+  }
+
+  if (sbdebugger.GetID() != m_debugger_user_id) {
+    sberror.SetErrorStringWithFormat(
+        "process belongs to a different SBDebugger instance than the one for "
+        "which the tool is instantiated; ProcessID = %" PRIu64,
+        sbprocess.GetProcessID());
+    return;
+  }
+}
Index: tools/intel-features/intel-pt/CMakeLists.txt
===================================================================
--- /dev/null
+++ tools/intel-features/intel-pt/CMakeLists.txt
@@ -0,0 +1,29 @@
+if (NOT LIBIPT_INCLUDE_PATH)
+  message (FATAL_ERROR "libipt include path not provided")
+endif()
+
+if (NOT EXISTS "${LIBIPT_INCLUDE_PATH}")
+  message (FATAL_ERROR "invalid libipt include path provided")
+endif()
+include_directories(${LIBIPT_INCLUDE_PATH})
+
+if (NOT LIBIPT_LIBRARY_PATH)
+  find_library(LIBIPT_LIBRARY ipt)
+else()
+  if (NOT EXISTS "${LIBIPT_LIBRARY_PATH}")
+    message (FATAL_ERROR "invalid libipt library path provided")
+  endif()
+  find_library(LIBIPT_LIBRARY ipt PATHS ${LIBIPT_LIBRARY_PATH})
+endif()
+
+if (NOT LIBIPT_LIBRARY)
+  message (FATAL_ERROR "libipt library not found")
+endif()
+
+add_library(lldbIntelPT
+  PTDecoder.cpp
+  Decoder.cpp
+  cli-wrapper-pt.cpp
+  )
+
+set(PT_DEPS ${PT_DEPS} ${LIBIPT_LIBRARY} PARENT_SCOPE)
Index: tools/intel-features/intel-mpx/test/main.cpp
===================================================================
--- tools/intel-features/intel-mpx/test/main.cpp
+++ tools/intel-features/intel-mpx/test/main.cpp
@@ -32,7 +32,8 @@
 int
 main(int argc, char const *argv[])
 {
-  // This call returns 0 only if the CPU and the kernel support Intel(R) MPX.
+  // This call returns 0 only if the CPU and the kernel support
+  // Intel(R) Memory Protection Extensions (Intel(R) MPX).
   if (prctl(PR_MPX_ENABLE_MANAGEMENT, 0, 0, 0, 0) != 0)
         return -1;
 
Index: tools/intel-features/intel-mpx/test/TestMPXTable.py
===================================================================
--- tools/intel-features/intel-mpx/test/TestMPXTable.py
+++ tools/intel-features/intel-mpx/test/TestMPXTable.py
@@ -24,16 +24,17 @@
     @skipIf(compiler="clang")
     @skipIf(oslist=no_match(['linux']))
     @skipIf(archs=no_match(['i386', 'x86_64']))
-    @skipIf(compiler="gcc", compiler_version=["<", "5"]) #GCC version >= 5 supports Intel(R) MPX.
+    @skipIf(compiler="gcc", compiler_version=["<", "5"]) #GCC version >= 5 supports
+    #Intel(R) Memory Protection Extensions (Intel(R) MPX).
     def test_show_command(self):
         """Test 'mpx-table show' command"""
         self.build()
 
         lldb_exec_dir = os.environ["LLDB_IMPLIB_DIR"]
         lldb_lib_dir = os.path.join(lldb_exec_dir, os.pardir, "lib")
-        plugin_file = os.path.join(lldb_lib_dir, "liblldb-intel-mpxtable.so")
+        plugin_file = os.path.join(lldb_lib_dir, "liblldbIntelFeatures.so")
         if not os.path.isfile(plugin_file):
-            self.skipTest("Intel(R) mpx-table plugin missing.")
+            self.skipTest("features plugin missing.")
         plugin_command = " "
         seq = ("plugin", "load", plugin_file)
         plugin_command = plugin_command.join(seq)
@@ -123,9 +124,9 @@
 
         lldb_exec_dir = os.environ["LLDB_IMPLIB_DIR"]
         lldb_lib_dir = os.path.join(lldb_exec_dir, os.pardir, "lib")
-        plugin_file = os.path.join(lldb_lib_dir, "liblldb-intel-mpxtable.so")
+        plugin_file = os.path.join(lldb_lib_dir, "liblldbIntelFeatures.so")
         if not os.path.isfile(plugin_file):
-            self.skipTest("Intel(R) mpx-table plugin missing.")
+            self.skipTest("features plugin missing.")
         plugin_command = " "
         seq = ("plugin", "load", plugin_file)
         plugin_command = plugin_command.join(seq)
Index: tools/intel-features/intel-mpx/test/README.txt
===================================================================
--- tools/intel-features/intel-mpx/test/README.txt
+++ tools/intel-features/intel-mpx/test/README.txt
@@ -2,5 +2,5 @@
 
     packages/Python/lldbsuite/test/functionalities/plugins/commands/mpxtablecmd
 
-and copy into it the contents of this direcotry.
+and copy into it the contents of this directory.
 
Index: tools/intel-mpx/test/Makefile
===================================================================
--- /dev/null
+++ tools/intel-mpx/test/Makefile
@@ -1,7 +0,0 @@
-LEVEL = ../../../../make
-
-CXX_SOURCES := main.cpp
-
-CFLAGS_EXTRAS += -mmpx -fcheck-pointer-bounds -lmpxwrappers -lmpx -fuse-ld=bfd
-
-include $(LEVEL)/Makefile.rules
Index: tools/intel-features/intel-mpx/cli-wrapper-mpxtable.h
===================================================================
--- /dev/null
+++ tools/intel-features/intel-mpx/cli-wrapper-mpxtable.h
@@ -0,0 +1,12 @@
+//===-- cli-wrapper-mpxtable.h----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/API/SBDebugger.h"
+
+bool MPXPluginInitialize(lldb::SBDebugger& debugger);
Index: tools/intel-features/intel-mpx/cli-wrapper-mpxtable.cpp
===================================================================
--- tools/intel-features/intel-mpx/cli-wrapper-mpxtable.cpp
+++ tools/intel-features/intel-mpx/cli-wrapper-mpxtable.cpp
@@ -1,4 +1,4 @@
-//===-- IntelMPXTablePlugin.cpp----------------------------------*- C++ -*-===//
+//===-- cli-wrapper-mpxtable.cpp----------------------------------*- C++ -*-===//
 //
 //                     The LLVM Compiler Infrastructure
 //
@@ -12,6 +12,7 @@
 #include <string>
 
 // Project includes
+#include "cli-wrapper-mpxtable.h"
 #include "lldb/API/SBCommandInterpreter.h"
 #include "lldb/API/SBCommandReturnObject.h"
 #include "lldb/API/SBMemoryRegionInfo.h"
@@ -21,10 +22,6 @@
 
 #include "llvm/ADT/Triple.h"
 
-namespace lldb {
-bool PluginInitialize(lldb::SBDebugger debugger);
-}
-
 static bool GetPtr(char *cptr, uint64_t &ptr, lldb::SBFrame &frame,
                    lldb::SBCommandReturnObject &result) {
   if (!cptr) {
@@ -286,7 +283,8 @@
   lldb::SBValue bndcfgu_val = frame.FindRegister("bndcfgu");
   if (!bndcfgu_val.IsValid()) {
     result.SetError(
-        "Cannot access register BNDCFGU. Does the target support MPX?");
+        "Cannot access register BNDCFGU. Does the target support "
+        "Intel(R) Memory Protection Extensions (Intel(R) MPX)?");
     result.SetStatus(lldb::eReturnStatusFailed);
     return false;
   }
@@ -409,17 +407,17 @@
   }
 };
 
-bool lldb::PluginInitialize(lldb::SBDebugger debugger) {
+bool MPXPluginInitialize(lldb::SBDebugger& debugger) {
   lldb::SBCommandInterpreter interpreter = debugger.GetCommandInterpreter();
   lldb::SBCommand mpxTable = interpreter.AddMultiwordCommand(
-      "mpx-table", "A utility to access the MPX table entries.");
+      "mpx-table", "A utility to access the Intel(R) MPX table entries.");
 
-  const char *mpx_show_help = "Show the MPX table entry of a pointer.\n"
-                              "mpx-table show <pointer>";
+  const char *mpx_show_help = "Show the Intel(R) MPX table entry of a pointer."
+                              "\nmpx-table show <pointer>";
   mpxTable.AddCommand("show", new MPXTableShow(), mpx_show_help);
 
   const char *mpx_set_help =
-      "Set the MPX table entry of a pointer.\n"
+      "Set the Intel(R) MPX table entry of a pointer.\n"
       "mpx-table set <pointer> <lower bound> <upper bound>";
   mpxTable.AddCommand("set", new MPXTableSet(), mpx_set_help);
 
Index: tools/intel-features/intel-mpx/CMakeLists.txt
===================================================================
--- /dev/null
+++ tools/intel-features/intel-mpx/CMakeLists.txt
@@ -0,0 +1,9 @@
+if (NOT CMAKE_SYSTEM_NAME MATCHES "Linux")
+  return ()
+endif ()
+
+add_library(lldbIntelMPX
+  cli-wrapper-mpxtable.cpp
+  )
+
+set(MPX_DEPS ${MPX_DEPS} LLVMSupport PARENT_SCOPE)
Index: tools/intel-features/cli-wrapper.cpp
===================================================================
--- /dev/null
+++ tools/intel-features/cli-wrapper.cpp
@@ -0,0 +1,30 @@
+//===-- cli-wrapper.cpp -----------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+// CLI Wrapper for hardware features of Intel(R) architecture based processors
+// to enable them to be used through LLDB's CLI. For details, please refer to
+// cli wrappers of each individual feature, residing in their respective
+// folders.
+//
+// Compile this into a shared lib and load by placing at appropriate locations
+// on disk or by using "plugin load" command at the LLDB command line.
+//
+//===----------------------------------------------------------------------===//
+
+#include "intel-mpx/cli-wrapper-mpxtable.h"
+#include "intel-pt/cli-wrapper-pt.h"
+#include "lldb/API/SBDebugger.h"
+
+namespace lldb {
+bool PluginInitialize(lldb::SBDebugger debugger);
+}
+
+bool lldb::PluginInitialize(lldb::SBDebugger debugger) {
+  PTPluginInitialize(debugger);
+  MPXPluginInitialize(debugger);
+  return true;
+}
Index: tools/intel-features/README.txt
===================================================================
--- /dev/null
+++ tools/intel-features/README.txt
@@ -0,0 +1,73 @@
+****************************************************************************
+*                            README                                        *
+*                                                                          *
+* This file provides all the information regarding new CLI commands that   *
+* enable using various hardware features of Intel(R) architecture based    *
+* processors from LLDB's CLI.                                              *
+****************************************************************************
+
+
+============
+Introduction
+============
+A shared library has been developed to use various hardware features of
+Intel(R) architecture based processors through LLDB's command line. The library
+currently comprises of hardware features namely Intel(R) Processor Trace and
+Intel(R) Memory Protection Extensions.
+
+
+============
+Details
+============
+A C++ based cli wrapper (cli-wrapper.cpp) has been developed here that
+agglomerates all cli commands for various hardware features. This wrapper is
+build to generate a shared library (lldbIntelFeatures) to provide all these
+commands.
+
+For each hardware feature, separate cli commands have been developed that are
+provided by wrappers (cli-wrapper-pt.cpp and cli-wrapper-mpxtable.cpp) residing
+in feature specific folders ("intel-pt" and "intel-mpx" respectively).
+
+For details regarding cli commands of each feature, please refer to these
+feature specific wrappers.
+
+
+
+============
+How to Build
+============
+The shared library (lldbIntelFeatures) has a cmake based build and can be built
+while building LLDB with cmake. "cli-wrapper.cpp" file is compiled along with all
+the feature specific source files (residing in feature specific folders).
+
+Furthermore, flexibility is provided to the user to include/exclude a particular
+feature while building lldbIntelFeatures library. This is done by flags described
+below:
+
+  - LLDB_BUILD_INTEL_PT - The flag enables building of Intel(R) Processor Trace
+    feature (inside intel-pt folder). This flag defaults to "OFF" meaning the
+    feature is excluded while building lldbIntelFeatures library. Set it to "ON"
+    in order to include it.
+
+  - LLDB_BUILD_INTEL_MPX - Enables building Intel(R) Memory Protection Extensions
+    feature (inside intel-mpx folder). This flag defaults to "ON" meaning
+    the feature is excluded while building lldbIntelFeatures library.
+
+Please refer to README files in feature specific folders to know about additional
+flags that need to be set in order to build that feature successfully.
+
+
+============
+How to Use
+============
+All CLI commands provided by this shared library can be used through the LLDB's
+CLI by executing "plugin load <shared_lib_name>" on LLDB CLI. shared_lib_name here
+is lldbIntelFeatures
+
+
+
+============
+Description
+============
+Please refer to README_CLI file of each feature to know about details of CLI
+commands.
Index: tools/intel-features/CMakeLists.txt
===================================================================
--- /dev/null
+++ tools/intel-features/CMakeLists.txt
@@ -0,0 +1,55 @@
+include(${LLDB_PROJECT_ROOT}/cmake/LLDBDependencies.cmake)
+
+LIST(APPEND COMMON_LINK_LIBS liblldb)
+LIST(APPEND PT_DEPS "")
+LIST(APPEND MPX_DEPS "")
+
+option(LLDB_BUILD_INTEL_MPX "Enable Building of Intel(R) Memory Protection Extensions" ON)
+if (LLDB_BUILD_INTEL_MPX)
+  add_subdirectory(intel-mpx)
+endif()
+
+option(LLDB_BUILD_INTEL_PT "Enable Building of Intel(R) Processor Trace Tool" OFF)
+if (LLDB_BUILD_INTEL_PT)
+  add_subdirectory(intel-pt)
+endif()
+
+if (NOT LLDB_DISABLE_PYTHON AND LLDB_BUILD_INTEL_PT)
+  set(LLDB_INTEL_FEATURES_PYTHON_WRAP ${LLDB_BINARY_DIR}/tools/intel-features/scripts/IntelFeaturesPythonWrap.cpp)
+  set_source_files_properties(${LLDB_INTEL_FEATURES_PYTHON_WRAP} PROPERTIES GENERATED 1)
+
+  if (CLANG_CL)
+    set_source_files_properties(${LLDB_INTEL_FEATURES_PYTHON_WRAP}
+                                 PROPERTIES COMPILE_FLAGS -Wno-unused-function)
+  endif()
+
+  if (LLVM_COMPILER_IS_GCC_COMPATIBLE AND
+      NOT "${CMAKE_SYSTEM_NAME}" MATCHES "Darwin")
+    set_property(SOURCE ${LLDB_INTEL_FEATURES_PYTHON_WRAP}
+                 APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-sequence-point -Wno-cast-qual")
+  endif ()
+  add_subdirectory(scripts)
+endif()
+
+add_library(lldbIntelFeatures SHARED
+  cli-wrapper.cpp
+  ${LLDB_INTEL_FEATURES_PYTHON_WRAP}
+  )
+
+if (LLDB_BUILD_INTEL_PT)
+  target_link_libraries(lldbIntelFeatures PUBLIC lldbIntelPT ${PT_DEPS})
+endif()
+
+if (LLDB_BUILD_INTEL_MPX)
+  target_link_libraries(lldbIntelFeatures PUBLIC lldbIntelMPX ${MPX_DEPS})
+endif()
+
+target_link_libraries(lldbIntelFeatures PUBLIC ${COMMON_LINK_LIBS})
+
+if (NOT LLDB_DISABLE_PYTHON AND LLDB_BUILD_INTEL_PT)
+  add_dependencies(lldbIntelFeatures intel-features-swig_wrapper)
+  target_link_libraries(lldbIntelFeatures PRIVATE ${LLDB_SYSTEM_LIBS})
+endif()
+
+install(TARGETS lldbIntelFeatures
+  LIBRARY DESTINATION lib${LLVM_LIBDIR_SUFFIX})
Index: tools/CMakeLists.txt
===================================================================
--- tools/CMakeLists.txt
+++ tools/CMakeLists.txt
@@ -8,4 +8,4 @@
 if (LLDB_CAN_USE_LLDB_SERVER)
   add_subdirectory(lldb-server)
 endif()
-add_subdirectory(intel-mpx)
+add_subdirectory(intel-features)
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to