Vendor import of lldb trunk r301441:

https://llvm.org/svn/llvm-project/lldb/trunk@301441
This commit is contained in:
Dimitry Andric 2017-04-26 19:24:53 +00:00
parent d44a35e87e
commit 5060b64b7d
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/vendor/lldb/dist/; revision=317455
svn path=/vendor/lldb/lldb-trunk-r301441/; revision=317456; tag=vendor/lldb/lldb-trunk-r301441
50 changed files with 1439 additions and 695 deletions

View File

@ -250,12 +250,6 @@ endif()
set(LLDB_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
set(LLDB_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
# If building on a 32-bit system, make sure off_t can store offsets > 2GB
if( CMAKE_SIZEOF_VOID_P EQUAL 4 )
add_definitions( -D_LARGEFILE_SOURCE )
add_definitions( -D_FILE_OFFSET_BITS=64 )
endif()
if (CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR)
message(FATAL_ERROR "In-source builds are not allowed. CMake would overwrite "
"the makefiles distributed with LLDB. Please create a directory and run cmake "

View File

@ -1,155 +0,0 @@
# Toolchain config for Android standalone NDK.
#
# Usage:
# build host llvm and clang first
# cmake -DCMAKE_TOOLCHAIN_FILE=../lldb/cmake/platforms/Android.cmake \
# -DANDROID_TOOLCHAIN_DIR=<toolchain_dir> \
# -DANDROID_ABI=<target_abi> \
# -DCMAKE_CXX_COMPILER_VERSION=<gcc_version> \
# -DLLVM_TARGET_ARCH=<llvm_target_arch> \
# -DLLVM_TARGETS_TO_BUILD=<llvm_targets_to_build> \
# -DLLVM_TABLEGEN=<path_to_llvm-tblgen> \
# -DCLANG_TABLEGEN=<path_to_clang-tblgen>
#
# Current Support:
# ANDROID_ABI = x86, x86_64
# CMAKE_CXX_COMPILER_VERSION = 4.9
# LLVM_TARGET_ARCH = X86
# LLVM_TARGETS_TO_BUILD = X86
# LLVM_TABLEGEN = path to host llvm-tblgen
# CLANG_TABLEGEN = path to host clang-tblgen
if( DEFINED CMAKE_CROSSCOMPILING )
return()
endif()
get_property( IS_IN_TRY_COMPILE GLOBAL PROPERTY IN_TRY_COMPILE )
if( IS_IN_TRY_COMPILE )
# this seems necessary and works fine but I'm unsure if it breaks anything
return()
endif()
set( CMAKE_SYSTEM_NAME Android )
include( CMakeForceCompiler )
# flags and definitions
add_definitions( -DANDROID -DLLDB_DISABLE_LIBEDIT )
set( ANDROID True )
set( LLDB_DEFAULT_DISABLE_LIBEDIT True )
# linking lldb-server statically for Android avoids the need to ship two
# binaries (pie for API 21+ and non-pie for API 16-). It's possible to use
# a non-pie shim on API 16-, but that requires lldb-server to dynamically export
# its symbols, which significantly increases the binary size. Static linking, on
# the other hand, has little to no effect on the binary size.
if( NOT DEFINED LLVM_BUILD_STATIC )
set( LLVM_BUILD_STATIC True CACHE INTERNAL "" FORCE )
set( LLVM_ENABLE_PIC FALSE CACHE INTERNAL "" FORCE )
set( BUILD_SHARED_LIBS FALSE CACHE INTERNAL "" FORCE )
endif()
set( ANDROID_ABI "${ANDROID_ABI}" CACHE INTERNAL "Android Abi" FORCE )
if( ANDROID_ABI STREQUAL "x86" )
set( CMAKE_SYSTEM_PROCESSOR "i686" )
set( ANDROID_TOOLCHAIN_NAME "i686-linux-android" )
elseif( ANDROID_ABI STREQUAL "x86_64" )
set( CMAKE_SYSTEM_PROCESSOR "x86_64" )
set( ANDROID_TOOLCHAIN_NAME "x86_64-linux-android" )
elseif( ANDROID_ABI STREQUAL "armeabi" )
set( CMAKE_SYSTEM_PROCESSOR "armv5te" )
set( ANDROID_TOOLCHAIN_NAME "arm-linux-androideabi" )
elseif( ANDROID_ABI STREQUAL "aarch64" )
set( CMAKE_SYSTEM_PROCESSOR "aarch64" )
set( ANDROID_TOOLCHAIN_NAME "aarch64-linux-android" )
elseif( ANDROID_ABI STREQUAL "mips" )
set( CMAKE_SYSTEM_PROCESSOR "mips" )
set( ANDROID_TOOLCHAIN_NAME "mipsel-linux-android" )
elseif( ANDROID_ABI STREQUAL "mips64" )
set( CMAKE_SYSTEM_PROCESSOR "mips64" )
set( ANDROID_TOOLCHAIN_NAME "mips64el-linux-android" )
else()
message( SEND_ERROR "Unknown ANDROID_ABI = \"${ANDROID_ABI}\"." )
endif()
set( ANDROID_TOOLCHAIN_DIR "${ANDROID_TOOLCHAIN_DIR}" CACHE PATH "Android standalone toolchain directory" )
set( ANDROID_SYSROOT "${ANDROID_TOOLCHAIN_DIR}/sysroot" CACHE PATH "Android Sysroot" )
# CMAKE_EXECUTABLE_SUFFIX is undefined in CMAKE_TOOLCHAIN_FILE
if( WIN32 )
set( EXECUTABLE_SUFFIX ".exe" )
endif()
set( PYTHON_EXECUTABLE "${ANDROID_TOOLCHAIN_DIR}/bin/python${EXECUTABLE_SUFFIX}" CACHE PATH "Python exec path" )
if( NOT CMAKE_C_COMPILER )
set( CMAKE_C_COMPILER "${ANDROID_TOOLCHAIN_DIR}/bin/${ANDROID_TOOLCHAIN_NAME}-gcc${EXECUTABLE_SUFFIX}" CACHE PATH "C compiler" )
set( CMAKE_CXX_COMPILER "${ANDROID_TOOLCHAIN_DIR}/bin/${ANDROID_TOOLCHAIN_NAME}-g++${EXECUTABLE_SUFFIX}" CACHE PATH "C++ compiler" )
set( CMAKE_ASM_COMPILER "${ANDROID_TOOLCHAIN_DIR}/bin/${ANDROID_TOOLCHAIN_NAME}-gcc${EXECUTABLE_SUFFIX}" CACHE PATH "assembler" )
set( CMAKE_STRIP "${ANDROID_TOOLCHAIN_DIR}/bin/${ANDROID_TOOLCHAIN_NAME}-strip${EXECUTABLE_SUFFIX}" CACHE PATH "strip" )
set( CMAKE_AR "${ANDROID_TOOLCHAIN_DIR}/bin/${ANDROID_TOOLCHAIN_NAME}-ar${EXECUTABLE_SUFFIX}" CACHE PATH "archive" )
set( CMAKE_LINKER "${ANDROID_TOOLCHAIN_DIR}/bin/${ANDROID_TOOLCHAIN_NAME}-ld${EXECUTABLE_SUFFIX}" CACHE PATH "linker" )
set( CMAKE_NM "${ANDROID_TOOLCHAIN_DIR}/bin/${ANDROID_TOOLCHAIN_NAME}-nm${EXECUTABLE_SUFFIX}" CACHE PATH "nm" )
set( CMAKE_OBJCOPY "${ANDROID_TOOLCHAIN_DIR}/bin/${ANDROID_TOOLCHAIN_NAME}-objcopy${EXECUTABLE_SUFFIX}" CACHE PATH "objcopy" )
set( CMAKE_OBJDUMP "${ANDROID_TOOLCHAIN_DIR}/bin/${ANDROID_TOOLCHAIN_NAME}-objdump${EXECUTABLE_SUFFIX}" CACHE PATH "objdump" )
set( CMAKE_RANLIB "${ANDROID_TOOLCHAIN_DIR}/bin/${ANDROID_TOOLCHAIN_NAME}-ranlib${EXECUTABLE_SUFFIX}" CACHE PATH "ranlib" )
endif()
set( ANDROID_CXX_FLAGS "--sysroot=${ANDROID_SYSROOT} -funwind-tables -fsigned-char -no-canonical-prefixes" )
# TODO: different ARM abi have different flags such as neon, vfpv etc
if( X86 )
set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funswitch-loops -finline-limit=300" )
elseif( ANDROID_ABI STREQUAL "armeabi" )
# 64 bit atomic operations used in c++ libraries require armv7-a instructions
# armv5te and armv6 were tried but do not work.
set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -march=armv7-a -mthumb" )
elseif( ANDROID_ABI STREQUAL "mips" )
# http://b.android.com/182094
list( FIND LLDB_SYSTEM_LIBS atomic index )
if( index EQUAL -1 )
list( APPEND LLDB_SYSTEM_LIBS atomic )
set( LLDB_SYSTEM_LIBS ${LLDB_SYSTEM_LIBS} CACHE INTERNAL "" FORCE )
endif()
endif()
# Use gold linker and enable safe ICF in case of x86, x86_64 and arm
if ( ANDROID_ABI STREQUAL "x86" OR
ANDROID_ABI STREQUAL "x86_64" OR
ANDROID_ABI STREQUAL "armeabi")
set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -fuse-ld=gold -Wl,--icf=safe" )
endif()
if( NOT LLVM_BUILD_STATIC )
# PIE is required for API 21+ so we enable it if we're not statically linking
# unfortunately, it is not supported before API 16 so we need to do something
# else there see http://llvm.org/pr23457
set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -pie -fPIE" )
endif()
# linker flags
set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fdata-sections -ffunction-sections" )
set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,--gc-sections" )
# cache flags
set( CMAKE_CXX_FLAGS "" CACHE STRING "c++ flags" )
set( CMAKE_C_FLAGS "" CACHE STRING "c flags" )
set( CMAKE_EXE_LINKER_FLAGS "-Wl,-z,nocopyreloc" CACHE STRING "executable linker flags" )
set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS}" CACHE INTERNAL "Android c/c++ flags" )
set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS}" CACHE INTERNAL "Android c/c++ linker flags" )
# final flags
set( CMAKE_CXX_FLAGS "${ANDROID_CXX_FLAGS} ${CMAKE_CXX_FLAGS}" )
set( CMAKE_C_FLAGS "${ANDROID_CXX_FLAGS} ${CMAKE_C_FLAGS}" )
set( CMAKE_EXE_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} ${CMAKE_EXE_LINKER_FLAGS}" )
# global includes and link directories
set( ANDROID_INCLUDE_DIRS "${ANDROID_TOOLCHAIN_DIR}/include/c++/${ANDROID_COMPILER_VERSION}" )
list( APPEND ANDROID_INCLUDE_DIRS "${ANDROID_TOOLCHAIN_DIR}/include/python2.7" )
include_directories( SYSTEM "${ANDROID_SYSROOT}/usr/include" ${ANDROID_INCLUDE_DIRS} )
# target environment
set( CMAKE_FIND_ROOT_PATH "${ANDROID_TOOLCHAIN_DIR}/bin" "${ANDROID_TOOLCHAIN_DIR}/${ANDROID_TOOLCHAIN_NAME}" "${ANDROID_SYSROOT}" )
# only search for libraries and includes in the ndk toolchain
set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY )
set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY )
set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY )

View File

@ -0,0 +1,48 @@
""" Adds the 'toggle-disassembly' command to switch you into a disassembly only mode """
import lldb
class DisassemblyMode:
def __init__(self, debugger, unused):
self.dbg = debugger
self.interp = debugger.GetCommandInterpreter()
self.store_state()
self.mode_off = True
def store_state(self):
self.dis_count = self.get_string_value("stop-disassembly-count")
self.dis_display = self.get_string_value("stop-disassembly-display")
self.before_count = self.get_string_value("stop-line-count-before")
self.after_count = self.get_string_value("stop-line-count-after")
def get_string_value(self, setting):
result = lldb.SBCommandReturnObject()
self.interp.HandleCommand("settings show " + setting, result)
value = result.GetOutput().split(" = ")[1].rstrip("\n")
return value
def set_value(self, setting, value):
result = lldb.SBCommandReturnObject()
self.interp.HandleCommand("settings set " + setting + " " + value, result)
def __call__(self, debugger, command, exe_ctx, result):
if self.mode_off:
self.mode_off = False
self.store_state()
self.set_value("stop-disassembly-display","always")
self.set_value("stop-disassembly-count", "8")
self.set_value("stop-line-count-before", "0")
self.set_value("stop-line-count-after", "0")
result.AppendMessage("Disassembly mode on.")
else:
self.mode_off = True
self.set_value("stop-disassembly-display",self.dis_display)
self.set_value("stop-disassembly-count", self.dis_count)
self.set_value("stop-line-count-before", self.before_count)
self.set_value("stop-line-count-after", self.after_count)
result.AppendMessage("Disassembly mode off.")
def get_short_help(self):
return "Toggles between a disassembly only mode and normal source mode\n"
def __lldb_init_module(debugger, unused):
debugger.HandleCommand("command script add -c disassembly_mode.DisassemblyMode toggle-disassembly")

View File

@ -63,6 +63,8 @@
#include "lldb/API/SBThread.h"
#include "lldb/API/SBThreadCollection.h"
#include "lldb/API/SBThreadPlan.h"
#include "lldb/API/SBTrace.h"
#include "lldb/API/SBTraceOptions.h"
#include "lldb/API/SBType.h"
#include "lldb/API/SBTypeCategory.h"
#include "lldb/API/SBTypeEnumMember.h"

View File

@ -79,6 +79,8 @@ class LLDB_API SBTarget;
class LLDB_API SBThread;
class LLDB_API SBThreadCollection;
class LLDB_API SBThreadPlan;
class LLDB_API SBTrace;
class LLDB_API SBTraceOptions;
class LLDB_API SBType;
class LLDB_API SBTypeCategory;
class LLDB_API SBTypeEnumMember;

View File

@ -61,6 +61,7 @@ class LLDB_API SBError {
friend class SBProcess;
friend class SBStructuredData;
friend class SBThread;
friend class SBTrace;
friend class SBTarget;
friend class SBValue;
friend class SBWatchpoint;

View File

@ -234,6 +234,33 @@ class LLDB_API SBProcess {
bool GetDescription(lldb::SBStream &description);
//------------------------------------------------------------------
/// Start Tracing with the given SBTraceOptions.
///
/// @param[in] options
/// Class containing trace options like trace buffer size, meta
/// data buffer size, TraceType and any custom parameters
/// {formatted as a JSON Dictionary}. In case of errors in
/// formatting, an error would be reported.
/// It must be noted that tracing options such as buffer sizes
/// or other custom parameters passed maybe invalid for some
/// trace technologies. In such cases the trace implementations
/// could choose to either throw an error or could round off to
/// the nearest valid options to start tracing if the passed
/// value is not supported. To obtain the actual used trace
/// options please use the GetTraceConfig API. For the custom
/// parameters, only the parameters recognized by the target
/// would be used and others would be ignored.
///
/// @param[out] error
/// An error explaining what went wrong.
///
/// @return
/// A SBTrace instance, which should be used
/// to get the trace data or other trace related operations.
//------------------------------------------------------------------
lldb::SBTrace StartTrace(SBTraceOptions &options, lldb::SBError &error);
uint32_t GetNumSupportedHardwareWatchpoints(lldb::SBError &error) const;
//------------------------------------------------------------------

View File

@ -13,8 +13,6 @@
#include "lldb/API/SBDefines.h"
#include "lldb/API/SBModule.h"
class StructuredDataImpl;
namespace lldb {
class SBStructuredData {
@ -31,14 +29,18 @@ class SBStructuredData {
bool IsValid() const;
lldb::SBError SetFromJSON(lldb::SBStream &stream);
void Clear();
lldb::SBError GetAsJSON(lldb::SBStream &stream) const;
lldb::SBError GetDescription(lldb::SBStream &stream) const;
private:
std::unique_ptr<StructuredDataImpl> m_impl_up;
protected:
friend class SBTraceOptions;
StructuredDataImplUP m_impl_up;
};
}

122
include/lldb/API/SBTrace.h Normal file
View File

@ -0,0 +1,122 @@
//===-- SBTrace.h -----------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLDB_SBTrace_h_
#define LLDB_SBTrace_h_
#include "lldb/API/SBDefines.h"
#include "lldb/API/SBError.h"
class TraceImpl;
namespace lldb {
class LLDB_API SBTrace {
public:
SBTrace();
//------------------------------------------------------------------
/// Obtain the trace data as raw bytes.
///
/// @param[out] error
/// An error explaining what went wrong.
///
/// @param[in] buf
/// Buffer to write the trace data to.
///
/// @param[in] size
/// The size of the buffer used to read the data. This is
/// also the size of the data intended to read. It is also
/// possible to partially read the trace data for some trace
/// technologies by specifying a smaller buffer.
///
/// @param[in] offset
/// The start offset to begin reading the trace data.
///
/// @param[in] thread_id
/// Tracing could be started for the complete process or a
/// single thread, in the first case the uid obtained would
/// map to all the threads existing within the process and the
/// ones spawning later. The thread_id parameter can be used in
/// such a scenario to select the trace data for a specific
/// thread.
///
/// @return
/// The size of the trace data effectively read by the API call.
//------------------------------------------------------------------
size_t GetTraceData(SBError &error, void *buf, size_t size, size_t offset = 0,
lldb::tid_t thread_id = LLDB_INVALID_THREAD_ID);
//------------------------------------------------------------------
/// Obtain any meta data as raw bytes for the tracing instance.
/// The input parameter definition is similar to the previous
/// function.
//------------------------------------------------------------------
size_t GetMetaData(SBError &error, void *buf, size_t size, size_t offset = 0,
lldb::tid_t thread_id = LLDB_INVALID_THREAD_ID);
//------------------------------------------------------------------
/// Stop the tracing instance. Stopping the trace will also
/// lead to deletion of any gathered trace data.
///
/// @param[out] error
/// An error explaining what went wrong.
///
/// @param[in] thread_id
/// The user id could map to a tracing instance for a thread
/// or could also map to a group of threads being traced with
/// the same trace options. A thread_id is normally optional
/// except in the case of tracing a complete process and tracing
/// needs to switched off on a particular thread.
/// A situation could occur where initially a thread (lets say
/// thread A) is being individually traced with a particular uid
/// and then tracing is started on the complete process, in this
/// case thread A will continue without any change. All newly
/// spawned threads would be traced with the uid of the process.
/// Now if the StopTrace API is called for the whole process,
/// thread A will not be stopped and must be stopped separately.
//------------------------------------------------------------------
void StopTrace(SBError &error,
lldb::tid_t thread_id = LLDB_INVALID_THREAD_ID);
//------------------------------------------------------------------
/// Get the trace configuration being used for the trace instance.
/// The threadid in the SBTraceOptions needs to be set when the
/// configuration used by a specific thread is being requested.
///
/// @param[out] options
/// The trace options actually used by the trace instance
/// would be filled by the API.
///
/// @param[out] error
/// An error explaining what went wrong.
//------------------------------------------------------------------
void GetTraceConfig(SBTraceOptions &options, SBError &error);
lldb::user_id_t GetTraceUID();
bool IsValid();
protected:
typedef std::shared_ptr<TraceImpl> TraceImplSP;
friend class SBProcess;
void SetTraceUID(lldb::user_id_t uid);
TraceImplSP m_trace_impl_sp;
lldb::ProcessSP GetSP() const;
void SetSP(const ProcessSP &process_sp);
lldb::ProcessWP m_opaque_wp;
};
} // namespace lldb
#endif // LLDB_SBTrace_h_

View File

@ -0,0 +1,58 @@
//===-- SBTraceOptions ------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef SBTRACEOPTIONS_H_
#define SBTRACEOPTIONS_H_
#include "lldb/API/SBDefines.h"
namespace lldb {
class LLDB_API SBTraceOptions {
public:
SBTraceOptions();
lldb::TraceType getType() const;
uint64_t getTraceBufferSize() const;
/// The trace parameters consist of any custom parameters
/// apart from the generic parameters such as
/// TraceType, trace_buffer_size and meta_data_buffer_size.
/// The returned parameters would be formatted as a JSON Dictionary.
lldb::SBStructuredData getTraceParams(lldb::SBError &error);
uint64_t getMetaDataBufferSize() const;
/// SBStructuredData is meant to hold any custom parameters
/// apart from meta buffer size and trace size. They should
/// be formatted as a JSON Dictionary.
void setTraceParams(lldb::SBStructuredData &params);
void setType(lldb::TraceType type);
void setTraceBufferSize(uint64_t size);
void setMetaDataBufferSize(uint64_t size);
void setThreadID(lldb::tid_t thread_id);
lldb::tid_t getThreadID();
bool IsValid();
protected:
friend class SBProcess;
friend class SBTrace;
lldb::TraceOptionsSP m_traceoptions_sp;
};
}
#endif /* SBTRACEOPTIONS_H_ */

View File

@ -0,0 +1,95 @@
//===-- StructuredDataImpl.h ------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef liblldb_StructuredDataImpl_h_
#define liblldb_StructuredDataImpl_h_
#include "lldb/Core/Event.h"
#include "lldb/Core/StructuredData.h"
#include "lldb/Utility/Error.h"
#include "lldb/Utility/Stream.h"
#include "lldb/Target/StructuredDataPlugin.h"
#include "lldb/lldb-forward.h"
#pragma mark--
#pragma mark StructuredDataImpl
namespace lldb_private {
class StructuredDataImpl {
public:
StructuredDataImpl() : m_plugin_wp(), m_data_sp() {}
StructuredDataImpl(const StructuredDataImpl &rhs) = default;
StructuredDataImpl(const lldb::EventSP &event_sp)
: m_plugin_wp(
EventDataStructuredData::GetPluginFromEvent(event_sp.get())),
m_data_sp(EventDataStructuredData::GetObjectFromEvent(event_sp.get())) {
}
~StructuredDataImpl() = default;
StructuredDataImpl &operator=(const StructuredDataImpl &rhs) = default;
bool IsValid() const { return m_data_sp.get() != nullptr; }
void Clear() {
m_plugin_wp.reset();
m_data_sp.reset();
}
Error GetAsJSON(Stream &stream) const {
Error error;
if (!m_data_sp) {
error.SetErrorString("No structured data.");
return error;
}
m_data_sp->Dump(stream);
return error;
}
Error GetDescription(Stream &stream) const {
Error error;
if (!m_data_sp) {
error.SetErrorString("Cannot pretty print structured data: "
"no data to print.");
return error;
}
// Grab the plugin.
auto plugin_sp = lldb::StructuredDataPluginSP(m_plugin_wp);
if (!plugin_sp) {
error.SetErrorString("Cannot pretty print structured data: "
"plugin doesn't exist.");
return error;
}
// Get the data's description.
return plugin_sp->GetDescription(m_data_sp, stream);
}
StructuredData::ObjectSP GetObjectSP() {
return m_data_sp;
}
void SetObjectSP(const StructuredData::ObjectSP &obj) {
m_data_sp = obj;
}
private:
lldb::StructuredDataPluginWP m_plugin_wp;
StructuredData::ObjectSP m_data_sp;
};
}
#endif

View File

@ -0,0 +1,62 @@
//===-- TraceOptions.h ------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef liblldb_TraceOptions_h_
#define liblldb_TraceOptions_h_
#include "lldb/lldb-defines.h"
#include "lldb/lldb-enumerations.h"
#include "lldb/Core/StructuredData.h"
namespace lldb_private {
class TraceOptions {
public:
TraceOptions()
: m_trace_params(new StructuredData::Dictionary()) {}
const StructuredData::DictionarySP &getTraceParams() const {
return m_trace_params;
}
lldb::TraceType getType() const { return m_type; }
uint64_t getTraceBufferSize() const { return m_trace_buffer_size; }
uint64_t getMetaDataBufferSize() const { return m_meta_data_buffer_size; }
void setTraceParams(const StructuredData::DictionarySP &dict_obj) {
m_trace_params = dict_obj;
}
void setType(lldb::TraceType type) { m_type = type; }
void setTraceBufferSize(uint64_t size) { m_trace_buffer_size = size; }
void setMetaDataBufferSize(uint64_t size) { m_meta_data_buffer_size = size; }
void setThreadID(lldb::tid_t thread_id) { m_thread_id = thread_id; }
lldb::tid_t getThreadID() { return m_thread_id; }
private:
lldb::TraceType m_type;
uint64_t m_trace_buffer_size;
uint64_t m_meta_data_buffer_size;
lldb::tid_t m_thread_id;
/// m_trace_params is meant to hold any custom parameters
/// apart from meta buffer size and trace size.
/// The interpretation of such parameters is left to
/// the lldb-server.
StructuredData::DictionarySP m_trace_params;
};
}
#endif // liblldb_TraceOptions_h_

View File

@ -27,6 +27,7 @@
#include "lldb/lldb-private-enumerations.h" // for AddressType
#include "lldb/lldb-types.h" // for addr_t, offs...
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h" // for StringRef
@ -37,7 +38,6 @@
#include <mutex> // for recursive_mutex
#include <string> // for string
#include <utility> // for pair
#include <vector>
#include <stddef.h> // for size_t
#include <stdint.h> // for uint32_t
@ -489,35 +489,19 @@ class ValueObject : public UserID {
virtual lldb::ValueObjectSP GetChildAtIndex(size_t idx, bool can_create);
// this will always create the children if necessary
lldb::ValueObjectSP
GetChildAtIndexPath(const std::initializer_list<size_t> &idxs,
size_t *index_of_error = nullptr);
lldb::ValueObjectSP GetChildAtIndexPath(const std::vector<size_t> &idxs,
lldb::ValueObjectSP GetChildAtIndexPath(llvm::ArrayRef<size_t> idxs,
size_t *index_of_error = nullptr);
lldb::ValueObjectSP GetChildAtIndexPath(
const std::initializer_list<std::pair<size_t, bool>> &idxs,
size_t *index_of_error = nullptr);
lldb::ValueObjectSP
GetChildAtIndexPath(const std::vector<std::pair<size_t, bool>> &idxs,
GetChildAtIndexPath(llvm::ArrayRef<std::pair<size_t, bool>> idxs,
size_t *index_of_error = nullptr);
// this will always create the children if necessary
lldb::ValueObjectSP
GetChildAtNamePath(const std::initializer_list<ConstString> &names,
ConstString *name_of_error = nullptr);
lldb::ValueObjectSP GetChildAtNamePath(const std::vector<ConstString> &names,
lldb::ValueObjectSP GetChildAtNamePath(llvm::ArrayRef<ConstString> names,
ConstString *name_of_error = nullptr);
lldb::ValueObjectSP GetChildAtNamePath(
const std::initializer_list<std::pair<ConstString, bool>> &names,
ConstString *name_of_error = nullptr);
lldb::ValueObjectSP
GetChildAtNamePath(const std::vector<std::pair<ConstString, bool>> &names,
GetChildAtNamePath(llvm::ArrayRef<std::pair<ConstString, bool>> names,
ConstString *name_of_error = nullptr);
virtual lldb::ValueObjectSP GetChildMemberWithName(const ConstString &name,

View File

@ -41,8 +41,9 @@ class SocketAddress {
//----------------------------------------------------------------------------
// Static method to get all address information for a host and/or service
//----------------------------------------------------------------------------
static std::vector<SocketAddress> GetAddressInfo(const char *hostname,
const char *servname);
static std::vector<SocketAddress>
GetAddressInfo(const char *hostname, const char *servname, int ai_family,
int ai_socktype, int ai_protocol, int ai_flags = 0);
//------------------------------------------------------------------
// Constructors and Destructors

View File

@ -36,6 +36,7 @@
#include "lldb/Core/PluginInterface.h"
#include "lldb/Core/StructuredData.h"
#include "lldb/Core/ThreadSafeValue.h"
#include "lldb/Core/TraceOptions.h"
#include "lldb/Core/UserSettingsController.h"
#include "lldb/Host/HostThread.h"
#include "lldb/Host/ProcessRunLock.h"
@ -2766,6 +2767,79 @@ class Process : public std::enable_shared_from_this<Process>,
lldb::StructuredDataPluginSP
GetStructuredDataPlugin(const ConstString &type_name) const;
//------------------------------------------------------------------
/// Starts tracing with the configuration provided in options. To
/// enable tracing on the complete process the thread_id in the
/// options should be set to LLDB_INVALID_THREAD_ID. The API returns
/// a user_id which is needed by other API's that manipulate the
/// trace instance.
/// The handling of erroneous or unsupported configuration is left
/// to the trace technology implementations in the server, as they
/// could be returned as an error, or rounded to a valid
/// configuration to start tracing. In the later case the
/// GetTraceConfig should supply the actual used trace
/// configuration.
//------------------------------------------------------------------
virtual lldb::user_id_t StartTrace(lldb::TraceOptionsSP &options,
Error &error) {
error.SetErrorString("Not implemented");
return LLDB_INVALID_UID;
}
//------------------------------------------------------------------
/// Stops the tracing instance leading to deletion of the trace
/// data. The tracing instance is identified by the user_id which
/// is obtained when tracing was started from the StartTrace.
/// In case tracing of the complete process needs to be stopped
/// the thread_id should be set to LLDB_INVALID_THREAD_ID.
/// In the other case that tracing on an individual thread needs
/// to be stopped a thread_id can be supplied.
//------------------------------------------------------------------
virtual void StopTrace(lldb::user_id_t uid, lldb::tid_t thread_id,
Error &error) {
error.SetErrorString("Not implemented");
}
//------------------------------------------------------------------
/// Provides the trace data as raw bytes. A buffer needs to be
/// supplied to copy the trace data. The exact behavior of this API
/// may vary across trace technology, as some may support partial
/// reading of the trace data from a specified offset while some
/// may not. The thread_id should be used to select a particular
/// thread for trace extraction.
//------------------------------------------------------------------
virtual size_t GetData(lldb::user_id_t uid, lldb::tid_t thread_id,
Error &error, void *buf, size_t size,
size_t offset = 0) {
error.SetErrorString("Not implemented");
return 0;
}
//------------------------------------------------------------------
/// Similar API as above except for obtaining meta data
//------------------------------------------------------------------
virtual size_t GetMetaData(lldb::user_id_t uid, lldb::tid_t thread_id,
Error &error, void *buf, size_t size,
size_t offset = 0) {
error.SetErrorString("Not implemented");
return 0;
}
//------------------------------------------------------------------
/// API to obtain the trace configuration used by a trace instance.
/// Configurations that may be specific to some trace technology
/// should be stored in the custom parameters. The options are
/// transported to the server, which shall interpret accordingly.
/// The thread_id can be specified in the options to obtain the
/// configuration used by a specific thread. The thread_id specified
/// should also match the uid otherwise an error will be returned.
//------------------------------------------------------------------
virtual void GetTraceConfig(lldb::user_id_t uid, Error &error,
lldb::TraceOptionsSP &options) {
error.SetErrorString("Not implemented");
return;
}
protected:
void SetState(lldb::EventSP &event_sp);

View File

@ -718,6 +718,13 @@ enum BasicType {
eBasicTypeOther
};
enum TraceType {
eTraceTypeNone = 0,
// Hardware Trace generated by the processor.
eTraceTypeProcessorTrace
};
FLAGS_ENUM(TypeClass){
eTypeClassInvalid = (0u), eTypeClassArray = (1u << 0),
eTypeClassBlockPointer = (1u << 1), eTypeClassBuiltin = (1u << 2),

View File

@ -215,6 +215,7 @@ class StreamFile;
class StreamString;
class StringList;
struct StringSummaryFormat;
class StructuredDataImpl;
class StructuredDataPlugin;
class SystemRuntime;
class TypeSummaryImpl;
@ -254,6 +255,7 @@ class ThreadPlanStepRange;
class ThreadPlanStepThrough;
class ThreadPlanTracer;
class ThreadSpec;
class TraceOptions;
class Type;
class TypeAndOrName;
class TypeCategoryMap;
@ -430,6 +432,7 @@ typedef std::weak_ptr<lldb_private::Stream> StreamWP;
typedef std::shared_ptr<lldb_private::StreamFile> StreamFileSP;
typedef std::shared_ptr<lldb_private::StringSummaryFormat>
StringTypeSummaryImplSP;
typedef std::unique_ptr<lldb_private::StructuredDataImpl> StructuredDataImplUP;
typedef std::shared_ptr<lldb_private::StructuredDataPlugin>
StructuredDataPluginSP;
typedef std::weak_ptr<lldb_private::StructuredDataPlugin>
@ -451,6 +454,7 @@ typedef std::weak_ptr<lldb_private::Thread> ThreadWP;
typedef std::shared_ptr<lldb_private::ThreadCollection> ThreadCollectionSP;
typedef std::shared_ptr<lldb_private::ThreadPlan> ThreadPlanSP;
typedef std::shared_ptr<lldb_private::ThreadPlanTracer> ThreadPlanTracerSP;
typedef std::shared_ptr<lldb_private::TraceOptions> TraceOptionsSP;
typedef std::shared_ptr<lldb_private::Type> TypeSP;
typedef std::weak_ptr<lldb_private::Type> TypeWP;
typedef std::shared_ptr<lldb_private::TypeCategoryImpl> TypeCategoryImplSP;

View File

@ -17,7 +17,7 @@ class NoreturnUnwind(TestBase):
mydir = TestBase.compute_mydir(__file__)
@skipIfWindows # clang-cl does not support gcc style attributes.
@expectedFailureAndroid(bugnumber="llvm.org/pr31192", archs=["x86_64"])
@expectedFailureAndroid(bugnumber="llvm.org/pr31192")
@expectedFailureAll(bugnumber="llvm.org/pr31192", oslist=['linux'], compiler="gcc", archs=['arm'])
def test(self):
"""Test that we can backtrace correctly with 'noreturn' functions on the stack"""

View File

@ -89,7 +89,7 @@ def test(self):
# resolve_location=True, read=False, write=True
write_watchpoint = write_value.Watch(True, False, True, error)
self.assertTrue(read_watchpoint, "Failed to set write watchpoint.")
self.assertTrue(write_watchpoint, "Failed to set write watchpoint.")
self.assertTrue(error.Success(),
"Error while setting watchpoint: %s" %
error.GetCString())

View File

@ -5,6 +5,11 @@ inline void test2(int) __attribute__ ((always_inline));
void test2(int b) {
printf("test2(%d)\n", b); //% self.expect("expression b", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["42"])
{
int c = b * 2;
printf("c=%d\n", c); //% self.expect("expression b", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["42"])
//% self.expect("expression c", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["84"])
}
}
void test1(int a) {

View File

@ -61,7 +61,7 @@ def test_with_run_command(self):
bugnumber="Compiler emits incomplete debug info")
@expectedFailureAll(
compiler=["clang"],
compiler_version=["<", "3.8"],
compiler_version=["<", "3.9"],
bugnumber='llvm.org/pr20550')
@add_test_categories(['pyapi'])
def test_with_python_api(self):

View File

@ -0,0 +1,3 @@
LEVEL = ../../../make
CXX_SOURCES := main.cpp
include $(LEVEL)/Makefile.rules

View File

@ -0,0 +1,7 @@
from lldbsuite.test import lldbinline
from lldbsuite.test import decorators
lldbinline.MakeInlineTest(
__file__, globals(), [
decorators.expectedFailureAll(
oslist=["windows"], bugnumber="llvm.org/pr24764")])

View File

@ -0,0 +1,36 @@
//===-- main.cpp ------------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LIDENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
namespace n {
struct D {
int i;
static int anInt() { return 2; }
int dump() { return i; }
};
class C {
public:
int foo(D *D);
};
}
using namespace n;
int C::foo(D* D) {
return D->dump(); //% self.expect("expression -- D->dump()", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["int", "2"])
//% self.expect("expression -- D::anInt()", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["int", "2"])
}
int main (int argc, char const *argv[])
{
D myD { D::anInt() };
C().foo(&myD);
return 0;
}

View File

@ -111,8 +111,8 @@ def test_with_run_command(self):
test_result = frame.EvaluateExpression("imported")
self.assertTrue(
test_result.IsValid() and test_result.GetError().Fail(),
"imported is ambiguous")
test_result.IsValid() and test_result.GetValueAsSigned() == 99,
"imported = 99")
test_result = frame.EvaluateExpression("single")
self.assertTrue(

View File

@ -0,0 +1,3 @@
LEVEL = ../../../make
CXX_SOURCES := main.cpp
include $(LEVEL)/Makefile.rules

View File

@ -0,0 +1,7 @@
from lldbsuite.test import lldbinline
from lldbsuite.test import decorators
lldbinline.MakeInlineTest(
__file__, globals(), [
decorators.expectedFailureAll(
oslist=["windows"], bugnumber="llvm.org/pr24764")])

View File

@ -0,0 +1,40 @@
//===-- main.cpp ------------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LIDENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
void *D = 0;
class D {
static int i;
};
int D::i = 3;
namespace errno {
int j = 4;
};
int twice(int n)
{
return n * 2; //% self.expect("expression -- D::i", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["int", "3"])
//% self.expect("expression -- D", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["void"])
//% self.expect("expression -- errno::j", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["int", "4"])
}
const char getAChar()
{
const char D[] = "Hello world";
return D[0]; //% self.expect("expression -- D::i", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["int", "3"])
//% self.expect("expression -- D", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["char", "Hello"])
}
int main (int argc, char const *argv[])
{
int six = twice(3);
return 0;
}

View File

@ -408,6 +408,9 @@ public:
lldb::SBError
SaveCore(const char *file_name);
lldb::SBTrace
StartTrace(SBTraceOptions &options, lldb::SBError &error);
lldb::SBError
GetMemoryRegionInfo(lldb::addr_t load_addr, lldb::SBMemoryRegionInfo &region_info);

View File

@ -38,5 +38,8 @@ namespace lldb {
lldb::SBError
GetDescription(lldb::SBStream &stream) const;
lldb::SBError
SetFromJSON(lldb::SBStream &stream);
};
}

View File

@ -0,0 +1,34 @@
//===-- SWIG Interface for SBTrace.h ----------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
namespace lldb {
class LLDB_API SBTrace {
public:
SBTrace();
size_t GetTraceData(SBError &error, void *buf,
size_t size, size_t offset,
lldb::tid_t thread_id);
size_t GetMetaData(SBError &error, void *buf,
size_t size, size_t offset,
lldb::tid_t thread_id);
void StopTrace(SBError &error,
lldb::tid_t thread_id);
void GetTraceConfig(SBTraceOptions &options,
SBError &error);
lldb::user_id_t GetTraceUID();
bool IsValid();
};
} // namespace lldb

View File

@ -0,0 +1,38 @@
//===-- SWIG Interface for SBTraceOptions -----------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
namespace lldb {
class LLDB_API SBTraceOptions {
public:
SBTraceOptions();
lldb::TraceType getType() const;
uint64_t getTraceBufferSize() const;
lldb::SBStructuredData getTraceParams(lldb::SBError &error);
uint64_t getMetaDataBufferSize() const;
void setTraceParams(lldb::SBStructuredData &params);
void setType(lldb::TraceType type);
void setTraceBufferSize(uint64_t size);
void setMetaDataBufferSize(uint64_t size);
void setThreadID(lldb::tid_t thread_id);
lldb::tid_t getThreadID();
bool IsValid();
};
}

View File

@ -103,6 +103,8 @@ import six
#include "lldb/API/SBThread.h"
#include "lldb/API/SBThreadCollection.h"
#include "lldb/API/SBThreadPlan.h"
#include "lldb/API/SBTrace.h"
#include "lldb/API/SBTraceOptions.h"
#include "lldb/API/SBType.h"
#include "lldb/API/SBTypeCategory.h"
#include "lldb/API/SBTypeEnumMember.h"
@ -186,6 +188,8 @@ import six
%include "./interface/SBThread.i"
%include "./interface/SBThreadCollection.i"
%include "./interface/SBThreadPlan.i"
%include "./interface/SBTrace.i"
%include "./interface/SBTraceOptions.i"
%include "./interface/SBType.i"
%include "./interface/SBTypeCategory.i"
%include "./interface/SBTypeEnumMember.i"

View File

@ -67,6 +67,8 @@ add_lldb_library(liblldb SHARED
SBThread.cpp
SBThreadCollection.cpp
SBThreadPlan.cpp
SBTrace.cpp
SBTraceOptions.cpp
SBType.cpp
SBTypeCategory.cpp
SBTypeEnumMember.cpp

View File

@ -44,6 +44,8 @@
#include "lldb/API/SBStructuredData.h"
#include "lldb/API/SBThread.h"
#include "lldb/API/SBThreadCollection.h"
#include "lldb/API/SBTrace.h"
#include "lldb/API/SBTraceOptions.h"
#include "lldb/API/SBUnixSignals.h"
using namespace lldb;
@ -349,6 +351,26 @@ size_t SBProcess::GetAsyncProfileData(char *dst, size_t dst_len) const {
return bytes_read;
}
lldb::SBTrace SBProcess::StartTrace(SBTraceOptions &options,
lldb::SBError &error) {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
ProcessSP process_sp(GetSP());
error.Clear();
SBTrace trace_instance;
trace_instance.SetSP(process_sp);
lldb::user_id_t uid = LLDB_INVALID_UID;
if (!process_sp) {
error.SetErrorString("invalid process");
} else {
uid = process_sp->StartTrace(options.m_traceoptions_sp, error.ref());
trace_instance.SetTraceUID(uid);
LLDB_LOG(log, "SBProcess::returned uid - %" PRIx64, uid);
}
return trace_instance;
}
void SBProcess::ReportEventState(const SBEvent &event, FILE *out) const {
if (out == NULL)
return;

View File

@ -12,6 +12,7 @@
#include "lldb/API/SBStream.h"
#include "lldb/Core/Event.h"
#include "lldb/Core/StructuredData.h"
#include "lldb/Core/StructuredDataImpl.h"
#include "lldb/Target/StructuredDataPlugin.h"
#include "lldb/Utility/Error.h"
#include "lldb/Utility/Stream.h"
@ -19,70 +20,6 @@
using namespace lldb;
using namespace lldb_private;
#pragma mark--
#pragma mark StructuredDataImpl
class StructuredDataImpl {
public:
StructuredDataImpl() : m_plugin_wp(), m_data_sp() {}
StructuredDataImpl(const StructuredDataImpl &rhs) = default;
StructuredDataImpl(const EventSP &event_sp)
: m_plugin_wp(
EventDataStructuredData::GetPluginFromEvent(event_sp.get())),
m_data_sp(EventDataStructuredData::GetObjectFromEvent(event_sp.get())) {
}
~StructuredDataImpl() = default;
StructuredDataImpl &operator=(const StructuredDataImpl &rhs) = default;
bool IsValid() const { return m_data_sp.get() != nullptr; }
void Clear() {
m_plugin_wp.reset();
m_data_sp.reset();
}
SBError GetAsJSON(lldb_private::Stream &stream) const {
SBError sb_error;
if (!m_data_sp) {
sb_error.SetErrorString("No structured data.");
return sb_error;
}
m_data_sp->Dump(stream);
return sb_error;
}
Error GetDescription(lldb_private::Stream &stream) const {
Error error;
if (!m_data_sp) {
error.SetErrorString("Cannot pretty print structured data: "
"no data to print.");
return error;
}
// Grab the plugin.
auto plugin_sp = StructuredDataPluginSP(m_plugin_wp);
if (!plugin_sp) {
error.SetErrorString("Cannot pretty print structured data: "
"plugin doesn't exist.");
return error;
}
// Get the data's description.
return plugin_sp->GetDescription(m_data_sp, stream);
}
private:
StructuredDataPluginWP m_plugin_wp;
StructuredData::ObjectSP m_data_sp;
};
#pragma mark--
#pragma mark SBStructuredData
@ -102,12 +39,26 @@ operator=(const lldb::SBStructuredData &rhs) {
return *this;
}
lldb::SBError SBStructuredData::SetFromJSON(lldb::SBStream &stream) {
lldb::SBError error;
std::string json_str(stream.GetData());
StructuredData::ObjectSP json_obj = StructuredData::ParseJSON(json_str);
m_impl_up->SetObjectSP(json_obj);
if (!json_obj || json_obj->GetType() != StructuredData::Type::eTypeDictionary)
error.SetErrorString("Invalid Syntax");
return error;
}
bool SBStructuredData::IsValid() const { return m_impl_up->IsValid(); }
void SBStructuredData::Clear() { m_impl_up->Clear(); }
SBError SBStructuredData::GetAsJSON(lldb::SBStream &stream) const {
return m_impl_up->GetAsJSON(stream.ref());
SBError error;
error.SetError(m_impl_up->GetAsJSON(stream.ref()));
return error;
}
lldb::SBError SBStructuredData::GetDescription(lldb::SBStream &stream) const {

109
source/API/SBTrace.cpp Normal file
View File

@ -0,0 +1,109 @@
//===-- SBTrace.cpp ---------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "lldb/Utility/Log.h"
#include "lldb/Target/Process.h"
#include "lldb/API/SBTrace.h"
#include "lldb/API/SBTraceOptions.h"
using namespace lldb;
using namespace lldb_private;
class TraceImpl {
public:
lldb::user_id_t uid;
};
lldb::ProcessSP SBTrace::GetSP() const { return m_opaque_wp.lock(); }
size_t SBTrace::GetTraceData(SBError &error, void *buf, size_t size,
size_t offset, lldb::tid_t thread_id) {
size_t bytes_read = 0;
ProcessSP process_sp(GetSP());
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
error.Clear();
if (!process_sp) {
error.SetErrorString("invalid process");
} else {
bytes_read = process_sp->GetData(GetTraceUID(), thread_id, error.ref(), buf,
size, offset);
LLDB_LOG(log, "SBTrace::bytes_read - %" PRIx64, bytes_read);
}
return bytes_read;
}
size_t SBTrace::GetMetaData(SBError &error, void *buf, size_t size,
size_t offset, lldb::tid_t thread_id) {
size_t bytes_read = 0;
ProcessSP process_sp(GetSP());
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
error.Clear();
if (!process_sp) {
error.SetErrorString("invalid process");
} else {
bytes_read = process_sp->GetMetaData(GetTraceUID(), thread_id, error.ref(),
buf, size, offset);
LLDB_LOG(log, "SBTrace::bytes_read - %" PRIx64, bytes_read);
}
return bytes_read;
}
void SBTrace::StopTrace(SBError &error, lldb::tid_t thread_id) {
ProcessSP process_sp(GetSP());
error.Clear();
if (!process_sp) {
error.SetErrorString("invalid process");
return;
}
process_sp->StopTrace(GetTraceUID(), thread_id, error.ref());
}
void SBTrace::GetTraceConfig(SBTraceOptions &options, SBError &error) {
ProcessSP process_sp(GetSP());
error.Clear();
if (!process_sp) {
error.SetErrorString("invalid process");
} else {
process_sp->GetTraceConfig(GetTraceUID(), error.ref(),
options.m_traceoptions_sp);
}
}
lldb::user_id_t SBTrace::GetTraceUID() {
if (m_trace_impl_sp)
return m_trace_impl_sp->uid;
return LLDB_INVALID_UID;
}
void SBTrace::SetTraceUID(lldb::user_id_t uid) {
if (m_trace_impl_sp)
m_trace_impl_sp->uid = uid;
}
SBTrace::SBTrace() {
m_trace_impl_sp.reset(new TraceImpl);
if (m_trace_impl_sp)
m_trace_impl_sp->uid = LLDB_INVALID_UID;
}
void SBTrace::SetSP(const ProcessSP &process_sp) { m_opaque_wp = process_sp; }
bool SBTrace::IsValid() {
if (!m_trace_impl_sp)
return false;
if (!GetSP())
return false;
return true;
}

View File

@ -0,0 +1,94 @@
//===-- SBTraceOptions.cpp --------------------------------------*- 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/SBTraceOptions.h"
#include "lldb/API/SBError.h"
#include "lldb/API/SBStructuredData.h"
#include "lldb/Utility/Log.h"
#include "lldb/Core/StructuredDataImpl.h"
#include "lldb/Core/TraceOptions.h"
using namespace lldb;
using namespace lldb_private;
SBTraceOptions::SBTraceOptions() {
m_traceoptions_sp.reset(new TraceOptions());
}
lldb::TraceType SBTraceOptions::getType() const {
if (m_traceoptions_sp)
return m_traceoptions_sp->getType();
return lldb::TraceType::eTraceTypeNone;
}
uint64_t SBTraceOptions::getTraceBufferSize() const {
if (m_traceoptions_sp)
return m_traceoptions_sp->getTraceBufferSize();
return 0;
}
lldb::SBStructuredData SBTraceOptions::getTraceParams(lldb::SBError &error) {
error.Clear();
const lldb_private::StructuredData::DictionarySP dict_obj =
m_traceoptions_sp->getTraceParams();
lldb::SBStructuredData structData;
if (dict_obj && structData.m_impl_up)
structData.m_impl_up->SetObjectSP(dict_obj->shared_from_this());
else
error.SetErrorString("Empty trace params");
return structData;
}
uint64_t SBTraceOptions::getMetaDataBufferSize() const {
if (m_traceoptions_sp)
return m_traceoptions_sp->getTraceBufferSize();
return 0;
}
void SBTraceOptions::setTraceParams(lldb::SBStructuredData &params) {
if (m_traceoptions_sp && params.m_impl_up) {
StructuredData::ObjectSP obj_sp = params.m_impl_up->GetObjectSP();
if (obj_sp && obj_sp->GetAsDictionary() != nullptr)
m_traceoptions_sp->setTraceParams(
std::static_pointer_cast<StructuredData::Dictionary>(obj_sp));
}
return;
}
void SBTraceOptions::setType(lldb::TraceType type) {
if (m_traceoptions_sp)
m_traceoptions_sp->setType(type);
}
void SBTraceOptions::setTraceBufferSize(uint64_t size) {
if (m_traceoptions_sp)
m_traceoptions_sp->setTraceBufferSize(size);
}
void SBTraceOptions::setMetaDataBufferSize(uint64_t size) {
if (m_traceoptions_sp)
m_traceoptions_sp->setMetaDataBufferSize(size);
}
bool SBTraceOptions::IsValid() {
if (m_traceoptions_sp)
return true;
return false;
}
void SBTraceOptions::setThreadID(lldb::tid_t thread_id) {
if (m_traceoptions_sp)
m_traceoptions_sp->setThreadID(thread_id);
}
lldb::tid_t SBTraceOptions::getThreadID() {
if (m_traceoptions_sp)
return m_traceoptions_sp->getThreadID();
return LLDB_INVALID_THREAD_ID;
}

View File

@ -481,21 +481,8 @@ ValueObjectSP ValueObject::GetChildAtIndex(size_t idx, bool can_create) {
return child_sp;
}
ValueObjectSP
ValueObject::GetChildAtIndexPath(const std::initializer_list<size_t> &idxs,
size_t *index_of_error) {
return GetChildAtIndexPath(std::vector<size_t>(idxs), index_of_error);
}
ValueObjectSP ValueObject::GetChildAtIndexPath(
const std::initializer_list<std::pair<size_t, bool>> &idxs,
size_t *index_of_error) {
return GetChildAtIndexPath(std::vector<std::pair<size_t, bool>>(idxs),
index_of_error);
}
lldb::ValueObjectSP
ValueObject::GetChildAtIndexPath(const std::vector<size_t> &idxs,
ValueObject::GetChildAtIndexPath(llvm::ArrayRef<size_t> idxs,
size_t *index_of_error) {
if (idxs.size() == 0)
return GetSP();
@ -512,7 +499,7 @@ ValueObject::GetChildAtIndexPath(const std::vector<size_t> &idxs,
}
lldb::ValueObjectSP ValueObject::GetChildAtIndexPath(
const std::vector<std::pair<size_t, bool>> &idxs, size_t *index_of_error) {
llvm::ArrayRef<std::pair<size_t, bool>> idxs, size_t *index_of_error) {
if (idxs.size() == 0)
return GetSP();
ValueObjectSP root(GetSP());
@ -528,20 +515,7 @@ lldb::ValueObjectSP ValueObject::GetChildAtIndexPath(
}
lldb::ValueObjectSP
ValueObject::GetChildAtNamePath(const std::initializer_list<ConstString> &names,
ConstString *name_of_error) {
return GetChildAtNamePath(std::vector<ConstString>(names), name_of_error);
}
lldb::ValueObjectSP ValueObject::GetChildAtNamePath(
const std::initializer_list<std::pair<ConstString, bool>> &names,
ConstString *name_of_error) {
return GetChildAtNamePath(std::vector<std::pair<ConstString, bool>>(names),
name_of_error);
}
lldb::ValueObjectSP
ValueObject::GetChildAtNamePath(const std::vector<ConstString> &names,
ValueObject::GetChildAtNamePath(llvm::ArrayRef<ConstString> names,
ConstString *name_of_error) {
if (names.size() == 0)
return GetSP();
@ -558,7 +532,7 @@ ValueObject::GetChildAtNamePath(const std::vector<ConstString> &names,
}
lldb::ValueObjectSP ValueObject::GetChildAtNamePath(
const std::vector<std::pair<ConstString, bool>> &names,
llvm::ArrayRef<std::pair<ConstString, bool>> names,
ConstString *name_of_error) {
if (names.size() == 0)
return GetSP();

View File

@ -227,6 +227,18 @@ bool SocketAddress::getaddrinfo(const char *host, const char *service,
int ai_flags) {
Clear();
auto addresses = GetAddressInfo(host, service, ai_family, ai_socktype, ai_protocol, ai_flags);
if (!addresses.empty())
*this = addresses[0];
return IsValid();
}
std::vector<SocketAddress>
SocketAddress::GetAddressInfo(const char *hostname, const char *servname,
int ai_family, int ai_socktype, int ai_protocol,
int ai_flags) {
std::vector<SocketAddress> addr_list;
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
hints.ai_family = ai_family;
@ -234,26 +246,8 @@ bool SocketAddress::getaddrinfo(const char *host, const char *service,
hints.ai_protocol = ai_protocol;
hints.ai_flags = ai_flags;
bool result = false;
struct addrinfo *service_info_list = NULL;
int err = ::getaddrinfo(host, service, &hints, &service_info_list);
if (err == 0 && service_info_list) {
*this = service_info_list;
result = IsValid();
}
if (service_info_list)
::freeaddrinfo(service_info_list);
return result;
}
std::vector<SocketAddress> SocketAddress::GetAddressInfo(const char *hostname,
const char *servname) {
std::vector<SocketAddress> addr_list;
struct addrinfo *service_info_list = NULL;
int err = ::getaddrinfo(hostname, servname, NULL, &service_info_list);
int err = ::getaddrinfo(hostname, servname, &hints, &service_info_list);
if (err == 0 && service_info_list) {
for (struct addrinfo *service_ptr = service_info_list; service_ptr != NULL;
service_ptr = service_ptr->ai_next) {

View File

@ -55,49 +55,53 @@ using namespace lldb_private;
static bool
GetFreeBSDProcessArgs(const ProcessInstanceInfoMatch *match_info_ptr,
ProcessInstanceInfo &process_info) {
if (process_info.ProcessIDIsValid()) {
int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_ARGS,
(int)process_info.GetProcessID()};
if (!process_info.ProcessIDIsValid())
return false;
char arg_data[8192];
size_t arg_data_size = sizeof(arg_data);
if (::sysctl(mib, 4, arg_data, &arg_data_size, NULL, 0) == 0) {
DataExtractor data(arg_data, arg_data_size, endian::InlHostByteOrder(),
sizeof(void *));
lldb::offset_t offset = 0;
const char *cstr;
int pid = process_info.GetProcessID();
cstr = data.GetCStr(&offset);
if (cstr) {
process_info.GetExecutableFile().SetFile(cstr, false);
int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_ARGS, pid};
if (!(match_info_ptr == NULL ||
NameMatches(
process_info.GetExecutableFile().GetFilename().GetCString(),
match_info_ptr->GetNameMatchType(),
match_info_ptr->GetProcessInfo().GetName())))
return false;
char arg_data[8192];
size_t arg_data_size = sizeof(arg_data);
if (::sysctl(mib, 4, arg_data, &arg_data_size, NULL, 0) != 0)
return false;
Args &proc_args = process_info.GetArguments();
while (1) {
const uint8_t *p = data.PeekData(offset, 1);
while ((p != NULL) && (*p == '\0') && offset < arg_data_size) {
++offset;
p = data.PeekData(offset, 1);
}
if (p == NULL || offset >= arg_data_size)
return true;
DataExtractor data(arg_data, arg_data_size, endian::InlHostByteOrder(),
sizeof(void *));
lldb::offset_t offset = 0;
const char *cstr;
cstr = data.GetCStr(&offset);
if (cstr)
proc_args.AppendArgument(llvm::StringRef(cstr));
else
return true;
}
}
cstr = data.GetCStr(&offset);
if (!cstr)
return false;
process_info.GetExecutableFile().SetFile(cstr, false);
if (!(match_info_ptr == NULL ||
NameMatches(process_info.GetExecutableFile().GetFilename().GetCString(),
match_info_ptr->GetNameMatchType(),
match_info_ptr->GetProcessInfo().GetName())))
return false;
Args &proc_args = process_info.GetArguments();
while (1) {
const uint8_t *p = data.PeekData(offset, 1);
while ((p != NULL) && (*p == '\0') && offset < arg_data_size) {
++offset;
p = data.PeekData(offset, 1);
}
if (p == NULL || offset >= arg_data_size)
break;
cstr = data.GetCStr(&offset);
if (!cstr)
break;
proc_args.AppendArgument(llvm::StringRef(cstr));
}
return false;
return true;
}
static bool GetFreeBSDProcessCPUType(ProcessInstanceInfo &process_info) {
@ -113,26 +117,31 @@ static bool GetFreeBSDProcessCPUType(ProcessInstanceInfo &process_info) {
static bool GetFreeBSDProcessUserAndGroup(ProcessInstanceInfo &process_info) {
struct kinfo_proc proc_kinfo;
size_t proc_kinfo_size;
const int pid = process_info.GetProcessID();
int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid};
if (process_info.ProcessIDIsValid()) {
int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID,
(int)process_info.GetProcessID()};
proc_kinfo_size = sizeof(struct kinfo_proc);
if (!process_info.ProcessIDIsValid())
goto error;
if (::sysctl(mib, 4, &proc_kinfo, &proc_kinfo_size, NULL, 0) == 0) {
if (proc_kinfo_size > 0) {
process_info.SetParentProcessID(proc_kinfo.ki_ppid);
process_info.SetUserID(proc_kinfo.ki_ruid);
process_info.SetGroupID(proc_kinfo.ki_rgid);
process_info.SetEffectiveUserID(proc_kinfo.ki_uid);
if (proc_kinfo.ki_ngroups > 0)
process_info.SetEffectiveGroupID(proc_kinfo.ki_groups[0]);
else
process_info.SetEffectiveGroupID(UINT32_MAX);
return true;
}
}
}
proc_kinfo_size = sizeof(struct kinfo_proc);
if (::sysctl(mib, 4, &proc_kinfo, &proc_kinfo_size, NULL, 0) != 0)
goto error;
if (proc_kinfo_size == 0)
goto error;
process_info.SetParentProcessID(proc_kinfo.ki_ppid);
process_info.SetUserID(proc_kinfo.ki_ruid);
process_info.SetGroupID(proc_kinfo.ki_rgid);
process_info.SetEffectiveUserID(proc_kinfo.ki_uid);
if (proc_kinfo.ki_ngroups > 0)
process_info.SetEffectiveGroupID(proc_kinfo.ki_groups[0]);
else
process_info.SetEffectiveGroupID(UINT32_MAX);
return true;
error:
process_info.SetParentProcessID(LLDB_INVALID_PROCESS_ID);
process_info.SetUserID(UINT32_MAX);
process_info.SetGroupID(UINT32_MAX);
@ -143,7 +152,11 @@ static bool GetFreeBSDProcessUserAndGroup(ProcessInstanceInfo &process_info) {
uint32_t Host::FindProcesses(const ProcessInstanceInfoMatch &match_info,
ProcessInstanceInfoList &process_infos) {
const ::pid_t our_pid = ::getpid();
const ::uid_t our_uid = ::getuid();
std::vector<struct kinfo_proc> kinfos;
// Special case, if lldb is being run as root we can attach to anything.
bool all_users = match_info.GetMatchAllUsers() || (our_uid == 0);
int mib[3] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL};
@ -163,29 +176,24 @@ uint32_t Host::FindProcesses(const ProcessInstanceInfoMatch &match_info,
const size_t actual_pid_count = (pid_data_size / sizeof(struct kinfo_proc));
bool all_users = match_info.GetMatchAllUsers();
const ::pid_t our_pid = getpid();
const uid_t our_uid = getuid();
for (size_t i = 0; i < actual_pid_count; i++) {
const struct kinfo_proc &kinfo = kinfos[i];
const bool kinfo_user_matches = (all_users || (kinfo.ki_ruid == our_uid) ||
// Special case, if lldb is being run as
// root we can attach to anything.
(our_uid == 0));
if (kinfo_user_matches == false || // Make sure the user is acceptable
kinfo.ki_pid == our_pid || // Skip this process
kinfo.ki_pid == 0 || // Skip kernel (kernel pid is zero)
kinfo.ki_stat == SZOMB || // Zombies are bad, they like brains...
kinfo.ki_flag & P_TRACED || // Being debugged?
kinfo.ki_flag & P_WEXIT) // Working on exiting
/* Make sure the user is acceptable */
if (!all_users && kinfo.ki_ruid != our_uid)
continue;
if (kinfo.ki_pid == our_pid || // Skip this process
kinfo.ki_pid == 0 || // Skip kernel (kernel pid is 0)
kinfo.ki_stat == SZOMB || // Zombies are bad
kinfo.ki_flag & P_TRACED || // Being debugged?
kinfo.ki_flag & P_WEXIT) // Working on exiting
continue;
// Every thread is a process in FreeBSD, but all the threads of a single
// process
// have the same pid. Do not store the process info in the result list if a
// process
// with given identifier is already registered there.
// process have the same pid. Do not store the process info in the
// result list if a process with given identifier is already registered
// there.
bool already_registered = false;
for (uint32_t pi = 0;
!already_registered && (const int)kinfo.ki_numthreads > 1 &&

View File

@ -814,9 +814,8 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls(
FindExternalVisibleDecls(context, lldb::ModuleSP(), namespace_decl,
current_id);
}
if (!context.m_found.variable && !context.m_found.local_vars_nsp)
ClangASTSource::FindExternalVisibleDecls(context);
ClangASTSource::FindExternalVisibleDecls(context);
}
void ClangExpressionDeclMap::FindExternalVisibleDecls(
@ -1217,7 +1216,7 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls(
}
}
if (var) {
if (var && !variable_found) {
variable_found = true;
valobj = ValueObjectVariable::Create(frame, var);
AddOneVariable(context, var, valobj, current_id);
@ -1248,305 +1247,299 @@ void ClangExpressionDeclMap::FindExternalVisibleDecls(
}
}
if (!context.m_found.variable) {
const bool include_inlines = false;
const bool append = false;
const bool include_inlines = false;
const bool append = false;
if (namespace_decl && module_sp) {
const bool include_symbols = false;
if (namespace_decl && module_sp) {
const bool include_symbols = false;
module_sp->FindFunctions(name, &namespace_decl, eFunctionNameTypeBase,
include_symbols, include_inlines, append,
sc_list);
} else if (target && !namespace_decl) {
const bool include_symbols = true;
module_sp->FindFunctions(name, &namespace_decl, eFunctionNameTypeBase,
include_symbols, include_inlines, append,
sc_list);
} else if (target && !namespace_decl) {
const bool include_symbols = true;
// TODO Fix FindFunctions so that it doesn't return
// instance methods for eFunctionNameTypeBase.
// TODO Fix FindFunctions so that it doesn't return
// instance methods for eFunctionNameTypeBase.
target->GetImages().FindFunctions(name, eFunctionNameTypeFull,
include_symbols, include_inlines,
append, sc_list);
}
target->GetImages().FindFunctions(name, eFunctionNameTypeFull,
include_symbols, include_inlines,
append, sc_list);
}
// If we found more than one function, see if we can use the
// frame's decl context to remove functions that are shadowed
// by other functions which match in type but are nearer in scope.
//
// AddOneFunction will not add a function whose type has already been
// added, so if there's another function in the list with a matching
// type, check to see if their decl context is a parent of the current
// frame's or was imported via a and using statement, and pick the
// best match according to lookup rules.
if (sc_list.GetSize() > 1) {
// Collect some info about our frame's context.
StackFrame *frame = m_parser_vars->m_exe_ctx.GetFramePtr();
SymbolContext frame_sym_ctx;
if (frame != nullptr)
frame_sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction |
lldb::eSymbolContextBlock);
CompilerDeclContext frame_decl_context =
frame_sym_ctx.block != nullptr
? frame_sym_ctx.block->GetDeclContext()
: CompilerDeclContext();
// If we found more than one function, see if we can use the
// frame's decl context to remove functions that are shadowed
// by other functions which match in type but are nearer in scope.
//
// AddOneFunction will not add a function whose type has already been
// added, so if there's another function in the list with a matching
// type, check to see if their decl context is a parent of the current
// frame's or was imported via a and using statement, and pick the
// best match according to lookup rules.
if (sc_list.GetSize() > 1) {
// Collect some info about our frame's context.
StackFrame *frame = m_parser_vars->m_exe_ctx.GetFramePtr();
SymbolContext frame_sym_ctx;
if (frame != nullptr)
frame_sym_ctx = frame->GetSymbolContext(lldb::eSymbolContextFunction |
lldb::eSymbolContextBlock);
CompilerDeclContext frame_decl_context =
frame_sym_ctx.block != nullptr ? frame_sym_ctx.block->GetDeclContext()
: CompilerDeclContext();
// We can't do this without a compiler decl context for our frame.
if (frame_decl_context) {
clang::DeclContext *frame_decl_ctx =
(clang::DeclContext *)frame_decl_context.GetOpaqueDeclContext();
ClangASTContext *ast = llvm::dyn_cast_or_null<ClangASTContext>(
frame_decl_context.GetTypeSystem());
// We can't do this without a compiler decl context for our frame.
if (frame_decl_context) {
clang::DeclContext *frame_decl_ctx =
(clang::DeclContext *)frame_decl_context.GetOpaqueDeclContext();
ClangASTContext *ast = llvm::dyn_cast_or_null<ClangASTContext>(
frame_decl_context.GetTypeSystem());
// Structure to hold the info needed when comparing function
// declarations.
struct FuncDeclInfo {
ConstString m_name;
CompilerType m_copied_type;
uint32_t m_decl_lvl;
SymbolContext m_sym_ctx;
};
// Structure to hold the info needed when comparing function
// declarations.
struct FuncDeclInfo {
ConstString m_name;
CompilerType m_copied_type;
uint32_t m_decl_lvl;
SymbolContext m_sym_ctx;
};
// First, symplify things by looping through the symbol contexts
// to remove unwanted functions and separate out the functions we
// want to compare and prune into a separate list.
// Cache the info needed about the function declarations in a
// vector for efficiency.
SymbolContextList sc_sym_list;
uint32_t num_indices = sc_list.GetSize();
std::vector<FuncDeclInfo> fdi_cache;
fdi_cache.reserve(num_indices);
for (uint32_t index = 0; index < num_indices; ++index) {
FuncDeclInfo fdi;
SymbolContext sym_ctx;
sc_list.GetContextAtIndex(index, sym_ctx);
// We don't know enough about symbols to compare them,
// but we should keep them in the list.
Function *function = sym_ctx.function;
if (!function) {
sc_sym_list.Append(sym_ctx);
continue;
}
// Filter out functions without declaration contexts, as well as
// class/instance methods, since they'll be skipped in the
// code that follows anyway.
CompilerDeclContext func_decl_context = function->GetDeclContext();
if (!func_decl_context ||
func_decl_context.IsClassMethod(nullptr, nullptr, nullptr))
continue;
// We can only prune functions for which we can copy the type.
CompilerType func_clang_type =
function->GetType()->GetFullCompilerType();
CompilerType copied_func_type = GuardedCopyType(func_clang_type);
if (!copied_func_type) {
sc_sym_list.Append(sym_ctx);
continue;
}
fdi.m_sym_ctx = sym_ctx;
fdi.m_name = function->GetName();
fdi.m_copied_type = copied_func_type;
fdi.m_decl_lvl = LLDB_INVALID_DECL_LEVEL;
if (fdi.m_copied_type && func_decl_context) {
// Call CountDeclLevels to get the number of parent scopes we
// have to look through before we find the function declaration.
// When comparing functions of the same type, the one with a
// lower count will be closer to us in the lookup scope and
// shadows the other.
clang::DeclContext *func_decl_ctx =
(clang::DeclContext *)
func_decl_context.GetOpaqueDeclContext();
fdi.m_decl_lvl =
ast->CountDeclLevels(frame_decl_ctx, func_decl_ctx,
&fdi.m_name, &fdi.m_copied_type);
}
fdi_cache.emplace_back(fdi);
}
// Loop through the functions in our cache looking for matching types,
// then compare their scope levels to see which is closer.
std::multimap<CompilerType, const FuncDeclInfo *> matches;
for (const FuncDeclInfo &fdi : fdi_cache) {
const CompilerType t = fdi.m_copied_type;
auto q = matches.find(t);
if (q != matches.end()) {
if (q->second->m_decl_lvl > fdi.m_decl_lvl)
// This function is closer; remove the old set.
matches.erase(t);
else if (q->second->m_decl_lvl < fdi.m_decl_lvl)
// The functions in our set are closer - skip this one.
continue;
}
matches.insert(std::make_pair(t, &fdi));
}
// Loop through our matches and add their symbol contexts to our list.
SymbolContextList sc_func_list;
for (const auto &q : matches)
sc_func_list.Append(q.second->m_sym_ctx);
// Rejoin the lists with the functions in front.
sc_list = sc_func_list;
sc_list.Append(sc_sym_list);
}
}
if (sc_list.GetSize()) {
Symbol *extern_symbol = NULL;
Symbol *non_extern_symbol = NULL;
for (uint32_t index = 0, num_indices = sc_list.GetSize();
index < num_indices; ++index) {
// First, symplify things by looping through the symbol contexts
// to remove unwanted functions and separate out the functions we
// want to compare and prune into a separate list.
// Cache the info needed about the function declarations in a
// vector for efficiency.
SymbolContextList sc_sym_list;
uint32_t num_indices = sc_list.GetSize();
std::vector<FuncDeclInfo> fdi_cache;
fdi_cache.reserve(num_indices);
for (uint32_t index = 0; index < num_indices; ++index) {
FuncDeclInfo fdi;
SymbolContext sym_ctx;
sc_list.GetContextAtIndex(index, sym_ctx);
if (sym_ctx.function) {
CompilerDeclContext decl_ctx = sym_ctx.function->GetDeclContext();
if (!decl_ctx)
continue;
// Filter out class/instance methods.
if (decl_ctx.IsClassMethod(nullptr, nullptr, nullptr))
continue;
AddOneFunction(context, sym_ctx.function, NULL, current_id);
context.m_found.function_with_type_info = true;
context.m_found.function = true;
} else if (sym_ctx.symbol) {
if (sym_ctx.symbol->GetType() == eSymbolTypeReExported && target) {
sym_ctx.symbol = sym_ctx.symbol->ResolveReExportedSymbol(*target);
if (sym_ctx.symbol == NULL)
continue;
}
if (sym_ctx.symbol->IsExternal())
extern_symbol = sym_ctx.symbol;
else
non_extern_symbol = sym_ctx.symbol;
// We don't know enough about symbols to compare them,
// but we should keep them in the list.
Function *function = sym_ctx.function;
if (!function) {
sc_sym_list.Append(sym_ctx);
continue;
}
// Filter out functions without declaration contexts, as well as
// class/instance methods, since they'll be skipped in the
// code that follows anyway.
CompilerDeclContext func_decl_context = function->GetDeclContext();
if (!func_decl_context ||
func_decl_context.IsClassMethod(nullptr, nullptr, nullptr))
continue;
// We can only prune functions for which we can copy the type.
CompilerType func_clang_type =
function->GetType()->GetFullCompilerType();
CompilerType copied_func_type = GuardedCopyType(func_clang_type);
if (!copied_func_type) {
sc_sym_list.Append(sym_ctx);
continue;
}
fdi.m_sym_ctx = sym_ctx;
fdi.m_name = function->GetName();
fdi.m_copied_type = copied_func_type;
fdi.m_decl_lvl = LLDB_INVALID_DECL_LEVEL;
if (fdi.m_copied_type && func_decl_context) {
// Call CountDeclLevels to get the number of parent scopes we
// have to look through before we find the function declaration.
// When comparing functions of the same type, the one with a
// lower count will be closer to us in the lookup scope and
// shadows the other.
clang::DeclContext *func_decl_ctx =
(clang::DeclContext *)func_decl_context.GetOpaqueDeclContext();
fdi.m_decl_lvl = ast->CountDeclLevels(
frame_decl_ctx, func_decl_ctx, &fdi.m_name, &fdi.m_copied_type);
}
fdi_cache.emplace_back(fdi);
}
if (!context.m_found.function_with_type_info) {
for (clang::NamedDecl *decl : decls_from_modules) {
if (llvm::isa<clang::FunctionDecl>(decl)) {
clang::NamedDecl *copied_decl =
llvm::cast_or_null<FunctionDecl>(m_ast_importer_sp->CopyDecl(
m_ast_context, &decl->getASTContext(), decl));
if (copied_decl) {
context.AddNamedDecl(copied_decl);
context.m_found.function_with_type_info = true;
}
}
// Loop through the functions in our cache looking for matching types,
// then compare their scope levels to see which is closer.
std::multimap<CompilerType, const FuncDeclInfo *> matches;
for (const FuncDeclInfo &fdi : fdi_cache) {
const CompilerType t = fdi.m_copied_type;
auto q = matches.find(t);
if (q != matches.end()) {
if (q->second->m_decl_lvl > fdi.m_decl_lvl)
// This function is closer; remove the old set.
matches.erase(t);
else if (q->second->m_decl_lvl < fdi.m_decl_lvl)
// The functions in our set are closer - skip this one.
continue;
}
matches.insert(std::make_pair(t, &fdi));
}
if (!context.m_found.function_with_type_info) {
if (extern_symbol) {
AddOneFunction(context, NULL, extern_symbol, current_id);
context.m_found.function = true;
} else if (non_extern_symbol) {
AddOneFunction(context, NULL, non_extern_symbol, current_id);
context.m_found.function = true;
// Loop through our matches and add their symbol contexts to our list.
SymbolContextList sc_func_list;
for (const auto &q : matches)
sc_func_list.Append(q.second->m_sym_ctx);
// Rejoin the lists with the functions in front.
sc_list = sc_func_list;
sc_list.Append(sc_sym_list);
}
}
if (sc_list.GetSize()) {
Symbol *extern_symbol = NULL;
Symbol *non_extern_symbol = NULL;
for (uint32_t index = 0, num_indices = sc_list.GetSize();
index < num_indices; ++index) {
SymbolContext sym_ctx;
sc_list.GetContextAtIndex(index, sym_ctx);
if (sym_ctx.function) {
CompilerDeclContext decl_ctx = sym_ctx.function->GetDeclContext();
if (!decl_ctx)
continue;
// Filter out class/instance methods.
if (decl_ctx.IsClassMethod(nullptr, nullptr, nullptr))
continue;
AddOneFunction(context, sym_ctx.function, NULL, current_id);
context.m_found.function_with_type_info = true;
context.m_found.function = true;
} else if (sym_ctx.symbol) {
if (sym_ctx.symbol->GetType() == eSymbolTypeReExported && target) {
sym_ctx.symbol = sym_ctx.symbol->ResolveReExportedSymbol(*target);
if (sym_ctx.symbol == NULL)
continue;
}
if (sym_ctx.symbol->IsExternal())
extern_symbol = sym_ctx.symbol;
else
non_extern_symbol = sym_ctx.symbol;
}
}
if (!context.m_found.function_with_type_info) {
for (clang::NamedDecl *decl : decls_from_modules) {
if (llvm::isa<clang::FunctionDecl>(decl)) {
clang::NamedDecl *copied_decl =
llvm::cast_or_null<FunctionDecl>(m_ast_importer_sp->CopyDecl(
m_ast_context, &decl->getASTContext(), decl));
if (copied_decl) {
context.AddNamedDecl(copied_decl);
context.m_found.function_with_type_info = true;
}
}
}
}
if (!context.m_found.function_with_type_info) {
// Try the modules next.
do {
if (ClangModulesDeclVendor *modules_decl_vendor =
m_target->GetClangModulesDeclVendor()) {
bool append = false;
uint32_t max_matches = 1;
std::vector<clang::NamedDecl *> decls;
if (!modules_decl_vendor->FindDecls(name, append, max_matches,
decls))
break;
clang::NamedDecl *const decl_from_modules = decls[0];
if (llvm::isa<clang::FunctionDecl>(decl_from_modules)) {
if (log) {
log->Printf(" CAS::FEVD[%u] Matching function found for "
"\"%s\" in the modules",
current_id, name.GetCString());
}
clang::Decl *copied_decl = m_ast_importer_sp->CopyDecl(
m_ast_context, &decl_from_modules->getASTContext(),
decl_from_modules);
clang::FunctionDecl *copied_function_decl =
copied_decl ? dyn_cast<clang::FunctionDecl>(copied_decl)
: nullptr;
if (!copied_function_decl) {
if (log)
log->Printf(" CAS::FEVD[%u] - Couldn't export a function "
"declaration from the modules",
current_id);
break;
}
MaybeRegisterFunctionBody(copied_function_decl);
context.AddNamedDecl(copied_function_decl);
context.m_found.function_with_type_info = true;
context.m_found.function = true;
} else if (llvm::isa<clang::VarDecl>(decl_from_modules)) {
if (log) {
log->Printf(" CAS::FEVD[%u] Matching variable found for "
"\"%s\" in the modules",
current_id, name.GetCString());
}
clang::Decl *copied_decl = m_ast_importer_sp->CopyDecl(
m_ast_context, &decl_from_modules->getASTContext(),
decl_from_modules);
clang::VarDecl *copied_var_decl =
copied_decl ? dyn_cast_or_null<clang::VarDecl>(copied_decl)
: nullptr;
if (!copied_var_decl) {
if (log)
log->Printf(" CAS::FEVD[%u] - Couldn't export a variable "
"declaration from the modules",
current_id);
break;
}
context.AddNamedDecl(copied_var_decl);
context.m_found.variable = true;
}
}
} while (0);
}
if (target && !context.m_found.variable && !namespace_decl) {
// We couldn't find a non-symbol variable for this. Now we'll hunt for
// a generic
// data symbol, and -- if it is found -- treat it as a variable.
const Symbol *data_symbol = FindGlobalDataSymbol(*target, name);
if (data_symbol) {
std::string warning("got name from symbols: ");
warning.append(name.AsCString());
const unsigned diag_id =
m_ast_context->getDiagnostics().getCustomDiagID(
clang::DiagnosticsEngine::Level::Warning, "%0");
m_ast_context->getDiagnostics().Report(diag_id) << warning.c_str();
AddOneGenericVariable(context, *data_symbol, current_id);
context.m_found.variable = true;
if (extern_symbol) {
AddOneFunction(context, NULL, extern_symbol, current_id);
context.m_found.function = true;
} else if (non_extern_symbol) {
AddOneFunction(context, NULL, non_extern_symbol, current_id);
context.m_found.function = true;
}
}
}
if (!context.m_found.function_with_type_info) {
// Try the modules next.
do {
if (ClangModulesDeclVendor *modules_decl_vendor =
m_target->GetClangModulesDeclVendor()) {
bool append = false;
uint32_t max_matches = 1;
std::vector<clang::NamedDecl *> decls;
if (!modules_decl_vendor->FindDecls(name, append, max_matches, decls))
break;
clang::NamedDecl *const decl_from_modules = decls[0];
if (llvm::isa<clang::FunctionDecl>(decl_from_modules)) {
if (log) {
log->Printf(" CAS::FEVD[%u] Matching function found for "
"\"%s\" in the modules",
current_id, name.GetCString());
}
clang::Decl *copied_decl = m_ast_importer_sp->CopyDecl(
m_ast_context, &decl_from_modules->getASTContext(),
decl_from_modules);
clang::FunctionDecl *copied_function_decl =
copied_decl ? dyn_cast<clang::FunctionDecl>(copied_decl)
: nullptr;
if (!copied_function_decl) {
if (log)
log->Printf(" CAS::FEVD[%u] - Couldn't export a function "
"declaration from the modules",
current_id);
break;
}
MaybeRegisterFunctionBody(copied_function_decl);
context.AddNamedDecl(copied_function_decl);
context.m_found.function_with_type_info = true;
context.m_found.function = true;
} else if (llvm::isa<clang::VarDecl>(decl_from_modules)) {
if (log) {
log->Printf(" CAS::FEVD[%u] Matching variable found for "
"\"%s\" in the modules",
current_id, name.GetCString());
}
clang::Decl *copied_decl = m_ast_importer_sp->CopyDecl(
m_ast_context, &decl_from_modules->getASTContext(),
decl_from_modules);
clang::VarDecl *copied_var_decl =
copied_decl ? dyn_cast_or_null<clang::VarDecl>(copied_decl)
: nullptr;
if (!copied_var_decl) {
if (log)
log->Printf(" CAS::FEVD[%u] - Couldn't export a variable "
"declaration from the modules",
current_id);
break;
}
context.AddNamedDecl(copied_var_decl);
context.m_found.variable = true;
}
}
} while (0);
}
if (target && !context.m_found.variable && !namespace_decl) {
// We couldn't find a non-symbol variable for this. Now we'll hunt for
// a generic
// data symbol, and -- if it is found -- treat it as a variable.
const Symbol *data_symbol = FindGlobalDataSymbol(*target, name);
if (data_symbol) {
std::string warning("got name from symbols: ");
warning.append(name.AsCString());
const unsigned diag_id =
m_ast_context->getDiagnostics().getCustomDiagID(
clang::DiagnosticsEngine::Level::Warning, "%0");
m_ast_context->getDiagnostics().Report(diag_id) << warning.c_str();
AddOneGenericVariable(context, *data_symbol, current_id);
context.m_found.variable = true;
}
}
}
}

View File

@ -588,7 +588,7 @@ addr_t ThreadSanitizerRuntime::GetFirstNonInternalFramePc(
ModuleSP runtime_module_sp = GetRuntimeModuleSP();
StructuredData::Array *trace_array = trace->GetAsArray();
for (int i = 0; i < trace_array->GetSize(); i++) {
for (size_t i = 0; i < trace_array->GetSize(); i++) {
if (skip_one_frame && i == 0)
continue;

View File

@ -395,7 +395,8 @@ static bool ExtractLibcxxStringInfo(ValueObject &valobj,
if (!D)
return false;
ValueObjectSP layout_decider(D->GetChildAtIndexPath({0, 0}));
ValueObjectSP layout_decider(
D->GetChildAtIndexPath(llvm::ArrayRef<size_t>({0, 0})));
// this child should exist
if (!layout_decider)

View File

@ -3682,7 +3682,7 @@ DWARFASTParserClang::GetClangDeclContextForDIE(const DWARFDIE &die) {
break;
case DW_TAG_lexical_block:
decl_ctx = (clang::DeclContext *)ResolveBlockDIE(die);
decl_ctx = GetDeclContextForBlock(die);
try_parsing_type = false;
break;
@ -3704,6 +3704,69 @@ DWARFASTParserClang::GetClangDeclContextForDIE(const DWARFDIE &die) {
return nullptr;
}
static bool IsSubroutine(const DWARFDIE &die) {
switch (die.Tag()) {
case DW_TAG_subprogram:
case DW_TAG_inlined_subroutine:
return true;
default:
return false;
}
}
static DWARFDIE GetContainingFunctionWithAbstractOrigin(const DWARFDIE &die) {
for (DWARFDIE candidate = die; candidate; candidate = candidate.GetParent()) {
if (IsSubroutine(candidate)) {
if (candidate.GetReferencedDIE(DW_AT_abstract_origin)) {
return candidate;
} else {
return DWARFDIE();
}
}
}
assert(!"Shouldn't call GetContainingFunctionWithAbstractOrigin on something "
"not in a function");
return DWARFDIE();
}
static DWARFDIE FindAnyChildWithAbstractOrigin(const DWARFDIE &context) {
for (DWARFDIE candidate = context.GetFirstChild(); candidate.IsValid();
candidate = candidate.GetSibling()) {
if (candidate.GetReferencedDIE(DW_AT_abstract_origin)) {
return candidate;
}
}
return DWARFDIE();
}
static DWARFDIE FindFirstChildWithAbstractOrigin(const DWARFDIE &block,
const DWARFDIE &function) {
assert(IsSubroutine(function));
for (DWARFDIE context = block; context != function.GetParent();
context = context.GetParent()) {
assert(!IsSubroutine(context) || context == function);
if (DWARFDIE child = FindAnyChildWithAbstractOrigin(context)) {
return child;
}
}
return DWARFDIE();
}
clang::DeclContext *
DWARFASTParserClang::GetDeclContextForBlock(const DWARFDIE &die) {
assert(die.Tag() == DW_TAG_lexical_block);
DWARFDIE containing_function_with_abstract_origin =
GetContainingFunctionWithAbstractOrigin(die);
if (!containing_function_with_abstract_origin) {
return (clang::DeclContext *)ResolveBlockDIE(die);
}
DWARFDIE child = FindFirstChildWithAbstractOrigin(
die, containing_function_with_abstract_origin);
CompilerDeclContext decl_context =
GetDeclContextContainingUIDFromDWARF(child);
return (clang::DeclContext *)decl_context.GetOpaqueDeclContext();
}
clang::BlockDecl *DWARFASTParserClang::ResolveBlockDIE(const DWARFDIE &die) {
if (die && die.Tag() == DW_TAG_lexical_block) {
clang::BlockDecl *decl =

View File

@ -66,6 +66,8 @@ class DWARFASTParserClang : public DWARFASTParser {
class DelayedAddObjCClassProperty;
typedef std::vector<DelayedAddObjCClassProperty> DelayedPropertyList;
clang::DeclContext *GetDeclContextForBlock(const DWARFDIE &die);
clang::BlockDecl *ResolveBlockDIE(const DWARFDIE &die);
clang::NamespaceDecl *ResolveNamespaceDIE(const DWARFDIE &die);

View File

@ -3051,7 +3051,13 @@ SymbolFileDWARF::GetDeclContextDIEContainingDIE(const DWARFDIE &orig_die) {
case DW_TAG_lexical_block:
case DW_TAG_subprogram:
return die;
case DW_TAG_inlined_subroutine: {
DWARFDIE abs_die = die.GetReferencedDIE(DW_AT_abstract_origin);
if (abs_die) {
return abs_die;
}
break;
}
default:
break;
}

View File

@ -3614,7 +3614,7 @@ rnb_err_t RNBRemote::HandlePacket_qSupported(const char *p) {
bool enable_compression = false;
(void)enable_compression;
#if (defined (TARGET_OS_WATCH) && TARGET_OS_WATCHOS == 1) || (defined (TARGET_OS_IOS) && TARGET_OS_IOS == 1) || (defined (TARGET_OS_TVOS) && TARGET_OS_TVOS == 1)
#if (defined (TARGET_OS_WATCH) && TARGET_OS_WATCH == 1) || (defined (TARGET_OS_IOS) && TARGET_OS_IOS == 1) || (defined (TARGET_OS_TV) && TARGET_OS_TV == 1)
enable_compression = true;
#endif

View File

@ -12,8 +12,21 @@
#include "lldb/Host/SocketAddress.h"
namespace {
class SocketAddressTest : public ::testing::Test {};
}
class SocketAddressTest : public testing::Test {
public:
static void SetUpTestCase() {
#ifdef _MSC_VER
WSADATA data;
ASSERT_EQ(0, WSAStartup(MAKEWORD(2, 2), &data));
#endif
}
static void TearDownTestCase() {
#ifdef _MSC_VER
ASSERT_EQ(0, WSACleanup());
#endif
}
};
} // namespace
using namespace lldb_private;
@ -34,6 +47,14 @@ TEST_F(SocketAddressTest, Set) {
ASSERT_EQ(1139, sa.GetPort());
}
TEST_F(SocketAddressTest, GetAddressInfo) {
auto addr = SocketAddress::GetAddressInfo("127.0.0.1", nullptr, AF_UNSPEC,
SOCK_STREAM, IPPROTO_TCP);
ASSERT_EQ(1u, addr.size());
EXPECT_EQ(AF_INET, addr[0].GetFamily());
EXPECT_EQ("127.0.0.1", addr[0].GetIPAddress());
}
#ifdef _WIN32
// we need to test our inet_ntop implementation for Windows XP

View File

@ -354,9 +354,8 @@
the target architecture. Since you already have a checkout of clang and lldb, you
can compile a host version of clang in a separate folder and use that.
Alternatively you can use system clang or even cross-gcc if your distribution
provides such packages (e.g., <code>g++-aarch64-linux-gnu</code> on Ubuntu). On
Android, a working toolchain can be produced by downloading the Android NDK and
running the contained <code>make-standalone-toolchain.sh</code> script.
provides such packages (e.g., <code>g++-aarch64-linux-gnu</code>
on Ubuntu).
</p>
<p>
@ -380,11 +379,6 @@
libraries.
</p>
<p>
In the case of Android, all required headers and libraries are provided by the
aforementioned <code>make-standalone-toolchain.sh</code> script.
</p>
<p>
Once all of the dependencies are in place, it's just a matter of configuring the
build system with the locations and arguments of all the necessary tools. The most
@ -472,38 +466,37 @@
<h3>Example 2: Cross-compiling for Android on Linux</h3>
<p>
All tools needed to build LLDB for android are available in the Android NDK. For
example, we can produce an x86 toolchain along with all the libraries and headers
by running
</p>
<code>
./build/tools/make-standalone-toolchain.sh \<br/>
--platform=android-21 \<br/>
--toolchain=x86-4.9 \<br/>
--install-dir=$HOME/Toolchains/x86-android-toolchain
</code>
<p>
from inside the unzipped NDK. Toolchains for other architectures can be produced in
a similar manner.
In the case of Android, the toolchain and all required headers and
libraries are available in the Android NDK.
</p>
<p>
For Android we provide a Android.cmake script which sets a lot of the required
options automatically. A cmake build can therefore be prepared with the following parameters:
The NDK also contains a cmake toolchain file, which makes
configuring the build much simpler. The compiler, include and
library paths will be configured by the toolchain file and all you
need to do is to select the architecture (ANDROID_ABI) and
platform level (ANDROID_PLATFORM, should be at least 21). You will
also need to set ANDROID_ALLOW_UNDEFINED_SYMBOLS=On, as the
toolchain file defaults to "no undefined symbols in shared
libraries", which is not compatible with some llvm libraries. The
first version of NDK which supports this approach is r14.
</p>
<p>
For example, the following arguments are sufficient to configure
an android arm64 build:
</p>
<code>
-DCMAKE_TOOLCHAIN_FILE=cmake/platforms/Android.cmake \<br/>
-DANDROID_TOOLCHAIN_DIR=$HOME/Toolchains/x86-android-toolchain \<br/>
-DANDROID_ABI=x86 \<br/>
-DLLVM_HOST_TRIPLE=i386-unknown-linux-android \<br/>
-DLLVM_TABLEGEN=&lt;path-to-host&gt;/bin/llvm-tblgen \<br/>
-DCLANG_TABLEGEN=&lt;path-to-host&gt;/bin/clang-tblgen
-DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK_HOME/build/cmake/android.toolchain.cmake \<br/>
-DANDROID_ABI=arm64-v8a \<br/>
-DANDROID_PLATFORM=android-21 \<br/>
-DANDROID_ALLOW_UNDEFINED_SYMBOLS=On \<br/>
-DLLVM_HOST_TRIPLE=aarch64-unknown-linux-android \<br/>
-DCROSS_TOOLCHAIN_FLAGS_NATIVE='-DCMAKE_C_COMPILER=cc;-DCMAKE_CXX_COMPILER=c++' <br/>
</code>
<p>
Note that the full LLVM build is not functional on android yet, so simply running
<code>ninja</code> will not work. You will need to manually specify the target you
want to build: <code>lldb</code>, <code>lldb-server</code>, etc.
Note that currently only lldb-server is functional on android. The
lldb client is not supported and unlikely to work.
</p>
</div>
<div class="postfooter"></div>