diff --git a/lldb/CMakeLists.txt b/lldb/CMakeLists.txt index b73f87635dca..d49d2a3c9f36 100644 --- a/lldb/CMakeLists.txt +++ b/lldb/CMakeLists.txt @@ -1,272 +1,272 @@ -# If we are not building as a part of LLVM, build LLDB as an -# standalone project, using LLVM as an external library: -if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) - project(lldb) - cmake_minimum_required(VERSION 2.8) - - set(LLDB_PATH_TO_LLVM_SOURCE "" CACHE PATH - "Path to LLVM source code. Not necessary if using an installed LLVM.") - set(LLDB_PATH_TO_LLVM_BUILD "" CACHE PATH - "Path to the directory where LLVM was built or installed.") - - set(LLDB_PATH_TO_CLANG_SOURCE "" CACHE PATH - "Path to Clang source code. Not necessary if using an installed Clang.") - set(LLDB_PATH_TO_CLANG_BUILD "" CACHE PATH - "Path to the directory where Clang was built or installed.") - - set(LLDB_DISABLE_PYTHON 1 BOOL "Disables the Python scripting integration.") - - if (LLDB_PATH_TO_LLVM_SOURCE) - if (NOT EXISTS "${LLDB_PATH_TO_LLVM_SOURCE}/cmake/config-ix.cmake") - message(FATAL_ERROR "Please set LLDB_PATH_TO_LLVM_SOURCE to the root " - "directory of LLVM source code.") - else() - get_filename_component(LLVM_MAIN_SRC_DIR ${LLDB_PATH_TO_LLVM_SOURCE} - ABSOLUTE) - list(APPEND CMAKE_MODULE_PATH "${LLVM_MAIN_SRC_DIR}/cmake/modules") - endif() - endif() - - if (LLDB_PATH_TO_CLANG_SOURCE) - get_filename_component(CLANG_MAIN_SRC_DIR ${LLDB_PATH_TO_CLANG_SOURCE} - ABSOLUTE) - endif() - - list(APPEND CMAKE_MODULE_PATH "${LLDB_PATH_TO_LLVM_BUILD}/share/llvm/cmake") - - get_filename_component(PATH_TO_LLVM_BUILD ${LLDB_PATH_TO_LLVM_BUILD} - ABSOLUTE) - - get_filename_component(PATH_TO_CLANG_BUILD ${LLDB_PATH_TO_CLANG_BUILD} - ABSOLUTE) - - include(AddLLVM) - include("${LLDB_PATH_TO_LLVM_BUILD}/share/llvm/cmake/LLVMConfig.cmake") - include(HandleLLVMOptions) - - set(PACKAGE_VERSION "${LLVM_PACKAGE_VERSION}") - - set(LLVM_MAIN_INCLUDE_DIR "${LLVM_MAIN_SRC_DIR}/include") - set(LLVM_BINARY_DIR ${CMAKE_BINARY_DIR}) - - set(CLANG_MAIN_INCLUDE_DIR "${CLANG_MAIN_SRC_DIR}/include") - - set(CMAKE_INCLUDE_CURRENT_DIR ON) - include_directories("${PATH_TO_LLVM_BUILD}/include" - "${LLVM_MAIN_INCLUDE_DIR}" - "${PATH_TO_CLANG_BUILD}/include" - "${CLANG_MAIN_INCLUDE_DIR}" - "${CMAKE_CURRENT_SOURCE_DIR}/source") - link_directories("${PATH_TO_LLVM_BUILD}/lib" - "${PATH_TO_CLANG_BUILD}/lib") - - set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) - set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) - set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) - - set(LLDB_BUILT_STANDALONE 1) - - if (LLDB_DISABLE_PYTHON) - add_definitions( -DLLDB_DISABLE_PYTHON ) - endif() -endif() - -if ( CMAKE_SYSTEM_NAME MATCHES "Windows" ) - add_definitions( -DLLDB_DISABLE_PYTHON ) -endif () - -macro(add_lldb_definitions) - # We don't want no semicolons on LLDB_DEFINITIONS: - foreach(arg ${ARGN}) - set(LLDB_DEFINITIONS "${LLVM_DEFINITIONS} ${arg}") - endforeach(arg) - add_definitions( ${ARGN} ) -endmacro(add_lldb_definitions) - -include_directories(/usr/include/python2.7) -include_directories(../clang/include) -include_directories("${CMAKE_CURRENT_BINARY_DIR}/../clang/include") - -# lldb requires c++11 to build. Make sure that we have a compiler and standard -# library combination that can do that. -if (MSVC11 OR MSVC12) - # Do nothing, we're good. -elseif (NOT MSVC) - # gcc and clang require the -std=c++0x or -std=c++11 flag. - if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU" OR - "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") - if (NOT ("${CMAKE_CXX_FLAGS}" MATCHES "-std=c\\+\\+0x" OR - "${CMAKE_CXX_FLAGS}" MATCHES "-std=gnu\\+\\+0x" OR - "${CMAKE_CXX_FLAGS}" MATCHES "-std=c\\+\\+11" OR - "${CMAKE_CXX_FLAGS}" MATCHES "-std=gnu\\+\\+11")) - if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") - if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.7") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") - else() - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") - endif() - else() - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") - endif() - endif() - endif() -else() - message(FATAL_ERROR "The selected compiler does not support c++11 which is " - "required to build lldb.") -endif() - -# Disable Clang warnings -if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") - add_lldb_definitions( - -Wno-deprecated-declarations # Suppress "deprecated auto_ptr" warnings - ) -endif() - -if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" - AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER "3.3") - add_lldb_definitions( - -Wno-deprecated-register # Suppress "deprecated register keyword" warnings - ) -endif() - -# Disable MSVC warnings -if( MSVC ) - add_lldb_definitions( - -wd4018 # Suppress 'warning C4018: '>=' : signed/unsigned mismatch' - -wd4068 # Suppress 'warning C4068: unknown pragma' - -wd4150 # Suppress 'warning C4150: deletion of pointer to incomplete type' - -wd4521 # Suppress 'warning C4521: 'type' : multiple copy constructors specified' - ) -endif() - -# If building on a 32-bit system, make sure off_t can store offsets > 2GB -if( CMAKE_SIZEOF_VOID_P EQUAL 4 ) - add_lldb_definitions( - -D_LARGEFILE_SOURCE - -D_FILE_OFFSET_BITS=64 - ) -endif() - -set(LLDB_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) -set(LLDB_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}) - -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 " -"from there, passing the path to this source directory as the last argument. " -"This process created the file `CMakeCache.txt' and the directory " -"`CMakeFiles'. Please delete them.") -endif() - -# Compute the LLDB version from the LLVM version. -string(REGEX MATCH "[0-9]+\\.[0-9]+(\\.[0-9]+)?" LLDB_VERSION - ${PACKAGE_VERSION}) -message(STATUS "LLDB version: ${LLDB_VERSION}") - -macro(add_lldb_library name) - llvm_process_sources(srcs ${ARGN}) - if (MSVC_IDE OR XCODE) - string(REGEX MATCHALL "/[^/]+" split_path ${CMAKE_CURRENT_SOURCE_DIR}) - list(GET split_path -1 dir) - file(GLOB_RECURSE headers - ../../include/lldb${dir}/*.h) - set(srcs ${srcs} ${headers}) - endif() - if (MODULE) - set(libkind MODULE) - elseif (SHARED_LIBRARY) - set(libkind SHARED) - else() - set(libkind STATIC) - endif() - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") - add_library(${name} ${libkind} ${srcs}) - #if (LLVM_COMMON_DEPENDS) - ##add_dependencies(${name} ${LLVM_COMMON_DEPENDS}) - #endif() - - if(LLDB_USED_LIBS) - if (CMAKE_SYSTEM_NAME MATCHES "Linux" OR CMAKE_SYSTEM_NAME MATCHES "FreeBSD" OR CMAKE_SYSTEM_NAME MATCHES "Windows") - target_link_libraries(${name} -Wl,--start-group ${LLDB_USED_LIBS} -Wl,--end-group) - else() - target_link_libraries(${name} ${LLDB_USED_LIBS}) - endif() - endif() - target_link_libraries(${name} ${CLANG_USED_LIBS}) - target_link_libraries(${name} ${LLVM_USED_LIBS}) - llvm_config(${name} ${LLVM_LINK_COMPONENTS}) - target_link_libraries(${name} ${LLVM_COMMON_LIBS}) - link_system_libs(${name}) - if (LLVM_COMMON_DEPENDS) - add_dependencies(${name} ${LLVM_COMMON_DEPENDS}) - endif() - - # Hack: only some LLDB libraries depend on the clang autogenerated headers, - # but it is simple enough to make all of LLDB depend on some of those - # headers without negatively impacting much of anything. - set (LLDB_DEPENDENCIES - libclang - ) - add_dependencies(${name} ${LLDB_DEPENDENCIES}) - - install(TARGETS ${name} - LIBRARY DESTINATION lib${LLVM_LIBDIR_SUFFIX} - ARCHIVE DESTINATION lib${LLVM_LIBDIR_SUFFIX}) - set_target_properties(${name} PROPERTIES FOLDER "lldb libraries") -endmacro(add_lldb_library) - -macro(add_lldb_executable name) - #add_llvm_executable(${name} ${ARGN}) - llvm_process_sources( ALL_FILES ${ARGN} ) - add_executable(${name} ${ALL_FILES}) - #target_link_libraries(${name} ${CLANG_USED_LIBS}) - #llvm_config( ${name} ${LLVM_LINK_COMPONENTS} ) - #link_system_libs( ${name} ) - #if (LLVM_COMMON_DEPENDS) - #add_dependencies(${name} ${LLVM_COMMON_DEPENDS}) - #endif() - set_target_properties(${name} PROPERTIES FOLDER "lldb executables") -endmacro(add_lldb_executable) - -include_directories(BEFORE - ${CMAKE_CURRENT_BINARY_DIR}/include - ${CMAKE_CURRENT_SOURCE_DIR}/include - ) - -install(DIRECTORY include/ - DESTINATION include - FILES_MATCHING - PATTERN "*.h" - PATTERN ".svn" EXCLUDE - ) - - -# Find libraries or frameworks that may be needed -if (CMAKE_SYSTEM_NAME MATCHES "Darwin") - find_library(CARBON_LIBRARY Carbon) - find_library(FOUNDATION_LIBRARY Foundation) - find_library(CORE_FOUNDATION_LIBRARY CoreFoundation) - find_library(CORE_SERVICES_LIBRARY CoreServices) - find_library(SECURITY_LIBRARY Security) - find_library(DEBUG_SYMBOLS_LIBRARY DebugSymbols PATHS "/System/Library/PrivateFrameworks") - - set(LIBXML2_INCLUDE_DIR "/usr/include/libxml2") - list(APPEND system_libs xml2) - list(APPEND system_libs ${CARBON_LIBRARY} ${FOUNDATION_LIBRARY} - ${CORE_FOUNDATION_LIBRARY} ${CORE_SERVICES_LIBRARY} ${SECURITY_LIBRARY} - ${DEBUG_SYMBOLS_LIBRARY}) -endif() - -# On FreeBSD, link libexecinfo because libc is missing backtrace() -if (CMAKE_SYSTEM_NAME MATCHES "FreeBSD") - list(APPEND system_libs execinfo) -endif() - -#add_subdirectory(include) -add_subdirectory(docs) -if (NOT CMAKE_SYSTEM_NAME MATCHES "Windows") - add_subdirectory(scripts) -endif() -add_subdirectory(source) -add_subdirectory(test) -add_subdirectory(tools) +# If we are not building as a part of LLVM, build LLDB as an +# standalone project, using LLVM as an external library: +if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) + project(lldb) + cmake_minimum_required(VERSION 2.8) + + set(LLDB_PATH_TO_LLVM_SOURCE "" CACHE PATH + "Path to LLVM source code. Not necessary if using an installed LLVM.") + set(LLDB_PATH_TO_LLVM_BUILD "" CACHE PATH + "Path to the directory where LLVM was built or installed.") + + set(LLDB_PATH_TO_CLANG_SOURCE "" CACHE PATH + "Path to Clang source code. Not necessary if using an installed Clang.") + set(LLDB_PATH_TO_CLANG_BUILD "" CACHE PATH + "Path to the directory where Clang was built or installed.") + + set(LLDB_DISABLE_PYTHON 1 BOOL "Disables the Python scripting integration.") + + if (LLDB_PATH_TO_LLVM_SOURCE) + if (NOT EXISTS "${LLDB_PATH_TO_LLVM_SOURCE}/cmake/config-ix.cmake") + message(FATAL_ERROR "Please set LLDB_PATH_TO_LLVM_SOURCE to the root " + "directory of LLVM source code.") + else() + get_filename_component(LLVM_MAIN_SRC_DIR ${LLDB_PATH_TO_LLVM_SOURCE} + ABSOLUTE) + list(APPEND CMAKE_MODULE_PATH "${LLVM_MAIN_SRC_DIR}/cmake/modules") + endif() + endif() + + if (LLDB_PATH_TO_CLANG_SOURCE) + get_filename_component(CLANG_MAIN_SRC_DIR ${LLDB_PATH_TO_CLANG_SOURCE} + ABSOLUTE) + endif() + + list(APPEND CMAKE_MODULE_PATH "${LLDB_PATH_TO_LLVM_BUILD}/share/llvm/cmake") + + get_filename_component(PATH_TO_LLVM_BUILD ${LLDB_PATH_TO_LLVM_BUILD} + ABSOLUTE) + + get_filename_component(PATH_TO_CLANG_BUILD ${LLDB_PATH_TO_CLANG_BUILD} + ABSOLUTE) + + include(AddLLVM) + include("${LLDB_PATH_TO_LLVM_BUILD}/share/llvm/cmake/LLVMConfig.cmake") + include(HandleLLVMOptions) + + set(PACKAGE_VERSION "${LLVM_PACKAGE_VERSION}") + + set(LLVM_MAIN_INCLUDE_DIR "${LLVM_MAIN_SRC_DIR}/include") + set(LLVM_BINARY_DIR ${CMAKE_BINARY_DIR}) + + set(CLANG_MAIN_INCLUDE_DIR "${CLANG_MAIN_SRC_DIR}/include") + + set(CMAKE_INCLUDE_CURRENT_DIR ON) + include_directories("${PATH_TO_LLVM_BUILD}/include" + "${LLVM_MAIN_INCLUDE_DIR}" + "${PATH_TO_CLANG_BUILD}/include" + "${CLANG_MAIN_INCLUDE_DIR}" + "${CMAKE_CURRENT_SOURCE_DIR}/source") + link_directories("${PATH_TO_LLVM_BUILD}/lib" + "${PATH_TO_CLANG_BUILD}/lib") + + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) + set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) + set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) + + set(LLDB_BUILT_STANDALONE 1) + + if (LLDB_DISABLE_PYTHON) + add_definitions( -DLLDB_DISABLE_PYTHON ) + endif() +endif() + +if ( CMAKE_SYSTEM_NAME MATCHES "Windows" ) + add_definitions( -DLLDB_DISABLE_PYTHON ) +endif () + +macro(add_lldb_definitions) + # We don't want no semicolons on LLDB_DEFINITIONS: + foreach(arg ${ARGN}) + set(LLDB_DEFINITIONS "${LLVM_DEFINITIONS} ${arg}") + endforeach(arg) + add_definitions( ${ARGN} ) +endmacro(add_lldb_definitions) + +include_directories(/usr/include/python2.7) +include_directories(../clang/include) +include_directories("${CMAKE_CURRENT_BINARY_DIR}/../clang/include") + +# lldb requires c++11 to build. Make sure that we have a compiler and standard +# library combination that can do that. +if (MSVC11 OR MSVC12) + # Do nothing, we're good. +elseif (NOT MSVC) + # gcc and clang require the -std=c++0x or -std=c++11 flag. + if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU" OR + "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") + if (NOT ("${CMAKE_CXX_FLAGS}" MATCHES "-std=c\\+\\+0x" OR + "${CMAKE_CXX_FLAGS}" MATCHES "-std=gnu\\+\\+0x" OR + "${CMAKE_CXX_FLAGS}" MATCHES "-std=c\\+\\+11" OR + "${CMAKE_CXX_FLAGS}" MATCHES "-std=gnu\\+\\+11")) + if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.7") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") + else() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + endif() + else() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + endif() + endif() + endif() +else() + message(FATAL_ERROR "The selected compiler does not support c++11 which is " + "required to build lldb.") +endif() + +# Disable Clang warnings +if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + add_lldb_definitions( + -Wno-deprecated-declarations # Suppress "deprecated auto_ptr" warnings + ) +endif() + +if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" + AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER "3.3") + add_lldb_definitions( + -Wno-deprecated-register # Suppress "deprecated register keyword" warnings + ) +endif() + +# Disable MSVC warnings +if( MSVC ) + add_lldb_definitions( + -wd4018 # Suppress 'warning C4018: '>=' : signed/unsigned mismatch' + -wd4068 # Suppress 'warning C4068: unknown pragma' + -wd4150 # Suppress 'warning C4150: deletion of pointer to incomplete type' + -wd4521 # Suppress 'warning C4521: 'type' : multiple copy constructors specified' + ) +endif() + +# If building on a 32-bit system, make sure off_t can store offsets > 2GB +if( CMAKE_SIZEOF_VOID_P EQUAL 4 ) + add_lldb_definitions( + -D_LARGEFILE_SOURCE + -D_FILE_OFFSET_BITS=64 + ) +endif() + +set(LLDB_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) +set(LLDB_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}) + +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 " +"from there, passing the path to this source directory as the last argument. " +"This process created the file `CMakeCache.txt' and the directory " +"`CMakeFiles'. Please delete them.") +endif() + +# Compute the LLDB version from the LLVM version. +string(REGEX MATCH "[0-9]+\\.[0-9]+(\\.[0-9]+)?" LLDB_VERSION + ${PACKAGE_VERSION}) +message(STATUS "LLDB version: ${LLDB_VERSION}") + +macro(add_lldb_library name) + llvm_process_sources(srcs ${ARGN}) + if (MSVC_IDE OR XCODE) + string(REGEX MATCHALL "/[^/]+" split_path ${CMAKE_CURRENT_SOURCE_DIR}) + list(GET split_path -1 dir) + file(GLOB_RECURSE headers + ../../include/lldb${dir}/*.h) + set(srcs ${srcs} ${headers}) + endif() + if (MODULE) + set(libkind MODULE) + elseif (SHARED_LIBRARY) + set(libkind SHARED) + else() + set(libkind STATIC) + endif() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") + add_library(${name} ${libkind} ${srcs}) + #if (LLVM_COMMON_DEPENDS) + ##add_dependencies(${name} ${LLVM_COMMON_DEPENDS}) + #endif() + + if(LLDB_USED_LIBS) + if (CMAKE_SYSTEM_NAME MATCHES "Linux" OR CMAKE_SYSTEM_NAME MATCHES "FreeBSD" OR CMAKE_SYSTEM_NAME MATCHES "Windows") + target_link_libraries(${name} -Wl,--start-group ${LLDB_USED_LIBS} -Wl,--end-group) + else() + target_link_libraries(${name} ${LLDB_USED_LIBS}) + endif() + endif() + target_link_libraries(${name} ${CLANG_USED_LIBS}) + target_link_libraries(${name} ${LLVM_USED_LIBS}) + llvm_config(${name} ${LLVM_LINK_COMPONENTS}) + target_link_libraries(${name} ${LLVM_COMMON_LIBS}) + link_system_libs(${name}) + if (LLVM_COMMON_DEPENDS) + add_dependencies(${name} ${LLVM_COMMON_DEPENDS}) + endif() + + # Hack: only some LLDB libraries depend on the clang autogenerated headers, + # but it is simple enough to make all of LLDB depend on some of those + # headers without negatively impacting much of anything. + set (LLDB_DEPENDENCIES + libclang + ) + add_dependencies(${name} ${LLDB_DEPENDENCIES}) + + install(TARGETS ${name} + LIBRARY DESTINATION lib${LLVM_LIBDIR_SUFFIX} + ARCHIVE DESTINATION lib${LLVM_LIBDIR_SUFFIX}) + set_target_properties(${name} PROPERTIES FOLDER "lldb libraries") +endmacro(add_lldb_library) + +macro(add_lldb_executable name) + #add_llvm_executable(${name} ${ARGN}) + llvm_process_sources( ALL_FILES ${ARGN} ) + add_executable(${name} ${ALL_FILES}) + #target_link_libraries(${name} ${CLANG_USED_LIBS}) + #llvm_config( ${name} ${LLVM_LINK_COMPONENTS} ) + #link_system_libs( ${name} ) + #if (LLVM_COMMON_DEPENDS) + #add_dependencies(${name} ${LLVM_COMMON_DEPENDS}) + #endif() + set_target_properties(${name} PROPERTIES FOLDER "lldb executables") +endmacro(add_lldb_executable) + +include_directories(BEFORE + ${CMAKE_CURRENT_BINARY_DIR}/include + ${CMAKE_CURRENT_SOURCE_DIR}/include + ) + +install(DIRECTORY include/ + DESTINATION include + FILES_MATCHING + PATTERN "*.h" + PATTERN ".svn" EXCLUDE + ) + + +# Find libraries or frameworks that may be needed +if (CMAKE_SYSTEM_NAME MATCHES "Darwin") + find_library(CARBON_LIBRARY Carbon) + find_library(FOUNDATION_LIBRARY Foundation) + find_library(CORE_FOUNDATION_LIBRARY CoreFoundation) + find_library(CORE_SERVICES_LIBRARY CoreServices) + find_library(SECURITY_LIBRARY Security) + find_library(DEBUG_SYMBOLS_LIBRARY DebugSymbols PATHS "/System/Library/PrivateFrameworks") + + set(LIBXML2_INCLUDE_DIR "/usr/include/libxml2") + list(APPEND system_libs xml2) + list(APPEND system_libs ${CARBON_LIBRARY} ${FOUNDATION_LIBRARY} + ${CORE_FOUNDATION_LIBRARY} ${CORE_SERVICES_LIBRARY} ${SECURITY_LIBRARY} + ${DEBUG_SYMBOLS_LIBRARY}) +endif() + +# On FreeBSD, link libexecinfo because libc is missing backtrace() +if (CMAKE_SYSTEM_NAME MATCHES "FreeBSD") + list(APPEND system_libs execinfo) +endif() + +#add_subdirectory(include) +add_subdirectory(docs) +if (NOT CMAKE_SYSTEM_NAME MATCHES "Windows") + add_subdirectory(scripts) +endif() +add_subdirectory(source) +add_subdirectory(test) +add_subdirectory(tools) diff --git a/lldb/scripts/Python/python-wrapper.swig b/lldb/scripts/Python/python-wrapper.swig index 444b9c3e395a..cd133cfa8a27 100644 --- a/lldb/scripts/Python/python-wrapper.swig +++ b/lldb/scripts/Python/python-wrapper.swig @@ -1,998 +1,998 @@ -%header %{ - -template -PyObject * -SBTypeToSWIGWrapper (T* item); - -class PyErr_Cleaner -{ -public: - PyErr_Cleaner(bool print=false) : - m_print(print) - { - } - - ~PyErr_Cleaner() - { - if (PyErr_Occurred()) - { - if(m_print) - PyErr_Print(); - PyErr_Clear(); - } - } - -private: - bool m_print; -}; - -static PyObject* -ResolvePythonName(const char* name, - PyObject* pmodule) -{ - if (!name) - return pmodule; - - PyErr_Cleaner pyerr_cleanup(true); // show Python errors - - PyObject* main_dict; - - if (!pmodule) - { - pmodule = PyImport_AddModule ("__main__"); - if (!pmodule) - return NULL; - } - - if (PyType_Check(pmodule)) - { - main_dict = ((PyTypeObject*)pmodule)->tp_dict; - if (!main_dict) - return NULL; - } - else if (!PyDict_Check(pmodule)) - { - main_dict = PyModule_GetDict (pmodule); - if (!main_dict) - return NULL; - } - else - main_dict = pmodule; - - const char* dot_pos = ::strchr(name, '.'); - - PyObject *dest_object; - PyObject *key, *value; - Py_ssize_t pos = 0; - - if (!dot_pos) - { - dest_object = NULL; - while (PyDict_Next (main_dict, &pos, &key, &value)) - { - // We have stolen references to the key and value objects in the dictionary; we need to increment - // them now so that Python's garbage collector doesn't collect them out from under us. - Py_INCREF (key); - Py_INCREF (value); - if (strcmp (PyString_AsString (key), name) == 0) - { - dest_object = value; - break; - } - } - if (!dest_object || dest_object == Py_None) - return NULL; - return dest_object; - } - else - { - size_t len = dot_pos - name; - std::string piece(name,len); - pmodule = ResolvePythonName(piece.c_str(), main_dict); - if (!pmodule) - return NULL; - name = dot_pos+1; - return ResolvePythonName(dot_pos+1,pmodule); // tail recursion.. should be optimized by the compiler - } -} - -static PyObject* -FindSessionDictionary(const char *session_dictionary_name) -{ - return ResolvePythonName(session_dictionary_name, NULL); -} - -class PyCallable -{ -public: - - operator - bool () - { - return m_callable != NULL; - } - - template - PyObject* - operator () (Args... args) - { - return (*this)({SBTypeToSWIGWrapper(args)...}); - } - - PyObject* - operator () (std::initializer_list args) - { - PyObject* retval = NULL; - PyObject* pargs = PyTuple_New (args.size()); - if (pargs == NULL) - { - if (PyErr_Occurred()) - PyErr_Clear(); - return retval; - } - size_t idx = 0; - for (auto arg : args) - { - if (!arg) - return retval; - PyTuple_SetItem(pargs,idx,arg); - idx++; - } - retval = PyObject_CallObject (m_callable, pargs); - Py_XDECREF (pargs); - return retval; - } - - static PyCallable - FindWithPythonObject (PyObject* pfunc) - { - return PyCallable(pfunc); - } - - static PyCallable - FindWithFunctionName (const char *python_function_name, - const char *session_dictionary_name) - { - if (!python_function_name || !session_dictionary_name) - return PyCallable(); - if ( (python_function_name[0] == 0) || (session_dictionary_name[0] == 0) ) - return PyCallable(); - return FindWithFunctionName(python_function_name,FindSessionDictionary (session_dictionary_name)); - } - - static PyCallable - FindWithFunctionName (const char *python_function_name, - PyObject *session_dict) - { - if (!python_function_name || !session_dict) - return PyCallable(); - if ( (python_function_name[0] == 0)) - return PyCallable(); - return PyCallable(ResolvePythonName (python_function_name, session_dict)); - } - - static PyCallable - FindWithMemberFunction (PyObject *self, - const char *python_function_name) - { - if (self == NULL || self == Py_None) - return PyCallable(); - if (!python_function_name || (python_function_name[0] == 0)) - return PyCallable(); - return PyCallable(PyObject_GetAttrString(self, python_function_name)); - } - -private: - PyObject* m_callable; - - PyCallable (PyObject *callable = NULL) : - m_callable(callable) - { - if (m_callable && PyCallable_Check(m_callable) == false) - m_callable = NULL; - } -}; - -%} - -%wrapper %{ - -// resolve a dotted Python name in the form -// foo.bar.baz.Foobar to an actual Python object -// if pmodule is NULL, the __main__ module will be used -// as the starting point for the search - - -// This function is called by lldb_private::ScriptInterpreterPython::BreakpointCallbackFunction(...) -// and is used when a script command is attached to a breakpoint for execution. - -SWIGEXPORT bool -LLDBSwigPythonBreakpointCallbackFunction -( - const char *python_function_name, - const char *session_dictionary_name, - const lldb::StackFrameSP& frame_sp, - const lldb::BreakpointLocationSP& bp_loc_sp -) -{ - lldb::SBFrame sb_frame (frame_sp); - lldb::SBBreakpointLocation sb_bp_loc(bp_loc_sp); - - bool stop_at_breakpoint = true; - - { - PyErr_Cleaner py_err_cleaner(true); - - PyCallable pfunc = PyCallable::FindWithFunctionName(python_function_name,session_dictionary_name); - - if (!pfunc) - return stop_at_breakpoint; - - PyObject* session_dict = NULL; - PyObject* pvalue = NULL; - pvalue = pfunc(sb_frame, sb_bp_loc, session_dict = FindSessionDictionary(session_dictionary_name)); - - Py_XINCREF (session_dict); - - if (pvalue == Py_False) - stop_at_breakpoint = false; - - Py_XDECREF (pvalue); - } - - return stop_at_breakpoint; -} - -// This function is called by lldb_private::ScriptInterpreterPython::WatchpointCallbackFunction(...) -// and is used when a script command is attached to a watchpoint for execution. - -SWIGEXPORT bool -LLDBSwigPythonWatchpointCallbackFunction -( - const char *python_function_name, - const char *session_dictionary_name, - const lldb::StackFrameSP& frame_sp, - const lldb::WatchpointSP& wp_sp -) -{ - lldb::SBFrame sb_frame (frame_sp); - lldb::SBWatchpoint sb_wp(wp_sp); - - bool stop_at_watchpoint = true; - - { - PyErr_Cleaner py_err_cleaner(true); - - PyCallable pfunc = PyCallable::FindWithFunctionName(python_function_name,session_dictionary_name); - - if (!pfunc) - return stop_at_watchpoint; - - PyObject* session_dict = NULL; - PyObject* pvalue = NULL; - pvalue = pfunc(sb_frame, sb_wp, session_dict = FindSessionDictionary(session_dictionary_name)); - - Py_XINCREF (session_dict); - - if (pvalue == Py_False) - stop_at_watchpoint = false; - - Py_XDECREF (pvalue); - } - - return stop_at_watchpoint; -} - -bool -PyObjectToString (PyObject* object, - std::string& retval) -{ - retval.clear(); - bool was_ok = false; - if (object != NULL && object != Py_None) - { - if (PyString_Check(object)) - { - retval.assign(PyString_AsString(object)); - was_ok = true; - } - else - { - PyObject* value_as_string = PyObject_Str(object); - if (value_as_string && value_as_string != Py_None && PyString_Check(value_as_string)) - { - retval.assign(PyString_AsString(value_as_string)); - was_ok = true; - } - Py_XDECREF(value_as_string); - } - } - return was_ok; -} - -SWIGEXPORT bool -LLDBSwigPythonCallTypeScript -( - const char *python_function_name, - const void *session_dictionary, - const lldb::ValueObjectSP& valobj_sp, - void** pyfunct_wrapper, - std::string& retval -) -{ - lldb::SBValue sb_value (valobj_sp); - - retval.clear(); - - if (!python_function_name || !session_dictionary) - return false; - - PyObject *session_dict = (PyObject*)session_dictionary, *pfunc_impl = NULL, *pvalue = NULL; - - if (pyfunct_wrapper && *pyfunct_wrapper && PyFunction_Check (*pyfunct_wrapper)) - { - pfunc_impl = (PyObject*)(*pyfunct_wrapper); - if (pfunc_impl->ob_refcnt == 1) - { - Py_XDECREF(pfunc_impl); - pfunc_impl = NULL; - } - } - - if (PyDict_Check(session_dict)) - { - PyErr_Cleaner pyerr_cleanup(true); // show Python errors - - if (!pfunc_impl) - { - pfunc_impl = ResolvePythonName (python_function_name, session_dict); - if (!pfunc_impl || !PyCallable_Check (pfunc_impl)) - return false; - else - { - if (pyfunct_wrapper) - *pyfunct_wrapper = pfunc_impl; - } - } - /*else - printf("caching works!!!!\n");*/ - - PyCallable pfunc = PyCallable::FindWithPythonObject(pfunc_impl); - - if (!pfunc) - return false; - - pvalue = pfunc(sb_value,session_dict); - - Py_INCREF (session_dict); - - PyObjectToString(pvalue,retval); - - Py_XDECREF (pvalue); - } - return true; -} - -SWIGEXPORT void* -LLDBSwigPythonCreateSyntheticProvider -( - const char *python_class_name, - const char *session_dictionary_name, - const lldb::ValueObjectSP& valobj_sp -) -{ - PyObject* retval = NULL; - - if (python_class_name == NULL || python_class_name[0] == '\0' || !session_dictionary_name) - Py_RETURN_NONE; - - // I do not want the SBValue to be deallocated when going out of scope because python - // has ownership of it and will manage memory for this object by itself - lldb::SBValue *sb_value = new lldb::SBValue(valobj_sp); - sb_value->SetPreferSyntheticValue(false); - PyObject *ValObj_PyObj = SBTypeToSWIGWrapper(sb_value); - - if (ValObj_PyObj == NULL) - Py_RETURN_NONE; - - { - PyErr_Cleaner py_err_cleaner(true); - - PyCallable pfunc = PyCallable::FindWithFunctionName(python_class_name,session_dictionary_name); - - if (!pfunc) - return retval; - - Py_INCREF(ValObj_PyObj); - - PyObject* session_dict = NULL; - session_dict = FindSessionDictionary(session_dictionary_name); - retval = pfunc(sb_value, session_dict); - - Py_XINCREF (session_dict); - - Py_XINCREF(retval); - } - - if (retval) - return retval; - else - Py_RETURN_NONE; -} - -// wrapper that calls an optional instance member of an object taking no arguments -static PyObject* -LLDBSwigPython_CallOptionalMember -( - PyObject* self, - char* callee_name, - PyObject* ret_if_not_found = Py_None, - bool* was_found = NULL -) -{ - PyErr_Cleaner py_err_cleaner(false); - - PyCallable pfunc = PyCallable::FindWithMemberFunction(self,callee_name); - - if (!pfunc) - { - if (was_found) - *was_found = false; - Py_XINCREF(ret_if_not_found); - return ret_if_not_found; - } - - if (was_found) - *was_found = true; - - PyObject* py_return = pfunc(); - return py_return; -} - -SWIGEXPORT uint32_t -LLDBSwigPython_CalculateNumChildren -( - PyObject *implementor -) -{ - uint32_t ret_val = UINT32_MAX; - - static char callee_name[] = "num_children"; - - PyObject* py_return = LLDBSwigPython_CallOptionalMember(implementor,callee_name, NULL); - - if (!py_return) - return ret_val; - - if (PyInt_Check(py_return)) - ret_val = PyInt_AsLong(py_return); - - Py_XDECREF(py_return); - - if (PyErr_Occurred()) - { - PyErr_Print(); - PyErr_Clear(); - } - - return ret_val; -} - -SWIGEXPORT PyObject* -LLDBSwigPython_GetChildAtIndex -( - PyObject *implementor, - uint32_t idx -) -{ - PyErr_Cleaner py_err_cleaner(true); - - PyCallable pfunc = PyCallable::FindWithMemberFunction(implementor,"get_child_at_index"); - - if (!pfunc) - return NULL; - - PyObject *py_return = NULL; - py_return = pfunc(idx); - - if (py_return == NULL || py_return == Py_None) - { - Py_XDECREF(py_return); - return NULL; - } - - lldb::SBValue* sbvalue_ptr = NULL; - - if (SWIG_ConvertPtr(py_return, (void**)&sbvalue_ptr, SWIGTYPE_p_lldb__SBValue, 0) == -1) - { - Py_XDECREF(py_return); - return NULL; - } - - if (sbvalue_ptr == NULL) - return NULL; - - return py_return; -} - -SWIGEXPORT int -LLDBSwigPython_GetIndexOfChildWithName -( - PyObject *implementor, - const char* child_name -) -{ - PyErr_Cleaner py_err_cleaner(true); - - PyCallable pfunc = PyCallable::FindWithMemberFunction(implementor,"get_child_index"); - - if (!pfunc) - return UINT32_MAX; - - PyObject *py_return = NULL; - py_return = pfunc(child_name); - - if (py_return == NULL || py_return == Py_None) - { - Py_XDECREF(py_return); - return UINT32_MAX; - } - - long retval = PyInt_AsLong(py_return); - Py_XDECREF(py_return); - - if (retval >= 0) - return (uint32_t)retval; - - return UINT32_MAX; -} - -SWIGEXPORT bool -LLDBSwigPython_UpdateSynthProviderInstance -( - PyObject *implementor -) -{ - bool ret_val = false; - - static char callee_name[] = "update"; - - PyObject* py_return = LLDBSwigPython_CallOptionalMember(implementor,callee_name); - - if (py_return == Py_True) - ret_val = true; - - Py_XDECREF(py_return); - - return ret_val; -} - -SWIGEXPORT bool -LLDBSwigPython_MightHaveChildrenSynthProviderInstance -( - PyObject *implementor -) -{ - bool ret_val = false; - - static char callee_name[] = "has_children"; - - PyObject* py_return = LLDBSwigPython_CallOptionalMember(implementor,callee_name, Py_True); - - if (py_return == Py_True) - ret_val = true; - - Py_XDECREF(py_return); - - return ret_val; -} - -SWIGEXPORT void* -LLDBSWIGPython_CastPyObjectToSBValue -( - PyObject* data -) -{ - lldb::SBValue* sb_ptr = NULL; - - int valid_cast = SWIG_ConvertPtr(data, (void**)&sb_ptr, SWIGTYPE_p_lldb__SBValue, 0); - - if (valid_cast == -1) - return NULL; - - return sb_ptr; -} - -// Currently, SBCommandReturnObjectReleaser wraps a unique pointer to an -// lldb_private::CommandReturnObject. This means that the destructor for the -// SB object will deallocate its contained CommandReturnObject. Because that -// object is used as the real return object for Python-based commands, we want -// it to stay around. Thus, we release the unique pointer before returning from -// LLDBSwigPythonCallCommand, and to guarantee that the release will occur no -// matter how we exit from the function, we have a releaser object whose -// destructor does the right thing for us -class SBCommandReturnObjectReleaser -{ -public: - SBCommandReturnObjectReleaser (lldb::SBCommandReturnObject &obj) : - m_command_return_object_ref (obj) - { - } - - ~SBCommandReturnObjectReleaser () - { - m_command_return_object_ref.Release(); - } -private: - lldb::SBCommandReturnObject &m_command_return_object_ref; -}; - -SWIGEXPORT bool -LLDBSwigPythonCallCommand -( - const char *python_function_name, - const char *session_dictionary_name, - lldb::DebuggerSP& debugger, - const char* args, - lldb_private::CommandReturnObject& cmd_retobj -) -{ - - lldb::SBCommandReturnObject cmd_retobj_sb(&cmd_retobj); - SBCommandReturnObjectReleaser cmd_retobj_sb_releaser(cmd_retobj_sb); - lldb::SBDebugger debugger_sb(debugger); - - bool retval = false; - - { - PyErr_Cleaner py_err_cleaner(true); - PyCallable pfunc = PyCallable::FindWithFunctionName(python_function_name,session_dictionary_name); - - if (!pfunc) - return retval; - - PyObject* session_dict = NULL; - // pass the pointer-to cmd_retobj_sb or watch the underlying object disappear from under you - // see comment above for SBCommandReturnObjectReleaser for further details - PyObject* pvalue = NULL; - pvalue = pfunc(debugger_sb, args, &cmd_retobj_sb, session_dict = FindSessionDictionary(session_dictionary_name)); - - Py_XINCREF (session_dict); - Py_XDECREF (pvalue); - - retval = true; - } - - return retval; -} - -SWIGEXPORT void* -LLDBSWIGPythonCreateOSPlugin -( - const char *python_class_name, - const char *session_dictionary_name, - const lldb::ProcessSP& process_sp -) -{ - PyObject* retval = NULL; - - if (python_class_name == NULL || python_class_name[0] == '\0' || !session_dictionary_name) - Py_RETURN_NONE; - - // I do not want the SBProcess to be deallocated when going out of scope because python - // has ownership of it and will manage memory for this object by itself - lldb::SBProcess *process_sb = new lldb::SBProcess(process_sp); - - PyObject *SBProc_PyObj = SBTypeToSWIGWrapper(process_sb); - - if (SBProc_PyObj == NULL) - Py_RETURN_NONE; - - { - PyErr_Cleaner py_err_cleaner(true); - - PyCallable pfunc = PyCallable::FindWithFunctionName(python_class_name,session_dictionary_name); - - if (!pfunc) - return retval; - - Py_INCREF(SBProc_PyObj); - - PyObject* session_dict = NULL; - session_dict = session_dict = FindSessionDictionary(session_dictionary_name); - retval = pfunc(SBProc_PyObj); - - Py_XINCREF (session_dict); - - Py_XINCREF(retval); - } - - if (retval) - return retval; - else - Py_RETURN_NONE; -} - -SWIGEXPORT bool -LLDBSWIGPythonRunScriptKeywordProcess -(const char* python_function_name, -const char* session_dictionary_name, -lldb::ProcessSP& process, -std::string& output) - -{ - bool retval = false; - - if (python_function_name == NULL || python_function_name[0] == '\0' || !session_dictionary_name) - return retval; - - lldb::SBProcess process_sb(process); - - { - PyErr_Cleaner py_err_cleaner(true); - - PyCallable pfunc = PyCallable::FindWithFunctionName(python_function_name,session_dictionary_name); - - if (!pfunc) - return retval; - - PyObject* session_dict = NULL; - PyObject* pvalue = NULL; - pvalue = pfunc(process_sb, session_dict = FindSessionDictionary(session_dictionary_name)); - - Py_XINCREF (session_dict); - - if (PyObjectToString(pvalue,output)) - retval = true; - - Py_XDECREF(pvalue); - } - - return retval; -} - -SWIGEXPORT bool -LLDBSWIGPythonRunScriptKeywordThread -(const char* python_function_name, -const char* session_dictionary_name, -lldb::ThreadSP& thread, -std::string& output) - -{ - bool retval = false; - - if (python_function_name == NULL || python_function_name[0] == '\0' || !session_dictionary_name) - return retval; - - lldb::SBThread thread_sb(thread); - - { - PyErr_Cleaner py_err_cleaner(true); - - PyCallable pfunc = PyCallable::FindWithFunctionName(python_function_name,session_dictionary_name); - - if (!pfunc) - return retval; - - PyObject* session_dict = NULL; - PyObject* pvalue = NULL; - pvalue = pfunc(thread_sb, session_dict = FindSessionDictionary(session_dictionary_name)); - - Py_XINCREF (session_dict); - - if (PyObjectToString(pvalue,output)) - retval = true; - - Py_XDECREF(pvalue); - } - - return retval; -} - -SWIGEXPORT bool -LLDBSWIGPythonRunScriptKeywordTarget -(const char* python_function_name, -const char* session_dictionary_name, -lldb::TargetSP& target, -std::string& output) - -{ - bool retval = false; - - if (python_function_name == NULL || python_function_name[0] == '\0' || !session_dictionary_name) - return retval; - - lldb::SBTarget target_sb(target); - - { - PyErr_Cleaner py_err_cleaner(true); - - PyCallable pfunc = PyCallable::FindWithFunctionName(python_function_name,session_dictionary_name); - - if (!pfunc) - return retval; - - PyObject* session_dict = NULL; - PyObject* pvalue = NULL; - pvalue = pfunc(target_sb, session_dict = FindSessionDictionary(session_dictionary_name)); - - Py_XINCREF (session_dict); - - if (PyObjectToString(pvalue,output)) - retval = true; - - Py_XDECREF(pvalue); - } - - return retval; -} - -SWIGEXPORT bool -LLDBSWIGPythonRunScriptKeywordFrame -(const char* python_function_name, -const char* session_dictionary_name, -lldb::StackFrameSP& frame, -std::string& output) - -{ - bool retval = false; - - if (python_function_name == NULL || python_function_name[0] == '\0' || !session_dictionary_name) - return retval; - - lldb::SBFrame frame_sb(frame); - - { - PyErr_Cleaner py_err_cleaner(true); - - PyCallable pfunc = PyCallable::FindWithFunctionName(python_function_name,session_dictionary_name); - - if (!pfunc) - return retval; - - PyObject* session_dict = NULL; - PyObject* pvalue = NULL; - pvalue = pfunc(frame_sb, session_dict = FindSessionDictionary(session_dictionary_name)); - - Py_XINCREF (session_dict); - - if (PyObjectToString(pvalue,output)) - retval = true; - - Py_XDECREF(pvalue); - } - - return retval; -} - -SWIGEXPORT bool -LLDBSwigPythonCallModuleInit -( - const char *python_module_name, - const char *session_dictionary_name, - lldb::DebuggerSP& debugger -) -{ - bool retval = false; - - lldb::SBDebugger debugger_sb(debugger); - - std::string python_function_name_string = python_module_name; - python_function_name_string += ".__lldb_init_module"; - const char* python_function_name = python_function_name_string.c_str(); - - { - PyErr_Cleaner py_err_cleaner(true); - - PyCallable pfunc = PyCallable::FindWithFunctionName(python_function_name,session_dictionary_name); - - if (!pfunc) - return true; - - PyObject* session_dict = NULL; - PyObject* pvalue = NULL; - pvalue = pfunc(debugger_sb, session_dict = FindSessionDictionary(session_dictionary_name)); - - Py_XINCREF (session_dict); - - retval = true; - - Py_XDECREF(pvalue); - } - - return retval; -} -%} - - -%runtime %{ -// Forward declaration to be inserted at the start of LLDBWrapPython.h -// I used runtime as a hack to make SWIG place it where it's needed. -// This is needed to use LLDBSwigPythonCallSBInputReaderCallback in the -// typemaps and in the extensions (SBInputReader.__del__()). -#include "lldb/API/SBInputReader.h" -#include "lldb/API/SBDebugger.h" -#include "lldb/API/SBValue.h" - -SWIGEXPORT lldb::ValueObjectSP -LLDBSWIGPython_GetValueObjectSPFromSBValue (void* data) -{ - lldb::ValueObjectSP valobj_sp; - if (data) - { - lldb::SBValue* sb_ptr = (lldb::SBValue *)data; - valobj_sp = sb_ptr->GetSP(); - } - return valobj_sp; -} - -#ifdef __cplusplus -extern "C" { -#endif - -size_t -LLDBSwigPythonCallSBInputReaderCallback(void *baton, - lldb::SBInputReader *reader, - lldb::InputReaderAction notification, - const char*bytes, - size_t bytes_len); - -void LLDBSwigPythonCallPythonLogOutputCallback(const char *str, void *baton); - -#ifdef __cplusplus -} -#endif -%} - -%wrapper %{ -// For the InputReader Callback functions -SWIGEXPORT size_t -LLDBSwigPythonCallSBInputReaderCallback(void *baton, - lldb::SBInputReader *reader, - lldb::InputReaderAction notification, - const char*bytes, - size_t bytes_len) { - if (baton != Py_None) { - SWIG_PYTHON_THREAD_BEGIN_BLOCK; - - PyObject *py_InputReader = SBTypeToSWIGWrapper(reader); - PyObject *py_Notification = PyInt_FromLong(notification); - PyObject *py_Bytes = PyBytes_FromStringAndSize(bytes, bytes_len); - - PyObject *tuple = PyTuple_Pack(3, py_InputReader, py_Notification, py_Bytes); - PyObject *res = PyObject_Call(reinterpret_cast(baton), tuple, NULL); - Py_XDECREF(tuple); - Py_XDECREF(py_InputReader); - Py_XDECREF(py_Notification); - Py_XDECREF(py_Bytes); - - if (res == NULL) { - PyObject *exc = PyErr_Occurred(); - if (exc) { - ::puts("\nErroring out at LLDBSwigPythonCallSBInputReaderCallback"); - PyErr_Print(); - } - return 0; - } - - size_t result = 0; - // If the callback misbehaves and returns Py_None, assume it returned 0 - if (res != Py_None) - result = static_cast(PyInt_AsSsize_t(res)); - - Py_XDECREF(res); - SWIG_PYTHON_THREAD_END_BLOCK; - return result; - } - return 0; -} - -// For the LogOutputCallback functions -void LLDBSwigPythonCallPythonLogOutputCallback(const char *str, void *baton) { - if (baton != Py_None) { - SWIG_PYTHON_THREAD_BEGIN_BLOCK; - PyObject_CallFunction(reinterpret_cast(baton), const_cast("s"), str); - SWIG_PYTHON_THREAD_END_BLOCK; - } -} -%} +%header %{ + +template +PyObject * +SBTypeToSWIGWrapper (T* item); + +class PyErr_Cleaner +{ +public: + PyErr_Cleaner(bool print=false) : + m_print(print) + { + } + + ~PyErr_Cleaner() + { + if (PyErr_Occurred()) + { + if(m_print) + PyErr_Print(); + PyErr_Clear(); + } + } + +private: + bool m_print; +}; + +static PyObject* +ResolvePythonName(const char* name, + PyObject* pmodule) +{ + if (!name) + return pmodule; + + PyErr_Cleaner pyerr_cleanup(true); // show Python errors + + PyObject* main_dict; + + if (!pmodule) + { + pmodule = PyImport_AddModule ("__main__"); + if (!pmodule) + return NULL; + } + + if (PyType_Check(pmodule)) + { + main_dict = ((PyTypeObject*)pmodule)->tp_dict; + if (!main_dict) + return NULL; + } + else if (!PyDict_Check(pmodule)) + { + main_dict = PyModule_GetDict (pmodule); + if (!main_dict) + return NULL; + } + else + main_dict = pmodule; + + const char* dot_pos = ::strchr(name, '.'); + + PyObject *dest_object; + PyObject *key, *value; + Py_ssize_t pos = 0; + + if (!dot_pos) + { + dest_object = NULL; + while (PyDict_Next (main_dict, &pos, &key, &value)) + { + // We have stolen references to the key and value objects in the dictionary; we need to increment + // them now so that Python's garbage collector doesn't collect them out from under us. + Py_INCREF (key); + Py_INCREF (value); + if (strcmp (PyString_AsString (key), name) == 0) + { + dest_object = value; + break; + } + } + if (!dest_object || dest_object == Py_None) + return NULL; + return dest_object; + } + else + { + size_t len = dot_pos - name; + std::string piece(name,len); + pmodule = ResolvePythonName(piece.c_str(), main_dict); + if (!pmodule) + return NULL; + name = dot_pos+1; + return ResolvePythonName(dot_pos+1,pmodule); // tail recursion.. should be optimized by the compiler + } +} + +static PyObject* +FindSessionDictionary(const char *session_dictionary_name) +{ + return ResolvePythonName(session_dictionary_name, NULL); +} + +class PyCallable +{ +public: + + operator + bool () + { + return m_callable != NULL; + } + + template + PyObject* + operator () (Args... args) + { + return (*this)({SBTypeToSWIGWrapper(args)...}); + } + + PyObject* + operator () (std::initializer_list args) + { + PyObject* retval = NULL; + PyObject* pargs = PyTuple_New (args.size()); + if (pargs == NULL) + { + if (PyErr_Occurred()) + PyErr_Clear(); + return retval; + } + size_t idx = 0; + for (auto arg : args) + { + if (!arg) + return retval; + PyTuple_SetItem(pargs,idx,arg); + idx++; + } + retval = PyObject_CallObject (m_callable, pargs); + Py_XDECREF (pargs); + return retval; + } + + static PyCallable + FindWithPythonObject (PyObject* pfunc) + { + return PyCallable(pfunc); + } + + static PyCallable + FindWithFunctionName (const char *python_function_name, + const char *session_dictionary_name) + { + if (!python_function_name || !session_dictionary_name) + return PyCallable(); + if ( (python_function_name[0] == 0) || (session_dictionary_name[0] == 0) ) + return PyCallable(); + return FindWithFunctionName(python_function_name,FindSessionDictionary (session_dictionary_name)); + } + + static PyCallable + FindWithFunctionName (const char *python_function_name, + PyObject *session_dict) + { + if (!python_function_name || !session_dict) + return PyCallable(); + if ( (python_function_name[0] == 0)) + return PyCallable(); + return PyCallable(ResolvePythonName (python_function_name, session_dict)); + } + + static PyCallable + FindWithMemberFunction (PyObject *self, + const char *python_function_name) + { + if (self == NULL || self == Py_None) + return PyCallable(); + if (!python_function_name || (python_function_name[0] == 0)) + return PyCallable(); + return PyCallable(PyObject_GetAttrString(self, python_function_name)); + } + +private: + PyObject* m_callable; + + PyCallable (PyObject *callable = NULL) : + m_callable(callable) + { + if (m_callable && PyCallable_Check(m_callable) == false) + m_callable = NULL; + } +}; + +%} + +%wrapper %{ + +// resolve a dotted Python name in the form +// foo.bar.baz.Foobar to an actual Python object +// if pmodule is NULL, the __main__ module will be used +// as the starting point for the search + + +// This function is called by lldb_private::ScriptInterpreterPython::BreakpointCallbackFunction(...) +// and is used when a script command is attached to a breakpoint for execution. + +SWIGEXPORT bool +LLDBSwigPythonBreakpointCallbackFunction +( + const char *python_function_name, + const char *session_dictionary_name, + const lldb::StackFrameSP& frame_sp, + const lldb::BreakpointLocationSP& bp_loc_sp +) +{ + lldb::SBFrame sb_frame (frame_sp); + lldb::SBBreakpointLocation sb_bp_loc(bp_loc_sp); + + bool stop_at_breakpoint = true; + + { + PyErr_Cleaner py_err_cleaner(true); + + PyCallable pfunc = PyCallable::FindWithFunctionName(python_function_name,session_dictionary_name); + + if (!pfunc) + return stop_at_breakpoint; + + PyObject* session_dict = NULL; + PyObject* pvalue = NULL; + pvalue = pfunc(sb_frame, sb_bp_loc, session_dict = FindSessionDictionary(session_dictionary_name)); + + Py_XINCREF (session_dict); + + if (pvalue == Py_False) + stop_at_breakpoint = false; + + Py_XDECREF (pvalue); + } + + return stop_at_breakpoint; +} + +// This function is called by lldb_private::ScriptInterpreterPython::WatchpointCallbackFunction(...) +// and is used when a script command is attached to a watchpoint for execution. + +SWIGEXPORT bool +LLDBSwigPythonWatchpointCallbackFunction +( + const char *python_function_name, + const char *session_dictionary_name, + const lldb::StackFrameSP& frame_sp, + const lldb::WatchpointSP& wp_sp +) +{ + lldb::SBFrame sb_frame (frame_sp); + lldb::SBWatchpoint sb_wp(wp_sp); + + bool stop_at_watchpoint = true; + + { + PyErr_Cleaner py_err_cleaner(true); + + PyCallable pfunc = PyCallable::FindWithFunctionName(python_function_name,session_dictionary_name); + + if (!pfunc) + return stop_at_watchpoint; + + PyObject* session_dict = NULL; + PyObject* pvalue = NULL; + pvalue = pfunc(sb_frame, sb_wp, session_dict = FindSessionDictionary(session_dictionary_name)); + + Py_XINCREF (session_dict); + + if (pvalue == Py_False) + stop_at_watchpoint = false; + + Py_XDECREF (pvalue); + } + + return stop_at_watchpoint; +} + +bool +PyObjectToString (PyObject* object, + std::string& retval) +{ + retval.clear(); + bool was_ok = false; + if (object != NULL && object != Py_None) + { + if (PyString_Check(object)) + { + retval.assign(PyString_AsString(object)); + was_ok = true; + } + else + { + PyObject* value_as_string = PyObject_Str(object); + if (value_as_string && value_as_string != Py_None && PyString_Check(value_as_string)) + { + retval.assign(PyString_AsString(value_as_string)); + was_ok = true; + } + Py_XDECREF(value_as_string); + } + } + return was_ok; +} + +SWIGEXPORT bool +LLDBSwigPythonCallTypeScript +( + const char *python_function_name, + const void *session_dictionary, + const lldb::ValueObjectSP& valobj_sp, + void** pyfunct_wrapper, + std::string& retval +) +{ + lldb::SBValue sb_value (valobj_sp); + + retval.clear(); + + if (!python_function_name || !session_dictionary) + return false; + + PyObject *session_dict = (PyObject*)session_dictionary, *pfunc_impl = NULL, *pvalue = NULL; + + if (pyfunct_wrapper && *pyfunct_wrapper && PyFunction_Check (*pyfunct_wrapper)) + { + pfunc_impl = (PyObject*)(*pyfunct_wrapper); + if (pfunc_impl->ob_refcnt == 1) + { + Py_XDECREF(pfunc_impl); + pfunc_impl = NULL; + } + } + + if (PyDict_Check(session_dict)) + { + PyErr_Cleaner pyerr_cleanup(true); // show Python errors + + if (!pfunc_impl) + { + pfunc_impl = ResolvePythonName (python_function_name, session_dict); + if (!pfunc_impl || !PyCallable_Check (pfunc_impl)) + return false; + else + { + if (pyfunct_wrapper) + *pyfunct_wrapper = pfunc_impl; + } + } + /*else + printf("caching works!!!!\n");*/ + + PyCallable pfunc = PyCallable::FindWithPythonObject(pfunc_impl); + + if (!pfunc) + return false; + + pvalue = pfunc(sb_value,session_dict); + + Py_INCREF (session_dict); + + PyObjectToString(pvalue,retval); + + Py_XDECREF (pvalue); + } + return true; +} + +SWIGEXPORT void* +LLDBSwigPythonCreateSyntheticProvider +( + const char *python_class_name, + const char *session_dictionary_name, + const lldb::ValueObjectSP& valobj_sp +) +{ + PyObject* retval = NULL; + + if (python_class_name == NULL || python_class_name[0] == '\0' || !session_dictionary_name) + Py_RETURN_NONE; + + // I do not want the SBValue to be deallocated when going out of scope because python + // has ownership of it and will manage memory for this object by itself + lldb::SBValue *sb_value = new lldb::SBValue(valobj_sp); + sb_value->SetPreferSyntheticValue(false); + PyObject *ValObj_PyObj = SBTypeToSWIGWrapper(sb_value); + + if (ValObj_PyObj == NULL) + Py_RETURN_NONE; + + { + PyErr_Cleaner py_err_cleaner(true); + + PyCallable pfunc = PyCallable::FindWithFunctionName(python_class_name,session_dictionary_name); + + if (!pfunc) + return retval; + + Py_INCREF(ValObj_PyObj); + + PyObject* session_dict = NULL; + session_dict = FindSessionDictionary(session_dictionary_name); + retval = pfunc(sb_value, session_dict); + + Py_XINCREF (session_dict); + + Py_XINCREF(retval); + } + + if (retval) + return retval; + else + Py_RETURN_NONE; +} + +// wrapper that calls an optional instance member of an object taking no arguments +static PyObject* +LLDBSwigPython_CallOptionalMember +( + PyObject* self, + char* callee_name, + PyObject* ret_if_not_found = Py_None, + bool* was_found = NULL +) +{ + PyErr_Cleaner py_err_cleaner(false); + + PyCallable pfunc = PyCallable::FindWithMemberFunction(self,callee_name); + + if (!pfunc) + { + if (was_found) + *was_found = false; + Py_XINCREF(ret_if_not_found); + return ret_if_not_found; + } + + if (was_found) + *was_found = true; + + PyObject* py_return = pfunc(); + return py_return; +} + +SWIGEXPORT uint32_t +LLDBSwigPython_CalculateNumChildren +( + PyObject *implementor +) +{ + uint32_t ret_val = UINT32_MAX; + + static char callee_name[] = "num_children"; + + PyObject* py_return = LLDBSwigPython_CallOptionalMember(implementor,callee_name, NULL); + + if (!py_return) + return ret_val; + + if (PyInt_Check(py_return)) + ret_val = PyInt_AsLong(py_return); + + Py_XDECREF(py_return); + + if (PyErr_Occurred()) + { + PyErr_Print(); + PyErr_Clear(); + } + + return ret_val; +} + +SWIGEXPORT PyObject* +LLDBSwigPython_GetChildAtIndex +( + PyObject *implementor, + uint32_t idx +) +{ + PyErr_Cleaner py_err_cleaner(true); + + PyCallable pfunc = PyCallable::FindWithMemberFunction(implementor,"get_child_at_index"); + + if (!pfunc) + return NULL; + + PyObject *py_return = NULL; + py_return = pfunc(idx); + + if (py_return == NULL || py_return == Py_None) + { + Py_XDECREF(py_return); + return NULL; + } + + lldb::SBValue* sbvalue_ptr = NULL; + + if (SWIG_ConvertPtr(py_return, (void**)&sbvalue_ptr, SWIGTYPE_p_lldb__SBValue, 0) == -1) + { + Py_XDECREF(py_return); + return NULL; + } + + if (sbvalue_ptr == NULL) + return NULL; + + return py_return; +} + +SWIGEXPORT int +LLDBSwigPython_GetIndexOfChildWithName +( + PyObject *implementor, + const char* child_name +) +{ + PyErr_Cleaner py_err_cleaner(true); + + PyCallable pfunc = PyCallable::FindWithMemberFunction(implementor,"get_child_index"); + + if (!pfunc) + return UINT32_MAX; + + PyObject *py_return = NULL; + py_return = pfunc(child_name); + + if (py_return == NULL || py_return == Py_None) + { + Py_XDECREF(py_return); + return UINT32_MAX; + } + + long retval = PyInt_AsLong(py_return); + Py_XDECREF(py_return); + + if (retval >= 0) + return (uint32_t)retval; + + return UINT32_MAX; +} + +SWIGEXPORT bool +LLDBSwigPython_UpdateSynthProviderInstance +( + PyObject *implementor +) +{ + bool ret_val = false; + + static char callee_name[] = "update"; + + PyObject* py_return = LLDBSwigPython_CallOptionalMember(implementor,callee_name); + + if (py_return == Py_True) + ret_val = true; + + Py_XDECREF(py_return); + + return ret_val; +} + +SWIGEXPORT bool +LLDBSwigPython_MightHaveChildrenSynthProviderInstance +( + PyObject *implementor +) +{ + bool ret_val = false; + + static char callee_name[] = "has_children"; + + PyObject* py_return = LLDBSwigPython_CallOptionalMember(implementor,callee_name, Py_True); + + if (py_return == Py_True) + ret_val = true; + + Py_XDECREF(py_return); + + return ret_val; +} + +SWIGEXPORT void* +LLDBSWIGPython_CastPyObjectToSBValue +( + PyObject* data +) +{ + lldb::SBValue* sb_ptr = NULL; + + int valid_cast = SWIG_ConvertPtr(data, (void**)&sb_ptr, SWIGTYPE_p_lldb__SBValue, 0); + + if (valid_cast == -1) + return NULL; + + return sb_ptr; +} + +// Currently, SBCommandReturnObjectReleaser wraps a unique pointer to an +// lldb_private::CommandReturnObject. This means that the destructor for the +// SB object will deallocate its contained CommandReturnObject. Because that +// object is used as the real return object for Python-based commands, we want +// it to stay around. Thus, we release the unique pointer before returning from +// LLDBSwigPythonCallCommand, and to guarantee that the release will occur no +// matter how we exit from the function, we have a releaser object whose +// destructor does the right thing for us +class SBCommandReturnObjectReleaser +{ +public: + SBCommandReturnObjectReleaser (lldb::SBCommandReturnObject &obj) : + m_command_return_object_ref (obj) + { + } + + ~SBCommandReturnObjectReleaser () + { + m_command_return_object_ref.Release(); + } +private: + lldb::SBCommandReturnObject &m_command_return_object_ref; +}; + +SWIGEXPORT bool +LLDBSwigPythonCallCommand +( + const char *python_function_name, + const char *session_dictionary_name, + lldb::DebuggerSP& debugger, + const char* args, + lldb_private::CommandReturnObject& cmd_retobj +) +{ + + lldb::SBCommandReturnObject cmd_retobj_sb(&cmd_retobj); + SBCommandReturnObjectReleaser cmd_retobj_sb_releaser(cmd_retobj_sb); + lldb::SBDebugger debugger_sb(debugger); + + bool retval = false; + + { + PyErr_Cleaner py_err_cleaner(true); + PyCallable pfunc = PyCallable::FindWithFunctionName(python_function_name,session_dictionary_name); + + if (!pfunc) + return retval; + + PyObject* session_dict = NULL; + // pass the pointer-to cmd_retobj_sb or watch the underlying object disappear from under you + // see comment above for SBCommandReturnObjectReleaser for further details + PyObject* pvalue = NULL; + pvalue = pfunc(debugger_sb, args, &cmd_retobj_sb, session_dict = FindSessionDictionary(session_dictionary_name)); + + Py_XINCREF (session_dict); + Py_XDECREF (pvalue); + + retval = true; + } + + return retval; +} + +SWIGEXPORT void* +LLDBSWIGPythonCreateOSPlugin +( + const char *python_class_name, + const char *session_dictionary_name, + const lldb::ProcessSP& process_sp +) +{ + PyObject* retval = NULL; + + if (python_class_name == NULL || python_class_name[0] == '\0' || !session_dictionary_name) + Py_RETURN_NONE; + + // I do not want the SBProcess to be deallocated when going out of scope because python + // has ownership of it and will manage memory for this object by itself + lldb::SBProcess *process_sb = new lldb::SBProcess(process_sp); + + PyObject *SBProc_PyObj = SBTypeToSWIGWrapper(process_sb); + + if (SBProc_PyObj == NULL) + Py_RETURN_NONE; + + { + PyErr_Cleaner py_err_cleaner(true); + + PyCallable pfunc = PyCallable::FindWithFunctionName(python_class_name,session_dictionary_name); + + if (!pfunc) + return retval; + + Py_INCREF(SBProc_PyObj); + + PyObject* session_dict = NULL; + session_dict = session_dict = FindSessionDictionary(session_dictionary_name); + retval = pfunc(SBProc_PyObj); + + Py_XINCREF (session_dict); + + Py_XINCREF(retval); + } + + if (retval) + return retval; + else + Py_RETURN_NONE; +} + +SWIGEXPORT bool +LLDBSWIGPythonRunScriptKeywordProcess +(const char* python_function_name, +const char* session_dictionary_name, +lldb::ProcessSP& process, +std::string& output) + +{ + bool retval = false; + + if (python_function_name == NULL || python_function_name[0] == '\0' || !session_dictionary_name) + return retval; + + lldb::SBProcess process_sb(process); + + { + PyErr_Cleaner py_err_cleaner(true); + + PyCallable pfunc = PyCallable::FindWithFunctionName(python_function_name,session_dictionary_name); + + if (!pfunc) + return retval; + + PyObject* session_dict = NULL; + PyObject* pvalue = NULL; + pvalue = pfunc(process_sb, session_dict = FindSessionDictionary(session_dictionary_name)); + + Py_XINCREF (session_dict); + + if (PyObjectToString(pvalue,output)) + retval = true; + + Py_XDECREF(pvalue); + } + + return retval; +} + +SWIGEXPORT bool +LLDBSWIGPythonRunScriptKeywordThread +(const char* python_function_name, +const char* session_dictionary_name, +lldb::ThreadSP& thread, +std::string& output) + +{ + bool retval = false; + + if (python_function_name == NULL || python_function_name[0] == '\0' || !session_dictionary_name) + return retval; + + lldb::SBThread thread_sb(thread); + + { + PyErr_Cleaner py_err_cleaner(true); + + PyCallable pfunc = PyCallable::FindWithFunctionName(python_function_name,session_dictionary_name); + + if (!pfunc) + return retval; + + PyObject* session_dict = NULL; + PyObject* pvalue = NULL; + pvalue = pfunc(thread_sb, session_dict = FindSessionDictionary(session_dictionary_name)); + + Py_XINCREF (session_dict); + + if (PyObjectToString(pvalue,output)) + retval = true; + + Py_XDECREF(pvalue); + } + + return retval; +} + +SWIGEXPORT bool +LLDBSWIGPythonRunScriptKeywordTarget +(const char* python_function_name, +const char* session_dictionary_name, +lldb::TargetSP& target, +std::string& output) + +{ + bool retval = false; + + if (python_function_name == NULL || python_function_name[0] == '\0' || !session_dictionary_name) + return retval; + + lldb::SBTarget target_sb(target); + + { + PyErr_Cleaner py_err_cleaner(true); + + PyCallable pfunc = PyCallable::FindWithFunctionName(python_function_name,session_dictionary_name); + + if (!pfunc) + return retval; + + PyObject* session_dict = NULL; + PyObject* pvalue = NULL; + pvalue = pfunc(target_sb, session_dict = FindSessionDictionary(session_dictionary_name)); + + Py_XINCREF (session_dict); + + if (PyObjectToString(pvalue,output)) + retval = true; + + Py_XDECREF(pvalue); + } + + return retval; +} + +SWIGEXPORT bool +LLDBSWIGPythonRunScriptKeywordFrame +(const char* python_function_name, +const char* session_dictionary_name, +lldb::StackFrameSP& frame, +std::string& output) + +{ + bool retval = false; + + if (python_function_name == NULL || python_function_name[0] == '\0' || !session_dictionary_name) + return retval; + + lldb::SBFrame frame_sb(frame); + + { + PyErr_Cleaner py_err_cleaner(true); + + PyCallable pfunc = PyCallable::FindWithFunctionName(python_function_name,session_dictionary_name); + + if (!pfunc) + return retval; + + PyObject* session_dict = NULL; + PyObject* pvalue = NULL; + pvalue = pfunc(frame_sb, session_dict = FindSessionDictionary(session_dictionary_name)); + + Py_XINCREF (session_dict); + + if (PyObjectToString(pvalue,output)) + retval = true; + + Py_XDECREF(pvalue); + } + + return retval; +} + +SWIGEXPORT bool +LLDBSwigPythonCallModuleInit +( + const char *python_module_name, + const char *session_dictionary_name, + lldb::DebuggerSP& debugger +) +{ + bool retval = false; + + lldb::SBDebugger debugger_sb(debugger); + + std::string python_function_name_string = python_module_name; + python_function_name_string += ".__lldb_init_module"; + const char* python_function_name = python_function_name_string.c_str(); + + { + PyErr_Cleaner py_err_cleaner(true); + + PyCallable pfunc = PyCallable::FindWithFunctionName(python_function_name,session_dictionary_name); + + if (!pfunc) + return true; + + PyObject* session_dict = NULL; + PyObject* pvalue = NULL; + pvalue = pfunc(debugger_sb, session_dict = FindSessionDictionary(session_dictionary_name)); + + Py_XINCREF (session_dict); + + retval = true; + + Py_XDECREF(pvalue); + } + + return retval; +} +%} + + +%runtime %{ +// Forward declaration to be inserted at the start of LLDBWrapPython.h +// I used runtime as a hack to make SWIG place it where it's needed. +// This is needed to use LLDBSwigPythonCallSBInputReaderCallback in the +// typemaps and in the extensions (SBInputReader.__del__()). +#include "lldb/API/SBInputReader.h" +#include "lldb/API/SBDebugger.h" +#include "lldb/API/SBValue.h" + +SWIGEXPORT lldb::ValueObjectSP +LLDBSWIGPython_GetValueObjectSPFromSBValue (void* data) +{ + lldb::ValueObjectSP valobj_sp; + if (data) + { + lldb::SBValue* sb_ptr = (lldb::SBValue *)data; + valobj_sp = sb_ptr->GetSP(); + } + return valobj_sp; +} + +#ifdef __cplusplus +extern "C" { +#endif + +size_t +LLDBSwigPythonCallSBInputReaderCallback(void *baton, + lldb::SBInputReader *reader, + lldb::InputReaderAction notification, + const char*bytes, + size_t bytes_len); + +void LLDBSwigPythonCallPythonLogOutputCallback(const char *str, void *baton); + +#ifdef __cplusplus +} +#endif +%} + +%wrapper %{ +// For the InputReader Callback functions +SWIGEXPORT size_t +LLDBSwigPythonCallSBInputReaderCallback(void *baton, + lldb::SBInputReader *reader, + lldb::InputReaderAction notification, + const char*bytes, + size_t bytes_len) { + if (baton != Py_None) { + SWIG_PYTHON_THREAD_BEGIN_BLOCK; + + PyObject *py_InputReader = SBTypeToSWIGWrapper(reader); + PyObject *py_Notification = PyInt_FromLong(notification); + PyObject *py_Bytes = PyBytes_FromStringAndSize(bytes, bytes_len); + + PyObject *tuple = PyTuple_Pack(3, py_InputReader, py_Notification, py_Bytes); + PyObject *res = PyObject_Call(reinterpret_cast(baton), tuple, NULL); + Py_XDECREF(tuple); + Py_XDECREF(py_InputReader); + Py_XDECREF(py_Notification); + Py_XDECREF(py_Bytes); + + if (res == NULL) { + PyObject *exc = PyErr_Occurred(); + if (exc) { + ::puts("\nErroring out at LLDBSwigPythonCallSBInputReaderCallback"); + PyErr_Print(); + } + return 0; + } + + size_t result = 0; + // If the callback misbehaves and returns Py_None, assume it returned 0 + if (res != Py_None) + result = static_cast(PyInt_AsSsize_t(res)); + + Py_XDECREF(res); + SWIG_PYTHON_THREAD_END_BLOCK; + return result; + } + return 0; +} + +// For the LogOutputCallback functions +void LLDBSwigPythonCallPythonLogOutputCallback(const char *str, void *baton) { + if (baton != Py_None) { + SWIG_PYTHON_THREAD_BEGIN_BLOCK; + PyObject_CallFunction(reinterpret_cast(baton), const_cast("s"), str); + SWIG_PYTHON_THREAD_END_BLOCK; + } +} +%} diff --git a/lldb/source/API/CMakeLists.txt b/lldb/source/API/CMakeLists.txt index 2170c9a62f2c..ef70ad593b74 100644 --- a/lldb/source/API/CMakeLists.txt +++ b/lldb/source/API/CMakeLists.txt @@ -1,51 +1,51 @@ -set(LLVM_NO_RTTI 1) - -add_lldb_library(lldbAPI - SBAddress.cpp - SBBlock.cpp - SBBreakpoint.cpp - SBBreakpointLocation.cpp - SBBroadcaster.cpp - SBCommandInterpreter.cpp - SBCommandReturnObject.cpp - SBCommunication.cpp - SBCompileUnit.cpp - SBData.cpp - SBDebugger.cpp - SBDeclaration.cpp - SBError.cpp - SBEvent.cpp - SBExpressionOptions.cpp - SBFileSpec.cpp - SBFileSpecList.cpp - SBFrame.cpp - SBFunction.cpp - SBHostOS.cpp - SBInputReader.cpp - SBInstruction.cpp - SBInstructionList.cpp - SBLineEntry.cpp - SBListener.cpp - SBModule.cpp - SBModuleSpec.cpp - SBProcess.cpp - SBSection.cpp - SBSourceManager.cpp - SBStream.cpp - SBStringList.cpp - SBSymbol.cpp - SBSymbolContext.cpp - SBSymbolContextList.cpp - SBTarget.cpp - SBThread.cpp - SBType.cpp - SBTypeCategory.cpp - SBTypeFilter.cpp - SBTypeFormat.cpp - SBTypeNameSpecifier.cpp - SBTypeSummary.cpp - SBTypeSynthetic.cpp - SBValue.cpp - SBValueList.cpp - SBWatchpoint.cpp - ) +set(LLVM_NO_RTTI 1) + +add_lldb_library(lldbAPI + SBAddress.cpp + SBBlock.cpp + SBBreakpoint.cpp + SBBreakpointLocation.cpp + SBBroadcaster.cpp + SBCommandInterpreter.cpp + SBCommandReturnObject.cpp + SBCommunication.cpp + SBCompileUnit.cpp + SBData.cpp + SBDebugger.cpp + SBDeclaration.cpp + SBError.cpp + SBEvent.cpp + SBExpressionOptions.cpp + SBFileSpec.cpp + SBFileSpecList.cpp + SBFrame.cpp + SBFunction.cpp + SBHostOS.cpp + SBInputReader.cpp + SBInstruction.cpp + SBInstructionList.cpp + SBLineEntry.cpp + SBListener.cpp + SBModule.cpp + SBModuleSpec.cpp + SBProcess.cpp + SBSection.cpp + SBSourceManager.cpp + SBStream.cpp + SBStringList.cpp + SBSymbol.cpp + SBSymbolContext.cpp + SBSymbolContextList.cpp + SBTarget.cpp + SBThread.cpp + SBType.cpp + SBTypeCategory.cpp + SBTypeFilter.cpp + SBTypeFormat.cpp + SBTypeNameSpecifier.cpp + SBTypeSummary.cpp + SBTypeSynthetic.cpp + SBValue.cpp + SBValueList.cpp + SBWatchpoint.cpp + ) diff --git a/lldb/source/Breakpoint/CMakeLists.txt b/lldb/source/Breakpoint/CMakeLists.txt index e3e0c90069cf..fc40aea74ed2 100644 --- a/lldb/source/Breakpoint/CMakeLists.txt +++ b/lldb/source/Breakpoint/CMakeLists.txt @@ -1,25 +1,25 @@ -set(LLVM_NO_RTTI 1) - -add_lldb_library(lldbBreakpoint - Breakpoint.cpp - BreakpointID.cpp - BreakpointIDList.cpp - BreakpointList.cpp - BreakpointLocation.cpp - BreakpointLocationCollection.cpp - BreakpointLocationList.cpp - BreakpointOptions.cpp - BreakpointResolver.cpp - BreakpointResolverAddress.cpp - BreakpointResolverFileLine.cpp - BreakpointResolverFileRegex.cpp - BreakpointResolverName.cpp - BreakpointSite.cpp - BreakpointSiteList.cpp - Stoppoint.cpp - StoppointCallbackContext.cpp - StoppointLocation.cpp - Watchpoint.cpp - WatchpointList.cpp - WatchpointOptions.cpp - ) +set(LLVM_NO_RTTI 1) + +add_lldb_library(lldbBreakpoint + Breakpoint.cpp + BreakpointID.cpp + BreakpointIDList.cpp + BreakpointList.cpp + BreakpointLocation.cpp + BreakpointLocationCollection.cpp + BreakpointLocationList.cpp + BreakpointOptions.cpp + BreakpointResolver.cpp + BreakpointResolverAddress.cpp + BreakpointResolverFileLine.cpp + BreakpointResolverFileRegex.cpp + BreakpointResolverName.cpp + BreakpointSite.cpp + BreakpointSiteList.cpp + Stoppoint.cpp + StoppointCallbackContext.cpp + StoppointLocation.cpp + Watchpoint.cpp + WatchpointList.cpp + WatchpointOptions.cpp + ) diff --git a/lldb/source/CMakeLists.txt b/lldb/source/CMakeLists.txt index 2a1292a80d1d..d928c30bc6b8 100644 --- a/lldb/source/CMakeLists.txt +++ b/lldb/source/CMakeLists.txt @@ -1,222 +1,222 @@ -include_directories(.) - -if ( CMAKE_SYSTEM_NAME MATCHES "Linux" ) -include_directories( - Plugins/Process/Linux - Plugins/Process/POSIX - ) -endif () - -if ( CMAKE_SYSTEM_NAME MATCHES "FreeBSD" ) -include_directories( - Plugins/Process/FreeBSD - Plugins/Process/POSIX - ) -endif () - -add_subdirectory(API) -add_subdirectory(Breakpoint) -add_subdirectory(Commands) -add_subdirectory(Core) -add_subdirectory(DataFormatters) -add_subdirectory(Expression) -add_subdirectory(Host) -add_subdirectory(Interpreter) -add_subdirectory(Plugins) -add_subdirectory(Symbol) -add_subdirectory(Target) -add_subdirectory(Utility) - -set( LLDB_USED_LIBS - lldbAPI - lldbBreakpoint - lldbCommands - lldbDataFormatters - lldbHostCommon - lldbCore - lldbExpression - lldbInterpreter - lldbSymbol - lldbTarget - lldbUtility - - # Plugins - lldbPluginDisassemblerLLVM - lldbPluginSymbolFileDWARF - lldbPluginSymbolFileSymtab - lldbPluginDynamicLoaderStatic - lldbPluginDynamicLoaderPosixDYLD - - lldbPluginObjectFileMachO - lldbPluginObjectFileELF - lldbPluginSymbolVendorELF - lldbPluginObjectContainerBSDArchive - lldbPluginObjectContainerMachOArchive - lldbPluginProcessGDBRemote - lldbPluginProcessMachCore - lldbPluginProcessUtility - lldbPluginPlatformGDB - lldbPluginPlatformFreeBSD - lldbPluginPlatformLinux - lldbPluginPlatformPOSIX - lldbPluginObjectFileMachO - lldbPluginObjectContainerMachOArchive - lldbPluginObjectContainerBSDArchive - lldbPluginPlatformMacOSX - lldbPluginDynamicLoaderMacOSXDYLD - lldbPluginUnwindAssemblyInstEmulation - lldbPluginUnwindAssemblyX86 - lldbPluginAppleObjCRuntime - lldbPluginCXXItaniumABI - lldbPluginABIMacOSX_arm - lldbPluginABIMacOSX_i386 - lldbPluginABISysV_x86_64 - lldbPluginInstructionARM - lldbPluginObjectFilePECOFF - lldbPluginOSPython - ) - -# Windows-only libraries -if ( CMAKE_SYSTEM_NAME MATCHES "Windows" ) - list(APPEND LLDB_USED_LIBS - lldbHostWindows - #lldbPluginPlatformWindows - Ws2_32 - ) -endif () - -# Linux-only libraries -if ( CMAKE_SYSTEM_NAME MATCHES "Linux" ) - list(APPEND LLDB_USED_LIBS - lldbHostLinux - lldbPluginProcessLinux - lldbPluginProcessPOSIX - lldbPluginProcessElfCore - ) -endif () - -# FreeBSD-only libraries -if ( CMAKE_SYSTEM_NAME MATCHES "FreeBSD" ) - list(APPEND LLDB_USED_LIBS - lldbHostFreeBSD - lldbPluginProcessFreeBSD - lldbPluginProcessPOSIX - lldbPluginProcessElfCore - ) -endif () - -# Darwin-only libraries -if ( CMAKE_SYSTEM_NAME MATCHES "Darwin" ) - set(LLDB_VERS_GENERATED_FILE ${LLDB_BINARY_DIR}/source/LLDB_vers.c) - add_custom_command(OUTPUT ${LLDB_VERS_GENERATED_FILE} - COMMAND ${LLDB_SOURCE_DIR}/scripts/generate-vers.pl - ${LLDB_SOURCE_DIR}/lldb.xcodeproj/project.pbxproj - > ${LLDB_VERS_GENERATED_FILE}) - - set_source_files_properties(${LLDB_VERS_GENERATED_FILE} PROPERTIES GENERATED 1) - list(APPEND LLDB_USED_LIBS - lldbHostMacOSX - lldbPluginDynamicLoaderDarwinKernel - lldbPluginProcessMacOSXKernel - lldbPluginSymbolVendorMacOSX - ) -endif() - -set( CLANG_USED_LIBS - clangAnalysis - clangAST - clangBasic - clangCodeGen - clangDriver - clangEdit - clangFrontend - clangLex - clangParse - clangRewriteCore - clangRewriteFrontend - clangSema - clangSerialization - ) - -if (NOT CMAKE_SYSTEM_NAME MATCHES "Windows") - set( LLDB_SYSTEM_LIBS - edit - python2.7 - ) -endif() - -set( LLVM_LINK_COMPONENTS - ${LLVM_TARGETS_TO_BUILD} - jit - interpreter - nativecodegen - asmparser - bitreader - bitwriter - codegen - ipo - selectiondag - bitreader - mc - mcjit - core - mcdisassembler - executionengine - ) - -set_source_files_properties(${LLDB_BINARY_DIR}/scripts/LLDBWrapPython.cpp PROPERTIES GENERATED 1) -set(SHARED_LIBRARY 1) - -if(NOT CMAKE_SYSTEM_NAME MATCHES "Windows") - set(LLDB_WRAP_PYTHON ${LLDB_BINARY_DIR}/scripts/LLDBWrapPython.cpp) -endif() - -add_lldb_library(liblldb - lldb.cpp - lldb-log.cpp - ${LLDB_WRAP_PYTHON} - ${LLDB_VERS_GENERATED_FILE} - ) -set_target_properties(liblldb - PROPERTIES - OUTPUT_NAME lldb - VERSION ${LLDB_VERSION} - ) -if (LLDB_WRAP_PYTHON OR LLDB_VERS_GENERATED_FILE) - add_dependencies(liblldb - ${LLDB_WRAP_PYTHON} - ${LLDB_VERS_GENERATED_FILE} - ) -endif() -target_link_libraries(liblldb ${LLDB_SYSTEM_LIBS}) - -# Determine LLDB revision and repository. GetSourceVersion and GetRepositoryPath are shell-scripts, and as -# such will not work on Windows. -if ( NOT CMAKE_SYSTEM_NAME MATCHES "Windows" ) - execute_process(COMMAND ${CMAKE_SOURCE_DIR}/utils/GetSourceVersion ${LLDB_SOURCE_DIR} - OUTPUT_VARIABLE LLDB_REVISION) - if ( LLDB_REVISION ) - string(REGEX REPLACE "(\r?\n)+$" "" LLDB_REVISION ${LLDB_REVISION}) - endif() - - execute_process(COMMAND ${CMAKE_SOURCE_DIR}/utils/GetRepositoryPath ${LLDB_SOURCE_DIR} - OUTPUT_VARIABLE LLDB_REPOSITORY) - if ( LLDB_REPOSITORY ) - # Replace newline characters with spaces - string(REGEX REPLACE "(\r?\n)+" " " LLDB_REPOSITORY ${LLDB_REPOSITORY}) - - # Remove trailing spaces - string(REGEX REPLACE "(\ )+$" "" LLDB_REPOSITORY ${LLDB_REPOSITORY}) - endif() - - set_property( - SOURCE lldb.cpp - PROPERTY COMPILE_DEFINITIONS "LLDB_REVISION=\"${LLDB_REVISION}\"" "LLDB_REPOSITORY=\"${LLDB_REPOSITORY}\"") -endif () -# FIXME: implement svn/git revision and repository parsing solution on Windows. There is an SVN-only -# revision parsing solution in tools/clang/lib/Basic/CMakelists.txt. - - -install(TARGETS liblldb - RUNTIME DESTINATION bin - LIBRARY DESTINATION lib) +include_directories(.) + +if ( CMAKE_SYSTEM_NAME MATCHES "Linux" ) +include_directories( + Plugins/Process/Linux + Plugins/Process/POSIX + ) +endif () + +if ( CMAKE_SYSTEM_NAME MATCHES "FreeBSD" ) +include_directories( + Plugins/Process/FreeBSD + Plugins/Process/POSIX + ) +endif () + +add_subdirectory(API) +add_subdirectory(Breakpoint) +add_subdirectory(Commands) +add_subdirectory(Core) +add_subdirectory(DataFormatters) +add_subdirectory(Expression) +add_subdirectory(Host) +add_subdirectory(Interpreter) +add_subdirectory(Plugins) +add_subdirectory(Symbol) +add_subdirectory(Target) +add_subdirectory(Utility) + +set( LLDB_USED_LIBS + lldbAPI + lldbBreakpoint + lldbCommands + lldbDataFormatters + lldbHostCommon + lldbCore + lldbExpression + lldbInterpreter + lldbSymbol + lldbTarget + lldbUtility + + # Plugins + lldbPluginDisassemblerLLVM + lldbPluginSymbolFileDWARF + lldbPluginSymbolFileSymtab + lldbPluginDynamicLoaderStatic + lldbPluginDynamicLoaderPosixDYLD + + lldbPluginObjectFileMachO + lldbPluginObjectFileELF + lldbPluginSymbolVendorELF + lldbPluginObjectContainerBSDArchive + lldbPluginObjectContainerMachOArchive + lldbPluginProcessGDBRemote + lldbPluginProcessMachCore + lldbPluginProcessUtility + lldbPluginPlatformGDB + lldbPluginPlatformFreeBSD + lldbPluginPlatformLinux + lldbPluginPlatformPOSIX + lldbPluginObjectFileMachO + lldbPluginObjectContainerMachOArchive + lldbPluginObjectContainerBSDArchive + lldbPluginPlatformMacOSX + lldbPluginDynamicLoaderMacOSXDYLD + lldbPluginUnwindAssemblyInstEmulation + lldbPluginUnwindAssemblyX86 + lldbPluginAppleObjCRuntime + lldbPluginCXXItaniumABI + lldbPluginABIMacOSX_arm + lldbPluginABIMacOSX_i386 + lldbPluginABISysV_x86_64 + lldbPluginInstructionARM + lldbPluginObjectFilePECOFF + lldbPluginOSPython + ) + +# Windows-only libraries +if ( CMAKE_SYSTEM_NAME MATCHES "Windows" ) + list(APPEND LLDB_USED_LIBS + lldbHostWindows + #lldbPluginPlatformWindows + Ws2_32 + ) +endif () + +# Linux-only libraries +if ( CMAKE_SYSTEM_NAME MATCHES "Linux" ) + list(APPEND LLDB_USED_LIBS + lldbHostLinux + lldbPluginProcessLinux + lldbPluginProcessPOSIX + lldbPluginProcessElfCore + ) +endif () + +# FreeBSD-only libraries +if ( CMAKE_SYSTEM_NAME MATCHES "FreeBSD" ) + list(APPEND LLDB_USED_LIBS + lldbHostFreeBSD + lldbPluginProcessFreeBSD + lldbPluginProcessPOSIX + lldbPluginProcessElfCore + ) +endif () + +# Darwin-only libraries +if ( CMAKE_SYSTEM_NAME MATCHES "Darwin" ) + set(LLDB_VERS_GENERATED_FILE ${LLDB_BINARY_DIR}/source/LLDB_vers.c) + add_custom_command(OUTPUT ${LLDB_VERS_GENERATED_FILE} + COMMAND ${LLDB_SOURCE_DIR}/scripts/generate-vers.pl + ${LLDB_SOURCE_DIR}/lldb.xcodeproj/project.pbxproj + > ${LLDB_VERS_GENERATED_FILE}) + + set_source_files_properties(${LLDB_VERS_GENERATED_FILE} PROPERTIES GENERATED 1) + list(APPEND LLDB_USED_LIBS + lldbHostMacOSX + lldbPluginDynamicLoaderDarwinKernel + lldbPluginProcessMacOSXKernel + lldbPluginSymbolVendorMacOSX + ) +endif() + +set( CLANG_USED_LIBS + clangAnalysis + clangAST + clangBasic + clangCodeGen + clangDriver + clangEdit + clangFrontend + clangLex + clangParse + clangRewriteCore + clangRewriteFrontend + clangSema + clangSerialization + ) + +if (NOT CMAKE_SYSTEM_NAME MATCHES "Windows") + set( LLDB_SYSTEM_LIBS + edit + python2.7 + ) +endif() + +set( LLVM_LINK_COMPONENTS + ${LLVM_TARGETS_TO_BUILD} + jit + interpreter + nativecodegen + asmparser + bitreader + bitwriter + codegen + ipo + selectiondag + bitreader + mc + mcjit + core + mcdisassembler + executionengine + ) + +set_source_files_properties(${LLDB_BINARY_DIR}/scripts/LLDBWrapPython.cpp PROPERTIES GENERATED 1) +set(SHARED_LIBRARY 1) + +if(NOT CMAKE_SYSTEM_NAME MATCHES "Windows") + set(LLDB_WRAP_PYTHON ${LLDB_BINARY_DIR}/scripts/LLDBWrapPython.cpp) +endif() + +add_lldb_library(liblldb + lldb.cpp + lldb-log.cpp + ${LLDB_WRAP_PYTHON} + ${LLDB_VERS_GENERATED_FILE} + ) +set_target_properties(liblldb + PROPERTIES + OUTPUT_NAME lldb + VERSION ${LLDB_VERSION} + ) +if (LLDB_WRAP_PYTHON OR LLDB_VERS_GENERATED_FILE) + add_dependencies(liblldb + ${LLDB_WRAP_PYTHON} + ${LLDB_VERS_GENERATED_FILE} + ) +endif() +target_link_libraries(liblldb ${LLDB_SYSTEM_LIBS}) + +# Determine LLDB revision and repository. GetSourceVersion and GetRepositoryPath are shell-scripts, and as +# such will not work on Windows. +if ( NOT CMAKE_SYSTEM_NAME MATCHES "Windows" ) + execute_process(COMMAND ${CMAKE_SOURCE_DIR}/utils/GetSourceVersion ${LLDB_SOURCE_DIR} + OUTPUT_VARIABLE LLDB_REVISION) + if ( LLDB_REVISION ) + string(REGEX REPLACE "(\r?\n)+$" "" LLDB_REVISION ${LLDB_REVISION}) + endif() + + execute_process(COMMAND ${CMAKE_SOURCE_DIR}/utils/GetRepositoryPath ${LLDB_SOURCE_DIR} + OUTPUT_VARIABLE LLDB_REPOSITORY) + if ( LLDB_REPOSITORY ) + # Replace newline characters with spaces + string(REGEX REPLACE "(\r?\n)+" " " LLDB_REPOSITORY ${LLDB_REPOSITORY}) + + # Remove trailing spaces + string(REGEX REPLACE "(\ )+$" "" LLDB_REPOSITORY ${LLDB_REPOSITORY}) + endif() + + set_property( + SOURCE lldb.cpp + PROPERTY COMPILE_DEFINITIONS "LLDB_REVISION=\"${LLDB_REVISION}\"" "LLDB_REPOSITORY=\"${LLDB_REPOSITORY}\"") +endif () +# FIXME: implement svn/git revision and repository parsing solution on Windows. There is an SVN-only +# revision parsing solution in tools/clang/lib/Basic/CMakelists.txt. + + +install(TARGETS liblldb + RUNTIME DESTINATION bin + LIBRARY DESTINATION lib) diff --git a/lldb/source/Commands/CMakeLists.txt b/lldb/source/Commands/CMakeLists.txt index 48382ffcb72c..1f287d57243b 100644 --- a/lldb/source/Commands/CMakeLists.txt +++ b/lldb/source/Commands/CMakeLists.txt @@ -1,31 +1,31 @@ -set(LLVM_NO_RTTI 1) - -add_lldb_library(lldbCommands - CommandCompletions.cpp - CommandObjectApropos.cpp - CommandObjectArgs.cpp - CommandObjectBreakpoint.cpp - CommandObjectBreakpointCommand.cpp - CommandObjectCommands.cpp - CommandObjectDisassemble.cpp - CommandObjectExpression.cpp - CommandObjectFrame.cpp - CommandObjectHelp.cpp - CommandObjectLog.cpp - CommandObjectMemory.cpp - CommandObjectMultiword.cpp - CommandObjectPlatform.cpp - CommandObjectPlugin.cpp - CommandObjectProcess.cpp - CommandObjectQuit.cpp - CommandObjectRegister.cpp - CommandObjectSettings.cpp - CommandObjectSource.cpp - CommandObjectSyntax.cpp - CommandObjectTarget.cpp - CommandObjectThread.cpp - CommandObjectType.cpp - CommandObjectVersion.cpp - CommandObjectWatchpoint.cpp - CommandObjectWatchpointCommand.cpp - ) +set(LLVM_NO_RTTI 1) + +add_lldb_library(lldbCommands + CommandCompletions.cpp + CommandObjectApropos.cpp + CommandObjectArgs.cpp + CommandObjectBreakpoint.cpp + CommandObjectBreakpointCommand.cpp + CommandObjectCommands.cpp + CommandObjectDisassemble.cpp + CommandObjectExpression.cpp + CommandObjectFrame.cpp + CommandObjectHelp.cpp + CommandObjectLog.cpp + CommandObjectMemory.cpp + CommandObjectMultiword.cpp + CommandObjectPlatform.cpp + CommandObjectPlugin.cpp + CommandObjectProcess.cpp + CommandObjectQuit.cpp + CommandObjectRegister.cpp + CommandObjectSettings.cpp + CommandObjectSource.cpp + CommandObjectSyntax.cpp + CommandObjectTarget.cpp + CommandObjectThread.cpp + CommandObjectType.cpp + CommandObjectVersion.cpp + CommandObjectWatchpoint.cpp + CommandObjectWatchpointCommand.cpp + ) diff --git a/lldb/source/Core/CMakeLists.txt b/lldb/source/Core/CMakeLists.txt index 165fb1de6408..eeca58ca0b91 100644 --- a/lldb/source/Core/CMakeLists.txt +++ b/lldb/source/Core/CMakeLists.txt @@ -1,76 +1,76 @@ -set(LLVM_NO_RTTI 1) - -add_lldb_library(lldbCore - Address.cpp - AddressRange.cpp - AddressResolver.cpp - AddressResolverFileLine.cpp - AddressResolverName.cpp - ArchSpec.cpp - Baton.cpp - Broadcaster.cpp - Communication.cpp - Connection.cpp - ConnectionFileDescriptor.cpp - ConnectionMachPort.cpp - ConnectionSharedMemory.cpp - ConstString.cpp - DataBufferHeap.cpp - DataBufferMemoryMap.cpp - DataEncoder.cpp - DataExtractor.cpp - Debugger.cpp - Disassembler.cpp - DynamicLoader.cpp - EmulateInstruction.cpp - Error.cpp - Event.cpp - FileLineResolver.cpp - FileSpecList.cpp - History.cpp - InputReader.cpp - InputReaderEZ.cpp - InputReaderStack.cpp - Language.cpp - Listener.cpp - Log.cpp - Mangled.cpp - Module.cpp - ModuleChild.cpp - ModuleList.cpp - Opcode.cpp - PluginManager.cpp - RegisterValue.cpp - RegularExpression.cpp - Scalar.cpp - SearchFilter.cpp - Section.cpp - SourceManager.cpp - State.cpp - Stream.cpp - StreamAsynchronousIO.cpp - StreamCallback.cpp - StreamFile.cpp - StreamGDBRemote.cpp - StreamString.cpp - StringList.cpp - Timer.cpp - UserID.cpp - UserSettingsController.cpp - UUID.cpp - Value.cpp - ValueObject.cpp - ValueObjectCast.cpp - ValueObjectChild.cpp - ValueObjectConstResult.cpp - ValueObjectConstResultChild.cpp - ValueObjectConstResultImpl.cpp - ValueObjectDynamicValue.cpp - ValueObjectList.cpp - ValueObjectMemory.cpp - ValueObjectRegister.cpp - ValueObjectSyntheticFilter.cpp - ValueObjectVariable.cpp - VMRange.cpp - ) - +set(LLVM_NO_RTTI 1) + +add_lldb_library(lldbCore + Address.cpp + AddressRange.cpp + AddressResolver.cpp + AddressResolverFileLine.cpp + AddressResolverName.cpp + ArchSpec.cpp + Baton.cpp + Broadcaster.cpp + Communication.cpp + Connection.cpp + ConnectionFileDescriptor.cpp + ConnectionMachPort.cpp + ConnectionSharedMemory.cpp + ConstString.cpp + DataBufferHeap.cpp + DataBufferMemoryMap.cpp + DataEncoder.cpp + DataExtractor.cpp + Debugger.cpp + Disassembler.cpp + DynamicLoader.cpp + EmulateInstruction.cpp + Error.cpp + Event.cpp + FileLineResolver.cpp + FileSpecList.cpp + History.cpp + InputReader.cpp + InputReaderEZ.cpp + InputReaderStack.cpp + Language.cpp + Listener.cpp + Log.cpp + Mangled.cpp + Module.cpp + ModuleChild.cpp + ModuleList.cpp + Opcode.cpp + PluginManager.cpp + RegisterValue.cpp + RegularExpression.cpp + Scalar.cpp + SearchFilter.cpp + Section.cpp + SourceManager.cpp + State.cpp + Stream.cpp + StreamAsynchronousIO.cpp + StreamCallback.cpp + StreamFile.cpp + StreamGDBRemote.cpp + StreamString.cpp + StringList.cpp + Timer.cpp + UserID.cpp + UserSettingsController.cpp + UUID.cpp + Value.cpp + ValueObject.cpp + ValueObjectCast.cpp + ValueObjectChild.cpp + ValueObjectConstResult.cpp + ValueObjectConstResultChild.cpp + ValueObjectConstResultImpl.cpp + ValueObjectDynamicValue.cpp + ValueObjectList.cpp + ValueObjectMemory.cpp + ValueObjectRegister.cpp + ValueObjectSyntheticFilter.cpp + ValueObjectVariable.cpp + VMRange.cpp + ) + diff --git a/lldb/source/DataFormatters/CMakeLists.txt b/lldb/source/DataFormatters/CMakeLists.txt index b9857fc6c8ba..cd3c1dd6c429 100644 --- a/lldb/source/DataFormatters/CMakeLists.txt +++ b/lldb/source/DataFormatters/CMakeLists.txt @@ -1,24 +1,24 @@ -set(LLVM_NO_RTTI 1) - -add_lldb_library(lldbDataFormatters - CF.cpp - Cocoa.cpp - CXXFormatterFunctions.cpp - DataVisualization.cpp - FormatCache.cpp - FormatClasses.cpp - FormatManager.cpp - LibCxx.cpp - LibCxxList.cpp - LibCxxMap.cpp - LibCxxUnorderedMap.cpp - LibStdcpp.cpp - NSArray.cpp - NSDictionary.cpp - NSSet.cpp - TypeCategory.cpp - TypeCategoryMap.cpp - TypeFormat.cpp - TypeSummary.cpp - TypeSynthetic.cpp - ) +set(LLVM_NO_RTTI 1) + +add_lldb_library(lldbDataFormatters + CF.cpp + Cocoa.cpp + CXXFormatterFunctions.cpp + DataVisualization.cpp + FormatCache.cpp + FormatClasses.cpp + FormatManager.cpp + LibCxx.cpp + LibCxxList.cpp + LibCxxMap.cpp + LibCxxUnorderedMap.cpp + LibStdcpp.cpp + NSArray.cpp + NSDictionary.cpp + NSSet.cpp + TypeCategory.cpp + TypeCategoryMap.cpp + TypeFormat.cpp + TypeSummary.cpp + TypeSynthetic.cpp + ) diff --git a/lldb/source/Expression/CMakeLists.txt b/lldb/source/Expression/CMakeLists.txt index a6ac91013476..100fc69e36c0 100644 --- a/lldb/source/Expression/CMakeLists.txt +++ b/lldb/source/Expression/CMakeLists.txt @@ -1,23 +1,23 @@ -set(LLVM_NO_RTTI 1) - -add_lldb_library(lldbExpression - ASTDumper.cpp - ASTResultSynthesizer.cpp - ASTStructExtractor.cpp - ClangASTSource.cpp - ClangExpressionDeclMap.cpp - ClangExpressionParser.cpp - ClangExpressionVariable.cpp - ClangFunction.cpp - ClangPersistentVariables.cpp - ClangUserExpression.cpp - ClangUtilityFunction.cpp - DWARFExpression.cpp - ExpressionSourceCode.cpp - IRDynamicChecks.cpp - IRExecutionUnit.cpp - IRForTarget.cpp - IRInterpreter.cpp - IRMemoryMap.cpp - Materializer.cpp - ) +set(LLVM_NO_RTTI 1) + +add_lldb_library(lldbExpression + ASTDumper.cpp + ASTResultSynthesizer.cpp + ASTStructExtractor.cpp + ClangASTSource.cpp + ClangExpressionDeclMap.cpp + ClangExpressionParser.cpp + ClangExpressionVariable.cpp + ClangFunction.cpp + ClangPersistentVariables.cpp + ClangUserExpression.cpp + ClangUtilityFunction.cpp + DWARFExpression.cpp + ExpressionSourceCode.cpp + IRDynamicChecks.cpp + IRExecutionUnit.cpp + IRForTarget.cpp + IRInterpreter.cpp + IRMemoryMap.cpp + Materializer.cpp + ) diff --git a/lldb/source/Host/CMakeLists.txt b/lldb/source/Host/CMakeLists.txt index 6c92a6cde262..d203d0b2847c 100644 --- a/lldb/source/Host/CMakeLists.txt +++ b/lldb/source/Host/CMakeLists.txt @@ -1,11 +1,11 @@ -add_subdirectory(common) - -if (CMAKE_SYSTEM_NAME MATCHES "Darwin") - add_subdirectory(macosx) -elseif (CMAKE_SYSTEM_NAME MATCHES "Linux") - add_subdirectory(linux) -elseif (CMAKE_SYSTEM_NAME MATCHES "FreeBSD") - add_subdirectory(freebsd) -elseif (CMAKE_SYSTEM_NAME MATCHES "Windows") - add_subdirectory(windows) -endif() +add_subdirectory(common) + +if (CMAKE_SYSTEM_NAME MATCHES "Darwin") + add_subdirectory(macosx) +elseif (CMAKE_SYSTEM_NAME MATCHES "Linux") + add_subdirectory(linux) +elseif (CMAKE_SYSTEM_NAME MATCHES "FreeBSD") + add_subdirectory(freebsd) +elseif (CMAKE_SYSTEM_NAME MATCHES "Windows") + add_subdirectory(windows) +endif() diff --git a/lldb/source/Host/common/CMakeLists.txt b/lldb/source/Host/common/CMakeLists.txt index 8cc7e3c03c07..443b983cb6d3 100644 --- a/lldb/source/Host/common/CMakeLists.txt +++ b/lldb/source/Host/common/CMakeLists.txt @@ -1,16 +1,16 @@ -set(LLVM_NO_RTTI 1) - -add_lldb_library(lldbHostCommon - Condition.cpp - DynamicLibrary.cpp - File.cpp - FileSpec.cpp - Host.cpp - Mutex.cpp - OptionParser.cpp - ProcessRunLock.cpp - SocketAddress.cpp - Symbols.cpp - Terminal.cpp - TimeValue.cpp - ) +set(LLVM_NO_RTTI 1) + +add_lldb_library(lldbHostCommon + Condition.cpp + DynamicLibrary.cpp + File.cpp + FileSpec.cpp + Host.cpp + Mutex.cpp + OptionParser.cpp + ProcessRunLock.cpp + SocketAddress.cpp + Symbols.cpp + Terminal.cpp + TimeValue.cpp + ) diff --git a/lldb/source/Host/linux/CMakeLists.txt b/lldb/source/Host/linux/CMakeLists.txt index b98c410b43c7..535b47fa5f29 100644 --- a/lldb/source/Host/linux/CMakeLists.txt +++ b/lldb/source/Host/linux/CMakeLists.txt @@ -1,5 +1,5 @@ -set(LLVM_NO_RTTI 1) - -add_lldb_library(lldbHostLinux - Host.cpp - ) +set(LLVM_NO_RTTI 1) + +add_lldb_library(lldbHostLinux + Host.cpp + ) diff --git a/lldb/source/Interpreter/CMakeLists.txt b/lldb/source/Interpreter/CMakeLists.txt index 95e02ec985aa..27597fc3c3ef 100644 --- a/lldb/source/Interpreter/CMakeLists.txt +++ b/lldb/source/Interpreter/CMakeLists.txt @@ -1,46 +1,46 @@ -set(LLVM_NO_RTTI 1) - -add_lldb_library(lldbInterpreter - Args.cpp - CommandHistory.cpp - CommandInterpreter.cpp - CommandObject.cpp - CommandObjectRegexCommand.cpp - CommandObjectScript.cpp - CommandReturnObject.cpp - OptionGroupArchitecture.cpp - OptionGroupBoolean.cpp - OptionGroupFile.cpp - OptionGroupFormat.cpp - OptionGroupOutputFile.cpp - OptionGroupPlatform.cpp - OptionGroupString.cpp - OptionGroupUInt64.cpp - OptionGroupUUID.cpp - OptionGroupValueObjectDisplay.cpp - OptionValue.cpp - OptionValueArch.cpp - OptionValueArgs.cpp - OptionValueArray.cpp - OptionValueBoolean.cpp - OptionValueDictionary.cpp - OptionValueEnumeration.cpp - OptionValueFileSpec.cpp - OptionValueFileSpecLIst.cpp - OptionValueFormat.cpp - OptionValuePathMappings.cpp - OptionValueProperties.cpp - OptionValueRegex.cpp - OptionValueSInt64.cpp - OptionValueString.cpp - OptionValueUInt64.cpp - OptionValueUUID.cpp - OptionGroupVariable.cpp - OptionGroupWatchpoint.cpp - Options.cpp - Property.cpp - PythonDataObjects.cpp - ScriptInterpreter.cpp - ScriptInterpreterNone.cpp - ScriptInterpreterPython.cpp - ) +set(LLVM_NO_RTTI 1) + +add_lldb_library(lldbInterpreter + Args.cpp + CommandHistory.cpp + CommandInterpreter.cpp + CommandObject.cpp + CommandObjectRegexCommand.cpp + CommandObjectScript.cpp + CommandReturnObject.cpp + OptionGroupArchitecture.cpp + OptionGroupBoolean.cpp + OptionGroupFile.cpp + OptionGroupFormat.cpp + OptionGroupOutputFile.cpp + OptionGroupPlatform.cpp + OptionGroupString.cpp + OptionGroupUInt64.cpp + OptionGroupUUID.cpp + OptionGroupValueObjectDisplay.cpp + OptionValue.cpp + OptionValueArch.cpp + OptionValueArgs.cpp + OptionValueArray.cpp + OptionValueBoolean.cpp + OptionValueDictionary.cpp + OptionValueEnumeration.cpp + OptionValueFileSpec.cpp + OptionValueFileSpecLIst.cpp + OptionValueFormat.cpp + OptionValuePathMappings.cpp + OptionValueProperties.cpp + OptionValueRegex.cpp + OptionValueSInt64.cpp + OptionValueString.cpp + OptionValueUInt64.cpp + OptionValueUUID.cpp + OptionGroupVariable.cpp + OptionGroupWatchpoint.cpp + Options.cpp + Property.cpp + PythonDataObjects.cpp + ScriptInterpreter.cpp + ScriptInterpreterNone.cpp + ScriptInterpreterPython.cpp + ) diff --git a/lldb/source/Plugins/ABI/CMakeLists.txt b/lldb/source/Plugins/ABI/CMakeLists.txt index c6316e03a493..5d4fb5ce3377 100644 --- a/lldb/source/Plugins/ABI/CMakeLists.txt +++ b/lldb/source/Plugins/ABI/CMakeLists.txt @@ -1,3 +1,3 @@ -add_subdirectory(SysV-x86_64) -add_subdirectory(MacOSX-i386) -add_subdirectory(MacOSX-arm) +add_subdirectory(SysV-x86_64) +add_subdirectory(MacOSX-i386) +add_subdirectory(MacOSX-arm) diff --git a/lldb/source/Plugins/ABI/MacOSX-arm/CMakeLists.txt b/lldb/source/Plugins/ABI/MacOSX-arm/CMakeLists.txt index 9dfc2ca9ca65..6b613d5bb16f 100644 --- a/lldb/source/Plugins/ABI/MacOSX-arm/CMakeLists.txt +++ b/lldb/source/Plugins/ABI/MacOSX-arm/CMakeLists.txt @@ -1,5 +1,5 @@ -set(LLVM_NO_RTTI 1) - -add_lldb_library(lldbPluginABIMacOSX_arm - ABIMacOSX_arm.cpp - ) +set(LLVM_NO_RTTI 1) + +add_lldb_library(lldbPluginABIMacOSX_arm + ABIMacOSX_arm.cpp + ) diff --git a/lldb/source/Plugins/ABI/MacOSX-i386/CMakeLists.txt b/lldb/source/Plugins/ABI/MacOSX-i386/CMakeLists.txt index d2a5f5ad22f3..dbfff7b1534a 100644 --- a/lldb/source/Plugins/ABI/MacOSX-i386/CMakeLists.txt +++ b/lldb/source/Plugins/ABI/MacOSX-i386/CMakeLists.txt @@ -1,5 +1,5 @@ -set(LLVM_NO_RTTI 1) - -add_lldb_library(lldbPluginABIMacOSX_i386 - ABIMacOSX_i386.cpp - ) +set(LLVM_NO_RTTI 1) + +add_lldb_library(lldbPluginABIMacOSX_i386 + ABIMacOSX_i386.cpp + ) diff --git a/lldb/source/Plugins/ABI/SysV-x86_64/CMakeLists.txt b/lldb/source/Plugins/ABI/SysV-x86_64/CMakeLists.txt index 090724877af3..680f7e546ef9 100644 --- a/lldb/source/Plugins/ABI/SysV-x86_64/CMakeLists.txt +++ b/lldb/source/Plugins/ABI/SysV-x86_64/CMakeLists.txt @@ -1,5 +1,5 @@ -set(LLVM_NO_RTTI 1) - -add_lldb_library(lldbPluginABISysV_x86_64 - ABISysV_x86_64.cpp - ) +set(LLVM_NO_RTTI 1) + +add_lldb_library(lldbPluginABISysV_x86_64 + ABISysV_x86_64.cpp + ) diff --git a/lldb/source/Plugins/CMakeLists.txt b/lldb/source/Plugins/CMakeLists.txt index 7e19b3f788ef..a1b515af29f2 100644 --- a/lldb/source/Plugins/CMakeLists.txt +++ b/lldb/source/Plugins/CMakeLists.txt @@ -1,13 +1,13 @@ -add_subdirectory(ABI) -add_subdirectory(Disassembler) -add_subdirectory(DynamicLoader) -add_subdirectory(Instruction) -add_subdirectory(LanguageRuntime) -add_subdirectory(ObjectContainer) -add_subdirectory(ObjectFile) -add_subdirectory(OperatingSystem) -add_subdirectory(Platform) -add_subdirectory(Process) -add_subdirectory(SymbolFile) -add_subdirectory(SymbolVendor) -add_subdirectory(UnwindAssembly) +add_subdirectory(ABI) +add_subdirectory(Disassembler) +add_subdirectory(DynamicLoader) +add_subdirectory(Instruction) +add_subdirectory(LanguageRuntime) +add_subdirectory(ObjectContainer) +add_subdirectory(ObjectFile) +add_subdirectory(OperatingSystem) +add_subdirectory(Platform) +add_subdirectory(Process) +add_subdirectory(SymbolFile) +add_subdirectory(SymbolVendor) +add_subdirectory(UnwindAssembly) diff --git a/lldb/source/Plugins/Disassembler/CMakeLists.txt b/lldb/source/Plugins/Disassembler/CMakeLists.txt index dd2113b2a68f..6e3c904d5a60 100644 --- a/lldb/source/Plugins/Disassembler/CMakeLists.txt +++ b/lldb/source/Plugins/Disassembler/CMakeLists.txt @@ -1 +1 @@ -add_subdirectory(llvm) +add_subdirectory(llvm) diff --git a/lldb/source/Plugins/Disassembler/llvm/CMakeLists.txt b/lldb/source/Plugins/Disassembler/llvm/CMakeLists.txt index f82627a809d0..7b1d56c389ba 100644 --- a/lldb/source/Plugins/Disassembler/llvm/CMakeLists.txt +++ b/lldb/source/Plugins/Disassembler/llvm/CMakeLists.txt @@ -1,5 +1,5 @@ -set(LLVM_NO_RTTI 1) - -add_lldb_library(lldbPluginDisassemblerLLVM - DisassemblerLLVMC.cpp - ) +set(LLVM_NO_RTTI 1) + +add_lldb_library(lldbPluginDisassemblerLLVM + DisassemblerLLVMC.cpp + ) diff --git a/lldb/source/Plugins/DynamicLoader/CMakeLists.txt b/lldb/source/Plugins/DynamicLoader/CMakeLists.txt index 88e6e0c931b7..c14740d05379 100644 --- a/lldb/source/Plugins/DynamicLoader/CMakeLists.txt +++ b/lldb/source/Plugins/DynamicLoader/CMakeLists.txt @@ -1,8 +1,8 @@ -add_subdirectory(MacOSX-DYLD) -add_subdirectory(POSIX-DYLD) -add_subdirectory(Static) - -if (CMAKE_SYSTEM_NAME MATCHES "Darwin") - add_subdirectory(Darwin-Kernel) -endif() - +add_subdirectory(MacOSX-DYLD) +add_subdirectory(POSIX-DYLD) +add_subdirectory(Static) + +if (CMAKE_SYSTEM_NAME MATCHES "Darwin") + add_subdirectory(Darwin-Kernel) +endif() + diff --git a/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/CMakeLists.txt b/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/CMakeLists.txt index 6db034d24d72..1facabe90129 100644 --- a/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/CMakeLists.txt +++ b/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/CMakeLists.txt @@ -1,5 +1,5 @@ -set(LLVM_NO_RTTI 1) - -add_lldb_library(lldbPluginDynamicLoaderDarwinKernel - DynamicLoaderDarwinKernel.cpp - ) +set(LLVM_NO_RTTI 1) + +add_lldb_library(lldbPluginDynamicLoaderDarwinKernel + DynamicLoaderDarwinKernel.cpp + ) diff --git a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/CMakeLists.txt b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/CMakeLists.txt index c78dc037c663..3546b6908e22 100644 --- a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/CMakeLists.txt +++ b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/CMakeLists.txt @@ -1,5 +1,5 @@ -set(LLVM_NO_RTTI 1) - -add_lldb_library(lldbPluginDynamicLoaderMacOSXDYLD - DynamicLoaderMacOSXDYLD.cpp - ) +set(LLVM_NO_RTTI 1) + +add_lldb_library(lldbPluginDynamicLoaderMacOSXDYLD + DynamicLoaderMacOSXDYLD.cpp + ) diff --git a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/CMakeLists.txt b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/CMakeLists.txt index 4dc3456c98c2..ee680382dbf0 100644 --- a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/CMakeLists.txt +++ b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/CMakeLists.txt @@ -1,7 +1,7 @@ -set(LLVM_NO_RTTI 1) - -add_lldb_library(lldbPluginDynamicLoaderPosixDYLD - AuxVector.cpp - DYLDRendezvous.cpp - DynamicLoaderPOSIXDYLD.cpp - ) +set(LLVM_NO_RTTI 1) + +add_lldb_library(lldbPluginDynamicLoaderPosixDYLD + AuxVector.cpp + DYLDRendezvous.cpp + DynamicLoaderPOSIXDYLD.cpp + ) diff --git a/lldb/source/Plugins/DynamicLoader/Static/CMakeLists.txt b/lldb/source/Plugins/DynamicLoader/Static/CMakeLists.txt index 3c0b519982e8..244079a5eee1 100644 --- a/lldb/source/Plugins/DynamicLoader/Static/CMakeLists.txt +++ b/lldb/source/Plugins/DynamicLoader/Static/CMakeLists.txt @@ -1,5 +1,5 @@ -set(LLVM_NO_RTTI 1) - -add_lldb_library(lldbPluginDynamicLoaderStatic - DynamicLoaderStatic.cpp - ) +set(LLVM_NO_RTTI 1) + +add_lldb_library(lldbPluginDynamicLoaderStatic + DynamicLoaderStatic.cpp + ) diff --git a/lldb/source/Plugins/Instruction/ARM/CMakeLists.txt b/lldb/source/Plugins/Instruction/ARM/CMakeLists.txt index 7089b8394e18..08ccb8ec6447 100644 --- a/lldb/source/Plugins/Instruction/ARM/CMakeLists.txt +++ b/lldb/source/Plugins/Instruction/ARM/CMakeLists.txt @@ -1,6 +1,6 @@ -set(LLVM_NO_RTTI 1) - -add_lldb_library(lldbPluginInstructionARM - EmulateInstructionARM.cpp - EmulationStateARM.cpp - ) +set(LLVM_NO_RTTI 1) + +add_lldb_library(lldbPluginInstructionARM + EmulateInstructionARM.cpp + EmulationStateARM.cpp + ) diff --git a/lldb/source/Plugins/Instruction/CMakeLists.txt b/lldb/source/Plugins/Instruction/CMakeLists.txt index 69a7cea6ab49..3eef5f4922ed 100644 --- a/lldb/source/Plugins/Instruction/CMakeLists.txt +++ b/lldb/source/Plugins/Instruction/CMakeLists.txt @@ -1 +1 @@ -add_subdirectory(ARM) +add_subdirectory(ARM) diff --git a/lldb/source/Plugins/LanguageRuntime/CMakeLists.txt b/lldb/source/Plugins/LanguageRuntime/CMakeLists.txt index 72694dce7e60..034ae1545ae8 100644 --- a/lldb/source/Plugins/LanguageRuntime/CMakeLists.txt +++ b/lldb/source/Plugins/LanguageRuntime/CMakeLists.txt @@ -1,2 +1,2 @@ -add_subdirectory(CPlusPlus) -add_subdirectory(ObjC) +add_subdirectory(CPlusPlus) +add_subdirectory(ObjC) diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CMakeLists.txt b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CMakeLists.txt index 4fdf10313c52..26c68c60b019 100644 --- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CMakeLists.txt +++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/CMakeLists.txt @@ -1,2 +1,2 @@ -add_subdirectory(ItaniumABI) -#add_subdirectory(MicrosoftABI) +add_subdirectory(ItaniumABI) +#add_subdirectory(MicrosoftABI) diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/CMakeLists.txt b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/CMakeLists.txt index 013663073a6a..622f1f7d11c6 100644 --- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/CMakeLists.txt +++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/CMakeLists.txt @@ -1,5 +1,5 @@ -set(LLVM_NO_RTTI 1) - -add_lldb_library(lldbPluginCXXItaniumABI - ItaniumABILanguageRuntime.cpp - ) +set(LLVM_NO_RTTI 1) + +add_lldb_library(lldbPluginCXXItaniumABI + ItaniumABILanguageRuntime.cpp + ) diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/CMakeLists.txt b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/CMakeLists.txt index d0c0181899c7..7fdd3004d1df 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/CMakeLists.txt +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/CMakeLists.txt @@ -1,10 +1,10 @@ -set(LLVM_NO_RTTI 1) - -add_lldb_library(lldbPluginAppleObjCRuntime - AppleObjCRuntime.cpp - AppleObjCRuntimeV1.cpp - AppleObjCRuntimeV2.cpp - AppleObjCTrampolineHandler.cpp - AppleObjCTypeVendor.cpp - AppleThreadPlanStepThroughObjCTrampoline.cpp - ) +set(LLVM_NO_RTTI 1) + +add_lldb_library(lldbPluginAppleObjCRuntime + AppleObjCRuntime.cpp + AppleObjCRuntimeV1.cpp + AppleObjCRuntimeV2.cpp + AppleObjCTrampolineHandler.cpp + AppleObjCTypeVendor.cpp + AppleThreadPlanStepThroughObjCTrampoline.cpp + ) diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/CMakeLists.txt b/lldb/source/Plugins/LanguageRuntime/ObjC/CMakeLists.txt index e4ce578b2207..af13dc6a144d 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/CMakeLists.txt +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/CMakeLists.txt @@ -1 +1 @@ -add_subdirectory(AppleObjCRuntime) +add_subdirectory(AppleObjCRuntime) diff --git a/lldb/source/Plugins/ObjectContainer/BSD-Archive/CMakeLists.txt b/lldb/source/Plugins/ObjectContainer/BSD-Archive/CMakeLists.txt index f206cdb477bf..deef023522d4 100644 --- a/lldb/source/Plugins/ObjectContainer/BSD-Archive/CMakeLists.txt +++ b/lldb/source/Plugins/ObjectContainer/BSD-Archive/CMakeLists.txt @@ -1,5 +1,5 @@ -set(LLVM_NO_RTTI 1) - -add_lldb_library(lldbPluginObjectContainerBSDArchive - ObjectContainerBSDArchive.cpp - ) +set(LLVM_NO_RTTI 1) + +add_lldb_library(lldbPluginObjectContainerBSDArchive + ObjectContainerBSDArchive.cpp + ) diff --git a/lldb/source/Plugins/ObjectContainer/CMakeLists.txt b/lldb/source/Plugins/ObjectContainer/CMakeLists.txt index 2a06774dd2c1..5dcef91f07d2 100644 --- a/lldb/source/Plugins/ObjectContainer/CMakeLists.txt +++ b/lldb/source/Plugins/ObjectContainer/CMakeLists.txt @@ -1,2 +1,2 @@ -add_subdirectory(BSD-Archive) -add_subdirectory(Universal-Mach-O) +add_subdirectory(BSD-Archive) +add_subdirectory(Universal-Mach-O) diff --git a/lldb/source/Plugins/ObjectContainer/Universal-Mach-O/CMakeLists.txt b/lldb/source/Plugins/ObjectContainer/Universal-Mach-O/CMakeLists.txt index 7d0aef87f743..361a23411a1a 100644 --- a/lldb/source/Plugins/ObjectContainer/Universal-Mach-O/CMakeLists.txt +++ b/lldb/source/Plugins/ObjectContainer/Universal-Mach-O/CMakeLists.txt @@ -1,5 +1,5 @@ -set(LLVM_NO_RTTI 1) - -add_lldb_library(lldbPluginObjectContainerMachOArchive - ObjectContainerUniversalMachO.cpp - ) +set(LLVM_NO_RTTI 1) + +add_lldb_library(lldbPluginObjectContainerMachOArchive + ObjectContainerUniversalMachO.cpp + ) diff --git a/lldb/source/Plugins/ObjectFile/CMakeLists.txt b/lldb/source/Plugins/ObjectFile/CMakeLists.txt index 14861ab99a39..f59a242eb490 100644 --- a/lldb/source/Plugins/ObjectFile/CMakeLists.txt +++ b/lldb/source/Plugins/ObjectFile/CMakeLists.txt @@ -1,3 +1,3 @@ -add_subdirectory(ELF) -add_subdirectory(Mach-O) -add_subdirectory(PECOFF) +add_subdirectory(ELF) +add_subdirectory(Mach-O) +add_subdirectory(PECOFF) diff --git a/lldb/source/Plugins/ObjectFile/ELF/CMakeLists.txt b/lldb/source/Plugins/ObjectFile/ELF/CMakeLists.txt index 073c47e1a8a0..ef05dcb3fd59 100644 --- a/lldb/source/Plugins/ObjectFile/ELF/CMakeLists.txt +++ b/lldb/source/Plugins/ObjectFile/ELF/CMakeLists.txt @@ -1,6 +1,6 @@ -set(LLVM_NO_RTTI 1) - -add_lldb_library(lldbPluginObjectFileELF - ELFHeader.cpp - ObjectFileELF.cpp - ) +set(LLVM_NO_RTTI 1) + +add_lldb_library(lldbPluginObjectFileELF + ELFHeader.cpp + ObjectFileELF.cpp + ) diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/CMakeLists.txt b/lldb/source/Plugins/ObjectFile/Mach-O/CMakeLists.txt index aac97135da16..06ea8317983b 100644 --- a/lldb/source/Plugins/ObjectFile/Mach-O/CMakeLists.txt +++ b/lldb/source/Plugins/ObjectFile/Mach-O/CMakeLists.txt @@ -1,5 +1,5 @@ -set(LLVM_NO_RTTI 1) - -add_lldb_library(lldbPluginObjectFileMachO - ObjectFileMachO.cpp - ) +set(LLVM_NO_RTTI 1) + +add_lldb_library(lldbPluginObjectFileMachO + ObjectFileMachO.cpp + ) diff --git a/lldb/source/Plugins/ObjectFile/PECOFF/CMakeLists.txt b/lldb/source/Plugins/ObjectFile/PECOFF/CMakeLists.txt index f704665dd0fb..1fb6bfa3ded0 100644 --- a/lldb/source/Plugins/ObjectFile/PECOFF/CMakeLists.txt +++ b/lldb/source/Plugins/ObjectFile/PECOFF/CMakeLists.txt @@ -1,5 +1,5 @@ -set(LLVM_NO_RTTI 1) - -add_lldb_library(lldbPluginObjectFilePECOFF - ObjectFilePECOFF.cpp - ) +set(LLVM_NO_RTTI 1) + +add_lldb_library(lldbPluginObjectFilePECOFF + ObjectFilePECOFF.cpp + ) diff --git a/lldb/source/Plugins/OperatingSystem/CMakeLists.txt b/lldb/source/Plugins/OperatingSystem/CMakeLists.txt index 9b07304806cd..655007a0aab9 100644 --- a/lldb/source/Plugins/OperatingSystem/CMakeLists.txt +++ b/lldb/source/Plugins/OperatingSystem/CMakeLists.txt @@ -1 +1 @@ -add_subdirectory(Python) +add_subdirectory(Python) diff --git a/lldb/source/Plugins/Platform/CMakeLists.txt b/lldb/source/Plugins/Platform/CMakeLists.txt index 3576d86bceb4..85869009a8a3 100644 --- a/lldb/source/Plugins/Platform/CMakeLists.txt +++ b/lldb/source/Plugins/Platform/CMakeLists.txt @@ -1,12 +1,12 @@ -#if (CMAKE_SYSTEM_NAME MATCHES "Linux") - add_subdirectory(Linux) -#elseif (CMAKE_SYSTEM_NAME MATCHES "FreeBSD") - add_subdirectory(FreeBSD) -#elseif (CMAKE_SYSTEM_NAME MATCHES "Darwin") - add_subdirectory(MacOSX) -#elseif (CMAKE_SYSTEM_NAME MATCHES "Windows") -# add_subdirectory(Windows) -#endif() - -add_subdirectory(POSIX) -add_subdirectory(gdb-server) +#if (CMAKE_SYSTEM_NAME MATCHES "Linux") + add_subdirectory(Linux) +#elseif (CMAKE_SYSTEM_NAME MATCHES "FreeBSD") + add_subdirectory(FreeBSD) +#elseif (CMAKE_SYSTEM_NAME MATCHES "Darwin") + add_subdirectory(MacOSX) +#elseif (CMAKE_SYSTEM_NAME MATCHES "Windows") +# add_subdirectory(Windows) +#endif() + +add_subdirectory(POSIX) +add_subdirectory(gdb-server) diff --git a/lldb/source/Plugins/Platform/MacOSX/CMakeLists.txt b/lldb/source/Plugins/Platform/MacOSX/CMakeLists.txt index bce7ac0d840d..ab4ad430ff9b 100644 --- a/lldb/source/Plugins/Platform/MacOSX/CMakeLists.txt +++ b/lldb/source/Plugins/Platform/MacOSX/CMakeLists.txt @@ -1,9 +1,9 @@ -set(LLVM_NO_RTTI 1) - -add_lldb_library(lldbPluginPlatformMacOSX - PlatformDarwin.cpp - PlatformDarwinKernel.cpp - PlatformiOSSimulator.cpp - PlatformMacOSX.cpp - PlatformRemoteiOS.cpp - ) +set(LLVM_NO_RTTI 1) + +add_lldb_library(lldbPluginPlatformMacOSX + PlatformDarwin.cpp + PlatformDarwinKernel.cpp + PlatformiOSSimulator.cpp + PlatformMacOSX.cpp + PlatformRemoteiOS.cpp + ) diff --git a/lldb/source/Plugins/Platform/POSIX/CMakeLists.txt b/lldb/source/Plugins/Platform/POSIX/CMakeLists.txt index 6802d2e80296..4b162fc7e4d1 100644 --- a/lldb/source/Plugins/Platform/POSIX/CMakeLists.txt +++ b/lldb/source/Plugins/Platform/POSIX/CMakeLists.txt @@ -1,5 +1,5 @@ -set(LLVM_NO_RTTI 1) - -add_lldb_library(lldbPluginPlatformPOSIX - PlatformPOSIX.cpp - ) +set(LLVM_NO_RTTI 1) + +add_lldb_library(lldbPluginPlatformPOSIX + PlatformPOSIX.cpp + ) diff --git a/lldb/source/Plugins/Platform/gdb-server/CMakeLists.txt b/lldb/source/Plugins/Platform/gdb-server/CMakeLists.txt index e46021ce0a8a..dcd2441c7c1b 100644 --- a/lldb/source/Plugins/Platform/gdb-server/CMakeLists.txt +++ b/lldb/source/Plugins/Platform/gdb-server/CMakeLists.txt @@ -1,5 +1,5 @@ -set(LLVM_NO_RTTI 1) - -add_lldb_library(lldbPluginPlatformGDB - PlatformRemoteGDBServer.cpp - ) +set(LLVM_NO_RTTI 1) + +add_lldb_library(lldbPluginPlatformGDB + PlatformRemoteGDBServer.cpp + ) diff --git a/lldb/source/Plugins/Process/CMakeLists.txt b/lldb/source/Plugins/Process/CMakeLists.txt index 5d8986ec5d4b..96fc57fafcbc 100644 --- a/lldb/source/Plugins/Process/CMakeLists.txt +++ b/lldb/source/Plugins/Process/CMakeLists.txt @@ -1,14 +1,14 @@ -if (CMAKE_SYSTEM_NAME MATCHES "Linux") - add_subdirectory(Linux) - add_subdirectory(POSIX) - add_subdirectory(elf-core) -elseif (CMAKE_SYSTEM_NAME MATCHES "FreeBSD") - add_subdirectory(FreeBSD) - add_subdirectory(POSIX) - add_subdirectory(elf-core) -elseif (CMAKE_SYSTEM_NAME MATCHES "Darwin") - add_subdirectory(MacOSX-Kernel) -endif() -add_subdirectory(gdb-remote) -add_subdirectory(Utility) -add_subdirectory(mach-core) +if (CMAKE_SYSTEM_NAME MATCHES "Linux") + add_subdirectory(Linux) + add_subdirectory(POSIX) + add_subdirectory(elf-core) +elseif (CMAKE_SYSTEM_NAME MATCHES "FreeBSD") + add_subdirectory(FreeBSD) + add_subdirectory(POSIX) + add_subdirectory(elf-core) +elseif (CMAKE_SYSTEM_NAME MATCHES "Darwin") + add_subdirectory(MacOSX-Kernel) +endif() +add_subdirectory(gdb-remote) +add_subdirectory(Utility) +add_subdirectory(mach-core) diff --git a/lldb/source/Plugins/SymbolFile/CMakeLists.txt b/lldb/source/Plugins/SymbolFile/CMakeLists.txt index 85e7129de432..add6697389f9 100644 --- a/lldb/source/Plugins/SymbolFile/CMakeLists.txt +++ b/lldb/source/Plugins/SymbolFile/CMakeLists.txt @@ -1,2 +1,2 @@ -add_subdirectory(DWARF) -add_subdirectory(Symtab) +add_subdirectory(DWARF) +add_subdirectory(Symtab) diff --git a/lldb/source/Plugins/SymbolFile/DWARF/CMakeLists.txt b/lldb/source/Plugins/SymbolFile/DWARF/CMakeLists.txt index 987111c98ca0..6464dc3fa8bd 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/CMakeLists.txt +++ b/lldb/source/Plugins/SymbolFile/DWARF/CMakeLists.txt @@ -1,28 +1,28 @@ -set(LLVM_NO_RTTI 1) - -add_lldb_library(lldbPluginSymbolFileDWARF - DWARFAbbreviationDeclaration.cpp - DWARFCompileUnit.cpp - DWARFDebugAbbrev.cpp - DWARFDebugAranges.cpp - DWARFDebugArangeSet.cpp - DWARFDebugInfo.cpp - DWARFDebugInfoEntry.cpp - DWARFDebugLine.cpp - DWARFDebugMacinfo.cpp - DWARFDebugMacinfoEntry.cpp - DWARFDebugPubnames.cpp - DWARFDebugPubnamesSet.cpp - DWARFDebugRanges.cpp - DWARFDeclContext.cpp - DWARFDefines.cpp - DWARFDIECollection.cpp - DWARFFormValue.cpp - DWARFLocationDescription.cpp - DWARFLocationList.cpp - LogChannelDWARF.cpp - NameToDIE.cpp - SymbolFileDWARF.cpp - SymbolFileDWARFDebugMap.cpp - UniqueDWARFASTType.cpp - ) +set(LLVM_NO_RTTI 1) + +add_lldb_library(lldbPluginSymbolFileDWARF + DWARFAbbreviationDeclaration.cpp + DWARFCompileUnit.cpp + DWARFDebugAbbrev.cpp + DWARFDebugAranges.cpp + DWARFDebugArangeSet.cpp + DWARFDebugInfo.cpp + DWARFDebugInfoEntry.cpp + DWARFDebugLine.cpp + DWARFDebugMacinfo.cpp + DWARFDebugMacinfoEntry.cpp + DWARFDebugPubnames.cpp + DWARFDebugPubnamesSet.cpp + DWARFDebugRanges.cpp + DWARFDeclContext.cpp + DWARFDefines.cpp + DWARFDIECollection.cpp + DWARFFormValue.cpp + DWARFLocationDescription.cpp + DWARFLocationList.cpp + LogChannelDWARF.cpp + NameToDIE.cpp + SymbolFileDWARF.cpp + SymbolFileDWARFDebugMap.cpp + UniqueDWARFASTType.cpp + ) diff --git a/lldb/source/Plugins/SymbolFile/Symtab/CMakeLists.txt b/lldb/source/Plugins/SymbolFile/Symtab/CMakeLists.txt index 00252ffeeb4e..eb7aed8403c9 100644 --- a/lldb/source/Plugins/SymbolFile/Symtab/CMakeLists.txt +++ b/lldb/source/Plugins/SymbolFile/Symtab/CMakeLists.txt @@ -1,5 +1,5 @@ -set(LLVM_NO_RTTI 1) - -add_lldb_library(lldbPluginSymbolFileSymtab - SymbolFileSymtab.cpp - ) +set(LLVM_NO_RTTI 1) + +add_lldb_library(lldbPluginSymbolFileSymtab + SymbolFileSymtab.cpp + ) diff --git a/lldb/source/Plugins/SymbolVendor/CMakeLists.txt b/lldb/source/Plugins/SymbolVendor/CMakeLists.txt index 9f5c6311b22d..94862d588727 100644 --- a/lldb/source/Plugins/SymbolVendor/CMakeLists.txt +++ b/lldb/source/Plugins/SymbolVendor/CMakeLists.txt @@ -1,5 +1,5 @@ -if (CMAKE_SYSTEM_NAME MATCHES "Darwin") - add_subdirectory(MacOSX) -endif() - -add_subdirectory(ELF) +if (CMAKE_SYSTEM_NAME MATCHES "Darwin") + add_subdirectory(MacOSX) +endif() + +add_subdirectory(ELF) diff --git a/lldb/source/Plugins/SymbolVendor/ELF/CMakeLists.txt b/lldb/source/Plugins/SymbolVendor/ELF/CMakeLists.txt index 2401b76a3428..9fa601697d5a 100644 --- a/lldb/source/Plugins/SymbolVendor/ELF/CMakeLists.txt +++ b/lldb/source/Plugins/SymbolVendor/ELF/CMakeLists.txt @@ -1,5 +1,5 @@ -set(LLVM_NO_RTTI 1) - -add_lldb_library(lldbPluginSymbolVendorELF - SymbolVendorELF.cpp - ) +set(LLVM_NO_RTTI 1) + +add_lldb_library(lldbPluginSymbolVendorELF + SymbolVendorELF.cpp + ) diff --git a/lldb/source/Plugins/SymbolVendor/MacOSX/CMakeLists.txt b/lldb/source/Plugins/SymbolVendor/MacOSX/CMakeLists.txt index 6a0040f2674b..a17150ffbf93 100644 --- a/lldb/source/Plugins/SymbolVendor/MacOSX/CMakeLists.txt +++ b/lldb/source/Plugins/SymbolVendor/MacOSX/CMakeLists.txt @@ -1,7 +1,7 @@ -set(LLVM_NO_RTTI 1) - -include_directories(${LIBXML2_INCLUDE_DIR}) - -add_lldb_library(lldbPluginSymbolVendorMacOSX - SymbolVendorMacOSX.cpp - ) +set(LLVM_NO_RTTI 1) + +include_directories(${LIBXML2_INCLUDE_DIR}) + +add_lldb_library(lldbPluginSymbolVendorMacOSX + SymbolVendorMacOSX.cpp + ) diff --git a/lldb/source/Plugins/UnwindAssembly/CMakeLists.txt b/lldb/source/Plugins/UnwindAssembly/CMakeLists.txt index c4a972991fb0..1723a0604580 100644 --- a/lldb/source/Plugins/UnwindAssembly/CMakeLists.txt +++ b/lldb/source/Plugins/UnwindAssembly/CMakeLists.txt @@ -1,2 +1,2 @@ -add_subdirectory(InstEmulation) -add_subdirectory(x86) +add_subdirectory(InstEmulation) +add_subdirectory(x86) diff --git a/lldb/source/Plugins/UnwindAssembly/InstEmulation/CMakeLists.txt b/lldb/source/Plugins/UnwindAssembly/InstEmulation/CMakeLists.txt index 6003672711ac..b07a30bed61d 100644 --- a/lldb/source/Plugins/UnwindAssembly/InstEmulation/CMakeLists.txt +++ b/lldb/source/Plugins/UnwindAssembly/InstEmulation/CMakeLists.txt @@ -1,5 +1,5 @@ -set(LLVM_NO_RTTI 1) - -add_lldb_library(lldbPluginUnwindAssemblyInstEmulation - UnwindAssemblyInstEmulation.cpp - ) +set(LLVM_NO_RTTI 1) + +add_lldb_library(lldbPluginUnwindAssemblyInstEmulation + UnwindAssemblyInstEmulation.cpp + ) diff --git a/lldb/source/Plugins/UnwindAssembly/x86/CMakeLists.txt b/lldb/source/Plugins/UnwindAssembly/x86/CMakeLists.txt index bb0ffad0bbab..2f81fc89ae6e 100644 --- a/lldb/source/Plugins/UnwindAssembly/x86/CMakeLists.txt +++ b/lldb/source/Plugins/UnwindAssembly/x86/CMakeLists.txt @@ -1,5 +1,5 @@ -set(LLVM_NO_RTTI 1) - -add_lldb_library(lldbPluginUnwindAssemblyX86 - UnwindAssembly-x86.cpp - ) +set(LLVM_NO_RTTI 1) + +add_lldb_library(lldbPluginUnwindAssemblyX86 + UnwindAssembly-x86.cpp + ) diff --git a/lldb/source/Symbol/CMakeLists.txt b/lldb/source/Symbol/CMakeLists.txt index 9386bd1f4a61..96b5c4baf3bf 100644 --- a/lldb/source/Symbol/CMakeLists.txt +++ b/lldb/source/Symbol/CMakeLists.txt @@ -1,31 +1,31 @@ -set(LLVM_NO_RTTI 1) - -add_lldb_library(lldbSymbol - Block.cpp - ClangASTContext.cpp - ClangASTImporter.cpp - ClangASTType.cpp - ClangExternalASTSourceCallbacks.cpp - ClangExternalASTSourceCommon.cpp - ClangNamespaceDecl.cpp - CompileUnit.cpp - Declaration.cpp - DWARFCallFrameInfo.cpp - Function.cpp - FuncUnwinders.cpp - LineEntry.cpp - LineTable.cpp - ObjectFile.cpp - Symbol.cpp - SymbolContext.cpp - SymbolFile.cpp - SymbolVendor.cpp - Symtab.cpp - Type.cpp - TypeList.cpp - UnwindPlan.cpp - UnwindTable.cpp - Variable.cpp - VariableList.cpp - VerifyDecl.cpp - ) +set(LLVM_NO_RTTI 1) + +add_lldb_library(lldbSymbol + Block.cpp + ClangASTContext.cpp + ClangASTImporter.cpp + ClangASTType.cpp + ClangExternalASTSourceCallbacks.cpp + ClangExternalASTSourceCommon.cpp + ClangNamespaceDecl.cpp + CompileUnit.cpp + Declaration.cpp + DWARFCallFrameInfo.cpp + Function.cpp + FuncUnwinders.cpp + LineEntry.cpp + LineTable.cpp + ObjectFile.cpp + Symbol.cpp + SymbolContext.cpp + SymbolFile.cpp + SymbolVendor.cpp + Symtab.cpp + Type.cpp + TypeList.cpp + UnwindPlan.cpp + UnwindTable.cpp + Variable.cpp + VariableList.cpp + VerifyDecl.cpp + ) diff --git a/lldb/source/Target/CMakeLists.txt b/lldb/source/Target/CMakeLists.txt index 383e6db42cc3..29f9bcddc421 100644 --- a/lldb/source/Target/CMakeLists.txt +++ b/lldb/source/Target/CMakeLists.txt @@ -1,44 +1,44 @@ -set(LLVM_NO_RTTI 1) - -include_directories(../Plugins/Process/Utility) - -add_lldb_library(lldbTarget - ABI.cpp - CPPLanguageRuntime.cpp - ExecutionContext.cpp - LanguageRuntime.cpp - Memory.cpp - ObjCLanguageRuntime.cpp - OperatingSystem.cpp - PathMappingList.cpp - Platform.cpp - Process.cpp - RegisterContext.cpp - SectionLoadList.cpp - StackFrame.cpp - StackFrameList.cpp - StackID.cpp - StopInfo.cpp - Target.cpp - TargetList.cpp - Thread.cpp - ThreadList.cpp - ThreadPlan.cpp - ThreadPlanBase.cpp - ThreadPlanCallFunction.cpp - ThreadPlanCallUserExpression.cpp - ThreadPlanRunToAddress.cpp - ThreadPlanShouldStopHere.cpp - ThreadPlanStepInRange.cpp - ThreadPlanStepInstruction.cpp - ThreadPlanStepOut.cpp - ThreadPlanStepOverBreakpoint.cpp - ThreadPlanStepOverRange.cpp - ThreadPlanStepRange.cpp - ThreadPlanStepThrough.cpp - ThreadPlanStepUntil.cpp - ThreadPlanTracer.cpp - ThreadSpec.cpp - UnixSignals.cpp - UnwindAssembly.cpp - ) +set(LLVM_NO_RTTI 1) + +include_directories(../Plugins/Process/Utility) + +add_lldb_library(lldbTarget + ABI.cpp + CPPLanguageRuntime.cpp + ExecutionContext.cpp + LanguageRuntime.cpp + Memory.cpp + ObjCLanguageRuntime.cpp + OperatingSystem.cpp + PathMappingList.cpp + Platform.cpp + Process.cpp + RegisterContext.cpp + SectionLoadList.cpp + StackFrame.cpp + StackFrameList.cpp + StackID.cpp + StopInfo.cpp + Target.cpp + TargetList.cpp + Thread.cpp + ThreadList.cpp + ThreadPlan.cpp + ThreadPlanBase.cpp + ThreadPlanCallFunction.cpp + ThreadPlanCallUserExpression.cpp + ThreadPlanRunToAddress.cpp + ThreadPlanShouldStopHere.cpp + ThreadPlanStepInRange.cpp + ThreadPlanStepInstruction.cpp + ThreadPlanStepOut.cpp + ThreadPlanStepOverBreakpoint.cpp + ThreadPlanStepOverRange.cpp + ThreadPlanStepRange.cpp + ThreadPlanStepThrough.cpp + ThreadPlanStepUntil.cpp + ThreadPlanTracer.cpp + ThreadSpec.cpp + UnixSignals.cpp + UnwindAssembly.cpp + ) diff --git a/lldb/source/Utility/CMakeLists.txt b/lldb/source/Utility/CMakeLists.txt index 64b17871fb08..19dcde5930b4 100644 --- a/lldb/source/Utility/CMakeLists.txt +++ b/lldb/source/Utility/CMakeLists.txt @@ -1,12 +1,12 @@ -set(LLVM_NO_RTTI 1) - -add_lldb_library(lldbUtility - ARM_DWARF_Registers.cpp - KQueue.cpp - PseudoTerminal.cpp - Range.cpp - SharingPtr.cpp - StringExtractor.cpp - StringExtractorGDBRemote.cpp - TimeSpecTimeout.cpp - ) +set(LLVM_NO_RTTI 1) + +add_lldb_library(lldbUtility + ARM_DWARF_Registers.cpp + KQueue.cpp + PseudoTerminal.cpp + Range.cpp + SharingPtr.cpp + StringExtractor.cpp + StringExtractorGDBRemote.cpp + TimeSpecTimeout.cpp + ) diff --git a/lldb/tools/CMakeLists.txt b/lldb/tools/CMakeLists.txt index b1989f815518..3f3a490d4ad7 100644 --- a/lldb/tools/CMakeLists.txt +++ b/lldb/tools/CMakeLists.txt @@ -1,7 +1,7 @@ -if (CMAKE_SYSTEM_NAME MATCHES "Darwin") - add_subdirectory(debugserver) -endif() -if (NOT CMAKE_SYSTEM_NAME MATCHES "Windows") - add_subdirectory(driver) - add_subdirectory(lldb-platform) -endif() +if (CMAKE_SYSTEM_NAME MATCHES "Darwin") + add_subdirectory(debugserver) +endif() +if (NOT CMAKE_SYSTEM_NAME MATCHES "Windows") + add_subdirectory(driver) + add_subdirectory(lldb-platform) +endif() diff --git a/lldb/tools/driver/CMakeLists.txt b/lldb/tools/driver/CMakeLists.txt index c70a2dba699e..bbd792a3818d 100644 --- a/lldb/tools/driver/CMakeLists.txt +++ b/lldb/tools/driver/CMakeLists.txt @@ -1,18 +1,18 @@ -set(LLVM_NO_RTTI 1) -add_lldb_executable(lldb - Driver.cpp - #DriverEvents.cpp - #DriverOptions.cpp - #DriverPosix.cpp - IOChannel.cpp - ) - -target_link_libraries(lldb liblldb) -# TODO: why isn't this done by add_lldb_executable? -#target_link_libraries(lldb ${LLDB_USED_LIBS}) -#llvm_config(lldb ${LLVM_LINK_COMPONENTS}) - -set_target_properties(lldb PROPERTIES VERSION ${LLDB_VERSION}) - -install(TARGETS lldb - RUNTIME DESTINATION bin) +set(LLVM_NO_RTTI 1) +add_lldb_executable(lldb + Driver.cpp + #DriverEvents.cpp + #DriverOptions.cpp + #DriverPosix.cpp + IOChannel.cpp + ) + +target_link_libraries(lldb liblldb) +# TODO: why isn't this done by add_lldb_executable? +#target_link_libraries(lldb ${LLDB_USED_LIBS}) +#llvm_config(lldb ${LLVM_LINK_COMPONENTS}) + +set_target_properties(lldb PROPERTIES VERSION ${LLDB_VERSION}) + +install(TARGETS lldb + RUNTIME DESTINATION bin) diff --git a/lldb/tools/lldb-platform/CMakeLists.txt b/lldb/tools/lldb-platform/CMakeLists.txt index 97ccde10199d..f3c70a7000c7 100644 --- a/lldb/tools/lldb-platform/CMakeLists.txt +++ b/lldb/tools/lldb-platform/CMakeLists.txt @@ -1,14 +1,14 @@ -set(LLVM_NO_RTTI 1) - -include_directories(../../source) - -add_lldb_executable(lldb-platform - lldb-platform.cpp - ) - -target_link_libraries(lldb-platform liblldb) - -set_target_properties(lldb-platform PROPERTIES VERSION ${LLDB_VERSION}) - -install(TARGETS lldb-platform - RUNTIME DESTINATION bin) +set(LLVM_NO_RTTI 1) + +include_directories(../../source) + +add_lldb_executable(lldb-platform + lldb-platform.cpp + ) + +target_link_libraries(lldb-platform liblldb) + +set_target_properties(lldb-platform PROPERTIES VERSION ${LLDB_VERSION}) + +install(TARGETS lldb-platform + RUNTIME DESTINATION bin) diff --git a/lldb/www/architecture.html b/lldb/www/architecture.html index 98b91b264b82..473ef800f97a 100755 --- a/lldb/www/architecture.html +++ b/lldb/www/architecture.html @@ -1,282 +1,282 @@ - - - - - -LLDB Architecture - - - -
- The LLDB Debugger -
- -
-
- - - -
-
-

Architecture

-
- -

LLDB is a large and complex codebase. This section will help you become more familiar with - the pieces that make up LLDB and give a general overview of the general architecture.

-
- -
-
-

Code Layout

-
- -

LLDB has many code groupings that makeup the source base:

- -
- -
- -
-

API

-
- -

The API folder contains the public interface to LLDB.

-

We are currently vending a C++ API. In order to be able to add - methods to this API and allow people to link to our classes, - we have certain rules that we must follow:

-
    -
  • Classes can't inherit from any other classes.
  • -
  • Classes can't contain virtual methods.
  • -
  • Classes should be compatible with script bridging utilities like swig.
  • -
  • Classes should be lightweight and be backed by a single member. Pointers (or shared pointers) are the preferred choice since they allow changing the contents of the backend without affecting the public object layout.
  • -
  • The interface should be as minimal as possible in order to give a complete API.
  • -
-

By adhering to these rules we should be able to continue to - vend a C++ API, and make changes to the API as any additional - methods added to these classes will just be a dynamic loader - lookup and they won't affect the class layout (since they - aren't virtual methods, and no members can be added to the - class).

-
- -
- -
-

Breakpoint

-
- -

A collection of classes that implement our breakpoint classes. - Breakpoints are resolved symbolically and always continue to - resolve themselves as your program runs. Whether settings breakpoints - by file and line, by symbol name, by symbol regular expression, - or by address, breakpoints will keep trying to resolve new locations - each time shared libraries are loaded. Breakpoints will of course - unresolve themselves when shared libraries are unloaded. Breakpoints - can also be scoped to be set only in a specific shared library. By - default, breakpoints can be set in any shared library and will continue - to attempt to be resolved with each shared library load.

-

Breakpoint options can be set on the breakpoint, - or on the individual locations. This allows flexibility when dealing - with breakpoints and allows us to do what the user wants.

-
- -
- -
-

Commands

-
- -

The command source files represent objects that implement - the functionality for all textual commands available - in our command line interface.

-

Every command is backed by a lldb_private::CommandObject - or lldb_private::CommandObjectMultiword object.

-

lldb_private::CommandObjectMultiword are commands that - have subcommands and allow command line commands to be - logically grouped into a hierarchy.

-

lldb_private::CommandObject command line commands - are the objects that implement the functionality of the - command. They can optionally define - options for themselves, as well as group those options into - logical groups that can go together. The help system is - tied into these objects and can extract the syntax and - option groupings to display appropriate help for each - command.

-
- -
- -
-

Core

-
- -

The Core source files contain basic functionality that - is required in the debugger. A wide variety of classes - are implemented:

- -
    -
  • Address (section offset addressing)
  • -
  • AddressRange
  • -
  • Architecture specification
  • -
  • Broadcaster / Event / Listener
  • -
  • Communication classes that use Connection objects
  • -
  • Uniqued C strings
  • -
  • Data extraction
  • -
  • File specifications
  • -
  • Mangled names
  • -
  • Regular expressions
  • -
  • Source manager
  • -
  • Streams
  • -
  • Value objects
  • -
-
- -
- -
-

DataFormatters

-
- -

A collection of classes that implement the data formatters subsystem.

-

The main entry point for interacting with the LLDB data formatters is the DataVisualization class. It provides - a relatively stable front-end interface to ask questions of the data formatters regardless of the internal implementation.

-

For people actively maintaining the data formatters subsystem itself, however, the FormatManager class is the relevant point of entry. - This class is subject to more frequent changes as the formatters evolve. Currently, it provides a thin caching layer on top of a list of categories - that each export a group of formatters. -

-

From an end-user perspective, the "type" LLDB command is the point of access to the data formatters. A large group of generally-useful formatters - is provided by default and loaded upon debugger startup. -

- -
- -
-

Expression

-
- -

Expression parsing files cover everything from evaluating - DWARF expressions, to evaluating expressions using - Clang.

-

The DWARF expression parser has been heavily modified to - support type promotion, new opcodes needed for evaluating - expressions with symbolic variable references (expression local variables, - program variables), and other operators required by - typical expressions such as assign, address of, float/double/long - double floating point values, casting, and more. The - DWARF expression parser uses a stack of lldb_private::Value - objects. These objects know how to do the standard C type - promotion, and allow for symbolic references to variables - in the program and in the LLDB process (expression local - and expression global variables).

-

The expression parser uses a full instance of the Clang - compiler in order to accurately evaluate expressions. - Hooks have been put into Clang so that the compiler knows - to ask about identifiers it doesn't know about. Once - expressions have be compiled into an AST, we can then - traverse this AST and either generate a DWARF expression - that contains simple opcodes that can be quickly re-evaluated - each time an expression needs to be evaluated, or JIT'ed - up into code that can be run on the process being debugged.

-
- -
- -
-

Host

-
- -

LLDB tries to abstract itself from the host upon which - it is currently running by providing a host abstraction - layer. This layer involves everything from spawning, detaching, - joining and killing native in-process threads, to getting - current information about the current host.

-

Host functionality includes abstraction layers for:

-
    -
  • Mutexes
  • -
  • Conditions
  • -
  • Timing functions
  • -
  • Thread functions
  • -
  • Host target triple
  • -
  • Host child process notifications
  • -
  • Host specific types
  • -
-
- -
- -
-

Interpreter

-
- -

The interpreter classes are the classes responsible for - being the base classes needed for each command object, - and is responsible for tracking and running command line - commands.

-
- -
- -
-

Symbol

-
-

Symbol classes involve everything needed in order to parse - object files and debug symbols. All the needed classes - for compilation units (code and debug info for a source file), - functions, lexical blocks within functions, inlined - functions, types, declaration locations, and variables - are in this section.

-
- -
- -
-

Target

-
- -

Classes that are related to a debug target include:

-
    -
  • Target
  • -
  • Process
  • -
  • Thread
  • -
  • Stack frames
  • -
  • Stack frame registers
  • -
  • ABI for function calling in process being debugged
  • -
  • Execution context batons
  • -
-
- -
- -
-

Utility

-
- -

Utility files should be as stand alone as possible and - available for LLDB, plug-ins or related - applications to use.

-

Files found in the Utility section include:

-
    -
  • Pseudo-terminal support
  • -
  • Register numbering for specific architectures.
  • -
  • String data extractors
  • -
-
- -
-
-
-
- - + + + + + +LLDB Architecture + + + +
+ The LLDB Debugger +
+ +
+
+ + + +
+
+

Architecture

+
+ +

LLDB is a large and complex codebase. This section will help you become more familiar with + the pieces that make up LLDB and give a general overview of the general architecture.

+
+ +
+
+

Code Layout

+
+ +

LLDB has many code groupings that makeup the source base:

+ +
+ +
+ +
+

API

+
+ +

The API folder contains the public interface to LLDB.

+

We are currently vending a C++ API. In order to be able to add + methods to this API and allow people to link to our classes, + we have certain rules that we must follow:

+
    +
  • Classes can't inherit from any other classes.
  • +
  • Classes can't contain virtual methods.
  • +
  • Classes should be compatible with script bridging utilities like swig.
  • +
  • Classes should be lightweight and be backed by a single member. Pointers (or shared pointers) are the preferred choice since they allow changing the contents of the backend without affecting the public object layout.
  • +
  • The interface should be as minimal as possible in order to give a complete API.
  • +
+

By adhering to these rules we should be able to continue to + vend a C++ API, and make changes to the API as any additional + methods added to these classes will just be a dynamic loader + lookup and they won't affect the class layout (since they + aren't virtual methods, and no members can be added to the + class).

+
+ +
+ +
+

Breakpoint

+
+ +

A collection of classes that implement our breakpoint classes. + Breakpoints are resolved symbolically and always continue to + resolve themselves as your program runs. Whether settings breakpoints + by file and line, by symbol name, by symbol regular expression, + or by address, breakpoints will keep trying to resolve new locations + each time shared libraries are loaded. Breakpoints will of course + unresolve themselves when shared libraries are unloaded. Breakpoints + can also be scoped to be set only in a specific shared library. By + default, breakpoints can be set in any shared library and will continue + to attempt to be resolved with each shared library load.

+

Breakpoint options can be set on the breakpoint, + or on the individual locations. This allows flexibility when dealing + with breakpoints and allows us to do what the user wants.

+
+ +
+ +
+

Commands

+
+ +

The command source files represent objects that implement + the functionality for all textual commands available + in our command line interface.

+

Every command is backed by a lldb_private::CommandObject + or lldb_private::CommandObjectMultiword object.

+

lldb_private::CommandObjectMultiword are commands that + have subcommands and allow command line commands to be + logically grouped into a hierarchy.

+

lldb_private::CommandObject command line commands + are the objects that implement the functionality of the + command. They can optionally define + options for themselves, as well as group those options into + logical groups that can go together. The help system is + tied into these objects and can extract the syntax and + option groupings to display appropriate help for each + command.

+
+ +
+ +
+

Core

+
+ +

The Core source files contain basic functionality that + is required in the debugger. A wide variety of classes + are implemented:

+ +
    +
  • Address (section offset addressing)
  • +
  • AddressRange
  • +
  • Architecture specification
  • +
  • Broadcaster / Event / Listener
  • +
  • Communication classes that use Connection objects
  • +
  • Uniqued C strings
  • +
  • Data extraction
  • +
  • File specifications
  • +
  • Mangled names
  • +
  • Regular expressions
  • +
  • Source manager
  • +
  • Streams
  • +
  • Value objects
  • +
+
+ +
+ +
+

DataFormatters

+
+ +

A collection of classes that implement the data formatters subsystem.

+

The main entry point for interacting with the LLDB data formatters is the DataVisualization class. It provides + a relatively stable front-end interface to ask questions of the data formatters regardless of the internal implementation.

+

For people actively maintaining the data formatters subsystem itself, however, the FormatManager class is the relevant point of entry. + This class is subject to more frequent changes as the formatters evolve. Currently, it provides a thin caching layer on top of a list of categories + that each export a group of formatters. +

+

From an end-user perspective, the "type" LLDB command is the point of access to the data formatters. A large group of generally-useful formatters + is provided by default and loaded upon debugger startup. +

+ +
+ +
+

Expression

+
+ +

Expression parsing files cover everything from evaluating + DWARF expressions, to evaluating expressions using + Clang.

+

The DWARF expression parser has been heavily modified to + support type promotion, new opcodes needed for evaluating + expressions with symbolic variable references (expression local variables, + program variables), and other operators required by + typical expressions such as assign, address of, float/double/long + double floating point values, casting, and more. The + DWARF expression parser uses a stack of lldb_private::Value + objects. These objects know how to do the standard C type + promotion, and allow for symbolic references to variables + in the program and in the LLDB process (expression local + and expression global variables).

+

The expression parser uses a full instance of the Clang + compiler in order to accurately evaluate expressions. + Hooks have been put into Clang so that the compiler knows + to ask about identifiers it doesn't know about. Once + expressions have be compiled into an AST, we can then + traverse this AST and either generate a DWARF expression + that contains simple opcodes that can be quickly re-evaluated + each time an expression needs to be evaluated, or JIT'ed + up into code that can be run on the process being debugged.

+
+ +
+ +
+

Host

+
+ +

LLDB tries to abstract itself from the host upon which + it is currently running by providing a host abstraction + layer. This layer involves everything from spawning, detaching, + joining and killing native in-process threads, to getting + current information about the current host.

+

Host functionality includes abstraction layers for:

+
    +
  • Mutexes
  • +
  • Conditions
  • +
  • Timing functions
  • +
  • Thread functions
  • +
  • Host target triple
  • +
  • Host child process notifications
  • +
  • Host specific types
  • +
+
+ +
+ +
+

Interpreter

+
+ +

The interpreter classes are the classes responsible for + being the base classes needed for each command object, + and is responsible for tracking and running command line + commands.

+
+ +
+ +
+

Symbol

+
+

Symbol classes involve everything needed in order to parse + object files and debug symbols. All the needed classes + for compilation units (code and debug info for a source file), + functions, lexical blocks within functions, inlined + functions, types, declaration locations, and variables + are in this section.

+
+ +
+ +
+

Target

+
+ +

Classes that are related to a debug target include:

+
    +
  • Target
  • +
  • Process
  • +
  • Thread
  • +
  • Stack frames
  • +
  • Stack frame registers
  • +
  • ABI for function calling in process being debugged
  • +
  • Execution context batons
  • +
+
+ +
+ +
+

Utility

+
+ +

Utility files should be as stand alone as possible and + available for LLDB, plug-ins or related + applications to use.

+

Files found in the Utility section include:

+
    +
  • Pseudo-terminal support
  • +
  • Register numbering for specific architectures.
  • +
  • String data extractors
  • +
+
+ +
+
+
+
+ + diff --git a/lldb/www/build.html b/lldb/www/build.html index e545b1198a49..755e608ee7d5 100755 --- a/lldb/www/build.html +++ b/lldb/www/build.html @@ -1,241 +1,241 @@ - - - - - -Building LLDB - - - -
- The LLDB Debugger -
- -
-
- - - -
-

Continuous Integraton

-
-

The following LLVM buildbots build and test LLDB trunk: -

-
- -
-

Building LLDB on Mac OS X

-
-

Building on Mac OS X is as easy as downloading the code and building the Xcode project or workspace:

-
-
-

Preliminaries

-
    -
  • XCode 4.3 or newer requires the "Command Line Tools" component (XCode->Preferences->Downloads->Components).
  • -
  • Mac OS X Lion or newer requires installing Swig.
  • -
-

Building LLDB

-
    -
  • Download the lldb sources.
  • -
  • Follow the code signing instructions in lldb/docs/code-signing.txt
  • -
  • In Xcode 3.x: lldb/lldb.xcodeproj, select the lldb-tool target, and build.
  • -
  • In Xcode 4.x: lldb/lldb.xcworkspace, select the lldb-tool scheme, and build.
  • -
-
- -
-
-

Building LLDB on Linux and FreeBSD

-
-

This document describes the steps needed to compile LLDB on most Linux systems, and FreeBSD.

-
-
-

Preliminaries

-

LLDB relies on many of the technologies developed by the larger LLVM project. - In particular, it requires both Clang and LLVM itself in order to build. Due to - this tight integration the Getting Started guides for both of these projects - come as prerequisite reading:

- -

Supported compilers for building LLDB on Linux include:

-
    -
  • Clang 3.2
  • -
  • GCC 4.6.2 (later versions should work as well)
  • -
-

It is recommended to use libstdc++ 4.6 (or higher) to build LLDB on Linux, but using libc++ is also known to work.

-

On FreeBSD the base system Clang and libc++ may be used to build LLDB, - or the GCC port or package.

-

In addition to any dependencies required by LLVM and Clang, LLDB needs a few - development packages that may also need to be installed depending on your - system. The current list of dependencies are:

- -

So for example, on a Fedora system one might run:

- > yum install swig python-devel libedit-devel -

On an Ubuntu system one might run:

- > sudo apt-get install build-essential subversion swig python-dev libedit-dev -

On FreeBSD one might run:

- > pkg install swig python -

If you wish to build the optional reference documentation, additional dependencies are required:

-
    -
  • Graphviz (for the 'dot' tool). -
  • doxygen (only if you wish to build the C++ API reference) -
  • epydoc (only if you wish to build the Python API reference) -
-

To install the prerequisites for building the documentation (on Ubuntu) do:

- -
> sudo apt-get install doxygen graphviz -
> sudo pip install epydoc -
-

Building LLDB

-

We first need to checkout the source trees into the appropriate locations. Both - Clang and LLDB build as subprojects of LLVM. This means we will be checking out - the source for both Clang and LLDB into the tools subdirectory of LLVM. We - will be setting up a directory hierarchy looking something like this:

-

-

  
-                  llvm
-                  |
-                  `-- tools
-                      |
-                      +-- clang
-                      |
-                      `-- lldb
-                
-

-

For reference, we will call the root of the LLVM project tree $llvm, and the - roots of the Clang and LLDB source trees $clang and $lldb respectively.

-

Change to the directory where you want to do development work and checkout LLVM:

- > svn co http://llvm.org/svn/llvm-project/llvm/trunk llvm - -

Now switch to LLVM’s tools subdirectory and checkout both Clang and LLDB:

- > cd $llvm/tools -
> svn co http://llvm.org/svn/llvm-project/cfe/trunk clang -
> svn co http://llvm.org/svn/llvm-project/lldb/trunk lldb -
- -

In general, building the LLDB trunk revision requires trunk revisions of both - LLVM and Clang. -

It is highly recommended that you build the system out of tree. Create a second - build directory and configure the LLVM project tree to your specifications as - outlined in LLVM’s Getting Started Guide. A typical build procedure - might be:

- > cd $llvm/.. -
> mkdir build -
> cd build -
-

To build with CMake

-

Using CMake is documented on the Building LLVM with CMake - page. Building LLDB is possible using one of the following generators: -

-
    -
  • Ninja
  • -
  • Unix Makefiles
  • -
-

Using CMake + Ninja

-

Ninja is the fastest way to build LLDB! In order to use ninja, you need to have recent versions of CMake and - ninja on your system. To build using ninja: -

- - > cmake .. -G Ninja -
> ninja lldb -
> ninja check-lldb -
-

Using CMake + Unix Makefiles

-

If you do not have Ninja, you can still use CMake to generate Unix Makefiles that build LLDB:

- - > cmake .. -
> make -
> make check-lldb -
-

To build with autoconf

-

If you do not have CMake, it is still possible to build LLDB using the autoconf build system. If you are using - Clang or GCC 4.7+, run:

- - > $llvm/configure --enable-cxx11 -
> make
-

Or, if you are using a version of GCC that does not support the -std=c++11 option:

- - > $llvm/configure -
> make CXXFLAGS=-std=c++0x
-

If you are building with a GCC that isn't the default gcc/g++, like gcc-4.7/g++-4.7

- - > $llvm/configure --enable-cxx11 CC=gcc-4.7 CXX=g++-4.7 -
> make CC=gcc-4.7 CXX=g++-4.7
-

If you are running in a system that doesn't have a lot of RAM (less than 4GB), you might want to disable - debug symbols by specifying DEBUG_SYMBOLS=0 when running make. You will know if you need to enable this - because you will fail to link clang (the linker will get a SIGKILL and exit with status 9).

- - > make DEBUG_SYMBOLS=0 -

To run the LLDB test suite, run:

- -
> make -C tools/lldb/test
-

Note that once both LLVM and Clang have been configured and built it is not - necessary to perform a top-level make to rebuild changes made only to LLDB. - You can run make from the build/tools/lldb subdirectory as well.

-

If you wish to build with libc++ instead of libstdc++ (the default), run configure with the - --enable-libcpp flag.

-

If you wish to build a release version of LLDB, run configure with the --enable-optimized flag.

- -

Testing

-

By default, the check-lldb target builds the 64-bit variants of the test programs with the same - compiler that was used to build LLDB. It is possible to customize the architecture and compiler by appending -A and - -C options respectively to the CMake variable LLDB_TEST_ARGS. For example, to test LLDB against 32-bit binaries - built with a custom version of clang, do:

- -
> cmake -DLLDB_TEST_ARGS="-A i386 -C /path/to/custom/clang" -G Ninja -
> ninja check-lldb -
-

Note that multiple -A and -C flags can be specified to LLDB_TEST_ARGS.

-

In addition to running all the LLDB test suites with the "check-lldb" CMake target above, it is possible to - run individual LLDB tests. For example, to run the test cases defined in TestInferiorCrashing.py, run:

- -
> cd $lldb/test -
> python dotest.py --executable <path-to-lldb> -p TestInferiorCrashing.py -
-

In addition to running a test by name, it is also possible to specify a directory path to dotest.py - in order to run all the tests under that directory. For example, to run all the tests under the - 'functionalities/data-formatter' directory, run:

- -
> python dotest.py --executable <path-to-lldb> functionalities/data-formatter -
-

To dump additional information to stdout about how the test harness is driving LLDB, run - dotest.py with the -t flag. Many more options that are available. To see a list of all of them, run:

- -
> python dotest.py -h -
-

Building API reference documentation

-

LLDB exposes a C++ as well as a Python API. To build the reference documentation for these two APIs, ensure you have - the required dependencies installed, and build the lldb-python-doc and lldb-cpp-doc CMake targets.

-

The output HTML reference documentation can be found in <build-dir>/tools/lldb/docs/.

-

Additional Notes

-

LLDB has a Python scripting capability and supplies its own Python module named lldb. - If a script is run inside the command line lldb application, the Python module - is made available automatically. However, if a script is to be run by a Python interpreter - outside the command line application, the PYTHONPATH environment variable can be used - to let the Python interpreter find the lldb module. -

The correct path can be obtained by invoking the command line lldb tool with the -P flag:

- > export PYTHONPATH=`$llvm/build/Debug+Asserts/bin/lldb -P` -

If you used a different build directory or made a release build, you may need to adjust the - above to suit your needs. To test that the lldb Python module - is built correctly and is available to the default Python interpreter, run:

- > python -c 'import lldb'

-
- -
-
-
-
- - + + + + + +Building LLDB + + + +
+ The LLDB Debugger +
+ +
+
+ + + +
+

Continuous Integraton

+
+

The following LLVM buildbots build and test LLDB trunk: +

+
+ +
+

Building LLDB on Mac OS X

+
+

Building on Mac OS X is as easy as downloading the code and building the Xcode project or workspace:

+
+
+

Preliminaries

+
    +
  • XCode 4.3 or newer requires the "Command Line Tools" component (XCode->Preferences->Downloads->Components).
  • +
  • Mac OS X Lion or newer requires installing Swig.
  • +
+

Building LLDB

+
    +
  • Download the lldb sources.
  • +
  • Follow the code signing instructions in lldb/docs/code-signing.txt
  • +
  • In Xcode 3.x: lldb/lldb.xcodeproj, select the lldb-tool target, and build.
  • +
  • In Xcode 4.x: lldb/lldb.xcworkspace, select the lldb-tool scheme, and build.
  • +
+
+ +
+
+

Building LLDB on Linux and FreeBSD

+
+

This document describes the steps needed to compile LLDB on most Linux systems, and FreeBSD.

+
+
+

Preliminaries

+

LLDB relies on many of the technologies developed by the larger LLVM project. + In particular, it requires both Clang and LLVM itself in order to build. Due to + this tight integration the Getting Started guides for both of these projects + come as prerequisite reading:

+ +

Supported compilers for building LLDB on Linux include:

+
    +
  • Clang 3.2
  • +
  • GCC 4.6.2 (later versions should work as well)
  • +
+

It is recommended to use libstdc++ 4.6 (or higher) to build LLDB on Linux, but using libc++ is also known to work.

+

On FreeBSD the base system Clang and libc++ may be used to build LLDB, + or the GCC port or package.

+

In addition to any dependencies required by LLVM and Clang, LLDB needs a few + development packages that may also need to be installed depending on your + system. The current list of dependencies are:

+ +

So for example, on a Fedora system one might run:

+ > yum install swig python-devel libedit-devel +

On an Ubuntu system one might run:

+ > sudo apt-get install build-essential subversion swig python-dev libedit-dev +

On FreeBSD one might run:

+ > pkg install swig python +

If you wish to build the optional reference documentation, additional dependencies are required:

+
    +
  • Graphviz (for the 'dot' tool). +
  • doxygen (only if you wish to build the C++ API reference) +
  • epydoc (only if you wish to build the Python API reference) +
+

To install the prerequisites for building the documentation (on Ubuntu) do:

+ +
> sudo apt-get install doxygen graphviz +
> sudo pip install epydoc +
+

Building LLDB

+

We first need to checkout the source trees into the appropriate locations. Both + Clang and LLDB build as subprojects of LLVM. This means we will be checking out + the source for both Clang and LLDB into the tools subdirectory of LLVM. We + will be setting up a directory hierarchy looking something like this:

+

+

  
+                  llvm
+                  |
+                  `-- tools
+                      |
+                      +-- clang
+                      |
+                      `-- lldb
+                
+

+

For reference, we will call the root of the LLVM project tree $llvm, and the + roots of the Clang and LLDB source trees $clang and $lldb respectively.

+

Change to the directory where you want to do development work and checkout LLVM:

+ > svn co http://llvm.org/svn/llvm-project/llvm/trunk llvm + +

Now switch to LLVM’s tools subdirectory and checkout both Clang and LLDB:

+ > cd $llvm/tools +
> svn co http://llvm.org/svn/llvm-project/cfe/trunk clang +
> svn co http://llvm.org/svn/llvm-project/lldb/trunk lldb +
+ +

In general, building the LLDB trunk revision requires trunk revisions of both + LLVM and Clang. +

It is highly recommended that you build the system out of tree. Create a second + build directory and configure the LLVM project tree to your specifications as + outlined in LLVM’s Getting Started Guide. A typical build procedure + might be:

+ > cd $llvm/.. +
> mkdir build +
> cd build +
+

To build with CMake

+

Using CMake is documented on the Building LLVM with CMake + page. Building LLDB is possible using one of the following generators: +

+
    +
  • Ninja
  • +
  • Unix Makefiles
  • +
+

Using CMake + Ninja

+

Ninja is the fastest way to build LLDB! In order to use ninja, you need to have recent versions of CMake and + ninja on your system. To build using ninja: +

+ + > cmake .. -G Ninja +
> ninja lldb +
> ninja check-lldb +
+

Using CMake + Unix Makefiles

+

If you do not have Ninja, you can still use CMake to generate Unix Makefiles that build LLDB:

+ + > cmake .. +
> make +
> make check-lldb +
+

To build with autoconf

+

If you do not have CMake, it is still possible to build LLDB using the autoconf build system. If you are using + Clang or GCC 4.7+, run:

+ + > $llvm/configure --enable-cxx11 +
> make
+

Or, if you are using a version of GCC that does not support the -std=c++11 option:

+ + > $llvm/configure +
> make CXXFLAGS=-std=c++0x
+

If you are building with a GCC that isn't the default gcc/g++, like gcc-4.7/g++-4.7

+ + > $llvm/configure --enable-cxx11 CC=gcc-4.7 CXX=g++-4.7 +
> make CC=gcc-4.7 CXX=g++-4.7
+

If you are running in a system that doesn't have a lot of RAM (less than 4GB), you might want to disable + debug symbols by specifying DEBUG_SYMBOLS=0 when running make. You will know if you need to enable this + because you will fail to link clang (the linker will get a SIGKILL and exit with status 9).

+ + > make DEBUG_SYMBOLS=0 +

To run the LLDB test suite, run:

+ +
> make -C tools/lldb/test
+

Note that once both LLVM and Clang have been configured and built it is not + necessary to perform a top-level make to rebuild changes made only to LLDB. + You can run make from the build/tools/lldb subdirectory as well.

+

If you wish to build with libc++ instead of libstdc++ (the default), run configure with the + --enable-libcpp flag.

+

If you wish to build a release version of LLDB, run configure with the --enable-optimized flag.

+ +

Testing

+

By default, the check-lldb target builds the 64-bit variants of the test programs with the same + compiler that was used to build LLDB. It is possible to customize the architecture and compiler by appending -A and + -C options respectively to the CMake variable LLDB_TEST_ARGS. For example, to test LLDB against 32-bit binaries + built with a custom version of clang, do:

+ +
> cmake -DLLDB_TEST_ARGS="-A i386 -C /path/to/custom/clang" -G Ninja +
> ninja check-lldb +
+

Note that multiple -A and -C flags can be specified to LLDB_TEST_ARGS.

+

In addition to running all the LLDB test suites with the "check-lldb" CMake target above, it is possible to + run individual LLDB tests. For example, to run the test cases defined in TestInferiorCrashing.py, run:

+ +
> cd $lldb/test +
> python dotest.py --executable <path-to-lldb> -p TestInferiorCrashing.py +
+

In addition to running a test by name, it is also possible to specify a directory path to dotest.py + in order to run all the tests under that directory. For example, to run all the tests under the + 'functionalities/data-formatter' directory, run:

+ +
> python dotest.py --executable <path-to-lldb> functionalities/data-formatter +
+

To dump additional information to stdout about how the test harness is driving LLDB, run + dotest.py with the -t flag. Many more options that are available. To see a list of all of them, run:

+ +
> python dotest.py -h +
+

Building API reference documentation

+

LLDB exposes a C++ as well as a Python API. To build the reference documentation for these two APIs, ensure you have + the required dependencies installed, and build the lldb-python-doc and lldb-cpp-doc CMake targets.

+

The output HTML reference documentation can be found in <build-dir>/tools/lldb/docs/.

+

Additional Notes

+

LLDB has a Python scripting capability and supplies its own Python module named lldb. + If a script is run inside the command line lldb application, the Python module + is made available automatically. However, if a script is to be run by a Python interpreter + outside the command line application, the PYTHONPATH environment variable can be used + to let the Python interpreter find the lldb module. +

The correct path can be obtained by invoking the command line lldb tool with the -P flag:

+ > export PYTHONPATH=`$llvm/build/Debug+Asserts/bin/lldb -P` +

If you used a different build directory or made a release build, you may need to adjust the + above to suit your needs. To test that the lldb Python module + is built correctly and is available to the default Python interpreter, run:

+ > python -c 'import lldb'

+
+ +
+
+
+
+ + diff --git a/lldb/www/customization.html b/lldb/www/customization.html index b61c716dd21d..52fac04a0f79 100755 --- a/lldb/www/customization.html +++ b/lldb/www/customization.html @@ -1,33 +1,33 @@ - - - - - -LLDB Customization - - - -
- The LLDB Debugger -
- -
-
- - -
-
-

Customization

-
-

There is an examples/customization directory under LLDB top of tree, - where you can find examples of customizations for interacting with the - lldb interpreter.

-

We welcome you to submit new and interesting examples of customizations. -

-
- -
-
-
- - + + + + + +LLDB Customization + + + +
+ The LLDB Debugger +
+ +
+
+ + +
+
+

Customization

+
+

There is an examples/customization directory under LLDB top of tree, + where you can find examples of customizations for interacting with the + lldb interpreter.

+

We welcome you to submit new and interesting examples of customizations. +

+
+ +
+
+
+ + diff --git a/lldb/www/docs.html b/lldb/www/docs.html index 4edcab17382c..5b69ded57ed1 100755 --- a/lldb/www/docs.html +++ b/lldb/www/docs.html @@ -1,34 +1,34 @@ - - - - - -LLDB Documentation - - - -
- The LLDB Debugger -
- -
-
- - - -
-
-

Documentation

-
-

LLDB is partially documented with header documentation that can be - parsed and viewed with doxygen.

-

The C++ reference documentation is available here.

-

The Python reference documentation is available here.

-
- -
-
-
-
- - + + + + + +LLDB Documentation + + + +
+ The LLDB Debugger +
+ +
+
+ + + +
+
+

Documentation

+
+

LLDB is partially documented with header documentation that can be + parsed and viewed with doxygen.

+

The C++ reference documentation is available here.

+

The Python reference documentation is available here.

+
+ +
+
+
+
+ + diff --git a/lldb/www/download.html b/lldb/www/download.html index e492e0744586..6fded58f1603 100755 --- a/lldb/www/download.html +++ b/lldb/www/download.html @@ -1,51 +1,51 @@ - - - - - -Downloading LLDB - - - -
- The LLDB Debugger -
- -
-
- - - -
-
-

Latest LLDB

-
-

Nightly builds of LLDB are packaged and tested from trunk:

- -
- -
-
-

LLDB releases

-
-

Debian packages are available for LLDB 3.2 and later.

- +
  • LLDB 3.3 (unstable)
  • +
  • LLDB 3.2 (unstable)
  • + +
    + +
    +
    +
    +
    + diff --git a/lldb/www/faq.html b/lldb/www/faq.html index f1de69ef89af..91a4498d3dce 100755 --- a/lldb/www/faq.html +++ b/lldb/www/faq.html @@ -1,30 +1,30 @@ - - - - - -LLDB FAQ - - - -
    - The LLDB Debugger -
    - -
    -
    - - -
    -
    -

    LLDB FAQ

    -
    -

    Q: What targets does LLDB currently support?

    -

    Mac OS X native debugging for i386 and x86_64 targets.

    -
    - -
    -
    -
    - + + + + + +LLDB FAQ + + + +
    + The LLDB Debugger +
    + +
    +
    + + +
    +
    +

    LLDB FAQ

    +
    +

    Q: What targets does LLDB currently support?

    +

    Mac OS X native debugging for i386 and x86_64 targets.

    +
    + +
    +
    +
    + \ No newline at end of file diff --git a/lldb/www/features.html b/lldb/www/features.html index 7beb8f11743c..92431a3d2e24 100755 --- a/lldb/www/features.html +++ b/lldb/www/features.html @@ -1,60 +1,60 @@ - - - - - -LLDB Features - - - -
    - The LLDB Debugger -
    - -
    -
    - - -
    -
    -

    Features

    -
    -

    LLDB supports a broad variety of basic debugging features such as - reading DWARF, supporting step, next, finish, backtraces, etc. Some - more interested bits are:

    - -
      -
    • Plug-in architecture for portability and extensibility:
    • -
        -
      • Object file parsers for executable file formats. Support currently - includes Mach-O (32 and 64-bit) & ELF (32-bit).
      • -
      • Object container parsers to extract object files contained within a file. - Support currently includes universal Mach-O files & BSD Archives. -
      • -
      • Debug symbol file parsers to incrementally extract debug information from - object files. Support currently includes DWARF & Mach-O symbol - tables.
      • -
      • Symbol vendor plug-ins collect data from a variety of different sources - for an executable object.
      • -
      • Disassembly plug-ins for each architecture. Support currently includes - an LLVM disassembler for i386, x86-64 - , & ARM/Thumb.
      • -
      • Debugger plug-ins implement the host and target specific functions - required to debug.
      • -
      -
    • SWIG-generated script bridging allows Python to access and control the - public API of the debugger library.
    • -
    • A remote protocol server, debugserver, implements Mac OS X debugging on - i386 and x86-64.
    • -
    • A command line debugger - the lldb executable itself.
    • -
    • A framework API to the library.
    • -
    -
    - -
    - -
    -
    -
    - + + + + + +LLDB Features + + + +
    + The LLDB Debugger +
    + +
    +
    + + +
    +
    +

    Features

    +
    +

    LLDB supports a broad variety of basic debugging features such as + reading DWARF, supporting step, next, finish, backtraces, etc. Some + more interested bits are:

    + +
      +
    • Plug-in architecture for portability and extensibility:
    • +
        +
      • Object file parsers for executable file formats. Support currently + includes Mach-O (32 and 64-bit) & ELF (32-bit).
      • +
      • Object container parsers to extract object files contained within a file. + Support currently includes universal Mach-O files & BSD Archives. +
      • +
      • Debug symbol file parsers to incrementally extract debug information from + object files. Support currently includes DWARF & Mach-O symbol + tables.
      • +
      • Symbol vendor plug-ins collect data from a variety of different sources + for an executable object.
      • +
      • Disassembly plug-ins for each architecture. Support currently includes + an LLVM disassembler for i386, x86-64 + , & ARM/Thumb.
      • +
      • Debugger plug-ins implement the host and target specific functions + required to debug.
      • +
      +
    • SWIG-generated script bridging allows Python to access and control the + public API of the debugger library.
    • +
    • A remote protocol server, debugserver, implements Mac OS X debugging on + i386 and x86-64.
    • +
    • A command line debugger - the lldb executable itself.
    • +
    • A framework API to the library.
    • +
    +
    + +
    + +
    +
    +
    + \ No newline at end of file diff --git a/lldb/www/formats.html b/lldb/www/formats.html index 364106f7bfcb..9e994cb5cdb5 100755 --- a/lldb/www/formats.html +++ b/lldb/www/formats.html @@ -1,279 +1,279 @@ - - - - - -LLDB Stack and Frame Formats - - - -
    - The LLDB Debugger -
    - -
    -
    - - -
    -
    -

    Stack Frame and Thread Format

    -
    -

    LLDB has a facility to allow users to define the - format of the information that generates the descriptions - for threads and stack frames. Typically when your program stops - at a breakpoint you will get a line that describes why - your thread stopped:

    - -

    * thread #1: tid = 0x2e03, 0x0000000100000e85 a.out`main + 4, stop reason = breakpoint 1.1

    - -

    Stack backtraces frames also have a similar information line:

    - -

    (lldb) thread backtrace -
    thread #1: tid = 0x2e03, stop reason = breakpoint 1.1 -
      frame #0: 0x0000000100000e85 a.out`main + 4 at test.c:19 -
      frame #1: 0x0000000100000e40 a.out`start + 52 -

    - -

    The two format strings can currently be set using the settings set command:

    -

    (lldb) settings set frame-format STRING -
    (lldb) settings set thread-format STRING -

    - -
    - -
    - -
    -

    Format Strings

    -
    - -

    So what is the format of the format strings? Format strings can - contain plain text, control characters and variables that have access - to the current program state.

    - -

    Normal characters are any text that doesn't contain a '{', '}', '$', - or '\' character.

    - -

    Variable names are found in between a "${" prefix, and - end with a "}" suffix. In other words, a variable looks like - "${frame.pc}".

    - -
    - -
    - -
    -

    Variables

    -
    - -

    A complete list of currently supported format string variables is listed below:

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Variable NameDescription
    file.basenameThe current compile unit file basename for the current frame.
    file.fullpathThe current compile unit file fullpath for the current frame.
    frame.indexThe frame index (0, 1, 2, 3...)
    frame.pcThe generic frame register for the program counter.
    frame.spThe generic frame register for the stack pointer.
    frame.fpThe generic frame register for the frame pointer.
    frame.flagsThe generic frame register for the flags register.
    frame.reg.NAMEAccess to any platform specific register by name (replace NAME with the name of the desired register).
    function.nameThe name of the current function or symbol.
    function.name-with-argsThe name of the current function with arguments and values or the symbol name.
    function.pc-offsetThe program counter offset within the current function or symbol
    line.file.basenameThe line table entry basename to the file for the current line entry in the current frame.
    line.file.fullpathThe line table entry fullpath to the file for the current line entry in the current frame.
    line.numberThe line table entry line number for the current line entry in the current frame.
    line.start-addrThe line table entry start address for the current line entry in the current frame.
    line.end-addrThe line table entry end address for the current line entry in the current frame.
    module.file.basenameThe basename of the current module (shared library or executable)
    module.file.fullpathThe basename of the current module (shared library or executable)
    process.file.basenameThe basename of the file for the process
    process.file.fullpathThe fullname of the file for the process
    process.idThe process ID native the the system on which the inferior runs.
    process.nameThe name of the process at runtime
    thread.idThe thread identifier for the current thread
    thread.indexThe unique one based thread index ID which is guaranteed to be unique as threads come and go.
    thread.nameThe name of the thread if the target OS supports naming threads
    thread.queueThe queue name of the thread if the target OS supports dispatch queues
    thread.stop-reasonA textual reason each thread stopped
    thread.return-valueThe return value of the latest step operation (currently only for step-out.)
    target.archThe architecture of the current target
    target.script:python_funcUse a Python function to generate a piece of textual output
    process.script:python_funcUse a Python function to generate a piece of textual output
    thread.script:python_funcUse a Python function to generate a piece of textual output
    frame.script:python_funcUse a Python function to generate a piece of textual output
    - -
    - -
    - -
    -

    Control Characters

    -
    - -

    Control characters include '{', - '}', and '\'.

    - -

    The '{' and '}' are used for scoping blocks, and the '\' character - allows you to desensitize control characters and also emit non-printable - characters. - -

    - -
    - -
    -

    Desensitizing Characters in the format string

    -
    -

    The backslash control character allows your to enter the typical - "\a", "\b", "\f", "\n", - "\r", "\t", "\v", "\\", characters - and along with the standard octal representation "\0123" - and hex "\xAB" characters. This allows you to enter - escape characters into your format strings and will - allow colorized output for terminals that support color. - -

    - -
    - -
    -

    Scoping

    -
    -

    Many times the information that you might have in your prompt might not be - available and you won't want it to print out if it isn't valid. To take care - of this you can enclose everything that must resolve into a scope. A scope - is starts with '{' and ends with - '}'. For example in order to only display - the current frame line table entry basename and line number when the information - is available for the current frame: - -

    "{ at {$line.file.basename}:${line.number}}"

    - -

    Broken down this is: -

      -
    • The start the scope

      "{"

    • -
    • format whose content will only be displayed if all information is available: -

      "at {$line.file.basename}:${line.number}"

    • -
    • end the scope:

      "}"

    • -
    - -
    - -
    - -
    -

    Making the Frame Format

    -
    -

    The information that we see when stopped in a frame: - -

    frame #0: 0x0000000100000e85 a.out`main + 4 at test.c:19

    - -

    can be displayed with the following format:

    - -

    "frame #${frame.index}: ${frame.pc}{ ${module.file.basename}`${function.name}{${function.pc-offset}}}{ at ${line.file.basename}:${line.number}}\n"

    - -

    This breaks down to: - -

      -
    • Always print the frame index and frame PC: - -

      "frame #${frame.index}: ${frame.pc}"

      - -
    • only print the module followed by a tick if there is a valid - module for the current frame: - -

      "{ ${module.file.basename}`}"

      - -
    • print the function name with optional offset:

      -

      "{${function.name}{${function.pc-offset}}}"

      - -
    • print the line info if it is available:

      - -

      "{ at ${line.file.basename}:${line.number}}"

      - -
    • then finish off with a newline:

      - -

      "\n"

      -
    - -
    - -
    - -
    -

    Making Your Own Formats

    -
    - -

    When modifying your own format strings, it is useful - to start with the default values for the frame and - thread format strings. These can be accessed with the - "settings show" command: - -

    (lldb) settings show thread-format -
    thread-format (string) = 'thread #${thread.index}: tid = ${thread.id}{, ${frame.pc}}{ ${module.file.basename}`${function.name}{${function.pc-offset}}}{, stop reason = ${thread.stop-reason}}{, name = ${thread.name}}{, queue = ${thread.queue}}\n' -
    (lldb) settings show frame-format -
    frame-format (string) = 'frame #${frame.index}: ${frame.pc}{ ${module.file.basename}`${function.name}{${function.pc-offset}}}{ at ${line.file.basename}:${line.number}}\n' -

    - - -

    When making thread formats, you will need surround any - of the information that comes from a stack frame with scopes ({ frame-content }) - as the thread format doesn't always want to show frame information. - When displaying the backtrace for a thread, we don't need to duplicate - the information for frame zero in the thread information: - -

    (lldb) thread backtrace -
    thread #1: tid = 0x2e03, stop reason = breakpoint 1.1 2.1 -
      frame #0: 0x0000000100000e85 a.out`main + 4 at test.c:19 -
      frame #1: 0x0000000100000e40 a.out`start + 52 -
    -

    - -

    The frame related variables are: -

      -
    • ${file.*}
    • -
    • ${frame.*}
    • -
    • ${function.*}
    • -
    • ${line.*}
    • -
    • ${module.*}
    • -
    -

    - -

    Looking at the default format for the thread, and underlining - the frame information: -

    'thread #${thread.index}: tid = ${thread.id}{, ${frame.pc}}{ ${module.file.basename}`${function.name}{${function.pc-offset}}}{, stop reason = ${thread.stop-reason}}{, name = ${thread.name}}{, queue = ${thread.queue}}\n' -

    -

    We can see that all frame information is contained in scopes so - that when the thread information is displayed in a context where - we only want to show thread information, we can do so. - -

    For both thread and frame formats, you can use ${target.script:python_func}, ${process.script:python_func} and ${thread.script:python_func} - (and of course ${frame.script:python_func} for frame formats)
    - In all cases, the signature of python_func is expected to be:
    -

    - def python_func(object,unused):
    -     ...
    -     return string
    -

    Where object is an instance of the SB class associated to the keyword you are using. - -

    e.g. Assuming your function looks like

    - def thread_printer_func (thread,unused):
    -   return "Thread %s has %d frames\n" % (thread.name, thread.num_frames)

    - - And you set it up with
    (lldb) settings set thread-format "${thread.script:thread_printer_func}"
    - you would see output like: -

    - * Thread main has 21 frames -
    - -
    - -
    -
    -
    - - + + + + + +LLDB Stack and Frame Formats + + + +
    + The LLDB Debugger +
    + +
    +
    + + +
    +
    +

    Stack Frame and Thread Format

    +
    +

    LLDB has a facility to allow users to define the + format of the information that generates the descriptions + for threads and stack frames. Typically when your program stops + at a breakpoint you will get a line that describes why + your thread stopped:

    + +

    * thread #1: tid = 0x2e03, 0x0000000100000e85 a.out`main + 4, stop reason = breakpoint 1.1

    + +

    Stack backtraces frames also have a similar information line:

    + +

    (lldb) thread backtrace +
    thread #1: tid = 0x2e03, stop reason = breakpoint 1.1 +
      frame #0: 0x0000000100000e85 a.out`main + 4 at test.c:19 +
      frame #1: 0x0000000100000e40 a.out`start + 52 +

    + +

    The two format strings can currently be set using the settings set command:

    +

    (lldb) settings set frame-format STRING +
    (lldb) settings set thread-format STRING +

    + +
    + +
    + +
    +

    Format Strings

    +
    + +

    So what is the format of the format strings? Format strings can + contain plain text, control characters and variables that have access + to the current program state.

    + +

    Normal characters are any text that doesn't contain a '{', '}', '$', + or '\' character.

    + +

    Variable names are found in between a "${" prefix, and + end with a "}" suffix. In other words, a variable looks like + "${frame.pc}".

    + +
    + +
    + +
    +

    Variables

    +
    + +

    A complete list of currently supported format string variables is listed below:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Variable NameDescription
    file.basenameThe current compile unit file basename for the current frame.
    file.fullpathThe current compile unit file fullpath for the current frame.
    frame.indexThe frame index (0, 1, 2, 3...)
    frame.pcThe generic frame register for the program counter.
    frame.spThe generic frame register for the stack pointer.
    frame.fpThe generic frame register for the frame pointer.
    frame.flagsThe generic frame register for the flags register.
    frame.reg.NAMEAccess to any platform specific register by name (replace NAME with the name of the desired register).
    function.nameThe name of the current function or symbol.
    function.name-with-argsThe name of the current function with arguments and values or the symbol name.
    function.pc-offsetThe program counter offset within the current function or symbol
    line.file.basenameThe line table entry basename to the file for the current line entry in the current frame.
    line.file.fullpathThe line table entry fullpath to the file for the current line entry in the current frame.
    line.numberThe line table entry line number for the current line entry in the current frame.
    line.start-addrThe line table entry start address for the current line entry in the current frame.
    line.end-addrThe line table entry end address for the current line entry in the current frame.
    module.file.basenameThe basename of the current module (shared library or executable)
    module.file.fullpathThe basename of the current module (shared library or executable)
    process.file.basenameThe basename of the file for the process
    process.file.fullpathThe fullname of the file for the process
    process.idThe process ID native the the system on which the inferior runs.
    process.nameThe name of the process at runtime
    thread.idThe thread identifier for the current thread
    thread.indexThe unique one based thread index ID which is guaranteed to be unique as threads come and go.
    thread.nameThe name of the thread if the target OS supports naming threads
    thread.queueThe queue name of the thread if the target OS supports dispatch queues
    thread.stop-reasonA textual reason each thread stopped
    thread.return-valueThe return value of the latest step operation (currently only for step-out.)
    target.archThe architecture of the current target
    target.script:python_funcUse a Python function to generate a piece of textual output
    process.script:python_funcUse a Python function to generate a piece of textual output
    thread.script:python_funcUse a Python function to generate a piece of textual output
    frame.script:python_funcUse a Python function to generate a piece of textual output
    + +
    + +
    + +
    +

    Control Characters

    +
    + +

    Control characters include '{', + '}', and '\'.

    + +

    The '{' and '}' are used for scoping blocks, and the '\' character + allows you to desensitize control characters and also emit non-printable + characters. + +

    + +
    + +
    +

    Desensitizing Characters in the format string

    +
    +

    The backslash control character allows your to enter the typical + "\a", "\b", "\f", "\n", + "\r", "\t", "\v", "\\", characters + and along with the standard octal representation "\0123" + and hex "\xAB" characters. This allows you to enter + escape characters into your format strings and will + allow colorized output for terminals that support color. + +

    + +
    + +
    +

    Scoping

    +
    +

    Many times the information that you might have in your prompt might not be + available and you won't want it to print out if it isn't valid. To take care + of this you can enclose everything that must resolve into a scope. A scope + is starts with '{' and ends with + '}'. For example in order to only display + the current frame line table entry basename and line number when the information + is available for the current frame: + +

    "{ at {$line.file.basename}:${line.number}}"

    + +

    Broken down this is: +

      +
    • The start the scope

      "{"

    • +
    • format whose content will only be displayed if all information is available: +

      "at {$line.file.basename}:${line.number}"

    • +
    • end the scope:

      "}"

    • +
    + +
    + +
    + +
    +

    Making the Frame Format

    +
    +

    The information that we see when stopped in a frame: + +

    frame #0: 0x0000000100000e85 a.out`main + 4 at test.c:19

    + +

    can be displayed with the following format:

    + +

    "frame #${frame.index}: ${frame.pc}{ ${module.file.basename}`${function.name}{${function.pc-offset}}}{ at ${line.file.basename}:${line.number}}\n"

    + +

    This breaks down to: + +

      +
    • Always print the frame index and frame PC: + +

      "frame #${frame.index}: ${frame.pc}"

      + +
    • only print the module followed by a tick if there is a valid + module for the current frame: + +

      "{ ${module.file.basename}`}"

      + +
    • print the function name with optional offset:

      +

      "{${function.name}{${function.pc-offset}}}"

      + +
    • print the line info if it is available:

      + +

      "{ at ${line.file.basename}:${line.number}}"

      + +
    • then finish off with a newline:

      + +

      "\n"

      +
    + +
    + +
    + +
    +

    Making Your Own Formats

    +
    + +

    When modifying your own format strings, it is useful + to start with the default values for the frame and + thread format strings. These can be accessed with the + "settings show" command: + +

    (lldb) settings show thread-format +
    thread-format (string) = 'thread #${thread.index}: tid = ${thread.id}{, ${frame.pc}}{ ${module.file.basename}`${function.name}{${function.pc-offset}}}{, stop reason = ${thread.stop-reason}}{, name = ${thread.name}}{, queue = ${thread.queue}}\n' +
    (lldb) settings show frame-format +
    frame-format (string) = 'frame #${frame.index}: ${frame.pc}{ ${module.file.basename}`${function.name}{${function.pc-offset}}}{ at ${line.file.basename}:${line.number}}\n' +

    + + +

    When making thread formats, you will need surround any + of the information that comes from a stack frame with scopes ({ frame-content }) + as the thread format doesn't always want to show frame information. + When displaying the backtrace for a thread, we don't need to duplicate + the information for frame zero in the thread information: + +

    (lldb) thread backtrace +
    thread #1: tid = 0x2e03, stop reason = breakpoint 1.1 2.1 +
      frame #0: 0x0000000100000e85 a.out`main + 4 at test.c:19 +
      frame #1: 0x0000000100000e40 a.out`start + 52 +
    +

    + +

    The frame related variables are: +

      +
    • ${file.*}
    • +
    • ${frame.*}
    • +
    • ${function.*}
    • +
    • ${line.*}
    • +
    • ${module.*}
    • +
    +

    + +

    Looking at the default format for the thread, and underlining + the frame information: +

    'thread #${thread.index}: tid = ${thread.id}{, ${frame.pc}}{ ${module.file.basename}`${function.name}{${function.pc-offset}}}{, stop reason = ${thread.stop-reason}}{, name = ${thread.name}}{, queue = ${thread.queue}}\n' +

    +

    We can see that all frame information is contained in scopes so + that when the thread information is displayed in a context where + we only want to show thread information, we can do so. + +

    For both thread and frame formats, you can use ${target.script:python_func}, ${process.script:python_func} and ${thread.script:python_func} + (and of course ${frame.script:python_func} for frame formats)
    + In all cases, the signature of python_func is expected to be:
    +

    + def python_func(object,unused):
    +     ...
    +     return string
    +

    Where object is an instance of the SB class associated to the keyword you are using. + +

    e.g. Assuming your function looks like

    + def thread_printer_func (thread,unused):
    +   return "Thread %s has %d frames\n" % (thread.name, thread.num_frames)

    + + And you set it up with
    (lldb) settings set thread-format "${thread.script:thread_printer_func}"
    + you would see output like: +

    + * Thread main has 21 frames +
    + +
    + +
    +
    +
    + + diff --git a/lldb/www/goals.html b/lldb/www/goals.html index 3bbb75904ecf..04d095cab807 100755 --- a/lldb/www/goals.html +++ b/lldb/www/goals.html @@ -1,63 +1,63 @@ - - - - - -LLDB Goals - - - -
    - The LLDB Debugger -
    - -
    -
    - -
    -
    -

    Goals

    -
    - -

    The current state of the art in open source debuggers are that - they work in the common cases for C applications, but don't - handle many "hard cases" properly. For example, C++ expression - parsing, handling overloading, templates, multi-threading, and - other non-trivial scenarios all work in some base cases, but - don't work reliably.

    - -

    The goal of LLDB is to provide an amazing debugging experience that "just - works". We aim to solve these long-standing problems where debuggers get - confused, so that you can think about debugging your problem, not - about deficiencies in the debugger.

    - -

    With a long view, there is no good reason for a debugger to - reinvent its own C/C++ parser, type system, know all the - target calling convention details, implement its own disassembler, - etc. By using the existing libraries vended by the LLVM - project, we believe that many of these problems will be defined - away, and the debugger can focus on important issues like - process control, efficient symbol reading and indexing, thread - management, and other debugger-specific problems.

    - -

    Some more specific goals include:

    - -
      -
    • Build libraries for inclusion in IDEs, command line tools, and - other analysis tools
    • -
    • High performance and efficient memory use
    • -
    • Extensible: Python scriptable and use a plug-in architecture
    • -
    • Reuse existing compiler technology where it makes sense
    • -
    • Excellent multi-threaded debugging support
    • -
    • Great support for C, Objective-C and C++
    • -
    • Retargetable to support multiple platforms
    • -
    • Provide a base for debugger research and other innovation
    • -
    -
    - -
    -
    -
    -
    - - + + + + + +LLDB Goals + + + +
    + The LLDB Debugger +
    + +
    +
    + +
    +
    +

    Goals

    +
    + +

    The current state of the art in open source debuggers are that + they work in the common cases for C applications, but don't + handle many "hard cases" properly. For example, C++ expression + parsing, handling overloading, templates, multi-threading, and + other non-trivial scenarios all work in some base cases, but + don't work reliably.

    + +

    The goal of LLDB is to provide an amazing debugging experience that "just + works". We aim to solve these long-standing problems where debuggers get + confused, so that you can think about debugging your problem, not + about deficiencies in the debugger.

    + +

    With a long view, there is no good reason for a debugger to + reinvent its own C/C++ parser, type system, know all the + target calling convention details, implement its own disassembler, + etc. By using the existing libraries vended by the LLVM + project, we believe that many of these problems will be defined + away, and the debugger can focus on important issues like + process control, efficient symbol reading and indexing, thread + management, and other debugger-specific problems.

    + +

    Some more specific goals include:

    + +
      +
    • Build libraries for inclusion in IDEs, command line tools, and + other analysis tools
    • +
    • High performance and efficient memory use
    • +
    • Extensible: Python scriptable and use a plug-in architecture
    • +
    • Reuse existing compiler technology where it makes sense
    • +
    • Excellent multi-threaded debugging support
    • +
    • Great support for C, Objective-C and C++
    • +
    • Retargetable to support multiple platforms
    • +
    • Provide a base for debugger research and other innovation
    • +
    +
    + +
    +
    +
    +
    + + diff --git a/lldb/www/index.html b/lldb/www/index.html index 85d64e6da6fc..3b77b95ece52 100755 --- a/lldb/www/index.html +++ b/lldb/www/index.html @@ -1,128 +1,128 @@ - - - - - -LLDB Homepage - - - -
    - The LLDB Debugger -
    - -
    -
    - - - -
    -
    -

    What is LLDB?

    -
    -

    LLDB is a next generation, high-performance debugger. It is built as a set - of reusable components which highly leverage existing libraries in the - larger LLVM Project, such as the Clang expression parser and LLVM - disassembler.

    -

    LLDB is the default debugger in Xcode on Mac OS X and supports - debugging C, Objective-C and C++ on the desktop and iOS devices and simulator.

    - -

    All of the code in the LLDB project is available under the standard - LLVM - License, an open source "BSD-style" license.

    -
    - -
    - -
    -

    Why a new debugger?

    -
    -

    In order to achieve our goals we decided to start with a fresh architecture - that would support modern multi-threaded programs, handle debugging symbols - in an efficient manner, use compiler based code knowledge and have plug-in - support for functionality and extensions. Additionally we want the debugger - capabilities to be available to other analysis tools, be they scripts or - compiled programs, without requiring them to be GPL.

    -
    - -
    - -
    -

    Compiler Integration Benefits

    -
    -

    LLDB currently converts debug information into clang types so that - it can leverage the clang compiler infrastructure. - This allows LLDB to support the latest C, C++, Objective C and Objective C++ - language features and runtimes in expressions without having to reimplement any - of this functionality. It also leverages the compiler to take care of all ABI - details when making functions calls for expressions, when disassembling - instructions and extracting instruciton details, and much more. -

    The major benefits include:

    -
      -
    • Up to date language support for C, C++, Objective C
    • -
    • Multi-line expressions that can declare local variables and types
    • -
    • Utilitize the JIT for expressions when supported
    • -
    • Evaluate expression Intermediate Representation (IR) when JIT can't be used
    • -
    -
    -
    - -
    -

    Reusability

    -
    -

    The LLDB debugger APIs are exposed as a C++ object oriented interface in a shared library. - The lldb command line tool links to, and uses this public API. On Mac OS X the shared library - is exposed as a framework named LLDB.framework, and unix systems expose it as lldb.so. - The entire API is also then exposed through Python script bindings which allow the API to be used - within the LLDB embedded script interpreter, and also in any python script that loads the lldb.py - module in standard python script files. See the Python Reference page for more details on how - and where Python can be used with the LLDB API.

    -

    Sharing the LLDB API allows LLDB to not only be used for debugging, but also for symbolication, - disassembly, object and symbol file introspection, and much more. -

    -
    - -
    -

    Platform Support

    -
    - -

    LLDB is known to work on the following platforms, but ports to new - platforms are welcome:

    -
      -
    • Mac OS X desktop user space debugging for i386 and x86-64
    • -
    • iOS simulator debugging on i386
    • -
    • iOS device debugging on ARM
    • -
    • Linux local user-space debugging for i386 and x86-64
    • -
    • FreeBSD local user-space debugging for i386 and x86-64
    • -
    -
    - -
    - - -
    -

    Get it and get involved!

    -
    - -

    To check out the code, use:

    - -
      -
    • svn co http://llvm.org/svn/llvm-project/lldb/trunk lldb
    • -
    - -

    Note that LLDB generally builds from top-of-trunk on Mac OS X with - Xcode and on Linux (with clang and libstdc++/libc++).

    - -

    Discussions about LLDB should go to the lldb-dev mailing - list. Commit messages for the lldb SVN module are automatically sent to the - lldb-commits - mailing list, and this is also the preferred mailing list for patch - submissions.

    -
    - -
    -
    -
    -
    - - + + + + + +LLDB Homepage + + + +
    + The LLDB Debugger +
    + +
    +
    + + + +
    +
    +

    What is LLDB?

    +
    +

    LLDB is a next generation, high-performance debugger. It is built as a set + of reusable components which highly leverage existing libraries in the + larger LLVM Project, such as the Clang expression parser and LLVM + disassembler.

    +

    LLDB is the default debugger in Xcode on Mac OS X and supports + debugging C, Objective-C and C++ on the desktop and iOS devices and simulator.

    + +

    All of the code in the LLDB project is available under the standard + LLVM + License, an open source "BSD-style" license.

    +
    + +
    + +
    +

    Why a new debugger?

    +
    +

    In order to achieve our goals we decided to start with a fresh architecture + that would support modern multi-threaded programs, handle debugging symbols + in an efficient manner, use compiler based code knowledge and have plug-in + support for functionality and extensions. Additionally we want the debugger + capabilities to be available to other analysis tools, be they scripts or + compiled programs, without requiring them to be GPL.

    +
    + +
    + +
    +

    Compiler Integration Benefits

    +
    +

    LLDB currently converts debug information into clang types so that + it can leverage the clang compiler infrastructure. + This allows LLDB to support the latest C, C++, Objective C and Objective C++ + language features and runtimes in expressions without having to reimplement any + of this functionality. It also leverages the compiler to take care of all ABI + details when making functions calls for expressions, when disassembling + instructions and extracting instruciton details, and much more. +

    The major benefits include:

    +
      +
    • Up to date language support for C, C++, Objective C
    • +
    • Multi-line expressions that can declare local variables and types
    • +
    • Utilitize the JIT for expressions when supported
    • +
    • Evaluate expression Intermediate Representation (IR) when JIT can't be used
    • +
    +
    +
    + +
    +

    Reusability

    +
    +

    The LLDB debugger APIs are exposed as a C++ object oriented interface in a shared library. + The lldb command line tool links to, and uses this public API. On Mac OS X the shared library + is exposed as a framework named LLDB.framework, and unix systems expose it as lldb.so. + The entire API is also then exposed through Python script bindings which allow the API to be used + within the LLDB embedded script interpreter, and also in any python script that loads the lldb.py + module in standard python script files. See the Python Reference page for more details on how + and where Python can be used with the LLDB API.

    +

    Sharing the LLDB API allows LLDB to not only be used for debugging, but also for symbolication, + disassembly, object and symbol file introspection, and much more. +

    +
    + +
    +

    Platform Support

    +
    + +

    LLDB is known to work on the following platforms, but ports to new + platforms are welcome:

    +
      +
    • Mac OS X desktop user space debugging for i386 and x86-64
    • +
    • iOS simulator debugging on i386
    • +
    • iOS device debugging on ARM
    • +
    • Linux local user-space debugging for i386 and x86-64
    • +
    • FreeBSD local user-space debugging for i386 and x86-64
    • +
    +
    + +
    + + +
    +

    Get it and get involved!

    +
    + +

    To check out the code, use:

    + +
      +
    • svn co http://llvm.org/svn/llvm-project/lldb/trunk lldb
    • +
    + +

    Note that LLDB generally builds from top-of-trunk on Mac OS X with + Xcode and on Linux (with clang and libstdc++/libc++).

    + +

    Discussions about LLDB should go to the lldb-dev mailing + list. Commit messages for the lldb SVN module are automatically sent to the + lldb-commits + mailing list, and this is also the preferred mailing list for patch + submissions.

    +
    + +
    +
    +
    +
    + + diff --git a/lldb/www/python-reference.html b/lldb/www/python-reference.html index cb06f9246657..dfc2165ee5c2 100755 --- a/lldb/www/python-reference.html +++ b/lldb/www/python-reference.html @@ -1,598 +1,598 @@ - - - - - -LLDB Python Reference - - - -
    - LLDB Python Reference -
    - -
    -
    - -
    -
    -

    Introduction

    -
    - -

    The entire LLDB API is available as Python functions through a script bridging interface. - This means the LLDB API's can be used directly from python either interactively or to build python apps that - provide debugger features.

    -

    Additionally, Python can be used as a programmatic interface within the - lldb command interpreter (we refer to this for brevity as the embedded interpreter). Of course, - in this context it has full access to the LLDB API - with some additional conveniences we will - call out in the FAQ.

    - -
    - -
    -

    Documentation

    -
    - -

    The LLDB API is contained in a python module named lldb. A useful resource when writing Python extensions is the lldb Python classes reference guide.

    -

    The documentation is also accessible in an interactive debugger session with the following command:

    -
    (lldb) script help(lldb)
    -    Help on package lldb:
    -
    -    NAME
    -        lldb - The lldb module contains the public APIs for Python binding.
    -
    -    FILE
    -        /System/Library/PrivateFrameworks/LLDB.framework/Versions/A/Resources/Python/lldb/__init__.py
    -
    -    DESCRIPTION
    -...
    -
    -

    You can also get help using a module class name. The full API that is exposed for that class will be displayed in a man page style window. Below we want to get help on the lldb.SBFrame class:

    -
    (lldb) script help(lldb.SBFrame)
    -    Help on class SBFrame in module lldb:
    -
    -    class SBFrame(__builtin__.object)
    -     |  Represents one of the stack frames associated with a thread.
    -     |  SBThread contains SBFrame(s). For example (from test/lldbutil.py),
    -     |  
    -     |  def print_stacktrace(thread, string_buffer = False):
    -     |      '''Prints a simple stack trace of this thread.'''
    -     |  
    -...
    -
    -

    Or you can get help using any python object, here we use the lldb.process object which is a global variable in the lldb module which represents the currently selected process:

    -
    (lldb) script help(lldb.process)
    -    Help on SBProcess in module lldb object:
    -
    -    class SBProcess(__builtin__.object)
    -     |  Represents the process associated with the target program.
    -     |  
    -     |  SBProcess supports thread iteration. For example (from test/lldbutil.py),
    -     |  
    -     |  # ==================================================
    -     |  # Utility functions related to Threads and Processes
    -     |  # ==================================================
    -     |  
    -...
    -
    - -
    - - -
    -

    Embedded Python Interpreter

    -
    - -

    The embedded python interpreter can be accessed in a variety of ways from within LLDB. The - easiest way is to use the lldb command script with no arguments at the lldb command prompt:

    -
    (lldb) script
    -Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.
    ->>> 2+3
    -5
    ->>> hex(12345)
    -'0x3039'
    ->>> 
    -
    - -

    This drops you into the embedded python interpreter. When running under the script command, - lldb sets some convenience variables that give you quick access to the currently selected entities that characterize - the program and debugger state. In each case, if there is no currently selected entity of the appropriate - type, the variable's IsValid method will return false. These variables are:

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    VariableTypeDescription
    - lldb.debugger - - lldb.SBDebugger - - Contains the debugger object whose script command was invoked. - The lldb.SBDebugger object owns the command interpreter - and all the targets in your debug session. There will always be a - Debugger in the embedded interpreter. -
    - lldb.target - - lldb.SBTarget - - Contains the currently selected target - for instance the one made with the - file or selected by the target select <target-index> command. - The lldb.SBTarget manages one running process, and all the executable - and debug files for the process. -
    - lldb.process - - lldb.SBProcess - - Contains the process of the currently selected target. - The lldb.SBProcess object manages the threads and allows access to - memory for the process. -
    - lldb.thread - - lldb.SBThread - - Contains the currently selected thread. - The lldb.SBThread object manages the stack frames in that thread. - A thread is always selected in the command interpreter when a target stops. - The thread select <thread-index> command can be used to change the - currently selected thread. So as long as you have a stopped process, there will be - some selected thread. -
    - lldb.frame - - lldb.SBFrame - - Contains the currently selected stack frame. - The lldb.SBFrame object manage the stack locals and the register set for - that stack. - A stack frame is always selected in the command interpreter when a target stops. - The frame select <frame-index> command can be used to change the - currently selected frame. So as long as you have a stopped process, there will - be some selected frame. -
    - -

    While extremely convenient, these variables have a couple caveats that you should be aware of. - First of all, they hold the values - of the selected objects on entry to the embedded interpreter. They do not update as you use the LLDB - API's to change, for example, the currently selected stack frame or thread. -

    Moreover, they are only defined and meaningful while in the interactive Python interpreter. - There is no guarantee on their value in any other situation, hence you should not use them when defining - Python formatters, breakpoint scripts and commands (or any other Python extension point that LLDB provides). - As a rationale for such behavior, consider that lldb can - run in a multithreaded environment, and another thread might call the "script" command, changing the value out - from under you.

    - -

    To get started with these objects and LLDB scripting, please note that almost - all of the lldb Python objects are able to briefly describe themselves when you pass them - to the Python print function: -

    (lldb) script
    -Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.
    ->>> print lldb.debugger
    -Debugger (instance: "debugger_1", id: 1)
    ->>> print lldb.target
    -a.out
    ->>> print lldb.process
    -SBProcess: pid = 59289, state = stopped, threads = 1, executable = a.out
    ->>> print lldb.thread
    -SBThread: tid = 0x1f03
    ->>> print lldb.frame
    -frame #0: 0x0000000100000bb6 a.out main + 54 at main.c:16
    -
    - -
    - - -
    -
    -

    Running a Python script when a breakpoint gets hit

    -
    - -

    One very powerful use of the lldb Python API is to have a python script run when a breakpoint gets hit. Adding python - scripts to breakpoints provides a way to create complex breakpoint - conditions and also allows for smart logging and data gathering.

    -

    When your process hits a breakpoint to which you have attached some python code, the code is executed as the - body of a function which takes three arguments:

    -

    -

    def breakpoint_function_wrapper(frame, bp_loc, dict):
    -  # Your code goes here
    -
    -

    - - - - - - - - - - - - - - - - - - - - - -
    ArgumentTypeDescription
    - frame - - lldb.SBFrame - - The current stack frame where the breakpoint got hit. - The object will always be valid. - This frame argument might not match the currently selected stack frame found in the lldb module global variable lldb.frame. -
    - bp_loc - - lldb.SBBreakpointLocation - - The breakpoint location that just got hit. Breakpoints are represented by lldb.SBBreakpoint - objects. These breakpoint objects can have one or more locations. These locations - are represented by lldb.SBBreakpointLocation objects. -
    - dict - - dict - - The python session dictionary as a standard python dictionary object. -
    -

    Optionally, a Python breakpoint command can return a value. Returning False tells LLDB that you do not want to stop at the breakpoint. - Any other return value (including None or leaving out the return statement altogether) is akin to telling LLDB to actually stop at the breakpoint. - This can be useful in situations where a breakpoint only needs to stop the process when certain conditions are met, and you do not want to inspect the - program state manually at every stop and then continue. -

    An example will show how simple it is to write some python code and attach it to a breakpoint. - The following example will allow you to track the order in which the functions in a given shared library - are first executed during one run of your program. This is a simple method to gather an order file which - can be used to optimize function placement within a binary for execution locality.

    -

    We do this by setting a regular expression breakpoint - that will match every function in the shared library. The regular expression '.' will match - any string that has at least one character in it, so we will use that. - This will result in one lldb.SBBreakpoint object - that contains an lldb.SBBreakpointLocation object for each function. As the breakpoint gets - hit, we use a counter to track the order in which the function at this particular breakpoint location got hit. - Since our code is passed the location that was hit, we can get the name of the function from the location, - disable the location so we won't count this function again; then log some info and continue the process.

    -

    Note we also have to initialize our counter, which we do with the simple one-line version of the script - command. -

    Here is the code: - -

    (lldb) breakpoint set --func-regex=. --shlib=libfoo.dylib
    -Breakpoint created: 1: regex = '.', module = libfoo.dylib, locations = 223
    -(lldb) script counter = 0
    -(lldb) breakpoint command add --script-type python 1
    -Enter your Python command(s). Type 'DONE' to end.
    -> # Increment our counter.  Since we are in a function, this must be a global python variable
    -> global counter 
    -> counter += 1
    -> # Get the name of the function
    -> name = frame.GetFunctionName()
    -> # Print the order and the function name
    -> print '[%i] %s' % (counter, name)
    -> # Disable the current breakpoint location so it doesn't get hit again
    -> bp_loc.SetEnabled(False)
    -> # No need to stop here
    -> return False
    -> DONE
    -
    -

    The breakpoint command add command above attaches a python script to breakpoint 1. - To remove the breakpoint command: -

    (lldb) breakpoint command delete 1 -

    -
    -
    -

    Create a new LLDB command using a python function

    -
    - -

    Python functions can be used to create new LLDB command interpreter commands, which will work - like all the natively defined lldb commands. This provides a very flexible and easy way to extend LLDB to meet your - debugging requirements.

    -

    To write a python function that implements a new LDB command define the function to take four arguments as follows:

    - -
    def command_function(debugger, command, result, internal_dict):
    -          # Your code goes here
    -        
    - - Optionally, you can also provide a Python docstring, and LLDB will use it when providing help for your command, as in: -
    def command_function(debugger, command, result, internal_dict):
    -          """This command takes a lot of options and does many fancy things"""    
    -          # Your code goes here
    -        
    - -

    - - - - - - - - - - - - - - - - - - - - - - - - - - -
    ArgumentTypeDescription
    - debugger - - lldb.SBDebugger - - The current debugger object. -
    - command - - python string - - A python string containing all arguments for your command. If you need to chop up the arguments - try using the shlex module's shlex.split(command) to properly extract the - arguments. -
    - result - - lldb.SBCommandReturnObject - - A return object which encapsulates success/failure information for the command and output text - that needs to be printed as a result of the command. The plain Python "print" command also works but - text won't go in the result by default (it is useful as a temporary logging facility). -
    - internal_dict - - python dict object - - The dictionary for the current embedded script session which contains all variables - and functions. -
    -

    As a convenience, you can treat the result object as a Python file object, and say -

    print >>result, "my command does lots of cool stuff"
    - SBCommandReturnObject and SBStream - both support this file-like behavior by providing write() and flush() calls at the Python layer.

    -

    One other handy convenience when defining lldb command-line commands is the command - command script import which will import a module specified by file path - so you - don't have to change your PYTHONPATH for temporary scripts. It also has another convenience - that if your new script module has a function of the form:

    - -
    def __lldb_init_module(debugger, internal_dict):
    -    # Command Initialization code goes here
    -
    - -

    where debugger and internal_dict are as above, that function will get run when the module is loaded - allowing you to add whatever commands you want into the current debugger. Note that - this function will only be run when using the LLDB comand command script import, - it will not get run if anyone imports your module from another module. - If you want to always run code when your module is loaded from LLDB - or when loaded via an import statement in python code - you can test the lldb.debugger object, since you imported the - module at the top of the python ls.py module. This test - must be in code that isn't contained inside of any function or class, - just like the standard test for __main__ like all python modules - usally do. Sample code would look like: - -

    if __name__ == '__main__':
    -    # Create a new debugger instance in your module if your module 
    -    # can be run from the command line. When we run a script from
    -    # the command line, we won't have any debugger object in
    -    # lldb.debugger, so we can just create it if it will be needed
    -    lldb.debugger = lldb.SBDebugger.Create()
    -elif lldb.debugger:
    -    # Module is being run inside the LLDB interpreter
    -    lldb.debugger.HandleCommand('command script add -f ls.ls ls')
    -    print 'The "ls" python command has been installed and is ready for use.'
    -
    -

    Now we can create a module called ls.py in the file ~/ls.py that will implement a function that - can be used by LLDB's python command code:

    - -
    #!/usr/bin/python
    -
    -import lldb
    -import commands
    -import optparse
    -import shlex
    -
    -def ls(debugger, command, result, internal_dict):
    -    print >>result, (commands.getoutput('/bin/ls %s' % command))
    -
    -# And the initialization code to add your commands 
    -def __lldb_init_module(debugger, internal_dict):
    -    debugger.HandleCommand('command script add -f ls.ls ls')
    -    print 'The "ls" python command has been installed and is ready for use.'
    -
    -

    Now we can load the module into LLDB and use it

    -
    % lldb
    -(lldb) command script import ~/ls.py
    -The "ls" python command has been installed and is ready for use.
    -(lldb) ls -l /tmp/
    -total 365848
    --rw-r--r--@  1 someuser  wheel         6148 Jan 19 17:27 .DS_Store
    --rw-------   1 someuser  wheel         7331 Jan 19 15:37 crash.log
    -
    -

    A more interesting template has been created in the source repository that can help you to create - lldb command quickly:

    - cmdtemplate.py -

    - A commonly required facility is being able to create a command that does some token substitution, and then runs a different debugger command - (usually, it po'es the result of an expression evaluated on its argument). For instance, given the following program: -

    
    -#import <Foundation/Foundation.h>
    -NSString*
    -ModifyString(NSString* src)
    -{
    -	return [src stringByAppendingString:@"foobar"];
    -}
    -
    -int main()
    -{
    -	NSString* aString = @"Hello world";
    -	NSString* anotherString = @"Let's be friends";
    -	return 1;
    -}
    -		
    - you may want a pofoo X command, that equates po [ModifyString(X) capitalizedString]. - The following debugger interaction shows how to achieve that goal: -
    
    -(lldb) script
    -Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.
    ->>> def pofoo_funct(debugger, command, result, internal_dict):
    -...	cmd = "po [ModifyString(" + command + ") capitalizedString]"
    -...	lldb.debugger.HandleCommand(cmd)
    -... 
    ->>> ^D
    -(lldb) command script add pofoo -f pofoo_funct
    -(lldb) pofoo aString
    -$1 = 0x000000010010aa00 Hello Worldfoobar
    -(lldb) pofoo anotherString
    -$2 = 0x000000010010aba0 Let's Be Friendsfoobar
    -
    -
    -

    Using the lldb.py module in python

    -
    - -

    LLDB has all of its core code build into a shared library which gets - used by the lldb command line application. On Mac OS X this - shared library is a framework: LLDB.framework and on other - unix variants the program is a shared library: lldb.so. LLDB also - provides an lldb.py module that contains the bindings from LLDB into Python. - To use the - LLDB.framework to create your own stand-alone python programs, you will - need to tell python where to look in order to find this module. This - is done by setting the PYTHONPATH environment variable, adding - a path to the directory that contains the lldb.py python module. On - Mac OS X, this is contained inside the LLDB.framework, so you would do: - -

    For csh and tcsh:

    -

    % setenv PYTHONPATH /Developer/Library/PrivateFrameworks/LLDB.framework/Resources/Python

    -

    For sh and bash: -

    % export PYTHONPATH=/Developer/Library/PrivateFrameworks/LLDB.framework/Resources/Python

    - -

    Alternately, you can append the LLDB Python directory to the sys.path list directly in - your Python code before importing the lldb module.

    - -

    - Now your python scripts are ready to import the lldb module. Below is a - python script that will launch a program from the current working directory - called "a.out", set a breakpoint at "main", and then run and hit the breakpoint, - and print the process, thread and frame objects if the process stopped: - -

    -
    #!/usr/bin/python
    -
    -import lldb
    -import os
    -
    -def disassemble_instructions(insts):
    -    for i in insts:
    -        print i
    -
    -# Set the path to the executable to debug
    -exe = "./a.out"
    -
    -# Create a new debugger instance
    -debugger = lldb.SBDebugger.Create()
    -
    -# When we step or continue, don't return from the function until the process 
    -# stops. Otherwise we would have to handle the process events ourselves which, while doable is
    -#a little tricky.  We do this by setting the async mode to false.
    -debugger.SetAsync (False)
    -
    -# Create a target from a file and arch
    -print "Creating a target for '%s'" % exe
    -
    -target = debugger.CreateTargetWithFileAndArch (exe, lldb.LLDB_ARCH_DEFAULT)
    -
    -if target:
    -    # If the target is valid set a breakpoint at main
    -    main_bp = target.BreakpointCreateByName ("main", target.GetExecutable().GetFilename());
    -
    -    print main_bp
    -
    -    # Launch the process. Since we specified synchronous mode, we won't return
    -    # from this function until we hit the breakpoint at main
    -    process = target.LaunchSimple (None, None, os.getcwd())
    -    
    -    # Make sure the launch went ok
    -    if process:
    -        # Print some simple process info
    -        state = process.GetState ()
    -        print process
    -        if state == lldb.eStateStopped:
    -            # Get the first thread
    -            thread = process.GetThreadAtIndex (0)
    -            if thread:
    -                # Print some simple thread info
    -                print thread
    -                # Get the first frame
    -                frame = thread.GetFrameAtIndex (0)
    -                if frame:
    -                    # Print some simple frame info
    -                    print frame
    -                    function = frame.GetFunction()
    -                    # See if we have debug info (a function)
    -                    if function:
    -                        # We do have a function, print some info for the function
    -                        print function
    -                        # Now get all instructions for this function and print them
    -                        insts = function.GetInstructions(target)
    -                        disassemble_instructions (insts)
    -                    else:
    -                        # See if we have a symbol in the symbol table for where we stopped
    -                        symbol = frame.GetSymbol();
    -                        if symbol:
    -                            # We do have a symbol, print some info for the symbol
    -                            print symbol
    -
    -
    - - -
    -
    -
    - - + + + + + +LLDB Python Reference + + + +
    + LLDB Python Reference +
    + +
    +
    + +
    +
    +

    Introduction

    +
    + +

    The entire LLDB API is available as Python functions through a script bridging interface. + This means the LLDB API's can be used directly from python either interactively or to build python apps that + provide debugger features.

    +

    Additionally, Python can be used as a programmatic interface within the + lldb command interpreter (we refer to this for brevity as the embedded interpreter). Of course, + in this context it has full access to the LLDB API - with some additional conveniences we will + call out in the FAQ.

    + +
    + +
    +

    Documentation

    +
    + +

    The LLDB API is contained in a python module named lldb. A useful resource when writing Python extensions is the lldb Python classes reference guide.

    +

    The documentation is also accessible in an interactive debugger session with the following command:

    +
    (lldb) script help(lldb)
    +    Help on package lldb:
    +
    +    NAME
    +        lldb - The lldb module contains the public APIs for Python binding.
    +
    +    FILE
    +        /System/Library/PrivateFrameworks/LLDB.framework/Versions/A/Resources/Python/lldb/__init__.py
    +
    +    DESCRIPTION
    +...
    +
    +

    You can also get help using a module class name. The full API that is exposed for that class will be displayed in a man page style window. Below we want to get help on the lldb.SBFrame class:

    +
    (lldb) script help(lldb.SBFrame)
    +    Help on class SBFrame in module lldb:
    +
    +    class SBFrame(__builtin__.object)
    +     |  Represents one of the stack frames associated with a thread.
    +     |  SBThread contains SBFrame(s). For example (from test/lldbutil.py),
    +     |  
    +     |  def print_stacktrace(thread, string_buffer = False):
    +     |      '''Prints a simple stack trace of this thread.'''
    +     |  
    +...
    +
    +

    Or you can get help using any python object, here we use the lldb.process object which is a global variable in the lldb module which represents the currently selected process:

    +
    (lldb) script help(lldb.process)
    +    Help on SBProcess in module lldb object:
    +
    +    class SBProcess(__builtin__.object)
    +     |  Represents the process associated with the target program.
    +     |  
    +     |  SBProcess supports thread iteration. For example (from test/lldbutil.py),
    +     |  
    +     |  # ==================================================
    +     |  # Utility functions related to Threads and Processes
    +     |  # ==================================================
    +     |  
    +...
    +
    + +
    + + +
    +

    Embedded Python Interpreter

    +
    + +

    The embedded python interpreter can be accessed in a variety of ways from within LLDB. The + easiest way is to use the lldb command script with no arguments at the lldb command prompt:

    +
    (lldb) script
    +Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.
    +>>> 2+3
    +5
    +>>> hex(12345)
    +'0x3039'
    +>>> 
    +
    + +

    This drops you into the embedded python interpreter. When running under the script command, + lldb sets some convenience variables that give you quick access to the currently selected entities that characterize + the program and debugger state. In each case, if there is no currently selected entity of the appropriate + type, the variable's IsValid method will return false. These variables are:

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    VariableTypeDescription
    + lldb.debugger + + lldb.SBDebugger + + Contains the debugger object whose script command was invoked. + The lldb.SBDebugger object owns the command interpreter + and all the targets in your debug session. There will always be a + Debugger in the embedded interpreter. +
    + lldb.target + + lldb.SBTarget + + Contains the currently selected target - for instance the one made with the + file or selected by the target select <target-index> command. + The lldb.SBTarget manages one running process, and all the executable + and debug files for the process. +
    + lldb.process + + lldb.SBProcess + + Contains the process of the currently selected target. + The lldb.SBProcess object manages the threads and allows access to + memory for the process. +
    + lldb.thread + + lldb.SBThread + + Contains the currently selected thread. + The lldb.SBThread object manages the stack frames in that thread. + A thread is always selected in the command interpreter when a target stops. + The thread select <thread-index> command can be used to change the + currently selected thread. So as long as you have a stopped process, there will be + some selected thread. +
    + lldb.frame + + lldb.SBFrame + + Contains the currently selected stack frame. + The lldb.SBFrame object manage the stack locals and the register set for + that stack. + A stack frame is always selected in the command interpreter when a target stops. + The frame select <frame-index> command can be used to change the + currently selected frame. So as long as you have a stopped process, there will + be some selected frame. +
    + +

    While extremely convenient, these variables have a couple caveats that you should be aware of. + First of all, they hold the values + of the selected objects on entry to the embedded interpreter. They do not update as you use the LLDB + API's to change, for example, the currently selected stack frame or thread. +

    Moreover, they are only defined and meaningful while in the interactive Python interpreter. + There is no guarantee on their value in any other situation, hence you should not use them when defining + Python formatters, breakpoint scripts and commands (or any other Python extension point that LLDB provides). + As a rationale for such behavior, consider that lldb can + run in a multithreaded environment, and another thread might call the "script" command, changing the value out + from under you.

    + +

    To get started with these objects and LLDB scripting, please note that almost + all of the lldb Python objects are able to briefly describe themselves when you pass them + to the Python print function: +

    (lldb) script
    +Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.
    +>>> print lldb.debugger
    +Debugger (instance: "debugger_1", id: 1)
    +>>> print lldb.target
    +a.out
    +>>> print lldb.process
    +SBProcess: pid = 59289, state = stopped, threads = 1, executable = a.out
    +>>> print lldb.thread
    +SBThread: tid = 0x1f03
    +>>> print lldb.frame
    +frame #0: 0x0000000100000bb6 a.out main + 54 at main.c:16
    +
    + +
    + + +
    +
    +

    Running a Python script when a breakpoint gets hit

    +
    + +

    One very powerful use of the lldb Python API is to have a python script run when a breakpoint gets hit. Adding python + scripts to breakpoints provides a way to create complex breakpoint + conditions and also allows for smart logging and data gathering.

    +

    When your process hits a breakpoint to which you have attached some python code, the code is executed as the + body of a function which takes three arguments:

    +

    +

    def breakpoint_function_wrapper(frame, bp_loc, dict):
    +  # Your code goes here
    +
    +

    + + + + + + + + + + + + + + + + + + + + + +
    ArgumentTypeDescription
    + frame + + lldb.SBFrame + + The current stack frame where the breakpoint got hit. + The object will always be valid. + This frame argument might not match the currently selected stack frame found in the lldb module global variable lldb.frame. +
    + bp_loc + + lldb.SBBreakpointLocation + + The breakpoint location that just got hit. Breakpoints are represented by lldb.SBBreakpoint + objects. These breakpoint objects can have one or more locations. These locations + are represented by lldb.SBBreakpointLocation objects. +
    + dict + + dict + + The python session dictionary as a standard python dictionary object. +
    +

    Optionally, a Python breakpoint command can return a value. Returning False tells LLDB that you do not want to stop at the breakpoint. + Any other return value (including None or leaving out the return statement altogether) is akin to telling LLDB to actually stop at the breakpoint. + This can be useful in situations where a breakpoint only needs to stop the process when certain conditions are met, and you do not want to inspect the + program state manually at every stop and then continue. +

    An example will show how simple it is to write some python code and attach it to a breakpoint. + The following example will allow you to track the order in which the functions in a given shared library + are first executed during one run of your program. This is a simple method to gather an order file which + can be used to optimize function placement within a binary for execution locality.

    +

    We do this by setting a regular expression breakpoint + that will match every function in the shared library. The regular expression '.' will match + any string that has at least one character in it, so we will use that. + This will result in one lldb.SBBreakpoint object + that contains an lldb.SBBreakpointLocation object for each function. As the breakpoint gets + hit, we use a counter to track the order in which the function at this particular breakpoint location got hit. + Since our code is passed the location that was hit, we can get the name of the function from the location, + disable the location so we won't count this function again; then log some info and continue the process.

    +

    Note we also have to initialize our counter, which we do with the simple one-line version of the script + command. +

    Here is the code: + +

    (lldb) breakpoint set --func-regex=. --shlib=libfoo.dylib
    +Breakpoint created: 1: regex = '.', module = libfoo.dylib, locations = 223
    +(lldb) script counter = 0
    +(lldb) breakpoint command add --script-type python 1
    +Enter your Python command(s). Type 'DONE' to end.
    +> # Increment our counter.  Since we are in a function, this must be a global python variable
    +> global counter 
    +> counter += 1
    +> # Get the name of the function
    +> name = frame.GetFunctionName()
    +> # Print the order and the function name
    +> print '[%i] %s' % (counter, name)
    +> # Disable the current breakpoint location so it doesn't get hit again
    +> bp_loc.SetEnabled(False)
    +> # No need to stop here
    +> return False
    +> DONE
    +
    +

    The breakpoint command add command above attaches a python script to breakpoint 1. + To remove the breakpoint command: +

    (lldb) breakpoint command delete 1 +

    +
    +
    +

    Create a new LLDB command using a python function

    +
    + +

    Python functions can be used to create new LLDB command interpreter commands, which will work + like all the natively defined lldb commands. This provides a very flexible and easy way to extend LLDB to meet your + debugging requirements.

    +

    To write a python function that implements a new LDB command define the function to take four arguments as follows:

    + +
    def command_function(debugger, command, result, internal_dict):
    +          # Your code goes here
    +        
    + + Optionally, you can also provide a Python docstring, and LLDB will use it when providing help for your command, as in: +
    def command_function(debugger, command, result, internal_dict):
    +          """This command takes a lot of options and does many fancy things"""    
    +          # Your code goes here
    +        
    + +

    + + + + + + + + + + + + + + + + + + + + + + + + + + +
    ArgumentTypeDescription
    + debugger + + lldb.SBDebugger + + The current debugger object. +
    + command + + python string + + A python string containing all arguments for your command. If you need to chop up the arguments + try using the shlex module's shlex.split(command) to properly extract the + arguments. +
    + result + + lldb.SBCommandReturnObject + + A return object which encapsulates success/failure information for the command and output text + that needs to be printed as a result of the command. The plain Python "print" command also works but + text won't go in the result by default (it is useful as a temporary logging facility). +
    + internal_dict + + python dict object + + The dictionary for the current embedded script session which contains all variables + and functions. +
    +

    As a convenience, you can treat the result object as a Python file object, and say +

    print >>result, "my command does lots of cool stuff"
    + SBCommandReturnObject and SBStream + both support this file-like behavior by providing write() and flush() calls at the Python layer.

    +

    One other handy convenience when defining lldb command-line commands is the command + command script import which will import a module specified by file path - so you + don't have to change your PYTHONPATH for temporary scripts. It also has another convenience + that if your new script module has a function of the form:

    + +
    def __lldb_init_module(debugger, internal_dict):
    +    # Command Initialization code goes here
    +
    + +

    where debugger and internal_dict are as above, that function will get run when the module is loaded + allowing you to add whatever commands you want into the current debugger. Note that + this function will only be run when using the LLDB comand command script import, + it will not get run if anyone imports your module from another module. + If you want to always run code when your module is loaded from LLDB + or when loaded via an import statement in python code + you can test the lldb.debugger object, since you imported the + module at the top of the python ls.py module. This test + must be in code that isn't contained inside of any function or class, + just like the standard test for __main__ like all python modules + usally do. Sample code would look like: + +

    if __name__ == '__main__':
    +    # Create a new debugger instance in your module if your module 
    +    # can be run from the command line. When we run a script from
    +    # the command line, we won't have any debugger object in
    +    # lldb.debugger, so we can just create it if it will be needed
    +    lldb.debugger = lldb.SBDebugger.Create()
    +elif lldb.debugger:
    +    # Module is being run inside the LLDB interpreter
    +    lldb.debugger.HandleCommand('command script add -f ls.ls ls')
    +    print 'The "ls" python command has been installed and is ready for use.'
    +
    +

    Now we can create a module called ls.py in the file ~/ls.py that will implement a function that + can be used by LLDB's python command code:

    + +
    #!/usr/bin/python
    +
    +import lldb
    +import commands
    +import optparse
    +import shlex
    +
    +def ls(debugger, command, result, internal_dict):
    +    print >>result, (commands.getoutput('/bin/ls %s' % command))
    +
    +# And the initialization code to add your commands 
    +def __lldb_init_module(debugger, internal_dict):
    +    debugger.HandleCommand('command script add -f ls.ls ls')
    +    print 'The "ls" python command has been installed and is ready for use.'
    +
    +

    Now we can load the module into LLDB and use it

    +
    % lldb
    +(lldb) command script import ~/ls.py
    +The "ls" python command has been installed and is ready for use.
    +(lldb) ls -l /tmp/
    +total 365848
    +-rw-r--r--@  1 someuser  wheel         6148 Jan 19 17:27 .DS_Store
    +-rw-------   1 someuser  wheel         7331 Jan 19 15:37 crash.log
    +
    +

    A more interesting template has been created in the source repository that can help you to create + lldb command quickly:

    + cmdtemplate.py +

    + A commonly required facility is being able to create a command that does some token substitution, and then runs a different debugger command + (usually, it po'es the result of an expression evaluated on its argument). For instance, given the following program: +

    
    +#import <Foundation/Foundation.h>
    +NSString*
    +ModifyString(NSString* src)
    +{
    +	return [src stringByAppendingString:@"foobar"];
    +}
    +
    +int main()
    +{
    +	NSString* aString = @"Hello world";
    +	NSString* anotherString = @"Let's be friends";
    +	return 1;
    +}
    +		
    + you may want a pofoo X command, that equates po [ModifyString(X) capitalizedString]. + The following debugger interaction shows how to achieve that goal: +
    
    +(lldb) script
    +Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.
    +>>> def pofoo_funct(debugger, command, result, internal_dict):
    +...	cmd = "po [ModifyString(" + command + ") capitalizedString]"
    +...	lldb.debugger.HandleCommand(cmd)
    +... 
    +>>> ^D
    +(lldb) command script add pofoo -f pofoo_funct
    +(lldb) pofoo aString
    +$1 = 0x000000010010aa00 Hello Worldfoobar
    +(lldb) pofoo anotherString
    +$2 = 0x000000010010aba0 Let's Be Friendsfoobar
    +
    +
    +

    Using the lldb.py module in python

    +
    + +

    LLDB has all of its core code build into a shared library which gets + used by the lldb command line application. On Mac OS X this + shared library is a framework: LLDB.framework and on other + unix variants the program is a shared library: lldb.so. LLDB also + provides an lldb.py module that contains the bindings from LLDB into Python. + To use the + LLDB.framework to create your own stand-alone python programs, you will + need to tell python where to look in order to find this module. This + is done by setting the PYTHONPATH environment variable, adding + a path to the directory that contains the lldb.py python module. On + Mac OS X, this is contained inside the LLDB.framework, so you would do: + +

    For csh and tcsh:

    +

    % setenv PYTHONPATH /Developer/Library/PrivateFrameworks/LLDB.framework/Resources/Python

    +

    For sh and bash: +

    % export PYTHONPATH=/Developer/Library/PrivateFrameworks/LLDB.framework/Resources/Python

    + +

    Alternately, you can append the LLDB Python directory to the sys.path list directly in + your Python code before importing the lldb module.

    + +

    + Now your python scripts are ready to import the lldb module. Below is a + python script that will launch a program from the current working directory + called "a.out", set a breakpoint at "main", and then run and hit the breakpoint, + and print the process, thread and frame objects if the process stopped: + +

    +
    #!/usr/bin/python
    +
    +import lldb
    +import os
    +
    +def disassemble_instructions(insts):
    +    for i in insts:
    +        print i
    +
    +# Set the path to the executable to debug
    +exe = "./a.out"
    +
    +# Create a new debugger instance
    +debugger = lldb.SBDebugger.Create()
    +
    +# When we step or continue, don't return from the function until the process 
    +# stops. Otherwise we would have to handle the process events ourselves which, while doable is
    +#a little tricky.  We do this by setting the async mode to false.
    +debugger.SetAsync (False)
    +
    +# Create a target from a file and arch
    +print "Creating a target for '%s'" % exe
    +
    +target = debugger.CreateTargetWithFileAndArch (exe, lldb.LLDB_ARCH_DEFAULT)
    +
    +if target:
    +    # If the target is valid set a breakpoint at main
    +    main_bp = target.BreakpointCreateByName ("main", target.GetExecutable().GetFilename());
    +
    +    print main_bp
    +
    +    # Launch the process. Since we specified synchronous mode, we won't return
    +    # from this function until we hit the breakpoint at main
    +    process = target.LaunchSimple (None, None, os.getcwd())
    +    
    +    # Make sure the launch went ok
    +    if process:
    +        # Print some simple process info
    +        state = process.GetState ()
    +        print process
    +        if state == lldb.eStateStopped:
    +            # Get the first thread
    +            thread = process.GetThreadAtIndex (0)
    +            if thread:
    +                # Print some simple thread info
    +                print thread
    +                # Get the first frame
    +                frame = thread.GetFrameAtIndex (0)
    +                if frame:
    +                    # Print some simple frame info
    +                    print frame
    +                    function = frame.GetFunction()
    +                    # See if we have debug info (a function)
    +                    if function:
    +                        # We do have a function, print some info for the function
    +                        print function
    +                        # Now get all instructions for this function and print them
    +                        insts = function.GetInstructions(target)
    +                        disassemble_instructions (insts)
    +                    else:
    +                        # See if we have a symbol in the symbol table for where we stopped
    +                        symbol = frame.GetSymbol();
    +                        if symbol:
    +                            # We do have a symbol, print some info for the symbol
    +                            print symbol
    +
    +
    + + +
    +
    +
    + + diff --git a/lldb/www/scripting.html b/lldb/www/scripting.html index dfd858abdfbc..7e86acfaa8e8 100755 --- a/lldb/www/scripting.html +++ b/lldb/www/scripting.html @@ -1,586 +1,586 @@ - - - - - -LLDB Example - Python Scripting to Debug a Problem - - - -
    - Example - Using Scripting and Python to Debug in LLDB -
    - -
    -
    - -
    -
    -

    Introduction

    -
    - -

    LLDB has been structured from the beginning to be scriptable in two ways - -- a Unix Python session can initiate/run a debug session non-interactively - using LLDB; and within the LLDB debugger tool, Python scripts can be used to - help with many tasks, including inspecting program data, iterating over - containers and determining if a breakpoint should stop execution or continue. - This document will show how to do some of these things by going through an - example, explaining how to use Python scripting to find a bug in a program - that searches for text in a large binary tree.

    - -
    - - -
    -

    The Test Program and Input

    -
    - -

    We have a simple C program (dictionary.c) that reads in a text file, and - stores all the words from the file in a Binary Search Tree, sorted - alphabetically. It then enters a loop prompting the user for a word, searching - for the word in the tree (using Binary Search), and reporting to the user - whether or not it found the word in the tree.

    - -

    The input text file we are using to test our program contains the text for - William Shakespeare's famous tragedy "Romeo and Juliet".

    - -
    - - -
    -

    The Bug

    -
    - -

    When we try running our program, we find there is a problem. While it - successfully finds some of the words we would expect to find, such as "love" - or "sun", it fails to find the word "Romeo", which MUST be in the input text - file:

    - - - % ./dictionary Romeo-and-Juliet.txt
    - Dictionary loaded.
    - Enter search word: love
    - Yes!
    - Enter search word: sun
    - Yes!
    - Enter search word: Romeo
    - No!
    - Enter search word: ^D
    - %
    -
    - -
    - - - -
    -

    Is the word in our tree: Using Depth First Search

    -
    - -

    Our first job is to determine if the word "Romeo" actually got inserted into - the tree or not. Since "Romeo and Juliet" has thousands of words, trying to - examine our binary search tree by hand is completely impractical. Therefore we - will write a Python script to search the tree for us. We will write a recursive - Depth First Search function that traverses the entire tree searching for a word, - and maintaining information about the path from the root of the tree to the - current node. If it finds the word in the tree, it returns the path from the - root to the node containing the word. This is what our DFS function in Python - would look like, with line numbers added for easy reference in later - explanations:

    - - -
    
    - 1: def DFS (root, word, cur_path):
    - 2:     root_word_ptr = root.GetChildMemberWithName ("word")
    - 3:     left_child_ptr = root.GetChildMemberWithName ("left")
    - 4:     right_child_ptr = root.GetChildMemberWithName ("right")
    - 5:     root_word = root_word_ptr.GetSummary()
    - 6:     end = len (root_word) - 1
    - 7:     if root_word[0] == '"' and root_word[end] == '"':
    - 8:         root_word = root_word[1:end]
    - 9:     end = len (root_word) - 1
    -10:     if root_word[0] == '\'' and root_word[end] == '\'':
    -11:        root_word = root_word[1:end]
    -12:     if root_word == word:
    -13:         return cur_path
    -14:     elif word < root_word:
    -15:         if left_child_ptr.GetValue() == None:
    -16:             return ""
    -17:         else:
    -18:             cur_path = cur_path + "L"
    -19:             return DFS (left_child_ptr, word, cur_path)
    -20:     else:
    -21:         if right_child_ptr.GetValue() == None:
    -22:             return ""
    -23:         else:
    -24:             cur_path = cur_path + "R"
    -25:             return DFS (right_child_ptr, word, cur_path)
    -
    -
    - -
    - - - -
    -

    Accessing & Manipulating Program Variables in Python -

    -
    - -

    Before we can call any Python function on any of our program's variables, we - need to get the variable into a form that Python can access. To show you how to - do this we will look at the parameters for the DFS function. The first - parameter is going to be a node in our binary search tree, put into a Python - variable. The second parameter is the word we are searching for (a string), and - the third parameter is a string representing the path from the root of the tree - to our current node.

    - -

    The most interesting parameter is the first one, the Python variable that - needs to contain a node in our search tree. How can we take a variable out of - our program and put it into a Python variable? What kind of Python variable - will it be? The answers are to use the LLDB API functions, provided as part of - the LLDB Python module. Running Python from inside LLDB, LLDB will - automatically give us our current frame object as a Python variable, - "lldb.frame". This variable has the type "SBFrame" (see the LLDB API for - more information about SBFrame objects). One of the things we can do with a - frame object, is to ask it to find and return its local variable. We will call - the API function "FindVariable" on the lldb.frame object to give us our - dictionary variable as a Python variable:

    - - - root = lldb.frame.FindVariable ("dictionary") - - -

    The line above, executed in the Python script interpreter in LLDB, asks the - current frame to find the variable named "dictionary" and return it. We then - store the returned value in the Python variable named "root". This answers the - question of HOW to get the variable, but it still doesn't explain WHAT actually - gets put into "root". If you examine the LLDB API, you will find that the - SBFrame method "FindVariable" returns an object of type SBValue. SBValue - objects are used, among other things, to wrap up program variables and values. - There are many useful methods defined in the SBValue class to allow you to get - information or children values out of SBValues. For complete information, see - the header file SBValue.h. The - SBValue methods that we use in our DFS function are - GetChildMemberWithName(), - GetSummary(), and GetValue().

    - -
    - - - -
    -

    Explaining Depth First Search Script in Detail

    -
    - -

    "DFS" Overview. Before diving into the details of this - code, it would be best to give a high-level overview of what it does. The nodes - in our binary search tree were defined to have type tree_node *, - which is defined as: - - -

    typedef struct tree_node
    -{
    -  const char *word;
    -  struct tree_node *left;
    -  struct tree_node *right;
    -} tree_node;
    - -

    Lines 2-11 of DFS are getting data out of the current tree node and getting - ready to do the actual search; lines 12-25 are the actual depth-first search. - Lines 2-4 of our DFS function get the word, left and - right fields out of the current node and store them in Python - variables. Since root_word_ptr is a pointer to our word, and we - want the actual word, line 5 calls GetSummary() to get a string - containing the value out of the pointer. Since GetSummary() adds - quotes around its result, lines 6-11 strip surrounding quotes off the word.

    - -

    Line 12 checks to see if the word in the current node is the one we are - searching for. If so, we are done, and line 13 returns the current path. - Otherwise, line 14 checks to see if we should go left (search word comes before - the current word). If we decide to go left, line 15 checks to see if the left - pointer child is NULL ("None" is the Python equivalent of NULL). If the left - pointer is NULL, then the word is not in this tree and we return an empty path - (line 16). Otherwise, we add an "L" to the end of our current path string, to - indicate we are going left (line 18), and then recurse on the left child (line - 19). Lines 20-25 are the same as lines 14-19, except for going right rather - than going left.

    - -

    One other note: Typing something as long as our DFS function directly into - the interpreter can be difficult, as making a single typing mistake means having - to start all over. Therefore we recommend doing as we have done: Writing your - longer, more complicated script functions in a separate file (in this case - tree_utils.py) and then importing it into your LLDB Python interpreter.

    - -
    - - - -
    -

    Seeing the DFS Script in Action

    -
    - - -

    At this point we are ready to use the DFS function to see if the word "Romeo" - is in our tree or not. To actually use it in LLDB on our dictionary program, - you would do something like this:

    - - - % lldb
    - (lldb) process attach -n "dictionary"
    - Architecture set to: x86_64.
    - Process 521 stopped
    - * thread #1: tid = 0x2c03, 0x00007fff86c8bea0 libSystem.B.dylib`read$NOCANCEL + 8, stop reason = signal SIGSTOP
    - frame #0: 0x00007fff86c8bea0 libSystem.B.dylib`read$NOCANCEL + 8
    - (lldb) breakpoint set -n find_word
    - Breakpoint created: 1: name = 'find_word', locations = 1, resolved = 1
    - (lldb) continue
    - Process 521 resuming
    - Process 521 stopped
    - * thread #1: tid = 0x2c03, 0x0000000100001830 dictionary`find_word + 16
    - at dictionary.c:105, stop reason = breakpoint 1.1
    - frame #0: 0x0000000100001830 dictionary`find_word + 16 at dictionary.c:105
    - 102 int
    - 103 find_word (tree_node *dictionary, char *word)
    - 104 {
    - -> 105 if (!word || !dictionary)
    - 106 return 0;
    - 107
    - 108 int compare_value = strcmp (word, dictionary->word);
    - (lldb) script
    - Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.
    - >>> import tree_utils
    - >>> root = lldb.frame.FindVariable ("dictionary")
    - >>> current_path = ""
    - >>> path = tree_utils.DFS (root, "Romeo", current_path)
    - >>> print path
    - LLRRL
    - >>> ^D
    - (lldb)
    -
    - -

    The first bit of code above shows starting lldb, attaching to the dictionary - program, and getting to the find_word function in LLDB. The interesting part - (as far as this example is concerned) begins when we enter the - script command and drop into the embedded interactive Python - interpreter. We will go over this Python code line by line. The first line

    - - - import tree_utils - - -

    imports the file where we wrote our DFS function, tree_utils.py, into Python. - Notice that to import the file we leave off the ".py" extension. We can now - call any function in that file, giving it the prefix "tree_utils.", so that - Python knows where to look for the function. The line

    - - - root = lldb.frame.FindVariable ("dictionary") - - -

    gets our program variable "dictionary" (which contains the binary search - tree) and puts it into the Python variable "root". See - Accessing & Manipulating Program Variables in Python - above for more details about how this works. The next line is

    - - - current_path = "" - - -

    This line initializes the current_path from the root of the tree to our - current node. Since we are starting at the root of the tree, our current path - starts as an empty string. As we go right and left through the tree, the DFS - function will append an 'R' or an 'L' to the current path, as appropriate. The - line

    - - - path = tree_utils.DFS (root, "Romeo", current_path) - - -

    calls our DFS function (prefixing it with the module name so that Python can - find it). We pass in our binary tree stored in the variable root, - the word we are searching for, and our current path. We assign whatever path - the DFS function returns to the Python variable path.

    - - -

    Finally, we want to see if the word was found or not, and if so we want to - see the path through the tree to the word. So we do

    - - - print path - - -

    From this we can see that the word "Romeo" was indeed found in the tree, and - the path from the root of the tree to the node containing "Romeo" is - left-left-right-right-left.

    - -
    - - - -
    -

    What next? Using Breakpoint Command Scripts...

    -
    - -

    We are halfway to figuring out what the problem is. We know the word we are - looking for is in the binary tree, and we know exactly where it is in the binary - tree. Now we need to figure out why our binary search algorithm is not finding - the word. We will do this using breakpoint command scripts.

    - - -

    The idea is as follows. The binary search algorithm has two main decision - points: the decision to follow the right branch; and, the decision to follow - the left branch. We will set a breakpoint at each of these decision points, and - attach a Python breakpoint command script to each breakpoint. The breakpoint - commands will use the global path Python variable that we got from - our DFS function. Each time one of these decision breakpoints is hit, the script - will compare the actual decision with the decision the front of the - path variable says should be made (the first character of the - path). If the actual decision and the path agree, then the front character is - stripped off the path, and execution is resumed. In this case the user never - even sees the breakpoint being hit. But if the decision differs from what the - path says it should be, then the script prints out a message and does NOT resume - execution, leaving the user sitting at the first point where a wrong decision is - being made.

    - -
    - - - -
    -

    Side Note: Python Breakpoint Command Scripts are NOT What They Seem

    -
    - -
    - - -

    What do we mean by that? When you enter a Python breakpoint command in LLDB, - it appears that you are entering one or more plain lines of Python. BUT LLDB - then takes what you entered and wraps it into a Python FUNCTION (just like using - the "def" Python command). It automatically gives the function an obscure, - unique, hard-to-stumble-across function name, and gives it two parameters: - frame and bp_loc. When the breakpoint gets hit, LLDB - wraps up the frame object where the breakpoint was hit, and the breakpoint - location object for the breakpoint that was hit, and puts them into Python - variables for you. It then calls the Python function that was created for the - breakpoint command, and passes in the frame and breakpoint location objects.

    - -

    So, being practical, what does this mean for you when you write your Python - breakpoint commands? It means that there are two things you need to keep in - mind: 1. If you want to access any Python variables created outside your script, - you must declare such variables to be global. If you do not - declare them as global, then the Python function will treat them as local - variables, and you will get unexpected behavior. 2. All Python - breakpoint command scripts automatically have a frame and a - bp_loc variable. The variables are pre-loaded by LLDB - with the correct context for the breakpoint. You do not have to use these - variables, but they are there if you want them.

    - -
    - - - -
    -

    The Decision Point Breakpoint Commands

    -
    - -

    This is what the Python breakpoint command script would look like for the - decision to go right:

    - -

    
    -global path
    -if path[0] == 'R':
    -    path = path[1:]
    -    thread = frame.GetThread()
    -    process = thread.GetProcess()
    -    process.Continue()
    -else:
    -    print "Here is the problem; going right, should go left!"
    -
    - -

    Just as a reminder, LLDB is going to take this script and wrap it up in a - function, like this:

    - -
    
    -def some_unique_and_obscure_function_name (frame, bp_loc):
    -    global path
    -    if path[0] == 'R':
    -        path = path[1:]
    -        thread = frame.GetThread()
    -        process = thread.GetProcess()
    -        process.Continue()
    -    else:
    -        print "Here is the problem; going right, should go left!"
    -
    - -

    LLDB will call the function, passing in the correct frame and breakpoint - location whenever the breakpoint gets hit. There are several things to notice - about this function. The first one is that we are accessing and updating a - piece of state (the path variable), and actually conditioning our - behavior based upon this variable. Since the variable was defined outside of - our script (and therefore outside of the corresponding function) we need to tell - Python that we are accessing a global variable. That is what the first line of - the script does. Next we check where the path says we should go and compare it to - our decision (recall that we are at the breakpoint for the decision to go - right). If the path agrees with our decision, then we strip the first character - off of the path.

    - -

    Since the decision matched the path, we want to resume execution. To do this - we make use of the frame parameter that LLDB guarantees will be - there for us. We use LLDB API functions to get the current thread from the - current frame, and then to get the process from the thread. Once we have the - process, we tell it to resume execution (using the Continue() API - function).

    - -

    If the decision to go right does not agree with the path, then we do not - resume execution. We allow the breakpoint to remain stopped (by doing nothing), - and we print an informational message telling the user we have found the - problem, and what the problem is.

    - -
    - - -
    -

    Actually Using the Breakpoint Commands

    -
    - -

    Now we will look at what happens when we actually use these breakpoint - commands on our program. Doing a source list -n find_word shows - us the function containing our two decision points. Looking at the code below, - we see that we want to set our breakpoints on lines 113 and 115:

    - -
    
    -(lldb) source list -n find_word
    -File: /Volumes/Data/HD2/carolinetice/Desktop/LLDB-Web-Examples/dictionary.c.
    -101 
    -102 int
    -103 find_word (tree_node *dictionary, char *word)
    -104 {
    -105   if (!word || !dictionary)
    -106     return 0;
    -107 
    -108   int compare_value = strcmp (word, dictionary->word);
    -109 
    -110   if (compare_value == 0)
    -111     return 1;
    -112   else if (compare_value < 0)
    -113     return find_word (dictionary->left, word);
    -114   else
    -115     return find_word (dictionary->right, word);
    -116 }
    -117 
    -
    - -

    So, we set our breakpoints, enter our breakpoint command scripts, and see - what happens:

    - -

    
    -(lldb) breakpoint set -l 113
    -Breakpoint created: 2: file ='dictionary.c', line = 113, locations = 1, resolved = 1
    -(lldb) breakpoint set -l 115
    -Breakpoint created: 3: file ='dictionary.c', line = 115, locations = 1, resolved = 1
    -(lldb) breakpoint command add -s python 2
    -Enter your Python command(s). Type 'DONE' to end.
    -> global path
    -> if (path[0] == 'L'):
    ->     path = path[1:]
    ->     thread = frame.GetThread()
    ->     process = thread.GetProcess()
    ->     process.Continue()
    -> else:
    ->     print "Here is the problem. Going left, should go right!"
    -> DONE
    -(lldb) breakpoint command add -s python 3
    -Enter your Python command(s). Type 'DONE' to end.
    -> global path
    -> if (path[0] == 'R'):
    ->     path = path[1:]
    ->     thread = frame.GetThread()
    ->     process = thread.GetProcess()
    ->     process.Continue()
    -> else:
    ->     print "Here is the problem. Going right, should go left!"
    -> DONE
    -(lldb) continue
    -Process 696 resuming
    -Here is the problem. Going right, should go left!
    -Process 696 stopped
    -* thread #1: tid = 0x2d03, 0x000000010000189f dictionary`find_word + 127 at dictionary.c:115, stop reason = breakpoint 3.1
    -  frame #0: 0x000000010000189f dictionary`find_word + 127 at dictionary.c:115
    -    112   else if (compare_value < 0)
    -    113     return find_word (dictionary->left, word);
    -    114   else
    - -> 115     return find_word (dictionary->right, word);
    -    116 }
    -    117 
    -    118 void
    -(lldb)
    -
    - - -

    After setting our breakpoints, adding our breakpoint commands and continuing, - we run for a little bit and then hit one of our breakpoints, printing out the - error message from the breakpoint command. Apparently at this point the the - tree, our search algorithm decided to go right, but our path says the node we - want is to the left. Examining the word at the node where we stopped, and our - search word, we see:

    - - - (lldb) expr dictionary->word
    - (const char *) $1 = 0x0000000100100080 "dramatis"
    - (lldb) expr word
    - (char *) $2 = 0x00007fff5fbff108 "romeo"
    -
    - -

    So the word at our current node is "dramatis", and the word we are searching - for is "romeo". "romeo" comes after "dramatis" alphabetically, so it seems like - going right would be the correct decision. Let's ask Python what it thinks the - path from the current node to our word is:

    - - - (lldb) script print path
    - LLRRL
    -
    - -

    According to Python we need to go left-left-right-right-left from our current - node to find the word we are looking for. Let's double check our tree, and see - what word it has at that node:

    - - - (lldb) expr dictionary->left->left->right->right->left->word
    - (const char *) $4 = 0x0000000100100880 "Romeo"
    -
    - -

    So the word we are searching for is "romeo" and the word at our DFS location - is "Romeo". Aha! One is uppercase and the other is lowercase: We seem to have - a case conversion problem somewhere in our program (we do).

    - -

    This is the end of our example on how you might use Python scripting in LLDB - to help you find bugs in your program.

    - -
    - - -
    -

    Source Files for The Example

    -
    - - -
    - - -

    The complete code for the Dictionary program (with case-conversion bug), - the DFS function and other Python script examples (tree_utils.py) used for this - example are available via following file links:

    - -tree_utils.py - Example Python functions using LLDB's API, including DFS
    -dictionary.c - Sample dictionary program, with bug
    - -

    The text for "Romeo and Juliet" can be obtained from the Gutenberg Project - (http://www.gutenberg.org).

    -
    -
    -
    -
    - - + + + + + +LLDB Example - Python Scripting to Debug a Problem + + + +
    + Example - Using Scripting and Python to Debug in LLDB +
    + +
    +
    + +
    +
    +

    Introduction

    +
    + +

    LLDB has been structured from the beginning to be scriptable in two ways + -- a Unix Python session can initiate/run a debug session non-interactively + using LLDB; and within the LLDB debugger tool, Python scripts can be used to + help with many tasks, including inspecting program data, iterating over + containers and determining if a breakpoint should stop execution or continue. + This document will show how to do some of these things by going through an + example, explaining how to use Python scripting to find a bug in a program + that searches for text in a large binary tree.

    + +
    + + +
    +

    The Test Program and Input

    +
    + +

    We have a simple C program (dictionary.c) that reads in a text file, and + stores all the words from the file in a Binary Search Tree, sorted + alphabetically. It then enters a loop prompting the user for a word, searching + for the word in the tree (using Binary Search), and reporting to the user + whether or not it found the word in the tree.

    + +

    The input text file we are using to test our program contains the text for + William Shakespeare's famous tragedy "Romeo and Juliet".

    + +
    + + +
    +

    The Bug

    +
    + +

    When we try running our program, we find there is a problem. While it + successfully finds some of the words we would expect to find, such as "love" + or "sun", it fails to find the word "Romeo", which MUST be in the input text + file:

    + + + % ./dictionary Romeo-and-Juliet.txt
    + Dictionary loaded.
    + Enter search word: love
    + Yes!
    + Enter search word: sun
    + Yes!
    + Enter search word: Romeo
    + No!
    + Enter search word: ^D
    + %
    +
    + +
    + + + +
    +

    Is the word in our tree: Using Depth First Search

    +
    + +

    Our first job is to determine if the word "Romeo" actually got inserted into + the tree or not. Since "Romeo and Juliet" has thousands of words, trying to + examine our binary search tree by hand is completely impractical. Therefore we + will write a Python script to search the tree for us. We will write a recursive + Depth First Search function that traverses the entire tree searching for a word, + and maintaining information about the path from the root of the tree to the + current node. If it finds the word in the tree, it returns the path from the + root to the node containing the word. This is what our DFS function in Python + would look like, with line numbers added for easy reference in later + explanations:

    + + +
    
    + 1: def DFS (root, word, cur_path):
    + 2:     root_word_ptr = root.GetChildMemberWithName ("word")
    + 3:     left_child_ptr = root.GetChildMemberWithName ("left")
    + 4:     right_child_ptr = root.GetChildMemberWithName ("right")
    + 5:     root_word = root_word_ptr.GetSummary()
    + 6:     end = len (root_word) - 1
    + 7:     if root_word[0] == '"' and root_word[end] == '"':
    + 8:         root_word = root_word[1:end]
    + 9:     end = len (root_word) - 1
    +10:     if root_word[0] == '\'' and root_word[end] == '\'':
    +11:        root_word = root_word[1:end]
    +12:     if root_word == word:
    +13:         return cur_path
    +14:     elif word < root_word:
    +15:         if left_child_ptr.GetValue() == None:
    +16:             return ""
    +17:         else:
    +18:             cur_path = cur_path + "L"
    +19:             return DFS (left_child_ptr, word, cur_path)
    +20:     else:
    +21:         if right_child_ptr.GetValue() == None:
    +22:             return ""
    +23:         else:
    +24:             cur_path = cur_path + "R"
    +25:             return DFS (right_child_ptr, word, cur_path)
    +
    +
    + +
    + + + +
    +

    Accessing & Manipulating Program Variables in Python +

    +
    + +

    Before we can call any Python function on any of our program's variables, we + need to get the variable into a form that Python can access. To show you how to + do this we will look at the parameters for the DFS function. The first + parameter is going to be a node in our binary search tree, put into a Python + variable. The second parameter is the word we are searching for (a string), and + the third parameter is a string representing the path from the root of the tree + to our current node.

    + +

    The most interesting parameter is the first one, the Python variable that + needs to contain a node in our search tree. How can we take a variable out of + our program and put it into a Python variable? What kind of Python variable + will it be? The answers are to use the LLDB API functions, provided as part of + the LLDB Python module. Running Python from inside LLDB, LLDB will + automatically give us our current frame object as a Python variable, + "lldb.frame". This variable has the type "SBFrame" (see the LLDB API for + more information about SBFrame objects). One of the things we can do with a + frame object, is to ask it to find and return its local variable. We will call + the API function "FindVariable" on the lldb.frame object to give us our + dictionary variable as a Python variable:

    + + + root = lldb.frame.FindVariable ("dictionary") + + +

    The line above, executed in the Python script interpreter in LLDB, asks the + current frame to find the variable named "dictionary" and return it. We then + store the returned value in the Python variable named "root". This answers the + question of HOW to get the variable, but it still doesn't explain WHAT actually + gets put into "root". If you examine the LLDB API, you will find that the + SBFrame method "FindVariable" returns an object of type SBValue. SBValue + objects are used, among other things, to wrap up program variables and values. + There are many useful methods defined in the SBValue class to allow you to get + information or children values out of SBValues. For complete information, see + the header file SBValue.h. The + SBValue methods that we use in our DFS function are + GetChildMemberWithName(), + GetSummary(), and GetValue().

    + +
    + + + +
    +

    Explaining Depth First Search Script in Detail

    +
    + +

    "DFS" Overview. Before diving into the details of this + code, it would be best to give a high-level overview of what it does. The nodes + in our binary search tree were defined to have type tree_node *, + which is defined as: + + +

    typedef struct tree_node
    +{
    +  const char *word;
    +  struct tree_node *left;
    +  struct tree_node *right;
    +} tree_node;
    + +

    Lines 2-11 of DFS are getting data out of the current tree node and getting + ready to do the actual search; lines 12-25 are the actual depth-first search. + Lines 2-4 of our DFS function get the word, left and + right fields out of the current node and store them in Python + variables. Since root_word_ptr is a pointer to our word, and we + want the actual word, line 5 calls GetSummary() to get a string + containing the value out of the pointer. Since GetSummary() adds + quotes around its result, lines 6-11 strip surrounding quotes off the word.

    + +

    Line 12 checks to see if the word in the current node is the one we are + searching for. If so, we are done, and line 13 returns the current path. + Otherwise, line 14 checks to see if we should go left (search word comes before + the current word). If we decide to go left, line 15 checks to see if the left + pointer child is NULL ("None" is the Python equivalent of NULL). If the left + pointer is NULL, then the word is not in this tree and we return an empty path + (line 16). Otherwise, we add an "L" to the end of our current path string, to + indicate we are going left (line 18), and then recurse on the left child (line + 19). Lines 20-25 are the same as lines 14-19, except for going right rather + than going left.

    + +

    One other note: Typing something as long as our DFS function directly into + the interpreter can be difficult, as making a single typing mistake means having + to start all over. Therefore we recommend doing as we have done: Writing your + longer, more complicated script functions in a separate file (in this case + tree_utils.py) and then importing it into your LLDB Python interpreter.

    + +
    + + + +
    +

    Seeing the DFS Script in Action

    +
    + + +

    At this point we are ready to use the DFS function to see if the word "Romeo" + is in our tree or not. To actually use it in LLDB on our dictionary program, + you would do something like this:

    + + + % lldb
    + (lldb) process attach -n "dictionary"
    + Architecture set to: x86_64.
    + Process 521 stopped
    + * thread #1: tid = 0x2c03, 0x00007fff86c8bea0 libSystem.B.dylib`read$NOCANCEL + 8, stop reason = signal SIGSTOP
    + frame #0: 0x00007fff86c8bea0 libSystem.B.dylib`read$NOCANCEL + 8
    + (lldb) breakpoint set -n find_word
    + Breakpoint created: 1: name = 'find_word', locations = 1, resolved = 1
    + (lldb) continue
    + Process 521 resuming
    + Process 521 stopped
    + * thread #1: tid = 0x2c03, 0x0000000100001830 dictionary`find_word + 16
    + at dictionary.c:105, stop reason = breakpoint 1.1
    + frame #0: 0x0000000100001830 dictionary`find_word + 16 at dictionary.c:105
    + 102 int
    + 103 find_word (tree_node *dictionary, char *word)
    + 104 {
    + -> 105 if (!word || !dictionary)
    + 106 return 0;
    + 107
    + 108 int compare_value = strcmp (word, dictionary->word);
    + (lldb) script
    + Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.
    + >>> import tree_utils
    + >>> root = lldb.frame.FindVariable ("dictionary")
    + >>> current_path = ""
    + >>> path = tree_utils.DFS (root, "Romeo", current_path)
    + >>> print path
    + LLRRL
    + >>> ^D
    + (lldb)
    +
    + +

    The first bit of code above shows starting lldb, attaching to the dictionary + program, and getting to the find_word function in LLDB. The interesting part + (as far as this example is concerned) begins when we enter the + script command and drop into the embedded interactive Python + interpreter. We will go over this Python code line by line. The first line

    + + + import tree_utils + + +

    imports the file where we wrote our DFS function, tree_utils.py, into Python. + Notice that to import the file we leave off the ".py" extension. We can now + call any function in that file, giving it the prefix "tree_utils.", so that + Python knows where to look for the function. The line

    + + + root = lldb.frame.FindVariable ("dictionary") + + +

    gets our program variable "dictionary" (which contains the binary search + tree) and puts it into the Python variable "root". See + Accessing & Manipulating Program Variables in Python + above for more details about how this works. The next line is

    + + + current_path = "" + + +

    This line initializes the current_path from the root of the tree to our + current node. Since we are starting at the root of the tree, our current path + starts as an empty string. As we go right and left through the tree, the DFS + function will append an 'R' or an 'L' to the current path, as appropriate. The + line

    + + + path = tree_utils.DFS (root, "Romeo", current_path) + + +

    calls our DFS function (prefixing it with the module name so that Python can + find it). We pass in our binary tree stored in the variable root, + the word we are searching for, and our current path. We assign whatever path + the DFS function returns to the Python variable path.

    + + +

    Finally, we want to see if the word was found or not, and if so we want to + see the path through the tree to the word. So we do

    + + + print path + + +

    From this we can see that the word "Romeo" was indeed found in the tree, and + the path from the root of the tree to the node containing "Romeo" is + left-left-right-right-left.

    + +
    + + + +
    +

    What next? Using Breakpoint Command Scripts...

    +
    + +

    We are halfway to figuring out what the problem is. We know the word we are + looking for is in the binary tree, and we know exactly where it is in the binary + tree. Now we need to figure out why our binary search algorithm is not finding + the word. We will do this using breakpoint command scripts.

    + + +

    The idea is as follows. The binary search algorithm has two main decision + points: the decision to follow the right branch; and, the decision to follow + the left branch. We will set a breakpoint at each of these decision points, and + attach a Python breakpoint command script to each breakpoint. The breakpoint + commands will use the global path Python variable that we got from + our DFS function. Each time one of these decision breakpoints is hit, the script + will compare the actual decision with the decision the front of the + path variable says should be made (the first character of the + path). If the actual decision and the path agree, then the front character is + stripped off the path, and execution is resumed. In this case the user never + even sees the breakpoint being hit. But if the decision differs from what the + path says it should be, then the script prints out a message and does NOT resume + execution, leaving the user sitting at the first point where a wrong decision is + being made.

    + +
    + + + +
    +

    Side Note: Python Breakpoint Command Scripts are NOT What They Seem

    +
    + +
    + + +

    What do we mean by that? When you enter a Python breakpoint command in LLDB, + it appears that you are entering one or more plain lines of Python. BUT LLDB + then takes what you entered and wraps it into a Python FUNCTION (just like using + the "def" Python command). It automatically gives the function an obscure, + unique, hard-to-stumble-across function name, and gives it two parameters: + frame and bp_loc. When the breakpoint gets hit, LLDB + wraps up the frame object where the breakpoint was hit, and the breakpoint + location object for the breakpoint that was hit, and puts them into Python + variables for you. It then calls the Python function that was created for the + breakpoint command, and passes in the frame and breakpoint location objects.

    + +

    So, being practical, what does this mean for you when you write your Python + breakpoint commands? It means that there are two things you need to keep in + mind: 1. If you want to access any Python variables created outside your script, + you must declare such variables to be global. If you do not + declare them as global, then the Python function will treat them as local + variables, and you will get unexpected behavior. 2. All Python + breakpoint command scripts automatically have a frame and a + bp_loc variable. The variables are pre-loaded by LLDB + with the correct context for the breakpoint. You do not have to use these + variables, but they are there if you want them.

    + +
    + + + +
    +

    The Decision Point Breakpoint Commands

    +
    + +

    This is what the Python breakpoint command script would look like for the + decision to go right:

    + +

    
    +global path
    +if path[0] == 'R':
    +    path = path[1:]
    +    thread = frame.GetThread()
    +    process = thread.GetProcess()
    +    process.Continue()
    +else:
    +    print "Here is the problem; going right, should go left!"
    +
    + +

    Just as a reminder, LLDB is going to take this script and wrap it up in a + function, like this:

    + +
    
    +def some_unique_and_obscure_function_name (frame, bp_loc):
    +    global path
    +    if path[0] == 'R':
    +        path = path[1:]
    +        thread = frame.GetThread()
    +        process = thread.GetProcess()
    +        process.Continue()
    +    else:
    +        print "Here is the problem; going right, should go left!"
    +
    + +

    LLDB will call the function, passing in the correct frame and breakpoint + location whenever the breakpoint gets hit. There are several things to notice + about this function. The first one is that we are accessing and updating a + piece of state (the path variable), and actually conditioning our + behavior based upon this variable. Since the variable was defined outside of + our script (and therefore outside of the corresponding function) we need to tell + Python that we are accessing a global variable. That is what the first line of + the script does. Next we check where the path says we should go and compare it to + our decision (recall that we are at the breakpoint for the decision to go + right). If the path agrees with our decision, then we strip the first character + off of the path.

    + +

    Since the decision matched the path, we want to resume execution. To do this + we make use of the frame parameter that LLDB guarantees will be + there for us. We use LLDB API functions to get the current thread from the + current frame, and then to get the process from the thread. Once we have the + process, we tell it to resume execution (using the Continue() API + function).

    + +

    If the decision to go right does not agree with the path, then we do not + resume execution. We allow the breakpoint to remain stopped (by doing nothing), + and we print an informational message telling the user we have found the + problem, and what the problem is.

    + +
    + + +
    +

    Actually Using the Breakpoint Commands

    +
    + +

    Now we will look at what happens when we actually use these breakpoint + commands on our program. Doing a source list -n find_word shows + us the function containing our two decision points. Looking at the code below, + we see that we want to set our breakpoints on lines 113 and 115:

    + +
    
    +(lldb) source list -n find_word
    +File: /Volumes/Data/HD2/carolinetice/Desktop/LLDB-Web-Examples/dictionary.c.
    +101 
    +102 int
    +103 find_word (tree_node *dictionary, char *word)
    +104 {
    +105   if (!word || !dictionary)
    +106     return 0;
    +107 
    +108   int compare_value = strcmp (word, dictionary->word);
    +109 
    +110   if (compare_value == 0)
    +111     return 1;
    +112   else if (compare_value < 0)
    +113     return find_word (dictionary->left, word);
    +114   else
    +115     return find_word (dictionary->right, word);
    +116 }
    +117 
    +
    + +

    So, we set our breakpoints, enter our breakpoint command scripts, and see + what happens:

    + +

    
    +(lldb) breakpoint set -l 113
    +Breakpoint created: 2: file ='dictionary.c', line = 113, locations = 1, resolved = 1
    +(lldb) breakpoint set -l 115
    +Breakpoint created: 3: file ='dictionary.c', line = 115, locations = 1, resolved = 1
    +(lldb) breakpoint command add -s python 2
    +Enter your Python command(s). Type 'DONE' to end.
    +> global path
    +> if (path[0] == 'L'):
    +>     path = path[1:]
    +>     thread = frame.GetThread()
    +>     process = thread.GetProcess()
    +>     process.Continue()
    +> else:
    +>     print "Here is the problem. Going left, should go right!"
    +> DONE
    +(lldb) breakpoint command add -s python 3
    +Enter your Python command(s). Type 'DONE' to end.
    +> global path
    +> if (path[0] == 'R'):
    +>     path = path[1:]
    +>     thread = frame.GetThread()
    +>     process = thread.GetProcess()
    +>     process.Continue()
    +> else:
    +>     print "Here is the problem. Going right, should go left!"
    +> DONE
    +(lldb) continue
    +Process 696 resuming
    +Here is the problem. Going right, should go left!
    +Process 696 stopped
    +* thread #1: tid = 0x2d03, 0x000000010000189f dictionary`find_word + 127 at dictionary.c:115, stop reason = breakpoint 3.1
    +  frame #0: 0x000000010000189f dictionary`find_word + 127 at dictionary.c:115
    +    112   else if (compare_value < 0)
    +    113     return find_word (dictionary->left, word);
    +    114   else
    + -> 115     return find_word (dictionary->right, word);
    +    116 }
    +    117 
    +    118 void
    +(lldb)
    +
    + + +

    After setting our breakpoints, adding our breakpoint commands and continuing, + we run for a little bit and then hit one of our breakpoints, printing out the + error message from the breakpoint command. Apparently at this point the the + tree, our search algorithm decided to go right, but our path says the node we + want is to the left. Examining the word at the node where we stopped, and our + search word, we see:

    + + + (lldb) expr dictionary->word
    + (const char *) $1 = 0x0000000100100080 "dramatis"
    + (lldb) expr word
    + (char *) $2 = 0x00007fff5fbff108 "romeo"
    +
    + +

    So the word at our current node is "dramatis", and the word we are searching + for is "romeo". "romeo" comes after "dramatis" alphabetically, so it seems like + going right would be the correct decision. Let's ask Python what it thinks the + path from the current node to our word is:

    + + + (lldb) script print path
    + LLRRL
    +
    + +

    According to Python we need to go left-left-right-right-left from our current + node to find the word we are looking for. Let's double check our tree, and see + what word it has at that node:

    + + + (lldb) expr dictionary->left->left->right->right->left->word
    + (const char *) $4 = 0x0000000100100880 "Romeo"
    +
    + +

    So the word we are searching for is "romeo" and the word at our DFS location + is "Romeo". Aha! One is uppercase and the other is lowercase: We seem to have + a case conversion problem somewhere in our program (we do).

    + +

    This is the end of our example on how you might use Python scripting in LLDB + to help you find bugs in your program.

    + +
    + + +
    +

    Source Files for The Example

    +
    + + +
    + + +

    The complete code for the Dictionary program (with case-conversion bug), + the DFS function and other Python script examples (tree_utils.py) used for this + example are available via following file links:

    + +tree_utils.py - Example Python functions using LLDB's API, including DFS
    +dictionary.c - Sample dictionary program, with bug
    + +

    The text for "Romeo and Juliet" can be obtained from the Gutenberg Project + (http://www.gutenberg.org).

    +
    +
    +
    +
    + + diff --git a/lldb/www/source.html b/lldb/www/source.html index a8c041898193..91ed971089e2 100755 --- a/lldb/www/source.html +++ b/lldb/www/source.html @@ -1,51 +1,51 @@ - - - - - -Accessing LLDB Sources - - - -
    - The LLDB Debugger -
    - -
    -
    - - - -
    -
    -

    Downloading LLDB sources

    -
    -

    Obtaining read only access to the LLDB sources is easy:

    -
      -
    • svn co http://llvm.org/svn/llvm-project/lldb/trunk lldb
    • -
    -

    If you prefer using Git, you can check out LLDB from the LLVM git mirror instead:

    -
      -
    • git clone http://llvm.org/git/lldb.git
    • -
    -
    - -
    -
    -

    Contributing to LLDB

    -
    -

    If you wish to contribute to LLDB, you must first get commit access by - requesting commit access

    -

    Once you have commit access, you will have a USERNAME and you can checkout the sources: - requesting commit access

    -
      -
    • svn co https://USERNAME@llvm.org/svn/llvm-project/lldb/trunk lldb
    • -
    -
    - -
    -
    -
    -
    - - + + + + + +Accessing LLDB Sources + + + +
    + The LLDB Debugger +
    + +
    +
    + + + +
    +
    +

    Downloading LLDB sources

    +
    +

    Obtaining read only access to the LLDB sources is easy:

    +
      +
    • svn co http://llvm.org/svn/llvm-project/lldb/trunk lldb
    • +
    +

    If you prefer using Git, you can check out LLDB from the LLVM git mirror instead:

    +
      +
    • git clone http://llvm.org/git/lldb.git
    • +
    +
    + +
    +
    +

    Contributing to LLDB

    +
    +

    If you wish to contribute to LLDB, you must first get commit access by + requesting commit access

    +

    Once you have commit access, you will have a USERNAME and you can checkout the sources: + requesting commit access

    +
      +
    • svn co https://USERNAME@llvm.org/svn/llvm-project/lldb/trunk lldb
    • +
    +
    + +
    +
    +
    +
    + + diff --git a/lldb/www/style.css b/lldb/www/style.css index 6e96fefacbb8..a3dabc2d9133 100755 --- a/lldb/www/style.css +++ b/lldb/www/style.css @@ -1,161 +1,161 @@ - -.www_title { font-family: "Georgia,Palatino,Times,Roman"; - font-size: 33pt; - text-align: center;} - -#container { - margin: 0px auto; - text-align: left; - width: 860px; -} -#header{ - height:40px; - width:777px; -} -#content{ - padding: 0px 0px 0px 0px; - border:1px solid white; -} -#left{ - padding: 0px 0px 0px 0px; - border:1px solid white; - width:192px; - float:left; -} -#middle{ - padding: 0px 0px 0px 0px; - border:1px solid white; - margin-left:200px; - margin-right:196px; - width:658px; -} - -/*Credits: Dynamic Drive CSS Library */ -/*URL: http://www.dynamicdrive.com/style/ */ - -.urbangreymenu{ -width: 190px; /*width of menu*/ -} - -.urbangreymenu .headerbar{ -font: bold 13px Verdana; -color: white; -background: #606060; -margin-bottom: 0; /*bottom spacing between header and rest of content*/ -text-transform: uppercase; -padding: 7px 0 7px 7px; -} - -.urbangreymenu ul{ -list-style-type: none; -margin: 0; -padding: 0; -margin-bottom: 0; /*bottom spacing between each UL and rest of content*/ -} - -.urbangreymenu ul li{ -padding-bottom: 1px; /*bottom spacing between menu items*/ -} - -.urbangreymenu ul li a{ -font: normal 12px Arial; -color: black; -background: #E9E9E9; -display: block; -padding: 5px 0; -line-height: 17px; -padding-left: 14px; -text-decoration: none; -} - -.urbangreymenu ul li a:visited{ -color: black; -} - -.urbangreymenu ul li a:hover { /*hover state CSS*/ -color: black; -background: #bbbbbb; -} - -.samplecode { - background-repeat:repeat-x; - border:1px solid #d1c7ac; - width: 230px; - color:#333333; - padding:3px; - margin-right:4px; - margin-bottom:8px; - font-family:tahoma, arial, sans-serif; -} - -table.stats { - text-align: center; - font-family: Verdana, Geneva, Arial, Helvetica, sans-serif ; - font-weight: normal; - font-size: 11px; - color: #fff; - background-color: #666; - border: 0px; - border-collapse: collapse; - border-spacing: 0px; -} - -td.blank { - background-color: white; - background: white; - color: white; -} - -td.content { - background-color: #E9E9E9; - color: #000; - padding: 4px; - text-align: left; - border: 1px #fff solid; - height: 40px; - vertical-align: top; -} - -td.header { - background-color: #bbb; - color: #000; - padding: 4px; - text-align: left; - border: 1px #fff solid; - vertical-align: top; -} - -table.stats { - color: #000; - padding: 4px; - text-align: left; - border: 1px #fff solid; -} - - -table.stats td.hed { - background: #606060; - color: white; - padding: 4px; - text-align: left; - border-bottom: 2px #fff solid; - font-size: 12px; - font-weight: bold; -} - -.post { - width: 640px; /*width of menu*/ -} - -.postheader { - font: bold 13px Verdana; - color: white; - background: #606060; - margin-bottom: 0; /*bottom spacing between header and rest of content*/ - text-transform: uppercase; - padding: 7px 0 7px 7px; -} - -.postcontent{ - padding-left: 14px; -} + +.www_title { font-family: "Georgia,Palatino,Times,Roman"; + font-size: 33pt; + text-align: center;} + +#container { + margin: 0px auto; + text-align: left; + width: 860px; +} +#header{ + height:40px; + width:777px; +} +#content{ + padding: 0px 0px 0px 0px; + border:1px solid white; +} +#left{ + padding: 0px 0px 0px 0px; + border:1px solid white; + width:192px; + float:left; +} +#middle{ + padding: 0px 0px 0px 0px; + border:1px solid white; + margin-left:200px; + margin-right:196px; + width:658px; +} + +/*Credits: Dynamic Drive CSS Library */ +/*URL: http://www.dynamicdrive.com/style/ */ + +.urbangreymenu{ +width: 190px; /*width of menu*/ +} + +.urbangreymenu .headerbar{ +font: bold 13px Verdana; +color: white; +background: #606060; +margin-bottom: 0; /*bottom spacing between header and rest of content*/ +text-transform: uppercase; +padding: 7px 0 7px 7px; +} + +.urbangreymenu ul{ +list-style-type: none; +margin: 0; +padding: 0; +margin-bottom: 0; /*bottom spacing between each UL and rest of content*/ +} + +.urbangreymenu ul li{ +padding-bottom: 1px; /*bottom spacing between menu items*/ +} + +.urbangreymenu ul li a{ +font: normal 12px Arial; +color: black; +background: #E9E9E9; +display: block; +padding: 5px 0; +line-height: 17px; +padding-left: 14px; +text-decoration: none; +} + +.urbangreymenu ul li a:visited{ +color: black; +} + +.urbangreymenu ul li a:hover { /*hover state CSS*/ +color: black; +background: #bbbbbb; +} + +.samplecode { + background-repeat:repeat-x; + border:1px solid #d1c7ac; + width: 230px; + color:#333333; + padding:3px; + margin-right:4px; + margin-bottom:8px; + font-family:tahoma, arial, sans-serif; +} + +table.stats { + text-align: center; + font-family: Verdana, Geneva, Arial, Helvetica, sans-serif ; + font-weight: normal; + font-size: 11px; + color: #fff; + background-color: #666; + border: 0px; + border-collapse: collapse; + border-spacing: 0px; +} + +td.blank { + background-color: white; + background: white; + color: white; +} + +td.content { + background-color: #E9E9E9; + color: #000; + padding: 4px; + text-align: left; + border: 1px #fff solid; + height: 40px; + vertical-align: top; +} + +td.header { + background-color: #bbb; + color: #000; + padding: 4px; + text-align: left; + border: 1px #fff solid; + vertical-align: top; +} + +table.stats { + color: #000; + padding: 4px; + text-align: left; + border: 1px #fff solid; +} + + +table.stats td.hed { + background: #606060; + color: white; + padding: 4px; + text-align: left; + border-bottom: 2px #fff solid; + font-size: 12px; + font-weight: bold; +} + +.post { + width: 640px; /*width of menu*/ +} + +.postheader { + font: bold 13px Verdana; + color: white; + background: #606060; + margin-bottom: 0; /*bottom spacing between header and rest of content*/ + text-transform: uppercase; + padding: 7px 0 7px 7px; +} + +.postcontent{ + padding-left: 14px; +} diff --git a/lldb/www/symbolication.html b/lldb/www/symbolication.html index 877c1f10bd49..4945ff3e9ba6 100755 --- a/lldb/www/symbolication.html +++ b/lldb/www/symbolication.html @@ -1,363 +1,363 @@ - - - - - -Symbolicating with LLDB - - - -
    - The LLDB Debugger -
    - -
    -
    - - - -
    -
    -

    Manual Symbolication with LLDB

    -
    -

    LLDB is separated into a shared library that contains the core of the debugger, - and a driver that implements debugging and a command interpreter. LLDB can be - used to symbolicate your crash logs and can often provide more information than - other symbolication programs: -

    -
      -
    • Inlined functions
    • -
    • Variables that are in scope for an address, along with their locations
    • -
    -

    The simplest form of symbolication is to load an executable:

    -
    (lldb) target create --no-dependents --arch x86_64 /tmp/a.out
    -
    -

    We use the "--no-dependents" flag with the "target create" command so - that we don't load all of the dependent shared libraries from the current - system. When we symbolicate, we are often symbolicating a binary that - was running on another system, and even though the main executable might - reference shared libraries in "/usr/lib", we often don't want to load - the versions on the current computer.

    -

    Using the "image list" command will show us a list of all shared libraries - associated with the current target. As expected, we currently only have a single - binary: -

    -
    (lldb) image list
    -[  0] 73431214-6B76-3489-9557-5075F03E36B4 0x0000000100000000 /tmp/a.out 
    -      /tmp/a.out.dSYM/Contents/Resources/DWARF/a.out
    -
    - -

    Now we can look up an address:

    -
    (lldb) image lookup --address 0x100000aa3
    -      Address: a.out[0x0000000100000aa3] (a.out.__TEXT.__text + 131)
    -      Summary: a.out`main + 67 at main.c:13
    -
    -

    Since we haven't specified a slide or any load addresses for individual sections - in the binary, the address that we use here is a file address. A file - address refers to a virtual address as defined by each object file. -

    -

    If we didn't use the "--no-dependents" option with "target create", we would - have loaded all dependent shared libraries:

    -

    (lldb) image list
    -[  0] 73431214-6B76-3489-9557-5075F03E36B4 0x0000000100000000 /tmp/a.out 
    -      /tmp/a.out.dSYM/Contents/Resources/DWARF/a.out
    -[  1] 8CBCF9B9-EBB7-365E-A3FF-2F3850763C6B 0x0000000000000000 /usr/lib/system/libsystem_c.dylib 
    -[  2] 62AA0B84-188A-348B-8F9E-3E2DB08DB93C 0x0000000000000000 /usr/lib/system/libsystem_dnssd.dylib 
    -[  3] C0535565-35D1-31A7-A744-63D9F10F12A4 0x0000000000000000 /usr/lib/system/libsystem_kernel.dylib 
    -...
    -
    - - -

    Now if we do a lookup using a file address, this can result in multiple - matches since most shared libraries have a virtual address space that starts at zero:

    -
    (lldb) image lookup -a 0x1000
    -      Address: a.out[0x0000000000001000] (a.out.__PAGEZERO + 4096)
    -
    -      Address: libsystem_c.dylib[0x0000000000001000] (libsystem_c.dylib.__TEXT.__text + 928)
    -      Summary: libsystem_c.dylib`mcount + 9
    -
    -      Address: libsystem_dnssd.dylib[0x0000000000001000] (libsystem_dnssd.dylib.__TEXT.__text + 456)
    -      Summary: libsystem_dnssd.dylib`ConvertHeaderBytes + 38
    -
    -      Address: libsystem_kernel.dylib[0x0000000000001000] (libsystem_kernel.dylib.__TEXT.__text + 1116)
    -      Summary: libsystem_kernel.dylib`clock_get_time + 102
    -...
    -
    -

    To avoid getting multiple file address matches, you can specify the - name of the shared library to limit the search:

    -
    (lldb) image lookup -a 0x1000 a.out
    -      Address: a.out[0x0000000000001000] (a.out.__PAGEZERO + 4096)
    -
    -
    - -
    -
    -

    Defining Load Addresses for Sections

    -
    -

    When symbolicating your crash logs, it can be tedious if you always have to - adjust your crashlog-addresses into file addresses. To avoid having to do any - conversion, you can set the load address for the sections of the modules in your target. - Once you set any section load address, lookups will switch to using - load addresses. You can slide all sections in the executable by the same amount, - or set the load address for individual sections. The - "target modules load --slide" command allows us to set the load address for - all sections. -

    Below is an example of sliding all sections in a.out by adding 0x123000 to each section's file address:

    -
    (lldb) target create --no-dependents --arch x86_64 /tmp/a.out
    -(lldb) target modules load --file a.out --slide 0x123000
    -
    -

    It is often much easier to specify the actual load location of each section by name. - Crash logs on Mac OS X have a Binary Images section that specifies - that address of the __TEXT segment for each binary. Specifying a slide requires - requires that you first find the original (file) address for the __TEXT - segment, and subtract the two values. - If you specify the - address of the __TEXT segment with "target modules load section address", you don't need to do any calculations. To specify - the load addresses of sections we can specify one or more section name + address pairs - in the "target modules load" command:

    -
    (lldb) target create --no-dependents --arch x86_64 /tmp/a.out
    -(lldb) target modules load --file a.out __TEXT 0x100123000
    -
    -

    We specified that the __TEXT section is loaded at 0x100123000. - Now that we have defined where sections have been loaded in our target, - any lookups we do will now use load addresses so we don't have to - do any math on the addresses in the crashlog backtraces, we can just use the - raw addresses:

    -
    (lldb) image lookup --address 0x100123aa3
    -      Address: a.out[0x0000000100000aa3] (a.out.__TEXT.__text + 131)
    -      Summary: a.out`main + 67 at main.c:13
    -
    -
    - -
    -
    -

    Loading Multiple Executables

    -
    -

    You often have more than one executable involved when you need to symbolicate - a crash log. When this happens, you create a target for the main executable - or one of the shared libraries, then add more modules to the target using the - "target modules add" command.

    -

    Lets say we have a Darwin crash log that contains the following images: -

    Binary Images:
    -    0x100000000 -    0x100000ff7 <A866975B-CA1E-3649-98D0-6C5FAA444ECF> /tmp/a.out
    - 0x7fff83f32000 - 0x7fff83ffefe7 <8CBCF9B9-EBB7-365E-A3FF-2F3850763C6B> /usr/lib/system/libsystem_c.dylib
    - 0x7fff883db000 - 0x7fff883e3ff7 <62AA0B84-188A-348B-8F9E-3E2DB08DB93C> /usr/lib/system/libsystem_dnssd.dylib
    - 0x7fff8c0dc000 - 0x7fff8c0f7ff7 <C0535565-35D1-31A7-A744-63D9F10F12A4> /usr/lib/system/libsystem_kernel.dylib
    -
    - -

    First we create the target using the main executable and then add any extra shared libraries we want:

    -
    (lldb) target create --no-dependents --arch x86_64 /tmp/a.out
    -(lldb) target modules add /usr/lib/system/libsystem_c.dylib
    -(lldb) target modules add /usr/lib/system/libsystem_dnssd.dylib
    -(lldb) target modules add /usr/lib/system/libsystem_kernel.dylib
    -
    -

    If you have debug symbols in standalone files, such as dSYM files on Mac OS X, you can specify their paths using the --symfile option for the "target create" (recent LLDB releases only) and "target modules add" commands:

    -
    (lldb) target create --no-dependents --arch x86_64 /tmp/a.out --symfile /tmp/a.out.dSYM
    -(lldb) target modules add /usr/lib/system/libsystem_c.dylib --symfile /build/server/a/libsystem_c.dylib.dSYM
    -(lldb) target modules add /usr/lib/system/libsystem_dnssd.dylib --symfile /build/server/b/libsystem_dnssd.dylib.dSYM
    -(lldb) target modules add /usr/lib/system/libsystem_kernel.dylib --symfile /build/server/c/libsystem_kernel.dylib.dSYM
    -
    -

    Then we set the load addresses for each __TEXT section (note the colors of the load addresses above and below) using the first address from the Binary Images section for each image:

    -
    (lldb) target modules load --file a.out 0x100000000
    -(lldb) target modules load --file libsystem_c.dylib 0x7fff83f32000
    -(lldb) target modules load --file libsystem_dnssd.dylib 0x7fff883db000
    -(lldb) target modules load --file libsystem_kernel.dylib 0x7fff8c0dc000
    -
    -

    Now any stack backtraces that haven't been symbolicated can be symbolicated using "image lookup" - with the raw backtrace addresses.

    -

    Given the following raw backtrace:

    -
    Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
    -0   libsystem_kernel.dylib        	0x00007fff8a1e6d46 __kill + 10
    -1   libsystem_c.dylib             	0x00007fff84597df0 abort + 177
    -2   libsystem_c.dylib             	0x00007fff84598e2a __assert_rtn + 146
    -3   a.out                         	0x0000000100000f46 main + 70
    -4   libdyld.dylib                 	0x00007fff8c4197e1 start + 1
    -
    -

    We can now symbolicate the load addresses:

    -

    (lldb) image lookup -a 0x00007fff8a1e6d46
    -(lldb) image lookup -a 0x00007fff84597df0
    -(lldb) image lookup -a 0x00007fff84598e2a
    -(lldb) image lookup -a 0x0000000100000f46
    -
    -
    - -
    -
    -

    Getting Variable Information

    -
    -

    If you add the --verbose flag to the "image lookup --address" command, - you can get verbose information which can often include the locations - of some of your local variables: -

    >(lldb) image lookup --address 0x100123aa3 --verbose
    -      Address: a.out[0x0000000100000aa3] (a.out.__TEXT.__text + 110)
    -      Summary: a.out`main + 50 at main.c:13
    -       Module: file = "/tmp/a.out", arch = "x86_64"
    -  CompileUnit: id = {0x00000000}, file = "/tmp/main.c", language = "ISO C:1999"
    -     Function: id = {0x0000004f}, name = "main", range = [0x0000000100000bc0-0x0000000100000dc9)
    -     FuncType: id = {0x0000004f}, decl = main.c:9, clang_type = "int (int, const char **, const char **, const char **)"
    -       Blocks: id = {0x0000004f}, range = [0x100000bc0-0x100000dc9)
    -               id = {0x000000ae}, range = [0x100000bf2-0x100000dc4)
    -    LineEntry: [0x0000000100000bf2-0x0000000100000bfa): /tmp/main.c:13:23
    -       Symbol: id = {0x00000004}, range = [0x0000000100000bc0-0x0000000100000dc9), name="main"
    -     Variable: id = {0x000000bf}, name = "path", type= "char [1024]", location = DW_OP_fbreg(-1072), decl = main.c:28
    -     Variable: id = {0x00000072}, name = "argc", type= "int", location = r13, decl = main.c:8
    -     Variable: id = {0x00000081}, name = "argv", type= "const char **", location = r12, decl = main.c:8
    -     Variable: id = {0x00000090}, name = "envp", type= "const char **", location = r15, decl = main.c:8
    -     Variable: id = {0x0000009f}, name = "aapl", type= "const char **", location = rbx, decl = main.c:8
    -
    -

    The interesting part is the variables that are listed. The variables are - the parameters and local variables that are in scope for the address that - was specified. These variable entries have locations which are shown in bold - above. Crash logs often have register information for the first frame in each - stack, and being able to reconstruct one or more local variables can often - help you decipher more information from a crash log than you normally would be - able to. Note that this is really only useful for the first frame, and only if - your crash logs have register information for your threads. -

    - -
    -
    -

    Using Python API to Symbolicate

    -
    -

    All of the commands above can be done through the python script bridge. The code below - will recreate the target and add the three shared libraries that we added in the darwin - crash log example above: -

    triple = "x86_64-apple-macosx"
    -platform_name = None
    -add_dependents = False
    -target = lldb.debugger.CreateTarget("/tmp/a.out", triple, platform_name, add_dependents, lldb.SBError())
    -if target:
    -	# Get the executable module
    -	module = target.GetModuleAtIndex(0)
    -	target.SetSectionLoadAddress(module.FindSection("__TEXT"), 0x100000000)
    -	module = target.AddModule ("/usr/lib/system/libsystem_c.dylib", triple, None, "/build/server/a/libsystem_c.dylib.dSYM")
    -	target.SetSectionLoadAddress(module.FindSection("__TEXT"), 0x7fff83f32000)
    -	module = target.AddModule ("/usr/lib/system/libsystem_dnssd.dylib", triple, None, "/build/server/b/libsystem_dnssd.dylib.dSYM")
    -	target.SetSectionLoadAddress(module.FindSection("__TEXT"), 0x7fff883db000)
    -	module = target.AddModule ("/usr/lib/system/libsystem_kernel.dylib", triple, None, "/build/server/c/libsystem_kernel.dylib.dSYM")
    -	target.SetSectionLoadAddress(module.FindSection("__TEXT"), 0x7fff8c0dc000)
    -
    -	load_addr = 0x00007fff8a1e6d46
    -	# so_addr is a section offset address, or a lldb.SBAddress object
    -	so_addr = target.ResolveLoadAddress (load_addr)
    -	# Get a symbol context for the section offset address which includes
    -	# a module, compile unit, function, block, line entry, and symbol
    -	sym_ctx = so_addr.GetSymbolContext (lldb.eSymbolContextEverything)
    -	print sym_ctx
    -
    -
    -
    - -
    -
    -

    Use Builtin Python module to Symbolicate

    -
    -

    LLDB includes a module in the lldb package named lldb.utils.symbolication. - This module contains a lot of symbolication functions that simplify the symbolication - process by allowing you to create objects that represent symbolication class objects such as: -

      -
    • lldb.utils.symbolication.Address
    • -
    • lldb.utils.symbolication.Section
    • -
    • lldb.utils.symbolication.Image
    • -
    • lldb.utils.symbolication.Symbolicator
    • -
    -

    lldb.utils.symbolication.Address

    -

    This class represents an address that will be symbolicated. It will cache any information - that has been looked up: module, compile unit, function, block, line entry, symbol. - It does this by having a lldb.SBSymbolContext as a member variable. -

    -

    lldb.utils.symbolication.Section

    -

    This class represents a section that might get loaded in a lldb.utils.symbolication.Image. - It has helper functions that allow you to set it from text that might have been extracted from - a crash log file. -

    -

    lldb.utils.symbolication.Image

    -

    This class represents a module that might get loaded into the target we use for symbolication. - This class contains the executable path, optional symbol file path, the triple, and the list of sections that will need to be loaded - if we choose the ask the target to load this image. Many of these objects will never be loaded - into the target unless they are needed by symbolication. You often have a crash log that has - 100 to 200 different shared libraries loaded, but your crash log stack backtraces only use a few - of these shared libraries. Only the images that contain stack backtrace addresses need to be loaded - in the target in order to symbolicate. -

    -

    Subclasses of this class will want to override the locate_module_and_debug_symbols method: -

    class CustomImage(lldb.utils.symbolication.Image):
    -    def locate_module_and_debug_symbols (self):
    -        # Locate the module and symbol given the info found in the crash log
    -
    -

    Overriding this function allows clients to find the correct executable module and symbol files as they might reside on a build server.

    -

    lldb.utils.symbolication.Symbolicator

    -

    This class coordinates the symbolication process by loading only the lldb.utils.symbolication.Image - instances that need to be loaded in order to symbolicate an supplied address. -

    -

    lldb.macosx.crashlog

    -

    lldb.macosx.crashlog is a package that is distributed on Mac OS X builds that subclasses the above classes. - This module parses the information in the Darwin crash logs and creates symbolication objects that - represent the images, the sections and the thread frames for the backtraces. It then uses the functions - in the lldb.utils.symbolication to symbolicate the crash logs.

    -

    - This module installs a new "crashlog" command into the lldb command interpreter so that you can use - it to parse and symbolicate Mac OS X crash logs:

    -
    (lldb) command script import lldb.macosx.crashlog
    -"crashlog" and "save_crashlog" command installed, use the "--help" option for detailed help
    -(lldb) crashlog /tmp/crash.log
    -...
    -
    -

    The command that is installed has built in help that shows the - options that can be used when symbolicating: -

    (lldb) crashlog --help
    -Usage: crashlog [options]  [FILE ...]
    -
    -Symbolicate one or more darwin crash log files to provide source file and line
    -information, inlined stack frames back to the concrete functions, and
    -disassemble the location of the crash for the first frame of the crashed
    -thread. If this script is imported into the LLDB command interpreter, a
    -"crashlog" command will be added to the interpreter for use at the LLDB
    -command line. After a crash log has been parsed and symbolicated, a target
    -will have been created that has all of the shared libraries loaded at the load
    -addresses found in the crash log file. This allows you to explore the program
    -as if it were stopped at the locations described in the crash log and
    -functions can  be disassembled and lookups can be performed using the
    -addresses found in the crash log.
    -
    -Options:
    -  -h, --help            show this help message and exit
    -  -v, --verbose         display verbose debug info
    -  -g, --debug           display verbose debug logging
    -  -a, --load-all        load all executable images, not just the images found
    -                        in the crashed stack frames
    -  --images              show image list
    -  --debug-delay=NSEC    pause for NSEC seconds for debugger
    -  -c, --crashed-only    only symbolicate the crashed thread
    -  -d DISASSEMBLE_DEPTH, --disasm-depth=DISASSEMBLE_DEPTH
    -                        set the depth in stack frames that should be
    -                        disassembled (default is 1)
    -  -D, --disasm-all      enabled disassembly of frames on all threads (not just
    -                        the crashed thread)
    -  -B DISASSEMBLE_BEFORE, --disasm-before=DISASSEMBLE_BEFORE
    -                        the number of instructions to disassemble before the
    -                        frame PC
    -  -A DISASSEMBLE_AFTER, --disasm-after=DISASSEMBLE_AFTER
    -                        the number of instructions to disassemble after the
    -                        frame PC
    -  -C NLINES, --source-context=NLINES
    -                        show NLINES source lines of source context (default =
    -                        4)
    -  --source-frames=NFRAMES
    -                        show source for NFRAMES (default = 4)
    -  --source-all          show source for all threads, not just the crashed
    -                        thread
    -  -i, --interactive     parse all crash logs and enter interactive mode
    -
    -
    -

    The source for the "symbolication" and "crashlog" modules are available in SVN:

    - -
    - -
    -
    - - + + + + + +Symbolicating with LLDB + + + +
    + The LLDB Debugger +
    + +
    +
    + + + +
    +
    +

    Manual Symbolication with LLDB

    +
    +

    LLDB is separated into a shared library that contains the core of the debugger, + and a driver that implements debugging and a command interpreter. LLDB can be + used to symbolicate your crash logs and can often provide more information than + other symbolication programs: +

    +
      +
    • Inlined functions
    • +
    • Variables that are in scope for an address, along with their locations
    • +
    +

    The simplest form of symbolication is to load an executable:

    +
    (lldb) target create --no-dependents --arch x86_64 /tmp/a.out
    +
    +

    We use the "--no-dependents" flag with the "target create" command so + that we don't load all of the dependent shared libraries from the current + system. When we symbolicate, we are often symbolicating a binary that + was running on another system, and even though the main executable might + reference shared libraries in "/usr/lib", we often don't want to load + the versions on the current computer.

    +

    Using the "image list" command will show us a list of all shared libraries + associated with the current target. As expected, we currently only have a single + binary: +

    +
    (lldb) image list
    +[  0] 73431214-6B76-3489-9557-5075F03E36B4 0x0000000100000000 /tmp/a.out 
    +      /tmp/a.out.dSYM/Contents/Resources/DWARF/a.out
    +
    + +

    Now we can look up an address:

    +
    (lldb) image lookup --address 0x100000aa3
    +      Address: a.out[0x0000000100000aa3] (a.out.__TEXT.__text + 131)
    +      Summary: a.out`main + 67 at main.c:13
    +
    +

    Since we haven't specified a slide or any load addresses for individual sections + in the binary, the address that we use here is a file address. A file + address refers to a virtual address as defined by each object file. +

    +

    If we didn't use the "--no-dependents" option with "target create", we would + have loaded all dependent shared libraries:

    +

    (lldb) image list
    +[  0] 73431214-6B76-3489-9557-5075F03E36B4 0x0000000100000000 /tmp/a.out 
    +      /tmp/a.out.dSYM/Contents/Resources/DWARF/a.out
    +[  1] 8CBCF9B9-EBB7-365E-A3FF-2F3850763C6B 0x0000000000000000 /usr/lib/system/libsystem_c.dylib 
    +[  2] 62AA0B84-188A-348B-8F9E-3E2DB08DB93C 0x0000000000000000 /usr/lib/system/libsystem_dnssd.dylib 
    +[  3] C0535565-35D1-31A7-A744-63D9F10F12A4 0x0000000000000000 /usr/lib/system/libsystem_kernel.dylib 
    +...
    +
    + + +

    Now if we do a lookup using a file address, this can result in multiple + matches since most shared libraries have a virtual address space that starts at zero:

    +
    (lldb) image lookup -a 0x1000
    +      Address: a.out[0x0000000000001000] (a.out.__PAGEZERO + 4096)
    +
    +      Address: libsystem_c.dylib[0x0000000000001000] (libsystem_c.dylib.__TEXT.__text + 928)
    +      Summary: libsystem_c.dylib`mcount + 9
    +
    +      Address: libsystem_dnssd.dylib[0x0000000000001000] (libsystem_dnssd.dylib.__TEXT.__text + 456)
    +      Summary: libsystem_dnssd.dylib`ConvertHeaderBytes + 38
    +
    +      Address: libsystem_kernel.dylib[0x0000000000001000] (libsystem_kernel.dylib.__TEXT.__text + 1116)
    +      Summary: libsystem_kernel.dylib`clock_get_time + 102
    +...
    +
    +

    To avoid getting multiple file address matches, you can specify the + name of the shared library to limit the search:

    +
    (lldb) image lookup -a 0x1000 a.out
    +      Address: a.out[0x0000000000001000] (a.out.__PAGEZERO + 4096)
    +
    +
    + +
    +
    +

    Defining Load Addresses for Sections

    +
    +

    When symbolicating your crash logs, it can be tedious if you always have to + adjust your crashlog-addresses into file addresses. To avoid having to do any + conversion, you can set the load address for the sections of the modules in your target. + Once you set any section load address, lookups will switch to using + load addresses. You can slide all sections in the executable by the same amount, + or set the load address for individual sections. The + "target modules load --slide" command allows us to set the load address for + all sections. +

    Below is an example of sliding all sections in a.out by adding 0x123000 to each section's file address:

    +
    (lldb) target create --no-dependents --arch x86_64 /tmp/a.out
    +(lldb) target modules load --file a.out --slide 0x123000
    +
    +

    It is often much easier to specify the actual load location of each section by name. + Crash logs on Mac OS X have a Binary Images section that specifies + that address of the __TEXT segment for each binary. Specifying a slide requires + requires that you first find the original (file) address for the __TEXT + segment, and subtract the two values. + If you specify the + address of the __TEXT segment with "target modules load section address", you don't need to do any calculations. To specify + the load addresses of sections we can specify one or more section name + address pairs + in the "target modules load" command:

    +
    (lldb) target create --no-dependents --arch x86_64 /tmp/a.out
    +(lldb) target modules load --file a.out __TEXT 0x100123000
    +
    +

    We specified that the __TEXT section is loaded at 0x100123000. + Now that we have defined where sections have been loaded in our target, + any lookups we do will now use load addresses so we don't have to + do any math on the addresses in the crashlog backtraces, we can just use the + raw addresses:

    +
    (lldb) image lookup --address 0x100123aa3
    +      Address: a.out[0x0000000100000aa3] (a.out.__TEXT.__text + 131)
    +      Summary: a.out`main + 67 at main.c:13
    +
    +
    + +
    +
    +

    Loading Multiple Executables

    +
    +

    You often have more than one executable involved when you need to symbolicate + a crash log. When this happens, you create a target for the main executable + or one of the shared libraries, then add more modules to the target using the + "target modules add" command.

    +

    Lets say we have a Darwin crash log that contains the following images: +

    Binary Images:
    +    0x100000000 -    0x100000ff7 <A866975B-CA1E-3649-98D0-6C5FAA444ECF> /tmp/a.out
    + 0x7fff83f32000 - 0x7fff83ffefe7 <8CBCF9B9-EBB7-365E-A3FF-2F3850763C6B> /usr/lib/system/libsystem_c.dylib
    + 0x7fff883db000 - 0x7fff883e3ff7 <62AA0B84-188A-348B-8F9E-3E2DB08DB93C> /usr/lib/system/libsystem_dnssd.dylib
    + 0x7fff8c0dc000 - 0x7fff8c0f7ff7 <C0535565-35D1-31A7-A744-63D9F10F12A4> /usr/lib/system/libsystem_kernel.dylib
    +
    + +

    First we create the target using the main executable and then add any extra shared libraries we want:

    +
    (lldb) target create --no-dependents --arch x86_64 /tmp/a.out
    +(lldb) target modules add /usr/lib/system/libsystem_c.dylib
    +(lldb) target modules add /usr/lib/system/libsystem_dnssd.dylib
    +(lldb) target modules add /usr/lib/system/libsystem_kernel.dylib
    +
    +

    If you have debug symbols in standalone files, such as dSYM files on Mac OS X, you can specify their paths using the --symfile option for the "target create" (recent LLDB releases only) and "target modules add" commands:

    +
    (lldb) target create --no-dependents --arch x86_64 /tmp/a.out --symfile /tmp/a.out.dSYM
    +(lldb) target modules add /usr/lib/system/libsystem_c.dylib --symfile /build/server/a/libsystem_c.dylib.dSYM
    +(lldb) target modules add /usr/lib/system/libsystem_dnssd.dylib --symfile /build/server/b/libsystem_dnssd.dylib.dSYM
    +(lldb) target modules add /usr/lib/system/libsystem_kernel.dylib --symfile /build/server/c/libsystem_kernel.dylib.dSYM
    +
    +

    Then we set the load addresses for each __TEXT section (note the colors of the load addresses above and below) using the first address from the Binary Images section for each image:

    +
    (lldb) target modules load --file a.out 0x100000000
    +(lldb) target modules load --file libsystem_c.dylib 0x7fff83f32000
    +(lldb) target modules load --file libsystem_dnssd.dylib 0x7fff883db000
    +(lldb) target modules load --file libsystem_kernel.dylib 0x7fff8c0dc000
    +
    +

    Now any stack backtraces that haven't been symbolicated can be symbolicated using "image lookup" + with the raw backtrace addresses.

    +

    Given the following raw backtrace:

    +
    Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
    +0   libsystem_kernel.dylib        	0x00007fff8a1e6d46 __kill + 10
    +1   libsystem_c.dylib             	0x00007fff84597df0 abort + 177
    +2   libsystem_c.dylib             	0x00007fff84598e2a __assert_rtn + 146
    +3   a.out                         	0x0000000100000f46 main + 70
    +4   libdyld.dylib                 	0x00007fff8c4197e1 start + 1
    +
    +

    We can now symbolicate the load addresses:

    +

    (lldb) image lookup -a 0x00007fff8a1e6d46
    +(lldb) image lookup -a 0x00007fff84597df0
    +(lldb) image lookup -a 0x00007fff84598e2a
    +(lldb) image lookup -a 0x0000000100000f46
    +
    +
    + +
    +
    +

    Getting Variable Information

    +
    +

    If you add the --verbose flag to the "image lookup --address" command, + you can get verbose information which can often include the locations + of some of your local variables: +

    >(lldb) image lookup --address 0x100123aa3 --verbose
    +      Address: a.out[0x0000000100000aa3] (a.out.__TEXT.__text + 110)
    +      Summary: a.out`main + 50 at main.c:13
    +       Module: file = "/tmp/a.out", arch = "x86_64"
    +  CompileUnit: id = {0x00000000}, file = "/tmp/main.c", language = "ISO C:1999"
    +     Function: id = {0x0000004f}, name = "main", range = [0x0000000100000bc0-0x0000000100000dc9)
    +     FuncType: id = {0x0000004f}, decl = main.c:9, clang_type = "int (int, const char **, const char **, const char **)"
    +       Blocks: id = {0x0000004f}, range = [0x100000bc0-0x100000dc9)
    +               id = {0x000000ae}, range = [0x100000bf2-0x100000dc4)
    +    LineEntry: [0x0000000100000bf2-0x0000000100000bfa): /tmp/main.c:13:23
    +       Symbol: id = {0x00000004}, range = [0x0000000100000bc0-0x0000000100000dc9), name="main"
    +     Variable: id = {0x000000bf}, name = "path", type= "char [1024]", location = DW_OP_fbreg(-1072), decl = main.c:28
    +     Variable: id = {0x00000072}, name = "argc", type= "int", location = r13, decl = main.c:8
    +     Variable: id = {0x00000081}, name = "argv", type= "const char **", location = r12, decl = main.c:8
    +     Variable: id = {0x00000090}, name = "envp", type= "const char **", location = r15, decl = main.c:8
    +     Variable: id = {0x0000009f}, name = "aapl", type= "const char **", location = rbx, decl = main.c:8
    +
    +

    The interesting part is the variables that are listed. The variables are + the parameters and local variables that are in scope for the address that + was specified. These variable entries have locations which are shown in bold + above. Crash logs often have register information for the first frame in each + stack, and being able to reconstruct one or more local variables can often + help you decipher more information from a crash log than you normally would be + able to. Note that this is really only useful for the first frame, and only if + your crash logs have register information for your threads. +

    + +
    +
    +

    Using Python API to Symbolicate

    +
    +

    All of the commands above can be done through the python script bridge. The code below + will recreate the target and add the three shared libraries that we added in the darwin + crash log example above: +

    triple = "x86_64-apple-macosx"
    +platform_name = None
    +add_dependents = False
    +target = lldb.debugger.CreateTarget("/tmp/a.out", triple, platform_name, add_dependents, lldb.SBError())
    +if target:
    +	# Get the executable module
    +	module = target.GetModuleAtIndex(0)
    +	target.SetSectionLoadAddress(module.FindSection("__TEXT"), 0x100000000)
    +	module = target.AddModule ("/usr/lib/system/libsystem_c.dylib", triple, None, "/build/server/a/libsystem_c.dylib.dSYM")
    +	target.SetSectionLoadAddress(module.FindSection("__TEXT"), 0x7fff83f32000)
    +	module = target.AddModule ("/usr/lib/system/libsystem_dnssd.dylib", triple, None, "/build/server/b/libsystem_dnssd.dylib.dSYM")
    +	target.SetSectionLoadAddress(module.FindSection("__TEXT"), 0x7fff883db000)
    +	module = target.AddModule ("/usr/lib/system/libsystem_kernel.dylib", triple, None, "/build/server/c/libsystem_kernel.dylib.dSYM")
    +	target.SetSectionLoadAddress(module.FindSection("__TEXT"), 0x7fff8c0dc000)
    +
    +	load_addr = 0x00007fff8a1e6d46
    +	# so_addr is a section offset address, or a lldb.SBAddress object
    +	so_addr = target.ResolveLoadAddress (load_addr)
    +	# Get a symbol context for the section offset address which includes
    +	# a module, compile unit, function, block, line entry, and symbol
    +	sym_ctx = so_addr.GetSymbolContext (lldb.eSymbolContextEverything)
    +	print sym_ctx
    +
    +
    +
    + +
    +
    +

    Use Builtin Python module to Symbolicate

    +
    +

    LLDB includes a module in the lldb package named lldb.utils.symbolication. + This module contains a lot of symbolication functions that simplify the symbolication + process by allowing you to create objects that represent symbolication class objects such as: +

      +
    • lldb.utils.symbolication.Address
    • +
    • lldb.utils.symbolication.Section
    • +
    • lldb.utils.symbolication.Image
    • +
    • lldb.utils.symbolication.Symbolicator
    • +
    +

    lldb.utils.symbolication.Address

    +

    This class represents an address that will be symbolicated. It will cache any information + that has been looked up: module, compile unit, function, block, line entry, symbol. + It does this by having a lldb.SBSymbolContext as a member variable. +

    +

    lldb.utils.symbolication.Section

    +

    This class represents a section that might get loaded in a lldb.utils.symbolication.Image. + It has helper functions that allow you to set it from text that might have been extracted from + a crash log file. +

    +

    lldb.utils.symbolication.Image

    +

    This class represents a module that might get loaded into the target we use for symbolication. + This class contains the executable path, optional symbol file path, the triple, and the list of sections that will need to be loaded + if we choose the ask the target to load this image. Many of these objects will never be loaded + into the target unless they are needed by symbolication. You often have a crash log that has + 100 to 200 different shared libraries loaded, but your crash log stack backtraces only use a few + of these shared libraries. Only the images that contain stack backtrace addresses need to be loaded + in the target in order to symbolicate. +

    +

    Subclasses of this class will want to override the locate_module_and_debug_symbols method: +

    class CustomImage(lldb.utils.symbolication.Image):
    +    def locate_module_and_debug_symbols (self):
    +        # Locate the module and symbol given the info found in the crash log
    +
    +

    Overriding this function allows clients to find the correct executable module and symbol files as they might reside on a build server.

    +

    lldb.utils.symbolication.Symbolicator

    +

    This class coordinates the symbolication process by loading only the lldb.utils.symbolication.Image + instances that need to be loaded in order to symbolicate an supplied address. +

    +

    lldb.macosx.crashlog

    +

    lldb.macosx.crashlog is a package that is distributed on Mac OS X builds that subclasses the above classes. + This module parses the information in the Darwin crash logs and creates symbolication objects that + represent the images, the sections and the thread frames for the backtraces. It then uses the functions + in the lldb.utils.symbolication to symbolicate the crash logs.

    +

    + This module installs a new "crashlog" command into the lldb command interpreter so that you can use + it to parse and symbolicate Mac OS X crash logs:

    +
    (lldb) command script import lldb.macosx.crashlog
    +"crashlog" and "save_crashlog" command installed, use the "--help" option for detailed help
    +(lldb) crashlog /tmp/crash.log
    +...
    +
    +

    The command that is installed has built in help that shows the + options that can be used when symbolicating: +

    (lldb) crashlog --help
    +Usage: crashlog [options]  [FILE ...]
    +
    +Symbolicate one or more darwin crash log files to provide source file and line
    +information, inlined stack frames back to the concrete functions, and
    +disassemble the location of the crash for the first frame of the crashed
    +thread. If this script is imported into the LLDB command interpreter, a
    +"crashlog" command will be added to the interpreter for use at the LLDB
    +command line. After a crash log has been parsed and symbolicated, a target
    +will have been created that has all of the shared libraries loaded at the load
    +addresses found in the crash log file. This allows you to explore the program
    +as if it were stopped at the locations described in the crash log and
    +functions can  be disassembled and lookups can be performed using the
    +addresses found in the crash log.
    +
    +Options:
    +  -h, --help            show this help message and exit
    +  -v, --verbose         display verbose debug info
    +  -g, --debug           display verbose debug logging
    +  -a, --load-all        load all executable images, not just the images found
    +                        in the crashed stack frames
    +  --images              show image list
    +  --debug-delay=NSEC    pause for NSEC seconds for debugger
    +  -c, --crashed-only    only symbolicate the crashed thread
    +  -d DISASSEMBLE_DEPTH, --disasm-depth=DISASSEMBLE_DEPTH
    +                        set the depth in stack frames that should be
    +                        disassembled (default is 1)
    +  -D, --disasm-all      enabled disassembly of frames on all threads (not just
    +                        the crashed thread)
    +  -B DISASSEMBLE_BEFORE, --disasm-before=DISASSEMBLE_BEFORE
    +                        the number of instructions to disassemble before the
    +                        frame PC
    +  -A DISASSEMBLE_AFTER, --disasm-after=DISASSEMBLE_AFTER
    +                        the number of instructions to disassemble after the
    +                        frame PC
    +  -C NLINES, --source-context=NLINES
    +                        show NLINES source lines of source context (default =
    +                        4)
    +  --source-frames=NFRAMES
    +                        show source for NFRAMES (default = 4)
    +  --source-all          show source for all threads, not just the crashed
    +                        thread
    +  -i, --interactive     parse all crash logs and enter interactive mode
    +
    +
    +

    The source for the "symbolication" and "crashlog" modules are available in SVN:

    + +
    + +
    +
    + + diff --git a/lldb/www/symbols.html b/lldb/www/symbols.html index 47eb5bf0e510..76f638de8362 100755 --- a/lldb/www/symbols.html +++ b/lldb/www/symbols.html @@ -1,345 +1,345 @@ - - - - - -Debug Sybmols on Mac OS X - - - -
    - The LLDB Debugger -
    - -
    -
    - - - -
    -
    -

    Debug Symbols on MacOSX

    -
    -

    On MacOSX, debug symbols are often in stand alone bundles called dSYM files. - These are bundles that contain DWARF debug information and other resources related to - builds and debug info.

    -

    The DebugSymbols.framework framework helps locate dSYM files when given a UUID. It can - locate the symbols using a variety of methods:

    -
      -
    • Spotlight
    • -
    • Explicit search paths
    • -
    • Implicit search paths
    • -
    • File mapped UUID paths
    • -
    • Running one or more shell scripts
    • -
    -

    DebugSymbols.framework also has global defaults that can be modified to allow - all of the debug tools (lldb, gdb, sample, CoreSymbolication.framework) to easily - find important debug symbols. The domain for the DebugSymbols.framework defaults - is com.apple.DebugSymbols, and the defaults can be read, written or modified - using the defaults shell command: -

    % defaults read com.apple.DebugSymbols
    -% defaults write com.apple.DebugSymbols KEY ...
    -% defaults delete com.apple.DebugSymbols KEY
    -
    - -

    The following is a list of the defaults key value - setting pairs that can be used to enhance symbol location:

    - - - - - - - - - - - - - - - - - - - - - - - -
    Defaults KeyDescription
    - DBGFileMappedPaths - - This default can be specified as a single string, or an array of strings. - Each string represents a directory that contains file mapped UUID values - that point to dSYM files. See the "File Mapped UUID Directories" section - below for more details. Whenever DebugSymbols.framework is asked to lookup - a dSYM file, it will first look in any file mapped UUID directories - for a quick match. -
    -
    % defaults write com.apple.DebugSymbols DBGFileMappedPaths -string /path/to/uuidmap1
    -% defaults write com.apple.DebugSymbols DBGFileMappedPaths -array /path/to/uuidmap1 
    -    /path/to/uuidmap2
    -
    -
    - DBGShellCommands - - This default can be specified as a single string, or an array of strings. - Specifies a shell script that will get run in order to find the dSYM. - The shell script will be run given a single UUID value as the shell - command arguments and the shell command is expected to return a property - list. See the property list format defined below. -
    -
    % defaults write com.apple.DebugSymbols DBGShellCommands -string /path/to/script1
    -% defaults write com.apple.DebugSymbols DBGShellCommands -array /path/to/script1
    -    /path/to/script2
    -
    -
    - DBGSpotlightPaths - - Specifies the directories to limit spotlight searches to as a string or array of strings. When any - other defaults are supplied to com.apple.DebugSymbols, spotlight - searches will be disabled unless this default is set to an empty array: -
    -
    # Specify an empty array to keep Spotlight searches enabled in all locations
    -% defaults write com.apple.DebugSymbols DBGSpotlightPaths -array
    -
    -# Specify an array of paths to limit spotlight searches to certain directories
    -% defaults write com.apple.DebugSymbols DBGSpotlightPaths -array /path/dir1 /path/dir2
    -
    -
    -
    - -
    -
    -

    Shell Script Property List Format

    -
    -

    Shell scripts that are specified with the DBGShellCommands defaults key -will be run in the order in which they are specified until a match is found. -The shell script will be invoked with a single UUID string value like -"23516BE4-29BE-350C-91C9-F36E7999F0F1". The shell script must respond with a -property list being written to STDOUT. -The property list returned must contain UUID string values as the root key values, with -a dictionary for each UUID. The dictionaries can contain one or more of the following keys: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    KeyDescription
    - DBGArchitecture - A textual architecture or target triple like "x86_64", "i386", or "x86_64-apple-macosx". -
    - DBGBuildSourcePath - A path prefix that was used when building the dSYM file. The debug information will - contain paths with this prefix. -
    - DBGSourcePath - A path prefix for where the sources exist after the build has completed. Often when - building projects, build machines will host the sources in a temporary directory while building, then - move the sources to another location for archiving. If the paths in the debug info don't match where - the sources are currently hosted, then specifying this path along with the DBGBuildSourcePath - will help the developer tools always show you sources when debugging or symbolicating. -
    - DBGDSYMPath - A path to the dSYM mach-o file inside the dSYM bundle. -
    - DBGSymbolRichExecutable - A path to the symbol rich executable. Binaries are often stripped after - being built and packaged into a release. If your build systems saves an unstripped executable - a path to this executable can be provided. -
    - DBGError - If a binary can not be located for the supplied UUID, a user readable error - can be returned. -
    - -

    Below is a sample shell script output for a binary that contains two architectures: -

    
    -<?xml version="1.0" encoding="UTF-8"?>
    -<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    -<plist version="1.0">
    -<dict>
    -	<key>23516BE4-29BE-350C-91C9-F36E7999F0F1</key>
    -	<dict>
    -		<key>DBGArchitecture</key>
    -		<string>i386</string>
    -		<key>DBGBuildSourcePath</key>
    -		<string>/path/to/build/sources</string>
    -		<key>DBGSourcePath</key>
    -		<string>/path/to/actual/sources</string>
    -		<key>DBGDSYMPath</key>
    -		<string>/path/to/foo.dSYM/Contents/Resources/DWARF/foo</string>
    -		<key>DBGSymbolRichExecutable</key>
    -		<string>/path/to/unstripped/exectuable</string>
    -	</dict>
    -	<key>A40597AA-5529-3337-8C09-D8A014EB1578</key>
    -	<dict>
    -		<key>DBGArchitecture</key>
    -		<string>x86_64</string>
    -		<key>DBGBuildSourcePath</key>
    -		<string>/path/to/build/sources</string>
    -		<key>DBGSourcePath</key>
    -		<string>/path/to/actual/sources</string>
    -		<key>DBGDSYMPath</key>
    -		<string>/path/to/foo.dSYM/Contents/Resources/DWARF/foo</string>
    -		<key>DBGSymbolRichExecutable</key>
    -		<string>/path/to/unstripped/exectuable</string>
    -	</dict>
    -</dict>
    -</plist>
    -
    - -

    There is no timeout imposed on a shell script when is it asked to locate a dSYM file, so be careful to not make a shell -script that has high latency or takes a long time to download unless this -is really what you want. This can slow down debug sessions in LLDB and GDB, symbolication -with CoreSymbolication or Report Crash, with no visible feedback to the user. You can -quickly return a plist with a single DBGError key that indicates a timeout -has been reached. You might also want to exec new processes to do the downloads so -that if you return an error that indicates a timeout, your download can still proceed -after your shell script has exited so subsequent debug sessions can use the cached files. -It is also important to track when a current download is in progress in case you get multiple requests for the same UUID so -that you don't end up downloading the same file simultaneously. Also you will want -to verify the download was successful and then and only then place the file into the -cache for tools that will cache files locally. -

    - -
    -
    -

    Embedding UUID property lists inside the dSYM bundles

    -
    -

    Since dSYM files are bundles, you can also place UUID info plists files inside -your dSYM bundles in the Contents/Resources directory. One of the main -reasons to create the UUID plists inside the dSYM bundles -is that it will help LLDB and other developer tools show you source. LLDB currently -knows how to check for these plist files so it can automatically remap the source -location information in the debug info. - -

    If we take the two UUID values from the returns plist above, we can split -them out and save then in the dSYM bundle: - -

    % ls /path/to/foo.dSYM/Contents/Resources
    -23516BE4-29BE-350C-91C9-F36E7999F0F1.plist
    -A40597AA-5529-3337-8C09-D8A014EB1578.plist
    -
    -% cat /path/to/foo.dSYM/Contents/Resources/23516BE4-29BE-350C-91C9-F36E7999F0F1.plist
    -<?xml version="1.0" encoding="UTF-8"?>
    -<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    -<plist version="1.0">
    -<dict>
    -   <key>DBGArchitecture</key>
    -   <string>i386</string>
    -   <key>DBGBuildSourcePath</key>
    -   <string>/path/to/build/sources</string>
    -   <key>DBGSourcePath</key>
    -   <string>/path/to/actual/sources</string>
    -   <key>DBGDSYMPath</key>
    -   <string>/path/to/foo.dSYM/Contents/Resources/DWARF/foo</string>
    -   <key>DBGSymbolRichExecutable</key>
    -   <string>/path/to/unstripped/exectuable</string>
    -</dict>
    -</plist>
    -
    - -

    Note that the output is very close to what is needed by shell script output, -so making the results of your shell script will be very easy to create by -combining two plists into a single one where you take the UUID and use it a - string key, and the value is the contents of the plist. - - -

    - -
    -
    -

    File Mapped UUID Directories

    -
    -

    File Mapped directories can be used for efficient dSYM file lookups for -local or remote dSYM files. The UUID is broken up by splitting the first -20 hex digits into 4 character chunks, and a directory is created for each -chunk, and each subsequent directory is created inside the previous one. -A symlink is then created whose name is the last 12 hex digits in the deepest -directory. The symlinks value is a full path to the mach-o files inside the -dSYM bundle which contains the DWARF. Whenever DebugSymbols.framework is asked -to lookup a dSYM file, it will first look in any file mapped UUID directories -for a quick match if the defaults are appropriately set. - -

    For example, if we take the sample UUID plist inforamtion from above, we -can create a File Mapped UUID directory cache in ~/Library/SymbolCache/dsyms/uuids. -We can easily see how things are laid out: - -

    % find ~/Library/SymbolCache/dsyms/uuids -type l
    -~/Library/SymbolCache/dsyms/uuids/2351/6BE4/29BE/350C/91C9/F36E7999F0F1
    -~/Library/SymbolCache/dsyms/uuids/A405/97AA/5529/3337/8C09/D8A014EB1578
    -
    - -

    The last entries in these file mapped directories are symlinks to the actual dsym mach file in the dsym bundle: - -

    % ls -lAF ~/Library/SymbolCache/dsyms/uuids/2351/6BE4/29BE/350C/91C9/F36E7999F0F1
    -~/Library/SymbolCache/dsyms/uuids/2351/6BE4/29BE/350C/91C9/F36E7999F0F1@ -> ../../../../../../dsyms/foo.dSYM/Contents/Resources/DWARF/foo
    -
    -

    Then you can also tell DebugSymbols to check this UUID file map cache using: - -

    % defaults write com.apple.DebugSymbols DBGFileMappedPaths ~/Library/SymbolCache/dsyms/uuids
    -
    - - -
    - -
    -
    -

    dSYM Locating Shell Script Tips

    -
    - -

    One possible implementation of a dSYM finding shell script is to have the script -download and cache files locally in a known location. Then create a UUID map -for each UUID value that was found in a local UUID File Map cache so the next query for the dSYM -file will be able to use the cached version. So the shell script is used to -initially download and cache the file, and subsequent accesses will use the -cache and avoid calling the shell script. - -

    Then the defaults for DebugSymbols.framework will entail enabling your shell script, -enabling the file mapped path setting so that already downloaded dSYMS fill quickly -be found without needing to run the shell script every time, and also leaving spotlight enabled -so that other normal dSYM files are still found: - -

    % defaults write com.apple.DebugSymbols DBGShellCommands /path/to/shellscript
    -% defaults write com.apple.DebugSymbols DBGFileMappedPaths ~/Library/SymbolCache/dsyms/uuids
    -% defaults write com.apple.DebugSymbols DBGSpotlightPaths -array
    -
    - -Hopefully this helps explain how DebugSymbols.framework can help any company -implement a smart symbol finding and caching with minimal overhead. -

    -
    - -
    -
    -
    -
    - + + + + + +Debug Sybmols on Mac OS X + + + +
    + The LLDB Debugger +
    + +
    +
    + + + +
    +
    +

    Debug Symbols on MacOSX

    +
    +

    On MacOSX, debug symbols are often in stand alone bundles called dSYM files. + These are bundles that contain DWARF debug information and other resources related to + builds and debug info.

    +

    The DebugSymbols.framework framework helps locate dSYM files when given a UUID. It can + locate the symbols using a variety of methods:

    +
      +
    • Spotlight
    • +
    • Explicit search paths
    • +
    • Implicit search paths
    • +
    • File mapped UUID paths
    • +
    • Running one or more shell scripts
    • +
    +

    DebugSymbols.framework also has global defaults that can be modified to allow + all of the debug tools (lldb, gdb, sample, CoreSymbolication.framework) to easily + find important debug symbols. The domain for the DebugSymbols.framework defaults + is com.apple.DebugSymbols, and the defaults can be read, written or modified + using the defaults shell command: +

    % defaults read com.apple.DebugSymbols
    +% defaults write com.apple.DebugSymbols KEY ...
    +% defaults delete com.apple.DebugSymbols KEY
    +
    + +

    The following is a list of the defaults key value + setting pairs that can be used to enhance symbol location:

    + + + + + + + + + + + + + + + + + + + + + + + +
    Defaults KeyDescription
    + DBGFileMappedPaths + + This default can be specified as a single string, or an array of strings. + Each string represents a directory that contains file mapped UUID values + that point to dSYM files. See the "File Mapped UUID Directories" section + below for more details. Whenever DebugSymbols.framework is asked to lookup + a dSYM file, it will first look in any file mapped UUID directories + for a quick match. +
    +
    % defaults write com.apple.DebugSymbols DBGFileMappedPaths -string /path/to/uuidmap1
    +% defaults write com.apple.DebugSymbols DBGFileMappedPaths -array /path/to/uuidmap1 
    +    /path/to/uuidmap2
    +
    +
    + DBGShellCommands + + This default can be specified as a single string, or an array of strings. + Specifies a shell script that will get run in order to find the dSYM. + The shell script will be run given a single UUID value as the shell + command arguments and the shell command is expected to return a property + list. See the property list format defined below. +
    +
    % defaults write com.apple.DebugSymbols DBGShellCommands -string /path/to/script1
    +% defaults write com.apple.DebugSymbols DBGShellCommands -array /path/to/script1
    +    /path/to/script2
    +
    +
    + DBGSpotlightPaths + + Specifies the directories to limit spotlight searches to as a string or array of strings. When any + other defaults are supplied to com.apple.DebugSymbols, spotlight + searches will be disabled unless this default is set to an empty array: +
    +
    # Specify an empty array to keep Spotlight searches enabled in all locations
    +% defaults write com.apple.DebugSymbols DBGSpotlightPaths -array
    +
    +# Specify an array of paths to limit spotlight searches to certain directories
    +% defaults write com.apple.DebugSymbols DBGSpotlightPaths -array /path/dir1 /path/dir2
    +
    +
    +
    + +
    +
    +

    Shell Script Property List Format

    +
    +

    Shell scripts that are specified with the DBGShellCommands defaults key +will be run in the order in which they are specified until a match is found. +The shell script will be invoked with a single UUID string value like +"23516BE4-29BE-350C-91C9-F36E7999F0F1". The shell script must respond with a +property list being written to STDOUT. +The property list returned must contain UUID string values as the root key values, with +a dictionary for each UUID. The dictionaries can contain one or more of the following keys: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    KeyDescription
    + DBGArchitecture + A textual architecture or target triple like "x86_64", "i386", or "x86_64-apple-macosx". +
    + DBGBuildSourcePath + A path prefix that was used when building the dSYM file. The debug information will + contain paths with this prefix. +
    + DBGSourcePath + A path prefix for where the sources exist after the build has completed. Often when + building projects, build machines will host the sources in a temporary directory while building, then + move the sources to another location for archiving. If the paths in the debug info don't match where + the sources are currently hosted, then specifying this path along with the DBGBuildSourcePath + will help the developer tools always show you sources when debugging or symbolicating. +
    + DBGDSYMPath + A path to the dSYM mach-o file inside the dSYM bundle. +
    + DBGSymbolRichExecutable + A path to the symbol rich executable. Binaries are often stripped after + being built and packaged into a release. If your build systems saves an unstripped executable + a path to this executable can be provided. +
    + DBGError + If a binary can not be located for the supplied UUID, a user readable error + can be returned. +
    + +

    Below is a sample shell script output for a binary that contains two architectures: +

    
    +<?xml version="1.0" encoding="UTF-8"?>
    +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    +<plist version="1.0">
    +<dict>
    +	<key>23516BE4-29BE-350C-91C9-F36E7999F0F1</key>
    +	<dict>
    +		<key>DBGArchitecture</key>
    +		<string>i386</string>
    +		<key>DBGBuildSourcePath</key>
    +		<string>/path/to/build/sources</string>
    +		<key>DBGSourcePath</key>
    +		<string>/path/to/actual/sources</string>
    +		<key>DBGDSYMPath</key>
    +		<string>/path/to/foo.dSYM/Contents/Resources/DWARF/foo</string>
    +		<key>DBGSymbolRichExecutable</key>
    +		<string>/path/to/unstripped/exectuable</string>
    +	</dict>
    +	<key>A40597AA-5529-3337-8C09-D8A014EB1578</key>
    +	<dict>
    +		<key>DBGArchitecture</key>
    +		<string>x86_64</string>
    +		<key>DBGBuildSourcePath</key>
    +		<string>/path/to/build/sources</string>
    +		<key>DBGSourcePath</key>
    +		<string>/path/to/actual/sources</string>
    +		<key>DBGDSYMPath</key>
    +		<string>/path/to/foo.dSYM/Contents/Resources/DWARF/foo</string>
    +		<key>DBGSymbolRichExecutable</key>
    +		<string>/path/to/unstripped/exectuable</string>
    +	</dict>
    +</dict>
    +</plist>
    +
    + +

    There is no timeout imposed on a shell script when is it asked to locate a dSYM file, so be careful to not make a shell +script that has high latency or takes a long time to download unless this +is really what you want. This can slow down debug sessions in LLDB and GDB, symbolication +with CoreSymbolication or Report Crash, with no visible feedback to the user. You can +quickly return a plist with a single DBGError key that indicates a timeout +has been reached. You might also want to exec new processes to do the downloads so +that if you return an error that indicates a timeout, your download can still proceed +after your shell script has exited so subsequent debug sessions can use the cached files. +It is also important to track when a current download is in progress in case you get multiple requests for the same UUID so +that you don't end up downloading the same file simultaneously. Also you will want +to verify the download was successful and then and only then place the file into the +cache for tools that will cache files locally. +

    + +
    +
    +

    Embedding UUID property lists inside the dSYM bundles

    +
    +

    Since dSYM files are bundles, you can also place UUID info plists files inside +your dSYM bundles in the Contents/Resources directory. One of the main +reasons to create the UUID plists inside the dSYM bundles +is that it will help LLDB and other developer tools show you source. LLDB currently +knows how to check for these plist files so it can automatically remap the source +location information in the debug info. + +

    If we take the two UUID values from the returns plist above, we can split +them out and save then in the dSYM bundle: + +

    % ls /path/to/foo.dSYM/Contents/Resources
    +23516BE4-29BE-350C-91C9-F36E7999F0F1.plist
    +A40597AA-5529-3337-8C09-D8A014EB1578.plist
    +
    +% cat /path/to/foo.dSYM/Contents/Resources/23516BE4-29BE-350C-91C9-F36E7999F0F1.plist
    +<?xml version="1.0" encoding="UTF-8"?>
    +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    +<plist version="1.0">
    +<dict>
    +   <key>DBGArchitecture</key>
    +   <string>i386</string>
    +   <key>DBGBuildSourcePath</key>
    +   <string>/path/to/build/sources</string>
    +   <key>DBGSourcePath</key>
    +   <string>/path/to/actual/sources</string>
    +   <key>DBGDSYMPath</key>
    +   <string>/path/to/foo.dSYM/Contents/Resources/DWARF/foo</string>
    +   <key>DBGSymbolRichExecutable</key>
    +   <string>/path/to/unstripped/exectuable</string>
    +</dict>
    +</plist>
    +
    + +

    Note that the output is very close to what is needed by shell script output, +so making the results of your shell script will be very easy to create by +combining two plists into a single one where you take the UUID and use it a + string key, and the value is the contents of the plist. + + +

    + +
    +
    +

    File Mapped UUID Directories

    +
    +

    File Mapped directories can be used for efficient dSYM file lookups for +local or remote dSYM files. The UUID is broken up by splitting the first +20 hex digits into 4 character chunks, and a directory is created for each +chunk, and each subsequent directory is created inside the previous one. +A symlink is then created whose name is the last 12 hex digits in the deepest +directory. The symlinks value is a full path to the mach-o files inside the +dSYM bundle which contains the DWARF. Whenever DebugSymbols.framework is asked +to lookup a dSYM file, it will first look in any file mapped UUID directories +for a quick match if the defaults are appropriately set. + +

    For example, if we take the sample UUID plist inforamtion from above, we +can create a File Mapped UUID directory cache in ~/Library/SymbolCache/dsyms/uuids. +We can easily see how things are laid out: + +

    % find ~/Library/SymbolCache/dsyms/uuids -type l
    +~/Library/SymbolCache/dsyms/uuids/2351/6BE4/29BE/350C/91C9/F36E7999F0F1
    +~/Library/SymbolCache/dsyms/uuids/A405/97AA/5529/3337/8C09/D8A014EB1578
    +
    + +

    The last entries in these file mapped directories are symlinks to the actual dsym mach file in the dsym bundle: + +

    % ls -lAF ~/Library/SymbolCache/dsyms/uuids/2351/6BE4/29BE/350C/91C9/F36E7999F0F1
    +~/Library/SymbolCache/dsyms/uuids/2351/6BE4/29BE/350C/91C9/F36E7999F0F1@ -> ../../../../../../dsyms/foo.dSYM/Contents/Resources/DWARF/foo
    +
    +

    Then you can also tell DebugSymbols to check this UUID file map cache using: + +

    % defaults write com.apple.DebugSymbols DBGFileMappedPaths ~/Library/SymbolCache/dsyms/uuids
    +
    + + +
    + +
    +
    +

    dSYM Locating Shell Script Tips

    +
    + +

    One possible implementation of a dSYM finding shell script is to have the script +download and cache files locally in a known location. Then create a UUID map +for each UUID value that was found in a local UUID File Map cache so the next query for the dSYM +file will be able to use the cached version. So the shell script is used to +initially download and cache the file, and subsequent accesses will use the +cache and avoid calling the shell script. + +

    Then the defaults for DebugSymbols.framework will entail enabling your shell script, +enabling the file mapped path setting so that already downloaded dSYMS fill quickly +be found without needing to run the shell script every time, and also leaving spotlight enabled +so that other normal dSYM files are still found: + +

    % defaults write com.apple.DebugSymbols DBGShellCommands /path/to/shellscript
    +% defaults write com.apple.DebugSymbols DBGFileMappedPaths ~/Library/SymbolCache/dsyms/uuids
    +% defaults write com.apple.DebugSymbols DBGSpotlightPaths -array
    +
    + +Hopefully this helps explain how DebugSymbols.framework can help any company +implement a smart symbol finding and caching with minimal overhead. +

    +
    + +
    +
    +
    +
    + \ No newline at end of file diff --git a/lldb/www/troubleshooting.html b/lldb/www/troubleshooting.html index 9db56e3d1d51..7d03faf7ae25 100755 --- a/lldb/www/troubleshooting.html +++ b/lldb/www/troubleshooting.html @@ -1,89 +1,89 @@ - - - - - -LLDB FAQ - - - -
    - Troubleshooting LLDB -
    - -
    -
    - - -
    -
    -

    File and line breakpoints are not getting hit

    -
    -

    First you must make sure that your source files were compiled with - debug information. Typically this means passing -g to the - compiler when compiling your source file. -

    -

    When setting breakpoints in implementation source files - (.c, cpp, cxx, .m, .mm, etc), LLDB by default will only search for compile units whose filename matches. If your - code does tricky things like using #include to include source files: -

    % cat foo.c
    -#include "bar.c"
    -#include "baz.c"
    -...
    -
    -

    This will cause breakpoints in "bar.c" to be inlined into the compile unit for "foo.c". - If your code does this, or if your build system combines multiple files in some way such - that breakpoints from one implementation file will be compiled into another implementation file, - you will need to tell LLDB to always search for inlined breakpoint locations - by adding the following line to your ~/.lldbinit file: -

    -
    % echo "settings set target.inline-breakpoint-strategy always" >> ~/.lldbinit
    -

    This tells LLDB to always look in all compile units and search for breakpoint - locations by file and line even if the implementation file doesn't match. Setting breakpoints - in header files always searches all compile units because inline functions are commonly defined - in header files and often cause multiple breakpoints to have source line information that matches - many header file paths. -

    -

    If you set a file and line breakpoint using a full path to the source file, like Xcode does when setting a - breakpoint in its GUI on Mac OS X when you click in the gutter of the source view, this path must match - the full paths in the debug information. If the paths mismatch, possibly due to - passing in a resolved source file path that doesn't match an unresolved path in the debug - information, this can cause breakpoints to not be resolved. Try setting breakpoints using the file - basename only. -

    If you are using an IDE and you move your project in your file system and build again, sometimes doing a - clean then build will solve the issue.This will fix the issue if some .o files didn't get rebuilt - after the move as the .o files in the build folder might still contain stale debug information with - the old source locations. -

    -
    - -
    -
    - -
    -
    -

    How do I check if I have debug symbols?

    -
    -

    Checking if a module has any compile units (source files) is a good way to check - if there is debug information in a module: -

    
    -(lldb) file /tmp/a.out
    -(lldb) image list
    -[  0] 71E5A649-8FEF-3887-9CED-D3EF8FC2FD6E 0x0000000100000000 /tmp/a.out 
    -      /tmp/a.out.dSYM/Contents/Resources/DWARF/a.out
    -[  1] 6900F2BA-DB48-3B78-B668-58FC0CF6BCB8 0x00007fff5fc00000 /usr/lib/dyld 
    -....
    -(lldb) script lldb.target.module['/tmp/a.out'].GetNumCompileUnits()
    -1
    -(lldb) script lldb.target.module['/usr/lib/dyld'].GetNumCompileUnits()
    -0
    -
    -

    Above we can see that "/tmp/a.out" does have a compile unit, and "/usr/lib/dyld" does not. -

    - -
    -
    -
    -
    - - + + + + + +LLDB FAQ + + + +
    + Troubleshooting LLDB +
    + +
    +
    + + +
    +
    +

    File and line breakpoints are not getting hit

    +
    +

    First you must make sure that your source files were compiled with + debug information. Typically this means passing -g to the + compiler when compiling your source file. +

    +

    When setting breakpoints in implementation source files + (.c, cpp, cxx, .m, .mm, etc), LLDB by default will only search for compile units whose filename matches. If your + code does tricky things like using #include to include source files: +

    % cat foo.c
    +#include "bar.c"
    +#include "baz.c"
    +...
    +
    +

    This will cause breakpoints in "bar.c" to be inlined into the compile unit for "foo.c". + If your code does this, or if your build system combines multiple files in some way such + that breakpoints from one implementation file will be compiled into another implementation file, + you will need to tell LLDB to always search for inlined breakpoint locations + by adding the following line to your ~/.lldbinit file: +

    +
    % echo "settings set target.inline-breakpoint-strategy always" >> ~/.lldbinit
    +

    This tells LLDB to always look in all compile units and search for breakpoint + locations by file and line even if the implementation file doesn't match. Setting breakpoints + in header files always searches all compile units because inline functions are commonly defined + in header files and often cause multiple breakpoints to have source line information that matches + many header file paths. +

    +

    If you set a file and line breakpoint using a full path to the source file, like Xcode does when setting a + breakpoint in its GUI on Mac OS X when you click in the gutter of the source view, this path must match + the full paths in the debug information. If the paths mismatch, possibly due to + passing in a resolved source file path that doesn't match an unresolved path in the debug + information, this can cause breakpoints to not be resolved. Try setting breakpoints using the file + basename only. +

    If you are using an IDE and you move your project in your file system and build again, sometimes doing a + clean then build will solve the issue.This will fix the issue if some .o files didn't get rebuilt + after the move as the .o files in the build folder might still contain stale debug information with + the old source locations. +

    +
    + +
    +
    + +
    +
    +

    How do I check if I have debug symbols?

    +
    +

    Checking if a module has any compile units (source files) is a good way to check + if there is debug information in a module: +

    
    +(lldb) file /tmp/a.out
    +(lldb) image list
    +[  0] 71E5A649-8FEF-3887-9CED-D3EF8FC2FD6E 0x0000000100000000 /tmp/a.out 
    +      /tmp/a.out.dSYM/Contents/Resources/DWARF/a.out
    +[  1] 6900F2BA-DB48-3B78-B668-58FC0CF6BCB8 0x00007fff5fc00000 /usr/lib/dyld 
    +....
    +(lldb) script lldb.target.module['/tmp/a.out'].GetNumCompileUnits()
    +1
    +(lldb) script lldb.target.module['/usr/lib/dyld'].GetNumCompileUnits()
    +0
    +
    +

    Above we can see that "/tmp/a.out" does have a compile unit, and "/usr/lib/dyld" does not. +

    + +
    +
    +
    +
    + + diff --git a/lldb/www/tutorial.html b/lldb/www/tutorial.html index 3e83fb8ad9b6..bbab90de2c4c 100755 --- a/lldb/www/tutorial.html +++ b/lldb/www/tutorial.html @@ -1,726 +1,726 @@ - - - - - -LLDB Tutorial - - - -
    - The LLDB Debugger -
    - -
    -
    - -
    -
    -

    Getting Started

    -
    - -

    Here's a short precis of how to run lldb if you are familiar with the gdb command set. - We will start with some details on lldb command structure and syntax to help orient you.

    - -
    - - -
    -

    Command Structure

    -
    - -

    Unlike gdb's command set, which is rather free-form, we tried to make - the lldb command syntax fairly structured. The commands are all of the - form:

    - - - <noun> <verb> [-options [option-value]] [argument [argument...]] - - -

    The command line parsing is done before command execution, so it is - uniform across all the commands. The command syntax for basic commands is very simple, - arguments, options and option values are all white-space - separated, and double-quotes are used to protect white-spaces in an argument. - If you need to put a backslash or double-quote character - in an argument you back-slash it in the argument. That makes the - command syntax more regular, but it also means you may have to - quote some arguments in lldb that you wouldn't in gdb.

    - -

    Options can be placed anywhere on the command line, but if the arguments - begin with a "-" then you have to tell lldb that you're done with options - for the current command by adding an option termination: "--" - So for instance if you want to launch a process and give the "process launch" command - the "--stop-at-entry" option, yet you want the - process you are about to launch to be launched with the arguments - "-program_arg value", you would type:

    - - - (lldb) process launch --stop-at-entry -- -program_arg value - - -

    We also tried to reduce the number of special purpose argument - parsers, which sometimes forces the user to be a little more explicit - about stating their intentions. The first instance you'll note of - this is the breakpoint command. In gdb, to set a breakpoint, you - might enter

    - - - (gdb) break foo.c:12 - -

    to break at line 12 of foo.c, and:

    - - (gdb) break foo - - -

    to break at the function foo. As time went on, the parser that tells foo.c:12 - from foo from foo.c::foo (which means the function foo in the file - foo.c) got more and more complex and bizarre, and especially in C++ - there are times where there's really no way to specify the function - you want to break on. The lldb commands are more verbose but also more precise - and allow for intellegent auto completion. - -

    To set the same file and line breakpoint in LLDB you can enter either of:

    - - - (lldb) breakpoint set --file foo.c --line 12 -
    (lldb) breakpoint set -f foo.c -l 12 -
    - -

    To set a breakpoint on a function named foo in LLDB you can enter either of:

    - - - (lldb) breakpoint set --name foo -
    (lldb) breakpoint set -n foo -
    - -

    You can use the --name option multiple times to make a breakpoint on a set of functions as well. This is convenient - since it allows you to set commmon conditions or commands without having to specify them multiple times:

    - - - (lldb) breakpoint set --name foo --name bar - - -

    Setting breakpoints by name is even more specialized in LLDB as you can specify - that you want to set a breakpoint at a function by method name. To set a breakpoint - on all C++ methods named foo you can enter either of:

    - - - (lldb) breakpoint set --method foo -
    (lldb) breakpoint set -M foo -
    - -

    To set a breakpoint Objective C selectors named alignLeftEdges: you can enter either of:

    - - - (lldb) breakpoint set --selector alignLeftEdges: -
    (lldb) breakpoint set -S alignLeftEdges: -
    - -

    You can limit any breakpoints to a specific executable image by using - the "--shlib <path>" ("-s <path>" for short):

    - - - (lldb) breakpoint set --shlib foo.dylib --name foo -
    (lldb) breakpoint set -s foo.dylib -n foo -
    - -

    The --shlib option can also be repeated to specify several shared libraries.

    - -

    Suggestions on more interesting primitives of this sort are also very welcome.

    - -

    Just like gdb, the lldb command interpreter does a shortest unique - string match on command names, so the following two commands will - both execute the same command:

    - - - (lldb) breakpoint set -n "-[SKTGraphicView alignLeftEdges:]" -
    (lldb) br s -n "-[SKTGraphicView alignLeftEdges:]" -
    - -

    lldb also supports command completion for source file names, symbol - names, file names, etc. Completion is initiated by a hitting a TAB. - Individual options in a command can have different completers, so for - instance the "--file <path>" option in "breakpoint" completes to source files, the - "--shlib <path>" option to currently loaded shared libraries, etc. We can even do - things like if you specify "--shlib <path>", and are completing on "--file <path>", we will only - list source files in the shared library specified by "--shlib <path>".

    - -

    The individual commands are pretty extensively documented. You can - use the help command to get an overview of which commands are - available or to obtain details about specific commands. There is also an - apropos command that will search the help text for all commands - for a particular word and dump a summary help string for each matching - command.

    - -

    Finally, there is a mechanism to construct aliases for commonly used - commands. So for instance if you get annoyed typing:

    - - - (lldb) breakpoint set --file foo.c --line 12 - - -

    you can do:

    - - - (lldb) command alias bfl breakpoint set -f %1 -l %2 -
    (lldb) bfl foo.c 12 -
    - -

    We have added a few aliases for commonly used commands (e.g. "step", - "next" and "continue") but we haven't tried to be exhaustive because - in our experience it is more convenient to make the basic commands - unique down to a letter or two, and then learn these sequences than - to fill the namespace with lots of aliases, and then have to type them - all the way out.

    - -

    However, users are free to customize lldb's command set however they - like, and since lldb reads the file ~/.lldbinit at startup, you can - store all your aliases there and they will be generally available to - you. Your aliases are also documented in the help command so you can - remind yourself of what you've set up.

    - -

    One alias of note that we do include by popular demand is a weak emulator - of gdb's "break" command. It doesn't try to do everything that gdb's - break command does (for instance, it doesn't handle foo.c::bar. But - it mostly works, and makes the transition easier. Also by popular demand, it - is aliased to b. If you actually want to learn the lldb command - set natively, that means it will get in the way of the rest of the breakpoint - commands. Fortunately, if you don't like one of our aliases, you an easily - get rid of it by running (for example):

    - - - (lldb) command unalias b - - -

    I actually also do:

    - - - (lldb) command alias b breakpoint - - -

    so I can run the native lldb breakpoint command with just b

    - -

    The lldb command parser also supports "raw" commands, where, after command options - are stripped off, the rest of the command string is passed uninterpreted to the command. - This is convenient for commands whose arguments might be some complex expression that would - be painful to backslash protect. - For instance the "expression" command is a "raw" command for obvious reasons. The - "help" output for a command will tell you if it is "raw" or not, so you know what to expect. - The one thing you have to watch out for is that since raw commands still can have options, - if your command string has dashes in it, you'll have to indicate these are not option - markers by putting "--" after the command name, but before your command string. - -

    lldb also has a built-in Python interpreter, which is accessible by - the "script" command. All the functionality of the debugger is - available as classes in the Python interpreter, so the more complex - commands that in gdb you would introduce with the "define" command can - be done by writing Python functions using the lldb-Python library, - then loading the scripts into your running session and accessing them - with the "script" command.

    - -

    Having given an overview of lldb's command syntax, we proceed to lay out the stages - of a standard debug session.

    - -
    - - - -
    -

    Loading a program into lldb

    -
    - -

    First we need to set the program to debug. As with gdb, you - can start lldb and specify the file you wish to debug on the command line:

    - - - $ lldb /Projects/Sketch/build/Debug/Sketch.app -
    Current executable set to '/Projects/Sketch/build/Debug/Sketch.app' (x86_64). -
    - -

    or you can specify it after the fact with the "file" command:

    - - - $ lldb -
    (lldb) file /Projects/Sketch/build/Debug/Sketch.app -
    Current executable set to '/Projects/Sketch/build/Debug/Sketch.app' (x86_64). -
    -

    -

    - - -
    -

    Setting breakpoints

    -
    - -

    We've discussed how to set breakpoints above. You can use help breakpoint set - to see all the options for breakpoint setting. For instance, we might do:

    - - - (lldb) breakpoint set --selector alignLeftEdges: -
    Breakpoint created: 1: name = 'alignLeftEdges:', locations = 1, resolved = 1 -
    - -

    You can find out about the breakpoints you've set with:

    - -
    (lldb) breakpoint list
    -Current breakpoints:
    -1: name = 'alignLeftEdges:', locations = 1, resolved = 1
    -  1.1: where = Sketch`-[SKTGraphicView alignLeftEdges:] + 33 at /Projects/Sketch/SKTGraphicView.m:1405, address = 0x0000000100010d5b, resolved, hit count = 0 
    -
    - -

    Note that setting a breakpoint creates a logical breakpoint, which could - resolve to one or more locations. For instance, break by selector would - set a breakpoint on all the methods that implement that selector in the classes in - your program. Similarly, a file and line breakpoint might result in multiple - locations if that file and line were inlined in different places in your code.

    - -

    The logical breakpoint has an integer id, and it's locations have an - id within their parent breakpoint (the two are joined by a ".", - e.g. 1.1 in the example above.)

    - -

    Also the logical breakpoints remain live so that if another shared library - were to be loaded that had another implementation of the - "alignLeftEdges:" selector, the new location would be added to - breakpoint 1 (e.g. a "1.2" breakpoint would be set on the newly loaded - selector).

    - -

    The other piece of information in the breakpoint listing is whether the - breakpoint location was resolved or not. A location gets resolved when - the file address it corresponds to gets loaded into the program you are - debugging. For instance if you set a breakpoint in a shared library that - then gets unloaded, that breakpoint location will remain, but it will no - longer be resolved.

    - -

    One other thing to note for gdb users is that lldb acts like gdb with:

    - - - (gdb) set breakpoint pending on - - -

    That is, lldb will always make a breakpoint from your specification, even - if it couldn't find any locations that match the specification. You can tell - whether the expression was resolved or not by checking the locations field - in "breakpoint list", and we report the breakpoint as "pending" when you - set it so you can tell you've made a typo more easily, if that was indeed - the reason no locations were found:

    - - - (lldb) breakpoint set --file foo.c --line 12 -
    Breakpoint created: 2: file ='foo.c', line = 12, locations = 0 (pending) -
    WARNING: Unable to resolve breakpoint to any actual locations. -
    - -

    You can delete, disable, set conditions and ignore counts either on all the - locations generated by your logical breakpoint, or on any one of the particular locations - your specification resolved to. For instance if we wanted to add a command - to print a backtrace when we hit this breakpoint we could do:

    - - - (lldb) breakpoint command add 1.1 -
    Enter your debugger command(s). Type 'DONE' to end. -
    > bt -
    > DONE -
    - -

    By default, the breakpoint command add command takes lldb command line commands. - You can also specify this explicitly by passing the "--command" option. - Use "--script" if you want to implement your breakpoint command using the Python script instead.

    - -

    This is an convenient point to bring up another feature of the lldb command help. Do:

    - - - (lldb) help break command add -
    Add a set of commands to a breakpoint, to be executed whenever the breakpoint is hit. -
    -
    Syntax: breakpoint command add <cmd-options> <breakpt-id> -
    etc... -
    - -

    When you see arguments to commands specified in the Syntax in angle - brackets like <breakpt-id>, that indicates that - that is some common argument type that you can get further help on from the command system. - So in this case you could do:

    - - - (lldb) help <breakpt-id> -
    <breakpt-id> -- Breakpoint ID's consist major and minor numbers; the major -
    etc... -
    - -
    - - -
    -

    Setting watchpoints

    -
    - -

    In addition to breakpoints, you can use help watchpoint - to see all the commands for watchpoint manipulations. For instance, we might do the following to watch - a variable called 'global' for write operation, but only stop if the condition '(global==5)' is true:

    - -
    (lldb) watch set var global
    -Watchpoint created: Watchpoint 1: addr = 0x100001018 size = 4 state = enabled type = w
    -    declare @ '/Volumes/data/lldb/svn/ToT/test/functionalities/watchpoint/watchpoint_commands/condition/main.cpp:12'
    -(lldb) watch modify -c '(global==5)'
    -(lldb) watch list
    -Current watchpoints:
    -Watchpoint 1: addr = 0x100001018 size = 4 state = enabled type = w
    -    declare @ '/Volumes/data/lldb/svn/ToT/test/functionalities/watchpoint/watchpoint_commands/condition/main.cpp:12'
    -    condition = '(global==5)'
    -(lldb) c
    -Process 15562 resuming
    -(lldb) about to write to 'global'...
    -Process 15562 stopped and was programmatically restarted.
    -Process 15562 stopped and was programmatically restarted.
    -Process 15562 stopped and was programmatically restarted.
    -Process 15562 stopped and was programmatically restarted.
    -Process 15562 stopped
    -* thread #1: tid = 0x1c03, 0x0000000100000ef5 a.out`modify + 21 at main.cpp:16, stop reason = watchpoint 1
    -    frame #0: 0x0000000100000ef5 a.out`modify + 21 at main.cpp:16
    -   13  	
    -   14  	static void modify(int32_t &var) {
    -   15  	    ++var;
    --> 16  	}
    -   17  	
    -   18  	int main(int argc, char** argv) {
    -   19  	    int local = 0;
    -(lldb) bt
    -* thread #1: tid = 0x1c03, 0x0000000100000ef5 a.out`modify + 21 at main.cpp:16, stop reason = watchpoint 1
    -    frame #0: 0x0000000100000ef5 a.out`modify + 21 at main.cpp:16
    -    frame #1: 0x0000000100000eac a.out`main + 108 at main.cpp:25
    -    frame #2: 0x00007fff8ac9c7e1 libdyld.dylib`start + 1
    -(lldb) frame var global
    -(int32_t) global = 5
    -(lldb) watch list -v
    -Current watchpoints:
    -Watchpoint 1: addr = 0x100001018 size = 4 state = enabled type = w
    -    declare @ '/Volumes/data/lldb/svn/ToT/test/functionalities/watchpoint/watchpoint_commands/condition/main.cpp:12'
    -    condition = '(global==5)'
    -    hw_index = 0  hit_count = 5     ignore_count = 0   
    -(lldb) 
    -
    - - -
    -

    Starting or attaching to your Program

    -
    - -

    To launch a program in lldb we use the "process launch" command or - one of its built in aliases:

    - - - (lldb) process launch -
    (lldb) run -
    (lldb) r -
    - -

    You can also attach to a process by process ID or process name. - When attaching to a process by name, lldb also supports the "--waitfor" option which waits for the - next process that has that name to show up, and attaches to it

    - - - (lldb) process attach --pid 123 -
    (lldb) process attach --name Sketch -
    (lldb) process attach --name Sketch --waitfor -
    - -

    After you launch or attach to a process, your process might stop - somewhere:

    - - (lldb) process attach -p 12345 -
    Process 46915 Attaching -
    Process 46915 Stopped -
    1 of 3 threads stopped with reasons: -
    * thread #1: tid = 0x2c03, 0x00007fff85cac76a, where = libSystem.B.dylib`__getdirentries64 + 10, stop reason = signal = SIGSTOP, queue = com.apple.main-thread -
    - - -

    Note the line that says "1 of 3 threads stopped with reasons:" and the - lines that follow it. In a multi-threaded environment it is very - common for more than one thread to hit your breakpoint(s) before the - kernel actually returns control to the debugger. In that case, you - will see all the threads that stopped for some interesting reason - listed in the stop message.

    - -
    - - -
    -

    Controlling your Program

    -
    - - -

    After launching, we can continue until we hit our breakpoint. The primitive - commands for process control all exist under the "thread" command:

    - - - (lldb) thread continue -
    Resuming thread 0x2c03 in process 46915 -
    Resuming process 46915 -
    (lldb) -
    - -

    At present you can only operate on one thread at a time, but the - design will ultimately support saying "step over the function in - Thread 1, and step into the function in Thread 2, and continue Thread - 3" etc. When we eventually support keeping some threads running while - others are stopped this will be particularly important. For - convenience, however, all the stepping commands have easy aliases. - So "thread continue" is just "c", etc.

    - -

    The other program stepping commands are pretty much the same as in gdb. - You've got:

    - -
    (lldb) thread step-in    // The same as gdb's "step" or "s" 
    -(lldb) thread step-over  // The same as gdb's "next" or "n"
    -(lldb) thread step-out   // The same as gdb's "finish" or "f"
    -
    - -

    By default, lldb does defined aliases to all common gdb process control - commands ("s", "step", "n", "next", "finish"). - If we have missed any, please add them to your ~/.lldbinit file - using the "command alias" command. - -

    lldb also supported the step by instruction versions:

    -
    (lldb) thread step-inst       // The same as gdb's "stepi" / "si"
    -(lldb) thread step-over-inst  // The same as gdb's "nexti" / "ni"
    -
    - -

    Finally, lldb has a run until line or frame exit stepping mode:

    - - - (lldb) thread until 100 - - -

    This command will run the thread in the current frame till it reaches line 100 in - this frame or stops if it leaves the current frame. This is a pretty - close equivalent to gdb's "until" command.

    - -

    A process, by default, will shared the lldb terminal with the inferior - process. When in this mode, much like when debugging with gdb, when - the process is running anything you type will go to the STDIN of the - inferior process. To interrupt your inferior program, type CTRL+C.

    - -

    If you attach to a process, or launch a process with the "--no-stdin" - option, the command interpreter is always available to enter commands. This - might be a little disconcerting to gdb users when always have an (lldb) - prompt. This allows you to set a breakpoint, etc without having to explicitly interrupt - the program you are debugging:

    - - - (lldb) process continue -
    (lldb) breakpoint set --name stop_here -
    - -

    There are many commands that won't work while running, and the command - interpreter should do a good job of letting you know when this is the - case. If you find any instances where the command interpreter isn't - doing its job, please file a bug. This way of operation will set us - up for a future debugging mode called thread centric debugging. - This mode will allow us to run all threads and only stop the threads - that are at breakpoints or have exceptions or signals.

    - -

    The commands that currently work while running include - interrupting the process to halt execution ("process interrupt"), - getting the process status ("process status"), - breakpoint setting and clearing (" breakpoint [set|clear|enable|disable|list] ..."), - and memory reading and writing (" memory [read|write] ..."). -

    - -

    The question of disabling stdio when running brings up a good opportunity to - show how to set debugger properties in general. - If you always want to run in the --no-stdin mode, you can set this - as a generic process property using the lldb "settings&qout; command, - which is equivalent to gdb's "set" command. For instance, - in this case you would say:

    - - - (lldb) settings set target.process.disable-stdio true - - -

    Over time, gdb's "set command became a wilderness of disordered options, - so that there were useful options that even experienced gdb users didn't know about - because they were too hard to find. We tried to organize the settings hierarchically - using the structure of the basic entities in the debugger. For the most part anywhere - you can specify a setting on a generic entity (threads, for example) you can also apply - the option to a particular instance, which can also be convenient at times. - You can view the available settings with "settings list" and - there is help on the settings command explaining how it works more generally.

    - -
    - - -
    -

    Examining Thread State

    -
    - -

    Once you've stopped, lldb will choose a current thread, usually the - one that stopped "for a reason", and a current frame in that thread (on stop this is always the bottom-most frame). - Many the commands for inspecting state work on this current - thread/frame.

    - -

    To inspect the current state of your process, you can start with the - threads:

    - -
    (lldb) thread list
    -Process 46915 state is Stopped
    -* thread #1: tid = 0x2c03, 0x00007fff85cac76a, where = libSystem.B.dylib`__getdirentries64 + 10, stop reason = signal = SIGSTOP, queue = com.apple.main-thread
    -  thread #2: tid = 0x2e03, 0x00007fff85cbb08a, where = libSystem.B.dylib`kevent + 10, queue = com.apple.libdispatch-manager
    -  thread #3: tid = 0x2f03, 0x00007fff85cbbeaa, where = libSystem.B.dylib`__workq_kernreturn + 10
    -
    - -

    The * indicates that Thread 1 is the current thread. To get a - backtrace for that thread, do:

    - -
    (lldb) thread backtrace
    -thread #1: tid = 0x2c03, stop reason = breakpoint 1.1, queue = com.apple.main-thread
    - frame #0: 0x0000000100010d5b, where = Sketch`-[SKTGraphicView alignLeftEdges:] + 33 at /Projects/Sketch/SKTGraphicView.m:1405
    - frame #1: 0x00007fff8602d152, where = AppKit`-[NSApplication sendAction:to:from:] + 95
    - frame #2: 0x00007fff860516be, where = AppKit`-[NSMenuItem _corePerformAction] + 365
    - frame #3: 0x00007fff86051428, where = AppKit`-[NSCarbonMenuImpl performActionWithHighlightingForItemAtIndex:] + 121
    - frame #4: 0x00007fff860370c1, where = AppKit`-[NSMenu performKeyEquivalent:] + 272
    - frame #5: 0x00007fff86035e69, where = AppKit`-[NSApplication _handleKeyEquivalent:] + 559
    - frame #6: 0x00007fff85f06aa1, where = AppKit`-[NSApplication sendEvent:] + 3630
    - frame #7: 0x00007fff85e9d922, where = AppKit`-[NSApplication run] + 474
    - frame #8: 0x00007fff85e965f8, where = AppKit`NSApplicationMain + 364
    - frame #9: 0x0000000100015ae3, where = Sketch`main + 33 at /Projects/Sketch/SKTMain.m:11
    - frame #10: 0x0000000100000f20, where = Sketch`start + 52
    -
    - -

    You can also provide a list of threads to backtrace, or the keyword - "all" to see all threads:

    - - - (lldb) thread backtrace all - - -

    You can select the current thread, which will be used by default in all the commands in - the next section, with the "thread select" command:

    - - - (lldb) thread select 2 - - -

    where the thread index is just the one shown in the "thread list" listing. - -

    - - -
    -

    Examining Stack Frame State

    -
    - - -

    The most convenient way to inspect a frame's arguments and local variables is to use the "frame variable" command:

    - - - (lldb) frame variable -
    self = (SKTGraphicView *) 0x0000000100208b40 -
    _cmd = (struct objc_selector *) 0x000000010001bae1 -
    sender = (id) 0x00000001001264e0 -
    selection = (NSArray *) 0x00000001001264e0 -
    i = (NSUInteger) 0x00000001001264e0 -
    c = (NSUInteger) 0x00000001001253b0 -
    - -

    As you see above, if you don't specify any variable names, all arguments - and locals will be shown. If you call "frame variable" - passing in the names of a particular local(s), only those variables - will be printed. For instance: -

    - - - (lldb) frame variable self -
    (SKTGraphicView *) self = 0x0000000100208b40 -
    - -

    You can also pass in a path to some subelement of one of the available locals, - and that sub-element will be printed. For instance: -

    - - -
    (lldb) frame variable self.isa -
    (struct objc_class *) self.isa = 0x0000000100023730 -
    - -

    The "frame variable" command is not a full expression - parser but it does support a few simple operations like &, *, ->, [] (no overloaded - operators). The array brackets can be used on pointers to treat pointers - as arrays:

    - - - (lldb) frame variable *self -
    (SKTGraphicView *) self = 0x0000000100208b40 -
    (NSView) NSView = { -
    (NSResponder) NSResponder = { -
    ... -
    -
    (lldb) frame variable &self -
    (SKTGraphicView **) &self = 0x0000000100304ab -
    -
    (lldb) frame variable argv[0] -
    (char const *) argv[0] = 0x00007fff5fbffaf8 "/Projects/Sketch/build/Debug/Sketch.app/Contents/MacOS/Sketch" -
    - -

    The frame variable command will also perform "object printing" operations on - variables (currently we only support ObjC printing, using the object's "description" method. - Turn this on by passing the -o flag to frame variable:

    - - - (lldb) frame variable -o self - (SKTGraphicView *) self = 0x0000000100208b40 <SKTGraphicView: 0x100208b40> - - -

    You can select another frame to view with the "frame select" command

    - - - (lldb) frame select 9 -
    frame #9: 0x0000000100015ae3, where = Sketch`function1 + 33 at /Projects/Sketch/SKTFunctions.m:11 -
    - -

    You can also move up and down the stack by passing the "--relative" ("-r") - option. And we have built-in aliases "u" and "d" which - behave like their gdb equivalents. - -

    If you need to view more complex data or change program data, you can - use the general "expression" command. It takes an expression and - evaluates it in the scope of the currently selected frame. For instance:

    - - - (lldb) expr self -
    $0 = (SKTGraphicView *) 0x0000000100135430 -
    (lldb) expr self = 0x00 -
    $1 = (SKTGraphicView *) 0x0000000000000000 -
    (lldb) frame var self -
    (SKTGraphicView *) self = 0x0000000000000000 -
    - -

    You can also call functions:

    - - - (lldb) expr (int) printf ("I have a pointer 0x%llx.\n", self) -
    $2 = (int) 22 -
    I have a pointer 0x0. -
    - -

    As I said above, "expression" is one of the "raw" commands. So - you don't have to quote your whole expression, nor backslash protect quotes, - etc...

    - -

    Finally, the results of the expressions are stored in persistent variables - (of the form $[0-9]+) that you can use in further expressions, like:

    - - - (lldb) expr self = $0 -
    $4 = (SKTGraphicView *) 0x0000000100135430 -
    -

    -

    - - -
    -
    -
    -
    - - + + + + + +LLDB Tutorial + + + +
    + The LLDB Debugger +
    + +
    +
    + +
    +
    +

    Getting Started

    +
    + +

    Here's a short precis of how to run lldb if you are familiar with the gdb command set. + We will start with some details on lldb command structure and syntax to help orient you.

    + +
    + + +
    +

    Command Structure

    +
    + +

    Unlike gdb's command set, which is rather free-form, we tried to make + the lldb command syntax fairly structured. The commands are all of the + form:

    + + + <noun> <verb> [-options [option-value]] [argument [argument...]] + + +

    The command line parsing is done before command execution, so it is + uniform across all the commands. The command syntax for basic commands is very simple, + arguments, options and option values are all white-space + separated, and double-quotes are used to protect white-spaces in an argument. + If you need to put a backslash or double-quote character + in an argument you back-slash it in the argument. That makes the + command syntax more regular, but it also means you may have to + quote some arguments in lldb that you wouldn't in gdb.

    + +

    Options can be placed anywhere on the command line, but if the arguments + begin with a "-" then you have to tell lldb that you're done with options + for the current command by adding an option termination: "--" + So for instance if you want to launch a process and give the "process launch" command + the "--stop-at-entry" option, yet you want the + process you are about to launch to be launched with the arguments + "-program_arg value", you would type:

    + + + (lldb) process launch --stop-at-entry -- -program_arg value + + +

    We also tried to reduce the number of special purpose argument + parsers, which sometimes forces the user to be a little more explicit + about stating their intentions. The first instance you'll note of + this is the breakpoint command. In gdb, to set a breakpoint, you + might enter

    + + + (gdb) break foo.c:12 + +

    to break at line 12 of foo.c, and:

    + + (gdb) break foo + + +

    to break at the function foo. As time went on, the parser that tells foo.c:12 + from foo from foo.c::foo (which means the function foo in the file + foo.c) got more and more complex and bizarre, and especially in C++ + there are times where there's really no way to specify the function + you want to break on. The lldb commands are more verbose but also more precise + and allow for intellegent auto completion. + +

    To set the same file and line breakpoint in LLDB you can enter either of:

    + + + (lldb) breakpoint set --file foo.c --line 12 +
    (lldb) breakpoint set -f foo.c -l 12 +
    + +

    To set a breakpoint on a function named foo in LLDB you can enter either of:

    + + + (lldb) breakpoint set --name foo +
    (lldb) breakpoint set -n foo +
    + +

    You can use the --name option multiple times to make a breakpoint on a set of functions as well. This is convenient + since it allows you to set commmon conditions or commands without having to specify them multiple times:

    + + + (lldb) breakpoint set --name foo --name bar + + +

    Setting breakpoints by name is even more specialized in LLDB as you can specify + that you want to set a breakpoint at a function by method name. To set a breakpoint + on all C++ methods named foo you can enter either of:

    + + + (lldb) breakpoint set --method foo +
    (lldb) breakpoint set -M foo +
    + +

    To set a breakpoint Objective C selectors named alignLeftEdges: you can enter either of:

    + + + (lldb) breakpoint set --selector alignLeftEdges: +
    (lldb) breakpoint set -S alignLeftEdges: +
    + +

    You can limit any breakpoints to a specific executable image by using + the "--shlib <path>" ("-s <path>" for short):

    + + + (lldb) breakpoint set --shlib foo.dylib --name foo +
    (lldb) breakpoint set -s foo.dylib -n foo +
    + +

    The --shlib option can also be repeated to specify several shared libraries.

    + +

    Suggestions on more interesting primitives of this sort are also very welcome.

    + +

    Just like gdb, the lldb command interpreter does a shortest unique + string match on command names, so the following two commands will + both execute the same command:

    + + + (lldb) breakpoint set -n "-[SKTGraphicView alignLeftEdges:]" +
    (lldb) br s -n "-[SKTGraphicView alignLeftEdges:]" +
    + +

    lldb also supports command completion for source file names, symbol + names, file names, etc. Completion is initiated by a hitting a TAB. + Individual options in a command can have different completers, so for + instance the "--file <path>" option in "breakpoint" completes to source files, the + "--shlib <path>" option to currently loaded shared libraries, etc. We can even do + things like if you specify "--shlib <path>", and are completing on "--file <path>", we will only + list source files in the shared library specified by "--shlib <path>".

    + +

    The individual commands are pretty extensively documented. You can + use the help command to get an overview of which commands are + available or to obtain details about specific commands. There is also an + apropos command that will search the help text for all commands + for a particular word and dump a summary help string for each matching + command.

    + +

    Finally, there is a mechanism to construct aliases for commonly used + commands. So for instance if you get annoyed typing:

    + + + (lldb) breakpoint set --file foo.c --line 12 + + +

    you can do:

    + + + (lldb) command alias bfl breakpoint set -f %1 -l %2 +
    (lldb) bfl foo.c 12 +
    + +

    We have added a few aliases for commonly used commands (e.g. "step", + "next" and "continue") but we haven't tried to be exhaustive because + in our experience it is more convenient to make the basic commands + unique down to a letter or two, and then learn these sequences than + to fill the namespace with lots of aliases, and then have to type them + all the way out.

    + +

    However, users are free to customize lldb's command set however they + like, and since lldb reads the file ~/.lldbinit at startup, you can + store all your aliases there and they will be generally available to + you. Your aliases are also documented in the help command so you can + remind yourself of what you've set up.

    + +

    One alias of note that we do include by popular demand is a weak emulator + of gdb's "break" command. It doesn't try to do everything that gdb's + break command does (for instance, it doesn't handle foo.c::bar. But + it mostly works, and makes the transition easier. Also by popular demand, it + is aliased to b. If you actually want to learn the lldb command + set natively, that means it will get in the way of the rest of the breakpoint + commands. Fortunately, if you don't like one of our aliases, you an easily + get rid of it by running (for example):

    + + + (lldb) command unalias b + + +

    I actually also do:

    + + + (lldb) command alias b breakpoint + + +

    so I can run the native lldb breakpoint command with just b

    + +

    The lldb command parser also supports "raw" commands, where, after command options + are stripped off, the rest of the command string is passed uninterpreted to the command. + This is convenient for commands whose arguments might be some complex expression that would + be painful to backslash protect. + For instance the "expression" command is a "raw" command for obvious reasons. The + "help" output for a command will tell you if it is "raw" or not, so you know what to expect. + The one thing you have to watch out for is that since raw commands still can have options, + if your command string has dashes in it, you'll have to indicate these are not option + markers by putting "--" after the command name, but before your command string. + +

    lldb also has a built-in Python interpreter, which is accessible by + the "script" command. All the functionality of the debugger is + available as classes in the Python interpreter, so the more complex + commands that in gdb you would introduce with the "define" command can + be done by writing Python functions using the lldb-Python library, + then loading the scripts into your running session and accessing them + with the "script" command.

    + +

    Having given an overview of lldb's command syntax, we proceed to lay out the stages + of a standard debug session.

    + +
    + + + +
    +

    Loading a program into lldb

    +
    + +

    First we need to set the program to debug. As with gdb, you + can start lldb and specify the file you wish to debug on the command line:

    + + + $ lldb /Projects/Sketch/build/Debug/Sketch.app +
    Current executable set to '/Projects/Sketch/build/Debug/Sketch.app' (x86_64). +
    + +

    or you can specify it after the fact with the "file" command:

    + + + $ lldb +
    (lldb) file /Projects/Sketch/build/Debug/Sketch.app +
    Current executable set to '/Projects/Sketch/build/Debug/Sketch.app' (x86_64). +
    +

    +

    + + +
    +

    Setting breakpoints

    +
    + +

    We've discussed how to set breakpoints above. You can use help breakpoint set + to see all the options for breakpoint setting. For instance, we might do:

    + + + (lldb) breakpoint set --selector alignLeftEdges: +
    Breakpoint created: 1: name = 'alignLeftEdges:', locations = 1, resolved = 1 +
    + +

    You can find out about the breakpoints you've set with:

    + +
    (lldb) breakpoint list
    +Current breakpoints:
    +1: name = 'alignLeftEdges:', locations = 1, resolved = 1
    +  1.1: where = Sketch`-[SKTGraphicView alignLeftEdges:] + 33 at /Projects/Sketch/SKTGraphicView.m:1405, address = 0x0000000100010d5b, resolved, hit count = 0 
    +
    + +

    Note that setting a breakpoint creates a logical breakpoint, which could + resolve to one or more locations. For instance, break by selector would + set a breakpoint on all the methods that implement that selector in the classes in + your program. Similarly, a file and line breakpoint might result in multiple + locations if that file and line were inlined in different places in your code.

    + +

    The logical breakpoint has an integer id, and it's locations have an + id within their parent breakpoint (the two are joined by a ".", + e.g. 1.1 in the example above.)

    + +

    Also the logical breakpoints remain live so that if another shared library + were to be loaded that had another implementation of the + "alignLeftEdges:" selector, the new location would be added to + breakpoint 1 (e.g. a "1.2" breakpoint would be set on the newly loaded + selector).

    + +

    The other piece of information in the breakpoint listing is whether the + breakpoint location was resolved or not. A location gets resolved when + the file address it corresponds to gets loaded into the program you are + debugging. For instance if you set a breakpoint in a shared library that + then gets unloaded, that breakpoint location will remain, but it will no + longer be resolved.

    + +

    One other thing to note for gdb users is that lldb acts like gdb with:

    + + + (gdb) set breakpoint pending on + + +

    That is, lldb will always make a breakpoint from your specification, even + if it couldn't find any locations that match the specification. You can tell + whether the expression was resolved or not by checking the locations field + in "breakpoint list", and we report the breakpoint as "pending" when you + set it so you can tell you've made a typo more easily, if that was indeed + the reason no locations were found:

    + + + (lldb) breakpoint set --file foo.c --line 12 +
    Breakpoint created: 2: file ='foo.c', line = 12, locations = 0 (pending) +
    WARNING: Unable to resolve breakpoint to any actual locations. +
    + +

    You can delete, disable, set conditions and ignore counts either on all the + locations generated by your logical breakpoint, or on any one of the particular locations + your specification resolved to. For instance if we wanted to add a command + to print a backtrace when we hit this breakpoint we could do:

    + + + (lldb) breakpoint command add 1.1 +
    Enter your debugger command(s). Type 'DONE' to end. +
    > bt +
    > DONE +
    + +

    By default, the breakpoint command add command takes lldb command line commands. + You can also specify this explicitly by passing the "--command" option. + Use "--script" if you want to implement your breakpoint command using the Python script instead.

    + +

    This is an convenient point to bring up another feature of the lldb command help. Do:

    + + + (lldb) help break command add +
    Add a set of commands to a breakpoint, to be executed whenever the breakpoint is hit. +
    +
    Syntax: breakpoint command add <cmd-options> <breakpt-id> +
    etc... +
    + +

    When you see arguments to commands specified in the Syntax in angle + brackets like <breakpt-id>, that indicates that + that is some common argument type that you can get further help on from the command system. + So in this case you could do:

    + + + (lldb) help <breakpt-id> +
    <breakpt-id> -- Breakpoint ID's consist major and minor numbers; the major +
    etc... +
    + +
    + + +
    +

    Setting watchpoints

    +
    + +

    In addition to breakpoints, you can use help watchpoint + to see all the commands for watchpoint manipulations. For instance, we might do the following to watch + a variable called 'global' for write operation, but only stop if the condition '(global==5)' is true:

    + +
    (lldb) watch set var global
    +Watchpoint created: Watchpoint 1: addr = 0x100001018 size = 4 state = enabled type = w
    +    declare @ '/Volumes/data/lldb/svn/ToT/test/functionalities/watchpoint/watchpoint_commands/condition/main.cpp:12'
    +(lldb) watch modify -c '(global==5)'
    +(lldb) watch list
    +Current watchpoints:
    +Watchpoint 1: addr = 0x100001018 size = 4 state = enabled type = w
    +    declare @ '/Volumes/data/lldb/svn/ToT/test/functionalities/watchpoint/watchpoint_commands/condition/main.cpp:12'
    +    condition = '(global==5)'
    +(lldb) c
    +Process 15562 resuming
    +(lldb) about to write to 'global'...
    +Process 15562 stopped and was programmatically restarted.
    +Process 15562 stopped and was programmatically restarted.
    +Process 15562 stopped and was programmatically restarted.
    +Process 15562 stopped and was programmatically restarted.
    +Process 15562 stopped
    +* thread #1: tid = 0x1c03, 0x0000000100000ef5 a.out`modify + 21 at main.cpp:16, stop reason = watchpoint 1
    +    frame #0: 0x0000000100000ef5 a.out`modify + 21 at main.cpp:16
    +   13  	
    +   14  	static void modify(int32_t &var) {
    +   15  	    ++var;
    +-> 16  	}
    +   17  	
    +   18  	int main(int argc, char** argv) {
    +   19  	    int local = 0;
    +(lldb) bt
    +* thread #1: tid = 0x1c03, 0x0000000100000ef5 a.out`modify + 21 at main.cpp:16, stop reason = watchpoint 1
    +    frame #0: 0x0000000100000ef5 a.out`modify + 21 at main.cpp:16
    +    frame #1: 0x0000000100000eac a.out`main + 108 at main.cpp:25
    +    frame #2: 0x00007fff8ac9c7e1 libdyld.dylib`start + 1
    +(lldb) frame var global
    +(int32_t) global = 5
    +(lldb) watch list -v
    +Current watchpoints:
    +Watchpoint 1: addr = 0x100001018 size = 4 state = enabled type = w
    +    declare @ '/Volumes/data/lldb/svn/ToT/test/functionalities/watchpoint/watchpoint_commands/condition/main.cpp:12'
    +    condition = '(global==5)'
    +    hw_index = 0  hit_count = 5     ignore_count = 0   
    +(lldb) 
    +
    + + +
    +

    Starting or attaching to your Program

    +
    + +

    To launch a program in lldb we use the "process launch" command or + one of its built in aliases:

    + + + (lldb) process launch +
    (lldb) run +
    (lldb) r +
    + +

    You can also attach to a process by process ID or process name. + When attaching to a process by name, lldb also supports the "--waitfor" option which waits for the + next process that has that name to show up, and attaches to it

    + + + (lldb) process attach --pid 123 +
    (lldb) process attach --name Sketch +
    (lldb) process attach --name Sketch --waitfor +
    + +

    After you launch or attach to a process, your process might stop + somewhere:

    + + (lldb) process attach -p 12345 +
    Process 46915 Attaching +
    Process 46915 Stopped +
    1 of 3 threads stopped with reasons: +
    * thread #1: tid = 0x2c03, 0x00007fff85cac76a, where = libSystem.B.dylib`__getdirentries64 + 10, stop reason = signal = SIGSTOP, queue = com.apple.main-thread +
    + + +

    Note the line that says "1 of 3 threads stopped with reasons:" and the + lines that follow it. In a multi-threaded environment it is very + common for more than one thread to hit your breakpoint(s) before the + kernel actually returns control to the debugger. In that case, you + will see all the threads that stopped for some interesting reason + listed in the stop message.

    + +
    + + +
    +

    Controlling your Program

    +
    + + +

    After launching, we can continue until we hit our breakpoint. The primitive + commands for process control all exist under the "thread" command:

    + + + (lldb) thread continue +
    Resuming thread 0x2c03 in process 46915 +
    Resuming process 46915 +
    (lldb) +
    + +

    At present you can only operate on one thread at a time, but the + design will ultimately support saying "step over the function in + Thread 1, and step into the function in Thread 2, and continue Thread + 3" etc. When we eventually support keeping some threads running while + others are stopped this will be particularly important. For + convenience, however, all the stepping commands have easy aliases. + So "thread continue" is just "c", etc.

    + +

    The other program stepping commands are pretty much the same as in gdb. + You've got:

    + +
    (lldb) thread step-in    // The same as gdb's "step" or "s" 
    +(lldb) thread step-over  // The same as gdb's "next" or "n"
    +(lldb) thread step-out   // The same as gdb's "finish" or "f"
    +
    + +

    By default, lldb does defined aliases to all common gdb process control + commands ("s", "step", "n", "next", "finish"). + If we have missed any, please add them to your ~/.lldbinit file + using the "command alias" command. + +

    lldb also supported the step by instruction versions:

    +
    (lldb) thread step-inst       // The same as gdb's "stepi" / "si"
    +(lldb) thread step-over-inst  // The same as gdb's "nexti" / "ni"
    +
    + +

    Finally, lldb has a run until line or frame exit stepping mode:

    + + + (lldb) thread until 100 + + +

    This command will run the thread in the current frame till it reaches line 100 in + this frame or stops if it leaves the current frame. This is a pretty + close equivalent to gdb's "until" command.

    + +

    A process, by default, will shared the lldb terminal with the inferior + process. When in this mode, much like when debugging with gdb, when + the process is running anything you type will go to the STDIN of the + inferior process. To interrupt your inferior program, type CTRL+C.

    + +

    If you attach to a process, or launch a process with the "--no-stdin" + option, the command interpreter is always available to enter commands. This + might be a little disconcerting to gdb users when always have an (lldb) + prompt. This allows you to set a breakpoint, etc without having to explicitly interrupt + the program you are debugging:

    + + + (lldb) process continue +
    (lldb) breakpoint set --name stop_here +
    + +

    There are many commands that won't work while running, and the command + interpreter should do a good job of letting you know when this is the + case. If you find any instances where the command interpreter isn't + doing its job, please file a bug. This way of operation will set us + up for a future debugging mode called thread centric debugging. + This mode will allow us to run all threads and only stop the threads + that are at breakpoints or have exceptions or signals.

    + +

    The commands that currently work while running include + interrupting the process to halt execution ("process interrupt"), + getting the process status ("process status"), + breakpoint setting and clearing (" breakpoint [set|clear|enable|disable|list] ..."), + and memory reading and writing (" memory [read|write] ..."). +

    + +

    The question of disabling stdio when running brings up a good opportunity to + show how to set debugger properties in general. + If you always want to run in the --no-stdin mode, you can set this + as a generic process property using the lldb "settings&qout; command, + which is equivalent to gdb's "set" command. For instance, + in this case you would say:

    + + + (lldb) settings set target.process.disable-stdio true + + +

    Over time, gdb's "set command became a wilderness of disordered options, + so that there were useful options that even experienced gdb users didn't know about + because they were too hard to find. We tried to organize the settings hierarchically + using the structure of the basic entities in the debugger. For the most part anywhere + you can specify a setting on a generic entity (threads, for example) you can also apply + the option to a particular instance, which can also be convenient at times. + You can view the available settings with "settings list" and + there is help on the settings command explaining how it works more generally.

    + +
    + + +
    +

    Examining Thread State

    +
    + +

    Once you've stopped, lldb will choose a current thread, usually the + one that stopped "for a reason", and a current frame in that thread (on stop this is always the bottom-most frame). + Many the commands for inspecting state work on this current + thread/frame.

    + +

    To inspect the current state of your process, you can start with the + threads:

    + +
    (lldb) thread list
    +Process 46915 state is Stopped
    +* thread #1: tid = 0x2c03, 0x00007fff85cac76a, where = libSystem.B.dylib`__getdirentries64 + 10, stop reason = signal = SIGSTOP, queue = com.apple.main-thread
    +  thread #2: tid = 0x2e03, 0x00007fff85cbb08a, where = libSystem.B.dylib`kevent + 10, queue = com.apple.libdispatch-manager
    +  thread #3: tid = 0x2f03, 0x00007fff85cbbeaa, where = libSystem.B.dylib`__workq_kernreturn + 10
    +
    + +

    The * indicates that Thread 1 is the current thread. To get a + backtrace for that thread, do:

    + +
    (lldb) thread backtrace
    +thread #1: tid = 0x2c03, stop reason = breakpoint 1.1, queue = com.apple.main-thread
    + frame #0: 0x0000000100010d5b, where = Sketch`-[SKTGraphicView alignLeftEdges:] + 33 at /Projects/Sketch/SKTGraphicView.m:1405
    + frame #1: 0x00007fff8602d152, where = AppKit`-[NSApplication sendAction:to:from:] + 95
    + frame #2: 0x00007fff860516be, where = AppKit`-[NSMenuItem _corePerformAction] + 365
    + frame #3: 0x00007fff86051428, where = AppKit`-[NSCarbonMenuImpl performActionWithHighlightingForItemAtIndex:] + 121
    + frame #4: 0x00007fff860370c1, where = AppKit`-[NSMenu performKeyEquivalent:] + 272
    + frame #5: 0x00007fff86035e69, where = AppKit`-[NSApplication _handleKeyEquivalent:] + 559
    + frame #6: 0x00007fff85f06aa1, where = AppKit`-[NSApplication sendEvent:] + 3630
    + frame #7: 0x00007fff85e9d922, where = AppKit`-[NSApplication run] + 474
    + frame #8: 0x00007fff85e965f8, where = AppKit`NSApplicationMain + 364
    + frame #9: 0x0000000100015ae3, where = Sketch`main + 33 at /Projects/Sketch/SKTMain.m:11
    + frame #10: 0x0000000100000f20, where = Sketch`start + 52
    +
    + +

    You can also provide a list of threads to backtrace, or the keyword + "all" to see all threads:

    + + + (lldb) thread backtrace all + + +

    You can select the current thread, which will be used by default in all the commands in + the next section, with the "thread select" command:

    + + + (lldb) thread select 2 + + +

    where the thread index is just the one shown in the "thread list" listing. + +

    + + +
    +

    Examining Stack Frame State

    +
    + + +

    The most convenient way to inspect a frame's arguments and local variables is to use the "frame variable" command:

    + + + (lldb) frame variable +
    self = (SKTGraphicView *) 0x0000000100208b40 +
    _cmd = (struct objc_selector *) 0x000000010001bae1 +
    sender = (id) 0x00000001001264e0 +
    selection = (NSArray *) 0x00000001001264e0 +
    i = (NSUInteger) 0x00000001001264e0 +
    c = (NSUInteger) 0x00000001001253b0 +
    + +

    As you see above, if you don't specify any variable names, all arguments + and locals will be shown. If you call "frame variable" + passing in the names of a particular local(s), only those variables + will be printed. For instance: +

    + + + (lldb) frame variable self +
    (SKTGraphicView *) self = 0x0000000100208b40 +
    + +

    You can also pass in a path to some subelement of one of the available locals, + and that sub-element will be printed. For instance: +

    + + +
    (lldb) frame variable self.isa +
    (struct objc_class *) self.isa = 0x0000000100023730 +
    + +

    The "frame variable" command is not a full expression + parser but it does support a few simple operations like &, *, ->, [] (no overloaded + operators). The array brackets can be used on pointers to treat pointers + as arrays:

    + + + (lldb) frame variable *self +
    (SKTGraphicView *) self = 0x0000000100208b40 +
    (NSView) NSView = { +
    (NSResponder) NSResponder = { +
    ... +
    +
    (lldb) frame variable &self +
    (SKTGraphicView **) &self = 0x0000000100304ab +
    +
    (lldb) frame variable argv[0] +
    (char const *) argv[0] = 0x00007fff5fbffaf8 "/Projects/Sketch/build/Debug/Sketch.app/Contents/MacOS/Sketch" +
    + +

    The frame variable command will also perform "object printing" operations on + variables (currently we only support ObjC printing, using the object's "description" method. + Turn this on by passing the -o flag to frame variable:

    + + + (lldb) frame variable -o self + (SKTGraphicView *) self = 0x0000000100208b40 <SKTGraphicView: 0x100208b40> + + +

    You can select another frame to view with the "frame select" command

    + + + (lldb) frame select 9 +
    frame #9: 0x0000000100015ae3, where = Sketch`function1 + 33 at /Projects/Sketch/SKTFunctions.m:11 +
    + +

    You can also move up and down the stack by passing the "--relative" ("-r") + option. And we have built-in aliases "u" and "d" which + behave like their gdb equivalents. + +

    If you need to view more complex data or change program data, you can + use the general "expression" command. It takes an expression and + evaluates it in the scope of the currently selected frame. For instance:

    + + + (lldb) expr self +
    $0 = (SKTGraphicView *) 0x0000000100135430 +
    (lldb) expr self = 0x00 +
    $1 = (SKTGraphicView *) 0x0000000000000000 +
    (lldb) frame var self +
    (SKTGraphicView *) self = 0x0000000000000000 +
    + +

    You can also call functions:

    + + + (lldb) expr (int) printf ("I have a pointer 0x%llx.\n", self) +
    $2 = (int) 22 +
    I have a pointer 0x0. +
    + +

    As I said above, "expression" is one of the "raw" commands. So + you don't have to quote your whole expression, nor backslash protect quotes, + etc...

    + +

    Finally, the results of the expressions are stored in persistent variables + (of the form $[0-9]+) that you can use in further expressions, like:

    + + + (lldb) expr self = $0 +
    $4 = (SKTGraphicView *) 0x0000000100135430 +
    +

    +

    + + +
    +
    +
    +
    + +