diff options
author | Joerg Sonnenberger <joerg@bec.de> | 2013-09-25 10:37:32 +0000 |
---|---|---|
committer | Joerg Sonnenberger <joerg@bec.de> | 2013-09-25 10:37:32 +0000 |
commit | 340a17595eaaadc3dcb481ae9282830fb50454bd (patch) | |
tree | 4cf7be649a6dd21472719ad67879a7b0bbfb65c0 | |
parent | f348f831d5dd35c419308f63ad2cab498c16dc64 (diff) | |
download | bcm5719-llvm-340a17595eaaadc3dcb481ae9282830fb50454bd.tar.gz bcm5719-llvm-340a17595eaaadc3dcb481ae9282830fb50454bd.zip |
Convert to UNIX line endings.
llvm-svn: 191367
78 files changed, 6276 insertions, 6276 deletions
diff --git a/lldb/CMakeLists.txt b/lldb/CMakeLists.txt index b73f87635dc..d49d2a3c9f3 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 444b9c3e395..cd133cfa8a2 100644 --- a/lldb/scripts/Python/python-wrapper.swig +++ b/lldb/scripts/Python/python-wrapper.swig @@ -1,998 +1,998 @@ -%header %{
-
-template <typename T>
-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<typename ...Args>
- PyObject*
- operator () (Args... args)
- {
- return (*this)({SBTypeToSWIGWrapper(args)...});
- }
-
- PyObject*
- operator () (std::initializer_list<PyObject*> 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<PyObject*>(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<size_t>(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<PyObject*>(baton), const_cast<char*>("s"), str);
- SWIG_PYTHON_THREAD_END_BLOCK;
- }
-}
-%}
+%header %{ + +template <typename T> +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<typename ...Args> + PyObject* + operator () (Args... args) + { + return (*this)({SBTypeToSWIGWrapper(args)...}); + } + + PyObject* + operator () (std::initializer_list<PyObject*> 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<PyObject*>(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<size_t>(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<PyObject*>(baton), const_cast<char*>("s"), str); + SWIG_PYTHON_THREAD_END_BLOCK; + } +} +%} diff --git a/lldb/source/API/CMakeLists.txt b/lldb/source/API/CMakeLists.txt index 2170c9a62f2..ef70ad593b7 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 e3e0c90069c..fc40aea74ed 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 2a1292a80d1..d928c30bc6b 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 48382ffcb72..1f287d57243 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 165fb1de640..eeca58ca0b9 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 b9857fc6c8b..cd3c1dd6c42 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 a6ac9101347..100fc69e36c 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 6c92a6cde26..d203d0b2847 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 8cc7e3c03c0..443b983cb6d 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 b98c410b43c..535b47fa5f2 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 95e02ec985a..27597fc3c3e 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 c6316e03a49..5d4fb5ce337 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 9dfc2ca9ca6..6b613d5bb16 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 d2a5f5ad22f..dbfff7b1534 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 090724877af..680f7e546ef 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 7e19b3f788e..a1b515af29f 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 dd2113b2a68..6e3c904d5a6 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 f82627a809d..7b1d56c389b 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 88e6e0c931b..c14740d0537 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 6db034d24d7..1facabe9012 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 c78dc037c66..3546b6908e2 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 4dc3456c98c..ee680382dbf 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 3c0b519982e..244079a5eee 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 7089b8394e1..08ccb8ec644 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 69a7cea6ab4..3eef5f4922e 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 72694dce7e6..034ae1545ae 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 4fdf10313c5..26c68c60b01 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 013663073a6..622f1f7d11c 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 d0c0181899c..7fdd3004d1d 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 e4ce578b220..af13dc6a144 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 f206cdb477b..deef023522d 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 2a06774dd2c..5dcef91f07d 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 7d0aef87f74..361a23411a1 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 14861ab99a3..f59a242eb49 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 073c47e1a8a..ef05dcb3fd5 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 aac97135da1..06ea8317983 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 f704665dd0f..1fb6bfa3ded 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 9b07304806c..655007a0aab 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 3576d86bceb..85869009a8a 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 bce7ac0d840..ab4ad430ff9 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 6802d2e8029..4b162fc7e4d 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 e46021ce0a8..dcd2441c7c1 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 5d8986ec5d4..96fc57fafcb 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 85e7129de43..add6697389f 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 987111c98ca..6464dc3fa8b 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 00252ffeeb4..eb7aed8403c 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 9f5c6311b22..94862d58872 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 2401b76a342..9fa601697d5 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 6a0040f2674..a17150ffbf9 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 c4a972991fb..1723a060458 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 6003672711a..b07a30bed61 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 bb0ffad0bba..2f81fc89ae6 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 9386bd1f4a6..96b5c4baf3b 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 383e6db42cc..29f9bcddc42 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 64b17871fb0..19dcde5930b 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 b1989f81551..3f3a490d4ad 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 c70a2dba699..bbd792a3818 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 97ccde10199..f3c70a7000c 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 98b91b264b8..473ef800f97 100755 --- a/lldb/www/architecture.html +++ b/lldb/www/architecture.html @@ -1,282 +1,282 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
-<link href="style.css" rel="stylesheet" type="text/css" />
-<title>LLDB Architecture</title>
-</head>
-
-<body>
- <div class="www_title">
- The <strong>LLDB</strong> Debugger
- </div>
-
-<div id="container">
- <div id="content">
-
- <!--#include virtual="sidebar.incl"-->
-
- <div id="middle">
- <div class="post">
- <h1 class ="postheader">Architecture</h1>
- <div class="postcontent">
-
- <p>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.</p>
- </div>
- <div class="postfooter"></div>
- </div>
- <div class="post">
- <h1 class ="postheader">Code Layout</h1>
- <div class="postcontent">
-
- <p>LLDB has many code groupings that makeup the source base:</p>
- <ul>
- <li><a href="#api">API</a></li>
- <li><a href="#breakpoint">Breakpoint</a></li>
- <li><a href="#commands">Commands</a></li>
- <li><a href="#core">Core</a></li>
- <li><a href="#dataformatters">DataFormatters</a></li>
- <li><a href="#expression">Expression</a></li>
- <li><a href="#host">Host</a></li>
- <li><a href="#interpreter">Interpreter</a></li>
- <li><a href="#symbol">Symbol</a></li>
- <li><a href="#targ">Target</a></li>
- <li><a href="#utility">Utility</a></li>
- </ul>
- </div>
- <div class="postfooter"></div>
- </div>
- <a name="api"></a>
- <div class="post">
- <h1 class ="postheader">API</h1>
- <div class="postcontent">
-
- <p>The API folder contains the public interface to LLDB.</p>
- <p>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:</p>
- <ul>
- <li>Classes can't inherit from any other classes.</li>
- <li>Classes can't contain virtual methods.</li>
- <li>Classes should be compatible with script bridging utilities like <a href="http://www.swig.org/">swig</a>.</li>
- <li>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.</li>
- <li>The interface should be as minimal as possible in order to give a complete API.</li>
- </ul>
- <p>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).</p>
- </div>
- <div class="postfooter"></div>
- </div>
- <a name="breakpoint"></a>
- <div class="post">
- <h1 class ="postheader">Breakpoint</h1>
- <div class="postcontent">
-
- <p>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.</p>
- <p>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.</p>
- </div>
- <div class="postfooter"></div>
- </div>
- <a name="commands"></a>
- <div class="post">
- <h1 class ="postheader">Commands</h1>
- <div class="postcontent">
-
- <p>The command source files represent objects that implement
- the functionality for all textual commands available
- in our command line interface.</p>
- <p>Every command is backed by a <b>lldb_private::CommandObject</b>
- or <b>lldb_private::CommandObjectMultiword</b> object.</p>
- <p><b>lldb_private::CommandObjectMultiword</b> are commands that
- have subcommands and allow command line commands to be
- logically grouped into a hierarchy.</p>
- <p><b>lldb_private::CommandObject</b> 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.</p>
- </div>
- <div class="postfooter"></div>
- </div>
- <a name="core"></a>
- <div class="post">
- <h1 class ="postheader">Core</h1>
- <div class="postcontent">
-
- <p>The Core source files contain basic functionality that
- is required in the debugger. A wide variety of classes
- are implemented:</p>
-
- <ul>
- <li>Address (section offset addressing)</li>
- <li>AddressRange</li>
- <li>Architecture specification</li>
- <li>Broadcaster / Event / Listener </li>
- <li>Communication classes that use Connection objects</li>
- <li>Uniqued C strings</li>
- <li>Data extraction</li>
- <li>File specifications</li>
- <li>Mangled names</li>
- <li>Regular expressions</li>
- <li>Source manager</li>
- <li>Streams</li>
- <li>Value objects</li>
- </ul>
- </div>
- <div class="postfooter"></div>
- </div>
- <a name="dataformatters"></a>
- <div class="post">
- <h1 class ="postheader">DataFormatters</h1>
- <div class="postcontent">
-
- <p>A collection of classes that implement the data formatters subsystem.</p>
- <p>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.</p>
- <p>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.
- </p>
- <p>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.
- </div>
- <div class="postfooter"></div>
- </div>
- <a name="expression"></a>
- <div class="post">
- <h1 class ="postheader">Expression</h1>
- <div class="postcontent">
-
- <p>Expression parsing files cover everything from evaluating
- DWARF expressions, to evaluating expressions using
- Clang.</p>
- <p>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).</p>
- <p>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.</p>
- </div>
- <div class="postfooter"></div>
- </div>
- <a name="host"></a>
- <div class="post">
- <h1 class ="postheader">Host</h1>
- <div class="postcontent">
-
- <p>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.</p>
- <p>Host functionality includes abstraction layers for:</p>
- <ul>
- <li>Mutexes</li>
- <li>Conditions</li>
- <li>Timing functions</li>
- <li>Thread functions</li>
- <li>Host target triple</li>
- <li>Host child process notifications</li>
- <li>Host specific types</li>
- </ul>
- </div>
- <div class="postfooter"></div>
- </div>
- <a name="interpreter"></a>
- <div class="post">
- <h1 class ="postheader">Interpreter</h1>
- <div class="postcontent">
-
- <p>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.</p>
- </div>
- <div class="postfooter"></div>
- </div>
- <a name="symbol"></a>
- <div class="post">
- <h1 class ="postheader">Symbol</h1>
- <div class="postcontent">
- <p>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.</p>
- </div>
- <div class="postfooter"></div>
- </div>
- <a name="targ"></a>
- <div class="post">
- <h1 class ="postheader">Target</h1>
- <div class="postcontent">
-
- <p>Classes that are related to a debug target include:</p>
- <ul>
- <li>Target</li>
- <li>Process</li>
- <li>Thread</li>
- <li>Stack frames</li>
- <li>Stack frame registers</li>
- <li>ABI for function calling in process being debugged</li>
- <li>Execution context batons</li>
- </ul>
- </div>
- <div class="postfooter"></div>
- </div>
- <a name="utility"></a>
- <div class="post">
- <h1 class ="postheader">Utility</h1>
- <div class="postcontent">
-
- <p>Utility files should be as stand alone as possible and
- available for LLDB, plug-ins or related
- applications to use.</p>
- <p>Files found in the Utility section include:</p>
- <ul>
- <li>Pseudo-terminal support</li>
- <li>Register numbering for specific architectures.</li>
- <li>String data extractors</li>
- </ul>
- </div>
- <div class="postfooter"></div>
- </div>
- </div>
- </div>
-</div>
-</body>
-</html>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> +<link href="style.css" rel="stylesheet" type="text/css" /> +<title>LLDB Architecture</title> +</head> + +<body> + <div class="www_title"> + The <strong>LLDB</strong> Debugger + </div> + +<div id="container"> + <div id="content"> + + <!--#include virtual="sidebar.incl"--> + + <div id="middle"> + <div class="post"> + <h1 class ="postheader">Architecture</h1> + <div class="postcontent"> + + <p>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.</p> + </div> + <div class="postfooter"></div> + </div> + <div class="post"> + <h1 class ="postheader">Code Layout</h1> + <div class="postcontent"> + + <p>LLDB has many code groupings that makeup the source base:</p> + <ul> + <li><a href="#api">API</a></li> + <li><a href="#breakpoint">Breakpoint</a></li> + <li><a href="#commands">Commands</a></li> + <li><a href="#core">Core</a></li> + <li><a href="#dataformatters">DataFormatters</a></li> + <li><a href="#expression">Expression</a></li> + <li><a href="#host">Host</a></li> + <li><a href="#interpreter">Interpreter</a></li> + <li><a href="#symbol">Symbol</a></li> + <li><a href="#targ">Target</a></li> + <li><a href="#utility">Utility</a></li> + </ul> + </div> + <div class="postfooter"></div> + </div> + <a name="api"></a> + <div class="post"> + <h1 class ="postheader">API</h1> + <div class="postcontent"> + + <p>The API folder contains the public interface to LLDB.</p> + <p>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:</p> + <ul> + <li>Classes can't inherit from any other classes.</li> + <li>Classes can't contain virtual methods.</li> + <li>Classes should be compatible with script bridging utilities like <a href="http://www.swig.org/">swig</a>.</li> + <li>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.</li> + <li>The interface should be as minimal as possible in order to give a complete API.</li> + </ul> + <p>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).</p> + </div> + <div class="postfooter"></div> + </div> + <a name="breakpoint"></a> + <div class="post"> + <h1 class ="postheader">Breakpoint</h1> + <div class="postcontent"> + + <p>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.</p> + <p>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.</p> + </div> + <div class="postfooter"></div> + </div> + <a name="commands"></a> + <div class="post"> + <h1 class ="postheader">Commands</h1> + <div class="postcontent"> + + <p>The command source files represent objects that implement + the functionality for all textual commands available + in our command line interface.</p> + <p>Every command is backed by a <b>lldb_private::CommandObject</b> + or <b>lldb_private::CommandObjectMultiword</b> object.</p> + <p><b>lldb_private::CommandObjectMultiword</b> are commands that + have subcommands and allow command line commands to be + logically grouped into a hierarchy.</p> + <p><b>lldb_private::CommandObject</b> 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.</p> + </div> + <div class="postfooter"></div> + </div> + <a name="core"></a> + <div class="post"> + <h1 class ="postheader">Core</h1> + <div class="postcontent"> + + <p>The Core source files contain basic functionality that + is required in the debugger. A wide variety of classes + are implemented:</p> + + <ul> + <li>Address (section offset addressing)</li> + <li>AddressRange</li> + <li>Architecture specification</li> + <li>Broadcaster / Event / Listener </li> + <li>Communication classes that use Connection objects</li> + <li>Uniqued C strings</li> + <li>Data extraction</li> + <li>File specifications</li> + <li>Mangled names</li> + <li>Regular expressions</li> + <li>Source manager</li> + <li>Streams</li> + <li>Value objects</li> + </ul> + </div> + <div class="postfooter"></div> + </div> + <a name="dataformatters"></a> + <div class="post"> + <h1 class ="postheader">DataFormatters</h1> + <div class="postcontent"> + + <p>A collection of classes that implement the data formatters subsystem.</p> + <p>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.</p> + <p>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. + </p> + <p>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. + </div> + <div class="postfooter"></div> + </div> + <a name="expression"></a> + <div class="post"> + <h1 class ="postheader">Expression</h1> + <div class="postcontent"> + + <p>Expression parsing files cover everything from evaluating + DWARF expressions, to evaluating expressions using + Clang.</p> + <p>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).</p> + <p>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.</p> + </div> + <div class="postfooter"></div> + </div> + <a name="host"></a> + <div class="post"> + <h1 class ="postheader">Host</h1> + <div class="postcontent"> + + <p>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.</p> + <p>Host functionality includes abstraction layers for:</p> + <ul> + <li>Mutexes</li> + <li>Conditions</li> + <li>Timing functions</li> + <li>Thread functions</li> + <li>Host target triple</li> + <li>Host child process notifications</li> + <li>Host specific types</li> + </ul> + </div> + <div class="postfooter"></div> + </div> + <a name="interpreter"></a> + <div class="post"> + <h1 class ="postheader">Interpreter</h1> + <div class="postcontent"> + + <p>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.</p> + </div> + <div class="postfooter"></div> + </div> + <a name="symbol"></a> + <div class="post"> + <h1 class ="postheader">Symbol</h1> + <div class="postcontent"> + <p>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.</p> + </div> + <div class="postfooter"></div> + </div> + <a name="targ"></a> + <div class="post"> + <h1 class ="postheader">Target</h1> + <div class="postcontent"> + + <p>Classes that are related to a debug target include:</p> + <ul> + <li>Target</li> + <li>Process</li> + <li>Thread</li> + <li>Stack frames</li> + <li>Stack frame registers</li> + <li>ABI for function calling in process being debugged</li> + <li>Execution context batons</li> + </ul> + </div> + <div class="postfooter"></div> + </div> + <a name="utility"></a> + <div class="post"> + <h1 class ="postheader">Utility</h1> + <div class="postcontent"> + + <p>Utility files should be as stand alone as possible and + available for LLDB, plug-ins or related + applications to use.</p> + <p>Files found in the Utility section include:</p> + <ul> + <li>Pseudo-terminal support</li> + <li>Register numbering for specific architectures.</li> + <li>String data extractors</li> + </ul> + </div> + <div class="postfooter"></div> + </div> + </div> + </div> +</div> +</body> +</html> diff --git a/lldb/www/build.html b/lldb/www/build.html index e545b1198a4..755e608ee7d 100755 --- a/lldb/www/build.html +++ b/lldb/www/build.html @@ -1,241 +1,241 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
-<link href="style.css" rel="stylesheet" type="text/css" />
-<title>Building LLDB</title>
-</head>
-
-<body>
- <div class="www_title">
- The <strong>LLDB</strong> Debugger
- </div>
-
-<div id="container">
- <div id="content">
-
- <!--#include virtual="sidebar.incl"-->
-
- <div id="middle">
- <h1 class ="postheader">Continuous Integraton</h1>
- <div class="postcontent">
- <p> The following LLVM buildbots build and test LLDB trunk:
- <ul>
- <li> <a href="http://lab.llvm.org:8011/builders/lldb-x86_64-debian-clang">LLDB Linux x86_64 build with Clang (automake)</a>
- <li> <a href="http://lab.llvm.org:8011/builders/lldb-x86_64-linux">LLDB Linux x86_64 build with GCC 4.6 (automake)</a>
- <li> <a href="http://lab.llvm.org:8011/builders/lldb-x86_64-darwin11">LLDB Mac OS X x86_64 build with Clang (XCode)</a>
- <li> <a href="http://llvm-amd64.freebsd.your.org:8010/builders/lldb-amd64-freebsd">LLDB FreeBSD x86_64</a>
- <li> <a href="http://llvm-amd64.freebsd.your.org:8010/builders/lldb-i386-freebsd">LLDB FreeBSD i386</a>
- </ul>
- </div>
- <div class="postfooter"></div>
- <div class="post">
- <h1 class ="postheader">Building LLDB on Mac OS X</h1>
- <div class="postcontent">
- <p>Building on Mac OS X is as easy as downloading the code and building the Xcode project or workspace:</p>
- </div>
- <div class="postcontent">
- <h2>Preliminaries</h2>
- <ul>
- <li>XCode 4.3 or newer requires the "Command Line Tools" component (XCode->Preferences->Downloads->Components).</li>
- <li>Mac OS X Lion or newer requires installing <a href="http://swig.org">Swig</a>.</li>
- </ul>
- <h2>Building LLDB</h2>
- <ul>
- <li><a href="download.html">Download</a> the lldb sources.</li>
- <li>Follow the code signing instructions in <b>lldb/docs/code-signing.txt</b></li>
- <li>In Xcode 3.x: <b>lldb/lldb.xcodeproj</b>, select the <b>lldb-tool</b> target, and build.</li>
- <li>In Xcode 4.x: <b>lldb/lldb.xcworkspace</b>, select the <b>lldb-tool</b> scheme, and build.</li>
- </ul>
- </div>
- <div class="postfooter"></div>
- </div>
- <div class="post">
- <h1 class ="postheader">Building LLDB on Linux and FreeBSD</h1>
- <div class="postcontent">
- <p>This document describes the steps needed to compile LLDB on most Linux systems, and FreeBSD.</a></p>
- </div>
- <div class="postcontent">
- <h2>Preliminaries</h2>
- <p>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 <em>Getting Started</em> guides for both of these projects
- come as prerequisite reading:</p>
- <ul>
- <li><a href="http://llvm.org/docs/GettingStarted.html">LLVM</a></li>
- <li><a href="http://clang.llvm.org/get_started.html">Clang</a></li>
- </ul>
- <p>Supported compilers for building LLDB on Linux include:</p>
- <ul>
- <li>Clang 3.2</li>
- <li><a href="http://gcc.gnu.org">GCC</a> 4.6.2 (later versions should work as well)</li>
- </ul>
- <p>It is recommended to use libstdc++ 4.6 (or higher) to build LLDB on Linux, but using libc++ is also known to work.</p>
- <p>On FreeBSD the base system Clang and libc++ may be used to build LLDB,
- or the GCC port or package.</p>
- <p>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:</p>
- <ul>
- <li><a href="http://swig.org">Swig</a></li>
- <li><a href="http://www.thrysoee.dk/editline">libedit</a> (Linux only)</li>
- <li><a href="http://www.python.org">Python</a></li>
- </ul>
- <p>So for example, on a Fedora system one might run:</p>
- <code>> yum install swig python-devel libedit-devel</code>
- <p>On an Ubuntu system one might run:</p>
- <code>> sudo apt-get install build-essential subversion swig python-dev libedit-dev </code>
- <p>On FreeBSD one might run:</p>
- <code>> pkg install swig python</code>
- <p>If you wish to build the optional reference documentation, additional dependencies are required:</p>
- <ul>
- <li> Graphviz (for the 'dot' tool).
- <li> doxygen (only if you wish to build the C++ API reference)
- <li> epydoc (only if you wish to build the Python API reference)
- </ul>
- <p>To install the prerequisites for building the documentation (on Ubuntu) do:</p>
- <code>
- <br>> sudo apt-get install doxygen graphviz
- <br>> sudo pip install epydoc
- </code>
- <h2 >Building LLDB</h2>
- <p>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 <tt>tools</tt> subdirectory of LLVM. We
- will be setting up a directory hierarchy looking something like this:</p>
- <p>
- <pre><tt>
- llvm
- |
- `-- tools
- |
- +-- clang
- |
- `-- lldb
- </tt></pre>
- </p>
- <p>For reference, we will call the root of the LLVM project tree <tt>$llvm</tt>, and the
- roots of the Clang and LLDB source trees <tt>$clang</tt> and <tt>$lldb</tt> respectively.</p>
- <p>Change to the directory where you want to do development work and checkout LLVM:</p>
- <code>> svn co http://llvm.org/svn/llvm-project/llvm/trunk llvm</code>
-
- <p>Now switch to LLVM’s tools subdirectory and checkout both Clang and LLDB:</p>
- <code>> cd $llvm/tools
- <br>> svn co http://llvm.org/svn/llvm-project/cfe/trunk clang
- <br>> svn co http://llvm.org/svn/llvm-project/lldb/trunk lldb
- </code>
-
- <p>In general, building the LLDB trunk revision requires trunk revisions of both
- LLVM and Clang.
- <p>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 <em>Getting Started Guide</em>. A typical build procedure
- might be:</p>
- <code>> cd $llvm/..
- <br>> mkdir build
- <br>> cd build
- </code>
- <h2>To build with CMake</h2>
- <p>Using CMake is documented on the <a href="http://llvm.org/docs/CMake.html">Building LLVM with CMake</a>
- page. Building LLDB is possible using one of the following generators:
- </p>
- <ul>
- <li> Ninja </li>
- <li> Unix Makefiles </li>
- </ul>
- <h3>Using CMake + Ninja</h3>
- <p>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:
- </p>
- <code>
- > cmake .. -G Ninja
- <br>> ninja lldb
- <br>> ninja check-lldb
- </code>
- <h3>Using CMake + Unix Makefiles</h3>
- <p>If you do not have Ninja, you can still use CMake to generate Unix Makefiles that build LLDB:</p>
- <code>
- > cmake ..
- <br>> make
- <br>> make check-lldb
- </code>
- <h2>To build with autoconf</h2>
- <p>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:</p>
- <code>
- > $llvm/configure --enable-cxx11
- <br>> make </code>
- <p>Or, if you are using a version of GCC that does not support the <tt>-std=c++11</tt> option:</p>
- <code>
- > $llvm/configure
- <br>> make CXXFLAGS=-std=c++0x</code>
- <p>If you are building with a GCC that isn't the default gcc/g++, like gcc-4.7/g++-4.7</p>
- <code>
- > $llvm/configure --enable-cxx11 CC=gcc-4.7 CXX=g++-4.7
- <br>> make CC=gcc-4.7 CXX=g++-4.7</code>
- <p>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).</p>
- <code>
- > make DEBUG_SYMBOLS=0</code>
- <p> To run the LLDB test suite, run:</p>
- <code>
- <br>> make -C tools/lldb/test</code>
- <p>Note that once both LLVM and Clang have been configured and built it is not
- necessary to perform a top-level <tt>make</tt> to rebuild changes made only to LLDB.
- You can run <tt>make</tt> from the <tt>build/tools/lldb</tt> subdirectory as well.</p>
- <p> If you wish to build with libc++ instead of libstdc++ (the default), run configure with the
- <tt>--enable-libcpp</tt> flag.</p>
- <p> If you wish to build a release version of LLDB, run configure with the <tt>--enable-optimized</tt> flag.</p>
-
- <h2>Testing</h2>
- <p>By default, the <tt>check-lldb</tt> 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 <tt>LLDB_TEST_ARGS</tt>. For example, to test LLDB against 32-bit binaries
- built with a custom version of clang, do:</p>
- <code>
- <br>> cmake -DLLDB_TEST_ARGS="-A i386 -C /path/to/custom/clang" -G Ninja
- <br>> ninja check-lldb
- </code>
- <p>Note that multiple -A and -C flags can be specified to <tt>LLDB_TEST_ARGS</tt>.</p>
- <p>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:</p>
- <code>
- <br>> cd $lldb/test
- <br>> python dotest.py --executable <path-to-lldb> -p TestInferiorCrashing.py
- </code>
- <p>In addition to running a test by name, it is also possible to specify a directory path to <tt>dotest.py</tt>
- in order to run all the tests under that directory. For example, to run all the tests under the
- 'functionalities/data-formatter' directory, run:</p>
- <code>
- <br>> python dotest.py --executable <path-to-lldb> functionalities/data-formatter
- </code>
- <p>To dump additional information to <tt>stdout</tt> about how the test harness is driving LLDB, run
- <tt>dotest.py</tt> with the <tt>-t</tt> flag. Many more options that are available. To see a list of all of them, run:</p>
- <code>
- <br>> python dotest.py -h
- </code>
- <h2>Building API reference documentation</h2>
- <p>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 <tt>lldb-python-doc</tt> and <tt>lldb-cpp-doc</tt> CMake targets.</p>
- <p> The output HTML reference documentation can be found in <tt><build-dir>/tools/lldb/docs/</tt>.<p>
- <h2>Additional Notes</h2>
- <p>LLDB has a Python scripting capability and supplies its own Python module named <tt>lldb</tt>.
- If a script is run inside the command line <tt>lldb</tt> 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 <tt>PYTHONPATH</tt> environment variable can be used
- to let the Python interpreter find the <tt>lldb</tt> module.
- <p>The correct path can be obtained by invoking the command line <tt>lldb</tt> tool with the -P flag:</p>
- <code>> export PYTHONPATH=`$llvm/build/Debug+Asserts/bin/lldb -P`</code>
- <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:</p>
- <code>> python -c 'import lldb'</code></p>
- </div>
- <div class="postfooter"></div>
- </div>
- </div>
- </div>
-</div>
-</body>
-</html>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> +<link href="style.css" rel="stylesheet" type="text/css" /> +<title>Building LLDB</title> +</head> + +<body> + <div class="www_title"> + The <strong>LLDB</strong> Debugger + </div> + +<div id="container"> + <div id="content"> + + <!--#include virtual="sidebar.incl"--> + + <div id="middle"> + <h1 class ="postheader">Continuous Integraton</h1> + <div class="postcontent"> + <p> The following LLVM buildbots build and test LLDB trunk: + <ul> + <li> <a href="http://lab.llvm.org:8011/builders/lldb-x86_64-debian-clang">LLDB Linux x86_64 build with Clang (automake)</a> + <li> <a href="http://lab.llvm.org:8011/builders/lldb-x86_64-linux">LLDB Linux x86_64 build with GCC 4.6 (automake)</a> + <li> <a href="http://lab.llvm.org:8011/builders/lldb-x86_64-darwin11">LLDB Mac OS X x86_64 build with Clang (XCode)</a> + <li> <a href="http://llvm-amd64.freebsd.your.org:8010/builders/lldb-amd64-freebsd">LLDB FreeBSD x86_64</a> + <li> <a href="http://llvm-amd64.freebsd.your.org:8010/builders/lldb-i386-freebsd">LLDB FreeBSD i386</a> + </ul> + </div> + <div class="postfooter"></div> + <div class="post"> + <h1 class ="postheader">Building LLDB on Mac OS X</h1> + <div class="postcontent"> + <p>Building on Mac OS X is as easy as downloading the code and building the Xcode project or workspace:</p> + </div> + <div class="postcontent"> + <h2>Preliminaries</h2> + <ul> + <li>XCode 4.3 or newer requires the "Command Line Tools" component (XCode->Preferences->Downloads->Components).</li> + <li>Mac OS X Lion or newer requires installing <a href="http://swig.org">Swig</a>.</li> + </ul> + <h2>Building LLDB</h2> + <ul> + <li><a href="download.html">Download</a> the lldb sources.</li> + <li>Follow the code signing instructions in <b>lldb/docs/code-signing.txt</b></li> + <li>In Xcode 3.x: <b>lldb/lldb.xcodeproj</b>, select the <b>lldb-tool</b> target, and build.</li> + <li>In Xcode 4.x: <b>lldb/lldb.xcworkspace</b>, select the <b>lldb-tool</b> scheme, and build.</li> + </ul> + </div> + <div class="postfooter"></div> + </div> + <div class="post"> + <h1 class ="postheader">Building LLDB on Linux and FreeBSD</h1> + <div class="postcontent"> + <p>This document describes the steps needed to compile LLDB on most Linux systems, and FreeBSD.</a></p> + </div> + <div class="postcontent"> + <h2>Preliminaries</h2> + <p>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 <em>Getting Started</em> guides for both of these projects + come as prerequisite reading:</p> + <ul> + <li><a href="http://llvm.org/docs/GettingStarted.html">LLVM</a></li> + <li><a href="http://clang.llvm.org/get_started.html">Clang</a></li> + </ul> + <p>Supported compilers for building LLDB on Linux include:</p> + <ul> + <li>Clang 3.2</li> + <li><a href="http://gcc.gnu.org">GCC</a> 4.6.2 (later versions should work as well)</li> + </ul> + <p>It is recommended to use libstdc++ 4.6 (or higher) to build LLDB on Linux, but using libc++ is also known to work.</p> + <p>On FreeBSD the base system Clang and libc++ may be used to build LLDB, + or the GCC port or package.</p> + <p>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:</p> + <ul> + <li><a href="http://swig.org">Swig</a></li> + <li><a href="http://www.thrysoee.dk/editline">libedit</a> (Linux only)</li> + <li><a href="http://www.python.org">Python</a></li> + </ul> + <p>So for example, on a Fedora system one might run:</p> + <code>> yum install swig python-devel libedit-devel</code> + <p>On an Ubuntu system one might run:</p> + <code>> sudo apt-get install build-essential subversion swig python-dev libedit-dev </code> + <p>On FreeBSD one might run:</p> + <code>> pkg install swig python</code> + <p>If you wish to build the optional reference documentation, additional dependencies are required:</p> + <ul> + <li> Graphviz (for the 'dot' tool). + <li> doxygen (only if you wish to build the C++ API reference) + <li> epydoc (only if you wish to build the Python API reference) + </ul> + <p>To install the prerequisites for building the documentation (on Ubuntu) do:</p> + <code> + <br>> sudo apt-get install doxygen graphviz + <br>> sudo pip install epydoc + </code> + <h2 >Building LLDB</h2> + <p>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 <tt>tools</tt> subdirectory of LLVM. We + will be setting up a directory hierarchy looking something like this:</p> + <p> + <pre><tt> + llvm + | + `-- tools + | + +-- clang + | + `-- lldb + </tt></pre> + </p> + <p>For reference, we will call the root of the LLVM project tree <tt>$llvm</tt>, and the + roots of the Clang and LLDB source trees <tt>$clang</tt> and <tt>$lldb</tt> respectively.</p> + <p>Change to the directory where you want to do development work and checkout LLVM:</p> + <code>> svn co http://llvm.org/svn/llvm-project/llvm/trunk llvm</code> + + <p>Now switch to LLVM’s tools subdirectory and checkout both Clang and LLDB:</p> + <code>> cd $llvm/tools + <br>> svn co http://llvm.org/svn/llvm-project/cfe/trunk clang + <br>> svn co http://llvm.org/svn/llvm-project/lldb/trunk lldb + </code> + + <p>In general, building the LLDB trunk revision requires trunk revisions of both + LLVM and Clang. + <p>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 <em>Getting Started Guide</em>. A typical build procedure + might be:</p> + <code>> cd $llvm/.. + <br>> mkdir build + <br>> cd build + </code> + <h2>To build with CMake</h2> + <p>Using CMake is documented on the <a href="http://llvm.org/docs/CMake.html">Building LLVM with CMake</a> + page. Building LLDB is possible using one of the following generators: + </p> + <ul> + <li> Ninja </li> + <li> Unix Makefiles </li> + </ul> + <h3>Using CMake + Ninja</h3> + <p>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: + </p> + <code> + > cmake .. -G Ninja + <br>> ninja lldb + <br>> ninja check-lldb + </code> + <h3>Using CMake + Unix Makefiles</h3> + <p>If you do not have Ninja, you can still use CMake to generate Unix Makefiles that build LLDB:</p> + <code> + > cmake .. + <br>> make + <br>> make check-lldb + </code> + <h2>To build with autoconf</h2> + <p>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:</p> + <code> + > $llvm/configure --enable-cxx11 + <br>> make </code> + <p>Or, if you are using a version of GCC that does not support the <tt>-std=c++11</tt> option:</p> + <code> + > $llvm/configure + <br>> make CXXFLAGS=-std=c++0x</code> + <p>If you are building with a GCC that isn't the default gcc/g++, like gcc-4.7/g++-4.7</p> + <code> + > $llvm/configure --enable-cxx11 CC=gcc-4.7 CXX=g++-4.7 + <br>> make CC=gcc-4.7 CXX=g++-4.7</code> + <p>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).</p> + <code> + > make DEBUG_SYMBOLS=0</code> + <p> To run the LLDB test suite, run:</p> + <code> + <br>> make -C tools/lldb/test</code> + <p>Note that once both LLVM and Clang have been configured and built it is not + necessary to perform a top-level <tt>make</tt> to rebuild changes made only to LLDB. + You can run <tt>make</tt> from the <tt>build/tools/lldb</tt> subdirectory as well.</p> + <p> If you wish to build with libc++ instead of libstdc++ (the default), run configure with the + <tt>--enable-libcpp</tt> flag.</p> + <p> If you wish to build a release version of LLDB, run configure with the <tt>--enable-optimized</tt> flag.</p> + + <h2>Testing</h2> + <p>By default, the <tt>check-lldb</tt> 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 <tt>LLDB_TEST_ARGS</tt>. For example, to test LLDB against 32-bit binaries + built with a custom version of clang, do:</p> + <code> + <br>> cmake -DLLDB_TEST_ARGS="-A i386 -C /path/to/custom/clang" -G Ninja + <br>> ninja check-lldb + </code> + <p>Note that multiple -A and -C flags can be specified to <tt>LLDB_TEST_ARGS</tt>.</p> + <p>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:</p> + <code> + <br>> cd $lldb/test + <br>> python dotest.py --executable <path-to-lldb> -p TestInferiorCrashing.py + </code> + <p>In addition to running a test by name, it is also possible to specify a directory path to <tt>dotest.py</tt> + in order to run all the tests under that directory. For example, to run all the tests under the + 'functionalities/data-formatter' directory, run:</p> + <code> + <br>> python dotest.py --executable <path-to-lldb> functionalities/data-formatter + </code> + <p>To dump additional information to <tt>stdout</tt> about how the test harness is driving LLDB, run + <tt>dotest.py</tt> with the <tt>-t</tt> flag. Many more options that are available. To see a list of all of them, run:</p> + <code> + <br>> python dotest.py -h + </code> + <h2>Building API reference documentation</h2> + <p>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 <tt>lldb-python-doc</tt> and <tt>lldb-cpp-doc</tt> CMake targets.</p> + <p> The output HTML reference documentation can be found in <tt><build-dir>/tools/lldb/docs/</tt>.<p> + <h2>Additional Notes</h2> + <p>LLDB has a Python scripting capability and supplies its own Python module named <tt>lldb</tt>. + If a script is run inside the command line <tt>lldb</tt> 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 <tt>PYTHONPATH</tt> environment variable can be used + to let the Python interpreter find the <tt>lldb</tt> module. + <p>The correct path can be obtained by invoking the command line <tt>lldb</tt> tool with the -P flag:</p> + <code>> export PYTHONPATH=`$llvm/build/Debug+Asserts/bin/lldb -P`</code> + <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:</p> + <code>> python -c 'import lldb'</code></p> + </div> + <div class="postfooter"></div> + </div> + </div> + </div> +</div> +</body> +</html> diff --git a/lldb/www/customization.html b/lldb/www/customization.html index b61c716dd21..52fac04a0f7 100755 --- a/lldb/www/customization.html +++ b/lldb/www/customization.html @@ -1,33 +1,33 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
-<link href="style.css" rel="stylesheet" type="text/css" />
-<title>LLDB Customization</title>
-</head>
-
-<body>
-<div class="www_title">
- The <strong>LLDB</strong> Debugger
-</div>
-
-<div id="container">
-<div id="content">
- <!--#include virtual="sidebar.incl"-->
-
- <div id="middle">
- <div class="post">
- <h1 class ="postheader">Customization</h1>
- <div class="postcontent">
- <p>There is an examples/customization directory under LLDB top of tree,
- where you can find examples of customizations for interacting with the
- lldb interpreter.</p>
- <p>We welcome you to submit new and interesting examples of customizations.
- </p>
- </div>
- <div class="postfooter"></div>
-</div>
-</div>
-</div>
-</body>
-</html>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> +<link href="style.css" rel="stylesheet" type="text/css" /> +<title>LLDB Customization</title> +</head> + +<body> +<div class="www_title"> + The <strong>LLDB</strong> Debugger +</div> + +<div id="container"> +<div id="content"> + <!--#include virtual="sidebar.incl"--> + + <div id="middle"> + <div class="post"> + <h1 class ="postheader">Customization</h1> + <div class="postcontent"> + <p>There is an examples/customization directory under LLDB top of tree, + where you can find examples of customizations for interacting with the + lldb interpreter.</p> + <p>We welcome you to submit new and interesting examples of customizations. + </p> + </div> + <div class="postfooter"></div> +</div> +</div> +</div> +</body> +</html> diff --git a/lldb/www/docs.html b/lldb/www/docs.html index 4edcab17382..5b69ded57ed 100755 --- a/lldb/www/docs.html +++ b/lldb/www/docs.html @@ -1,34 +1,34 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
-<link href="style.css" rel="stylesheet" type="text/css" />
-<title>LLDB Documentation</title>
-</head>
-
-<body>
- <div class="www_title">
- The <strong>LLDB</strong> Debugger
- </div>
-
-<div id="container">
- <div id="content">
-
- <!--#include virtual="sidebar.incl"-->
-
- <div id="middle">
- <div class="post">
- <h1 class ="postheader">Documentation</h1>
- <div class="postcontent">
- <p>LLDB is partially documented with header documentation that can be
- parsed and viewed with <a href="http://www.stack.nl/~dimitri/doxygen/">doxygen.</a></p>
- <p>The C++ reference documentation is available <a href="cpp_reference/html/index.html">here.</a></p>
- <p>The Python reference documentation is available <a href="python_reference/index.html">here.</a></p>
- </div>
- <div class="postfooter"></div>
- </div>
- </div>
- </div>
-</div>
-</body>
-</html>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> +<link href="style.css" rel="stylesheet" type="text/css" /> +<title>LLDB Documentation</title> +</head> + +<body> + <div class="www_title"> + The <strong>LLDB</strong> Debugger + </div> + +<div id="container"> + <div id="content"> + + <!--#include virtual="sidebar.incl"--> + + <div id="middle"> + <div class="post"> + <h1 class ="postheader">Documentation</h1> + <div class="postcontent"> + <p>LLDB is partially documented with header documentation that can be + parsed and viewed with <a href="http://www.stack.nl/~dimitri/doxygen/">doxygen.</a></p> + <p>The C++ reference documentation is available <a href="cpp_reference/html/index.html">here.</a></p> + <p>The Python reference documentation is available <a href="python_reference/index.html">here.</a></p> + </div> + <div class="postfooter"></div> + </div> + </div> + </div> +</div> +</body> +</html> diff --git a/lldb/www/download.html b/lldb/www/download.html index e492e074458..6fded58f160 100755 --- a/lldb/www/download.html +++ b/lldb/www/download.html @@ -1,51 +1,51 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
-<link href="style.css" rel="stylesheet" type="text/css" />
-<title>Downloading LLDB</title>
-</head>
-
-<body>
- <div class="www_title">
- The <strong>LLDB</strong> Debugger
- </div>
-
-<div id="container">
- <div id="content">
-
- <!--#include virtual="sidebar.incl"-->
-
- <div id="middle">
- <div class="post">
- <h1 class ="postheader">Latest LLDB</h1>
- <div class="postcontent">
- <p>Nightly builds of LLDB are <a href="http://blog.llvm.org/2013/04/llvm-debianubuntu-nightly-packages.html">packaged and tested</a> from trunk:</p>
- <ul>
- <li>Debian and Ubuntu:
- <a href="http://llvm.org/apt/">llvm.org/apt</a></li>
- </ul>
- </div>
- <div class="postfooter"></div>
- </div>
- <div class="post">
- <h1 class ="postheader">LLDB releases</h1>
- <div class="postcontent">
- <p>Debian packages are available for LLDB 3.2 and later.</p>
- <ul>
- <li><a href="http://packages.debian.org/experimental/lldb-3.4">LLDB 3.4 - incremental release</a> (experimental)</li>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> +<link href="style.css" rel="stylesheet" type="text/css" /> +<title>Downloading LLDB</title> +</head> + +<body> + <div class="www_title"> + The <strong>LLDB</strong> Debugger + </div> + +<div id="container"> + <div id="content"> + + <!--#include virtual="sidebar.incl"--> + + <div id="middle"> + <div class="post"> + <h1 class ="postheader">Latest LLDB</h1> + <div class="postcontent"> + <p>Nightly builds of LLDB are <a href="http://blog.llvm.org/2013/04/llvm-debianubuntu-nightly-packages.html">packaged and tested</a> from trunk:</p> + <ul> + <li>Debian and Ubuntu: + <a href="http://llvm.org/apt/">llvm.org/apt</a></li> + </ul> + </div> + <div class="postfooter"></div> + </div> + <div class="post"> + <h1 class ="postheader">LLDB releases</h1> + <div class="postcontent"> + <p>Debian packages are available for LLDB 3.2 and later.</p> + <ul> + <li><a href="http://packages.debian.org/experimental/lldb-3.4">LLDB 3.4 - incremental release</a> (experimental)</li> <ul> - <li><a href="http://packages.debian.org/experimental/amd64/lldb-3.4/download">amd64</a> (x86-64)</li>
- <li><a href="http://packages.debian.org/experimental/s390/lldb-3.4/download">System/390</a> (i386)</li>
- </ul>
- <li><a href="http://packages.debian.org/unstable/lldb-3.3">LLDB 3.3</a> (unstable)</li>
- <li><a href="http://packages.debian.org/unstable/lldb-3.2">LLDB 3.2</a> (unstable)</li>
- </ul>
- </div>
- <div class="postfooter"></div>
- </div>
- </div>
- </div>
-</div>
-</body>
+ <li><a href="http://packages.debian.org/experimental/amd64/lldb-3.4/download">amd64</a> (x86-64)</li> + <li><a href="http://packages.debian.org/experimental/s390/lldb-3.4/download">System/390</a> (i386)</li> + </ul> + <li><a href="http://packages.debian.org/unstable/lldb-3.3">LLDB 3.3</a> (unstable)</li> + <li><a href="http://packages.debian.org/unstable/lldb-3.2">LLDB 3.2</a> (unstable)</li> + </ul> + </div> + <div class="postfooter"></div> + </div> + </div> + </div> +</div> +</body> </html> diff --git a/lldb/www/faq.html b/lldb/www/faq.html index f1de69ef89a..91a4498d3dc 100755 --- a/lldb/www/faq.html +++ b/lldb/www/faq.html @@ -1,30 +1,30 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
-<link href="style.css" rel="stylesheet" type="text/css" />
-<title>LLDB FAQ</title>
-</head>
-
-<body>
-<div class="www_title">
- The <strong>LLDB</strong> Debugger
-</div>
-
-<div id="container">
-<div id="content">
- <!--#include virtual="sidebar.incl"-->
-
- <div id="middle">
- <div class="post">
- <h1 class ="postheader">LLDB FAQ</h1>
- <div class="postcontent">
- <p><b>Q: What targets does LLDB currently support?</b></p>
- <p>Mac OS X native debugging for i386 and x86_64 targets.</p>
- </div>
- <div class="postfooter"></div>
-</div>
-</div>
-</div>
-</body>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> +<link href="style.css" rel="stylesheet" type="text/css" /> +<title>LLDB FAQ</title> +</head> + +<body> +<div class="www_title"> + The <strong>LLDB</strong> Debugger +</div> + +<div id="container"> +<div id="content"> + <!--#include virtual="sidebar.incl"--> + + <div id="middle"> + <div class="post"> + <h1 class ="postheader">LLDB FAQ</h1> + <div class="postcontent"> + <p><b>Q: What targets does LLDB currently support?</b></p> + <p>Mac OS X native debugging for i386 and x86_64 targets.</p> + </div> + <div class="postfooter"></div> +</div> +</div> +</div> +</body> </html>
\ No newline at end of file diff --git a/lldb/www/features.html b/lldb/www/features.html index 7beb8f11743..92431a3d2e2 100755 --- a/lldb/www/features.html +++ b/lldb/www/features.html @@ -1,60 +1,60 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
-<link href="style.css" rel="stylesheet" type="text/css" />
-<title>LLDB Features</title>
-</head>
-
-<body>
- <div class="www_title">
- The <strong>LLDB</strong> Debugger
- </div>
-
-<div id="container">
- <div id="content">
- <!--#include virtual="sidebar.incl"-->
-
- <div id="middle">
- <div class="post">
- <h1 class ="postheader">Features</h1>
- <div class="postcontent">
- <p>LLDB supports a broad variety of basic debugging features such as
- reading DWARF, supporting step, next, finish, backtraces, etc. Some
- more interested bits are:</p>
-
- <ul>
- <li>Plug-in architecture for portability and extensibility:</li>
- <ul>
- <li>Object file parsers for executable file formats. Support currently
- includes Mach-O (32 and 64-bit) & ELF (32-bit).</li>
- <li>Object container parsers to extract object files contained within a file.
- Support currently includes universal Mach-O files & BSD Archives.
- </li>
- <li>Debug symbol file parsers to incrementally extract debug information from
- object files. Support currently includes DWARF & Mach-O symbol
- tables.</li>
- <li>Symbol vendor plug-ins collect data from a variety of different sources
- for an executable object.</li>
- <li>Disassembly plug-ins for each architecture. Support currently includes
- an LLVM disassembler for <a href="http://blog.llvm.org/2010/01/x86-disassembler.html">i386, x86-64</a>
- , & ARM/Thumb.</li>
- <li>Debugger plug-ins implement the host and target specific functions
- required to debug.</li>
- </ul>
- <li>SWIG-generated script bridging allows Python to access and control the
- public API of the debugger library.</li>
- <li>A remote protocol server, debugserver, implements Mac OS X debugging on
- i386 and x86-64.</li>
- <li>A command line debugger - the lldb executable itself.</li>
- <li>A framework API to the library.</li>
- </ul>
- </div>
- <div class="postfooter"></div>
- </div>
-
- </div>
- </div>
-</div>
-</body>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> +<link href="style.css" rel="stylesheet" type="text/css" /> +<title>LLDB Features</title> +</head> + +<body> + <div class="www_title"> + The <strong>LLDB</strong> Debugger + </div> + +<div id="container"> + <div id="content"> + <!--#include virtual="sidebar.incl"--> + + <div id="middle"> + <div class="post"> + <h1 class ="postheader">Features</h1> + <div class="postcontent"> + <p>LLDB supports a broad variety of basic debugging features such as + reading DWARF, supporting step, next, finish, backtraces, etc. Some + more interested bits are:</p> + + <ul> + <li>Plug-in architecture for portability and extensibility:</li> + <ul> + <li>Object file parsers for executable file formats. Support currently + includes Mach-O (32 and 64-bit) & ELF (32-bit).</li> + <li>Object container parsers to extract object files contained within a file. + Support currently includes universal Mach-O files & BSD Archives. + </li> + <li>Debug symbol file parsers to incrementally extract debug information from + object files. Support currently includes DWARF & Mach-O symbol + tables.</li> + <li>Symbol vendor plug-ins collect data from a variety of different sources + for an executable object.</li> + <li>Disassembly plug-ins for each architecture. Support currently includes + an LLVM disassembler for <a href="http://blog.llvm.org/2010/01/x86-disassembler.html">i386, x86-64</a> + , & ARM/Thumb.</li> + <li>Debugger plug-ins implement the host and target specific functions + required to debug.</li> + </ul> + <li>SWIG-generated script bridging allows Python to access and control the + public API of the debugger library.</li> + <li>A remote protocol server, debugserver, implements Mac OS X debugging on + i386 and x86-64.</li> + <li>A command line debugger - the lldb executable itself.</li> + <li>A framework API to the library.</li> + </ul> + </div> + <div class="postfooter"></div> + </div> + + </div> + </div> +</div> +</body> </html>
\ No newline at end of file diff --git a/lldb/www/formats.html b/lldb/www/formats.html index 364106f7bfc..9e994cb5cdb 100755 --- a/lldb/www/formats.html +++ b/lldb/www/formats.html @@ -1,279 +1,279 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
-<link href="style.css" rel="stylesheet" type="text/css" />
-<title>LLDB Stack and Frame Formats</title>
-</head>
-
-<body>
- <div class="www_title">
- The <strong>LLDB</strong> Debugger
- </div>
-
-<div id="container">
- <div id="content">
- <!--#include virtual="sidebar.incl"-->
-
- <div id="middle">
- <div class="post">
- <h1 class ="postheader">Stack Frame and Thread Format</h1>
- <div class="postcontent">
- <p>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:</p>
-
- <p><b><code>* thread #1: tid = 0x2e03, 0x0000000100000e85 a.out`main + 4, stop reason = breakpoint 1.1</code></b></p>
-
- <p>Stack backtraces frames also have a similar information line:</p>
-
- <p><code><b>(lldb)</b> thread backtrace
- <br><b>thread #1: tid = 0x2e03, stop reason = breakpoint 1.1
- <br> frame #0: 0x0000000100000e85 a.out`main + 4 at test.c:19
- <br> frame #1: 0x0000000100000e40 a.out`start + 52
- </code></b></p>
-
- <p>The two format strings can currently be set using the <b>settings set</b> command:</p>
- <p><code><b>(lldb)</b> settings set frame-format STRING
- <br><b>(lldb)</b> settings set thread-format STRING
- </p></code>
-
- </div>
- <div class="postfooter"></div>
- </div>
-
- <div class="post">
- <h1 class ="postheader">Format Strings</h1>
- <div class="postcontent">
-
- <p>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.</p>
-
- <p>Normal characters are any text that doesn't contain a <code><b>'{'</b></code>, <code><b>'}'</b></code>, <code><b>'$'</b></code>,
- or <code><b>'\'</b></code> character.</p>
-
- <p>Variable names are found in between a <code><b>"${"</b></code> prefix, and
- end with a <code><b>"}"</b></code> suffix. In other words, a variable looks like
- <code>"<b>${frame.pc}</b>"</code>.</p>
-
- </div>
- <div class="postfooter"></div>
- </div>
-
- <div class="post">
- <h1 class ="postheader">Variables</h1>
- <div class="postcontent">
-
- <p>A complete list of currently supported format string variables is listed below:</p>
-
- <table border="1">
- <tr valign=top><td><b>Variable Name</b></td><td><b>Description</b></td></tr>
- <tr valign=top><td><b>file.basename</b></td><td>The current compile unit file basename for the current frame.</td></tr>
- <tr valign=top><td><b>file.fullpath</b></td><td>The current compile unit file fullpath for the current frame.</td></tr>
- <tr valign=top><td><b>frame.index</b></td><td>The frame index (0, 1, 2, 3...)</td></tr>
- <tr valign=top><td><b>frame.pc</b></td><td>The generic frame register for the program counter.</td></tr>
- <tr valign=top><td><b>frame.sp</b></td><td>The generic frame register for the stack pointer.</td></tr>
- <tr valign=top><td><b>frame.fp</b></td><td>The generic frame register for the frame pointer.</td></tr>
- <tr valign=top><td><b>frame.flags</b></td><td>The generic frame register for the flags register.</td></tr>
- <tr valign=top><td><b>frame.reg.NAME</b></td><td>Access to any platform specific register by name (replace <b>NAME</b> with the name of the desired register).</td></tr>
- <tr valign=top><td><b>function.name</b></td><td>The name of the current function or symbol.</td></tr>
- <tr valign=top><td><b>function.name-with-args</b></td><td>The name of the current function with arguments and values or the symbol name.</td></tr>
- <tr valign=top><td><b>function.pc-offset</b></td><td>The program counter offset within the current function or symbol</td></tr>
- <tr valign=top><td><b>line.file.basename</b></td><td>The line table entry basename to the file for the current line entry in the current frame.</td></tr>
- <tr valign=top><td><b>line.file.fullpath</b></td><td>The line table entry fullpath to the file for the current line entry in the current frame.</td></tr>
- <tr valign=top><td><b>line.number</b></td><td>The line table entry line number for the current line entry in the current frame.</td></tr>
- <tr valign=top><td><b>line.start-addr</b></td><td>The line table entry start address for the current line entry in the current frame.</td></tr>
- <tr valign=top><td><b>line.end-addr</b></td><td>The line table entry end address for the current line entry in the current frame.</td></tr>
- <tr valign=top><td><b>module.file.basename</b></td><td>The basename of the current module (shared library or executable)</td></tr>
- <tr valign=top><td><b>module.file.fullpath</b></td><td>The basename of the current module (shared library or executable)</td></tr>
- <tr valign=top><td><b>process.file.basename</b></td><td>The basename of the file for the process</td></tr>
- <tr valign=top><td><b>process.file.fullpath</b></td><td>The fullname of the file for the process</td></tr>
- <tr valign=top><td><b>process.id</b></td><td>The process ID native the the system on which the inferior runs.</td></tr>
- <tr valign=top><td><b>process.name</b></td><td>The name of the process at runtime</td></tr>
- <tr valign=top><td><b>thread.id</b></td><td>The thread identifier for the current thread</td></tr>
- <tr valign=top><td><b>thread.index</b></td><td>The unique one based thread index ID which is guaranteed to be unique as threads come and go.</td></tr>
- <tr valign=top><td><b>thread.name</b></td><td>The name of the thread if the target OS supports naming threads</td></tr>
- <tr valign=top><td><b>thread.queue</b></td><td>The queue name of the thread if the target OS supports dispatch queues</td></tr>
- <tr valign=top><td><b>thread.stop-reason</b></td><td>A textual reason each thread stopped</td></tr>
- <tr valign=top><td><b>thread.return-value</b></td><td>The return value of the latest step operation (currently only for step-out.)</td></tr>
- <tr valign=top><td><b>target.arch</b></td><td>The architecture of the current target</td></tr>
- <tr valign=top><td><b>target.script:<i>python_func</i></b></td><td>Use a Python function to generate a piece of textual output</td></tr>
- <tr valign=top><td><b>process.script:<i>python_func</i></b></td><td>Use a Python function to generate a piece of textual output</td></tr>
- <tr valign=top><td><b>thread.script:<i>python_func</i></b></td><td>Use a Python function to generate a piece of textual output</td></tr>
- <tr valign=top><td><b>frame.script:<i>python_func</i></b></td><td>Use a Python function to generate a piece of textual output</td></tr>
- </table>
-
- </div>
- <div class="postfooter"></div>
- </div>
-
- <div class="post">
- <h1 class ="postheader">Control Characters</h1>
- <div class="postcontent">
-
- <p>Control characters include <b><code>'{'</code></b>,
- <b><code>'}'</code></b>, and <b><code>'\'</code></b>.</p>
-
- <p>The '{' and '}' are used for scoping blocks, and the '\' character
- allows you to desensitize control characters and also emit non-printable
- characters.
-
- </div>
- <div class="postfooter"></div>
- </div>
-
- <div class="post">
- <h1 class ="postheader">Desensitizing Characters in the format string</h1>
- <div class="postcontent">
- <p>The backslash control character allows your to enter the typical
- <b><code>"\a"</code></b>, <b><code>"\b"</code></b>, <b><code>"\f"</code></b>, <b><code>"\n"</code></b>,
- <b><code>"\r"</code></b>, <b><code>"\t"</code></b>, <b><code>"\v"</code></b>, <b><code>"\\"</code></b>, characters
- and along with the standard octal representation <b><code>"\0123"</code></b>
- and hex <b><code>"\xAB"</code></b> characters. This allows you to enter
- escape characters into your format strings and will
- allow colorized output for terminals that support color.
-
- </div>
- <div class="postfooter"></div>
- </div>
-
- <div class="post">
- <h1 class ="postheader">Scoping</h1>
- <div class="postcontent">
- <p>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 <b>must</b> resolve into a scope. A scope
- is starts with <code><b>'{'</code></b> and ends with
- <code><b>'}'</code></b>. 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:
-
- <p><b><code>"{ at {$line.file.basename}:${line.number}}"</code></b></p>
-
- <p>Broken down this is:
- <ul>
- <li>The start the scope <p><b><code>"{"</code></b></p></li>
- <li> format whose content will only be displayed if all information is available:
- <p><b><code>"at {$line.file.basename}:${line.number}"</code></b></p></li>
- <li>end the scope: <p><b><code>"}"</code></b></p></li>
- </ul>
-
- </div>
- <div class="postfooter"></div>
- </div>
-
- <div class="post">
- <h1 class ="postheader">Making the Frame Format</h1>
- <div class="postcontent">
- <p>The information that we see when stopped in a frame:
-
- <p><b><code>frame #0: 0x0000000100000e85 a.out`main + 4 at test.c:19</code></b></p>
-
- <p>can be displayed with the following format:</p>
-
- <p><b><code>"frame #${frame.index}: ${frame.pc}{ ${module.file.basename}`${function.name}{${function.pc-offset}}}{ at ${line.file.basename}:${line.number}}\n"</code></b></p>
-
- <p>This breaks down to:
-
- <ul>
- <li>Always print the frame index and frame PC:
-
- <p><b><code>"frame #${frame.index}: ${frame.pc}"</code></b></p>
-
- <li>only print the module followed by a tick if there is a valid
- module for the current frame:
-
- <p><b><code>"{ ${module.file.basename}`}"</code></b></p>
-
- <li>print the function name with optional offset:</p>
- <p><b><code>"{${function.name}{${function.pc-offset}}}"</code></b></p>
-
- <li>print the line info if it is available:</p>
-
- <p><b><code>"{ at ${line.file.basename}:${line.number}}"</code></b></p>
-
- <li>then finish off with a newline:</p>
-
- <p><b><code>"\n"</code></b></p>
- </ul>
-
- </div>
- <div class="postfooter"></div>
- </div>
-
- <div class="post">
- <h1 class ="postheader">Making Your Own Formats</h1>
- <div class="postcontent">
-
- <p>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
- <b><code>"settings show"</code></b> command:
-
- <p><b><code>(lldb)</b> settings show thread-format
- <br>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'
- <br><b>(lldb)</b> settings show frame-format
- <br>frame-format (string) = 'frame #${frame.index}: ${frame.pc}{ ${module.file.basename}`${function.name}{${function.pc-offset}}}{ at ${line.file.basename}:${line.number}}\n'
- </code></p>
-
-
- <p>When making thread formats, you will need surround any
- of the information that comes from a stack frame with scopes (<b>{</b> <i>frame-content</i> <b>}</b>)
- 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:
-
- <p><code><b>(lldb)</b> thread backtrace
- <br>thread #1: tid = 0x2e03, stop reason = breakpoint 1.1 2.1
- <br> frame #0: 0x0000000100000e85 a.out`main + 4 at test.c:19
- <br> frame #1: 0x0000000100000e40 a.out`start + 52
- </code>
- </p>
-
- <p>The frame related variables are:
- <ul>
- <li><code><b>${file.*}</b></code></li>
- <li><code><b>${frame.*}</b></code></li>
- <li><code><b>${function.*}</b></code></li>
- <li><code><b>${line.*}</b></code></li>
- <li><code><b>${module.*}</b></code></li>
- </ul>
- </p>
-
- <p>Looking at the default format for the thread, and underlining
- the frame information:
- <p><code>'thread #${thread.index}: tid = ${thread.id}<u><b>{</b>, ${frame.pc}<b>}{</b> ${module.file.basename}`${function.name}{${function.pc-offset}}<b>}</b></u>{, stop reason = ${thread.stop-reason}}{, name = ${thread.name}}{, queue = ${thread.queue}}\n'
- </code></p>
- <p>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.
-
- <p>For both thread and frame formats, you can use ${target.script:<i>python_func</i>}, ${process.script:<i>python_func</i>} and ${thread.script:<i>python_func</i>}
- (and of course ${frame.script:<i>python_func</i>} for frame formats)<br/>
- In all cases, the signature of <i>python_func</i> is expected to be:<br/>
- <p><code>
- def <i>python_func</i>(<i>object</i>,unused):<br/>
- ...<br/>
- return <i>string</i><br/></code>
- <p>Where <i>object</i> is an instance of the SB class associated to the keyword you are using.
-
- <p>e.g. Assuming your function looks like<br/><code><p>
- def thread_printer_func (thread,unused):<br/>
- return "Thread %s has %d frames\n" % (thread.name, thread.num_frames)<br/></code><p>
-
- And you set it up with <code><br/><b>(lldb)</b> settings set thread-format "${thread.script:thread_printer_func}"<br/></code>
- you would see output like:
- </p>
- <code>* Thread main has 21 frames</code>
- </div>
- <div class="postfooter"></div>
- </div>
-
- </div>
- </div>
-</div>
-</body>
-</html>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> +<link href="style.css" rel="stylesheet" type="text/css" /> +<title>LLDB Stack and Frame Formats</title> +</head> + +<body> + <div class="www_title"> + The <strong>LLDB</strong> Debugger + </div> + +<div id="container"> + <div id="content"> + <!--#include virtual="sidebar.incl"--> + + <div id="middle"> + <div class="post"> + <h1 class ="postheader">Stack Frame and Thread Format</h1> + <div class="postcontent"> + <p>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:</p> + + <p><b><code>* thread #1: tid = 0x2e03, 0x0000000100000e85 a.out`main + 4, stop reason = breakpoint 1.1</code></b></p> + + <p>Stack backtraces frames also have a similar information line:</p> + + <p><code><b>(lldb)</b> thread backtrace + <br><b>thread #1: tid = 0x2e03, stop reason = breakpoint 1.1 + <br> frame #0: 0x0000000100000e85 a.out`main + 4 at test.c:19 + <br> frame #1: 0x0000000100000e40 a.out`start + 52 + </code></b></p> + + <p>The two format strings can currently be set using the <b>settings set</b> command:</p> + <p><code><b>(lldb)</b> settings set frame-format STRING + <br><b>(lldb)</b> settings set thread-format STRING + </p></code> + + </div> + <div class="postfooter"></div> + </div> + + <div class="post"> + <h1 class ="postheader">Format Strings</h1> + <div class="postcontent"> + + <p>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.</p> + + <p>Normal characters are any text that doesn't contain a <code><b>'{'</b></code>, <code><b>'}'</b></code>, <code><b>'$'</b></code>, + or <code><b>'\'</b></code> character.</p> + + <p>Variable names are found in between a <code><b>"${"</b></code> prefix, and + end with a <code><b>"}"</b></code> suffix. In other words, a variable looks like + <code>"<b>${frame.pc}</b>"</code>.</p> + + </div> + <div class="postfooter"></div> + </div> + + <div class="post"> + <h1 class ="postheader">Variables</h1> + <div class="postcontent"> + + <p>A complete list of currently supported format string variables is listed below:</p> + + <table border="1"> + <tr valign=top><td><b>Variable Name</b></td><td><b>Description</b></td></tr> + <tr valign=top><td><b>file.basename</b></td><td>The current compile unit file basename for the current frame.</td></tr> + <tr valign=top><td><b>file.fullpath</b></td><td>The current compile unit file fullpath for the current frame.</td></tr> + <tr valign=top><td><b>frame.index</b></td><td>The frame index (0, 1, 2, 3...)</td></tr> + <tr valign=top><td><b>frame.pc</b></td><td>The generic frame register for the program counter.</td></tr> + <tr valign=top><td><b>frame.sp</b></td><td>The generic frame register for the stack pointer.</td></tr> + <tr valign=top><td><b>frame.fp</b></td><td>The generic frame register for the frame pointer.</td></tr> + <tr valign=top><td><b>frame.flags</b></td><td>The generic frame register for the flags register.</td></tr> + <tr valign=top><td><b>frame.reg.NAME</b></td><td>Access to any platform specific register by name (replace <b>NAME</b> with the name of the desired register).</td></tr> + <tr valign=top><td><b>function.name</b></td><td>The name of the current function or symbol.</td></tr> + <tr valign=top><td><b>function.name-with-args</b></td><td>The name of the current function with arguments and values or the symbol name.</td></tr> + <tr valign=top><td><b>function.pc-offset</b></td><td>The program counter offset within the current function or symbol</td></tr> + <tr valign=top><td><b>line.file.basename</b></td><td>The line table entry basename to the file for the current line entry in the current frame.</td></tr> + <tr valign=top><td><b>line.file.fullpath</b></td><td>The line table entry fullpath to the file for the current line entry in the current frame.</td></tr> + <tr valign=top><td><b>line.number</b></td><td>The line table entry line number for the current line entry in the current frame.</td></tr> + <tr valign=top><td><b>line.start-addr</b></td><td>The line table entry start address for the current line entry in the current frame.</td></tr> + <tr valign=top><td><b>line.end-addr</b></td><td>The line table entry end address for the current line entry in the current frame.</td></tr> + <tr valign=top><td><b>module.file.basename</b></td><td>The basename of the current module (shared library or executable)</td></tr> + <tr valign=top><td><b>module.file.fullpath</b></td><td>The basename of the current module (shared library or executable)</td></tr> + <tr valign=top><td><b>process.file.basename</b></td><td>The basename of the file for the process</td></tr> + <tr valign=top><td><b>process.file.fullpath</b></td><td>The fullname of the file for the process</td></tr> + <tr valign=top><td><b>process.id</b></td><td>The process ID native the the system on which the inferior runs.</td></tr> + <tr valign=top><td><b>process.name</b></td><td>The name of the process at runtime</td></tr> + <tr valign=top><td><b>thread.id</b></td><td>The thread identifier for the current thread</td></tr> + <tr valign=top><td><b>thread.index</b></td><td>The unique one based thread index ID which is guaranteed to be unique as threads come and go.</td></tr> + <tr valign=top><td><b>thread.name</b></td><td>The name of the thread if the target OS supports naming threads</td></tr> + <tr valign=top><td><b>thread.queue</b></td><td>The queue name of the thread if the target OS supports dispatch queues</td></tr> + <tr valign=top><td><b>thread.stop-reason</b></td><td>A textual reason each thread stopped</td></tr> + <tr valign=top><td><b>thread.return-value</b></td><td>The return value of the latest step operation (currently only for step-out.)</td></tr> + <tr valign=top><td><b>target.arch</b></td><td>The architecture of the current target</td></tr> + <tr valign=top><td><b>target.script:<i>python_func</i></b></td><td>Use a Python function to generate a piece of textual output</td></tr> + <tr valign=top><td><b>process.script:<i>python_func</i></b></td><td>Use a Python function to generate a piece of textual output</td></tr> + <tr valign=top><td><b>thread.script:<i>python_func</i></b></td><td>Use a Python function to generate a piece of textual output</td></tr> + <tr valign=top><td><b>frame.script:<i>python_func</i></b></td><td>Use a Python function to generate a piece of textual output</td></tr> + </table> + + </div> + <div class="postfooter"></div> + </div> + + <div class="post"> + <h1 class ="postheader">Control Characters</h1> + <div class="postcontent"> + + <p>Control characters include <b><code>'{'</code></b>, + <b><code>'}'</code></b>, and <b><code>'\'</code></b>.</p> + + <p>The '{' and '}' are used for scoping blocks, and the '\' character + allows you to desensitize control characters and also emit non-printable + characters. + + </div> + <div class="postfooter"></div> + </div> + + <div class="post"> + <h1 class ="postheader">Desensitizing Characters in the format string</h1> + <div class="postcontent"> + <p>The backslash control character allows your to enter the typical + <b><code>"\a"</code></b>, <b><code>"\b"</code></b>, <b><code>"\f"</code></b>, <b><code>"\n"</code></b>, + <b><code>"\r"</code></b>, <b><code>"\t"</code></b>, <b><code>"\v"</code></b>, <b><code>"\\"</code></b>, characters + and along with the standard octal representation <b><code>"\0123"</code></b> + and hex <b><code>"\xAB"</code></b> characters. This allows you to enter + escape characters into your format strings and will + allow colorized output for terminals that support color. + + </div> + <div class="postfooter"></div> + </div> + + <div class="post"> + <h1 class ="postheader">Scoping</h1> + <div class="postcontent"> + <p>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 <b>must</b> resolve into a scope. A scope + is starts with <code><b>'{'</code></b> and ends with + <code><b>'}'</code></b>. 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: + + <p><b><code>"{ at {$line.file.basename}:${line.number}}"</code></b></p> + + <p>Broken down this is: + <ul> + <li>The start the scope <p><b><code>"{"</code></b></p></li> + <li> format whose content will only be displayed if all information is available: + <p><b><code>"at {$line.file.basename}:${line.number}"</code></b></p></li> + <li>end the scope: <p><b><code>"}"</code></b></p></li> + </ul> + + </div> + <div class="postfooter"></div> + </div> + + <div class="post"> + <h1 class ="postheader">Making the Frame Format</h1> + <div class="postcontent"> + <p>The information that we see when stopped in a frame: + + <p><b><code>frame #0: 0x0000000100000e85 a.out`main + 4 at test.c:19</code></b></p> + + <p>can be displayed with the following format:</p> + + <p><b><code>"frame #${frame.index}: ${frame.pc}{ ${module.file.basename}`${function.name}{${function.pc-offset}}}{ at ${line.file.basename}:${line.number}}\n"</code></b></p> + + <p>This breaks down to: + + <ul> + <li>Always print the frame index and frame PC: + + <p><b><code>"frame #${frame.index}: ${frame.pc}"</code></b></p> + + <li>only print the module followed by a tick if there is a valid + module for the current frame: + + <p><b><code>"{ ${module.file.basename}`}"</code></b></p> + + <li>print the function name with optional offset:</p> + <p><b><code>"{${function.name}{${function.pc-offset}}}"</code></b></p> + + <li>print the line info if it is available:</p> + + <p><b><code>"{ at ${line.file.basename}:${line.number}}"</code></b></p> + + <li>then finish off with a newline:</p> + + <p><b><code>"\n"</code></b></p> + </ul> + + </div> + <div class="postfooter"></div> + </div> + + <div class="post"> + <h1 class ="postheader">Making Your Own Formats</h1> + <div class="postcontent"> + + <p>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 + <b><code>"settings show"</code></b> command: + + <p><b><code>(lldb)</b> settings show thread-format + <br>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' + <br><b>(lldb)</b> settings show frame-format + <br>frame-format (string) = 'frame #${frame.index}: ${frame.pc}{ ${module.file.basename}`${function.name}{${function.pc-offset}}}{ at ${line.file.basename}:${line.number}}\n' + </code></p> + + + <p>When making thread formats, you will need surround any + of the information that comes from a stack frame with scopes (<b>{</b> <i>frame-content</i> <b>}</b>) + 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: + + <p><code><b>(lldb)</b> thread backtrace + <br>thread #1: tid = 0x2e03, stop reason = breakpoint 1.1 2.1 + <br> frame #0: 0x0000000100000e85 a.out`main + 4 at test.c:19 + <br> frame #1: 0x0000000100000e40 a.out`start + 52 + </code> + </p> + + <p>The frame related variables are: + <ul> + <li><code><b>${file.*}</b></code></li> + <li><code><b>${frame.*}</b></code></li> + <li><code><b>${function.*}</b></code></li> + <li><code><b>${line.*}</b></code></li> + <li><code><b>${module.*}</b></code></li> + </ul> + </p> + + <p>Looking at the default format for the thread, and underlining + the frame information: + <p><code>'thread #${thread.index}: tid = ${thread.id}<u><b>{</b>, ${frame.pc}<b>}{</b> ${module.file.basename}`${function.name}{${function.pc-offset}}<b>}</b></u>{, stop reason = ${thread.stop-reason}}{, name = ${thread.name}}{, queue = ${thread.queue}}\n' + </code></p> + <p>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. + + <p>For both thread and frame formats, you can use ${target.script:<i>python_func</i>}, ${process.script:<i>python_func</i>} and ${thread.script:<i>python_func</i>} + (and of course ${frame.script:<i>python_func</i>} for frame formats)<br/> + In all cases, the signature of <i>python_func</i> is expected to be:<br/> + <p><code> + def <i>python_func</i>(<i>object</i>,unused):<br/> + ...<br/> + return <i>string</i><br/></code> + <p>Where <i>object</i> is an instance of the SB class associated to the keyword you are using. + + <p>e.g. Assuming your function looks like<br/><code><p> + def thread_printer_func (thread,unused):<br/> + return "Thread %s has %d frames\n" % (thread.name, thread.num_frames)<br/></code><p> + + And you set it up with <code><br/><b>(lldb)</b> settings set thread-format "${thread.script:thread_printer_func}"<br/></code> + you would see output like: + </p> + <code>* Thread main has 21 frames</code> + </div> + <div class="postfooter"></div> + </div> + + </div> + </div> +</div> +</body> +</html> diff --git a/lldb/www/goals.html b/lldb/www/goals.html index 3bbb75904ec..04d095cab80 100755 --- a/lldb/www/goals.html +++ b/lldb/www/goals.html @@ -1,63 +1,63 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
-<link href="style.css" rel="stylesheet" type="text/css" />
-<title>LLDB Goals</title>
-</head>
-
-<body>
- <div class="www_title">
- The <strong>LLDB</strong> Debugger
- </div>
-
-<div id="container">
- <div id="content">
- <!--#include virtual="sidebar.incl"-->
- <div id="middle">
- <div class="post">
- <h1 class ="postheader">Goals</h1>
- <div class="postcontent">
-
- <p>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.</p>
-
- <p>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.</p>
-
- <p>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.</p>
-
- <p>Some more specific goals include:</p>
-
- <ul>
- <li>Build libraries for inclusion in IDEs, command line tools, and
- other analysis tools</li>
- <li>High performance and efficient memory use</li>
- <li>Extensible: Python scriptable and use a plug-in architecture</li>
- <li>Reuse existing compiler technology where it makes sense</li>
- <li>Excellent multi-threaded debugging support</li>
- <li>Great support for C, Objective-C and C++</li>
- <li>Retargetable to support multiple platforms</li>
- <li>Provide a base for debugger research and other innovation</li>
- </ul>
- </div>
- <div class="postfooter"></div>
- </div>
- </div>
- </div>
-</div>
-</body>
-</html>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> +<link href="style.css" rel="stylesheet" type="text/css" /> +<title>LLDB Goals</title> +</head> + +<body> + <div class="www_title"> + The <strong>LLDB</strong> Debugger + </div> + +<div id="container"> + <div id="content"> + <!--#include virtual="sidebar.incl"--> + <div id="middle"> + <div class="post"> + <h1 class ="postheader">Goals</h1> + <div class="postcontent"> + + <p>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.</p> + + <p>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.</p> + + <p>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.</p> + + <p>Some more specific goals include:</p> + + <ul> + <li>Build libraries for inclusion in IDEs, command line tools, and + other analysis tools</li> + <li>High performance and efficient memory use</li> + <li>Extensible: Python scriptable and use a plug-in architecture</li> + <li>Reuse existing compiler technology where it makes sense</li> + <li>Excellent multi-threaded debugging support</li> + <li>Great support for C, Objective-C and C++</li> + <li>Retargetable to support multiple platforms</li> + <li>Provide a base for debugger research and other innovation</li> + </ul> + </div> + <div class="postfooter"></div> + </div> + </div> + </div> +</div> +</body> +</html> diff --git a/lldb/www/index.html b/lldb/www/index.html index 85d64e6da6f..3b77b95ece5 100755 --- a/lldb/www/index.html +++ b/lldb/www/index.html @@ -1,128 +1,128 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
-<link href="style.css" rel="stylesheet" type="text/css" />
-<title>LLDB Homepage</title>
-</head>
-
-<body>
- <div class="www_title">
- The <strong>LLDB</strong> Debugger
- </div>
-
-<div id="container">
- <div id="content">
-
- <!--#include virtual="sidebar.incl"-->
-
- <div id="middle">
- <div class="post">
- <h1 class ="postheader">What is LLDB?</h1>
- <div class="postcontent">
- <p>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.</p>
- <p>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.</p>
-
- <p>All of the code in the LLDB project is available under the standard
- <a href="http://llvm.org/docs/DeveloperPolicy.html#license">LLVM
- License</a>, an open source "BSD-style" license.</p>
- </div>
- <div class="postfooter"></div>
- </div>
-
- <div class="post">
- <h1 class ="postheader">Why a new debugger?</h1>
- <div class="postcontent">
- <p>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.</p>
- </div>
- <div class="postfooter"></div>
- </div>
-
- <div class="post">
- <h1 class ="postheader">Compiler Integration Benefits</h1>
- <div class="postcontent">
- <p>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 <b>any</b>
- 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.
- <p>The major benefits include:</p>
- <ul>
- <li>Up to date language support for C, C++, Objective C</li>
- <li>Multi-line expressions that can declare local variables and types</li>
- <li>Utilitize the JIT for expressions when supported</li>
- <li>Evaluate expression Intermediate Representation (IR) when JIT can't be used</li>
- </ul>
- </div>
- </div>
-
- <div class="post">
- <h1 class ="postheader">Reusability</h1>
- <div class="postcontent">
- <p>The LLDB debugger APIs are exposed as a C++ object oriented interface in a shared library.
- The <b>lldb</b> command line tool links to, and uses this public API. On Mac OS X the shared library
- is exposed as a framework named <b>LLDB.framework</b>, and unix systems expose it as <b>lldb.so</b>.
- 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 <b>lldb.py</b>
- module in standard python script files. See the <a href="python-reference.html">Python Reference</a> page for more details on how
- and where Python can be used with the LLDB API.</p>
- <p>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.
- </div>
- </div>
-
- <div class="post">
- <h1 class ="postheader">Platform Support</h1>
- <div class="postcontent">
-
- <p>LLDB is known to work on the following platforms, but ports to new
- platforms are welcome:</p>
- <ul>
- <li>Mac OS X desktop user space debugging for i386 and x86-64</li>
- <li>iOS simulator debugging on i386</li>
- <li>iOS device debugging on ARM</li>
- <li>Linux local user-space debugging for i386 and x86-64</li>
- <li>FreeBSD local user-space debugging for i386 and x86-64</li>
- </ul>
- </div>
- <div class="postfooter"></div>
- </div>
-
-
- <div class="post">
- <h1 class ="postheader">Get it and get involved!</h1>
- <div class="postcontent">
-
- <p>To check out the code, use:</p>
-
- <ul>
- <li>svn co http://llvm.org/svn/llvm-project/lldb/trunk lldb</li>
- </ul>
-
- <p>Note that LLDB generally builds from top-of-trunk on Mac OS X with
- Xcode and on Linux (with clang and libstdc++/libc++). </p>
-
- <p>Discussions about LLDB should go to the <a href="http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev">lldb-dev</a> mailing
- list. Commit messages for the lldb SVN module are automatically sent to the
- <a href="http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits">lldb-commits</a>
- mailing list, and this is also the preferred mailing list for patch
- submissions.</p>
- </div>
- <div class="postfooter"></div>
- </div>
- </div>
- </div>
-</div>
-</body>
-</html>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> +<link href="style.css" rel="stylesheet" type="text/css" /> +<title>LLDB Homepage</title> +</head> + +<body> + <div class="www_title"> + The <strong>LLDB</strong> Debugger + </div> + +<div id="container"> + <div id="content"> + + <!--#include virtual="sidebar.incl"--> + + <div id="middle"> + <div class="post"> + <h1 class ="postheader">What is LLDB?</h1> + <div class="postcontent"> + <p>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.</p> + <p>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.</p> + + <p>All of the code in the LLDB project is available under the standard + <a href="http://llvm.org/docs/DeveloperPolicy.html#license">LLVM + License</a>, an open source "BSD-style" license.</p> + </div> + <div class="postfooter"></div> + </div> + + <div class="post"> + <h1 class ="postheader">Why a new debugger?</h1> + <div class="postcontent"> + <p>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.</p> + </div> + <div class="postfooter"></div> + </div> + + <div class="post"> + <h1 class ="postheader">Compiler Integration Benefits</h1> + <div class="postcontent"> + <p>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 <b>any</b> + 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. + <p>The major benefits include:</p> + <ul> + <li>Up to date language support for C, C++, Objective C</li> + <li>Multi-line expressions that can declare local variables and types</li> + <li>Utilitize the JIT for expressions when supported</li> + <li>Evaluate expression Intermediate Representation (IR) when JIT can't be used</li> + </ul> + </div> + </div> + + <div class="post"> + <h1 class ="postheader">Reusability</h1> + <div class="postcontent"> + <p>The LLDB debugger APIs are exposed as a C++ object oriented interface in a shared library. + The <b>lldb</b> command line tool links to, and uses this public API. On Mac OS X the shared library + is exposed as a framework named <b>LLDB.framework</b>, and unix systems expose it as <b>lldb.so</b>. + 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 <b>lldb.py</b> + module in standard python script files. See the <a href="python-reference.html">Python Reference</a> page for more details on how + and where Python can be used with the LLDB API.</p> + <p>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. + </div> + </div> + + <div class="post"> + <h1 class ="postheader">Platform Support</h1> + <div class="postcontent"> + + <p>LLDB is known to work on the following platforms, but ports to new + platforms are welcome:</p> + <ul> + <li>Mac OS X desktop user space debugging for i386 and x86-64</li> + <li>iOS simulator debugging on i386</li> + <li>iOS device debugging on ARM</li> + <li>Linux local user-space debugging for i386 and x86-64</li> + <li>FreeBSD local user-space debugging for i386 and x86-64</li> + </ul> + </div> + <div class="postfooter"></div> + </div> + + + <div class="post"> + <h1 class ="postheader">Get it and get involved!</h1> + <div class="postcontent"> + + <p>To check out the code, use:</p> + + <ul> + <li>svn co http://llvm.org/svn/llvm-project/lldb/trunk lldb</li> + </ul> + + <p>Note that LLDB generally builds from top-of-trunk on Mac OS X with + Xcode and on Linux (with clang and libstdc++/libc++). </p> + + <p>Discussions about LLDB should go to the <a href="http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev">lldb-dev</a> mailing + list. Commit messages for the lldb SVN module are automatically sent to the + <a href="http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits">lldb-commits</a> + mailing list, and this is also the preferred mailing list for patch + submissions.</p> + </div> + <div class="postfooter"></div> + </div> + </div> + </div> +</div> +</body> +</html> diff --git a/lldb/www/python-reference.html b/lldb/www/python-reference.html index cb06f924665..dfc2165ee5c 100755 --- a/lldb/www/python-reference.html +++ b/lldb/www/python-reference.html @@ -1,598 +1,598 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
-<link href="style.css" rel="stylesheet" type="text/css" />
-<title>LLDB Python Reference</title>
-</head>
-
-<body>
- <div class="www_title">
- LLDB Python Reference
- </div>
-
-<div id="container">
- <div id="content">
- <!--#include virtual="sidebar.incl"-->
- <div id="middle">
- <div class="post">
- <h1 class ="postheader">Introduction</h1>
- <div class="postcontent">
-
- <p>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. </p>
- <p>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.</p>
-
- </div>
- <div class="postfooter"></div>
- <div class="post">
- <h1 class ="postheader">Documentation</h1>
- <div class="postcontent">
-
- <p>The LLDB API is contained in a python module named <b>lldb</b>. A useful resource when writing Python extensions is the <a href="python_reference/index.html">lldb Python classes reference guide</a>.</p>
- <p>The documentation is also accessible in an interactive debugger session with the following command:</p>
-<code><pre><tt>(lldb) <b>script help(lldb)</b>
- 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
-...
-</tt></pre></code>
- <p>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:</p>
-<code><pre><tt>(lldb) <b>script help(lldb.SBFrame)</b>
- 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.'''
- |
-...
-</tt></pre></code>
- <p>Or you can get help using any python object, here we use the <b>lldb.process</b> object which is a global variable in the <b>lldb</b> module which represents the currently selected process:</p>
-<code><pre><tt>(lldb) <b>script help(lldb.process)</b>
- 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
- | # ==================================================
- |
-...
-</tt></pre></code>
-
- </div>
- <div class="postfooter"></div>
-
- <div class="post">
- <h1 class ="postheader">Embedded Python Interpreter</h1>
- <div class="postcontent">
-
- <p>The embedded python interpreter can be accessed in a variety of ways from within LLDB. The
- easiest way is to use the lldb command <b>script</b> with no arguments at the lldb command prompt:</p>
-<code><pre><tt>(lldb) <strong>script</strong>
-Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.
->>> 2+3
-5
->>> hex(12345)
-'0x3039'
->>>
-</tt></pre></code>
-
- <p>This drops you into the embedded python interpreter. When running under the <b>script</b> 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 <b>IsValid</b> method will return false. These variables are:</p>
-
- <table class="stats" width="620" cellspacing="0">
- <tr>
- <td class="hed" width="20%">Variable</td>
- <td class="hed" width="10%">Type</td>
- <td class="hed" width="70%">Description</td>
- </tr>
-
- <tr>
- <td class="content">
- <b>lldb.debugger</b>
- </td>
- <td class="content">
- <b>lldb.SBDebugger</b>
- </td>
- <td class="content">
- Contains the debugger object whose <b>script</b> command was invoked.
- The <b>lldb.SBDebugger</b> object owns the command interpreter
- and all the targets in your debug session. There will always be a
- Debugger in the embedded interpreter.
- </td>
- </tr>
- <tr>
- <td class="content">
- <b>lldb.target</b>
- </td>
- <td class="content">
- <b>lldb.SBTarget</b>
- </td>
- <td class="content">
- Contains the currently selected target - for instance the one made with the
- <b>file</b> or selected by the <b>target select <target-index></b> command.
- The <b>lldb.SBTarget</b> manages one running process, and all the executable
- and debug files for the process.
- </td>
- </tr>
- <tr>
- <td class="content">
- <b>lldb.process</b>
- </td>
- <td class="content">
- <b>lldb.SBProcess</b>
- </td>
- <td class="content">
- Contains the process of the currently selected target.
- The <b>lldb.SBProcess</b> object manages the threads and allows access to
- memory for the process.
- </td>
- </tr>
- <tr>
- <td class="content">
- <b>lldb.thread</b>
- </td>
- <td class="content">
- <b>lldb.SBThread</b>
- </td>
- <td class="content">
- Contains the currently selected thread.
- The <b>lldb.SBThread</b> object manages the stack frames in that thread.
- A thread is always selected in the command interpreter when a target stops.
- The <b>thread select <thread-index></b> 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.
- </td>
- </tr>
- <tr>
- <td class="content">
- <b>lldb.frame</b>
- </td>
- <td class="content">
- <b>lldb.SBFrame</b>
- </td>
- <td class="content">
- Contains the currently selected stack frame.
- The <b>lldb.SBFrame</b> 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 <b>frame select <frame-index></b> 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.
- </td>
- </tr>
- </table>
-
- <p>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.
- <p>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.</p>
-
- <p>To get started with these objects and LLDB scripting, please note that almost
- all of the <b>lldb</b> Python objects are able to briefly describe themselves when you pass them
- to the Python <b>print</b> function:
-<code><pre><tt>(lldb) <b>script</b>
-Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.
->>> <strong>print lldb.debugger</strong>
-Debugger (instance: "debugger_1", id: 1)
->>> <strong>print lldb.target</strong>
-a.out
->>> <strong>print lldb.process</strong>
-SBProcess: pid = 59289, state = stopped, threads = 1, executable = a.out
->>> <strong>print lldb.thread</strong>
-SBThread: tid = 0x1f03
->>> <strong>print lldb.frame</strong>
-frame #0: 0x0000000100000bb6 a.out main + 54 at main.c:16
-</tt></pre></code>
-
- </div>
- <div class="postfooter"></div>
-
- </div>
- <div class="post">
- <h1 class ="postheader">Running a Python script when a breakpoint gets hit</h1>
- <div class="postcontent">
-
- <p>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.</p>
- <p>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:</p>
- <p>
-<code><pre><tt>def breakpoint_function_wrapper(<b>frame</b>, <b>bp_loc</b>, <b>dict</b>):
- <font color=green># Your code goes here</font>
-</tt></pre></code>
- <p><table class="stats" width="620" cellspacing="0">
- <tr>
- <td class="hed" width="10%">Argument</td>
- <td class="hed" width="10%">Type</td>
- <td class="hed" width="80%">Description</td>
- </tr>
-
- <tr>
- <td class="content">
- <b>frame</b>
- </td>
- <td class="content">
- <b>lldb.SBFrame</b>
- </td>
- <td class="content">
- The current stack frame where the breakpoint got hit.
- The object will always be valid.
- This <b>frame</b> argument might <i>not</i> match the currently selected stack frame found in the <b>lldb</b> module global variable <b>lldb.frame</b>.
- </td>
- </tr>
- <tr>
- <td class="content">
- <b>bp_loc</b>
- </td>
- <td class="content">
- <b>lldb.SBBreakpointLocation</b>
- </td>
- <td class="content">
- The breakpoint location that just got hit. Breakpoints are represented by <b>lldb.SBBreakpoint</b>
- objects. These breakpoint objects can have one or more locations. These locations
- are represented by <b>lldb.SBBreakpointLocation</b> objects.
- </td>
- </tr>
- <tr>
- <td class="content">
- <b>dict</b>
- </td>
- <td class="content">
- <b>dict</b>
- </td>
- <td class="content">
- The python session dictionary as a standard python dictionary object.
- </td>
- </tr>
- </table>
- <p>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.
- <p>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.</p>
- <p>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 <b>lldb.SBBreakpoint</b> object
- that contains an <b>lldb.SBBreakpointLocation</b> 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.</p>
- <p>Note we also have to initialize our counter, which we do with the simple one-line version of the <b>script</b>
- command.
- <p>Here is the code:
-
-<code><pre><tt>(lldb) <strong>breakpoint set --func-regex=. --shlib=libfoo.dylib</strong>
-Breakpoint created: 1: regex = '.', module = libfoo.dylib, locations = 223
-(lldb) <strong>script counter = 0</strong>
-(lldb) <strong>breakpoint command add --script-type python 1</strong>
-Enter your Python command(s). Type 'DONE' to end.
-> <font color=green># Increment our counter. Since we are in a function, this must be a global python variable</font>
-> <strong>global counter</strong>
-> <strong>counter += 1</strong>
-> <font color=green># Get the name of the function</font>
-> <strong>name = frame.GetFunctionName()</strong>
-> <font color=green># Print the order and the function name</font>
-> <strong>print '[%i] %s' % (counter, name)</strong>
-> <font color=green># Disable the current breakpoint location so it doesn't get hit again</font>
-> <strong>bp_loc.SetEnabled(False)</strong>
-> <font color=green># No need to stop here</font>
-> <strong>return False</strong>
-> <strong>DONE</strong>
-</tt></pre></code>
- <p>The <b>breakpoint command add</b> command above attaches a python script to breakpoint 1.
- To remove the breakpoint command:
- <p><code>(lldb) <strong>breakpoint command delete 1</strong></code>
- </div>
- </div>
- <div class="post">
- <h1 class ="postheader">Create a new LLDB command using a python function</h1>
- <div class="postcontent">
-
- <p>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. </p>
- <p>To write a python function that implements a new LDB command define the function to take four arguments as follows:</p>
-
- <code><pre><tt>def command_function(<b>debugger</b>, <b>command</b>, <b>result</b>, <b>internal_dict</b>):
- <font color=green># Your code goes here</font>
- </tt></pre></code>
-
- Optionally, you can also provide a Python docstring, and LLDB will use it when providing help for your command, as in:
- <code><pre><tt>def command_function(<b>debugger</b>, <b>command</b>, <b>result</b>, <b>internal_dict</b>):
- <font color=green>"""This command takes a lot of options and does many fancy things"""</font>
- <font color=green># Your code goes here</font>
- </tt></pre></code>
-
- <p><table class="stats" width="620" cellspacing="0">
- <tr>
- <td class="hed" width="10%">Argument</td>
- <td class="hed" width="10%">Type</td>
- <td class="hed" width="80%">Description</td>
- </tr>
-
- <tr>
- <td class="content">
- <b>debugger</b>
- </td>
- <td class="content">
- <b>lldb.SBDebugger</b>
- </td>
- <td class="content">
- The current debugger object.
- </td>
- </tr>
- <tr>
- <td class="content">
- <b>command</b>
- </td>
- <td class="content">
- <b>python string</b>
- </td>
- <td class="content">
- A python string containing all arguments for your command. If you need to chop up the arguments
- try using the <b>shlex</b> module's <code>shlex.split(command)</code> to properly extract the
- arguments.
- </td>
- </tr>
- <tr>
- <td class="content">
- <b>result</b>
- </td>
- <td class="content">
- <b>lldb.SBCommandReturnObject</b>
- </td>
- <td class="content">
- 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).
- </td>
- </tr>
- <tr>
- <td class="content">
- <b>internal_dict</b>
- </td>
- <td class="content">
- <b>python dict object</b>
- </td>
- <td class="content">
- The dictionary for the current embedded script session which contains all variables
- and functions.
- </td>
- </tr>
- </table>
- <p>As a convenience, you can treat the result object as a Python file object, and say
- <code><pre><tt>print >>result, "my command does lots of cool stuff"</tt></pre></code>
- SBCommandReturnObject and SBStream
- both support this file-like behavior by providing write() and flush() calls at the Python layer.</p>
- <p>One other handy convenience when defining lldb command-line commands is the command
- <b>command script import</b> 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:</p>
-
-<code><pre><tt>def __lldb_init_module(<b>debugger</b>, <b>internal_dict</b>):
- <font color=green># Command Initialization code goes here</font>
-</tt></pre></code>
-
- <p>where <b>debugger</b> and <b>internal_dict</b> 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 <b>command script import</b>,
- 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
- <u>or</u> when loaded via an <b>import</b> statement in python code
- you can test the <b>lldb.debugger</b> object, since you imported the
- <lldb> module at the top of the python <b>ls.py</b> module. This test
- must be in code that isn't contained inside of any function or class,
- just like the standard test for <b>__main__</b> like all python modules
- usally do. Sample code would look like:
-
-<code><pre><tt>if __name__ == '__main__':
- <font color=green># 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</font>
- lldb.debugger = lldb.SBDebugger.Create()
-elif lldb.debugger:
- <font color=green># Module is being run inside the LLDB interpreter</font>
- lldb.debugger.HandleCommand('command script add -f ls.ls ls')
- print 'The "ls" python command has been installed and is ready for use.'
-</tt></pre></code>
- <p>Now we can create a module called <b>ls.py</b> in the file <b>~/ls.py</b> that will implement a function that
- can be used by LLDB's python command code:</p>
-
-<code><pre><tt><font color=green>#!/usr/bin/python</font>
-
-import lldb
-import commands
-import optparse
-import shlex
-
-def ls(debugger, command, result, internal_dict):
- print >>result, (commands.getoutput('/bin/ls %s' % command))
-
-<font color=green># And the initialization code to add your commands </font>
-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.'
-</tt></pre></code>
- <p>Now we can load the module into LLDB and use it</p>
-<code><pre><tt>% lldb
-(lldb) <strong>command script import ~/ls.py</strong>
-The "ls" python command has been installed and is ready for use.
-(lldb) <strong>ls -l /tmp/</strong>
-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
-</tt></pre></code>
- <p>A more interesting template has been created in the source repository that can help you to create
- lldb command quickly:</p>
- <a href="http://llvm.org/svn/llvm-project/lldb/trunk/examples/python/cmdtemplate.py">cmdtemplate.py</a>
- <p>
- 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:
- <code><pre><tt>
-#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;
-}
- </tt></pre></code>
- you may want a pofoo X command, that equates po [ModifyString(X) capitalizedString].
- The following debugger interaction shows how to achieve that goal:
- <code><pre><tt>
-(lldb) <b>script</b>
-Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.
->>> <b>def pofoo_funct(debugger, command, result, internal_dict):</b>
-... <b>cmd = "po [ModifyString(" + command + ") capitalizedString]"</b>
-... <b>lldb.debugger.HandleCommand(cmd)</b>
-...
->>> ^D
-(lldb) <b>command script add pofoo -f pofoo_funct</b>
-(lldb) <b>pofoo aString</b>
-$1 = 0x000000010010aa00 Hello Worldfoobar
-(lldb) <b>pofoo anotherString</b>
-$2 = 0x000000010010aba0 Let's Be Friendsfoobar</tt></pre></code>
- </div>
- <div class="post">
- <h1 class ="postheader">Using the lldb.py module in python</h1>
- <div class="postcontent">
-
- <p>LLDB has all of its core code build into a shared library which gets
- used by the <b>lldb</b> command line application. On Mac OS X this
- shared library is a framework: <b>LLDB.framework</b> and on other
- unix variants the program is a shared library: <b>lldb.so</b>. LLDB also
- provides an lldb.py module that contains the bindings from LLDB into Python.
- To use the
- <b>LLDB.framework</b> 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 <b>PYTHONPATH</b> environment variable, adding
- a path to the directory that contains the <b>lldb.py</b> python module. On
- Mac OS X, this is contained inside the LLDB.framework, so you would do:
-
- <p>For csh and tcsh:</p>
- <p><code>% <b>setenv PYTHONPATH /Developer/Library/PrivateFrameworks/LLDB.framework/Resources/Python</b></code></p>
- <p>For sh and bash:
- <p><code>% <b>export PYTHONPATH=/Developer/Library/PrivateFrameworks/LLDB.framework/Resources/Python</b></code></p>
-
- <p> Alternately, you can append the LLDB Python directory to the <b>sys.path</b> list directly in
- your Python code before importing the lldb module.</p>
-
- <p>
- 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:
-
- </p>
-<code><pre><tt><font color=green>#!/usr/bin/python</font>
-
-import lldb
-import os
-
-def disassemble_instructions(insts):
- for i in insts:
- print i
-
-<font color=green># Set the path to the executable to debug</font>
-exe = "./a.out"
-
-<font color=green># Create a new debugger instance</font>
-debugger = lldb.SBDebugger.Create()
-
-<font color=green># 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.</font>
-debugger.SetAsync (False)
-
-<font color=green># Create a target from a file and arch</font>
-print "Creating a target for '%s'" % exe
-
-target = debugger.CreateTargetWithFileAndArch (exe, lldb.LLDB_ARCH_DEFAULT)
-
-if target:
- <font color=green># If the target is valid set a breakpoint at main</font>
- main_bp = target.BreakpointCreateByName ("main", target.GetExecutable().GetFilename());
-
- print main_bp
-
- <font color=green># Launch the process. Since we specified synchronous mode, we won't return
- # from this function until we hit the breakpoint at main</font>
- process = target.LaunchSimple (None, None, os.getcwd())
-
- <font color=green># Make sure the launch went ok</font>
- if process:
- <font color=green># Print some simple process info</font>
- state = process.GetState ()
- print process
- if state == lldb.eStateStopped:
- <font color=green># Get the first thread</font>
- thread = process.GetThreadAtIndex (0)
- if thread:
- <font color=green># Print some simple thread info</font>
- print thread
- <font color=green># Get the first frame</font>
- frame = thread.GetFrameAtIndex (0)
- if frame:
- <font color=green># Print some simple frame info</font>
- print frame
- function = frame.GetFunction()
- <font color=green># See if we have debug info (a function)</font>
- if function:
- <font color=green># We do have a function, print some info for the function</font>
- print function
- <font color=green># Now get all instructions for this function and print them</font>
- insts = function.GetInstructions(target)
- disassemble_instructions (insts)
- else:
- <font color=green># See if we have a symbol in the symbol table for where we stopped</font>
- symbol = frame.GetSymbol();
- if symbol:
- <font color=green># We do have a symbol, print some info for the symbol</font>
- print symbol
-</tt></pre></code>
- </div>
- <div class="postfooter"></div>
-
- </div>
- </div>
-</div>
-</body>
-</html>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> +<link href="style.css" rel="stylesheet" type="text/css" /> +<title>LLDB Python Reference</title> +</head> + +<body> + <div class="www_title"> + LLDB Python Reference + </div> + +<div id="container"> + <div id="content"> + <!--#include virtual="sidebar.incl"--> + <div id="middle"> + <div class="post"> + <h1 class ="postheader">Introduction</h1> + <div class="postcontent"> + + <p>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. </p> + <p>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.</p> + + </div> + <div class="postfooter"></div> + <div class="post"> + <h1 class ="postheader">Documentation</h1> + <div class="postcontent"> + + <p>The LLDB API is contained in a python module named <b>lldb</b>. A useful resource when writing Python extensions is the <a href="python_reference/index.html">lldb Python classes reference guide</a>.</p> + <p>The documentation is also accessible in an interactive debugger session with the following command:</p> +<code><pre><tt>(lldb) <b>script help(lldb)</b> + 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 +... +</tt></pre></code> + <p>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:</p> +<code><pre><tt>(lldb) <b>script help(lldb.SBFrame)</b> + 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.''' + | +... +</tt></pre></code> + <p>Or you can get help using any python object, here we use the <b>lldb.process</b> object which is a global variable in the <b>lldb</b> module which represents the currently selected process:</p> +<code><pre><tt>(lldb) <b>script help(lldb.process)</b> + 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 + | # ================================================== + | +... +</tt></pre></code> + + </div> + <div class="postfooter"></div> + + <div class="post"> + <h1 class ="postheader">Embedded Python Interpreter</h1> + <div class="postcontent"> + + <p>The embedded python interpreter can be accessed in a variety of ways from within LLDB. The + easiest way is to use the lldb command <b>script</b> with no arguments at the lldb command prompt:</p> +<code><pre><tt>(lldb) <strong>script</strong> +Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D. +>>> 2+3 +5 +>>> hex(12345) +'0x3039' +>>> +</tt></pre></code> + + <p>This drops you into the embedded python interpreter. When running under the <b>script</b> 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 <b>IsValid</b> method will return false. These variables are:</p> + + <table class="stats" width="620" cellspacing="0"> + <tr> + <td class="hed" width="20%">Variable</td> + <td class="hed" width="10%">Type</td> + <td class="hed" width="70%">Description</td> + </tr> + + <tr> + <td class="content"> + <b>lldb.debugger</b> + </td> + <td class="content"> + <b>lldb.SBDebugger</b> + </td> + <td class="content"> + Contains the debugger object whose <b>script</b> command was invoked. + The <b>lldb.SBDebugger</b> object owns the command interpreter + and all the targets in your debug session. There will always be a + Debugger in the embedded interpreter. + </td> + </tr> + <tr> + <td class="content"> + <b>lldb.target</b> + </td> + <td class="content"> + <b>lldb.SBTarget</b> + </td> + <td class="content"> + Contains the currently selected target - for instance the one made with the + <b>file</b> or selected by the <b>target select <target-index></b> command. + The <b>lldb.SBTarget</b> manages one running process, and all the executable + and debug files for the process. + </td> + </tr> + <tr> + <td class="content"> + <b>lldb.process</b> + </td> + <td class="content"> + <b>lldb.SBProcess</b> + </td> + <td class="content"> + Contains the process of the currently selected target. + The <b>lldb.SBProcess</b> object manages the threads and allows access to + memory for the process. + </td> + </tr> + <tr> + <td class="content"> + <b>lldb.thread</b> + </td> + <td class="content"> + <b>lldb.SBThread</b> + </td> + <td class="content"> + Contains the currently selected thread. + The <b>lldb.SBThread</b> object manages the stack frames in that thread. + A thread is always selected in the command interpreter when a target stops. + The <b>thread select <thread-index></b> 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. + </td> + </tr> + <tr> + <td class="content"> + <b>lldb.frame</b> + </td> + <td class="content"> + <b>lldb.SBFrame</b> + </td> + <td class="content"> + Contains the currently selected stack frame. + The <b>lldb.SBFrame</b> 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 <b>frame select <frame-index></b> 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. + </td> + </tr> + </table> + + <p>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. + <p>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.</p> + + <p>To get started with these objects and LLDB scripting, please note that almost + all of the <b>lldb</b> Python objects are able to briefly describe themselves when you pass them + to the Python <b>print</b> function: +<code><pre><tt>(lldb) <b>script</b> +Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D. +>>> <strong>print lldb.debugger</strong> +Debugger (instance: "debugger_1", id: 1) +>>> <strong>print lldb.target</strong> +a.out +>>> <strong>print lldb.process</strong> +SBProcess: pid = 59289, state = stopped, threads = 1, executable = a.out +>>> <strong>print lldb.thread</strong> +SBThread: tid = 0x1f03 +>>> <strong>print lldb.frame</strong> +frame #0: 0x0000000100000bb6 a.out main + 54 at main.c:16 +</tt></pre></code> + + </div> + <div class="postfooter"></div> + + </div> + <div class="post"> + <h1 class ="postheader">Running a Python script when a breakpoint gets hit</h1> + <div class="postcontent"> + + <p>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.</p> + <p>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:</p> + <p> +<code><pre><tt>def breakpoint_function_wrapper(<b>frame</b>, <b>bp_loc</b>, <b>dict</b>): + <font color=green># Your code goes here</font> +</tt></pre></code> + <p><table class="stats" width="620" cellspacing="0"> + <tr> + <td class="hed" width="10%">Argument</td> + <td class="hed" width="10%">Type</td> + <td class="hed" width="80%">Description</td> + </tr> + + <tr> + <td class="content"> + <b>frame</b> + </td> + <td class="content"> + <b>lldb.SBFrame</b> + </td> + <td class="content"> + The current stack frame where the breakpoint got hit. + The object will always be valid. + This <b>frame</b> argument might <i>not</i> match the currently selected stack frame found in the <b>lldb</b> module global variable <b>lldb.frame</b>. + </td> + </tr> + <tr> + <td class="content"> + <b>bp_loc</b> + </td> + <td class="content"> + <b>lldb.SBBreakpointLocation</b> + </td> + <td class="content"> + The breakpoint location that just got hit. Breakpoints are represented by <b>lldb.SBBreakpoint</b> + objects. These breakpoint objects can have one or more locations. These locations + are represented by <b>lldb.SBBreakpointLocation</b> objects. + </td> + </tr> + <tr> + <td class="content"> + <b>dict</b> + </td> + <td class="content"> + <b>dict</b> + </td> + <td class="content"> + The python session dictionary as a standard python dictionary object. + </td> + </tr> + </table> + <p>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. + <p>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.</p> + <p>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 <b>lldb.SBBreakpoint</b> object + that contains an <b>lldb.SBBreakpointLocation</b> 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.</p> + <p>Note we also have to initialize our counter, which we do with the simple one-line version of the <b>script</b> + command. + <p>Here is the code: + +<code><pre><tt>(lldb) <strong>breakpoint set --func-regex=. --shlib=libfoo.dylib</strong> +Breakpoint created: 1: regex = '.', module = libfoo.dylib, locations = 223 +(lldb) <strong>script counter = 0</strong> +(lldb) <strong>breakpoint command add --script-type python 1</strong> +Enter your Python command(s). Type 'DONE' to end. +> <font color=green># Increment our counter. Since we are in a function, this must be a global python variable</font> +> <strong>global counter</strong> +> <strong>counter += 1</strong> +> <font color=green># Get the name of the function</font> +> <strong>name = frame.GetFunctionName()</strong> +> <font color=green># Print the order and the function name</font> +> <strong>print '[%i] %s' % (counter, name)</strong> +> <font color=green># Disable the current breakpoint location so it doesn't get hit again</font> +> <strong>bp_loc.SetEnabled(False)</strong> +> <font color=green># No need to stop here</font> +> <strong>return False</strong> +> <strong>DONE</strong> +</tt></pre></code> + <p>The <b>breakpoint command add</b> command above attaches a python script to breakpoint 1. + To remove the breakpoint command: + <p><code>(lldb) <strong>breakpoint command delete 1</strong></code> + </div> + </div> + <div class="post"> + <h1 class ="postheader">Create a new LLDB command using a python function</h1> + <div class="postcontent"> + + <p>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. </p> + <p>To write a python function that implements a new LDB command define the function to take four arguments as follows:</p> + + <code><pre><tt>def command_function(<b>debugger</b>, <b>command</b>, <b>result</b>, <b>internal_dict</b>): + <font color=green># Your code goes here</font> + </tt></pre></code> + + Optionally, you can also provide a Python docstring, and LLDB will use it when providing help for your command, as in: + <code><pre><tt>def command_function(<b>debugger</b>, <b>command</b>, <b>result</b>, <b>internal_dict</b>): + <font color=green>"""This command takes a lot of options and does many fancy things"""</font> + <font color=green># Your code goes here</font> + </tt></pre></code> + + <p><table class="stats" width="620" cellspacing="0"> + <tr> + <td class="hed" width="10%">Argument</td> + <td class="hed" width="10%">Type</td> + <td class="hed" width="80%">Description</td> + </tr> + + <tr> + <td class="content"> + <b>debugger</b> + </td> + <td class="content"> + <b>lldb.SBDebugger</b> + </td> + <td class="content"> + The current debugger object. + </td> + </tr> + <tr> + <td class="content"> + <b>command</b> + </td> + <td class="content"> + <b>python string</b> + </td> + <td class="content"> + A python string containing all arguments for your command. If you need to chop up the arguments + try using the <b>shlex</b> module's <code>shlex.split(command)</code> to properly extract the + arguments. + </td> + </tr> + <tr> + <td class="content"> + <b>result</b> + </td> + <td class="content"> + <b>lldb.SBCommandReturnObject</b> + </td> + <td class="content"> + 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). + </td> + </tr> + <tr> + <td class="content"> + <b>internal_dict</b> + </td> + <td class="content"> + <b>python dict object</b> + </td> + <td class="content"> + The dictionary for the current embedded script session which contains all variables + and functions. + </td> + </tr> + </table> + <p>As a convenience, you can treat the result object as a Python file object, and say + <code><pre><tt>print >>result, "my command does lots of cool stuff"</tt></pre></code> + SBCommandReturnObject and SBStream + both support this file-like behavior by providing write() and flush() calls at the Python layer.</p> + <p>One other handy convenience when defining lldb command-line commands is the command + <b>command script import</b> 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:</p> + +<code><pre><tt>def __lldb_init_module(<b>debugger</b>, <b>internal_dict</b>): + <font color=green># Command Initialization code goes here</font> +</tt></pre></code> + + <p>where <b>debugger</b> and <b>internal_dict</b> 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 <b>command script import</b>, + 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 + <u>or</u> when loaded via an <b>import</b> statement in python code + you can test the <b>lldb.debugger</b> object, since you imported the + <lldb> module at the top of the python <b>ls.py</b> module. This test + must be in code that isn't contained inside of any function or class, + just like the standard test for <b>__main__</b> like all python modules + usally do. Sample code would look like: + +<code><pre><tt>if __name__ == '__main__': + <font color=green># 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</font> + lldb.debugger = lldb.SBDebugger.Create() +elif lldb.debugger: + <font color=green># Module is being run inside the LLDB interpreter</font> + lldb.debugger.HandleCommand('command script add -f ls.ls ls') + print 'The "ls" python command has been installed and is ready for use.' +</tt></pre></code> + <p>Now we can create a module called <b>ls.py</b> in the file <b>~/ls.py</b> that will implement a function that + can be used by LLDB's python command code:</p> + +<code><pre><tt><font color=green>#!/usr/bin/python</font> + +import lldb +import commands +import optparse +import shlex + +def ls(debugger, command, result, internal_dict): + print >>result, (commands.getoutput('/bin/ls %s' % command)) + +<font color=green># And the initialization code to add your commands </font> +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.' +</tt></pre></code> + <p>Now we can load the module into LLDB and use it</p> +<code><pre><tt>% lldb +(lldb) <strong>command script import ~/ls.py</strong> +The "ls" python command has been installed and is ready for use. +(lldb) <strong>ls -l /tmp/</strong> +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 +</tt></pre></code> + <p>A more interesting template has been created in the source repository that can help you to create + lldb command quickly:</p> + <a href="http://llvm.org/svn/llvm-project/lldb/trunk/examples/python/cmdtemplate.py">cmdtemplate.py</a> + <p> + 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: + <code><pre><tt> +#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; +} + </tt></pre></code> + you may want a pofoo X command, that equates po [ModifyString(X) capitalizedString]. + The following debugger interaction shows how to achieve that goal: + <code><pre><tt> +(lldb) <b>script</b> +Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D. +>>> <b>def pofoo_funct(debugger, command, result, internal_dict):</b> +... <b>cmd = "po [ModifyString(" + command + ") capitalizedString]"</b> +... <b>lldb.debugger.HandleCommand(cmd)</b> +... +>>> ^D +(lldb) <b>command script add pofoo -f pofoo_funct</b> +(lldb) <b>pofoo aString</b> +$1 = 0x000000010010aa00 Hello Worldfoobar +(lldb) <b>pofoo anotherString</b> +$2 = 0x000000010010aba0 Let's Be Friendsfoobar</tt></pre></code> + </div> + <div class="post"> + <h1 class ="postheader">Using the lldb.py module in python</h1> + <div class="postcontent"> + + <p>LLDB has all of its core code build into a shared library which gets + used by the <b>lldb</b> command line application. On Mac OS X this + shared library is a framework: <b>LLDB.framework</b> and on other + unix variants the program is a shared library: <b>lldb.so</b>. LLDB also + provides an lldb.py module that contains the bindings from LLDB into Python. + To use the + <b>LLDB.framework</b> 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 <b>PYTHONPATH</b> environment variable, adding + a path to the directory that contains the <b>lldb.py</b> python module. On + Mac OS X, this is contained inside the LLDB.framework, so you would do: + + <p>For csh and tcsh:</p> + <p><code>% <b>setenv PYTHONPATH /Developer/Library/PrivateFrameworks/LLDB.framework/Resources/Python</b></code></p> + <p>For sh and bash: + <p><code>% <b>export PYTHONPATH=/Developer/Library/PrivateFrameworks/LLDB.framework/Resources/Python</b></code></p> + + <p> Alternately, you can append the LLDB Python directory to the <b>sys.path</b> list directly in + your Python code before importing the lldb module.</p> + + <p> + 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: + + </p> +<code><pre><tt><font color=green>#!/usr/bin/python</font> + +import lldb +import os + +def disassemble_instructions(insts): + for i in insts: + print i + +<font color=green># Set the path to the executable to debug</font> +exe = "./a.out" + +<font color=green># Create a new debugger instance</font> +debugger = lldb.SBDebugger.Create() + +<font color=green># 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.</font> +debugger.SetAsync (False) + +<font color=green># Create a target from a file and arch</font> +print "Creating a target for '%s'" % exe + +target = debugger.CreateTargetWithFileAndArch (exe, lldb.LLDB_ARCH_DEFAULT) + +if target: + <font color=green># If the target is valid set a breakpoint at main</font> + main_bp = target.BreakpointCreateByName ("main", target.GetExecutable().GetFilename()); + + print main_bp + + <font color=green># Launch the process. Since we specified synchronous mode, we won't return + # from this function until we hit the breakpoint at main</font> + process = target.LaunchSimple (None, None, os.getcwd()) + + <font color=green># Make sure the launch went ok</font> + if process: + <font color=green># Print some simple process info</font> + state = process.GetState () + print process + if state == lldb.eStateStopped: + <font color=green># Get the first thread</font> + thread = process.GetThreadAtIndex (0) + if thread: + <font color=green># Print some simple thread info</font> + print thread + <font color=green># Get the first frame</font> + frame = thread.GetFrameAtIndex (0) + if frame: + <font color=green># Print some simple frame info</font> + print frame + function = frame.GetFunction() + <font color=green># See if we have debug info (a function)</font> + if function: + <font color=green># We do have a function, print some info for the function</font> + print function + <font color=green># Now get all instructions for this function and print them</font> + insts = function.GetInstructions(target) + disassemble_instructions (insts) + else: + <font color=green># See if we have a symbol in the symbol table for where we stopped</font> + symbol = frame.GetSymbol(); + if symbol: + <font color=green># We do have a symbol, print some info for the symbol</font> + print symbol +</tt></pre></code> + </div> + <div class="postfooter"></div> + + </div> + </div> +</div> +</body> +</html> diff --git a/lldb/www/scripting.html b/lldb/www/scripting.html index dfd858abdfb..7e86acfaa8e 100755 --- a/lldb/www/scripting.html +++ b/lldb/www/scripting.html @@ -1,586 +1,586 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
-<link href="style.css" rel="stylesheet" type="text/css" />
-<title>LLDB Example - Python Scripting to Debug a Problem</title>
-</head>
-
-<body>
- <div class="www_title">
- Example - Using Scripting and Python to Debug in LLDB
- </div>
-
-<div id="container">
- <div id="content">
- <!--#include virtual="sidebar.incl"-->
- <div id="middle">
- <div class="post">
- <h1 class ="postheader">Introduction</h1>
- <div class="postcontent">
-
- <p>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.</p>
-
- </div>
- <div class="postfooter"></div>
-
- <div class="post">
- <h1 class ="postheader">The Test Program and Input</h1>
- <div class="postcontent">
-
- <p>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.</p>
-
- <p>The input text file we are using to test our program contains the text for
- William Shakespeare's famous tragedy "Romeo and Juliet".</p>
-
- </div>
- <div class="postfooter"></div>
-
- <div class="post">
- <h1 class ="postheader">The Bug</h1>
- <div class="postcontent">
-
- <p>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:</p>
-
- <code color=#ff0000>
- % ./dictionary Romeo-and-Juliet.txt<br>
- Dictionary loaded.<br>
- Enter search word: love<br>
- Yes!<br>
- Enter search word: sun<br>
- Yes!<br>
- Enter search word: Romeo<br>
- No!<br>
- Enter search word: ^D<br>
- %<br>
- </code>
-
- </div>
- <div class="postfooter"></div>
-
-
- <div class="post">
- <h1 class ="postheader">Is the word in our tree: Using Depth First Search</h1>
- <div class="postcontent">
-
- <p>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:</p>
-
- <code>
-<pre><tt>
- 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)
-</tt></pre>
- </code>
-
- </div>
- <div class="postfooter"></div>
-
-
- <div class="post">
- <h1 class ="postheader"><a name="accessing-variables">Accessing & Manipulating <strong>Program</strong> Variables in Python</a>
-</h1>
- <div class="postcontent">
-
- <p>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.</p>
-
- <p>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:</p>
-
- <code>
- root = lldb.frame.FindVariable ("dictionary")
- </code>
-
- <p>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 <a href="http://llvm.org/svn/llvm-project/lldb/trunk/include/lldb/API/SBValue.h">SBValue.h</a>. The
- SBValue methods that we use in our DFS function are
- <code>GetChildMemberWithName()</code>,
- <code>GetSummary()</code>, and <code>GetValue()</code>.</p>
-
- </div>
- <div class="postfooter"></div>
-
-
- <div class="post">
- <h1 class ="postheader">Explaining Depth First Search Script in Detail</h1>
- <div class="postcontent">
-
- <p><strong>"DFS" Overview.</strong> 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 <code>tree_node *</code>,
- which is defined as:
-
- <code>
-<pre><tt>typedef struct tree_node
-{
- const char *word;
- struct tree_node *left;
- struct tree_node *right;
-} tree_node;</tt></pre></code>
-
- <p>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 <code>word</code>, <code>left</code> and
- <code>right</code> fields out of the current node and store them in Python
- variables. Since <code>root_word_ptr</code> is a pointer to our word, and we
- want the actual word, line 5 calls <code>GetSummary()</code> to get a string
- containing the value out of the pointer. Since <code>GetSummary()</code> adds
- quotes around its result, lines 6-11 strip surrounding quotes off the word.</p>
-
- <p>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.</p>
-
- <p>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.</p>
-
- </div>
- <div class="postfooter"></div>
-
-
- <div class="post">
- <h1 class ="postheader">Seeing the DFS Script in Action</h1>
- <div class="postcontent">
-
-
- <p>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:</p>
-
- <code>
- % <strong>lldb</strong><br>
- (lldb) <strong>process attach -n "dictionary"</strong><br>
- Architecture set to: x86_64.<br>
- Process 521 stopped<br>
- * thread #1: tid = 0x2c03, 0x00007fff86c8bea0 libSystem.B.dylib`read$NOCANCEL + 8, stop reason = signal SIGSTOP<br>
- frame #0: 0x00007fff86c8bea0 libSystem.B.dylib`read$NOCANCEL + 8<br>
- (lldb) <strong>breakpoint set -n find_word</strong><br>
- Breakpoint created: 1: name = 'find_word', locations = 1, resolved = 1<br>
- (lldb) <strong>continue</strong><br>
- Process 521 resuming<br>
- Process 521 stopped<br>
- * thread #1: tid = 0x2c03, 0x0000000100001830 dictionary`find_word + 16 <br>
- at dictionary.c:105, stop reason = breakpoint 1.1<br>
- frame #0: 0x0000000100001830 dictionary`find_word + 16 at dictionary.c:105<br>
- 102 int<br>
- 103 find_word (tree_node *dictionary, char *word)<br>
- 104 {<br>
- -> 105 if (!word || !dictionary)<br>
- 106 return 0;<br>
- 107 <br>
- 108 int compare_value = strcmp (word, dictionary->word);<br>
- (lldb) <strong>script</strong><br>
- Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.<br>
- >>> <strong>import tree_utils</strong><br>
- >>> <strong>root = lldb.frame.FindVariable ("dictionary")</strong><br>
- >>> <strong>current_path = ""</strong><br>
- >>> <strong>path = tree_utils.DFS (root, "Romeo", current_path)</strong><br>
- >>> <strong>print path</strong><br>
- LLRRL<br>
- >>> <strong>^D</strong><br>
- (lldb) <br>
- </code>
-
- <p>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
- <code>script</code> command and drop into the embedded interactive Python
- interpreter. We will go over this Python code line by line. The first line</p>
-
- <code>
- import tree_utils
- </code>
-
- <p>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</p>
-
- <code>
- root = lldb.frame.FindVariable ("dictionary")
- </code>
-
- <p>gets our program variable "dictionary" (which contains the binary search
- tree) and puts it into the Python variable "root". See
- <a href="#accessing-variables">Accessing & Manipulating Program Variables in Python</a>
- above for more details about how this works. The next line is</p>
-
- <code>
- current_path = ""
- </code>
-
- <p>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</p>
-
- <code>
- path = tree_utils.DFS (root, "Romeo", current_path)
- </code>
-
- <p>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 <code>root</code>,
- the word we are searching for, and our current path. We assign whatever path
- the DFS function returns to the Python variable <code>path</code>.</p>
-
-
- <p>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</p>
-
- <code>
- print path
- </code>
-
- <p>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.</p>
-
- </div>
- <div class="postfooter"></div>
-
-
- <div class="post">
- <h1 class ="postheader">What next? Using Breakpoint Command Scripts...</h1>
- <div class="postcontent">
-
- <p>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.</p>
-
-
- <p>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 <code>path</code> 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
- <code>path</code> 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.</p>
-
- </div>
- <div class="postfooter"></div>
-
-
- <div class="post">
- <h1 class ="postheader">Side Note: Python Breakpoint Command Scripts are NOT What They Seem</h1>
- <div class="postcontent">
-
- </div>
- <div class="postfooter"></div>
-
- <p>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:
- <code>frame</code> and <code>bp_loc</code>. 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.</p>
-
- <p>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,
- <strong>you must declare such variables to be global</strong>. 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. <strong>All Python
- breakpoint command scripts automatically have a <code>frame</code> and a
- <code>bp_loc</code> variable.</strong> 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.</p>
-
- </div>
- <div class="postfooter"></div>
-
-
- <div class="post">
- <h1 class ="postheader">The Decision Point Breakpoint Commands</h1>
- <div class="postcontent">
-
- <p>This is what the Python breakpoint command script would look like for the
- decision to go right:<p>
-
-<code><pre><tt>
-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!"
-</tt></pre></code>
-
- <p>Just as a reminder, LLDB is going to take this script and wrap it up in a
- function, like this:</p>
-
-<code><pre><tt>
-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!"
-</tt></pre></code>
-
- <p>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 <code>path</code> 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.</p>
-
- <p>Since the decision matched the path, we want to resume execution. To do this
- we make use of the <code>frame</code> 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 <code>Continue()</code> API
- function).</p>
-
- <p>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.</p>
-
- </div>
- <div class="postfooter"></div>
-
- <div class="post">
- <h1 class ="postheader">Actually Using the Breakpoint Commands</h1>
- <div class="postcontent">
-
- <p>Now we will look at what happens when we actually use these breakpoint
- commands on our program. Doing a <code>source list -n find_word</code> 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:</p>
-
-<code><pre><tt>
-(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
-</tt></pre></code>
-
- <p>So, we set our breakpoints, enter our breakpoint command scripts, and see
- what happens:<p>
-
-<code><pre><tt>
-(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)
-</tt></pre></code>
-
-
- <p>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:</p>
-
- <code>
- (lldb) expr dictionary->word<br>
- (const char *) $1 = 0x0000000100100080 "dramatis"<br>
- (lldb) expr word<br>
- (char *) $2 = 0x00007fff5fbff108 "romeo"<br>
- </code>
-
- <p>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:</p>
-
- <code>
- (lldb) script print path<br>
- LLRRL<br>
- </code>
-
- <p>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:</p>
-
- <code>
- (lldb) expr dictionary->left->left->right->right->left->word<br>
- (const char *) $4 = 0x0000000100100880 "Romeo"<br>
- </code>
-
- <p>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).</p>
-
- <p>This is the end of our example on how you might use Python scripting in LLDB
- to help you find bugs in your program.</p>
-
- </div>
- <div class="postfooter"></div>
-
- <div class="post">
- <h1 class ="postheader">Source Files for The Example</h1>
- <div class="postcontent">
-
-
- </div>
- <div class="postfooter"></div>
-
- <p> 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:</p>
-
-<a href="http://llvm.org/svn/llvm-project/lldb/trunk/examples/scripting/tree_utils.py">tree_utils.py</a> - Example Python functions using LLDB's API, including DFS<br>
-<a href="http://llvm.org/svn/llvm-project/lldb/trunk/examples/scripting/dictionary.c">dictionary.c</a> - Sample dictionary program, with bug<br>
-
- <p>The text for "Romeo and Juliet" can be obtained from the Gutenberg Project
- (http://www.gutenberg.org).</p>
- </div>
- </div>
- </div>
-</div>
-</body>
-</html>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> +<link href="style.css" rel="stylesheet" type="text/css" /> +<title>LLDB Example - Python Scripting to Debug a Problem</title> +</head> + +<body> + <div class="www_title"> + Example - Using Scripting and Python to Debug in LLDB + </div> + +<div id="container"> + <div id="content"> + <!--#include virtual="sidebar.incl"--> + <div id="middle"> + <div class="post"> + <h1 class ="postheader">Introduction</h1> + <div class="postcontent"> + + <p>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.</p> + + </div> + <div class="postfooter"></div> + + <div class="post"> + <h1 class ="postheader">The Test Program and Input</h1> + <div class="postcontent"> + + <p>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.</p> + + <p>The input text file we are using to test our program contains the text for + William Shakespeare's famous tragedy "Romeo and Juliet".</p> + + </div> + <div class="postfooter"></div> + + <div class="post"> + <h1 class ="postheader">The Bug</h1> + <div class="postcontent"> + + <p>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:</p> + + <code color=#ff0000> + % ./dictionary Romeo-and-Juliet.txt<br> + Dictionary loaded.<br> + Enter search word: love<br> + Yes!<br> + Enter search word: sun<br> + Yes!<br> + Enter search word: Romeo<br> + No!<br> + Enter search word: ^D<br> + %<br> + </code> + + </div> + <div class="postfooter"></div> + + + <div class="post"> + <h1 class ="postheader">Is the word in our tree: Using Depth First Search</h1> + <div class="postcontent"> + + <p>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:</p> + + <code> +<pre><tt> + 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) +</tt></pre> + </code> + + </div> + <div class="postfooter"></div> + + + <div class="post"> + <h1 class ="postheader"><a name="accessing-variables">Accessing & Manipulating <strong>Program</strong> Variables in Python</a> +</h1> + <div class="postcontent"> + + <p>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.</p> + + <p>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:</p> + + <code> + root = lldb.frame.FindVariable ("dictionary") + </code> + + <p>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 <a href="http://llvm.org/svn/llvm-project/lldb/trunk/include/lldb/API/SBValue.h">SBValue.h</a>. The + SBValue methods that we use in our DFS function are + <code>GetChildMemberWithName()</code>, + <code>GetSummary()</code>, and <code>GetValue()</code>.</p> + + </div> + <div class="postfooter"></div> + + + <div class="post"> + <h1 class ="postheader">Explaining Depth First Search Script in Detail</h1> + <div class="postcontent"> + + <p><strong>"DFS" Overview.</strong> 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 <code>tree_node *</code>, + which is defined as: + + <code> +<pre><tt>typedef struct tree_node +{ + const char *word; + struct tree_node *left; + struct tree_node *right; +} tree_node;</tt></pre></code> + + <p>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 <code>word</code>, <code>left</code> and + <code>right</code> fields out of the current node and store them in Python + variables. Since <code>root_word_ptr</code> is a pointer to our word, and we + want the actual word, line 5 calls <code>GetSummary()</code> to get a string + containing the value out of the pointer. Since <code>GetSummary()</code> adds + quotes around its result, lines 6-11 strip surrounding quotes off the word.</p> + + <p>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.</p> + + <p>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.</p> + + </div> + <div class="postfooter"></div> + + + <div class="post"> + <h1 class ="postheader">Seeing the DFS Script in Action</h1> + <div class="postcontent"> + + + <p>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:</p> + + <code> + % <strong>lldb</strong><br> + (lldb) <strong>process attach -n "dictionary"</strong><br> + Architecture set to: x86_64.<br> + Process 521 stopped<br> + * thread #1: tid = 0x2c03, 0x00007fff86c8bea0 libSystem.B.dylib`read$NOCANCEL + 8, stop reason = signal SIGSTOP<br> + frame #0: 0x00007fff86c8bea0 libSystem.B.dylib`read$NOCANCEL + 8<br> + (lldb) <strong>breakpoint set -n find_word</strong><br> + Breakpoint created: 1: name = 'find_word', locations = 1, resolved = 1<br> + (lldb) <strong>continue</strong><br> + Process 521 resuming<br> + Process 521 stopped<br> + * thread #1: tid = 0x2c03, 0x0000000100001830 dictionary`find_word + 16 <br> + at dictionary.c:105, stop reason = breakpoint 1.1<br> + frame #0: 0x0000000100001830 dictionary`find_word + 16 at dictionary.c:105<br> + 102 int<br> + 103 find_word (tree_node *dictionary, char *word)<br> + 104 {<br> + -> 105 if (!word || !dictionary)<br> + 106 return 0;<br> + 107 <br> + 108 int compare_value = strcmp (word, dictionary->word);<br> + (lldb) <strong>script</strong><br> + Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.<br> + >>> <strong>import tree_utils</strong><br> + >>> <strong>root = lldb.frame.FindVariable ("dictionary")</strong><br> + >>> <strong>current_path = ""</strong><br> + >>> <strong>path = tree_utils.DFS (root, "Romeo", current_path)</strong><br> + >>> <strong>print path</strong><br> + LLRRL<br> + >>> <strong>^D</strong><br> + (lldb) <br> + </code> + + <p>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 + <code>script</code> command and drop into the embedded interactive Python + interpreter. We will go over this Python code line by line. The first line</p> + + <code> + import tree_utils + </code> + + <p>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</p> + + <code> + root = lldb.frame.FindVariable ("dictionary") + </code> + + <p>gets our program variable "dictionary" (which contains the binary search + tree) and puts it into the Python variable "root". See + <a href="#accessing-variables">Accessing & Manipulating Program Variables in Python</a> + above for more details about how this works. The next line is</p> + + <code> + current_path = "" + </code> + + <p>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</p> + + <code> + path = tree_utils.DFS (root, "Romeo", current_path) + </code> + + <p>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 <code>root</code>, + the word we are searching for, and our current path. We assign whatever path + the DFS function returns to the Python variable <code>path</code>.</p> + + + <p>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</p> + + <code> + print path + </code> + + <p>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.</p> + + </div> + <div class="postfooter"></div> + + + <div class="post"> + <h1 class ="postheader">What next? Using Breakpoint Command Scripts...</h1> + <div class="postcontent"> + + <p>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.</p> + + + <p>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 <code>path</code> 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 + <code>path</code> 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.</p> + + </div> + <div class="postfooter"></div> + + + <div class="post"> + <h1 class ="postheader">Side Note: Python Breakpoint Command Scripts are NOT What They Seem</h1> + <div class="postcontent"> + + </div> + <div class="postfooter"></div> + + <p>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: + <code>frame</code> and <code>bp_loc</code>. 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.</p> + + <p>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, + <strong>you must declare such variables to be global</strong>. 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. <strong>All Python + breakpoint command scripts automatically have a <code>frame</code> and a + <code>bp_loc</code> variable.</strong> 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.</p> + + </div> + <div class="postfooter"></div> + + + <div class="post"> + <h1 class ="postheader">The Decision Point Breakpoint Commands</h1> + <div class="postcontent"> + + <p>This is what the Python breakpoint command script would look like for the + decision to go right:<p> + +<code><pre><tt> +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!" +</tt></pre></code> + + <p>Just as a reminder, LLDB is going to take this script and wrap it up in a + function, like this:</p> + +<code><pre><tt> +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!" +</tt></pre></code> + + <p>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 <code>path</code> 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.</p> + + <p>Since the decision matched the path, we want to resume execution. To do this + we make use of the <code>frame</code> 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 <code>Continue()</code> API + function).</p> + + <p>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.</p> + + </div> + <div class="postfooter"></div> + + <div class="post"> + <h1 class ="postheader">Actually Using the Breakpoint Commands</h1> + <div class="postcontent"> + + <p>Now we will look at what happens when we actually use these breakpoint + commands on our program. Doing a <code>source list -n find_word</code> 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:</p> + +<code><pre><tt> +(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 +</tt></pre></code> + + <p>So, we set our breakpoints, enter our breakpoint command scripts, and see + what happens:<p> + +<code><pre><tt> +(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) +</tt></pre></code> + + + <p>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:</p> + + <code> + (lldb) expr dictionary->word<br> + (const char *) $1 = 0x0000000100100080 "dramatis"<br> + (lldb) expr word<br> + (char *) $2 = 0x00007fff5fbff108 "romeo"<br> + </code> + + <p>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:</p> + + <code> + (lldb) script print path<br> + LLRRL<br> + </code> + + <p>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:</p> + + <code> + (lldb) expr dictionary->left->left->right->right->left->word<br> + (const char *) $4 = 0x0000000100100880 "Romeo"<br> + </code> + + <p>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).</p> + + <p>This is the end of our example on how you might use Python scripting in LLDB + to help you find bugs in your program.</p> + + </div> + <div class="postfooter"></div> + + <div class="post"> + <h1 class ="postheader">Source Files for The Example</h1> + <div class="postcontent"> + + + </div> + <div class="postfooter"></div> + + <p> 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:</p> + +<a href="http://llvm.org/svn/llvm-project/lldb/trunk/examples/scripting/tree_utils.py">tree_utils.py</a> - Example Python functions using LLDB's API, including DFS<br> +<a href="http://llvm.org/svn/llvm-project/lldb/trunk/examples/scripting/dictionary.c">dictionary.c</a> - Sample dictionary program, with bug<br> + + <p>The text for "Romeo and Juliet" can be obtained from the Gutenberg Project + (http://www.gutenberg.org).</p> + </div> + </div> + </div> +</div> +</body> +</html> diff --git a/lldb/www/source.html b/lldb/www/source.html index a8c04189819..91ed971089e 100755 --- a/lldb/www/source.html +++ b/lldb/www/source.html @@ -1,51 +1,51 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
-<link href="style.css" rel="stylesheet" type="text/css" />
-<title>Accessing LLDB Sources</title>
-</head>
-
-<body>
- <div class="www_title">
- The <strong>LLDB</strong> Debugger
- </div>
-
-<div id="container">
- <div id="content">
-
- <!--#include virtual="sidebar.incl"-->
-
- <div id="middle">
- <div class="post">
- <h1 class ="postheader">Downloading LLDB sources</h1>
- <div class="postcontent">
- <p>Obtaining read only access to the LLDB sources is easy:</p>
- <ul>
- <li>svn co http://llvm.org/svn/llvm-project/lldb/trunk lldb</li>
- </ul>
- <p>If you prefer using Git, you can check out LLDB from the <a href="http://llvm.org/docs/GettingStarted.html#git-mirror">LLVM git mirror</a> instead:</p>
- <ul>
- <li>git clone http://llvm.org/git/lldb.git</li>
- </ul>
- </div>
- <div class="postfooter"></div>
- </div>
- <div class="post">
- <h1 class ="postheader">Contributing to LLDB</h1>
- <div class="postcontent">
- <p>If you wish to contribute to LLDB, you must first get commit access by
- <a href="http://llvm.org/docs/DeveloperPolicy.html#commitaccess">requesting commit access</a></p>
- <p>Once you have commit access, you will have a <b>USERNAME</b> and you can checkout the sources:
- <a href="http://llvm.org/docs/DeveloperPolicy.html#commitaccess">requesting commit access</a></p>
- <ul>
- <li>svn co https://USERNAME@llvm.org/svn/llvm-project/lldb/trunk lldb</li>
- </ul>
- </div>
- <div class="postfooter"></div>
- </div>
- </div>
- </div>
-</div>
-</body>
-</html>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> +<link href="style.css" rel="stylesheet" type="text/css" /> +<title>Accessing LLDB Sources</title> +</head> + +<body> + <div class="www_title"> + The <strong>LLDB</strong> Debugger + </div> + +<div id="container"> + <div id="content"> + + <!--#include virtual="sidebar.incl"--> + + <div id="middle"> + <div class="post"> + <h1 class ="postheader">Downloading LLDB sources</h1> + <div class="postcontent"> + <p>Obtaining read only access to the LLDB sources is easy:</p> + <ul> + <li>svn co http://llvm.org/svn/llvm-project/lldb/trunk lldb</li> + </ul> + <p>If you prefer using Git, you can check out LLDB from the <a href="http://llvm.org/docs/GettingStarted.html#git-mirror">LLVM git mirror</a> instead:</p> + <ul> + <li>git clone http://llvm.org/git/lldb.git</li> + </ul> + </div> + <div class="postfooter"></div> + </div> + <div class="post"> + <h1 class ="postheader">Contributing to LLDB</h1> + <div class="postcontent"> + <p>If you wish to contribute to LLDB, you must first get commit access by + <a href="http://llvm.org/docs/DeveloperPolicy.html#commitaccess">requesting commit access</a></p> + <p>Once you have commit access, you will have a <b>USERNAME</b> and you can checkout the sources: + <a href="http://llvm.org/docs/DeveloperPolicy.html#commitaccess">requesting commit access</a></p> + <ul> + <li>svn co https://USERNAME@llvm.org/svn/llvm-project/lldb/trunk lldb</li> + </ul> + </div> + <div class="postfooter"></div> + </div> + </div> + </div> +</div> +</body> +</html> diff --git a/lldb/www/style.css b/lldb/www/style.css index 6e96fefacbb..a3dabc2d913 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 877c1f10bd4..4945ff3e9ba 100755 --- a/lldb/www/symbolication.html +++ b/lldb/www/symbolication.html @@ -1,363 +1,363 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
-<link href="style.css" rel="stylesheet" type="text/css" />
-<title>Symbolicating with LLDB</title>
-</head>
-
-<body>
- <div class="www_title">
- The <strong>LLDB</strong> Debugger
- </div>
-
-<div id="container">
- <div id="content">
-
- <!--#include virtual="sidebar.incl"-->
-
- <div id="middle">
- <div class="post">
- <h1 class="postheader">Manual Symbolication with LLDB</h1>
- <div class="postcontent">
- <p>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:
- </p>
- <ul>
- <li>Inlined functions</li>
- <li>Variables that are in scope for an address, along with their locations</li>
- </ul>
- <p>The simplest form of symbolication is to load an executable:</p>
-<code><pre><tt><b>(lldb)</b> target create --no-dependents --arch x86_64 /tmp/a.out
-</tt></pre></code>
- <p>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.</p>
- <p>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:
- </p>
- <code><pre><tt><b>(lldb)</b> image list
-[ 0] 73431214-6B76-3489-9557-5075F03E36B4 0x0000000100000000 /tmp/a.out
- /tmp/a.out.dSYM/Contents/Resources/DWARF/a.out
-</tt></pre></code>
-
- <p>Now we can look up an address:</p>
-<code><pre><tt><b>(lldb)</b> image lookup --address 0x100000aa3
- Address: a.out[0x0000000100000aa3] (a.out.__TEXT.__text + 131)
- Summary: a.out`main + 67 at main.c:13
-</tt></pre></code>
- <p>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 <b>file</b> address. A <b>file</b>
- address refers to a virtual address as defined by each object file.
- </p>
- <p>If we didn't use the "--no-dependents" option with "target create", we would
- have loaded all dependent shared libraries:<p>
- <code><pre><tt><b>(lldb)</b> 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
-...
-</tt></pre></code>
-
-
- <p>Now if we do a lookup using a <b>file</b> address, this can result in multiple
- matches since most shared libraries have a virtual address space that starts at zero:</p>
-<code><pre><tt><b>(lldb)</b> 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
-...
-</tt></pre></code>
- <p>To avoid getting multiple file address matches, you can specify the
- <b>name</b> of the shared library to limit the search:</p>
-<code><pre><tt><b>(lldb)</b> image lookup -a 0x1000 <b>a.out</b>
- Address: a.out[0x0000000000001000] (a.out.__PAGEZERO + 4096)
-</tt></pre></code>
- </div>
- <div class="postfooter"></div>
- </div>
- <div class="post">
- <h1 class="postheader">Defining Load Addresses for Sections</h1>
- <div class="postcontent">
- <p>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
- <b>load</b> addresses. You can slide all sections in the executable by the same amount,
- or set the <b>load</b> address for individual sections. The
- "target modules load --slide" command allows us to set the <b>load</b> address for
- all sections.
- <p>Below is an example of sliding all sections in <b>a.out</b> by adding 0x123000 to each section's <b>file</b> address:</p>
-<code><pre><tt><b>(lldb)</b> target create --no-dependents --arch x86_64 /tmp/a.out
-<b>(lldb)</b> target modules load --file a.out --slide 0x123000
-</tt></pre></code>
- <p>It is often much easier to specify the actual load location of each section by name.
- Crash logs on Mac OS X have a <b>Binary Images</b> section that specifies
- that address of the __TEXT segment for each binary. Specifying a slide requires
- requires that you first find the original (<b>file</b>) address for the __TEXT
- segment, and subtract the two values.
- If you specify the
- address of the __TEXT segment with "target modules load <i>section</i> <i>address</i>", 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:</p>
-<code><pre><tt><b>(lldb)</b> target create --no-dependents --arch x86_64 /tmp/a.out
-<b>(lldb)</b> target modules load --file a.out __TEXT 0x100123000
-</tt></pre></code>
- <p>We specified that the <b>__TEXT</b> 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 <b>load</b> addresses so we don't have to
- do any math on the addresses in the crashlog backtraces, we can just use the
- raw addresses:</p>
-<code><pre><tt><b>(lldb)</b> image lookup --address 0x100123aa3
- Address: a.out[0x0000000100000aa3] (a.out.__TEXT.__text + 131)
- Summary: a.out`main + 67 at main.c:13
-</tt></pre></code>
- </div>
- <div class="postfooter"></div>
- </div>
- <div class="post">
- <h1 class="postheader">Loading Multiple Executables</h1>
- <div class="postcontent">
- <p>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.<p>
- <p>Lets say we have a Darwin crash log that contains the following images:
-<code><pre><tt>Binary Images:
- <font color=blue>0x100000000</font> - 0x100000ff7 <A866975B-CA1E-3649-98D0-6C5FAA444ECF> /tmp/a.out
- <font color=green>0x7fff83f32000</font> - 0x7fff83ffefe7 <8CBCF9B9-EBB7-365E-A3FF-2F3850763C6B> /usr/lib/system/libsystem_c.dylib
- <font color=red>0x7fff883db000</font> - 0x7fff883e3ff7 <62AA0B84-188A-348B-8F9E-3E2DB08DB93C> /usr/lib/system/libsystem_dnssd.dylib
- <font color=purple>0x7fff8c0dc000</font> - 0x7fff8c0f7ff7 <C0535565-35D1-31A7-A744-63D9F10F12A4> /usr/lib/system/libsystem_kernel.dylib
-</tt></pre></code>
-
- <p>First we create the target using the main executable and then add any extra shared libraries we want:</p>
-<code><pre><tt><b>(lldb)</b> target create --no-dependents --arch x86_64 /tmp/a.out
-<b>(lldb)</b> target modules add /usr/lib/system/libsystem_c.dylib
-<b>(lldb)</b> target modules add /usr/lib/system/libsystem_dnssd.dylib
-<b>(lldb)</b> target modules add /usr/lib/system/libsystem_kernel.dylib
-</tt></pre></code>
- <p>If you have debug symbols in standalone files, such as dSYM files on Mac OS X, you can specify their paths using the <b>--symfile</b> option for the "target create" (recent LLDB releases only) and "target modules add" commands:</p>
-<code><pre><tt><b>(lldb)</b> target create --no-dependents --arch x86_64 /tmp/a.out <b>--symfile /tmp/a.out.dSYM</b>
-<b>(lldb)</b> target modules add /usr/lib/system/libsystem_c.dylib <b>--symfile /build/server/a/libsystem_c.dylib.dSYM</b>
-<b>(lldb)</b> target modules add /usr/lib/system/libsystem_dnssd.dylib <b>--symfile /build/server/b/libsystem_dnssd.dylib.dSYM</b>
-<b>(lldb)</b> target modules add /usr/lib/system/libsystem_kernel.dylib <b>--symfile /build/server/c/libsystem_kernel.dylib.dSYM</b>
-</tt></pre></code>
- <p>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:</p>
-<code><pre><tt><b>(lldb)</b> target modules load --file a.out <font color=blue>0x100000000</font>
-<b>(lldb)</b> target modules load --file libsystem_c.dylib <font color=green>0x7fff83f32000</font>
-<b>(lldb)</b> target modules load --file libsystem_dnssd.dylib <font color=red>0x7fff883db000</font>
-<b>(lldb)</b> target modules load --file libsystem_kernel.dylib <font color=purple>0x7fff8c0dc000</font>
-</tt></pre></code>
- <p>Now any stack backtraces that haven't been symbolicated can be symbolicated using "image lookup"
- with the raw backtrace addresses.</p>
- <p>Given the following raw backtrace:</p>
-<code><pre><tt>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
-</tt></pre></code>
- <p>We can now symbolicate the <b>load</b> addresses:<p>
-<code><pre><tt><b>(lldb)</b> image lookup -a 0x00007fff8a1e6d46
-<b>(lldb)</b> image lookup -a 0x00007fff84597df0
-<b>(lldb)</b> image lookup -a 0x00007fff84598e2a
-<b>(lldb)</b> image lookup -a 0x0000000100000f46
-</tt></pre></code>
- </div>
- <div class="postfooter"></div>
- </div>
- <div class="post">
- <h1 class="postheader">Getting Variable Information</h1>
- <div class="postcontent">
- <p>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:
-<code><pre><tt>><b>(lldb)</b> 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", <b>location = r13</b>, decl = main.c:8
- Variable: id = {0x00000081}, name = "argv", type= "const char **", <b>location = r12</b>, decl = main.c:8
- Variable: id = {0x00000090}, name = "envp", type= "const char **", <b>location = r15</b>, decl = main.c:8
- Variable: id = {0x0000009f}, name = "aapl", type= "const char **", <b>location = rbx</b>, decl = main.c:8
-</tt></pre></code>
- <p>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.
- </div>
- <div class="postfooter"></div>
- </div>
- <div class="post">
- <h1 class="postheader">Using Python API to Symbolicate</h1>
- <div class="postcontent">
- <p>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:
-<code><pre><tt>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:
- <font color=green># Get the executable module</font>
- 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
- <font color=green># so_addr is a section offset address, or a lldb.SBAddress object</font>
- so_addr = target.ResolveLoadAddress (load_addr)
- <font color=green># Get a symbol context for the section offset address which includes
- # a module, compile unit, function, block, line entry, and symbol</font>
- sym_ctx = so_addr.GetSymbolContext (lldb.eSymbolContextEverything)
- print sym_ctx
-
-</tt></pre></code>
- </div>
- <div class="postfooter"></div>
- </div>
- <div class="post">
- <h1 class="postheader">Use Builtin Python module to Symbolicate</h1>
- <div class="postcontent">
- <p>LLDB includes a module in the <b>lldb</b> package named <b>lldb.utils.symbolication</b>.
- 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:
- <ul>
- <li>lldb.utils.symbolication.Address</li>
- <li>lldb.utils.symbolication.Section</li>
- <li>lldb.utils.symbolication.Image</li>
- <li>lldb.utils.symbolication.Symbolicator</li>
- </ul>
- <h2>lldb.utils.symbolication.Address</h2>
- <p>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.
- </p>
- <h2>lldb.utils.symbolication.Section</h2>
- <p>This class represents a section that might get loaded in a <b>lldb.utils.symbolication.Image</b>.
- It has helper functions that allow you to set it from text that might have been extracted from
- a crash log file.
- </p>
- <h2>lldb.utils.symbolication.Image</h2>
- <p>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.
- </p>
- <p>Subclasses of this class will want to override the <b>locate_module_and_debug_symbols</b> method:
-<code><pre><tt>class CustomImage(lldb.utils.symbolication.Image):
- def locate_module_and_debug_symbols (self):
- <font color=green># Locate the module and symbol given the info found in the crash log</font>
-</tt></pre></code>
- <p>Overriding this function allows clients to find the correct executable module and symbol files as they might reside on a build server.<p>
- <h2>lldb.utils.symbolication.Symbolicator</h2>
- <p>This class coordinates the symbolication process by loading only the <b>lldb.utils.symbolication.Image</b>
- instances that need to be loaded in order to symbolicate an supplied address.
- </p>
- <h2>lldb.macosx.crashlog</h2>
- <p><b>lldb.macosx.crashlog</b> 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.</p>
- <p>
- 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:</p>
-<code><pre><tt><b>(lldb)</b> command script import lldb.macosx.crashlog
-"crashlog" and "save_crashlog" command installed, use the "--help" option for detailed help
-<b>(lldb)</b> crashlog /tmp/crash.log
-...
-</tt></pre></code>
- <p>The command that is installed has built in help that shows the
- options that can be used when symbolicating:
-<code><pre><tt><b>(lldb)</b> crashlog --help
-Usage: crashlog [options] <FILE> [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
-
-</tt></pre></code>
- <p>The source for the "symbolication" and "crashlog" modules are available in SVN:</p>
- <ul>
- <li><a href="http://llvm.org/svn/llvm-project/lldb/trunk/examples/python/symbolication.py">symbolication.py</a></li>
- <li><a href="http://llvm.org/svn/llvm-project/lldb/trunk/examples/python/crashlog.py">crashlog.py</a></li>
- </ul>
- </div>
- <div class="postfooter"></div>
- </div>
-</div>
-</body>
-</html>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> +<link href="style.css" rel="stylesheet" type="text/css" /> +<title>Symbolicating with LLDB</title> +</head> + +<body> + <div class="www_title"> + The <strong>LLDB</strong> Debugger + </div> + +<div id="container"> + <div id="content"> + + <!--#include virtual="sidebar.incl"--> + + <div id="middle"> + <div class="post"> + <h1 class="postheader">Manual Symbolication with LLDB</h1> + <div class="postcontent"> + <p>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: + </p> + <ul> + <li>Inlined functions</li> + <li>Variables that are in scope for an address, along with their locations</li> + </ul> + <p>The simplest form of symbolication is to load an executable:</p> +<code><pre><tt><b>(lldb)</b> target create --no-dependents --arch x86_64 /tmp/a.out +</tt></pre></code> + <p>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.</p> + <p>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: + </p> + <code><pre><tt><b>(lldb)</b> image list +[ 0] 73431214-6B76-3489-9557-5075F03E36B4 0x0000000100000000 /tmp/a.out + /tmp/a.out.dSYM/Contents/Resources/DWARF/a.out +</tt></pre></code> + + <p>Now we can look up an address:</p> +<code><pre><tt><b>(lldb)</b> image lookup --address 0x100000aa3 + Address: a.out[0x0000000100000aa3] (a.out.__TEXT.__text + 131) + Summary: a.out`main + 67 at main.c:13 +</tt></pre></code> + <p>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 <b>file</b> address. A <b>file</b> + address refers to a virtual address as defined by each object file. + </p> + <p>If we didn't use the "--no-dependents" option with "target create", we would + have loaded all dependent shared libraries:<p> + <code><pre><tt><b>(lldb)</b> 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 +... +</tt></pre></code> + + + <p>Now if we do a lookup using a <b>file</b> address, this can result in multiple + matches since most shared libraries have a virtual address space that starts at zero:</p> +<code><pre><tt><b>(lldb)</b> 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 +... +</tt></pre></code> + <p>To avoid getting multiple file address matches, you can specify the + <b>name</b> of the shared library to limit the search:</p> +<code><pre><tt><b>(lldb)</b> image lookup -a 0x1000 <b>a.out</b> + Address: a.out[0x0000000000001000] (a.out.__PAGEZERO + 4096) +</tt></pre></code> + </div> + <div class="postfooter"></div> + </div> + <div class="post"> + <h1 class="postheader">Defining Load Addresses for Sections</h1> + <div class="postcontent"> + <p>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 + <b>load</b> addresses. You can slide all sections in the executable by the same amount, + or set the <b>load</b> address for individual sections. The + "target modules load --slide" command allows us to set the <b>load</b> address for + all sections. + <p>Below is an example of sliding all sections in <b>a.out</b> by adding 0x123000 to each section's <b>file</b> address:</p> +<code><pre><tt><b>(lldb)</b> target create --no-dependents --arch x86_64 /tmp/a.out +<b>(lldb)</b> target modules load --file a.out --slide 0x123000 +</tt></pre></code> + <p>It is often much easier to specify the actual load location of each section by name. + Crash logs on Mac OS X have a <b>Binary Images</b> section that specifies + that address of the __TEXT segment for each binary. Specifying a slide requires + requires that you first find the original (<b>file</b>) address for the __TEXT + segment, and subtract the two values. + If you specify the + address of the __TEXT segment with "target modules load <i>section</i> <i>address</i>", 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:</p> +<code><pre><tt><b>(lldb)</b> target create --no-dependents --arch x86_64 /tmp/a.out +<b>(lldb)</b> target modules load --file a.out __TEXT 0x100123000 +</tt></pre></code> + <p>We specified that the <b>__TEXT</b> 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 <b>load</b> addresses so we don't have to + do any math on the addresses in the crashlog backtraces, we can just use the + raw addresses:</p> +<code><pre><tt><b>(lldb)</b> image lookup --address 0x100123aa3 + Address: a.out[0x0000000100000aa3] (a.out.__TEXT.__text + 131) + Summary: a.out`main + 67 at main.c:13 +</tt></pre></code> + </div> + <div class="postfooter"></div> + </div> + <div class="post"> + <h1 class="postheader">Loading Multiple Executables</h1> + <div class="postcontent"> + <p>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.<p> + <p>Lets say we have a Darwin crash log that contains the following images: +<code><pre><tt>Binary Images: + <font color=blue>0x100000000</font> - 0x100000ff7 <A866975B-CA1E-3649-98D0-6C5FAA444ECF> /tmp/a.out + <font color=green>0x7fff83f32000</font> - 0x7fff83ffefe7 <8CBCF9B9-EBB7-365E-A3FF-2F3850763C6B> /usr/lib/system/libsystem_c.dylib + <font color=red>0x7fff883db000</font> - 0x7fff883e3ff7 <62AA0B84-188A-348B-8F9E-3E2DB08DB93C> /usr/lib/system/libsystem_dnssd.dylib + <font color=purple>0x7fff8c0dc000</font> - 0x7fff8c0f7ff7 <C0535565-35D1-31A7-A744-63D9F10F12A4> /usr/lib/system/libsystem_kernel.dylib +</tt></pre></code> + + <p>First we create the target using the main executable and then add any extra shared libraries we want:</p> +<code><pre><tt><b>(lldb)</b> target create --no-dependents --arch x86_64 /tmp/a.out +<b>(lldb)</b> target modules add /usr/lib/system/libsystem_c.dylib +<b>(lldb)</b> target modules add /usr/lib/system/libsystem_dnssd.dylib +<b>(lldb)</b> target modules add /usr/lib/system/libsystem_kernel.dylib +</tt></pre></code> + <p>If you have debug symbols in standalone files, such as dSYM files on Mac OS X, you can specify their paths using the <b>--symfile</b> option for the "target create" (recent LLDB releases only) and "target modules add" commands:</p> +<code><pre><tt><b>(lldb)</b> target create --no-dependents --arch x86_64 /tmp/a.out <b>--symfile /tmp/a.out.dSYM</b> +<b>(lldb)</b> target modules add /usr/lib/system/libsystem_c.dylib <b>--symfile /build/server/a/libsystem_c.dylib.dSYM</b> +<b>(lldb)</b> target modules add /usr/lib/system/libsystem_dnssd.dylib <b>--symfile /build/server/b/libsystem_dnssd.dylib.dSYM</b> +<b>(lldb)</b> target modules add /usr/lib/system/libsystem_kernel.dylib <b>--symfile /build/server/c/libsystem_kernel.dylib.dSYM</b> +</tt></pre></code> + <p>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:</p> +<code><pre><tt><b>(lldb)</b> target modules load --file a.out <font color=blue>0x100000000</font> +<b>(lldb)</b> target modules load --file libsystem_c.dylib <font color=green>0x7fff83f32000</font> +<b>(lldb)</b> target modules load --file libsystem_dnssd.dylib <font color=red>0x7fff883db000</font> +<b>(lldb)</b> target modules load --file libsystem_kernel.dylib <font color=purple>0x7fff8c0dc000</font> +</tt></pre></code> + <p>Now any stack backtraces that haven't been symbolicated can be symbolicated using "image lookup" + with the raw backtrace addresses.</p> + <p>Given the following raw backtrace:</p> +<code><pre><tt>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 +</tt></pre></code> + <p>We can now symbolicate the <b>load</b> addresses:<p> +<code><pre><tt><b>(lldb)</b> image lookup -a 0x00007fff8a1e6d46 +<b>(lldb)</b> image lookup -a 0x00007fff84597df0 +<b>(lldb)</b> image lookup -a 0x00007fff84598e2a +<b>(lldb)</b> image lookup -a 0x0000000100000f46 +</tt></pre></code> + </div> + <div class="postfooter"></div> + </div> + <div class="post"> + <h1 class="postheader">Getting Variable Information</h1> + <div class="postcontent"> + <p>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: +<code><pre><tt>><b>(lldb)</b> 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", <b>location = r13</b>, decl = main.c:8 + Variable: id = {0x00000081}, name = "argv", type= "const char **", <b>location = r12</b>, decl = main.c:8 + Variable: id = {0x00000090}, name = "envp", type= "const char **", <b>location = r15</b>, decl = main.c:8 + Variable: id = {0x0000009f}, name = "aapl", type= "const char **", <b>location = rbx</b>, decl = main.c:8 +</tt></pre></code> + <p>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. + </div> + <div class="postfooter"></div> + </div> + <div class="post"> + <h1 class="postheader">Using Python API to Symbolicate</h1> + <div class="postcontent"> + <p>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: +<code><pre><tt>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: + <font color=green># Get the executable module</font> + 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 + <font color=green># so_addr is a section offset address, or a lldb.SBAddress object</font> + so_addr = target.ResolveLoadAddress (load_addr) + <font color=green># Get a symbol context for the section offset address which includes + # a module, compile unit, function, block, line entry, and symbol</font> + sym_ctx = so_addr.GetSymbolContext (lldb.eSymbolContextEverything) + print sym_ctx + +</tt></pre></code> + </div> + <div class="postfooter"></div> + </div> + <div class="post"> + <h1 class="postheader">Use Builtin Python module to Symbolicate</h1> + <div class="postcontent"> + <p>LLDB includes a module in the <b>lldb</b> package named <b>lldb.utils.symbolication</b>. + 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: + <ul> + <li>lldb.utils.symbolication.Address</li> + <li>lldb.utils.symbolication.Section</li> + <li>lldb.utils.symbolication.Image</li> + <li>lldb.utils.symbolication.Symbolicator</li> + </ul> + <h2>lldb.utils.symbolication.Address</h2> + <p>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. + </p> + <h2>lldb.utils.symbolication.Section</h2> + <p>This class represents a section that might get loaded in a <b>lldb.utils.symbolication.Image</b>. + It has helper functions that allow you to set it from text that might have been extracted from + a crash log file. + </p> + <h2>lldb.utils.symbolication.Image</h2> + <p>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. + </p> + <p>Subclasses of this class will want to override the <b>locate_module_and_debug_symbols</b> method: +<code><pre><tt>class CustomImage(lldb.utils.symbolication.Image): + def locate_module_and_debug_symbols (self): + <font color=green># Locate the module and symbol given the info found in the crash log</font> +</tt></pre></code> + <p>Overriding this function allows clients to find the correct executable module and symbol files as they might reside on a build server.<p> + <h2>lldb.utils.symbolication.Symbolicator</h2> + <p>This class coordinates the symbolication process by loading only the <b>lldb.utils.symbolication.Image</b> + instances that need to be loaded in order to symbolicate an supplied address. + </p> + <h2>lldb.macosx.crashlog</h2> + <p><b>lldb.macosx.crashlog</b> 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.</p> + <p> + 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:</p> +<code><pre><tt><b>(lldb)</b> command script import lldb.macosx.crashlog +"crashlog" and "save_crashlog" command installed, use the "--help" option for detailed help +<b>(lldb)</b> crashlog /tmp/crash.log +... +</tt></pre></code> + <p>The command that is installed has built in help that shows the + options that can be used when symbolicating: +<code><pre><tt><b>(lldb)</b> crashlog --help +Usage: crashlog [options] <FILE> [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 + +</tt></pre></code> + <p>The source for the "symbolication" and "crashlog" modules are available in SVN:</p> + <ul> + <li><a href="http://llvm.org/svn/llvm-project/lldb/trunk/examples/python/symbolication.py">symbolication.py</a></li> + <li><a href="http://llvm.org/svn/llvm-project/lldb/trunk/examples/python/crashlog.py">crashlog.py</a></li> + </ul> + </div> + <div class="postfooter"></div> + </div> +</div> +</body> +</html> diff --git a/lldb/www/symbols.html b/lldb/www/symbols.html index 47eb5bf0e51..76f638de836 100755 --- a/lldb/www/symbols.html +++ b/lldb/www/symbols.html @@ -1,345 +1,345 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
-<link href="style.css" rel="stylesheet" type="text/css" />
-<title>Debug Sybmols on Mac OS X</title>
-</head>
-
-<body>
- <div class="www_title">
- The <strong>LLDB</strong> Debugger
- </div>
-
-<div id="container">
- <div id="content">
-
- <!--#include virtual="sidebar.incl"-->
-
- <div id="middle">
- <div class="post">
- <h1 class="postheader">Debug Symbols on MacOSX</h1>
- <div class="postcontent">
- <p>On MacOSX, debug symbols are often in stand alone bundles called <b>dSYM</b> files.
- These are bundles that contain DWARF debug information and other resources related to
- builds and debug info.</p>
- <p>The DebugSymbols.framework framework helps locate dSYM files when given a UUID. It can
- locate the symbols using a variety of methods:</p>
- <ul>
- <li>Spotlight</li>
- <li>Explicit search paths</li>
- <li>Implicit search paths</li>
- <li>File mapped UUID paths</li>
- <li>Running one or more shell scripts</li>
- </ul>
- <p>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 <b>com.apple.DebugSymbols</b>, and the defaults can be read, written or modified
- using the <b>defaults</b> shell command:
-<code><pre><tt><b>% defaults read com.apple.DebugSymbols
-% defaults write com.apple.DebugSymbols KEY ...
-% defaults delete com.apple.DebugSymbols KEY</b>
-</tt></pre></code>
-
- <p>The following is a list of the defaults key value
- setting pairs that can be used to enhance symbol location:</p>
- <table class="stats" width="620" cellspacing="0">
- <tr>
- <td class="hed" width="20%">Defaults Key</td>
- <td class="hed" width="70%">Description</td>
- </tr>
-
- <tr>
- <td class="content">
- <b>DBGFileMappedPaths</b>
- </td>
- <td class="content">
- 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.
- </td>
- </tr>
- <td class="content" colspan="2">
-<code><pre><tt><b>% defaults write com.apple.DebugSymbols DBGFileMappedPaths -string /path/to/uuidmap1</b>
-<b>% defaults write com.apple.DebugSymbols DBGFileMappedPaths -array /path/to/uuidmap1
- /path/to/uuidmap2</b>
-</tt></pre></code>
- </tr>
- <tr>
- <td class="content">
- <b>DBGShellCommands</b>
- </td>
- <td class="content">
- 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.
- </td>
- </tr>
- <td class="content" colspan="2">
-<code><pre><tt><b>% defaults write com.apple.DebugSymbols DBGShellCommands -string /path/to/script1</b>
-<b>% defaults write com.apple.DebugSymbols DBGShellCommands -array /path/to/script1
- /path/to/script2</b>
-</tt></pre></code>
- </td>
- </tr>
- <tr>
- <td class="content">
- <b>DBGSpotlightPaths</b>
- </td>
- <td class="content">
- Specifies the directories to limit spotlight searches to as a string or array of strings. When any
- other defaults are supplied to <b>com.apple.DebugSymbols</b>, spotlight
- searches will be disabled unless this default is set to an empty array:
- </td>
- </tr>
- <td class="content" colspan="2">
-<code><pre><tt><font color="green"># Specify an empty array to keep Spotlight searches enabled in all locations</font>
-<b>% defaults write com.apple.DebugSymbols DBGSpotlightPaths -array</b>
-
-<font color="green"># Specify an array of paths to limit spotlight searches to certain directories</font>
-<b>% defaults write com.apple.DebugSymbols DBGSpotlightPaths -array /path/dir1 /path/dir2</b>
-</tt></pre></code>
- </td>
- </tr>
- </table>
- </div>
- <div class="postfooter"></div>
- </div>
- <div class="post">
- <h1 class="postheader">Shell Script Property List Format</h1>
- <div class="postcontent">
-<p>Shell scripts that are specified with the <b>DBGShellCommands</b> 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:
-
- <table class="stats" width="620" cellspacing="0">
- <tr>
- <td class="hed" width="20%">Key</td>
- <td class="hed" width="70%">Description</td>
- </tr>
- <tr>
- <td class="content">
- <b>DBGArchitecture</b>
- </td>
- <td class="content">A textual architecture or target triple like "x86_64", "i386", or "x86_64-apple-macosx".
- </td>
- </tr>
- <tr>
- <td class="content">
- <b>DBGBuildSourcePath</b>
- </td>
- <td class="content">A path prefix that was used when building the dSYM file. The debug information will
- contain paths with this prefix.
- </td>
- </tr>
- <tr>
- <td class="content">
- <b>DBGSourcePath</b>
- </td>
- <td class="content">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 <b>DBGBuildSourcePath</b>
- will help the developer tools always show you sources when debugging or symbolicating.
- </td>
- </tr>
- <tr>
- <td class="content">
- <b>DBGDSYMPath</b>
- </td>
- <td class="content">A path to the dSYM mach-o file inside the dSYM bundle.
- </td>
- </tr>
- <tr>
- <td class="content">
- <b>DBGSymbolRichExecutable</b>
- </td>
- <td class="content">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.
- </td>
- </tr>
- <tr>
- <td class="content">
- <b>DBGError</b>
- </td>
- <td class="content">If a binary can not be located for the supplied UUID, a user readable error
- can be returned.
- </td>
- </tr>
- </table>
-
-<p>Below is a sample shell script output for a binary that contains two architectures:
-<code><pre><tt>
-<?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>
-</tt></pre></code>
-
-<p>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 <b>DBGError</b> 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.
- </div>
- <div class="postfooter"></div>
- </div>
- <div class="post">
- <h1 class="postheader">Embedding UUID property lists inside the dSYM bundles</h1>
- <div class="postcontent">
-<p>Since dSYM files are bundles, you can also place UUID info plists files inside
-your dSYM bundles in the <b>Contents/Resources</b> 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.
-
-<p>If we take the two UUID values from the returns plist above, we can split
-them out and save then in the dSYM bundle:
-
-<code><pre><tt><b>% ls /path/to/foo.dSYM/Contents/Resources</b>
-23516BE4-29BE-350C-91C9-F36E7999F0F1.plist
-A40597AA-5529-3337-8C09-D8A014EB1578.plist
-
-<b>% cat /path/to/foo.dSYM/Contents/Resources/23516BE4-29BE-350C-91C9-F36E7999F0F1.plist</b>
-<?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>
-</tt></pre></code>
-
-<p>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.
-
-
- </div>
- <div class="postfooter"></div>
- </div>
- <div class="post">
- <h1 class="postheader">File Mapped UUID Directories</h1>
- <div class="postcontent">
-<p>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.
-
-<p>For example, if we take the sample UUID plist inforamtion from above, we
-can create a File Mapped UUID directory cache in <b>~/Library/SymbolCache/dsyms/uuids</b>.
-We can easily see how things are laid out:
-
-<code><pre><tt><b>% find ~/Library/SymbolCache/dsyms/uuids -type l</b>
-~/Library/SymbolCache/dsyms/uuids/2351/6BE4/29BE/350C/91C9/F36E7999F0F1
-~/Library/SymbolCache/dsyms/uuids/A405/97AA/5529/3337/8C09/D8A014EB1578
-</tt></pre></code>
-
-<p>The last entries in these file mapped directories are symlinks to the actual dsym mach file in the dsym bundle:
-
-<code><pre><tt><b>% ls -lAF ~/Library/SymbolCache/dsyms/uuids/2351/6BE4/29BE/350C/91C9/F36E7999F0F1</b>
-~/Library/SymbolCache/dsyms/uuids/2351/6BE4/29BE/350C/91C9/F36E7999F0F1@ -> ../../../../../../dsyms/foo.dSYM/Contents/Resources/DWARF/foo
-</tt></pre></code>
-<p>Then you can also tell DebugSymbols to check this UUID file map cache using:
-
-<code><pre><tt><b>% defaults write com.apple.DebugSymbols DBGFileMappedPaths ~/Library/SymbolCache/dsyms/uuids</b>
-</tt></pre></code>
-
-
- </div>
- <div class="postfooter"></div>
- </div>
- <div class="post">
- <h1 class="postheader">dSYM Locating Shell Script Tips</h1>
- <div class="postcontent">
-
-<p>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.
-
-<p>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:
-
-<code><pre><tt><b>% 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</b>
-</tt></pre></code>
-
-Hopefully this helps explain how DebugSymbols.framework can help any company
-implement a smart symbol finding and caching with minimal overhead.
-</p>
- </div>
- <div class="postfooter"></div>
- </div>
- </div>
- </div>
-</div>
-</body>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> +<link href="style.css" rel="stylesheet" type="text/css" /> +<title>Debug Sybmols on Mac OS X</title> +</head> + +<body> + <div class="www_title"> + The <strong>LLDB</strong> Debugger + </div> + +<div id="container"> + <div id="content"> + + <!--#include virtual="sidebar.incl"--> + + <div id="middle"> + <div class="post"> + <h1 class="postheader">Debug Symbols on MacOSX</h1> + <div class="postcontent"> + <p>On MacOSX, debug symbols are often in stand alone bundles called <b>dSYM</b> files. + These are bundles that contain DWARF debug information and other resources related to + builds and debug info.</p> + <p>The DebugSymbols.framework framework helps locate dSYM files when given a UUID. It can + locate the symbols using a variety of methods:</p> + <ul> + <li>Spotlight</li> + <li>Explicit search paths</li> + <li>Implicit search paths</li> + <li>File mapped UUID paths</li> + <li>Running one or more shell scripts</li> + </ul> + <p>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 <b>com.apple.DebugSymbols</b>, and the defaults can be read, written or modified + using the <b>defaults</b> shell command: +<code><pre><tt><b>% defaults read com.apple.DebugSymbols +% defaults write com.apple.DebugSymbols KEY ... +% defaults delete com.apple.DebugSymbols KEY</b> +</tt></pre></code> + + <p>The following is a list of the defaults key value + setting pairs that can be used to enhance symbol location:</p> + <table class="stats" width="620" cellspacing="0"> + <tr> + <td class="hed" width="20%">Defaults Key</td> + <td class="hed" width="70%">Description</td> + </tr> + + <tr> + <td class="content"> + <b>DBGFileMappedPaths</b> + </td> + <td class="content"> + 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. + </td> + </tr> + <td class="content" colspan="2"> +<code><pre><tt><b>% defaults write com.apple.DebugSymbols DBGFileMappedPaths -string /path/to/uuidmap1</b> +<b>% defaults write com.apple.DebugSymbols DBGFileMappedPaths -array /path/to/uuidmap1 + /path/to/uuidmap2</b> +</tt></pre></code> + </tr> + <tr> + <td class="content"> + <b>DBGShellCommands</b> + </td> + <td class="content"> + 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. + </td> + </tr> + <td class="content" colspan="2"> +<code><pre><tt><b>% defaults write com.apple.DebugSymbols DBGShellCommands -string /path/to/script1</b> +<b>% defaults write com.apple.DebugSymbols DBGShellCommands -array /path/to/script1 + /path/to/script2</b> +</tt></pre></code> + </td> + </tr> + <tr> + <td class="content"> + <b>DBGSpotlightPaths</b> + </td> + <td class="content"> + Specifies the directories to limit spotlight searches to as a string or array of strings. When any + other defaults are supplied to <b>com.apple.DebugSymbols</b>, spotlight + searches will be disabled unless this default is set to an empty array: + </td> + </tr> + <td class="content" colspan="2"> +<code><pre><tt><font color="green"># Specify an empty array to keep Spotlight searches enabled in all locations</font> +<b>% defaults write com.apple.DebugSymbols DBGSpotlightPaths -array</b> + +<font color="green"># Specify an array of paths to limit spotlight searches to certain directories</font> +<b>% defaults write com.apple.DebugSymbols DBGSpotlightPaths -array /path/dir1 /path/dir2</b> +</tt></pre></code> + </td> + </tr> + </table> + </div> + <div class="postfooter"></div> + </div> + <div class="post"> + <h1 class="postheader">Shell Script Property List Format</h1> + <div class="postcontent"> +<p>Shell scripts that are specified with the <b>DBGShellCommands</b> 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: + + <table class="stats" width="620" cellspacing="0"> + <tr> + <td class="hed" width="20%">Key</td> + <td class="hed" width="70%">Description</td> + </tr> + <tr> + <td class="content"> + <b>DBGArchitecture</b> + </td> + <td class="content">A textual architecture or target triple like "x86_64", "i386", or "x86_64-apple-macosx". + </td> + </tr> + <tr> + <td class="content"> + <b>DBGBuildSourcePath</b> + </td> + <td class="content">A path prefix that was used when building the dSYM file. The debug information will + contain paths with this prefix. + </td> + </tr> + <tr> + <td class="content"> + <b>DBGSourcePath</b> + </td> + <td class="content">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 <b>DBGBuildSourcePath</b> + will help the developer tools always show you sources when debugging or symbolicating. + </td> + </tr> + <tr> + <td class="content"> + <b>DBGDSYMPath</b> + </td> + <td class="content">A path to the dSYM mach-o file inside the dSYM bundle. + </td> + </tr> + <tr> + <td class="content"> + <b>DBGSymbolRichExecutable</b> + </td> + <td class="content">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. + </td> + </tr> + <tr> + <td class="content"> + <b>DBGError</b> + </td> + <td class="content">If a binary can not be located for the supplied UUID, a user readable error + can be returned. + </td> + </tr> + </table> + +<p>Below is a sample shell script output for a binary that contains two architectures: +<code><pre><tt> +<?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> +</tt></pre></code> + +<p>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 <b>DBGError</b> 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. + </div> + <div class="postfooter"></div> + </div> + <div class="post"> + <h1 class="postheader">Embedding UUID property lists inside the dSYM bundles</h1> + <div class="postcontent"> +<p>Since dSYM files are bundles, you can also place UUID info plists files inside +your dSYM bundles in the <b>Contents/Resources</b> 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. + +<p>If we take the two UUID values from the returns plist above, we can split +them out and save then in the dSYM bundle: + +<code><pre><tt><b>% ls /path/to/foo.dSYM/Contents/Resources</b> +23516BE4-29BE-350C-91C9-F36E7999F0F1.plist +A40597AA-5529-3337-8C09-D8A014EB1578.plist + +<b>% cat /path/to/foo.dSYM/Contents/Resources/23516BE4-29BE-350C-91C9-F36E7999F0F1.plist</b> +<?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> +</tt></pre></code> + +<p>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. + + + </div> + <div class="postfooter"></div> + </div> + <div class="post"> + <h1 class="postheader">File Mapped UUID Directories</h1> + <div class="postcontent"> +<p>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. + +<p>For example, if we take the sample UUID plist inforamtion from above, we +can create a File Mapped UUID directory cache in <b>~/Library/SymbolCache/dsyms/uuids</b>. +We can easily see how things are laid out: + +<code><pre><tt><b>% find ~/Library/SymbolCache/dsyms/uuids -type l</b> +~/Library/SymbolCache/dsyms/uuids/2351/6BE4/29BE/350C/91C9/F36E7999F0F1 +~/Library/SymbolCache/dsyms/uuids/A405/97AA/5529/3337/8C09/D8A014EB1578 +</tt></pre></code> + +<p>The last entries in these file mapped directories are symlinks to the actual dsym mach file in the dsym bundle: + +<code><pre><tt><b>% ls -lAF ~/Library/SymbolCache/dsyms/uuids/2351/6BE4/29BE/350C/91C9/F36E7999F0F1</b> +~/Library/SymbolCache/dsyms/uuids/2351/6BE4/29BE/350C/91C9/F36E7999F0F1@ -> ../../../../../../dsyms/foo.dSYM/Contents/Resources/DWARF/foo +</tt></pre></code> +<p>Then you can also tell DebugSymbols to check this UUID file map cache using: + +<code><pre><tt><b>% defaults write com.apple.DebugSymbols DBGFileMappedPaths ~/Library/SymbolCache/dsyms/uuids</b> +</tt></pre></code> + + + </div> + <div class="postfooter"></div> + </div> + <div class="post"> + <h1 class="postheader">dSYM Locating Shell Script Tips</h1> + <div class="postcontent"> + +<p>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. + +<p>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: + +<code><pre><tt><b>% 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</b> +</tt></pre></code> + +Hopefully this helps explain how DebugSymbols.framework can help any company +implement a smart symbol finding and caching with minimal overhead. +</p> + </div> + <div class="postfooter"></div> + </div> + </div> + </div> +</div> +</body> </html>
\ No newline at end of file diff --git a/lldb/www/troubleshooting.html b/lldb/www/troubleshooting.html index 9db56e3d1d5..7d03faf7ae2 100755 --- a/lldb/www/troubleshooting.html +++ b/lldb/www/troubleshooting.html @@ -1,89 +1,89 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
-<link href="style.css" rel="stylesheet" type="text/css" />
-<title>LLDB FAQ</title>
-</head>
-
-<body>
-<div class="www_title">
- Troubleshooting <strong>LLDB</strong>
-</div>
-
-<div id="container">
- <div id="content">
- <!--#include virtual="sidebar.incl"-->
- <div class="postfooter"></div>
- <div id="middle">
- <div class="post">
- <h1 class ="postheader">File and line breakpoints are not getting hit</h1>
- <div class="postcontent">
- <p>First you must make sure that your source files were compiled with
- debug information. Typically this means passing <code>-g</code> to the
- compiler when compiling your source file.
- </p>
- <p>When setting breakpoints in <b>implementation</b> 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 <font color=purple>#include</font> to include source files:
-<code><pre><tt>% <b>cat foo.c</b>
-<font color=purple>#include</font> "bar.c"
-<font color=purple>#include</font> "baz.c"
-...
-</tt></pre></code>
- <p> 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 <code>~/.lldbinit</code> file:
- </p>
-<code><pre><tt>% <b>echo "settings set target.inline-breakpoint-strategy always" >> ~/.lldbinit</b></tt></pre></code>
- <p> 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.
- </p>
- <p> 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.
- <p> 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.
- </p>
- </div>
- <div class="postfooter"></div>
- </div>
- </div>
- <div class="postfooter"></div>
- <div id="middle">
- <div class="post">
- <h1 class ="postheader">How do I check if I have debug symbols?</h1>
- <div class="postcontent">
- <p> Checking if a module has any compile units (source files) is a good way to check
- if there is debug information in a module:
-<code><pre><tt>
-(lldb) <b>file /tmp/a.out</b>
-(lldb) <b>image list</b>
-[ 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) <b>script lldb.target.module['/tmp/a.out'].GetNumCompileUnits()</b>
-1
-(lldb) <b>script lldb.target.module['/usr/lib/dyld'].GetNumCompileUnits()</b>
-0
-</tt></pre></code>
- <p> Above we can see that "/tmp/a.out" does have a compile unit, and "/usr/lib/dyld" does not.
- </div>
- <div class="postfooter"></div>
- </div>
- </div>
- </div>
-</div>
-</body>
-</html>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> +<link href="style.css" rel="stylesheet" type="text/css" /> +<title>LLDB FAQ</title> +</head> + +<body> +<div class="www_title"> + Troubleshooting <strong>LLDB</strong> +</div> + +<div id="container"> + <div id="content"> + <!--#include virtual="sidebar.incl"--> + <div class="postfooter"></div> + <div id="middle"> + <div class="post"> + <h1 class ="postheader">File and line breakpoints are not getting hit</h1> + <div class="postcontent"> + <p>First you must make sure that your source files were compiled with + debug information. Typically this means passing <code>-g</code> to the + compiler when compiling your source file. + </p> + <p>When setting breakpoints in <b>implementation</b> 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 <font color=purple>#include</font> to include source files: +<code><pre><tt>% <b>cat foo.c</b> +<font color=purple>#include</font> "bar.c" +<font color=purple>#include</font> "baz.c" +... +</tt></pre></code> + <p> 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 <code>~/.lldbinit</code> file: + </p> +<code><pre><tt>% <b>echo "settings set target.inline-breakpoint-strategy always" >> ~/.lldbinit</b></tt></pre></code> + <p> 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. + </p> + <p> 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. + <p> 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. + </p> + </div> + <div class="postfooter"></div> + </div> + </div> + <div class="postfooter"></div> + <div id="middle"> + <div class="post"> + <h1 class ="postheader">How do I check if I have debug symbols?</h1> + <div class="postcontent"> + <p> Checking if a module has any compile units (source files) is a good way to check + if there is debug information in a module: +<code><pre><tt> +(lldb) <b>file /tmp/a.out</b> +(lldb) <b>image list</b> +[ 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) <b>script lldb.target.module['/tmp/a.out'].GetNumCompileUnits()</b> +1 +(lldb) <b>script lldb.target.module['/usr/lib/dyld'].GetNumCompileUnits()</b> +0 +</tt></pre></code> + <p> Above we can see that "/tmp/a.out" does have a compile unit, and "/usr/lib/dyld" does not. + </div> + <div class="postfooter"></div> + </div> + </div> + </div> +</div> +</body> +</html> diff --git a/lldb/www/tutorial.html b/lldb/www/tutorial.html index 3e83fb8ad9b..bbab90de2c4 100755 --- a/lldb/www/tutorial.html +++ b/lldb/www/tutorial.html @@ -1,726 +1,726 @@ -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
-<link href="style.css" rel="stylesheet" type="text/css" />
-<title>LLDB Tutorial</title>
-</head>
-
-<body>
- <div class="www_title">
- The <strong>LLDB</strong> Debugger
- </div>
-
-<div id="container">
- <div id="content">
- <!--#include virtual="sidebar.incl"-->
- <div id="middle">
- <div class="post">
- <h1 class ="postheader">Getting Started</h1>
- <div class="postcontent">
-
- <p>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.</p>
-
- </div>
- <div class="postfooter"></div>
-
- <div class="post">
- <h1 class ="postheader">Command Structure</h1>
- <div class="postcontent">
-
- <p>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:</p>
-
- <code color=#ff0000>
- <noun> <verb> [-options [option-value]] [argument [argument...]]
- </code>
-
- <p>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.</p>
-
- <p>Options can be placed anywhere on the command line, but if the arguments
- begin with a "<code>-</code>" then you have to tell lldb that you're done with options
- for the current command by adding an option termination: "<code>--</code>"
- So for instance if you want to launch a process and give the "process launch" command
- the "<code>--stop-at-entry</code>" option, yet you want the
- process you are about to launch to be launched with the arguments
- "<code>-program_arg value</code>", you would type:</p>
-
- <code>
- (lldb) process launch --stop-at-entry -- -program_arg value
- </code>
-
- <p>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</p>
-
- <code>
- (gdb) break foo.c:12
- </code>
- <p>to break at line 12 of foo.c, and:</p>
- <code>
- (gdb) break foo
- </code>
-
- <p>to break at the function <code>foo</code>. As time went on, the parser that tells <code>foo.c:12</code>
- from <code>foo</code> from <code>foo.c::foo</code> (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.
-
- <p>To set the same file and line breakpoint in LLDB you can enter either of:</p>
-
- <code>
- (lldb) breakpoint set --file foo.c --line 12
- <br>(lldb) breakpoint set -f foo.c -l 12
- </code>
-
- <p>To set a breakpoint on a function named <code>foo</code> in LLDB you can enter either of:</p>
-
- <code>
- (lldb) breakpoint set --name foo
- <br>(lldb) breakpoint set -n foo
- </code>
-
- <p>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:</p>
-
- <code>
- (lldb) breakpoint set --name foo --name bar
- </code>
-
- <p>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 <code>foo</code> you can enter either of:</p>
-
- <code>
- (lldb) breakpoint set --method foo
- <br>(lldb) breakpoint set -M foo
- </code>
-
- <p>To set a breakpoint Objective C selectors named <code>alignLeftEdges:</code> you can enter either of:</p>
-
- <code>
- (lldb) breakpoint set --selector alignLeftEdges:
- <br>(lldb) breakpoint set -S alignLeftEdges:
- </code>
-
- <p>You can limit any breakpoints to a specific executable image by using
- the "<code>--shlib <path></code>" ("<code>-s <path></code>" for short):</p>
-
- <code>
- (lldb) breakpoint set --shlib foo.dylib --name foo
- <br>(lldb) breakpoint set -s foo.dylib -n foo
- </code>
-
- <p>The <code>--shlib</code> option can also be repeated to specify several shared libraries.</p>
-
- <p>Suggestions on more interesting primitives of this sort are also very welcome.</p>
-
- <p>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:</p>
-
- <code>
- (lldb) breakpoint set -n "-[SKTGraphicView alignLeftEdges:]"
- <br>(lldb) br s -n "-[SKTGraphicView alignLeftEdges:]"
- </code>
-
- <p>lldb also supports command completion for source file names, symbol
- names, file names, etc. Completion is initiated by a hitting a <b>TAB</b>.
- Individual options in a command can have different completers, so for
- instance the "<code>--file <path></code>" option in "breakpoint" completes to source files, the
- "<code>--shlib <path></code>" option to currently loaded shared libraries, etc. We can even do
- things like if you specify "<code>--shlib <path></code>", and are completing on "<code>--file <path></code>", we will only
- list source files in the shared library specified by "<code>--shlib <path></code>".</p>
-
- <p>The individual commands are pretty extensively documented. You can
- use the <code>help</code> command to get an overview of which commands are
- available or to obtain details about specific commands. There is also an
- <code>apropos</code> command that will search the help text for all commands
- for a particular word and dump a summary help string for each matching
- command.</p>
-
- <p>Finally, there is a mechanism to construct aliases for commonly used
- commands. So for instance if you get annoyed typing:</p>
-
- <code>
- (lldb) breakpoint set --file foo.c --line 12
- </code>
-
- <p>you can do:</p>
-
- <code>
- (lldb) command alias bfl breakpoint set -f %1 -l %2
- <br>(lldb) bfl foo.c 12
- </code>
-
- <p>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.</p>
-
- <p>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.</p>
-
- <p> 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 <code>foo.c::bar</code>. But
- it mostly works, and makes the transition easier. Also by popular demand, it
- is aliased to <code>b</code>. 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):</p>
-
- <code>
- (lldb) command unalias b
- </code>
-
- <p>I actually also do:</p>
-
- <code>
- (lldb) command alias b breakpoint
- </code>
-
- <p>so I can run the native lldb breakpoint command with just <code>b</code></p>
-
- <p>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.
-
- <p>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.</p>
-
- <p>Having given an overview of lldb's command syntax, we proceed to lay out the stages
- of a standard debug session.</p>
-
- </div>
- <div class="postfooter"></div>
-
-
- <div class="post">
- <h1 class ="postheader">Loading a program into lldb</h1>
- <div class="postcontent">
-
- <p>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:</p>
-
- <code>
- $ lldb /Projects/Sketch/build/Debug/Sketch.app
- <br>Current executable set to '/Projects/Sketch/build/Debug/Sketch.app' (x86_64).
- </code>
-
- <p>or you can specify it after the fact with the "file" command:</p>
-
- <code>
- $ lldb
- <br>(lldb) file /Projects/Sketch/build/Debug/Sketch.app
- <br>Current executable set to '/Projects/Sketch/build/Debug/Sketch.app' (x86_64).
- </code>
- <p>
- </div>
- <div class="postfooter"></div>
-
- <div class="post">
- <h1 class ="postheader">Setting breakpoints</h1>
- <div class="postcontent">
-
- <p>We've discussed how to set breakpoints above. You can use <code>help breakpoint set</code>
- to see all the options for breakpoint setting. For instance, we might do:</p>
-
- <code>
- (lldb) breakpoint set --selector alignLeftEdges:
- <br>Breakpoint created: 1: name = 'alignLeftEdges:', locations = 1, resolved = 1
- </code>
-
- <p>You can find out about the breakpoints you've set with:</p>
-
- <pre><tt>(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
-</tt></pre>
-
- <p>Note that setting a breakpoint creates a <i>logical</i> breakpoint, which could
- resolve to one or more <i>locations</i>. 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.</p>
-
- <p>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.) </p>
-
- <p>Also the logical breakpoints remain <i>live</i> so that if another shared library
- were to be loaded that had another implementation of the
- "<code>alignLeftEdges:</code>" selector, the new location would be added to
- breakpoint 1 (e.g. a "1.2" breakpoint would be set on the newly loaded
- selector).</p>
-
- <p>The other piece of information in the breakpoint listing is whether the
- breakpoint location was <i>resolved</i> 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 <i>resolved</i>.</p>
-
- <p>One other thing to note for gdb users is that lldb acts like gdb with:</p>
-
- <code>
- (gdb) set breakpoint pending on
- </code>
-
- <p>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:</p>
-
- <code>
- (lldb) breakpoint set --file foo.c --line 12
- <br>Breakpoint created: 2: file ='foo.c', line = 12, locations = 0 (pending)
- <br>WARNING: Unable to resolve breakpoint to any actual locations.
- </code>
-
- <p>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:</p>
-
- <code>
- (lldb) breakpoint command add 1.1
- <br>Enter your debugger command(s). Type 'DONE' to end.
- <br>> bt
- <br>> DONE
- </code>
-
- <p>By default, the <code> breakpoint command add</code> command takes lldb command line commands.
- You can also specify this explicitly by passing the "<code>--command</code>" option.
- Use "<code>--script</code>" if you want to implement your breakpoint command using the Python script instead.</p>
-
- <p>This is an convenient point to bring up another feature of the lldb command help. Do:</p>
-
- <code>
- (lldb) help break command add
- <br>Add a set of commands to a breakpoint, to be executed whenever the breakpoint is hit.
- <br>
- <br>Syntax: breakpoint command add <cmd-options> <breakpt-id>
- <br> etc...
- </code>
-
- <p>When you see arguments to commands specified in the Syntax in angle
- brackets like <code><breakpt-id></code>, 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:</p>
-
- <code>
- (lldb) help <breakpt-id>
- <br><breakpt-id> -- Breakpoint ID's consist major and minor numbers; the major
- <br> etc...
- </code>
-
- </div>
- <div class="postfooter"></div>
-
- <div class="post">
- <h1 class ="postheader">Setting watchpoints</h1>
- <div class="postcontent">
-
- <p>In addition to breakpoints, you can use <code>help watchpoint</code>
- 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:</p>
-
- <pre><tt>(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) </tt></pre>
- </div>
- <div class="postfooter"></div>
-
- <div class="post">
- <h1 class ="postheader">Starting or attaching to your Program</h1>
- <div class="postcontent">
-
- <p>To launch a program in lldb we use the "<code>process launch</code>" command or
- one of its built in aliases:</p>
-
- <code>
- (lldb) process launch
- <br>(lldb) run
- <br>(lldb) r
- </code>
-
- <p>You can also attach to a process by process ID or process name.
- When attaching to a process by name, lldb also supports the "<code>--waitfor</code>" option which waits for the
- next process that has that name to show up, and attaches to it</p>
-
- <code>
- (lldb) process attach --pid 123
- <br>(lldb) process attach --name Sketch
- <br>(lldb) process attach --name Sketch --waitfor
- </code>
-
- <p>After you launch or attach to a process, your process might stop
- somewhere:</p>
- <code>
- (lldb) process attach -p 12345
- <br>Process 46915 Attaching
- <br>Process 46915 Stopped
- <br>1 of 3 threads stopped with reasons:
- <br>* thread #1: tid = 0x2c03, 0x00007fff85cac76a, where = libSystem.B.dylib`__getdirentries64 + 10, stop reason = signal = SIGSTOP, queue = com.apple.main-thread
- </code>
-
-
- <p>Note the line that says "<code>1 of 3 threads stopped with reasons:</code>" 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.</p>
-
- </div>
- <div class="postfooter"></div>
-
- <div class="post">
- <h1 class ="postheader">Controlling your Program</h1>
- <div class="postcontent">
-
-
- <p>After launching, we can continue until we hit our breakpoint. The primitive
- commands for process control all exist under the "thread" command:</p>
-
- <code>
- (lldb) thread continue
- <br>Resuming thread 0x2c03 in process 46915
- <br>Resuming process 46915
- <br>(lldb)
- </code>
-
- <p>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.</p>
-
- <p>The other program stepping commands are pretty much the same as in gdb.
- You've got:</p>
-
- <pre><tt>(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"
-</tt></pre>
-
- <p>By default, lldb does defined aliases to all common gdb process control
- commands ("<code>s</code>", "<code>step</code>", "<code>n</code>", "<code>next</code>", "<code>finish</code>").
- If we have missed any, please add them to your <code>~/.lldbinit</code> file
- using the "<code>command alias</code>" command.
-
- <p>lldb also supported the <i>step by instruction</i> versions:</p>
- <pre><tt>(lldb) thread step-inst // The same as gdb's "stepi" / "si"
-(lldb) thread step-over-inst // The same as gdb's "nexti" / "ni"
-</tt></pre>
-
- <p>Finally, lldb has a <i>run until line or frame exit</i> stepping mode:</p>
-
- <code>
- (lldb) thread until 100
- </code>
-
- <p>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 "<code>until</code>" command.</p>
-
- <p>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.</p>
-
- <p>If you attach to a process, or launch a process with the "<code>--no-stdin</code>"
- option, the command interpreter is always available to enter commands. This
- might be a little disconcerting to gdb users when always have an <code>(lldb)</code>
- prompt. This allows you to set a breakpoint, etc without having to explicitly interrupt
- the program you are debugging:</p>
-
- <code>
- (lldb) process continue
- <br>(lldb) breakpoint set --name stop_here
- </code>
-
- <p>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 <i>thread centric debugging</i>.
- This mode will allow us to run all threads and only stop the threads
- that are at breakpoints or have exceptions or signals.</p>
-
- <p>The commands that currently work while running include
- interrupting the process to halt execution ("<code>process interrupt</code>"),
- getting the process status ("<code>process status</code>"),
- breakpoint setting and clearing ("<code> breakpoint [set|clear|enable|disable|list] ...</code>"),
- and memory reading and writing ("<code> memory [read|write] ...</code>").
- </p>
-
- <p>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 <code>--no-stdin</code> mode, you can set this
- as a generic process property using the lldb "<code>settings</code>&qout; command,
- which is equivalent to gdb's "<code>set</code>" command. For instance,
- in this case you would say:</p>
-
- <code>
- (lldb) settings set target.process.disable-stdio true
- </code>
-
- <p>Over time, gdb's "<code>set</code> 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 "<code>settings list</code>" and
- there is help on the settings command explaining how it works more generally.</p>
-
- </div>
- <div class="postfooter"></div>
-
- <div class="post">
- <h1 class ="postheader">Examining Thread State</h1>
- <div class="postcontent">
-
- <p>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.</p>
-
- <p>To inspect the current state of your process, you can start with the
- threads:</p>
-
- <pre><tt>(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
-</tt></pre>
-
- <p>The * indicates that Thread 1 is the current thread. To get a
- backtrace for that thread, do:</p>
-
- <pre><tt>(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
-</tt></pre>
-
- <p>You can also provide a list of threads to backtrace, or the keyword
- "all" to see all threads:</p>
-
- <code>
- (lldb) thread backtrace all
- </code>
-
- <p>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:</p>
-
- <code>
- (lldb) thread select 2
- </code>
-
- <p>where the thread index is just the one shown in the "<code>thread list</code>" listing.
-
- </div>
- <div class="postfooter"></div>
-
- <div class="post">
- <h1 class ="postheader">Examining Stack Frame State</h1>
- <div class="postcontent">
-
-
- <p>The most convenient way to inspect a frame's arguments and local variables is to use the "<code>frame variable</code>" command:</p>
-
- <code>
- (lldb) frame variable
- <br>self = (SKTGraphicView *) 0x0000000100208b40
- <br>_cmd = (struct objc_selector *) 0x000000010001bae1
- <br>sender = (id) 0x00000001001264e0
- <br>selection = (NSArray *) 0x00000001001264e0
- <br>i = (NSUInteger) 0x00000001001264e0
- <br>c = (NSUInteger) 0x00000001001253b0
- </code>
-
- <p>As you see above, if you don't specify any variable names, all arguments
- and locals will be shown. If you call "<code>frame variable</code>"
- passing in the names of a particular local(s), only those variables
- will be printed. For instance:
- </p>
-
- <code>
- (lldb) frame variable self
- <br>(SKTGraphicView *) self = 0x0000000100208b40
- </code>
-
- <p>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:
- </p>
-
- <code>
- <br>(lldb) frame variable self.isa
- <br>(struct objc_class *) self.isa = 0x0000000100023730
- </code>
-
- <p>The "<code>frame variable</code>" 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:</p>
-
- <code>
- (lldb) frame variable *self
- <br>(SKTGraphicView *) self = 0x0000000100208b40
- <br>(NSView) NSView = {
- <br>(NSResponder) NSResponder = {
- <br>...
- <br>
- <br>(lldb) frame variable &self
- <br>(SKTGraphicView **) &self = 0x0000000100304ab
- <br>
- <br>(lldb) frame variable argv[0]
- <br>(char const *) argv[0] = 0x00007fff5fbffaf8 "/Projects/Sketch/build/Debug/Sketch.app/Contents/MacOS/Sketch"
- </code>
-
- <p>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:</p>
-
- <code>
- (lldb) frame variable -o self
- (SKTGraphicView *) self = 0x0000000100208b40 <SKTGraphicView: 0x100208b40>
- </code>
-
- <p>You can select another frame to view with the "<code>frame select</code>" command</p>
-
- <code>
- (lldb) frame select 9
- <br>frame #9: 0x0000000100015ae3, where = Sketch`function1 + 33 at /Projects/Sketch/SKTFunctions.m:11
- </code>
-
- <p>You can also move up and down the stack by passing the "<code>--relative</code>" ("<code>-r</code>")
- option. And we have built-in aliases "<code>u</code>" and "<code>d</code>" which
- behave like their gdb equivalents.
-
- <p>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:</p>
-
- <code>
- (lldb) expr self
- <br>$0 = (SKTGraphicView *) 0x0000000100135430
- <br>(lldb) expr self = 0x00
- <br>$1 = (SKTGraphicView *) 0x0000000000000000
- <br>(lldb) frame var self
- <br>(SKTGraphicView *) self = 0x0000000000000000
- </code>
-
- <p>You can also call functions:</p>
-
- <code>
- (lldb) expr (int) printf ("I have a pointer 0x%llx.\n", self)
- <br>$2 = (int) 22
- <br>I have a pointer 0x0.
- </code>
-
- <p>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...</p>
-
- <p>Finally, the results of the expressions are stored in persistent variables
- (of the form $[0-9]+) that you can use in further expressions, like:</p>
-
- <code>
- (lldb) expr self = $0
- <br>$4 = (SKTGraphicView *) 0x0000000100135430
- </code>
- <p>
- </div>
- <div class="postfooter"></div>
-
- </div>
- </div>
- </div>
-</div>
-</body>
-</html>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> +<link href="style.css" rel="stylesheet" type="text/css" /> +<title>LLDB Tutorial</title> +</head> + +<body> + <div class="www_title"> + The <strong>LLDB</strong> Debugger + </div> + +<div id="container"> + <div id="content"> + <!--#include virtual="sidebar.incl"--> + <div id="middle"> + <div class="post"> + <h1 class ="postheader">Getting Started</h1> + <div class="postcontent"> + + <p>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.</p> + + </div> + <div class="postfooter"></div> + + <div class="post"> + <h1 class ="postheader">Command Structure</h1> + <div class="postcontent"> + + <p>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:</p> + + <code color=#ff0000> + <noun> <verb> [-options [option-value]] [argument [argument...]] + </code> + + <p>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.</p> + + <p>Options can be placed anywhere on the command line, but if the arguments + begin with a "<code>-</code>" then you have to tell lldb that you're done with options + for the current command by adding an option termination: "<code>--</code>" + So for instance if you want to launch a process and give the "process launch" command + the "<code>--stop-at-entry</code>" option, yet you want the + process you are about to launch to be launched with the arguments + "<code>-program_arg value</code>", you would type:</p> + + <code> + (lldb) process launch --stop-at-entry -- -program_arg value + </code> + + <p>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</p> + + <code> + (gdb) break foo.c:12 + </code> + <p>to break at line 12 of foo.c, and:</p> + <code> + (gdb) break foo + </code> + + <p>to break at the function <code>foo</code>. As time went on, the parser that tells <code>foo.c:12</code> + from <code>foo</code> from <code>foo.c::foo</code> (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. + + <p>To set the same file and line breakpoint in LLDB you can enter either of:</p> + + <code> + (lldb) breakpoint set --file foo.c --line 12 + <br>(lldb) breakpoint set -f foo.c -l 12 + </code> + + <p>To set a breakpoint on a function named <code>foo</code> in LLDB you can enter either of:</p> + + <code> + (lldb) breakpoint set --name foo + <br>(lldb) breakpoint set -n foo + </code> + + <p>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:</p> + + <code> + (lldb) breakpoint set --name foo --name bar + </code> + + <p>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 <code>foo</code> you can enter either of:</p> + + <code> + (lldb) breakpoint set --method foo + <br>(lldb) breakpoint set -M foo + </code> + + <p>To set a breakpoint Objective C selectors named <code>alignLeftEdges:</code> you can enter either of:</p> + + <code> + (lldb) breakpoint set --selector alignLeftEdges: + <br>(lldb) breakpoint set -S alignLeftEdges: + </code> + + <p>You can limit any breakpoints to a specific executable image by using + the "<code>--shlib <path></code>" ("<code>-s <path></code>" for short):</p> + + <code> + (lldb) breakpoint set --shlib foo.dylib --name foo + <br>(lldb) breakpoint set -s foo.dylib -n foo + </code> + + <p>The <code>--shlib</code> option can also be repeated to specify several shared libraries.</p> + + <p>Suggestions on more interesting primitives of this sort are also very welcome.</p> + + <p>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:</p> + + <code> + (lldb) breakpoint set -n "-[SKTGraphicView alignLeftEdges:]" + <br>(lldb) br s -n "-[SKTGraphicView alignLeftEdges:]" + </code> + + <p>lldb also supports command completion for source file names, symbol + names, file names, etc. Completion is initiated by a hitting a <b>TAB</b>. + Individual options in a command can have different completers, so for + instance the "<code>--file <path></code>" option in "breakpoint" completes to source files, the + "<code>--shlib <path></code>" option to currently loaded shared libraries, etc. We can even do + things like if you specify "<code>--shlib <path></code>", and are completing on "<code>--file <path></code>", we will only + list source files in the shared library specified by "<code>--shlib <path></code>".</p> + + <p>The individual commands are pretty extensively documented. You can + use the <code>help</code> command to get an overview of which commands are + available or to obtain details about specific commands. There is also an + <code>apropos</code> command that will search the help text for all commands + for a particular word and dump a summary help string for each matching + command.</p> + + <p>Finally, there is a mechanism to construct aliases for commonly used + commands. So for instance if you get annoyed typing:</p> + + <code> + (lldb) breakpoint set --file foo.c --line 12 + </code> + + <p>you can do:</p> + + <code> + (lldb) command alias bfl breakpoint set -f %1 -l %2 + <br>(lldb) bfl foo.c 12 + </code> + + <p>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.</p> + + <p>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.</p> + + <p> 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 <code>foo.c::bar</code>. But + it mostly works, and makes the transition easier. Also by popular demand, it + is aliased to <code>b</code>. 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):</p> + + <code> + (lldb) command unalias b + </code> + + <p>I actually also do:</p> + + <code> + (lldb) command alias b breakpoint + </code> + + <p>so I can run the native lldb breakpoint command with just <code>b</code></p> + + <p>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. + + <p>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.</p> + + <p>Having given an overview of lldb's command syntax, we proceed to lay out the stages + of a standard debug session.</p> + + </div> + <div class="postfooter"></div> + + + <div class="post"> + <h1 class ="postheader">Loading a program into lldb</h1> + <div class="postcontent"> + + <p>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:</p> + + <code> + $ lldb /Projects/Sketch/build/Debug/Sketch.app + <br>Current executable set to '/Projects/Sketch/build/Debug/Sketch.app' (x86_64). + </code> + + <p>or you can specify it after the fact with the "file" command:</p> + + <code> + $ lldb + <br>(lldb) file /Projects/Sketch/build/Debug/Sketch.app + <br>Current executable set to '/Projects/Sketch/build/Debug/Sketch.app' (x86_64). + </code> + <p> + </div> + <div class="postfooter"></div> + + <div class="post"> + <h1 class ="postheader">Setting breakpoints</h1> + <div class="postcontent"> + + <p>We've discussed how to set breakpoints above. You can use <code>help breakpoint set</code> + to see all the options for breakpoint setting. For instance, we might do:</p> + + <code> + (lldb) breakpoint set --selector alignLeftEdges: + <br>Breakpoint created: 1: name = 'alignLeftEdges:', locations = 1, resolved = 1 + </code> + + <p>You can find out about the breakpoints you've set with:</p> + + <pre><tt>(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 +</tt></pre> + + <p>Note that setting a breakpoint creates a <i>logical</i> breakpoint, which could + resolve to one or more <i>locations</i>. 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.</p> + + <p>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.) </p> + + <p>Also the logical breakpoints remain <i>live</i> so that if another shared library + were to be loaded that had another implementation of the + "<code>alignLeftEdges:</code>" selector, the new location would be added to + breakpoint 1 (e.g. a "1.2" breakpoint would be set on the newly loaded + selector).</p> + + <p>The other piece of information in the breakpoint listing is whether the + breakpoint location was <i>resolved</i> 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 <i>resolved</i>.</p> + + <p>One other thing to note for gdb users is that lldb acts like gdb with:</p> + + <code> + (gdb) set breakpoint pending on + </code> + + <p>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:</p> + + <code> + (lldb) breakpoint set --file foo.c --line 12 + <br>Breakpoint created: 2: file ='foo.c', line = 12, locations = 0 (pending) + <br>WARNING: Unable to resolve breakpoint to any actual locations. + </code> + + <p>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:</p> + + <code> + (lldb) breakpoint command add 1.1 + <br>Enter your debugger command(s). Type 'DONE' to end. + <br>> bt + <br>> DONE + </code> + + <p>By default, the <code> breakpoint command add</code> command takes lldb command line commands. + You can also specify this explicitly by passing the "<code>--command</code>" option. + Use "<code>--script</code>" if you want to implement your breakpoint command using the Python script instead.</p> + + <p>This is an convenient point to bring up another feature of the lldb command help. Do:</p> + + <code> + (lldb) help break command add + <br>Add a set of commands to a breakpoint, to be executed whenever the breakpoint is hit. + <br> + <br>Syntax: breakpoint command add <cmd-options> <breakpt-id> + <br> etc... + </code> + + <p>When you see arguments to commands specified in the Syntax in angle + brackets like <code><breakpt-id></code>, 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:</p> + + <code> + (lldb) help <breakpt-id> + <br><breakpt-id> -- Breakpoint ID's consist major and minor numbers; the major + <br> etc... + </code> + + </div> + <div class="postfooter"></div> + + <div class="post"> + <h1 class ="postheader">Setting watchpoints</h1> + <div class="postcontent"> + + <p>In addition to breakpoints, you can use <code>help watchpoint</code> + 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:</p> + + <pre><tt>(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) </tt></pre> + </div> + <div class="postfooter"></div> + + <div class="post"> + <h1 class ="postheader">Starting or attaching to your Program</h1> + <div class="postcontent"> + + <p>To launch a program in lldb we use the "<code>process launch</code>" command or + one of its built in aliases:</p> + + <code> + (lldb) process launch + <br>(lldb) run + <br>(lldb) r + </code> + + <p>You can also attach to a process by process ID or process name. + When attaching to a process by name, lldb also supports the "<code>--waitfor</code>" option which waits for the + next process that has that name to show up, and attaches to it</p> + + <code> + (lldb) process attach --pid 123 + <br>(lldb) process attach --name Sketch + <br>(lldb) process attach --name Sketch --waitfor + </code> + + <p>After you launch or attach to a process, your process might stop + somewhere:</p> + <code> + (lldb) process attach -p 12345 + <br>Process 46915 Attaching + <br>Process 46915 Stopped + <br>1 of 3 threads stopped with reasons: + <br>* thread #1: tid = 0x2c03, 0x00007fff85cac76a, where = libSystem.B.dylib`__getdirentries64 + 10, stop reason = signal = SIGSTOP, queue = com.apple.main-thread + </code> + + + <p>Note the line that says "<code>1 of 3 threads stopped with reasons:</code>" 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.</p> + + </div> + <div class="postfooter"></div> + + <div class="post"> + <h1 class ="postheader">Controlling your Program</h1> + <div class="postcontent"> + + + <p>After launching, we can continue until we hit our breakpoint. The primitive + commands for process control all exist under the "thread" command:</p> + + <code> + (lldb) thread continue + <br>Resuming thread 0x2c03 in process 46915 + <br>Resuming process 46915 + <br>(lldb) + </code> + + <p>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.</p> + + <p>The other program stepping commands are pretty much the same as in gdb. + You've got:</p> + + <pre><tt>(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" +</tt></pre> + + <p>By default, lldb does defined aliases to all common gdb process control + commands ("<code>s</code>", "<code>step</code>", "<code>n</code>", "<code>next</code>", "<code>finish</code>"). + If we have missed any, please add them to your <code>~/.lldbinit</code> file + using the "<code>command alias</code>" command. + + <p>lldb also supported the <i>step by instruction</i> versions:</p> + <pre><tt>(lldb) thread step-inst // The same as gdb's "stepi" / "si" +(lldb) thread step-over-inst // The same as gdb's "nexti" / "ni" +</tt></pre> + + <p>Finally, lldb has a <i>run until line or frame exit</i> stepping mode:</p> + + <code> + (lldb) thread until 100 + </code> + + <p>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 "<code>until</code>" command.</p> + + <p>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.</p> + + <p>If you attach to a process, or launch a process with the "<code>--no-stdin</code>" + option, the command interpreter is always available to enter commands. This + might be a little disconcerting to gdb users when always have an <code>(lldb)</code> + prompt. This allows you to set a breakpoint, etc without having to explicitly interrupt + the program you are debugging:</p> + + <code> + (lldb) process continue + <br>(lldb) breakpoint set --name stop_here + </code> + + <p>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 <i>thread centric debugging</i>. + This mode will allow us to run all threads and only stop the threads + that are at breakpoints or have exceptions or signals.</p> + + <p>The commands that currently work while running include + interrupting the process to halt execution ("<code>process interrupt</code>"), + getting the process status ("<code>process status</code>"), + breakpoint setting and clearing ("<code> breakpoint [set|clear|enable|disable|list] ...</code>"), + and memory reading and writing ("<code> memory [read|write] ...</code>"). + </p> + + <p>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 <code>--no-stdin</code> mode, you can set this + as a generic process property using the lldb "<code>settings</code>&qout; command, + which is equivalent to gdb's "<code>set</code>" command. For instance, + in this case you would say:</p> + + <code> + (lldb) settings set target.process.disable-stdio true + </code> + + <p>Over time, gdb's "<code>set</code> 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 "<code>settings list</code>" and + there is help on the settings command explaining how it works more generally.</p> + + </div> + <div class="postfooter"></div> + + <div class="post"> + <h1 class ="postheader">Examining Thread State</h1> + <div class="postcontent"> + + <p>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.</p> + + <p>To inspect the current state of your process, you can start with the + threads:</p> + + <pre><tt>(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 +</tt></pre> + + <p>The * indicates that Thread 1 is the current thread. To get a + backtrace for that thread, do:</p> + + <pre><tt>(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 +</tt></pre> + + <p>You can also provide a list of threads to backtrace, or the keyword + "all" to see all threads:</p> + + <code> + (lldb) thread backtrace all + </code> + + <p>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:</p> + + <code> + (lldb) thread select 2 + </code> + + <p>where the thread index is just the one shown in the "<code>thread list</code>" listing. + + </div> + <div class="postfooter"></div> + + <div class="post"> + <h1 class ="postheader">Examining Stack Frame State</h1> + <div class="postcontent"> + + + <p>The most convenient way to inspect a frame's arguments and local variables is to use the "<code>frame variable</code>" command:</p> + + <code> + (lldb) frame variable + <br>self = (SKTGraphicView *) 0x0000000100208b40 + <br>_cmd = (struct objc_selector *) 0x000000010001bae1 + <br>sender = (id) 0x00000001001264e0 + <br>selection = (NSArray *) 0x00000001001264e0 + <br>i = (NSUInteger) 0x00000001001264e0 + <br>c = (NSUInteger) 0x00000001001253b0 + </code> + + <p>As you see above, if you don't specify any variable names, all arguments + and locals will be shown. If you call "<code>frame variable</code>" + passing in the names of a particular local(s), only those variables + will be printed. For instance: + </p> + + <code> + (lldb) frame variable self + <br>(SKTGraphicView *) self = 0x0000000100208b40 + </code> + + <p>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: + </p> + + <code> + <br>(lldb) frame variable self.isa + <br>(struct objc_class *) self.isa = 0x0000000100023730 + </code> + + <p>The "<code>frame variable</code>" 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:</p> + + <code> + (lldb) frame variable *self + <br>(SKTGraphicView *) self = 0x0000000100208b40 + <br>(NSView) NSView = { + <br>(NSResponder) NSResponder = { + <br>... + <br> + <br>(lldb) frame variable &self + <br>(SKTGraphicView **) &self = 0x0000000100304ab + <br> + <br>(lldb) frame variable argv[0] + <br>(char const *) argv[0] = 0x00007fff5fbffaf8 "/Projects/Sketch/build/Debug/Sketch.app/Contents/MacOS/Sketch" + </code> + + <p>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:</p> + + <code> + (lldb) frame variable -o self + (SKTGraphicView *) self = 0x0000000100208b40 <SKTGraphicView: 0x100208b40> + </code> + + <p>You can select another frame to view with the "<code>frame select</code>" command</p> + + <code> + (lldb) frame select 9 + <br>frame #9: 0x0000000100015ae3, where = Sketch`function1 + 33 at /Projects/Sketch/SKTFunctions.m:11 + </code> + + <p>You can also move up and down the stack by passing the "<code>--relative</code>" ("<code>-r</code>") + option. And we have built-in aliases "<code>u</code>" and "<code>d</code>" which + behave like their gdb equivalents. + + <p>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:</p> + + <code> + (lldb) expr self + <br>$0 = (SKTGraphicView *) 0x0000000100135430 + <br>(lldb) expr self = 0x00 + <br>$1 = (SKTGraphicView *) 0x0000000000000000 + <br>(lldb) frame var self + <br>(SKTGraphicView *) self = 0x0000000000000000 + </code> + + <p>You can also call functions:</p> + + <code> + (lldb) expr (int) printf ("I have a pointer 0x%llx.\n", self) + <br>$2 = (int) 22 + <br>I have a pointer 0x0. + </code> + + <p>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...</p> + + <p>Finally, the results of the expressions are stored in persistent variables + (of the form $[0-9]+) that you can use in further expressions, like:</p> + + <code> + (lldb) expr self = $0 + <br>$4 = (SKTGraphicView *) 0x0000000100135430 + </code> + <p> + </div> + <div class="postfooter"></div> + + </div> + </div> + </div> +</div> +</body> +</html> |