Vendor import of lldb trunk r301441:
https://llvm.org/svn/llvm-project/lldb/trunk@301441
This commit is contained in:
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
@ -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 "
|
||||
|
@ -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 )
|
48
examples/python/disassembly_mode.py
Normal file
48
examples/python/disassembly_mode.py
Normal 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")
|
@ -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"
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
//------------------------------------------------------------------
|
||||
|
@ -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
122
include/lldb/API/SBTrace.h
Normal 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_
|
58
include/lldb/API/SBTraceOptions.h
Normal file
58
include/lldb/API/SBTraceOptions.h
Normal 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 ¶ms);
|
||||
|
||||
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_ */
|
95
include/lldb/Core/StructuredDataImpl.h
Normal file
95
include/lldb/Core/StructuredDataImpl.h
Normal 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
|
62
include/lldb/Core/TraceOptions.h
Normal file
62
include/lldb/Core/TraceOptions.h
Normal 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_
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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),
|
||||
|
@ -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;
|
||||
|
@ -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"""
|
||||
|
@ -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())
|
||||
|
@ -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) {
|
||||
|
@ -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):
|
||||
|
@ -0,0 +1,3 @@
|
||||
LEVEL = ../../../make
|
||||
CXX_SOURCES := main.cpp
|
||||
include $(LEVEL)/Makefile.rules
|
@ -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")])
|
36
packages/Python/lldbsuite/test/lang/cpp/llvm-style/main.cpp
Normal file
36
packages/Python/lldbsuite/test/lang/cpp/llvm-style/main.cpp
Normal 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;
|
||||
}
|
@ -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(
|
||||
|
3
packages/Python/lldbsuite/test/lang/cpp/symbols/Makefile
Normal file
3
packages/Python/lldbsuite/test/lang/cpp/symbols/Makefile
Normal file
@ -0,0 +1,3 @@
|
||||
LEVEL = ../../../make
|
||||
CXX_SOURCES := main.cpp
|
||||
include $(LEVEL)/Makefile.rules
|
@ -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")])
|
40
packages/Python/lldbsuite/test/lang/cpp/symbols/main.cpp
Normal file
40
packages/Python/lldbsuite/test/lang/cpp/symbols/main.cpp
Normal 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;
|
||||
}
|
@ -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 ®ion_info);
|
||||
|
||||
|
@ -38,5 +38,8 @@ namespace lldb {
|
||||
|
||||
lldb::SBError
|
||||
GetDescription(lldb::SBStream &stream) const;
|
||||
|
||||
lldb::SBError
|
||||
SetFromJSON(lldb::SBStream &stream);
|
||||
};
|
||||
}
|
||||
|
34
scripts/interface/SBTrace.i
Normal file
34
scripts/interface/SBTrace.i
Normal 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
|
38
scripts/interface/SBTraceOptions.i
Normal file
38
scripts/interface/SBTraceOptions.i
Normal 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 ¶ms);
|
||||
|
||||
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();
|
||||
};
|
||||
}
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
109
source/API/SBTrace.cpp
Normal 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;
|
||||
}
|
94
source/API/SBTraceOptions.cpp
Normal file
94
source/API/SBTraceOptions.cpp
Normal 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 ¶ms) {
|
||||
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;
|
||||
}
|
@ -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();
|
||||
|
@ -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) {
|
||||
|
@ -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 &&
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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 =
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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=<path-to-host>/bin/llvm-tblgen \<br/>
|
||||
-DCLANG_TABLEGEN=<path-to-host>/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>
|
||||
|
Loading…
Reference in New Issue
Block a user