[www-releases] r184289 - Add a patch for the lldb sources that fixes a hang in the test suite.
Bill Wendling
isanbard at gmail.com
Wed Jun 19 01:20:36 PDT 2013
Author: void
Date: Wed Jun 19 03:20:36 2013
New Revision: 184289
URL: http://llvm.org/viewvc/llvm-project?rev=184289&view=rev
Log:
Add a patch for the lldb sources that fixes a hang in the test suite.
Added:
www-releases/trunk/3.3/merge-lldb33.patch
www-releases/trunk/3.3/merge-lldb33.patch.sig (with props)
Modified:
www-releases/trunk/download.html
Added: www-releases/trunk/3.3/merge-lldb33.patch
URL: http://llvm.org/viewvc/llvm-project/www-releases/trunk/3.3/merge-lldb33.patch?rev=184289&view=auto
==============================================================================
--- www-releases/trunk/3.3/merge-lldb33.patch (added)
+++ www-releases/trunk/3.3/merge-lldb33.patch Wed Jun 19 03:20:36 2013
@@ -0,0 +1,17398 @@
+Index: include/lldb/Utility/AnsiTerminal.h
+===================================================================
+--- include/lldb/Utility/AnsiTerminal.h (revision 183906)
++++ include/lldb/Utility/AnsiTerminal.h (working copy)
+@@ -21,7 +21,7 @@
+ #define ANSI_BG_COLOR_BLACK 40
+ #define ANSI_BG_COLOR_RED 41
+ #define ANSI_BG_COLOR_GREEN 42
+-#define ANSI_BG_COLOR_YELLOW 44
++#define ANSI_BG_COLOR_YELLOW 43
+ #define ANSI_BG_COLOR_BLUE 44
+ #define ANSI_BG_COLOR_PURPLE 45
+ #define ANSI_BG_COLOR_CYAN 46
+@@ -82,5 +82,75 @@
+ const char *k_ctrl_conceal = "8";
+ const char *k_ctrl_crossed_out = "9";
+
++ inline std::string
++ FormatAnsiTerminalCodes(const char *format, bool do_color = true)
++ {
++ // Convert "${ansi.XXX}" tokens to ansi values or clear them if do_color is false.
++ static const struct
++ {
++ const char *name;
++ const char *value;
++ } g_color_tokens[] =
++ {
++ #define _TO_STR2(_val) #_val
++ #define _TO_STR(_val) _TO_STR2(_val)
++ { "fg.black}", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLACK) ANSI_ESC_END },
++ { "fg.red}", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_RED) ANSI_ESC_END },
++ { "fg.green}", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_GREEN) ANSI_ESC_END },
++ { "fg.yellow}", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_YELLOW) ANSI_ESC_END },
++ { "fg.blue}", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLUE) ANSI_ESC_END },
++ { "fg.purple}", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_PURPLE) ANSI_ESC_END },
++ { "fg.cyan}", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_CYAN) ANSI_ESC_END },
++ { "fg.white}", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_WHITE) ANSI_ESC_END },
++ { "bg.black}", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLACK) ANSI_ESC_END },
++ { "bg.red}", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_RED) ANSI_ESC_END },
++ { "bg.green}", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_GREEN) ANSI_ESC_END },
++ { "bg.yellow}", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_YELLOW) ANSI_ESC_END },
++ { "bg.blue}", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLUE) ANSI_ESC_END },
++ { "bg.purple}", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_PURPLE) ANSI_ESC_END },
++ { "bg.cyan}", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_CYAN) ANSI_ESC_END },
++ { "bg.white}", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_WHITE) ANSI_ESC_END },
++ { "normal}", ANSI_ESC_START _TO_STR(ANSI_CTRL_NORMAL) ANSI_ESC_END },
++ { "bold}", ANSI_ESC_START _TO_STR(ANSI_CTRL_BOLD) ANSI_ESC_END },
++ { "faint}", ANSI_ESC_START _TO_STR(ANSI_CTRL_FAINT) ANSI_ESC_END },
++ { "italic}", ANSI_ESC_START _TO_STR(ANSI_CTRL_ITALIC) ANSI_ESC_END },
++ { "underline}", ANSI_ESC_START _TO_STR(ANSI_CTRL_UNDERLINE) ANSI_ESC_END },
++ { "slow-blink}", ANSI_ESC_START _TO_STR(ANSI_CTRL_SLOW_BLINK) ANSI_ESC_END },
++ { "fast-blink}", ANSI_ESC_START _TO_STR(ANSI_CTRL_FAST_BLINK) ANSI_ESC_END },
++ { "negative}", ANSI_ESC_START _TO_STR(ANSI_CTRL_IMAGE_NEGATIVE) ANSI_ESC_END },
++ { "conceal}", ANSI_ESC_START _TO_STR(ANSI_CTRL_CONCEAL) ANSI_ESC_END },
++ { "crossed-out}", ANSI_ESC_START _TO_STR(ANSI_CTRL_CROSSED_OUT) ANSI_ESC_END },
++ #undef _TO_STR
++ #undef _TO_STR2
++ };
++ static const char tok_hdr[] = "${ansi.";
++
++ std::string fmt;
++ for (const char *p = format; *p; ++p)
++ {
++ const char *tok_start = strstr (p, tok_hdr);
++ if (!tok_start)
++ {
++ fmt.append (p, strlen(p));
++ break;
++ }
++
++ fmt.append (p, tok_start - p);
++ p = tok_start;
++
++ const char *tok_str = tok_start + sizeof(tok_hdr) - 1;
++ for (size_t i = 0; i < sizeof(g_color_tokens) / sizeof(g_color_tokens[0]); ++i)
++ {
++ if (!strncmp (tok_str, g_color_tokens[i].name, strlen(g_color_tokens[i].name)))
++ {
++ if (do_color)
++ fmt.append (g_color_tokens[i].value);
++ p = tok_str + strlen (g_color_tokens[i].name) - 1;
++ break;
++ }
++ }
++ }
++ return fmt;
++ }
+ }
+ }
+Index: include/lldb/Interpreter/PythonDataObjects.h
+===================================================================
+--- include/lldb/Interpreter/PythonDataObjects.h (revision 183906)
++++ include/lldb/Interpreter/PythonDataObjects.h (working copy)
+@@ -82,13 +82,16 @@
+ }
+
+ void
+- Dump () const
++ Dump () const
+ {
+ if (m_py_obj)
+ _PyObject_Dump (m_py_obj);
+ else
+ puts ("NULL");
+ }
++
++ void
++ Dump (Stream &strm) const;
+
+ PyObject*
+ GetPythonObject () const
+Index: include/lldb/Interpreter/CommandInterpreter.h
+===================================================================
+--- include/lldb/Interpreter/CommandInterpreter.h (revision 183906)
++++ include/lldb/Interpreter/CommandInterpreter.h (working copy)
+@@ -396,7 +396,9 @@
+ void
+ FindCommandsForApropos (const char *word,
+ StringList &commands_found,
+- StringList &commands_help);
++ StringList &commands_help,
++ bool search_builtin_commands,
++ bool search_user_commands);
+
+ bool
+ GetBatchCommandMode () { return m_batch_command_mode; }
+Index: include/lldb/Symbol/SymbolContext.h
+===================================================================
+--- include/lldb/Symbol/SymbolContext.h (revision 183906)
++++ include/lldb/Symbol/SymbolContext.h (working copy)
+@@ -153,7 +153,7 @@
+ /// information in this context. If a module, function, file and
+ /// line number are available, they will be dumped. If only a
+ /// module and function or symbol name with offset is available,
+- /// that will be ouput. Else just the address at which the target
++ /// that will be output. Else just the address at which the target
+ /// was stopped will be displayed.
+ ///
+ /// @param[in] s
+@@ -285,9 +285,33 @@
+ /// The name of the function represented by this symbol context.
+ //------------------------------------------------------------------
+ ConstString
+- GetFunctionName (Mangled::NamePreference preference = Mangled::ePreferDemangled);
++ GetFunctionName (Mangled::NamePreference preference = Mangled::ePreferDemangled) const;
+
++
+ //------------------------------------------------------------------
++ /// Get the line entry that corresponds to the function.
++ ///
++ /// If the symbol context contains an inlined block, the line entry
++ /// for the start address of the inlined function will be returned,
++ /// otherwise the line entry for the start address of the function
++ /// will be returned. This can be used after doing a
++ /// Module::FindFunctions(...) or ModuleList::FindFunctions(...)
++ /// call in order to get the correct line table information for
++ /// the symbol context.
++ /// it will return the inlined function name.
++ ///
++ /// @param[in] prefer_mangled
++ /// if \btrue, then the mangled name will be returned if there
++ /// is one. Otherwise the unmangled name will be returned if it
++ /// is available.
++ ///
++ /// @return
++ /// The name of the function represented by this symbol context.
++ //------------------------------------------------------------------
++ LineEntry
++ GetFunctionStartLineEntry () const;
++
++ //------------------------------------------------------------------
+ /// Find the block containing the inlined block that contains this block.
+ ///
+ /// For instance, if the symbol context contains an inlined block,
+Index: include/lldb/API/SBDebugger.h
+===================================================================
+--- include/lldb/API/SBDebugger.h (revision 183906)
++++ include/lldb/API/SBDebugger.h (working copy)
+@@ -172,6 +172,12 @@
+ bool
+ GetUseExternalEditor ();
+
++ bool
++ SetUseColor (bool use_color);
++
++ bool
++ GetUseColor () const;
++
+ static bool
+ GetDefaultArchitecture (char *arch_name, size_t arch_name_len);
+
+Index: include/lldb/API/SBDefines.h
+===================================================================
+--- include/lldb/API/SBDefines.h (revision 183906)
++++ include/lldb/API/SBDefines.h (working copy)
+@@ -19,6 +19,7 @@
+ #include "lldb/lldb-enumerations.h"
+ #include "lldb/lldb-forward.h"
+ #include "lldb/lldb-types.h"
++#include "lldb/lldb-versioning.h"
+
+ // Forward Declarations
+
+Index: include/lldb/lldb-enumerations.h
+===================================================================
+--- include/lldb/lldb-enumerations.h (revision 183906)
++++ include/lldb/lldb-enumerations.h (working copy)
+@@ -541,10 +541,7 @@
+ // methods or selectors will be searched.
+ eFunctionNameTypeMethod = (1u << 4), // Find function by method name (C++) with no namespace or arguments
+ eFunctionNameTypeSelector = (1u << 5), // Find function by selector name (ObjC) names
+- eFunctionNameTypeAny = (eFunctionNameTypeFull |
+- eFunctionNameTypeBase |
+- eFunctionNameTypeMethod |
+- eFunctionNameTypeSelector )
++ eFunctionNameTypeAny = eFunctionNameTypeAuto // DEPRECATED: use eFunctionNameTypeAuto
+ } FunctionNameType;
+
+
+Index: include/lldb/Host/Host.h
+===================================================================
+--- include/lldb/Host/Host.h (revision 183906)
++++ include/lldb/Host/Host.h (working copy)
+@@ -13,6 +13,7 @@
+
+ #include <stdarg.h>
+
++#include <map>
+ #include <string>
+
+ #include "lldb/lldb-private.h"
+@@ -414,8 +415,13 @@
+ static uint32_t
+ FindProcesses (const ProcessInstanceInfoMatch &match_info,
+ ProcessInstanceInfoList &proc_infos);
+-
++
++ typedef std::map<lldb::pid_t, bool> TidMap;
++ typedef std::pair<lldb::pid_t, bool> TidPair;
+ static bool
++ FindProcessThreads (const lldb::pid_t pid, TidMap &tids_to_attach);
++
++ static bool
+ GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &proc_info);
+
+ static lldb::pid_t
+Index: include/lldb/Host/File.h
+===================================================================
+--- include/lldb/Host/File.h (revision 183906)
++++ include/lldb/Host/File.h (working copy)
+@@ -282,17 +282,19 @@
+ /// @see File::Read (void *, size_t, off_t &)
+ /// @see File::Write (const void *, size_t, off_t &)
+ ///
+- /// @param[in/out] offset
++ /// @param[in] offset
+ /// The offset to seek to within the file relative to the
+- /// beginning of the file which gets filled in the the resulting
+- /// absolute file offset.
++ /// beginning of the file.
+ ///
++ /// @param[in] error_ptr
++ /// A pointer to a lldb_private::Error object that will be
++ /// filled in if non-NULL.
++ ///
+ /// @return
+- /// An error object that indicates success or the reason for
+- /// failure.
++ /// The resulting seek offset, or -1 on error.
+ //------------------------------------------------------------------
+- Error
+- SeekFromStart (off_t& offset);
++ off_t
++ SeekFromStart (off_t offset, Error *error_ptr = NULL);
+
+ //------------------------------------------------------------------
+ /// Seek to an offset relative to the current file position.
+@@ -303,17 +305,19 @@
+ /// @see File::Read (void *, size_t, off_t &)
+ /// @see File::Write (const void *, size_t, off_t &)
+ ///
+- /// @param[in/out] offset
++ /// @param[in] offset
+ /// The offset to seek to within the file relative to the
+- /// current file position. On return this parameter gets filled
+- /// in the the resulting absolute file offset.
++ /// current file position.
+ ///
++ /// @param[in] error_ptr
++ /// A pointer to a lldb_private::Error object that will be
++ /// filled in if non-NULL.
++ ///
+ /// @return
+- /// An error object that indicates success or the reason for
+- /// failure.
++ /// The resulting seek offset, or -1 on error.
+ //------------------------------------------------------------------
+- Error
+- SeekFromCurrent (off_t& offset);
++ off_t
++ SeekFromCurrent (off_t offset, Error *error_ptr = NULL);
+
+ //------------------------------------------------------------------
+ /// Seek to an offset relative to the end of the file.
+@@ -329,12 +333,15 @@
+ /// end of the file which gets filled in the the resulting
+ /// absolute file offset.
+ ///
++ /// @param[in] error_ptr
++ /// A pointer to a lldb_private::Error object that will be
++ /// filled in if non-NULL.
++ ///
+ /// @return
+- /// An error object that indicates success or the reason for
+- /// failure.
++ /// The resulting seek offset, or -1 on error.
+ //------------------------------------------------------------------
+- Error
+- SeekFromEnd (off_t& offset);
++ off_t
++ SeekFromEnd (off_t offset, Error *error_ptr = NULL);
+
+ //------------------------------------------------------------------
+ /// Read bytes from a file from the specified file offset.
+Index: include/lldb/lldb-versioning.h
+===================================================================
+--- include/lldb/lldb-versioning.h (revision 0)
++++ include/lldb/lldb-versioning.h (revision 0)
+@@ -0,0 +1,1607 @@
++//===-- lldb-versioning.h ----------------------------------------*- C++ -*-===//
++//
++// The LLVM Compiler Infrastructure
++//
++// This file is distributed under the University of Illinois Open Source
++// License. See LICENSE.TXT for details.
++//
++//===----------------------------------------------------------------------===//
++
++#ifndef LLDB_lldb_versioning_h_
++#define LLDB_lldb_versioning_h_
++
++//----------------------------------------------------------------------
++// LLDB API version
++//----------------------------------------------------------------------
++#define LLDB_API_MAJOR_VERSION 1
++#define LLDB_API_MINOR_VERSION 0
++
++/*
++ API versioning
++ ---------------------------------
++
++ The LLDB API is versioned independently of the LLDB source base
++ Our API version numbers are composed of a major and a minor number
++
++ The major number means a complete and stable revision of the API. Major numbers are compatibility breakers
++ (i.e. when we change the API major number, there is no promise of compatibility with the previous major version
++ and we are free to remove and/or change any APIs)
++ Minor numbers are a work-in-progress evolution of the API. APIs will not be removed or changed across minor versions
++ (minors do not break compatibility). However, we can deprecate APIs in minor versions or add new APIs in minor versions
++ A deprecated API is supposedly going to be removed in the next major version and will generate a warning if used
++ APIs we add in minor versions will not be removed (at least until the following major) but they might theoretically be deprecated
++ in a following minor version
++ Users are discouraged from using the LLDB version number to test for API features and should instead use the API version checking
++ as discussed below
++
++ API version checking
++ ---------------------------------
++
++ You can (optionally) sign into an API version checking feature
++ To do so you need to define three macros:
++ LLDB_API_CHECK_VERSIONING - define to any value (or no value)
++ LLDB_API_MAJOR_VERSION_WANTED - which major version of the LLDB API you are targeting
++ LLDB_API_MINOR_VERSION_WANTED - which minor version of the LLDB API you are targeting
++
++ If these macros exist - LLDB will enable version checking of the public API
++
++ If LLDB_API_MAJOR_VERSION is not equal to LLDB_API_MAJOR_VERSION_WANTED we will immediately halt your compilation with an error
++ This is by design, since we do not make any promise of compatibility across major versions - if you really want to test your luck, disable the versioning altogether
++
++ If the major version test passes, you have signed up for a specific minor version of the API
++ Whenever we add or deprecate an API in a minor version, we will mark it with either
++ LLDB_API_NEW_IN_DOT_x - this API is new in LLDB .x
++ LLDB_API_DEPRECATED_IN_DOT_x - this API is deprecated as of .x
++
++ If you are using an API new in DOT_x
++ if LLDB_API_MINOR_VERSION_WANTED >= x then all is well, else you will get a compilation error
++ This is meant to prevent you from using APIs that are newer than whatever LLDB you want to target
++
++ If you are using an API deprecated in DOT_x
++ if LLDB_API_MINOR_VERSION_WANTED >= x then you will get a compilation warning, else all is well
++ This is meant to let you know that you are using an API that is deprecated and might go away
++
++ Caveats
++ ---------------------------------
++
++ Version checking only works on clang on OSX - you will get an error if you try to enable it on any other OS/compiler
++ If you want to enable version checking on other platforms, you will need to define appropriate implementations for
++ LLDB_API_IMPL_DEPRECATED and LLDB_API_IMPL_TOONEW and any other infrastructure your compiler needs for this purpose
++
++ We have no deprecation-as-error mode
++
++ There is no support for API versioning in Python
++
++ We reserve to use macros whose names begin with LLDB_API_ and you should not use them in your source code as they might conflict
++ with present or future macro names we are using to implement versioning
++*/
++
++// if you want the version checking to work on other OS/compiler, define appropriate IMPL_DEPRECATED/IMPL_TOONEW
++// and define LLDB_API_CHECK_VERSIONING_WORKS when you are ready to go live
++#if defined(__APPLE__) && defined(__clang__)
++#define LLDB_API_IMPL_DEPRECATED __attribute__((deprecated))
++#define LLDB_API_IMPL_TOONEW __attribute__((unavailable))
++#define LLDB_API_CHECK_VERSIONING_WORKS
++#endif
++
++#if defined(LLDB_API_CHECK_VERSIONING) && !defined(LLDB_API_CHECK_VERSIONING_WORKS)
++#error "API version checking will not work here - please disable or create and submit patches to lldb-versioning.h"
++#endif
++
++#if defined(LLDB_API_CHECK_VERSIONING_WORKS) && (!defined(LLDB_API_IMPL_DEPRECATED) || !defined(LLDB_API_IMPL_TOONEW))
++#error "LLDB_API_CHECK_VERSIONING_WORKS needs LLDB_API_IMPL_DEPRECATED and LLDB_API_IMPL_TOONEW to be defined"
++#endif
++
++#if defined(LLDB_API_CHECK_VERSIONING) && defined(LLDB_API_MAJOR_VERSION_WANTED) && defined(LLDB_API_MINOR_VERSION_WANTED)
++
++#if defined (LLDB_API_MAJOR_VERSION) && (LLDB_API_MAJOR_VERSION != LLDB_API_MAJOR_VERSION_WANTED)
++#error "Cannot link using this LLDB version - public API versions are incompatible"
++#endif
++
++#define LLDB_API_MINOR_VERSION_DOT_0 0
++#define LLDB_API_MINOR_VERSION_DOT_1 1
++#define LLDB_API_MINOR_VERSION_DOT_2 2
++#define LLDB_API_MINOR_VERSION_DOT_3 3
++#define LLDB_API_MINOR_VERSION_DOT_4 4
++#define LLDB_API_MINOR_VERSION_DOT_5 5
++#define LLDB_API_MINOR_VERSION_DOT_6 6
++#define LLDB_API_MINOR_VERSION_DOT_7 7
++#define LLDB_API_MINOR_VERSION_DOT_8 8
++#define LLDB_API_MINOR_VERSION_DOT_9 9
++#define LLDB_API_MINOR_VERSION_DOT_10 10
++#define LLDB_API_MINOR_VERSION_DOT_11 11
++#define LLDB_API_MINOR_VERSION_DOT_12 12
++#define LLDB_API_MINOR_VERSION_DOT_13 13
++#define LLDB_API_MINOR_VERSION_DOT_14 14
++#define LLDB_API_MINOR_VERSION_DOT_15 15
++#define LLDB_API_MINOR_VERSION_DOT_16 16
++#define LLDB_API_MINOR_VERSION_DOT_17 17
++#define LLDB_API_MINOR_VERSION_DOT_18 18
++#define LLDB_API_MINOR_VERSION_DOT_19 19
++#define LLDB_API_MINOR_VERSION_DOT_20 20
++#define LLDB_API_MINOR_VERSION_DOT_21 21
++#define LLDB_API_MINOR_VERSION_DOT_22 22
++#define LLDB_API_MINOR_VERSION_DOT_23 23
++#define LLDB_API_MINOR_VERSION_DOT_24 24
++#define LLDB_API_MINOR_VERSION_DOT_25 25
++#define LLDB_API_MINOR_VERSION_DOT_26 26
++#define LLDB_API_MINOR_VERSION_DOT_27 27
++#define LLDB_API_MINOR_VERSION_DOT_28 28
++#define LLDB_API_MINOR_VERSION_DOT_29 29
++#define LLDB_API_MINOR_VERSION_DOT_30 30
++#define LLDB_API_MINOR_VERSION_DOT_31 31
++#define LLDB_API_MINOR_VERSION_DOT_32 32
++#define LLDB_API_MINOR_VERSION_DOT_33 33
++#define LLDB_API_MINOR_VERSION_DOT_34 34
++#define LLDB_API_MINOR_VERSION_DOT_35 35
++#define LLDB_API_MINOR_VERSION_DOT_36 36
++#define LLDB_API_MINOR_VERSION_DOT_37 37
++#define LLDB_API_MINOR_VERSION_DOT_38 38
++#define LLDB_API_MINOR_VERSION_DOT_39 39
++#define LLDB_API_MINOR_VERSION_DOT_40 40
++#define LLDB_API_MINOR_VERSION_DOT_41 41
++#define LLDB_API_MINOR_VERSION_DOT_42 42
++#define LLDB_API_MINOR_VERSION_DOT_43 43
++#define LLDB_API_MINOR_VERSION_DOT_44 44
++#define LLDB_API_MINOR_VERSION_DOT_45 45
++#define LLDB_API_MINOR_VERSION_DOT_46 46
++#define LLDB_API_MINOR_VERSION_DOT_47 47
++#define LLDB_API_MINOR_VERSION_DOT_48 48
++#define LLDB_API_MINOR_VERSION_DOT_49 49
++#define LLDB_API_MINOR_VERSION_DOT_50 50
++#define LLDB_API_MINOR_VERSION_DOT_51 51
++#define LLDB_API_MINOR_VERSION_DOT_52 52
++#define LLDB_API_MINOR_VERSION_DOT_53 53
++#define LLDB_API_MINOR_VERSION_DOT_54 54
++#define LLDB_API_MINOR_VERSION_DOT_55 55
++#define LLDB_API_MINOR_VERSION_DOT_56 56
++#define LLDB_API_MINOR_VERSION_DOT_57 57
++#define LLDB_API_MINOR_VERSION_DOT_58 58
++#define LLDB_API_MINOR_VERSION_DOT_59 59
++#define LLDB_API_MINOR_VERSION_DOT_60 60
++#define LLDB_API_MINOR_VERSION_DOT_61 61
++#define LLDB_API_MINOR_VERSION_DOT_62 62
++#define LLDB_API_MINOR_VERSION_DOT_63 63
++#define LLDB_API_MINOR_VERSION_DOT_64 64
++#define LLDB_API_MINOR_VERSION_DOT_65 65
++#define LLDB_API_MINOR_VERSION_DOT_66 66
++#define LLDB_API_MINOR_VERSION_DOT_67 67
++#define LLDB_API_MINOR_VERSION_DOT_68 68
++#define LLDB_API_MINOR_VERSION_DOT_69 69
++#define LLDB_API_MINOR_VERSION_DOT_70 70
++#define LLDB_API_MINOR_VERSION_DOT_71 71
++#define LLDB_API_MINOR_VERSION_DOT_72 72
++#define LLDB_API_MINOR_VERSION_DOT_73 73
++#define LLDB_API_MINOR_VERSION_DOT_74 74
++#define LLDB_API_MINOR_VERSION_DOT_75 75
++#define LLDB_API_MINOR_VERSION_DOT_76 76
++#define LLDB_API_MINOR_VERSION_DOT_77 77
++#define LLDB_API_MINOR_VERSION_DOT_78 78
++#define LLDB_API_MINOR_VERSION_DOT_79 79
++#define LLDB_API_MINOR_VERSION_DOT_80 80
++#define LLDB_API_MINOR_VERSION_DOT_81 81
++#define LLDB_API_MINOR_VERSION_DOT_82 82
++#define LLDB_API_MINOR_VERSION_DOT_83 83
++#define LLDB_API_MINOR_VERSION_DOT_84 84
++#define LLDB_API_MINOR_VERSION_DOT_85 85
++#define LLDB_API_MINOR_VERSION_DOT_86 86
++#define LLDB_API_MINOR_VERSION_DOT_87 87
++#define LLDB_API_MINOR_VERSION_DOT_88 88
++#define LLDB_API_MINOR_VERSION_DOT_89 89
++#define LLDB_API_MINOR_VERSION_DOT_90 90
++#define LLDB_API_MINOR_VERSION_DOT_91 91
++#define LLDB_API_MINOR_VERSION_DOT_92 92
++#define LLDB_API_MINOR_VERSION_DOT_93 93
++#define LLDB_API_MINOR_VERSION_DOT_94 94
++#define LLDB_API_MINOR_VERSION_DOT_95 95
++#define LLDB_API_MINOR_VERSION_DOT_96 96
++#define LLDB_API_MINOR_VERSION_DOT_97 97
++#define LLDB_API_MINOR_VERSION_DOT_98 98
++#define LLDB_API_MINOR_VERSION_DOT_99 99
++
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_0
++#define LLDB_API_NEW_IN_DOT_0 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_0
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_0
++#define LLDB_API_DEPRECATED_IN_DOT_0 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_0
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_1
++#define LLDB_API_NEW_IN_DOT_1 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_1
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_1
++#define LLDB_API_DEPRECATED_IN_DOT_1 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_1
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_2
++#define LLDB_API_NEW_IN_DOT_2 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_2
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_2
++#define LLDB_API_DEPRECATED_IN_DOT_2 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_2
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_3
++#define LLDB_API_NEW_IN_DOT_3 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_3
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_3
++#define LLDB_API_DEPRECATED_IN_DOT_3 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_3
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_4
++#define LLDB_API_NEW_IN_DOT_4 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_4
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_4
++#define LLDB_API_DEPRECATED_IN_DOT_4 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_4
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_5
++#define LLDB_API_NEW_IN_DOT_5 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_5
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_5
++#define LLDB_API_DEPRECATED_IN_DOT_5 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_5
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_6
++#define LLDB_API_NEW_IN_DOT_6 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_6
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_6
++#define LLDB_API_DEPRECATED_IN_DOT_6 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_6
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_7
++#define LLDB_API_NEW_IN_DOT_7 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_7
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_7
++#define LLDB_API_DEPRECATED_IN_DOT_7 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_7
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_8
++#define LLDB_API_NEW_IN_DOT_8 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_8
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_8
++#define LLDB_API_DEPRECATED_IN_DOT_8 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_8
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_9
++#define LLDB_API_NEW_IN_DOT_9 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_9
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_9
++#define LLDB_API_DEPRECATED_IN_DOT_9 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_9
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_10
++#define LLDB_API_NEW_IN_DOT_10 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_10
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_10
++#define LLDB_API_DEPRECATED_IN_DOT_10 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_10
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_11
++#define LLDB_API_NEW_IN_DOT_11 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_11
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_11
++#define LLDB_API_DEPRECATED_IN_DOT_11 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_11
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_12
++#define LLDB_API_NEW_IN_DOT_12 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_12
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_12
++#define LLDB_API_DEPRECATED_IN_DOT_12 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_12
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_13
++#define LLDB_API_NEW_IN_DOT_13 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_13
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_13
++#define LLDB_API_DEPRECATED_IN_DOT_13 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_13
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_14
++#define LLDB_API_NEW_IN_DOT_14 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_14
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_14
++#define LLDB_API_DEPRECATED_IN_DOT_14 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_14
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_15
++#define LLDB_API_NEW_IN_DOT_15 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_15
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_15
++#define LLDB_API_DEPRECATED_IN_DOT_15 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_15
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_16
++#define LLDB_API_NEW_IN_DOT_16 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_16
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_16
++#define LLDB_API_DEPRECATED_IN_DOT_16 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_16
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_17
++#define LLDB_API_NEW_IN_DOT_17 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_17
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_17
++#define LLDB_API_DEPRECATED_IN_DOT_17 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_17
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_18
++#define LLDB_API_NEW_IN_DOT_18 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_18
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_18
++#define LLDB_API_DEPRECATED_IN_DOT_18 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_18
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_19
++#define LLDB_API_NEW_IN_DOT_19 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_19
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_19
++#define LLDB_API_DEPRECATED_IN_DOT_19 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_19
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_20
++#define LLDB_API_NEW_IN_DOT_20 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_20
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_20
++#define LLDB_API_DEPRECATED_IN_DOT_20 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_20
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_21
++#define LLDB_API_NEW_IN_DOT_21 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_21
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_21
++#define LLDB_API_DEPRECATED_IN_DOT_21 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_21
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_22
++#define LLDB_API_NEW_IN_DOT_22 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_22
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_22
++#define LLDB_API_DEPRECATED_IN_DOT_22 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_22
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_23
++#define LLDB_API_NEW_IN_DOT_23 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_23
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_23
++#define LLDB_API_DEPRECATED_IN_DOT_23 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_23
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_24
++#define LLDB_API_NEW_IN_DOT_24 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_24
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_24
++#define LLDB_API_DEPRECATED_IN_DOT_24 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_24
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_25
++#define LLDB_API_NEW_IN_DOT_25 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_25
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_25
++#define LLDB_API_DEPRECATED_IN_DOT_25 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_25
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_26
++#define LLDB_API_NEW_IN_DOT_26 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_26
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_26
++#define LLDB_API_DEPRECATED_IN_DOT_26 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_26
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_27
++#define LLDB_API_NEW_IN_DOT_27 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_27
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_27
++#define LLDB_API_DEPRECATED_IN_DOT_27 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_27
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_28
++#define LLDB_API_NEW_IN_DOT_28 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_28
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_28
++#define LLDB_API_DEPRECATED_IN_DOT_28 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_28
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_29
++#define LLDB_API_NEW_IN_DOT_29 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_29
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_29
++#define LLDB_API_DEPRECATED_IN_DOT_29 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_29
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_30
++#define LLDB_API_NEW_IN_DOT_30 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_30
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_30
++#define LLDB_API_DEPRECATED_IN_DOT_30 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_30
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_31
++#define LLDB_API_NEW_IN_DOT_31 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_31
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_31
++#define LLDB_API_DEPRECATED_IN_DOT_31 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_31
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_32
++#define LLDB_API_NEW_IN_DOT_32 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_32
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_32
++#define LLDB_API_DEPRECATED_IN_DOT_32 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_32
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_33
++#define LLDB_API_NEW_IN_DOT_33 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_33
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_33
++#define LLDB_API_DEPRECATED_IN_DOT_33 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_33
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_34
++#define LLDB_API_NEW_IN_DOT_34 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_34
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_34
++#define LLDB_API_DEPRECATED_IN_DOT_34 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_34
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_35
++#define LLDB_API_NEW_IN_DOT_35 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_35
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_35
++#define LLDB_API_DEPRECATED_IN_DOT_35 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_35
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_36
++#define LLDB_API_NEW_IN_DOT_36 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_36
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_36
++#define LLDB_API_DEPRECATED_IN_DOT_36 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_36
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_37
++#define LLDB_API_NEW_IN_DOT_37 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_37
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_37
++#define LLDB_API_DEPRECATED_IN_DOT_37 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_37
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_38
++#define LLDB_API_NEW_IN_DOT_38 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_38
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_38
++#define LLDB_API_DEPRECATED_IN_DOT_38 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_38
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_39
++#define LLDB_API_NEW_IN_DOT_39 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_39
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_39
++#define LLDB_API_DEPRECATED_IN_DOT_39 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_39
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_40
++#define LLDB_API_NEW_IN_DOT_40 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_40
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_40
++#define LLDB_API_DEPRECATED_IN_DOT_40 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_40
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_41
++#define LLDB_API_NEW_IN_DOT_41 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_41
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_41
++#define LLDB_API_DEPRECATED_IN_DOT_41 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_41
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_42
++#define LLDB_API_NEW_IN_DOT_42 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_42
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_42
++#define LLDB_API_DEPRECATED_IN_DOT_42 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_42
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_43
++#define LLDB_API_NEW_IN_DOT_43 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_43
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_43
++#define LLDB_API_DEPRECATED_IN_DOT_43 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_43
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_44
++#define LLDB_API_NEW_IN_DOT_44 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_44
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_44
++#define LLDB_API_DEPRECATED_IN_DOT_44 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_44
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_45
++#define LLDB_API_NEW_IN_DOT_45 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_45
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_45
++#define LLDB_API_DEPRECATED_IN_DOT_45 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_45
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_46
++#define LLDB_API_NEW_IN_DOT_46 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_46
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_46
++#define LLDB_API_DEPRECATED_IN_DOT_46 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_46
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_47
++#define LLDB_API_NEW_IN_DOT_47 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_47
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_47
++#define LLDB_API_DEPRECATED_IN_DOT_47 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_47
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_48
++#define LLDB_API_NEW_IN_DOT_48 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_48
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_48
++#define LLDB_API_DEPRECATED_IN_DOT_48 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_48
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_49
++#define LLDB_API_NEW_IN_DOT_49 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_49
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_49
++#define LLDB_API_DEPRECATED_IN_DOT_49 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_49
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_50
++#define LLDB_API_NEW_IN_DOT_50 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_50
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_50
++#define LLDB_API_DEPRECATED_IN_DOT_50 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_50
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_51
++#define LLDB_API_NEW_IN_DOT_51 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_51
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_51
++#define LLDB_API_DEPRECATED_IN_DOT_51 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_51
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_52
++#define LLDB_API_NEW_IN_DOT_52 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_52
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_52
++#define LLDB_API_DEPRECATED_IN_DOT_52 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_52
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_53
++#define LLDB_API_NEW_IN_DOT_53 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_53
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_53
++#define LLDB_API_DEPRECATED_IN_DOT_53 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_53
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_54
++#define LLDB_API_NEW_IN_DOT_54 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_54
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_54
++#define LLDB_API_DEPRECATED_IN_DOT_54 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_54
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_55
++#define LLDB_API_NEW_IN_DOT_55 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_55
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_55
++#define LLDB_API_DEPRECATED_IN_DOT_55 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_55
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_56
++#define LLDB_API_NEW_IN_DOT_56 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_56
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_56
++#define LLDB_API_DEPRECATED_IN_DOT_56 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_56
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_57
++#define LLDB_API_NEW_IN_DOT_57 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_57
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_57
++#define LLDB_API_DEPRECATED_IN_DOT_57 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_57
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_58
++#define LLDB_API_NEW_IN_DOT_58 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_58
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_58
++#define LLDB_API_DEPRECATED_IN_DOT_58 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_58
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_59
++#define LLDB_API_NEW_IN_DOT_59 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_59
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_59
++#define LLDB_API_DEPRECATED_IN_DOT_59 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_59
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_60
++#define LLDB_API_NEW_IN_DOT_60 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_60
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_60
++#define LLDB_API_DEPRECATED_IN_DOT_60 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_60
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_61
++#define LLDB_API_NEW_IN_DOT_61 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_61
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_61
++#define LLDB_API_DEPRECATED_IN_DOT_61 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_61
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_62
++#define LLDB_API_NEW_IN_DOT_62 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_62
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_62
++#define LLDB_API_DEPRECATED_IN_DOT_62 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_62
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_63
++#define LLDB_API_NEW_IN_DOT_63 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_63
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_63
++#define LLDB_API_DEPRECATED_IN_DOT_63 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_63
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_64
++#define LLDB_API_NEW_IN_DOT_64 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_64
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_64
++#define LLDB_API_DEPRECATED_IN_DOT_64 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_64
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_65
++#define LLDB_API_NEW_IN_DOT_65 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_65
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_65
++#define LLDB_API_DEPRECATED_IN_DOT_65 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_65
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_66
++#define LLDB_API_NEW_IN_DOT_66 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_66
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_66
++#define LLDB_API_DEPRECATED_IN_DOT_66 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_66
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_67
++#define LLDB_API_NEW_IN_DOT_67 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_67
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_67
++#define LLDB_API_DEPRECATED_IN_DOT_67 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_67
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_68
++#define LLDB_API_NEW_IN_DOT_68 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_68
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_68
++#define LLDB_API_DEPRECATED_IN_DOT_68 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_68
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_69
++#define LLDB_API_NEW_IN_DOT_69 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_69
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_69
++#define LLDB_API_DEPRECATED_IN_DOT_69 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_69
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_70
++#define LLDB_API_NEW_IN_DOT_70 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_70
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_70
++#define LLDB_API_DEPRECATED_IN_DOT_70 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_70
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_71
++#define LLDB_API_NEW_IN_DOT_71 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_71
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_71
++#define LLDB_API_DEPRECATED_IN_DOT_71 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_71
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_72
++#define LLDB_API_NEW_IN_DOT_72 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_72
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_72
++#define LLDB_API_DEPRECATED_IN_DOT_72 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_72
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_73
++#define LLDB_API_NEW_IN_DOT_73 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_73
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_73
++#define LLDB_API_DEPRECATED_IN_DOT_73 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_73
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_74
++#define LLDB_API_NEW_IN_DOT_74 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_74
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_74
++#define LLDB_API_DEPRECATED_IN_DOT_74 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_74
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_75
++#define LLDB_API_NEW_IN_DOT_75 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_75
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_75
++#define LLDB_API_DEPRECATED_IN_DOT_75 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_75
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_76
++#define LLDB_API_NEW_IN_DOT_76 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_76
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_76
++#define LLDB_API_DEPRECATED_IN_DOT_76 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_76
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_77
++#define LLDB_API_NEW_IN_DOT_77 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_77
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_77
++#define LLDB_API_DEPRECATED_IN_DOT_77 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_77
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_78
++#define LLDB_API_NEW_IN_DOT_78 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_78
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_78
++#define LLDB_API_DEPRECATED_IN_DOT_78 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_78
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_79
++#define LLDB_API_NEW_IN_DOT_79 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_79
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_79
++#define LLDB_API_DEPRECATED_IN_DOT_79 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_79
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_80
++#define LLDB_API_NEW_IN_DOT_80 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_80
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_80
++#define LLDB_API_DEPRECATED_IN_DOT_80 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_80
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_81
++#define LLDB_API_NEW_IN_DOT_81 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_81
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_81
++#define LLDB_API_DEPRECATED_IN_DOT_81 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_81
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_82
++#define LLDB_API_NEW_IN_DOT_82 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_82
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_82
++#define LLDB_API_DEPRECATED_IN_DOT_82 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_82
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_83
++#define LLDB_API_NEW_IN_DOT_83 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_83
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_83
++#define LLDB_API_DEPRECATED_IN_DOT_83 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_83
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_84
++#define LLDB_API_NEW_IN_DOT_84 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_84
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_84
++#define LLDB_API_DEPRECATED_IN_DOT_84 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_84
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_85
++#define LLDB_API_NEW_IN_DOT_85 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_85
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_85
++#define LLDB_API_DEPRECATED_IN_DOT_85 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_85
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_86
++#define LLDB_API_NEW_IN_DOT_86 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_86
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_86
++#define LLDB_API_DEPRECATED_IN_DOT_86 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_86
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_87
++#define LLDB_API_NEW_IN_DOT_87 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_87
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_87
++#define LLDB_API_DEPRECATED_IN_DOT_87 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_87
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_88
++#define LLDB_API_NEW_IN_DOT_88 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_88
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_88
++#define LLDB_API_DEPRECATED_IN_DOT_88 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_88
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_89
++#define LLDB_API_NEW_IN_DOT_89 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_89
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_89
++#define LLDB_API_DEPRECATED_IN_DOT_89 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_89
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_90
++#define LLDB_API_NEW_IN_DOT_90 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_90
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_90
++#define LLDB_API_DEPRECATED_IN_DOT_90 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_90
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_91
++#define LLDB_API_NEW_IN_DOT_91 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_91
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_91
++#define LLDB_API_DEPRECATED_IN_DOT_91 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_91
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_92
++#define LLDB_API_NEW_IN_DOT_92 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_92
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_92
++#define LLDB_API_DEPRECATED_IN_DOT_92 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_92
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_93
++#define LLDB_API_NEW_IN_DOT_93 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_93
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_93
++#define LLDB_API_DEPRECATED_IN_DOT_93 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_93
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_94
++#define LLDB_API_NEW_IN_DOT_94 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_94
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_94
++#define LLDB_API_DEPRECATED_IN_DOT_94 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_94
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_95
++#define LLDB_API_NEW_IN_DOT_95 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_95
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_95
++#define LLDB_API_DEPRECATED_IN_DOT_95 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_95
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_96
++#define LLDB_API_NEW_IN_DOT_96 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_96
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_96
++#define LLDB_API_DEPRECATED_IN_DOT_96 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_96
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_97
++#define LLDB_API_NEW_IN_DOT_97 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_97
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_97
++#define LLDB_API_DEPRECATED_IN_DOT_97 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_97
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_98
++#define LLDB_API_NEW_IN_DOT_98 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_98
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_98
++#define LLDB_API_DEPRECATED_IN_DOT_98 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_98
++#endif
++#if LLDB_API_MINOR_VERSION_WANTED < LLDB_API_MINOR_VERSION_DOT_99
++#define LLDB_API_NEW_IN_DOT_99 LLDB_API_IMPL_TOONEW
++#else
++#define LLDB_API_NEW_IN_DOT_99
++#endif
++
++
++#if LLDB_API_MINOR_VERSION_WANTED >= LLDB_API_MINOR_VERSION_DOT_99
++#define LLDB_API_DEPRECATED_IN_DOT_99 LLDB_API_IMPL_DEPRECATED
++#else
++#define LLDB_API_DEPRECATED_IN_DOT_99
++#endif
++
++#else // defined(LLDB_CHECK_API_VERSIONING) && defined(LLDB_API_MAJOR_VERSION_WANTED) && defined(LLDB_API_MINOR_VERSION_WANTED) && defined (LLDB_API_MAJOR_VERSION)
++
++#define LLDB_API_NEW_IN_DOT_0
++#define LLDB_API_DEPRECATED_IN_DOT_0
++#define LLDB_API_NEW_IN_DOT_1
++#define LLDB_API_DEPRECATED_IN_DOT_1
++#define LLDB_API_NEW_IN_DOT_2
++#define LLDB_API_DEPRECATED_IN_DOT_2
++#define LLDB_API_NEW_IN_DOT_3
++#define LLDB_API_DEPRECATED_IN_DOT_3
++#define LLDB_API_NEW_IN_DOT_4
++#define LLDB_API_DEPRECATED_IN_DOT_4
++#define LLDB_API_NEW_IN_DOT_5
++#define LLDB_API_DEPRECATED_IN_DOT_5
++#define LLDB_API_NEW_IN_DOT_6
++#define LLDB_API_DEPRECATED_IN_DOT_6
++#define LLDB_API_NEW_IN_DOT_7
++#define LLDB_API_DEPRECATED_IN_DOT_7
++#define LLDB_API_NEW_IN_DOT_8
++#define LLDB_API_DEPRECATED_IN_DOT_8
++#define LLDB_API_NEW_IN_DOT_9
++#define LLDB_API_DEPRECATED_IN_DOT_9
++#define LLDB_API_NEW_IN_DOT_10
++#define LLDB_API_DEPRECATED_IN_DOT_10
++#define LLDB_API_NEW_IN_DOT_11
++#define LLDB_API_DEPRECATED_IN_DOT_11
++#define LLDB_API_NEW_IN_DOT_12
++#define LLDB_API_DEPRECATED_IN_DOT_12
++#define LLDB_API_NEW_IN_DOT_13
++#define LLDB_API_DEPRECATED_IN_DOT_13
++#define LLDB_API_NEW_IN_DOT_14
++#define LLDB_API_DEPRECATED_IN_DOT_14
++#define LLDB_API_NEW_IN_DOT_15
++#define LLDB_API_DEPRECATED_IN_DOT_15
++#define LLDB_API_NEW_IN_DOT_16
++#define LLDB_API_DEPRECATED_IN_DOT_16
++#define LLDB_API_NEW_IN_DOT_17
++#define LLDB_API_DEPRECATED_IN_DOT_17
++#define LLDB_API_NEW_IN_DOT_18
++#define LLDB_API_DEPRECATED_IN_DOT_18
++#define LLDB_API_NEW_IN_DOT_19
++#define LLDB_API_DEPRECATED_IN_DOT_19
++#define LLDB_API_NEW_IN_DOT_20
++#define LLDB_API_DEPRECATED_IN_DOT_20
++#define LLDB_API_NEW_IN_DOT_21
++#define LLDB_API_DEPRECATED_IN_DOT_21
++#define LLDB_API_NEW_IN_DOT_22
++#define LLDB_API_DEPRECATED_IN_DOT_22
++#define LLDB_API_NEW_IN_DOT_23
++#define LLDB_API_DEPRECATED_IN_DOT_23
++#define LLDB_API_NEW_IN_DOT_24
++#define LLDB_API_DEPRECATED_IN_DOT_24
++#define LLDB_API_NEW_IN_DOT_25
++#define LLDB_API_DEPRECATED_IN_DOT_25
++#define LLDB_API_NEW_IN_DOT_26
++#define LLDB_API_DEPRECATED_IN_DOT_26
++#define LLDB_API_NEW_IN_DOT_27
++#define LLDB_API_DEPRECATED_IN_DOT_27
++#define LLDB_API_NEW_IN_DOT_28
++#define LLDB_API_DEPRECATED_IN_DOT_28
++#define LLDB_API_NEW_IN_DOT_29
++#define LLDB_API_DEPRECATED_IN_DOT_29
++#define LLDB_API_NEW_IN_DOT_30
++#define LLDB_API_DEPRECATED_IN_DOT_30
++#define LLDB_API_NEW_IN_DOT_31
++#define LLDB_API_DEPRECATED_IN_DOT_31
++#define LLDB_API_NEW_IN_DOT_32
++#define LLDB_API_DEPRECATED_IN_DOT_32
++#define LLDB_API_NEW_IN_DOT_33
++#define LLDB_API_DEPRECATED_IN_DOT_33
++#define LLDB_API_NEW_IN_DOT_34
++#define LLDB_API_DEPRECATED_IN_DOT_34
++#define LLDB_API_NEW_IN_DOT_35
++#define LLDB_API_DEPRECATED_IN_DOT_35
++#define LLDB_API_NEW_IN_DOT_36
++#define LLDB_API_DEPRECATED_IN_DOT_36
++#define LLDB_API_NEW_IN_DOT_37
++#define LLDB_API_DEPRECATED_IN_DOT_37
++#define LLDB_API_NEW_IN_DOT_38
++#define LLDB_API_DEPRECATED_IN_DOT_38
++#define LLDB_API_NEW_IN_DOT_39
++#define LLDB_API_DEPRECATED_IN_DOT_39
++#define LLDB_API_NEW_IN_DOT_40
++#define LLDB_API_DEPRECATED_IN_DOT_40
++#define LLDB_API_NEW_IN_DOT_41
++#define LLDB_API_DEPRECATED_IN_DOT_41
++#define LLDB_API_NEW_IN_DOT_42
++#define LLDB_API_DEPRECATED_IN_DOT_42
++#define LLDB_API_NEW_IN_DOT_43
++#define LLDB_API_DEPRECATED_IN_DOT_43
++#define LLDB_API_NEW_IN_DOT_44
++#define LLDB_API_DEPRECATED_IN_DOT_44
++#define LLDB_API_NEW_IN_DOT_45
++#define LLDB_API_DEPRECATED_IN_DOT_45
++#define LLDB_API_NEW_IN_DOT_46
++#define LLDB_API_DEPRECATED_IN_DOT_46
++#define LLDB_API_NEW_IN_DOT_47
++#define LLDB_API_DEPRECATED_IN_DOT_47
++#define LLDB_API_NEW_IN_DOT_48
++#define LLDB_API_DEPRECATED_IN_DOT_48
++#define LLDB_API_NEW_IN_DOT_49
++#define LLDB_API_DEPRECATED_IN_DOT_49
++#define LLDB_API_NEW_IN_DOT_50
++#define LLDB_API_DEPRECATED_IN_DOT_50
++#define LLDB_API_NEW_IN_DOT_51
++#define LLDB_API_DEPRECATED_IN_DOT_51
++#define LLDB_API_NEW_IN_DOT_52
++#define LLDB_API_DEPRECATED_IN_DOT_52
++#define LLDB_API_NEW_IN_DOT_53
++#define LLDB_API_DEPRECATED_IN_DOT_53
++#define LLDB_API_NEW_IN_DOT_54
++#define LLDB_API_DEPRECATED_IN_DOT_54
++#define LLDB_API_NEW_IN_DOT_55
++#define LLDB_API_DEPRECATED_IN_DOT_55
++#define LLDB_API_NEW_IN_DOT_56
++#define LLDB_API_DEPRECATED_IN_DOT_56
++#define LLDB_API_NEW_IN_DOT_57
++#define LLDB_API_DEPRECATED_IN_DOT_57
++#define LLDB_API_NEW_IN_DOT_58
++#define LLDB_API_DEPRECATED_IN_DOT_58
++#define LLDB_API_NEW_IN_DOT_59
++#define LLDB_API_DEPRECATED_IN_DOT_59
++#define LLDB_API_NEW_IN_DOT_60
++#define LLDB_API_DEPRECATED_IN_DOT_60
++#define LLDB_API_NEW_IN_DOT_61
++#define LLDB_API_DEPRECATED_IN_DOT_61
++#define LLDB_API_NEW_IN_DOT_62
++#define LLDB_API_DEPRECATED_IN_DOT_62
++#define LLDB_API_NEW_IN_DOT_63
++#define LLDB_API_DEPRECATED_IN_DOT_63
++#define LLDB_API_NEW_IN_DOT_64
++#define LLDB_API_DEPRECATED_IN_DOT_64
++#define LLDB_API_NEW_IN_DOT_65
++#define LLDB_API_DEPRECATED_IN_DOT_65
++#define LLDB_API_NEW_IN_DOT_66
++#define LLDB_API_DEPRECATED_IN_DOT_66
++#define LLDB_API_NEW_IN_DOT_67
++#define LLDB_API_DEPRECATED_IN_DOT_67
++#define LLDB_API_NEW_IN_DOT_68
++#define LLDB_API_DEPRECATED_IN_DOT_68
++#define LLDB_API_NEW_IN_DOT_69
++#define LLDB_API_DEPRECATED_IN_DOT_69
++#define LLDB_API_NEW_IN_DOT_70
++#define LLDB_API_DEPRECATED_IN_DOT_70
++#define LLDB_API_NEW_IN_DOT_71
++#define LLDB_API_DEPRECATED_IN_DOT_71
++#define LLDB_API_NEW_IN_DOT_72
++#define LLDB_API_DEPRECATED_IN_DOT_72
++#define LLDB_API_NEW_IN_DOT_73
++#define LLDB_API_DEPRECATED_IN_DOT_73
++#define LLDB_API_NEW_IN_DOT_74
++#define LLDB_API_DEPRECATED_IN_DOT_74
++#define LLDB_API_NEW_IN_DOT_75
++#define LLDB_API_DEPRECATED_IN_DOT_75
++#define LLDB_API_NEW_IN_DOT_76
++#define LLDB_API_DEPRECATED_IN_DOT_76
++#define LLDB_API_NEW_IN_DOT_77
++#define LLDB_API_DEPRECATED_IN_DOT_77
++#define LLDB_API_NEW_IN_DOT_78
++#define LLDB_API_DEPRECATED_IN_DOT_78
++#define LLDB_API_NEW_IN_DOT_79
++#define LLDB_API_DEPRECATED_IN_DOT_79
++#define LLDB_API_NEW_IN_DOT_80
++#define LLDB_API_DEPRECATED_IN_DOT_80
++#define LLDB_API_NEW_IN_DOT_81
++#define LLDB_API_DEPRECATED_IN_DOT_81
++#define LLDB_API_NEW_IN_DOT_82
++#define LLDB_API_DEPRECATED_IN_DOT_82
++#define LLDB_API_NEW_IN_DOT_83
++#define LLDB_API_DEPRECATED_IN_DOT_83
++#define LLDB_API_NEW_IN_DOT_84
++#define LLDB_API_DEPRECATED_IN_DOT_84
++#define LLDB_API_NEW_IN_DOT_85
++#define LLDB_API_DEPRECATED_IN_DOT_85
++#define LLDB_API_NEW_IN_DOT_86
++#define LLDB_API_DEPRECATED_IN_DOT_86
++#define LLDB_API_NEW_IN_DOT_87
++#define LLDB_API_DEPRECATED_IN_DOT_87
++#define LLDB_API_NEW_IN_DOT_88
++#define LLDB_API_DEPRECATED_IN_DOT_88
++#define LLDB_API_NEW_IN_DOT_89
++#define LLDB_API_DEPRECATED_IN_DOT_89
++#define LLDB_API_NEW_IN_DOT_90
++#define LLDB_API_DEPRECATED_IN_DOT_90
++#define LLDB_API_NEW_IN_DOT_91
++#define LLDB_API_DEPRECATED_IN_DOT_91
++#define LLDB_API_NEW_IN_DOT_92
++#define LLDB_API_DEPRECATED_IN_DOT_92
++#define LLDB_API_NEW_IN_DOT_93
++#define LLDB_API_DEPRECATED_IN_DOT_93
++#define LLDB_API_NEW_IN_DOT_94
++#define LLDB_API_DEPRECATED_IN_DOT_94
++#define LLDB_API_NEW_IN_DOT_95
++#define LLDB_API_DEPRECATED_IN_DOT_95
++#define LLDB_API_NEW_IN_DOT_96
++#define LLDB_API_DEPRECATED_IN_DOT_96
++#define LLDB_API_NEW_IN_DOT_97
++#define LLDB_API_DEPRECATED_IN_DOT_97
++#define LLDB_API_NEW_IN_DOT_98
++#define LLDB_API_DEPRECATED_IN_DOT_98
++#define LLDB_API_NEW_IN_DOT_99
++#define LLDB_API_DEPRECATED_IN_DOT_99
++#endif // defined(LLDB_CHECK_API_VERSIONING) && defined(LLDB_API_MAJOR_VERSION_WANTED) && defined(LLDB_API_MINOR_VERSION_WANTED) && defined (LLDB_API_MAJOR_VERSION)
++
++#endif // LLDB_lldb_versioning_h_
+\ No newline at end of file
+Index: include/lldb/Target/Target.h
+===================================================================
+--- include/lldb/Target/Target.h (revision 183906)
++++ include/lldb/Target/Target.h (working copy)
+@@ -12,6 +12,7 @@
+
+ // C Includes
+ // C++ Includes
++#include <list>
+
+ // Other libraries and framework includes
+ // Project includes
+@@ -45,7 +46,14 @@
+ eInlineBreakpointsHeaders,
+ eInlineBreakpointsAlways
+ } InlineStrategy;
+-
++
++typedef enum LoadScriptFromSymFile
++{
++ eLoadScriptFromSymFileTrue,
++ eLoadScriptFromSymFileFalse,
++ eLoadScriptFromSymFileWarn
++} LoadScriptFromSymFile;
++
+ //----------------------------------------------------------------------
+ // TargetProperties
+ //----------------------------------------------------------------------
+@@ -119,6 +127,9 @@
+
+ uint32_t
+ GetMaximumSizeOfStringSummary() const;
++
++ uint32_t
++ GetMaximumMemReadSize () const;
+
+ FileSpec
+ GetStandardInputPath () const;
+@@ -147,12 +158,9 @@
+ bool
+ GetUseFastStepping() const;
+
+- bool
++ LoadScriptFromSymFile
+ GetLoadScriptFromSymbolFile() const;
+-
+- void
+- SetLoadScriptFromSymbolFile(bool b);
+-
++
+ };
+
+ typedef std::shared_ptr<TargetProperties> TargetPropertiesSP;
+@@ -730,6 +738,14 @@
+ void
+ SetExecutableModule (lldb::ModuleSP& module_sp, bool get_dependent_files);
+
++ bool
++ LoadScriptingResources (std::list<Error>& errors,
++ Stream* feedback_stream = NULL,
++ bool continue_on_error = true)
++ {
++ return m_images.LoadScriptingResourcesInTarget(this,errors,feedback_stream,continue_on_error);
++ }
++
+ //------------------------------------------------------------------
+ /// Get accessor for the images for this process.
+ ///
+Index: include/lldb/Target/CPPLanguageRuntime.h
+===================================================================
+--- include/lldb/Target/CPPLanguageRuntime.h (revision 183906)
++++ include/lldb/Target/CPPLanguageRuntime.h (working copy)
+@@ -86,7 +86,7 @@
+ return m_full;
+ }
+
+- const ConstString &
++ llvm::StringRef
+ GetBasename ();
+
+ llvm::StringRef
+@@ -103,7 +103,7 @@
+ Parse();
+
+ ConstString m_full; // Full name: "lldb::SBTarget::GetBreakpointAtIndex(unsigned int) const"
+- ConstString m_basename; // Basename: "GetBreakpointAtIndex"
++ llvm::StringRef m_basename; // Basename: "GetBreakpointAtIndex"
+ llvm::StringRef m_context; // Decl context: "lldb::SBTarget"
+ llvm::StringRef m_arguments; // Arguments: "(unsigned int)"
+ llvm::StringRef m_qualifiers; // Qualifiers: "const"
+@@ -134,9 +134,6 @@
+ IsCPPMangledName(const char *name);
+
+ static bool
+- IsPossibleCPPCall (const char *name, const char *&base_name_start, const char *&base_name_end);
+-
+- static bool
+ StripNamespacesFromVariableName (const char *name, const char *&base_name_start, const char *&base_name_end);
+
+ // in some cases, compilers will output different names for one same type. when tht happens, it might be impossible
+Index: include/lldb/Target/Process.h
+===================================================================
+--- include/lldb/Target/Process.h (revision 183906)
++++ include/lldb/Target/Process.h (working copy)
+@@ -3532,7 +3532,73 @@
+ else
+ return m_public_run_lock;
+ }
+-
++
++ //------------------------------------------------------------------
++ // This is a cache of reserved and available memory address ranges
++ // for a single modification ID (see m_mod_id). It's meant for use
++ // by IRMemoryMap, but to stick with the process. These memory
++ // ranges happen to be unallocated in the underlying process, but we
++ // make no guarantee that at a future modification ID they won't be
++ // gone. This is only useful if the underlying process can't
++ // allocate memory.
++ //
++ // When a memory space is determined to be available it is
++ // registered as reserved at the current modification. If it is
++ // freed later, it is added to the free list if the modification ID
++ // hasn't changed. Then clients can simply query the free list for
++ // the size they want.
++ //------------------------------------------------------------------
++ class ReservationCache
++ {
++ public:
++ ReservationCache (Process &process);
++
++ //------------------------------------------------------------------
++ // Mark that a particular range of addresses is in use. Adds it
++ // to the reserved map, implicitly tying it to the current
++ // modification ID.
++ //------------------------------------------------------------------
++ void
++ Reserve (lldb::addr_t addr, size_t size);
++
++ //------------------------------------------------------------------
++ // Mark that a range is no longer in use. If it's found in the
++ // reservation list, that means that the modification ID hasn't
++ // changed since it was reserved, so it can be safely added to the
++ // free list.
++ //------------------------------------------------------------------
++ void
++ Unreserve (lldb::addr_t addr);
++
++ //------------------------------------------------------------------
++ // Try to find an unused range of the given size in the free list.
++ //------------------------------------------------------------------
++ lldb::addr_t
++ Find (size_t size);
++ private:
++ //------------------------------------------------------------------
++ // Clear all lists if the modification ID has changed.
++ //------------------------------------------------------------------
++ void CheckModID();
++
++ typedef std::map <lldb::addr_t, size_t> ReservedMap;
++ typedef std::vector <lldb::addr_t> FreeList;
++ typedef std::map <size_t, FreeList> FreeMap;
++
++ ReservedMap m_reserved_cache;
++ FreeMap m_free_cache;
++
++ Process &m_process;
++ ProcessModID m_mod_id;
++ };
++
++ ReservationCache &
++ GetReservationCache ()
++ {
++ return m_reservation_cache;
++ }
++private:
++ ReservationCache m_reservation_cache;
+ protected:
+ //------------------------------------------------------------------
+ // NextEventAction provides a way to register an action on the next
+Index: include/lldb/Target/ThreadPlan.h
+===================================================================
+--- include/lldb/Target/ThreadPlan.h (revision 183906)
++++ include/lldb/Target/ThreadPlan.h (working copy)
+@@ -544,11 +544,11 @@
+ return m_thread.GetPreviousPlan (this);
+ }
+
+- // This forwards the private Thread::GetPrivateStopReason which is generally what
++ // This forwards the private Thread::GetPrivateStopInfo which is generally what
+ // ThreadPlan's need to know.
+
+ lldb::StopInfoSP
+- GetPrivateStopReason()
++ GetPrivateStopInfo()
+ {
+ return m_thread.GetPrivateStopInfo ();
+ }
+Index: include/lldb/Target/ThreadPlanCallFunction.h
+===================================================================
+--- include/lldb/Target/ThreadPlanCallFunction.h (revision 183906)
++++ include/lldb/Target/ThreadPlanCallFunction.h (working copy)
+@@ -115,12 +115,17 @@
+
+ // If the thread plan stops mid-course, this will be the stop reason that interrupted us.
+ // Once DoTakedown is called, this will be the real stop reason at the end of the function call.
++ // If it hasn't been set for one or the other of these reasons, we'll return the PrivateStopReason.
+ // This is needed because we want the CallFunction thread plans not to show up as the stop reason.
+ // But if something bad goes wrong, it is nice to be able to tell the user what really happened.
++
+ virtual lldb::StopInfoSP
+ GetRealStopInfo()
+ {
+- return m_real_stop_info_sp;
++ if (m_real_stop_info_sp)
++ return m_real_stop_info_sp;
++ else
++ return GetPrivateStopInfo ();
+ }
+
+ lldb::addr_t
+Index: include/lldb/Target/Thread.h
+===================================================================
+--- include/lldb/Target/Thread.h (revision 183906)
++++ include/lldb/Target/Thread.h (working copy)
+@@ -381,7 +381,9 @@
+ virtual lldb::StackFrameSP
+ GetFrameWithStackID (const StackID &stack_id)
+ {
+- return GetStackFrameList()->GetFrameWithStackID (stack_id);
++ if (stack_id.IsValid())
++ return GetStackFrameList()->GetFrameWithStackID (stack_id);
++ return lldb::StackFrameSP();
+ }
+
+ uint32_t
+Index: include/lldb/Target/Memory.h
+===================================================================
+--- include/lldb/Target/Memory.h (revision 183906)
++++ include/lldb/Target/Memory.h (working copy)
+@@ -38,7 +38,7 @@
+ ~MemoryCache ();
+
+ void
+- Clear();
++ Clear(bool clear_invalid_ranges = false);
+
+ void
+ Flush (lldb::addr_t addr, size_t size);
+Index: include/lldb/Core/ValueObject.h
+===================================================================
+--- include/lldb/Core/ValueObject.h (revision 183906)
++++ include/lldb/Core/ValueObject.h (working copy)
+@@ -1104,7 +1104,7 @@
+ }
+
+ //------------------------------------------------------------------
+- /// Find out if a SBValue might have children.
++ /// Find out if a ValueObject might have children.
+ ///
+ /// This call is much more efficient than CalculateNumChildren() as
+ /// it doesn't need to complete the underlying type. This is designed
+@@ -1116,7 +1116,7 @@
+ /// doing any expensive type completion.
+ ///
+ /// @return
+- /// Returns \b true if the SBValue might have children, or \b
++ /// Returns \b true if the ValueObject might have children, or \b
+ /// false otherwise.
+ //------------------------------------------------------------------
+ virtual bool
+@@ -1230,6 +1230,7 @@
+ // as an independent ValueObjectConstResult, which isn't managed by us.
+
+ lldb::Format m_format;
++ lldb::Format m_last_format;
+ uint32_t m_last_format_mgr_revision;
+ lldb::TypeSummaryImplSP m_type_summary_sp;
+ lldb::TypeFormatImplSP m_type_format_sp;
+Index: include/lldb/Core/Debugger.h
+===================================================================
+--- include/lldb/Core/Debugger.h (revision 183906)
++++ include/lldb/Core/Debugger.h (working copy)
+@@ -236,7 +236,6 @@
+ const ExecutionContext *exe_ctx,
+ const Address *addr,
+ Stream &s,
+- const char **end,
+ ValueObject* valobj = NULL);
+
+
+@@ -308,6 +307,12 @@
+ bool
+ SetUseExternalEditor (bool use_external_editor_p);
+
++ bool
++ GetUseColor () const;
++
++ bool
++ SetUseColor (bool use_color);
++
+ uint32_t
+ GetStopSourceLineCount (bool before) const;
+
+Index: include/lldb/Core/ModuleList.h
+===================================================================
+--- include/lldb/Core/ModuleList.h (revision 183906)
++++ include/lldb/Core/ModuleList.h (working copy)
+@@ -11,6 +11,7 @@
+ #define liblldb_ModuleList_h_
+
+ #include <vector>
++#include <list>
+
+ #include "lldb/lldb-private.h"
+ #include "lldb/Host/Mutex.h"
+@@ -484,6 +485,12 @@
+ size_t
+ GetSize () const;
+
++ bool
++ LoadScriptingResourcesInTarget (Target *target,
++ std::list<Error>& errors,
++ Stream* feedback_stream = NULL,
++ bool continue_on_error = true);
++
+ static bool
+ ModuleIsInCache (const Module *module_ptr);
+
+Index: include/lldb/Core/Scalar.h
+===================================================================
+--- include/lldb/Core/Scalar.h (revision 183906)
++++ include/lldb/Core/Scalar.h (working copy)
+@@ -102,6 +102,9 @@
+
+ bool
+ Cast (Scalar::Type type);
++
++ bool
++ MakeSigned ();
+
+ static const char *
+ GetValueTypeAsCString (Scalar::Type value_type);
+Index: include/lldb/Core/UUID.h
+===================================================================
+--- include/lldb/Core/UUID.h (revision 183906)
++++ include/lldb/Core/UUID.h (working copy)
+@@ -22,7 +22,8 @@
+ class UUID
+ {
+ public:
+- typedef uint8_t ValueType[16];
++ // Most UUIDs are 16 bytes, but some Linux build-ids (SHA1) are 20.
++ typedef uint8_t ValueType[20];
+
+ //------------------------------------------------------------------
+ // Constructors and Destructors
+@@ -45,20 +46,20 @@
+ const void *
+ GetBytes() const;
+
+- static size_t
++ size_t
+ GetByteSize();
+
+ bool
+ IsValid () const;
+
+ void
+- SetBytes (const void *uuid_bytes);
++ SetBytes (const void *uuid_bytes, uint32_t num_uuid_bytes = 16);
+
+ std::string
+ GetAsString () const;
+
+ size_t
+- SetFromCString (const char *c_str);
++ SetFromCString (const char *c_str, uint32_t num_uuid_bytes = 16);
+
+ // Decode as many UUID bytes (up to 16) as possible from the C string "cstr"
+ // This is used for auto completion where a partial UUID might have been
+@@ -86,12 +87,13 @@
+ /// which should be 16 if a full UUID value was properly decoded.
+ //------------------------------------------------------------------
+ static size_t
+- DecodeUUIDBytesFromCString (const char *cstr, ValueType &uuid_bytes, const char **end);
++ DecodeUUIDBytesFromCString (const char *cstr, ValueType &uuid_bytes, const char **end, uint32_t num_uuid_bytes = 16);
+
+ protected:
+ //------------------------------------------------------------------
+ // Classes that inherit from UUID can see and modify these
+ //------------------------------------------------------------------
++ uint32_t m_num_uuid_bytes; // Should be 16 or 20
+ ValueType m_uuid;
+ };
+
+Index: include/lldb/Core/Module.h
+===================================================================
+--- include/lldb/Core/Module.h (revision 183906)
++++ include/lldb/Core/Module.h (working copy)
+@@ -595,7 +595,9 @@
+ IsLoadedInTarget (Target *target);
+
+ bool
+- LoadScriptingResourceInTarget (Target *target, Error& error);
++ LoadScriptingResourceInTarget (Target *target,
++ Error& error,
++ Stream* feedback_stream = NULL);
+
+ //------------------------------------------------------------------
+ /// Get the number of compile units for this module.
+Index: include/lldb/lldb-private-log.h
+===================================================================
+--- include/lldb/lldb-private-log.h (revision 183906)
++++ include/lldb/lldb-private-log.h (working copy)
+@@ -43,6 +43,7 @@
+ #define LIBLLDB_LOG_MODULES (1u << 21)
+ #define LIBLLDB_LOG_TARGET (1u << 22)
+ #define LIBLLDB_LOG_MMAP (1u << 23)
++#define LIBLLDB_LOG_OS (1u << 24)
+ #define LIBLLDB_LOG_ALL (UINT32_MAX)
+ #define LIBLLDB_LOG_DEFAULT (LIBLLDB_LOG_PROCESS |\
+ LIBLLDB_LOG_THREAD |\
+Index: include/lldb/Breakpoint/BreakpointLocation.h
+===================================================================
+--- include/lldb/Breakpoint/BreakpointLocation.h (revision 183906)
++++ include/lldb/Breakpoint/BreakpointLocation.h (working copy)
+@@ -20,10 +20,11 @@
+ // Project includes
+ #include "lldb/lldb-private.h"
+ #include "lldb/Breakpoint/StoppointLocation.h"
++#include "lldb/Core/Address.h"
++#include "lldb/Core/StringList.h"
+ #include "lldb/Core/UserID.h"
+-#include "lldb/Core/Address.h"
++#include "lldb/Host/Mutex.h"
+ #include "lldb/Target/Process.h"
+-#include "lldb/Core/StringList.h"
+ #include "lldb/Expression/ClangUserExpression.h"
+
+ namespace lldb_private {
+@@ -386,6 +387,7 @@
+ std::unique_ptr<BreakpointOptions> m_options_ap; ///< Breakpoint options pointer, NULL if we're using our breakpoint's options.
+ lldb::BreakpointSiteSP m_bp_site_sp; ///< Our breakpoint site (it may be shared by more than one location.)
+ ClangUserExpression::ClangUserExpressionSP m_user_expression_sp; ///< The compiled expression to use in testing our condition.
++ Mutex m_condition_mutex; ///< Guards parsing and evaluation of the condition, which could be evaluated by multiple processes.
+ size_t m_condition_hash; ///< For testing whether the condition source code changed.
+
+ void
+Index: include/lldb/Expression/Materializer.h
+===================================================================
+--- include/lldb/Expression/Materializer.h (revision 183906)
++++ include/lldb/Expression/Materializer.h (working copy)
+@@ -155,7 +155,6 @@
+ typedef std::unique_ptr<Entity> EntityUP;
+ typedef std::vector<EntityUP> EntityVector;
+
+- unsigned m_result_index;
+ DematerializerWP m_dematerializer_wp;
+ EntityVector m_entities;
+ Entity *m_result_entity;
+Index: include/lldb/Expression/IRExecutionUnit.h
+===================================================================
+--- include/lldb/Expression/IRExecutionUnit.h (revision 183906)
++++ include/lldb/Expression/IRExecutionUnit.h (working copy)
+@@ -336,7 +336,13 @@
+ /// @return
+ /// True in case of failure, false in case of success.
+ //------------------------------------------------------------------
+- bool applyPermissions(std::string *ErrMsg) { return false; }
++ virtual bool applyPermissions(std::string *ErrMsg) {
++ // TODO: Ensure that the instruction cache is flushed because
++ // relocations are updated by dy-load. See:
++ // sys::Memory::InvalidateInstructionCache
++ // llvm::SectionMemoryManager
++ return false;
++ }
+
+ //------------------------------------------------------------------
+ /// Passthrough interface stub
+Index: include/lldb/Expression/IRMemoryMap.h
+===================================================================
+--- include/lldb/Expression/IRMemoryMap.h (revision 183906)
++++ include/lldb/Expression/IRMemoryMap.h (working copy)
+@@ -50,6 +50,7 @@
+ };
+
+ lldb::addr_t Malloc (size_t size, uint8_t alignment, uint32_t permissions, AllocationPolicy policy, Error &error);
++ void Leak (lldb::addr_t process_address, Error &error);
+ void Free (lldb::addr_t process_address, Error &error);
+
+ void WriteMemory (lldb::addr_t process_address, const uint8_t *bytes, size_t size, Error &error);
+@@ -84,7 +85,10 @@
+ uint32_t m_permissions; ///< The access permissions on the memory in the process. In the host, the memory is always read/write.
+ uint8_t m_alignment; ///< The alignment of the requested allocation
+ DataBufferHeap m_data;
++
++ ///< Flags
+ AllocationPolicy m_policy;
++ bool m_leak;
+ public:
+ Allocation (lldb::addr_t process_alloc,
+ lldb::addr_t process_start,
+@@ -100,7 +104,8 @@
+ m_permissions (0),
+ m_alignment (0),
+ m_data (),
+- m_policy (eAllocationPolicyInvalid)
++ m_policy (eAllocationPolicyInvalid),
++ m_leak (false)
+ {
+ }
+ };
+Index: www/python-reference.html
+===================================================================
+--- www/python-reference.html (revision 183906)
++++ www/python-reference.html (working copy)
+@@ -271,6 +271,10 @@
+ </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
+@@ -301,8 +305,8 @@
+ > <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># How continue the process</font>
+-> <strong>frame.GetThread().GetProcess().Continue()</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.
+@@ -387,7 +391,8 @@
+ </tr>
+ </table>
+ <p>As a convenience, you can treat the result object as a Python file object, and say
+- print >>result, "my command does lots of cool stuff". SBCommandReturnObject and SBStream
++ <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
+Index: www/architecture.html
+===================================================================
+--- www/architecture.html (revision 183906)
++++ www/architecture.html (working copy)
+@@ -60,7 +60,7 @@
+ <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 object pointer, shared pointer or global variable in the lldb_private.</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
+Index: www/status.html
+===================================================================
+--- www/status.html (revision 183906)
++++ www/status.html (working copy)
+@@ -34,9 +34,10 @@
+ <h1 class ="postheader">Linux Status</h1>
+ <div class="postcontent">
+ <p> LLDB is improving on Linux. While the debugserver is not ported
+- (to enable remote debugging) and there are some stability issues, most
+- of the basic functionality, including the Python API and the commandline tool,
+- are working on i386/x86_64 architectures. ARM architectures on Linux are untested.
++ (to enable remote debugging) and debugging of multi-threaded programs is in its infancy, most
++ of the functionality, including the Python API and the command line tool,
++ is working on the x86_64 architecture, and partially working with i386.
++ FreeBSD is untested. ARM architectures on Linux are untested.
+ For more details, see the Features by OS section below.
+ </div>
+ <h1 class ="postheader">Features by OS</h1>
+@@ -47,13 +48,13 @@
+ <table border="1">
+ <tr>
+ <th>Feature</th>
+- <th>Linux<br>(i386 and x86_64)</th>
++ <th>Linux<br>(x86_64)</th>
+ <th>Mac OS X (i386/x86_64 and ARM/Thumb)</th>
+ </tr>
+ <tr>
+ <td>Backtracing</td>
++ <td>OK (except with targets built with -fomit-frame-pointer)</td>
+ <td>OK</td>
+- <td>OK</td>
+ </tr>
+ <tr>
+ <td>Breakpoints
+@@ -119,10 +120,11 @@
+ <li>launch
+ <li>attach
+ <li>continue
++ <li>fork
+ </ul>
+ </td>
+- <td>OK except attach-by-name </td>
+ <td>OK</td>
++ <td>OK</td>
+ </tr>
+ <tr>
+ <td>Public Python API</td>
+@@ -130,6 +132,19 @@
+ <td>OK</td>
+ </tr>
+ <tr>
++ <td>Registers (x86_64 and i386)
++ <ul>
++ <li>general purpose
++ <li>floating point
++ <li>exception state
++ <li>SSE
++ <li>AVX
++ </ul>
++ </td>
++ <td>OK (except for exception state registers)</td>
++ <td>OK</td>
++ </tr>
++ <tr>
+ <td>Script bridging</td>
+ <td>OK</td>
+ <td>OK</td>
+Index: www/varformats.html
+===================================================================
+--- www/varformats.html (revision 183906)
++++ www/varformats.html (working copy)
+@@ -32,8 +32,7 @@
+ different style to the display for certain datatypes.
+ To do so, you need to give hints to the debugger as to
+ how variables should be displayed.<br>
+- A new <b>type</b> command has been introduced in LLDB
+- which allows to do just that.<br>
++ The LLDB <b>type</b> command allows you to do just that.<br>
+ </p>
+
+ <p>Using it you can change your visualization to look like this: </p>
+@@ -50,7 +49,7 @@
+ style="font-style: italic;">synthetic children</span>.</p>
+
+ <p>To reflect this, the <b>type</b> command has four
+- subcommands:<br>
++ subcommands (plus one specific for <i>categories</i>):<br>
+ </p>
+
+ <p><code>type format</code></p>
+@@ -456,9 +455,7 @@
+ <code>"<b>${*var.int_pointer[0-3]}</b>".</code></p>
+ <p>Basically, the syntax is the same one described <a
+ href="formats.html">Frame and Thread Formatting</a>
+- are accepted.
+- Beyond what's described there, additional symbols have become available
+- in the syntax for summary strings. The main of them is <code>${var</code>,
++ plus additional symbols specific for summary strings. The main of them is <code>${var</code>,
+ which is used refer to the variable that a summary is being created for.</p>
+ <p>The simplest thing you can do is grab a member variable
+ of a class or structure by typing its <i>expression
+@@ -527,7 +524,7 @@
+ as in <code>${var.x->x%u}</code>, which would display the value of <code>x</code> as an unsigned integer.
+
+ <p>You can also use some other special format markers, not available
+- for type formatters, but which carry a special meaning when used in this
++ for formats themselves, but which carry a special meaning when used in this
+ context:</p>
+
+ <table border="1">
+@@ -872,18 +869,16 @@
+ <table class="stats" width="620" cellspacing="0">
+ <td class="content">
+ <b>(lldb)</b> type summary add --python-script "height =
+- int(valobj.GetChildMemberWithName('height').GetValue());width =
+- int(valobj.GetChildMemberWithName('width').GetValue());
+- return 'Area: ' + str(height*width)" Rectangle<br/>
++ valobj.GetChildMemberWithName('height').GetValueAsUnsigned(0);width =
++ valobj.GetChildMemberWithName('width').GetValueAsUnsigned(0);
++ return 'Area: %d' % (height*width)" Rectangle<br/>
+ </td>
+ </table>
+ <ul>
+ <li> using the <code>--python-function</code> (<code>-F</code>) option to <code>type summary add </code> and giving the name of a
+ Python function with the correct prototype. Most probably, you will define (or have
+ already defined) the function in the interactive interpreter, or somehow
+- loaded it from a file, using the <code>script import</code> command. LLDB will not make any attempt at determining whether
+- the function is defined and syntactically correct, until you try to call it. Any errors will be shown at that stage, as if
+- you were executing your function inside the Python interactive interpreter itself.
++ loaded it from a file, using the <code>command script import</code> command. LLDB will emit a warning if it is unable to find the function you passed, but will still register the binding.
+ </ul>
+
+ </p>
+@@ -914,8 +909,9 @@
+ <table>
+
+ <code>
+- <b>(lldb)</b> frame variable sarray<br>
++ <b>(lldb)</b> frame variable<br>
+ (Simple [3]) sarray = [1,4,7]<br>
++ (Simple [2]) sother = [3,6]<br>
+ </code> The above scenario works for <code>Simple [3]</code>
+ as well as for any other array of <code>Simple</code>
+ objects. </p>
+@@ -925,20 +921,10 @@
+ matching is slower than normal name matching, LLDB will
+ first try to match by name in any way it can, and only
+ when this fails, will it resort to regular expression
+- matching. Thus, if your type has a base class with a
+- cascading summary, this will be preferred over any
+- regular expression match for your type itself.</p>
++ matching. </p>
+ <p>One of the ways LLDB uses this feature internally, is to match
+ the names of STL container classes, regardless of the template
+- arguments provided (e.g. <code>std::vector<T></code> for any
+- type argument <code>T</code>). The regular expressions used for this are:
+- </p>
+- <ul>
+- <li><code>^(std::)?vector<.+>$</code> for <code>std::vector<T></code></li>
+- <li><code>^(std::)?list<.+>$</code> for <code>std::list<T></code></li>
+- <li><code>^(std::)?map<.+> >$</code> for <code>std::map<K,V></code></li>
+- </ul>
+- As you can see, the actual template arguments are ignored by the regular expression.
++ arguments provided. The details for this are found at <a href="http://llvm.org/svn/llvm-project/lldb/trunk/source/DataFormatters/FormatManager.cpp">FormatManager.cpp</a></p>
+
+ <p>The regular expression language used by LLDB is the <a href="http://en.wikipedia.org/wiki/Regular_expression#POSIX_Extended_Regular_Expressions">POSIX extended language</a>, as defined by the <a href="http://pubs.opengroup.org/onlinepubs/7908799/xsh/regex.h.html">Single UNIX Specification</a>, of which Mac OS X is a
+ compliant implementation.
+@@ -1041,10 +1027,11 @@
+ <font color=blue>def</font> has_children(self): <br/>
+ <i>this call should return True if this object might have children, and False if this object can be guaranteed not to have children.</i><sup>[2]</sup><br/>
+ </code>
+-<sup>[1]</sup> This method is optional. Also, it may optionally choose to return a value (starting with LLDB SVN rev153061/LLDB-134). If it returns a value, and that value is <font color=blue><code>True</code></font>, LLDB will be allowed to cache the children and the children count it previously obtained, and will not return to the provider class to ask. If nothing, <font color=blue><code>None</code></font>, or anything other than <font color=blue><code>True</code></font> is returned, LLDB will discard the cached information and ask. Regardless, whenever necessary LLDB will call <code>update</code>.
++<sup>[1]</sup> This method is optional. Also, it may optionally choose to return a value (starting with SVN rev153061/LLDB-134). If it returns a value, and that value is <font color=blue><code>True</code></font>, LLDB will be allowed to cache the children and the children count it previously obtained, and will not return to the provider class to ask. If nothing, <font color=blue><code>None</code></font>, or anything other than <font color=blue><code>True</code></font> is returned, LLDB will discard the cached information and ask. Regardless, whenever necessary LLDB will call <code>update</code>.
+ <br/>
+-<sup>[2]</sup> This method is optional, and LLDB will honor it starting with SVN rev166495. While implementing it in terms of <code>num_children</code> is acceptable, implementors are encouraged to look for optimized coding alternatives whenever reasonable. For an example, see the <code>std::list</code> providers shipping with LLDB.
+- <p>For examples of how synthetic children are created, you are encouraged to look at <a href="http://llvm.org/svn/llvm-project/lldb/trunk/examples/synthetic/">examples/synthetic</a> in the LLDB trunk.
++<sup>[2]</sup> This method is optional (starting with SVN rev166495/LLDB-175). While implementing it in terms of <code>num_children</code> is acceptable, implementors are encouraged to look for optimized coding alternatives whenever reasonable.
++ <p>For examples of how synthetic children are created, you are encouraged to look at <a href="http://llvm.org/svn/llvm-project/lldb/trunk/examples/synthetic/">examples/synthetic</a> in the LLDB trunk. Please, be aware that the code in those files (except bitfield/)
++ is legacy code and is not maintained.
+ You may especially want to begin looking at <a href="http://llvm.org/svn/llvm-project/lldb/trunk/examples/synthetic/bitfield">this example</a> to get
+ a feel for this feature, as it is a very easy and well commented example.</p>
+ The design pattern consistently used in synthetic providers shipping with LLDB
+@@ -1075,7 +1062,7 @@
+ } <br/>
+ </code> </p>
+
+- <p>LLDB has synthetic children providers for basic STL classes, both in the version provided by <a href="http://gcc.gnu.org/libstdc++/">libstdcpp</a> and by <a href="http://libcxx.llvm.org/">libcxx</a>. and for basic Cocoa containers (NSArray and NSDictionary).</p>
++ <p>LLDB has synthetic children providers for a core subset of STL classes, both in the version provided by <a href="http://gcc.gnu.org/libstdc++/">libstdcpp</a> and by <a href="http://libcxx.llvm.org/">libcxx</a>, as well as for several Foundation classes.</p>
+
+ <p>Synthetic children extend summary strings by enabling a new special variable: <code>${svar</code>.<br/>
+ This symbol tells LLDB to refer expression paths to the
+@@ -1108,7 +1095,7 @@
+ error: Couldn't convert the expression to DWARF<br/>
+ </code> </p>
+ The reason for this is that classes might have an overloaded <code><font color="blue">operator</font> []</code>, or other special provisions
+- and the <code>expression</code> command ignores synthetic children when evaluating its arguments.
++ and the <code>expression</code> command chooses to ignore synthetic children in the interest of equivalency with code you asked to have compiled from source.
+ </div>
+ </div>
+
+@@ -1144,12 +1131,10 @@
+ <div class="postcontent">
+ <p>When doing Objective-C development, you may notice that some of your variables
+ come out as of type <code>id</code> (for instance, items extracted from <code>NSArray</code>).
+- While this does not influence the ability of the runtime to send messages to them, it could make it impossible for LLDB
+- to determine the actual formatters for that object, given its type-based algorithm.</p>
+- <p>The debugger, however, can dynamically discover the type of an Objective-C
++By default, LLDB will not show you the real type of the object. it can actually dynamically discover the type of an Objective-C
+ variable, much like the runtime itself does when invoking a selector. In order
+- to let LLDB do that, however, a special option to <code>frame variable</code> is
+- required: <code>--dynamic-type</code>.</p>
++ to be shown the result of that discovery that, however, a special option to <code>frame variable</code> or <code>expression</code> is
++ required: <br/><code>--dynamic-type</code>.</p>
+ <p><code>--dynamic-type</code> can have one of three values:
+ <ul>
+ <li><code>no-dynamic-values</code>: the default, prevents dynamic type discovery</li>
+@@ -1166,18 +1151,23 @@
+ </p>
+ <p><table class="stats" width="620" cellspacing="0">
+ <td class="content">
+- <b>(lldb)</b> frame variable ns_string --dynamic-type no-run-target --show-types
++ <b>(lldb)</b> expr @"Hello"
+ </td>
+ </table>
+- <code>(__NSCFString *) ns_string = 0x00000001001183d0 @"An NSString saying hello world"<br/>
++ <code>(NSString *) $0 = 0x00000001048000b0 @"Hello"<br/>
+ </code>
++ <p><table class="stats" width="620" cellspacing="0">
++ <td class="content">
++ <b>(lldb)</b> expr -d no-run @"Hello"
++ </td>
++ </table>
++ <code>(__NSCFString *) $1 = 0x00000001048000b0 @"Hello"<br/>
++ </code>
+ <p>
+ Because LLDB uses a detection algorithm that does not need to invoke any functions
+- on the target process, <code>no-run-target</code> is enough for this to work.
+- As a final sidenote on this, LLDB is currently able to provide a summary string for <code>NSString</code>
+- that shows the content of the string, without requiring you to run code on the target
+- process. This features requires you to enable the AppKit category (see below for details).
+- The first implementation of this feature was a Python script (still available for reference at <a href="http://llvm.org/svn/llvm-project/lldb/trunk/examples/summaries/cocoa/CFString.py">CFString.py</a>).
++ on the target process, <code>no-run-target</code> is enough for this to work.</p>
++ As a side note, the summary for NSString shown in the example is built right into LLDB.
++ It was initially implemented through Python (the code is still available for reference at <a href="http://llvm.org/svn/llvm-project/lldb/trunk/examples/summaries/cocoa/CFString.py">CFString.py</a>).
+ However, this is out of sync with the current implementation of the NSString formatter (which is a C++ function compiled into the LLDB core).
+ </p>
+ </div>
+@@ -1187,7 +1177,7 @@
+ <h1 class="postheader">Categories</h1>
+ <div class="postcontent">
+ <p>Categories are a way to group related formatters. For instance, LLDB itself groups
+- the formatters for the C++ STL objects in a category named <code>gnu-libstdc++</code>.
++ the formatters for the libstdc++ types in a category named <code>gnu-libstdc++</code>.
+ Basically, categories act like containers in which to store formatters for a same library
+ or OS release.</p>
+ <p>By default, several categories are created in LLDB:
+Index: www/build.html
+===================================================================
+--- www/build.html (revision 183906)
++++ www/build.html (working copy)
+@@ -81,6 +81,17 @@
+ <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>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
+@@ -131,14 +142,14 @@
+ ninja on your system. To build using ninja:
+ </p>
+ <code>
+- <br>> cmake -C .. -G Ninja
++ > cmake -C .. -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>
+- <br>> cmake -C ..
++ > cmake -C ..
+ <br>> make
+ <br>> make check-lldb
+ </code>
+@@ -146,12 +157,21 @@
+ <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>
+- <br>> $llvm/configure --enable-cxx11
++ > $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>
+- <br>> $llvm/configure
++ > $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>
+@@ -162,6 +182,37 @@
+ <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
+Index: scripts/lldb_python_module.cmake
+===================================================================
+--- scripts/lldb_python_module.cmake (revision 0)
++++ scripts/lldb_python_module.cmake (revision 0)
+@@ -0,0 +1,14 @@
++# This CMake script installs the LLDB python module from the build directory
++# to the install directory.
++
++# FIXME: if a non-standard version of python is requested, the cmake macro
++# below will need Python_ADDITIONAL_VERSIONS set in order to find it.
++include(FindPythonInterp)
++
++SET(PYTHON_DIRECTORY python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR})
++
++SET(lldb_module_src ${CMAKE_CURRENT_BINARY_DIR}/lib/${PYTHON_DIRECTORY})
++SET(lldb_module_dest ${CMAKE_INSTALL_PREFIX}/lib)
++
++MESSAGE(STATUS "Installing LLDB python module from: ${lldb_module_src} to ${lldb_module_dest}")
++FILE(COPY "${lldb_module_src}" DESTINATION "${lldb_module_dest}")
+Index: scripts/CMakeLists.txt
+===================================================================
+--- scripts/CMakeLists.txt (revision 183906)
++++ scripts/CMakeLists.txt (working copy)
+@@ -13,3 +13,8 @@
+ ADD_CUSTOM_TARGET(swig_wrapper ALL echo -n
+ DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/LLDBWrapPython.cpp
+ )
++
++# Install the LLDB python module on all operating systems (except Windows)
++if (NOT CMAKE_SYSTEM_NAME MATCHES "Windows")
++ install(SCRIPT lldb_python_module.cmake -DCMAKE_INSTALL_PREFIX=\"${CMAKE_INSTALL_PREFIX}\" -DCMAKE_BUILD_DIR=\"${CMAKE_BUILD_DIR}\")
++endif()
+Index: scripts/Python/python-wrapper.swig
+===================================================================
+--- scripts/Python/python-wrapper.swig (revision 183906)
++++ scripts/Python/python-wrapper.swig (working copy)
+@@ -318,8 +318,18 @@
+ pvalue = PyObject_CallObject (pfunc, pargs);
+ Py_DECREF (pargs);
+
+- if (pvalue != NULL && pvalue != Py_None && PyString_Check(pvalue))
+- retval.assign(PyString_AsString(pvalue));
++ if (pvalue != NULL && pvalue != Py_None)
++ {
++ if (PyString_Check(pvalue))
++ retval.assign(PyString_AsString(pvalue));
++ else
++ {
++ PyObject* value_as_string = PyObject_Str(pvalue);
++ if (value_as_string && value_as_string != Py_None && PyString_Check(value_as_string))
++ retval.assign(PyString_AsString(value_as_string));
++ Py_XDECREF(value_as_string);
++ }
++ }
+ Py_XDECREF (pvalue);
+ Py_INCREF (session_dict);
+ }
+Index: scripts/Python/finish-swig-Python-LLDB.sh
+===================================================================
+--- scripts/Python/finish-swig-Python-LLDB.sh (revision 183906)
++++ scripts/Python/finish-swig-Python-LLDB.sh (working copy)
+@@ -248,7 +248,8 @@
+ create_python_package "/macosx" "${package_files}"
+
+ # lldb/diagnose
+- package_files="${SRC_ROOT}/examples/python/diagnose_unwind.py"
++ package_files="${SRC_ROOT}/examples/python/diagnose_unwind.py
++ ${SRC_ROOT}/examples/python/diagnose_nsstring.py"
+ create_python_package "/diagnose" "${package_files}"
+
+ # Copy files needed by lldb/macosx/heap.py to build libheap.dylib
+Index: docs/CMakeLists.txt
+===================================================================
+--- docs/CMakeLists.txt (revision 0)
++++ docs/CMakeLists.txt (revision 0)
+@@ -0,0 +1,41 @@
++
++include(FindDoxygen)
++
++if(DOXYGEN_FOUND)
++ set(abs_top_srcdir ${CMAKE_CURRENT_SOURCE_DIR}/..)
++ set(DOT dot)
++ set(PACKAGE_VERSION mainline)
++ set(abs_top_builddir ..)
++ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/doxygen.cfg.in
++ ${CMAKE_CURRENT_BINARY_DIR}/doxygen.cfg @ONLY)
++
++ add_custom_target(lldb-cpp-doc
++ ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/doxygen.cfg
++ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
++ COMMENT "Generating LLDB C++ API reference with Doxygen" VERBATIM
++ )
++endif(DOXYGEN_FOUND)
++
++find_package(PythonInterp REQUIRED)
++find_program(EPYDOC_EXECUTABLE NAMES epydoc epydoc.py)
++if(EPYDOC_EXECUTABLE)
++ find_program(DOT_EXECUTABLE dot)
++ if(DOT_EXECUTABLE)
++ set(EPYDOC_OPTIONS ${EPYDOC_OPTIONS} --graph all --dotpath ${DOT_EXECUTABLE})
++ endif()
++ set(DOC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/doc")
++ file(MAKE_DIRECTORY "${DOC_DIR}")
++ #set(ENV{PYTHONPATH} ${CMAKE_CURRENT_BINARY_DIR}/../../../lib/python2.7/site-packages)
++ add_custom_target(lldb-python-doc
++ ${EPYDOC_EXECUTABLE}
++ --html
++ lldb
++ -o ${CMAKE_CURRENT_BINARY_DIR}/python_reference
++ --name "LLDB python API"
++ --url "http://lldb.llvm.org"
++ ${EPYDOC_OPTIONS}
++ DEPENDS swig_wrapper liblldb
++ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../../../lib/python2.7/site-packages
++ COMMENT "Generating LLDB Python API reference with epidoc" VERBATIM
++ )
++endif(EPYDOC_EXECUTABLE)
+Index: docs/doxygen.cfg.in
+===================================================================
+--- docs/doxygen.cfg.in (revision 0)
++++ docs/doxygen.cfg.in (revision 0)
+@@ -0,0 +1,1633 @@
++# Doxyfile 1.7.1
++
++# This file describes the settings to be used by the documentation system
++# doxygen (www.doxygen.org) for a project
++#
++# All text after a hash (#) is considered a comment and will be ignored
++# The format is:
++# TAG = value [value, ...]
++# For lists items can also be appended using:
++# TAG += value [value, ...]
++# Values that contain spaces should be placed between quotes (" ")
++
++#---------------------------------------------------------------------------
++# Project related configuration options
++#---------------------------------------------------------------------------
++
++# This tag specifies the encoding used for all characters in the config file
++# that follow. The default is UTF-8 which is also the encoding used for all
++# text before the first occurrence of this tag. Doxygen uses libiconv (or the
++# iconv built into libc) for the transcoding. See
++# http://www.gnu.org/software/libiconv for the list of possible encodings.
++
++DOXYFILE_ENCODING = UTF-8
++
++# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
++# by quotes) that should identify the project.
++
++PROJECT_NAME = LLVM
++
++# The PROJECT_NUMBER tag can be used to enter a project or revision number.
++# This could be handy for archiving the generated documentation or
++# if some version control system is used.
++
++PROJECT_NUMBER = @PACKAGE_VERSION@
++
++# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
++# base path where the generated documentation will be put.
++# If a relative path is entered, it will be relative to the location
++# where doxygen was started. If left blank the current directory will be used.
++
++OUTPUT_DIRECTORY = @abs_top_builddir@/docs/cpp_reference
++
++# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
++# 4096 sub-directories (in 2 levels) under the output directory of each output
++# format and will distribute the generated files over these directories.
++# Enabling this option can be useful when feeding doxygen a huge amount of
++# source files, where putting all generated files in the same directory would
++# otherwise cause performance problems for the file system.
++
++CREATE_SUBDIRS = NO
++
++# The OUTPUT_LANGUAGE tag is used to specify the language in which all
++# documentation generated by doxygen is written. Doxygen will use this
++# information to generate all constant output in the proper language.
++# The default language is English, other supported languages are:
++# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
++# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German,
++# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English
++# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian,
++# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak,
++# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
++
++OUTPUT_LANGUAGE = English
++
++# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
++# include brief member descriptions after the members that are listed in
++# the file and class documentation (similar to JavaDoc).
++# Set to NO to disable this.
++
++BRIEF_MEMBER_DESC = YES
++
++# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
++# the brief description of a member or function before the detailed description.
++# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
++# brief descriptions will be completely suppressed.
++
++REPEAT_BRIEF = YES
++
++# This tag implements a quasi-intelligent brief description abbreviator
++# that is used to form the text in various listings. Each string
++# in this list, if found as the leading text of the brief description, will be
++# stripped from the text and the result after processing the whole list, is
++# used as the annotated text. Otherwise, the brief description is used as-is.
++# If left blank, the following values are used ("$name" is automatically
++# replaced with the name of the entity): "The $name class" "The $name widget"
++# "The $name file" "is" "provides" "specifies" "contains"
++# "represents" "a" "an" "the"
++
++ABBREVIATE_BRIEF =
++
++# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
++# Doxygen will generate a detailed section even if there is only a brief
++# description.
++
++ALWAYS_DETAILED_SEC = NO
++
++# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
++# inherited members of a class in the documentation of that class as if those
++# members were ordinary class members. Constructors, destructors and assignment
++# operators of the base classes will not be shown.
++
++INLINE_INHERITED_MEMB = NO
++
++# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
++# path before files name in the file list and in the header files. If set
++# to NO the shortest path that makes the file name unique will be used.
++
++FULL_PATH_NAMES = NO
++
++# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
++# can be used to strip a user-defined part of the path. Stripping is
++# only done if one of the specified strings matches the left-hand part of
++# the path. The tag can be used to show relative paths in the file list.
++# If left blank the directory from which doxygen is run is used as the
++# path to strip.
++
++STRIP_FROM_PATH = ../..
++
++# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
++# the path mentioned in the documentation of a class, which tells
++# the reader which header file to include in order to use a class.
++# If left blank only the name of the header file containing the class
++# definition is used. Otherwise one should specify the include paths that
++# are normally passed to the compiler using the -I flag.
++
++STRIP_FROM_INC_PATH =
++
++# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
++# (but less readable) file names. This can be useful is your file systems
++# doesn't support long names like on DOS, Mac, or CD-ROM.
++
++SHORT_NAMES = NO
++
++# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
++# will interpret the first line (until the first dot) of a JavaDoc-style
++# comment as the brief description. If set to NO, the JavaDoc
++# comments will behave just like regular Qt-style comments
++# (thus requiring an explicit @brief command for a brief description.)
++
++JAVADOC_AUTOBRIEF = NO
++
++# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
++# interpret the first line (until the first dot) of a Qt-style
++# comment as the brief description. If set to NO, the comments
++# will behave just like regular Qt-style comments (thus requiring
++# an explicit \brief command for a brief description.)
++
++QT_AUTOBRIEF = NO
++
++# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
++# treat a multi-line C++ special comment block (i.e. a block of //! or ///
++# comments) as a brief description. This used to be the default behaviour.
++# The new default is to treat a multi-line C++ comment block as a detailed
++# description. Set this tag to YES if you prefer the old behaviour instead.
++
++MULTILINE_CPP_IS_BRIEF = NO
++
++# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
++# member inherits the documentation from any documented member that it
++# re-implements.
++
++INHERIT_DOCS = YES
++
++# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
++# a new page for each member. If set to NO, the documentation of a member will
++# be part of the file/class/namespace that contains it.
++
++SEPARATE_MEMBER_PAGES = NO
++
++# The TAB_SIZE tag can be used to set the number of spaces in a tab.
++# Doxygen uses this value to replace tabs by spaces in code fragments.
++
++TAB_SIZE = 2
++
++# This tag can be used to specify a number of aliases that acts
++# as commands in the documentation. An alias has the form "name=value".
++# For example adding "sideeffect=\par Side Effects:\n" will allow you to
++# put the command \sideeffect (or @sideeffect) in the documentation, which
++# will result in a user-defined paragraph with heading "Side Effects:".
++# You can put \n's in the value part of an alias to insert newlines.
++
++ALIASES =
++
++# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
++# sources only. Doxygen will then generate output that is more tailored for C.
++# For instance, some of the names that are used will be different. The list
++# of all members will be omitted, etc.
++
++OPTIMIZE_OUTPUT_FOR_C = NO
++
++# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
++# sources only. Doxygen will then generate output that is more tailored for
++# Java. For instance, namespaces will be presented as packages, qualified
++# scopes will look different, etc.
++
++OPTIMIZE_OUTPUT_JAVA = NO
++
++# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
++# sources only. Doxygen will then generate output that is more tailored for
++# Fortran.
++
++OPTIMIZE_FOR_FORTRAN = NO
++
++# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
++# sources. Doxygen will then generate output that is tailored for
++# VHDL.
++
++OPTIMIZE_OUTPUT_VHDL = NO
++
++# Doxygen selects the parser to use depending on the extension of the files it
++# parses. With this tag you can assign which parser to use for a given extension.
++# Doxygen has a built-in mapping, but you can override or extend it using this
++# tag. The format is ext=language, where ext is a file extension, and language
++# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C,
++# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make
++# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C
++# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions
++# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen.
++
++EXTENSION_MAPPING =
++
++# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
++# to include (a tag file for) the STL sources as input, then you should
++# set this tag to YES in order to let doxygen match functions declarations and
++# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
++# func(std::string) {}). This also make the inheritance and collaboration
++# diagrams that involve STL classes more complete and accurate.
++
++BUILTIN_STL_SUPPORT = NO
++
++# If you use Microsoft's C++/CLI language, you should set this option to YES to
++# enable parsing support.
++
++CPP_CLI_SUPPORT = NO
++
++# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
++# Doxygen will parse them like normal C++ but will assume all classes use public
++# instead of private inheritance when no explicit protection keyword is present.
++
++SIP_SUPPORT = NO
++
++# For Microsoft's IDL there are propget and propput attributes to indicate getter
++# and setter methods for a property. Setting this option to YES (the default)
++# will make doxygen to replace the get and set methods by a property in the
++# documentation. This will only work if the methods are indeed getting or
++# setting a simple type. If this is not the case, or you want to show the
++# methods anyway, you should set this option to NO.
++
++IDL_PROPERTY_SUPPORT = YES
++
++# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
++# tag is set to YES, then doxygen will reuse the documentation of the first
++# member in the group (if any) for the other members of the group. By default
++# all members of a group must be documented explicitly.
++
++DISTRIBUTE_GROUP_DOC = NO
++
++# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
++# the same type (for instance a group of public functions) to be put as a
++# subgroup of that type (e.g. under the Public Functions section). Set it to
++# NO to prevent subgrouping. Alternatively, this can be done per class using
++# the \nosubgrouping command.
++
++SUBGROUPING = YES
++
++# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
++# is documented as struct, union, or enum with the name of the typedef. So
++# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
++# with name TypeT. When disabled the typedef will appear as a member of a file,
++# namespace, or class. And the struct will be named TypeS. This can typically
++# be useful for C code in case the coding convention dictates that all compound
++# types are typedef'ed and only the typedef is referenced, never the tag name.
++
++TYPEDEF_HIDES_STRUCT = NO
++
++# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to
++# determine which symbols to keep in memory and which to flush to disk.
++# When the cache is full, less often used symbols will be written to disk.
++# For small to medium size projects (<1000 input files) the default value is
++# probably good enough. For larger projects a too small cache size can cause
++# doxygen to be busy swapping symbols to and from disk most of the time
++# causing a significant performance penality.
++# If the system has enough physical memory increasing the cache will improve the
++# performance by keeping more symbols in memory. Note that the value works on
++# a logarithmic scale so increasing the size by one will rougly double the
++# memory usage. The cache size is given by this formula:
++# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0,
++# corresponding to a cache size of 2^16 = 65536 symbols
++
++SYMBOL_CACHE_SIZE = 0
++
++#---------------------------------------------------------------------------
++# Build related configuration options
++#---------------------------------------------------------------------------
++
++# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
++# documentation are documented, even if no documentation was available.
++# Private class members and static file members will be hidden unless
++# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
++
++EXTRACT_ALL = YES
++
++# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
++# will be included in the documentation.
++
++EXTRACT_PRIVATE = NO
++
++# If the EXTRACT_STATIC tag is set to YES all static members of a file
++# will be included in the documentation.
++
++EXTRACT_STATIC = YES
++
++# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
++# defined locally in source files will be included in the documentation.
++# If set to NO only classes defined in header files are included.
++
++EXTRACT_LOCAL_CLASSES = YES
++
++# This flag is only useful for Objective-C code. When set to YES local
++# methods, which are defined in the implementation section but not in
++# the interface are included in the documentation.
++# If set to NO (the default) only methods in the interface are included.
++
++EXTRACT_LOCAL_METHODS = NO
++
++# If this flag is set to YES, the members of anonymous namespaces will be
++# extracted and appear in the documentation as a namespace called
++# 'anonymous_namespace{file}', where file will be replaced with the base
++# name of the file that contains the anonymous namespace. By default
++# anonymous namespace are hidden.
++
++EXTRACT_ANON_NSPACES = NO
++
++# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
++# undocumented members of documented classes, files or namespaces.
++# If set to NO (the default) these members will be included in the
++# various overviews, but no documentation section is generated.
++# This option has no effect if EXTRACT_ALL is enabled.
++
++HIDE_UNDOC_MEMBERS = NO
++
++# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
++# undocumented classes that are normally visible in the class hierarchy.
++# If set to NO (the default) these classes will be included in the various
++# overviews. This option has no effect if EXTRACT_ALL is enabled.
++
++HIDE_UNDOC_CLASSES = NO
++
++# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
++# friend (class|struct|union) declarations.
++# If set to NO (the default) these declarations will be included in the
++# documentation.
++
++HIDE_FRIEND_COMPOUNDS = NO
++
++# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
++# documentation blocks found inside the body of a function.
++# If set to NO (the default) these blocks will be appended to the
++# function's detailed documentation block.
++
++HIDE_IN_BODY_DOCS = NO
++
++# The INTERNAL_DOCS tag determines if documentation
++# that is typed after a \internal command is included. If the tag is set
++# to NO (the default) then the documentation will be excluded.
++# Set it to YES to include the internal documentation.
++
++INTERNAL_DOCS = NO
++
++# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
++# file names in lower-case letters. If set to YES upper-case letters are also
++# allowed. This is useful if you have classes or files whose names only differ
++# in case and if your file system supports case sensitive file names. Windows
++# and Mac users are advised to set this option to NO.
++
++CASE_SENSE_NAMES = YES
++
++# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
++# will show members with their full class and namespace scopes in the
++# documentation. If set to YES the scope will be hidden.
++
++HIDE_SCOPE_NAMES = NO
++
++# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
++# will put a list of the files that are included by a file in the documentation
++# of that file.
++
++SHOW_INCLUDE_FILES = YES
++
++# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen
++# will list include files with double quotes in the documentation
++# rather than with sharp brackets.
++
++FORCE_LOCAL_INCLUDES = NO
++
++# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
++# is inserted in the documentation for inline members.
++
++INLINE_INFO = YES
++
++# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
++# will sort the (detailed) documentation of file and class members
++# alphabetically by member name. If set to NO the members will appear in
++# declaration order.
++
++SORT_MEMBER_DOCS = YES
++
++# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
++# brief documentation of file, namespace and class members alphabetically
++# by member name. If set to NO (the default) the members will appear in
++# declaration order.
++
++SORT_BRIEF_DOCS = NO
++
++# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen
++# will sort the (brief and detailed) documentation of class members so that
++# constructors and destructors are listed first. If set to NO (the default)
++# the constructors will appear in the respective orders defined by
++# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS.
++# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO
++# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO.
++
++SORT_MEMBERS_CTORS_1ST = NO
++
++# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
++# hierarchy of group names into alphabetical order. If set to NO (the default)
++# the group names will appear in their defined order.
++
++SORT_GROUP_NAMES = NO
++
++# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
++# sorted by fully-qualified names, including namespaces. If set to
++# NO (the default), the class list will be sorted only by class name,
++# not including the namespace part.
++# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
++# Note: This option applies only to the class list, not to the
++# alphabetical list.
++
++SORT_BY_SCOPE_NAME = NO
++
++# The GENERATE_TODOLIST tag can be used to enable (YES) or
++# disable (NO) the todo list. This list is created by putting \todo
++# commands in the documentation.
++
++GENERATE_TODOLIST = YES
++
++# The GENERATE_TESTLIST tag can be used to enable (YES) or
++# disable (NO) the test list. This list is created by putting \test
++# commands in the documentation.
++
++GENERATE_TESTLIST = YES
++
++# The GENERATE_BUGLIST tag can be used to enable (YES) or
++# disable (NO) the bug list. This list is created by putting \bug
++# commands in the documentation.
++
++GENERATE_BUGLIST = YES
++
++# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
++# disable (NO) the deprecated list. This list is created by putting
++# \deprecated commands in the documentation.
++
++GENERATE_DEPRECATEDLIST= YES
++
++# The ENABLED_SECTIONS tag can be used to enable conditional
++# documentation sections, marked by \if sectionname ... \endif.
++
++ENABLED_SECTIONS =
++
++# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
++# the initial value of a variable or define consists of for it to appear in
++# the documentation. If the initializer consists of more lines than specified
++# here it will be hidden. Use a value of 0 to hide initializers completely.
++# The appearance of the initializer of individual variables and defines in the
++# documentation can be controlled using \showinitializer or \hideinitializer
++# command in the documentation regardless of this setting.
++
++MAX_INITIALIZER_LINES = 30
++
++# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
++# at the bottom of the documentation of classes and structs. If set to YES the
++# list will mention the files that were used to generate the documentation.
++
++SHOW_USED_FILES = YES
++
++# If the sources in your project are distributed over multiple directories
++# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
++# in the documentation. The default is NO.
++
++SHOW_DIRECTORIES = YES
++
++# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
++# This will remove the Files entry from the Quick Index and from the
++# Folder Tree View (if specified). The default is YES.
++
++SHOW_FILES = YES
++
++# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
++# Namespaces page.
++# This will remove the Namespaces entry from the Quick Index
++# and from the Folder Tree View (if specified). The default is YES.
++
++SHOW_NAMESPACES = YES
++
++# The FILE_VERSION_FILTER tag can be used to specify a program or script that
++# doxygen should invoke to get the current version for each file (typically from
++# the version control system). Doxygen will invoke the program by executing (via
++# popen()) the command <command> <input-file>, where <command> is the value of
++# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
++# provided by doxygen. Whatever the program writes to standard output
++# is used as the file version. See the manual for examples.
++
++FILE_VERSION_FILTER =
++
++# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
++# by doxygen. The layout file controls the global structure of the generated
++# output files in an output format independent way. The create the layout file
++# that represents doxygen's defaults, run doxygen with the -l option.
++# You can optionally specify a file name after the option, if omitted
++# DoxygenLayout.xml will be used as the name of the layout file.
++
++LAYOUT_FILE =
++
++#---------------------------------------------------------------------------
++# configuration options related to warning and progress messages
++#---------------------------------------------------------------------------
++
++# The QUIET tag can be used to turn on/off the messages that are generated
++# by doxygen. Possible values are YES and NO. If left blank NO is used.
++
++QUIET = NO
++
++# The WARNINGS tag can be used to turn on/off the warning messages that are
++# generated by doxygen. Possible values are YES and NO. If left blank
++# NO is used.
++
++WARNINGS = NO
++
++# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
++# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
++# automatically be disabled.
++
++WARN_IF_UNDOCUMENTED = NO
++
++# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
++# potential errors in the documentation, such as not documenting some
++# parameters in a documented function, or documenting parameters that
++# don't exist or using markup commands wrongly.
++
++WARN_IF_DOC_ERROR = YES
++
++# This WARN_NO_PARAMDOC option can be abled to get warnings for
++# functions that are documented, but have no documentation for their parameters
++# or return value. If set to NO (the default) doxygen will only warn about
++# wrong or incomplete parameter documentation, but not about the absence of
++# documentation.
++
++WARN_NO_PARAMDOC = NO
++
++# The WARN_FORMAT tag determines the format of the warning messages that
++# doxygen can produce. The string should contain the $file, $line, and $text
++# tags, which will be replaced by the file and line number from which the
++# warning originated and the warning text. Optionally the format may contain
++# $version, which will be replaced by the version of the file (if it could
++# be obtained via FILE_VERSION_FILTER)
++
++WARN_FORMAT =
++
++# The WARN_LOGFILE tag can be used to specify a file to which warning
++# and error messages should be written. If left blank the output is written
++# to stderr.
++
++WARN_LOGFILE =
++
++#---------------------------------------------------------------------------
++# configuration options related to the input files
++#---------------------------------------------------------------------------
++
++# The INPUT tag can be used to specify the files and/or directories that contain
++# documented source files. You may enter file names like "myfile.cpp" or
++# directories like "/usr/src/myproject". Separate the files or directories
++# with spaces.
++
++INPUT = @abs_top_srcdir@/include \
++ @abs_top_srcdir@/scripts/Python/interface \
++ @abs_top_srcdir@/source \
++ @abs_top_srcdir@/docs/doxygen.intro
++
++# This tag can be used to specify the character encoding of the source files
++# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
++# also the default input encoding. Doxygen uses libiconv (or the iconv built
++# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
++# the list of possible encodings.
++
++INPUT_ENCODING = UTF-8
++
++# If the value of the INPUT tag contains directories, you can use the
++# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
++# and *.h) to filter out the source-files in the directories. If left
++# blank the following patterns are tested:
++# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
++# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90
++
++FILE_PATTERNS =
++
++# The RECURSIVE tag can be used to turn specify whether or not subdirectories
++# should be searched for input files as well. Possible values are YES and NO.
++# If left blank NO is used.
++
++RECURSIVE = YES
++
++# The EXCLUDE tag can be used to specify files and/or directories that should
++# excluded from the INPUT source files. This way you can easily exclude a
++# subdirectory from a directory tree whose root is specified with the INPUT tag.
++
++EXCLUDE =
++
++# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
++# directories that are symbolic links (a Unix filesystem feature) are excluded
++# from the input.
++
++EXCLUDE_SYMLINKS = NO
++
++# If the value of the INPUT tag contains directories, you can use the
++# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
++# certain files from those directories. Note that the wildcards are matched
++# against the file with absolute path, so to exclude all test directories
++# for example use the pattern */test/*
++
++EXCLUDE_PATTERNS =
++
++# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
++# (namespaces, classes, functions, etc.) that should be excluded from the
++# output. The symbol name can be a fully qualified name, a word, or if the
++# wildcard * is used, a substring. Examples: ANamespace, AClass,
++# AClass::ANamespace, ANamespace::*Test
++
++EXCLUDE_SYMBOLS =
++
++# The EXAMPLE_PATH tag can be used to specify one or more files or
++# directories that contain example code fragments that are included (see
++# the \include command).
++
++EXAMPLE_PATH = @abs_top_srcdir@/examples
++
++# If the value of the EXAMPLE_PATH tag contains directories, you can use the
++# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
++# and *.h) to filter out the source-files in the directories. If left
++# blank all files are included.
++
++EXAMPLE_PATTERNS =
++
++# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
++# searched for input files to be used with the \include or \dontinclude
++# commands irrespective of the value of the RECURSIVE tag.
++# Possible values are YES and NO. If left blank NO is used.
++
++EXAMPLE_RECURSIVE = YES
++
++# The IMAGE_PATH tag can be used to specify one or more files or
++# directories that contain image that are included in the documentation (see
++# the \image command).
++
++IMAGE_PATH = @abs_top_srcdir@/docs/img
++
++# The INPUT_FILTER tag can be used to specify a program that doxygen should
++# invoke to filter for each input file. Doxygen will invoke the filter program
++# by executing (via popen()) the command <filter> <input-file>, where <filter>
++# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
++# input file. Doxygen will then use the output that the filter program writes
++# to standard output.
++# If FILTER_PATTERNS is specified, this tag will be
++# ignored.
++
++INPUT_FILTER =
++
++# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
++# basis.
++# Doxygen will compare the file name with each pattern and apply the
++# filter if there is a match.
++# The filters are a list of the form:
++# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
++# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
++# is applied to all files.
++
++FILTER_PATTERNS =
++
++# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
++# INPUT_FILTER) will be used to filter the input files when producing source
++# files to browse (i.e. when SOURCE_BROWSER is set to YES).
++
++FILTER_SOURCE_FILES = NO
++
++#---------------------------------------------------------------------------
++# configuration options related to source browsing
++#---------------------------------------------------------------------------
++
++# If the SOURCE_BROWSER tag is set to YES then a list of source files will
++# be generated. Documented entities will be cross-referenced with these sources.
++# Note: To get rid of all source code in the generated output, make sure also
++# VERBATIM_HEADERS is set to NO.
++
++SOURCE_BROWSER = YES
++
++# Setting the INLINE_SOURCES tag to YES will include the body
++# of functions and classes directly in the documentation.
++
++INLINE_SOURCES = NO
++
++# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
++# doxygen to hide any special comment blocks from generated source code
++# fragments. Normal C and C++ comments will always remain visible.
++
++STRIP_CODE_COMMENTS = NO
++
++# If the REFERENCED_BY_RELATION tag is set to YES
++# then for each documented function all documented
++# functions referencing it will be listed.
++
++REFERENCED_BY_RELATION = YES
++
++# If the REFERENCES_RELATION tag is set to YES
++# then for each documented function all documented entities
++# called/used by that function will be listed.
++
++REFERENCES_RELATION = YES
++
++# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
++# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
++# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
++# link to the source code.
++# Otherwise they will link to the documentation.
++
++REFERENCES_LINK_SOURCE = YES
++
++# If the USE_HTAGS tag is set to YES then the references to source code
++# will point to the HTML generated by the htags(1) tool instead of doxygen
++# built-in source browser. The htags tool is part of GNU's global source
++# tagging system (see http://www.gnu.org/software/global/global.html). You
++# will need version 4.8.6 or higher.
++
++USE_HTAGS = NO
++
++# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
++# will generate a verbatim copy of the header file for each class for
++# which an include is specified. Set to NO to disable this.
++
++VERBATIM_HEADERS = YES
++
++#---------------------------------------------------------------------------
++# configuration options related to the alphabetical class index
++#---------------------------------------------------------------------------
++
++# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
++# of all compounds will be generated. Enable this if the project
++# contains a lot of classes, structs, unions or interfaces.
++
++ALPHABETICAL_INDEX = YES
++
++# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
++# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
++# in which this list will be split (can be a number in the range [1..20])
++
++COLS_IN_ALPHA_INDEX = 4
++
++# In case all classes in a project start with a common prefix, all
++# classes will be put under the same header in the alphabetical index.
++# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
++# should be ignored while generating the index headers.
++
++IGNORE_PREFIX = llvm::
++
++#---------------------------------------------------------------------------
++# configuration options related to the HTML output
++#---------------------------------------------------------------------------
++
++# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
++# generate HTML output.
++
++GENERATE_HTML = YES
++
++# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
++# If a relative path is entered the value of OUTPUT_DIRECTORY will be
++# put in front of it. If left blank `html' will be used as the default path.
++
++HTML_OUTPUT = html
++
++# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
++# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
++# doxygen will generate files with .html extension.
++
++HTML_FILE_EXTENSION = .html
++
++# The HTML_HEADER tag can be used to specify a personal HTML header for
++# each generated HTML page. If it is left blank doxygen will generate a
++# standard header.
++
++HTML_HEADER = @abs_top_srcdir@/docs/doxygen.header
++
++# The HTML_FOOTER tag can be used to specify a personal HTML footer for
++# each generated HTML page. If it is left blank doxygen will generate a
++# standard footer.
++
++HTML_FOOTER = @abs_top_srcdir@/docs/doxygen.footer
++
++# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
++# style sheet that is used by each HTML page. It can be used to
++# fine-tune the look of the HTML output. If the tag is left blank doxygen
++# will generate a default style sheet. Note that doxygen will try to copy
++# the style sheet file to the HTML output directory, so don't put your own
++# stylesheet in the HTML output directory as well, or it will be erased!
++
++HTML_STYLESHEET = @abs_top_srcdir@/../../docs/doxygen.css
++
++# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output.
++# Doxygen will adjust the colors in the stylesheet and background images
++# according to this color. Hue is specified as an angle on a colorwheel,
++# see http://en.wikipedia.org/wiki/Hue for more information.
++# For instance the value 0 represents red, 60 is yellow, 120 is green,
++# 180 is cyan, 240 is blue, 300 purple, and 360 is red again.
++# The allowed range is 0 to 359.
++
++HTML_COLORSTYLE_HUE = 220
++
++# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of
++# the colors in the HTML output. For a value of 0 the output will use
++# grayscales only. A value of 255 will produce the most vivid colors.
++
++HTML_COLORSTYLE_SAT = 100
++
++# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to
++# the luminance component of the colors in the HTML output. Values below
++# 100 gradually make the output lighter, whereas values above 100 make
++# the output darker. The value divided by 100 is the actual gamma applied,
++# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2,
++# and 100 does not change the gamma.
++
++HTML_COLORSTYLE_GAMMA = 80
++
++# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
++# page will contain the date and time when the page was generated. Setting
++# this to NO can help when comparing the output of multiple runs.
++
++HTML_TIMESTAMP = YES
++
++# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
++# files or namespaces will be aligned in HTML using tables. If set to
++# NO a bullet list will be used.
++
++HTML_ALIGN_MEMBERS = YES
++
++# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
++# documentation will contain sections that can be hidden and shown after the
++# page has loaded. For this to work a browser that supports
++# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
++# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
++
++HTML_DYNAMIC_SECTIONS = NO
++
++# If the GENERATE_DOCSET tag is set to YES, additional index files
++# will be generated that can be used as input for Apple's Xcode 3
++# integrated development environment, introduced with OSX 10.5 (Leopard).
++# To create a documentation set, doxygen will generate a Makefile in the
++# HTML output directory. Running make will produce the docset in that
++# directory and running "make install" will install the docset in
++# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
++# it at startup.
++# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
++# for more information.
++
++GENERATE_DOCSET = NO
++
++# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
++# feed. A documentation feed provides an umbrella under which multiple
++# documentation sets from a single provider (such as a company or product suite)
++# can be grouped.
++
++DOCSET_FEEDNAME = "Doxygen generated docs"
++
++# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
++# should uniquely identify the documentation set bundle. This should be a
++# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
++# will append .docset to the name.
++
++DOCSET_BUNDLE_ID = org.doxygen.Project
++
++# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify
++# the documentation publisher. This should be a reverse domain-name style
++# string, e.g. com.mycompany.MyDocSet.documentation.
++
++DOCSET_PUBLISHER_ID = org.doxygen.Publisher
++
++# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher.
++
++DOCSET_PUBLISHER_NAME = Publisher
++
++# If the GENERATE_HTMLHELP tag is set to YES, additional index files
++# will be generated that can be used as input for tools like the
++# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
++# of the generated HTML documentation.
++
++GENERATE_HTMLHELP = NO
++
++# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
++# be used to specify the file name of the resulting .chm file. You
++# can add a path in front of the file if the result should not be
++# written to the html output directory.
++
++CHM_FILE =
++
++# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
++# be used to specify the location (absolute path including file name) of
++# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
++# the HTML help compiler on the generated index.hhp.
++
++HHC_LOCATION =
++
++# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
++# controls if a separate .chi index file is generated (YES) or that
++# it should be included in the master .chm file (NO).
++
++GENERATE_CHI = NO
++
++# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
++# is used to encode HtmlHelp index (hhk), content (hhc) and project file
++# content.
++
++CHM_INDEX_ENCODING =
++
++# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
++# controls whether a binary table of contents is generated (YES) or a
++# normal table of contents (NO) in the .chm file.
++
++BINARY_TOC = NO
++
++# The TOC_EXPAND flag can be set to YES to add extra items for group members
++# to the contents of the HTML help documentation and to the tree view.
++
++TOC_EXPAND = NO
++
++# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
++# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated
++# that can be used as input for Qt's qhelpgenerator to generate a
++# Qt Compressed Help (.qch) of the generated HTML documentation.
++
++GENERATE_QHP = NO
++
++# If the QHG_LOCATION tag is specified, the QCH_FILE tag can
++# be used to specify the file name of the resulting .qch file.
++# The path specified is relative to the HTML output folder.
++
++QCH_FILE =
++
++# The QHP_NAMESPACE tag specifies the namespace to use when generating
++# Qt Help Project output. For more information please see
++# http://doc.trolltech.com/qthelpproject.html#namespace
++
++QHP_NAMESPACE = org.doxygen.Project
++
++# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
++# Qt Help Project output. For more information please see
++# http://doc.trolltech.com/qthelpproject.html#virtual-folders
++
++QHP_VIRTUAL_FOLDER = doc
++
++# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to
++# add. For more information please see
++# http://doc.trolltech.com/qthelpproject.html#custom-filters
++
++QHP_CUST_FILTER_NAME =
++
++# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the
++# custom filter to add. For more information please see
++# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters">
++# Qt Help Project / Custom Filters</a>.
++
++QHP_CUST_FILTER_ATTRS =
++
++# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
++# project's
++# filter section matches.
++# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes">
++# Qt Help Project / Filter Attributes</a>.
++
++QHP_SECT_FILTER_ATTRS =
++
++# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can
++# be used to specify the location of Qt's qhelpgenerator.
++# If non-empty doxygen will try to run qhelpgenerator on the generated
++# .qhp file.
++
++QHG_LOCATION =
++
++# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files
++# will be generated, which together with the HTML files, form an Eclipse help
++# plugin. To install this plugin and make it available under the help contents
++# menu in Eclipse, the contents of the directory containing the HTML and XML
++# files needs to be copied into the plugins directory of eclipse. The name of
++# the directory within the plugins directory should be the same as
++# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before
++# the help appears.
++
++GENERATE_ECLIPSEHELP = NO
++
++# A unique identifier for the eclipse help plugin. When installing the plugin
++# the directory name containing the HTML and XML files should also have
++# this name.
++
++ECLIPSE_DOC_ID = org.doxygen.Project
++
++# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
++# top of each HTML page. The value NO (the default) enables the index and
++# the value YES disables it.
++
++DISABLE_INDEX = NO
++
++# This tag can be used to set the number of enum values (range [1..20])
++# that doxygen will group on one line in the generated HTML documentation.
++
++ENUM_VALUES_PER_LINE = 4
++
++# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
++# structure should be generated to display hierarchical information.
++# If the tag value is set to YES, a side panel will be generated
++# containing a tree-like index structure (just like the one that
++# is generated for HTML Help). For this to work a browser that supports
++# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser).
++# Windows users are probably better off using the HTML help feature.
++
++GENERATE_TREEVIEW = NO
++
++# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories,
++# and Class Hierarchy pages using a tree view instead of an ordered list.
++
++USE_INLINE_TREES = NO
++
++# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
++# used to set the initial width (in pixels) of the frame in which the tree
++# is shown.
++
++TREEVIEW_WIDTH = 250
++
++# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open
++# links to external symbols imported via tag files in a separate window.
++
++EXT_LINKS_IN_WINDOW = NO
++
++# Use this tag to change the font size of Latex formulas included
++# as images in the HTML documentation. The default is 10. Note that
++# when you change the font size after a successful doxygen run you need
++# to manually remove any form_*.png images from the HTML output directory
++# to force them to be regenerated.
++
++FORMULA_FONTSIZE = 10
++
++# Use the FORMULA_TRANPARENT tag to determine whether or not the images
++# generated for formulas are transparent PNGs. Transparent PNGs are
++# not supported properly for IE 6.0, but are supported on all modern browsers.
++# Note that when changing this option you need to delete any form_*.png files
++# in the HTML output before the changes have effect.
++
++FORMULA_TRANSPARENT = YES
++
++# When the SEARCHENGINE tag is enabled doxygen will generate a search box
++# for the HTML output. The underlying search engine uses javascript
++# and DHTML and should work on any modern browser. Note that when using
++# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets
++# (GENERATE_DOCSET) there is already a search function so this one should
++# typically be disabled. For large projects the javascript based search engine
++# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution.
++
++SEARCHENGINE = NO
++
++# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
++# implemented using a PHP enabled web server instead of at the web client
++# using Javascript. Doxygen will generate the search PHP script and index
++# file to put on the web server. The advantage of the server
++# based approach is that it scales better to large projects and allows
++# full text search. The disadvances is that it is more difficult to setup
++# and does not have live searching capabilities.
++
++SERVER_BASED_SEARCH = NO
++
++#---------------------------------------------------------------------------
++# configuration options related to the LaTeX output
++#---------------------------------------------------------------------------
++
++# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
++# generate Latex output.
++
++GENERATE_LATEX = NO
++
++# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
++# If a relative path is entered the value of OUTPUT_DIRECTORY will be
++# put in front of it. If left blank `latex' will be used as the default path.
++
++LATEX_OUTPUT =
++
++# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
++# invoked. If left blank `latex' will be used as the default command name.
++# Note that when enabling USE_PDFLATEX this option is only used for
++# generating bitmaps for formulas in the HTML output, but not in the
++# Makefile that is written to the output directory.
++
++LATEX_CMD_NAME = latex
++
++# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
++# generate index for LaTeX. If left blank `makeindex' will be used as the
++# default command name.
++
++MAKEINDEX_CMD_NAME = makeindex
++
++# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
++# LaTeX documents. This may be useful for small projects and may help to
++# save some trees in general.
++
++COMPACT_LATEX = NO
++
++# The PAPER_TYPE tag can be used to set the paper type that is used
++# by the printer. Possible values are: a4, a4wide, letter, legal and
++# executive. If left blank a4wide will be used.
++
++PAPER_TYPE = letter
++
++# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
++# packages that should be included in the LaTeX output.
++
++EXTRA_PACKAGES =
++
++# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
++# the generated latex document. The header should contain everything until
++# the first chapter. If it is left blank doxygen will generate a
++# standard header. Notice: only use this tag if you know what you are doing!
++
++LATEX_HEADER =
++
++# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
++# is prepared for conversion to pdf (using ps2pdf). The pdf file will
++# contain links (just like the HTML output) instead of page references
++# This makes the output suitable for online browsing using a pdf viewer.
++
++PDF_HYPERLINKS = NO
++
++# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
++# plain latex in the generated Makefile. Set this option to YES to get a
++# higher quality PDF documentation.
++
++USE_PDFLATEX = NO
++
++# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
++# command to the generated LaTeX files. This will instruct LaTeX to keep
++# running if errors occur, instead of asking the user for help.
++# This option is also used when generating formulas in HTML.
++
++LATEX_BATCHMODE = NO
++
++# If LATEX_HIDE_INDICES is set to YES then doxygen will not
++# include the index chapters (such as File Index, Compound Index, etc.)
++# in the output.
++
++LATEX_HIDE_INDICES = NO
++
++# If LATEX_SOURCE_CODE is set to YES then doxygen will include
++# source code with syntax highlighting in the LaTeX output.
++# Note that which sources are shown also depends on other settings
++# such as SOURCE_BROWSER.
++
++LATEX_SOURCE_CODE = NO
++
++#---------------------------------------------------------------------------
++# configuration options related to the RTF output
++#---------------------------------------------------------------------------
++
++# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
++# The RTF output is optimized for Word 97 and may not look very pretty with
++# other RTF readers or editors.
++
++GENERATE_RTF = NO
++
++# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
++# If a relative path is entered the value of OUTPUT_DIRECTORY will be
++# put in front of it. If left blank `rtf' will be used as the default path.
++
++RTF_OUTPUT =
++
++# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
++# RTF documents. This may be useful for small projects and may help to
++# save some trees in general.
++
++COMPACT_RTF = NO
++
++# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
++# will contain hyperlink fields. The RTF file will
++# contain links (just like the HTML output) instead of page references.
++# This makes the output suitable for online browsing using WORD or other
++# programs which support those fields.
++# Note: wordpad (write) and others do not support links.
++
++RTF_HYPERLINKS = NO
++
++# Load stylesheet definitions from file. Syntax is similar to doxygen's
++# config file, i.e. a series of assignments. You only have to provide
++# replacements, missing definitions are set to their default value.
++
++RTF_STYLESHEET_FILE =
++
++# Set optional variables used in the generation of an rtf document.
++# Syntax is similar to doxygen's config file.
++
++RTF_EXTENSIONS_FILE =
++
++#---------------------------------------------------------------------------
++# configuration options related to the man page output
++#---------------------------------------------------------------------------
++
++# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
++# generate man pages
++
++GENERATE_MAN = NO
++
++# The MAN_OUTPUT tag is used to specify where the man pages will be put.
++# If a relative path is entered the value of OUTPUT_DIRECTORY will be
++# put in front of it. If left blank `man' will be used as the default path.
++
++MAN_OUTPUT =
++
++# The MAN_EXTENSION tag determines the extension that is added to
++# the generated man pages (default is the subroutine's section .3)
++
++MAN_EXTENSION =
++
++# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
++# then it will generate one additional man file for each entity
++# documented in the real man page(s). These additional files
++# only source the real man page, but without them the man command
++# would be unable to find the correct page. The default is NO.
++
++MAN_LINKS = NO
++
++#---------------------------------------------------------------------------
++# configuration options related to the XML output
++#---------------------------------------------------------------------------
++
++# If the GENERATE_XML tag is set to YES Doxygen will
++# generate an XML file that captures the structure of
++# the code including all documentation.
++
++GENERATE_XML = NO
++
++# The XML_OUTPUT tag is used to specify where the XML pages will be put.
++# If a relative path is entered the value of OUTPUT_DIRECTORY will be
++# put in front of it. If left blank `xml' will be used as the default path.
++
++XML_OUTPUT = xml
++
++# The XML_SCHEMA tag can be used to specify an XML schema,
++# which can be used by a validating XML parser to check the
++# syntax of the XML files.
++
++XML_SCHEMA =
++
++# The XML_DTD tag can be used to specify an XML DTD,
++# which can be used by a validating XML parser to check the
++# syntax of the XML files.
++
++XML_DTD =
++
++# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
++# dump the program listings (including syntax highlighting
++# and cross-referencing information) to the XML output. Note that
++# enabling this will significantly increase the size of the XML output.
++
++XML_PROGRAMLISTING = YES
++
++#---------------------------------------------------------------------------
++# configuration options for the AutoGen Definitions output
++#---------------------------------------------------------------------------
++
++# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
++# generate an AutoGen Definitions (see autogen.sf.net) file
++# that captures the structure of the code including all
++# documentation. Note that this feature is still experimental
++# and incomplete at the moment.
++
++GENERATE_AUTOGEN_DEF = NO
++
++#---------------------------------------------------------------------------
++# configuration options related to the Perl module output
++#---------------------------------------------------------------------------
++
++# If the GENERATE_PERLMOD tag is set to YES Doxygen will
++# generate a Perl module file that captures the structure of
++# the code including all documentation. Note that this
++# feature is still experimental and incomplete at the
++# moment.
++
++GENERATE_PERLMOD = NO
++
++# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
++# the necessary Makefile rules, Perl scripts and LaTeX code to be able
++# to generate PDF and DVI output from the Perl module output.
++
++PERLMOD_LATEX = NO
++
++# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
++# nicely formatted so it can be parsed by a human reader.
++# This is useful
++# if you want to understand what is going on.
++# On the other hand, if this
++# tag is set to NO the size of the Perl module output will be much smaller
++# and Perl will parse it just the same.
++
++PERLMOD_PRETTY = YES
++
++# The names of the make variables in the generated doxyrules.make file
++# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
++# This is useful so different doxyrules.make files included by the same
++# Makefile don't overwrite each other's variables.
++
++PERLMOD_MAKEVAR_PREFIX =
++
++#---------------------------------------------------------------------------
++# Configuration options related to the preprocessor
++#---------------------------------------------------------------------------
++
++# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
++# evaluate all C-preprocessor directives found in the sources and include
++# files.
++
++ENABLE_PREPROCESSING = YES
++
++# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
++# names in the source code. If set to NO (the default) only conditional
++# compilation will be performed. Macro expansion can be done in a controlled
++# way by setting EXPAND_ONLY_PREDEF to YES.
++
++MACRO_EXPANSION = NO
++
++# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
++# then the macro expansion is limited to the macros specified with the
++# PREDEFINED and EXPAND_AS_DEFINED tags.
++
++EXPAND_ONLY_PREDEF = NO
++
++# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
++# in the INCLUDE_PATH (see below) will be search if a #include is found.
++
++SEARCH_INCLUDES = YES
++
++# The INCLUDE_PATH tag can be used to specify one or more directories that
++# contain include files that are not input files but should be processed by
++# the preprocessor.
++
++INCLUDE_PATH = ../scripts/Python/interface
++
++# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
++# patterns (like *.h and *.hpp) to filter out the header-files in the
++# directories. If left blank, the patterns specified with FILE_PATTERNS will
++# be used.
++
++INCLUDE_FILE_PATTERNS =
++
++# The PREDEFINED tag can be used to specify one or more macro names that
++# are defined before the preprocessor is started (similar to the -D option of
++# gcc). The argument of the tag is a list of macros of the form: name
++# or name=definition (no spaces). If the definition and the = are
++# omitted =1 is assumed. To prevent a macro definition from being
++# undefined via #undef or recursively expanded use the := operator
++# instead of the = operator.
++
++PREDEFINED =
++
++# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
++# this tag can be used to specify a list of macro names that should be expanded.
++# The macro definition that is found in the sources will be used.
++# Use the PREDEFINED tag if you want to use a different macro definition.
++
++EXPAND_AS_DEFINED =
++
++# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
++# doxygen's preprocessor will remove all function-like macros that are alone
++# on a line, have an all uppercase name, and do not end with a semicolon. Such
++# function macros are typically used for boiler-plate code, and will confuse
++# the parser if not removed.
++
++SKIP_FUNCTION_MACROS = YES
++
++#---------------------------------------------------------------------------
++# Configuration::additions related to external references
++#---------------------------------------------------------------------------
++
++# The TAGFILES option can be used to specify one or more tagfiles.
++# Optionally an initial location of the external documentation
++# can be added for each tagfile. The format of a tag file without
++# this location is as follows:
++#
++# TAGFILES = file1 file2 ...
++# Adding location for the tag files is done as follows:
++#
++# TAGFILES = file1=loc1 "file2 = loc2" ...
++# where "loc1" and "loc2" can be relative or absolute paths or
++# URLs. If a location is present for each tag, the installdox tool
++# does not have to be run to correct the links.
++# Note that each tag file must have a unique name
++# (where the name does NOT include the path)
++# If a tag file is not located in the directory in which doxygen
++# is run, you must also specify the path to the tagfile here.
++
++TAGFILES =
++
++# When a file name is specified after GENERATE_TAGFILE, doxygen will create
++# a tag file that is based on the input files it reads.
++
++GENERATE_TAGFILE =
++
++# If the ALLEXTERNALS tag is set to YES all external classes will be listed
++# in the class index. If set to NO only the inherited external classes
++# will be listed.
++
++ALLEXTERNALS = YES
++
++# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
++# in the modules index. If set to NO, only the current project's groups will
++# be listed.
++
++EXTERNAL_GROUPS = YES
++
++# The PERL_PATH should be the absolute path and name of the perl script
++# interpreter (i.e. the result of `which perl').
++
++PERL_PATH =
++
++#---------------------------------------------------------------------------
++# Configuration options related to the dot tool
++#---------------------------------------------------------------------------
++
++# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
++# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
++# or super classes. Setting the tag to NO turns the diagrams off. Note that
++# this option is superseded by the HAVE_DOT option below. This is only a
++# fallback. It is recommended to install and use dot, since it yields more
++# powerful graphs.
++
++CLASS_DIAGRAMS = YES
++
++# You can define message sequence charts within doxygen comments using the \msc
++# command. Doxygen will then run the mscgen tool (see
++# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
++# documentation. The MSCGEN_PATH tag allows you to specify the directory where
++# the mscgen tool resides. If left empty the tool is assumed to be found in the
++# default search path.
++
++MSCGEN_PATH =
++
++# If set to YES, the inheritance and collaboration graphs will hide
++# inheritance and usage relations if the target is undocumented
++# or is not a class.
++
++HIDE_UNDOC_RELATIONS = NO
++
++# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
++# available from the path. This tool is part of Graphviz, a graph visualization
++# toolkit from AT&T and Lucent Bell Labs. The other options in this section
++# have no effect if this option is set to NO (the default)
++
++HAVE_DOT = YES
++
++# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is
++# allowed to run in parallel. When set to 0 (the default) doxygen will
++# base this on the number of processors available in the system. You can set it
++# explicitly to a value larger than 0 to get control over the balance
++# between CPU load and processing speed.
++
++DOT_NUM_THREADS = 0
++
++# By default doxygen will write a font called FreeSans.ttf to the output
++# directory and reference it in all dot files that doxygen generates. This
++# font does not include all possible unicode characters however, so when you need
++# these (or just want a differently looking font) you can specify the font name
++# using DOT_FONTNAME. You need need to make sure dot is able to find the font,
++# which can be done by putting it in a standard location or by setting the
++# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory
++# containing the font.
++
++DOT_FONTNAME = FreeSans
++
++# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
++# The default size is 10pt.
++
++DOT_FONTSIZE = 10
++
++# By default doxygen will tell dot to use the output directory to look for the
++# FreeSans.ttf font (which doxygen will put there itself). If you specify a
++# different font using DOT_FONTNAME you can set the path where dot
++# can find it using this tag.
++
++DOT_FONTPATH =
++
++# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
++# will generate a graph for each documented class showing the direct and
++# indirect inheritance relations. Setting this tag to YES will force the
++# the CLASS_DIAGRAMS tag to NO.
++
++CLASS_GRAPH = YES
++
++# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
++# will generate a graph for each documented class showing the direct and
++# indirect implementation dependencies (inheritance, containment, and
++# class references variables) of the class with other documented classes.
++
++COLLABORATION_GRAPH = YES
++
++# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
++# will generate a graph for groups, showing the direct groups dependencies
++
++GROUP_GRAPHS = YES
++
++# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
++# collaboration diagrams in a style similar to the OMG's Unified Modeling
++# Language.
++
++UML_LOOK = NO
++
++# If set to YES, the inheritance and collaboration graphs will show the
++# relations between templates and their instances.
++
++TEMPLATE_RELATIONS = YES
++
++# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
++# tags are set to YES then doxygen will generate a graph for each documented
++# file showing the direct and indirect include dependencies of the file with
++# other documented files.
++
++INCLUDE_GRAPH = YES
++
++# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
++# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
++# documented header file showing the documented files that directly or
++# indirectly include this file.
++
++INCLUDED_BY_GRAPH = YES
++
++# If the CALL_GRAPH and HAVE_DOT options are set to YES then
++# doxygen will generate a call dependency graph for every global function
++# or class method. Note that enabling this option will significantly increase
++# the time of a run. So in most cases it will be better to enable call graphs
++# for selected functions only using the \callgraph command.
++
++CALL_GRAPH = NO
++
++# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
++# doxygen will generate a caller dependency graph for every global function
++# or class method. Note that enabling this option will significantly increase
++# the time of a run. So in most cases it will be better to enable caller
++# graphs for selected functions only using the \callergraph command.
++
++CALLER_GRAPH = NO
++
++# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
++# will graphical hierarchy of all classes instead of a textual one.
++
++GRAPHICAL_HIERARCHY = YES
++
++# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
++# then doxygen will show the dependencies a directory has on other directories
++# in a graphical way. The dependency relations are determined by the #include
++# relations between the files in the directories.
++
++DIRECTORY_GRAPH = YES
++
++# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
++# generated by dot. Possible values are png, jpg, or gif
++# If left blank png will be used.
++
++DOT_IMAGE_FORMAT = png
++
++# The tag DOT_PATH can be used to specify the path where the dot tool can be
++# found. If left blank, it is assumed the dot tool can be found in the path.
++
++DOT_PATH = @DOT@
++
++# The DOTFILE_DIRS tag can be used to specify one or more directories that
++# contain dot files that are included in the documentation (see the
++# \dotfile command).
++
++DOTFILE_DIRS =
++
++# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
++# nodes that will be shown in the graph. If the number of nodes in a graph
++# becomes larger than this value, doxygen will truncate the graph, which is
++# visualized by representing a node as a red box. Note that doxygen if the
++# number of direct children of the root node in a graph is already larger than
++# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
++# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
++
++DOT_GRAPH_MAX_NODES = 50
++
++# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
++# graphs generated by dot. A depth value of 3 means that only nodes reachable
++# from the root by following a path via at most 3 edges will be shown. Nodes
++# that lay further from the root node will be omitted. Note that setting this
++# option to 1 or 2 may greatly reduce the computation time needed for large
++# code bases. Also note that the size of a graph can be further restricted by
++# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
++
++MAX_DOT_GRAPH_DEPTH = 0
++
++# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
++# background. This is disabled by default, because dot on Windows does not
++# seem to support this out of the box. Warning: Depending on the platform used,
++# enabling this option may lead to badly anti-aliased labels on the edges of
++# a graph (i.e. they become hard to read).
++
++DOT_TRANSPARENT = YES
++
++# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
++# files in one run (i.e. multiple -o and -T options on the command line). This
++# makes dot run faster, but since only newer versions of dot (>1.8.10)
++# support this, this feature is disabled by default.
++
++DOT_MULTI_TARGETS = NO
++
++# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
++# generate a legend page explaining the meaning of the various boxes and
++# arrows in the dot generated graphs.
++
++GENERATE_LEGEND = YES
++
++# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
++# remove the intermediate dot files that are used to generate
++# the various graphs.
++
++DOT_CLEANUP = YES
+Index: docs/doxygen.header
+===================================================================
+--- docs/doxygen.header (revision 0)
++++ docs/doxygen.header (revision 0)
+@@ -0,0 +1,9 @@
++<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
++<html><head>
++<meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1"/>
++<meta name="keywords" content="LLDB,C++,doxygen,API,documentation"/>
++<meta name="description" content="C++ source code API documentation for LLDB."/>
++<title>LLVM: $title</title>
++<link href="doxygen.css" rel="stylesheet" type="text/css"/>
++</head><body>
++<p class="title">LLDB API Documentation</p>
+Index: docs/doxygen.intro
+===================================================================
+--- docs/doxygen.intro (revision 0)
++++ docs/doxygen.intro (revision 0)
+@@ -0,0 +1,19 @@
++/// @mainpage LLDB
++///
++/// @section main_intro Introduction
++/// Welcome to LLDB.
++///
++/// This documentation describes the @b interface that can drive LLDB.
++/// There are no instructions here on how to use LLDB, only the APIs
++/// that make up the software. For usage instructions, please see
++/// the help command.
++///
++/// @section main_caveat Caveat
++/// This documentation is generated directly from the source code with doxygen.
++/// Since LLDB is constantly under active development, what you're about to
++/// read is out of date! However, it may still be useful since certain portions
++/// of LLDB are very stable.
++///
++/// @section main_changelog Change Log
++/// - Adapted for LLDB 05/25 by Daniel Malea
++/// - Original content written 12/30/2003 by Reid Spencer
+Index: docs/doxygen.footer
+===================================================================
+--- docs/doxygen.footer (revision 0)
++++ docs/doxygen.footer (revision 0)
+@@ -0,0 +1,13 @@
++<hr>
++<p class="footer">
++Generated on $datetime for <a href="http://lldb.llvm.org/">$projectname</a> by
++<a href="http://www.doxygen.org"><img src="doxygen.png" alt="Doxygen"
++align="middle" border="0"/>$doxygenversion</a><br>
++Copyright © 2003-2013 University of Illinois at Urbana-Champaign.
++All Rights Reserved.</p>
++
++<hr>
++<!--#include virtual="/attrib.incl" -->
++
++</body>
++</html>
+Index: utils/vim-lldb/plugin/lldb.vim
+===================================================================
+--- utils/vim-lldb/plugin/lldb.vim (revision 183906)
++++ utils/vim-lldb/plugin/lldb.vim (working copy)
+@@ -42,11 +42,13 @@
+
+ " Window show/hide commands
+ command -complete=custom,s:CompleteWindow -nargs=1 Lhide python ctrl.doHide('<args>')
+- command -complete=custom,s:CompleteWindow -nargs=1 Lshow python ctrl.doShow('<args>')
++ command -complete=custom,s:CompleteWindow -nargs=0 Lshow python ctrl.doShow('<args>')
+
+ " Launching convenience commands (no autocompletion)
+ command -nargs=* Lstart python ctrl.doLaunch(True, '<args>')
+ command -nargs=* Lrun python ctrl.doLaunch(False, '<args>')
++ command -nargs=1 Lattach python ctrl.doAttach('<args>')
++ command -nargs=0 Ldetach python ctrl.doDetach()
+
+ " Regexp-commands: because vim's command mode does not support '_' or '-'
+ " characters in command names, we omit them when creating the :L<cmd>
+@@ -80,7 +82,9 @@
+ command -complete=custom,s:CompleteCommand -nargs=* Lwatchpoint python ctrl.doCommand('watchpoint', '<args>')
+
+ " Convenience (shortcut) LLDB commands
+- command -complete=custom,s:CompleteCommand -nargs=* Lprint python ctrl.doCommand('print', '<args>')
++ command -complete=custom,s:CompleteCommand -nargs=* Lprint python ctrl.doCommand('print', vim.eval("s:CursorWord('<args>')"))
++ command -complete=custom,s:CompleteCommand -nargs=* Lpo python ctrl.doCommand('po', vim.eval("s:CursorWord('<args>')"))
++ command -complete=custom,s:CompleteCommand -nargs=* LpO python ctrl.doCommand('po', vim.eval("s:CursorWORD('<args>')"))
+ command -complete=custom,s:CompleteCommand -nargs=* Lbt python ctrl.doCommand('bt', '<args>')
+
+ " Frame/Thread-Selection (commands that also do an Uupdate but do not
+@@ -133,4 +137,15 @@
+ EOF
+ endfunction()
+
++" Returns cword if search term is empty
++function! s:CursorWord(term)
++ return empty(a:term) ? expand('<cword>') : a:term
++endfunction()
++
++" Returns cleaned cWORD if search term is empty
++function! s:CursorWORD(term)
++ " Will strip all non-alphabetic characters from both sides
++ return empty(a:term) ? substitute(expand('<cWORD>'), '^\A*\(.\{-}\)\A*$', '\1', '') : a:term
++endfunction()
++
+ call s:InitLldbPlugin()
+Index: utils/vim-lldb/doc/lldb.txt
+===================================================================
+--- utils/vim-lldb/doc/lldb.txt (revision 183906)
++++ utils/vim-lldb/doc/lldb.txt (working copy)
+@@ -37,6 +37,12 @@
+ * locals
+ * registers
+ * threads
++ *lldb-:Lattach*
++:Lattach <process-name> Attach to a process by name.
++
++ *lldb-:Ldetach*
++:Ldetach Detach from the current process.
++
+ *lldb-:Ltarget*
+ :Ltarget [[create] executable]
+ Create a target with the specified executable. If
+@@ -84,6 +90,13 @@
+ command is invoked. If no arguments are provided,
+ a breakpoint at the location under the cursor.
+
++ *lldb-:Lprint*
++ *lldb-:Lpo*
++ *lldb-:LpO*
++:Lprint <expr> Aliases to the lldb print and po commands. Cursor
++:Lpo <expr> word (cursor WORD for LpO) will be used when
++:LpO <expr> expression omitted.
++
+ MAPPINGS *lldb-mappings*
+
+ On Mac OS X (under MacVim) , the following key mappings are available:
+Index: utils/vim-lldb/python-vim-lldb/lldb_controller.py
+===================================================================
+--- utils/vim-lldb/python-vim-lldb/lldb_controller.py (revision 183906)
++++ utils/vim-lldb/python-vim-lldb/lldb_controller.py (working copy)
+@@ -141,6 +141,29 @@
+ else:
+ self.doLaunch('-s' not in args, "")
+
++ def doAttach(self, process_name):
++ """ Handle process attach. """
++ error = lldb.SBError()
++
++ self.processListener = lldb.SBListener("process_event_listener")
++ self.target = self.dbg.CreateTarget('')
++ self.process = self.target.AttachToProcessWithName(self.processListener, process_name, False, error)
++ if not error.Success():
++ sys.stderr.write("Error during attach: " + str(error))
++ return
++
++ self.ui.activate()
++ self.pid = self.process.GetProcessID()
++
++ print "Attached to %s (pid=%d)" % (process_name, self.pid)
++
++ def doDetach(self):
++ if self.process is not None and self.process.IsValid():
++ pid = self.process.GetProcessID()
++ state = state_type_to_str(self.process.GetState())
++ self.process.Detach()
++ self.processPendingEvents(self.eventDelayLaunch)
++
+ def doLaunch(self, stop_at_entry, args):
+ """ Handle process launch. """
+ error = lldb.SBError()
+@@ -250,6 +273,10 @@
+
+ def doShow(self, name):
+ """ handle :Lshow <name> """
++ if not name:
++ self.ui.activate()
++ return
++
+ if self.ui.showWindow(name):
+ self.ui.update(self.target, "", self)
+
+@@ -321,6 +348,10 @@
+ self.processListener.GetNextEvent(event)
+ new_state = lldb.SBProcess.GetStateFromEvent(event)
+
++ # continue if stopped after attaching
++ if old_state == lldb.eStateAttaching and new_state == lldb.eStateStopped:
++ self.process.Continue()
++
+ # If needed, perform any event-specific behaviour here
+ num_events_handled += 1
+
+Index: tools/driver/Driver.cpp
+===================================================================
+--- tools/driver/Driver.cpp (revision 183906)
++++ tools/driver/Driver.cpp (working copy)
+@@ -105,7 +105,9 @@
+ "Tells the debugger to open source files using the host's \"external editor\" mechanism." },
+ { LLDB_3_TO_5, false, "no-lldbinit" , 'x', no_argument , 0, eArgTypeNone,
+ "Do not automatically parse any '.lldbinit' files." },
+- { LLDB_OPT_SET_6, true , "python-path" , 'P', no_argument , 0, eArgTypeNone,
++ { LLDB_3_TO_5, false, "no-use-colors" , 'o', no_argument , 0, eArgTypeNone,
++ "Do not use colors." },
++ { LLDB_OPT_SET_6, true , "python-path" , 'P', no_argument , 0, eArgTypeNone,
+ "Prints out the path to the lldb.py file for this version of lldb." },
+ { 0, false, NULL , 0 , 0 , 0, eArgTypeNone, NULL }
+ };
+@@ -621,6 +623,10 @@
+ m_debugger.SkipAppInitFiles (true);
+ break;
+
++ case 'o':
++ m_debugger.SetUseColor (false);
++ break;
++
+ case 'f':
+ {
+ SBFileSpec file(optarg);
+@@ -1587,9 +1593,15 @@
+ }
+ }
+
+- editline_output_pty.CloseMasterFileDescriptor();
++ master_out_comm.SetReadThreadBytesReceivedCallback(NULL, NULL);
+ master_out_comm.Disconnect();
++ master_out_comm.ReadThreadStop();
++
++ out_comm_2.SetReadThreadBytesReceivedCallback(NULL, NULL);
+ out_comm_2.Disconnect();
++ out_comm_2.ReadThreadStop();
++
++ editline_output_pty.CloseMasterFileDescriptor();
+ reset_stdin_termios();
+ fclose (stdin);
+
+Index: tools/driver/CMakeLists.txt
+===================================================================
+--- tools/driver/CMakeLists.txt (revision 183906)
++++ tools/driver/CMakeLists.txt (working copy)
+@@ -12,5 +12,7 @@
+ #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)
+Index: tools/debugserver/source/DNB.h
+===================================================================
+--- tools/debugserver/source/DNB.h (revision 183906)
++++ tools/debugserver/source/DNB.h (working copy)
+@@ -104,7 +104,6 @@
+ //----------------------------------------------------------------------
+ nub_event_t DNBProcessWaitForEvents (nub_process_t pid, nub_event_t event_mask, bool wait_for_set, struct timespec* timeout) DNB_EXPORT;
+ void DNBProcessResetEvents (nub_process_t pid, nub_event_t event_mask) DNB_EXPORT;
+-void DNBProcessInterruptEvents (nub_process_t pid) DNB_EXPORT;
+
+ //----------------------------------------------------------------------
+ // Thread functions
+Index: tools/debugserver/source/MacOSX/MachVMMemory.h
+===================================================================
+--- tools/debugserver/source/MacOSX/MachVMMemory.h (revision 183906)
++++ tools/debugserver/source/MacOSX/MachVMMemory.h (working copy)
+@@ -28,7 +28,7 @@
+ nub_size_t Write(task_t task, nub_addr_t address, const void *data, nub_size_t data_count);
+ nub_size_t PageSize(task_t task);
+ nub_bool_t GetMemoryRegionInfo(task_t task, nub_addr_t address, DNBRegionInfo *region_info);
+- nub_bool_t GetMemoryProfile(DNBProfileDataScanType scanType, task_t task, struct task_basic_info ti, cpu_type_t cputype, nub_process_t pid, vm_statistics_data_t &vm_stats, uint64_t &physical_memory, mach_vm_size_t &rprvt, mach_vm_size_t &rsize, mach_vm_size_t &vprvt, mach_vm_size_t &vsize, mach_vm_size_t &dirty_size);
++ nub_bool_t GetMemoryProfile(DNBProfileDataScanType scanType, task_t task, struct task_basic_info ti, cpu_type_t cputype, nub_process_t pid, vm_statistics_data_t &vm_stats, uint64_t &physical_memory, mach_vm_size_t &rprvt, mach_vm_size_t &rsize, mach_vm_size_t &vprvt, mach_vm_size_t &vsize, mach_vm_size_t &dirty_size, mach_vm_size_t &purgable, mach_vm_size_t &anonymous);
+
+ protected:
+ nub_size_t MaxBytesLeftInPage(task_t task, nub_addr_t addr, nub_size_t count);
+Index: tools/debugserver/source/MacOSX/MachProcess.h
+===================================================================
+--- tools/debugserver/source/MacOSX/MachProcess.h (revision 183906)
++++ tools/debugserver/source/MacOSX/MachProcess.h (working copy)
+@@ -18,7 +18,6 @@
+ #include "DNBBreakpoint.h"
+ #include "DNBError.h"
+ #include "DNBThreadResumeActions.h"
+-//#include "MachDYLD.h"
+ #include "MachException.h"
+ #include "MachVMMemory.h"
+ #include "MachTask.h"
+@@ -179,7 +178,7 @@
+ nub_thread_t GetCurrentThreadMachPort ();
+ nub_thread_t SetCurrentThread (nub_thread_t tid);
+ MachThreadList & GetThreadList() { return m_thread_list; }
+- bool GetThreadStoppedReason(nub_thread_t tid, struct DNBThreadStopInfo *stop_info) const;
++ bool GetThreadStoppedReason(nub_thread_t tid, struct DNBThreadStopInfo *stop_info);
+ void DumpThreadStoppedReason(nub_thread_t tid) const;
+ const char * GetThreadInfo (nub_thread_t tid) const;
+
+@@ -300,6 +299,7 @@
+ nub_state_t m_state; // The state of our process
+ PThreadMutex m_state_mutex; // Multithreaded protection for m_state
+ PThreadEvent m_events; // Process related events in the child processes lifetime can be waited upon
++ PThreadEvent m_private_events; // Used to coordinate running and stopping the process without affecting m_events
+ DNBBreakpointList m_breakpoints; // Breakpoint list for this process
+ DNBBreakpointList m_watchpoints; // Watchpoint list for this process
+ DNBCallbackNameToAddress m_name_to_addr_callback;
+@@ -307,6 +307,7 @@
+ DNBCallbackCopyExecutableImageInfos
+ m_image_infos_callback;
+ void * m_image_infos_baton;
++ bool m_did_exec;
+ };
+
+
+Index: tools/debugserver/source/MacOSX/MachVMMemory.cpp
+===================================================================
+--- tools/debugserver/source/MacOSX/MachVMMemory.cpp (revision 183906)
++++ tools/debugserver/source/MacOSX/MachVMMemory.cpp (working copy)
+@@ -17,6 +17,7 @@
+ #include <mach/mach_vm.h>
+ #include <mach/shared_region.h>
+ #include <sys/sysctl.h>
++#include <dlfcn.h>
+
+ MachVMMemory::MachVMMemory() :
+ m_page_size (kInvalidPageSize),
+@@ -281,14 +282,7 @@
+ }
+ }
+
+- static vm_size_t pagesize;
+- static bool calculated = false;
+- if (!calculated)
+- {
+- calculated = true;
+- pagesize = PageSize (task);
+- }
+-
++ vm_size_t pagesize = PageSize (task);
+ rsize = pages_resident * pagesize;
+ dirty_size = pages_dirtied * pagesize;
+ }
+@@ -333,15 +327,8 @@
+
+ mach_vm_size_t aliased = 0;
+ bool global_shared_text_data_mapped = false;
++ vm_size_t pagesize = PageSize (task);
+
+- static vm_size_t pagesize;
+- static bool calculated = false;
+- if (!calculated)
+- {
+- calculated = true;
+- pagesize = PageSize (task);
+- }
+-
+ for (mach_vm_address_t addr=0, size=0; ; addr += size)
+ {
+ vm_region_top_info_data_t info;
+@@ -430,8 +417,72 @@
+ rprvt += aliased;
+ }
+
++#if defined (TASK_VM_INFO) && TASK_VM_INFO >= 22
++
++// cribbed from sysmond
++static uint64_t
++SumVMPurgeableInfo(const vm_purgeable_info_t info)
++{
++ uint64_t sum = 0;
++ int i;
++
++ for (i = 0; i < 8; i++)
++ {
++ sum += info->fifo_data[i].size;
++ }
++ sum += info->obsolete_data.size;
++ for (i = 0; i < 8; i++)
++ {
++ sum += info->lifo_data[i].size;
++ }
++
++ return sum;
++}
++
++#endif
++
++static void
++GetPurgeableAndAnonymous(task_t task, uint64_t &purgeable, uint64_t &anonymous)
++{
++#if defined (TASK_VM_INFO) && TASK_VM_INFO >= 22
++
++ kern_return_t kr;
++ task_purgable_info_t purgeable_info;
++ uint64_t purgeable_sum = 0;
++ mach_msg_type_number_t info_count;
++ task_vm_info_data_t vm_info;
++
++ typedef kern_return_t (*task_purgable_info_type) (task_t, task_purgable_info_t *);
++ task_purgable_info_type task_purgable_info_ptr = NULL;
++ task_purgable_info_ptr = (task_purgable_info_type)dlsym(RTLD_NEXT, "task_purgable_info");
++ if (task_purgable_info_ptr != NULL)
++ {
++ kr = (*task_purgable_info_ptr)(task, &purgeable_info);
++ if (kr == KERN_SUCCESS) {
++ purgeable_sum = SumVMPurgeableInfo(&purgeable_info);
++ purgeable = purgeable_sum;
++ }
++ }
++
++ info_count = TASK_VM_INFO_COUNT;
++ kr = task_info(task, TASK_VM_INFO, (task_info_t)&vm_info, &info_count);
++ if (kr == KERN_SUCCESS)
++ {
++ if (purgeable_sum < vm_info.internal)
++ {
++ anonymous = vm_info.internal - purgeable_sum;
++ }
++ else
++ {
++ anonymous = 0;
++ }
++ }
++
++#endif
++}
++
+ nub_bool_t
+-MachVMMemory::GetMemoryProfile(DNBProfileDataScanType scanType, task_t task, struct task_basic_info ti, cpu_type_t cputype, nub_process_t pid, vm_statistics_data_t &vm_stats, uint64_t &physical_memory, mach_vm_size_t &rprvt, mach_vm_size_t &rsize, mach_vm_size_t &vprvt, mach_vm_size_t &vsize, mach_vm_size_t &dirty_size)
++MachVMMemory::GetMemoryProfile(DNBProfileDataScanType scanType, task_t task, struct task_basic_info ti, cpu_type_t cputype, nub_process_t pid, vm_statistics_data_t &vm_stats, uint64_t &physical_memory, mach_vm_size_t &rprvt, mach_vm_size_t &rsize, mach_vm_size_t &vprvt, mach_vm_size_t &vsize, mach_vm_size_t &dirty_size, mach_vm_size_t &purgeable, mach_vm_size_t &anonymous)
+ {
+ if (scanType & eProfileHostMemory)
+ physical_memory = GetPhysicalMemory();
+@@ -453,6 +504,11 @@
+ // This uses vmmap strategy. We don't use the returned rsize for now. We prefer to match top's version since that's what we do for the rest of the metrics.
+ GetRegionSizes(task, rsize, dirty_size);
+ }
++
++ if (scanType & eProfileMemoryAnonymous)
++ {
++ GetPurgeableAndAnonymous(task, purgeable, anonymous);
++ }
+ }
+
+ return true;
+Index: tools/debugserver/source/MacOSX/MachProcess.cpp
+===================================================================
+--- tools/debugserver/source/MacOSX/MachProcess.cpp (revision 183906)
++++ tools/debugserver/source/MacOSX/MachProcess.cpp (working copy)
+@@ -95,12 +95,14 @@
+ m_state (eStateUnloaded),
+ m_state_mutex (PTHREAD_MUTEX_RECURSIVE),
+ m_events (0, kAllEventsMask),
++ m_private_events (0, kAllEventsMask),
+ m_breakpoints (),
+ m_watchpoints (),
+ m_name_to_addr_callback(NULL),
+ m_name_to_addr_baton(NULL),
+ m_image_infos_callback(NULL),
+- m_image_infos_baton(NULL)
++ m_image_infos_baton(NULL),
++ m_did_exec (false)
+ {
+ DNBLogThreadedIf(LOG_PROCESS | LOG_VERBOSE, "%s", __PRETTY_FUNCTION__);
+ }
+@@ -198,9 +200,15 @@
+ }
+
+ bool
+-MachProcess::GetThreadStoppedReason(nub_thread_t tid, struct DNBThreadStopInfo *stop_info) const
++MachProcess::GetThreadStoppedReason(nub_thread_t tid, struct DNBThreadStopInfo *stop_info)
+ {
+- return m_thread_list.GetThreadStoppedReason(tid, stop_info);
++ if (m_thread_list.GetThreadStoppedReason(tid, stop_info))
++ {
++ if (m_did_exec)
++ stop_info->reason = eStopTypeExec;
++ return true;
++ }
++ return false;
+ }
+
+ void
+@@ -258,8 +266,6 @@
+ // Scope for mutex locker
+ {
+ PTHREAD_MUTEX_LOCKER(locker, m_state_mutex);
+- DNBLogThreadedIf(LOG_PROCESS, "MachProcess::SetState ( %s )", DNBStateAsString(new_state));
+-
+ const nub_state_t old_state = m_state;
+
+ if (old_state != new_state)
+@@ -269,15 +275,26 @@
+ else
+ event_mask = eEventProcessRunningStateChanged;
+
++ DNBLogThreadedIf(LOG_PROCESS, "MachProcess::SetState ( old = %s, new = %s ) updating state, event_mask = 0x%8.8x", DNBStateAsString(old_state), DNBStateAsString(new_state), event_mask);
++
+ m_state = new_state;
+ if (new_state == eStateStopped)
+ m_stop_count++;
+ }
++ else
++ {
++ DNBLogThreadedIf(LOG_PROCESS, "MachProcess::SetState ( old = %s, new = %s ) ignoring state...", DNBStateAsString(old_state), DNBStateAsString(new_state));
++ }
+ }
+
+ if (event_mask != 0)
+ {
+ m_events.SetEvents (event_mask);
++ m_private_events.SetEvents (event_mask);
++ if (event_mask == eEventProcessStoppedStateChanged)
++ m_private_events.ResetEvents (eEventProcessRunningStateChanged);
++ else
++ m_private_events.ResetEvents (eEventProcessStoppedStateChanged);
+
+ // Wait for the event bit to reset if a reset ACK is requested
+ m_events.WaitForResetAck(event_mask);
+@@ -419,7 +436,7 @@
+ if (IsRunning(state) && timeout_abstime)
+ {
+ DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Signal (signal = %d, timeout = %p) waiting for signal to stop process...", signal, timeout_abstime);
+- m_events.WaitForSetEvents(eEventProcessStoppedStateChanged, timeout_abstime);
++ m_private_events.WaitForSetEvents(eEventProcessStoppedStateChanged, timeout_abstime);
+ state = GetState();
+ DNBLogThreadedIf(LOG_PROCESS, "MachProcess::Signal (signal = %d, timeout = %p) state = %s", signal, timeout_abstime, DNBStateAsString(state));
+ return !IsRunning (state);
+@@ -823,6 +840,11 @@
+ DNBBreakpoint *bp = m_breakpoints.FindByID (breakID);
+ if (bp)
+ {
++ // After "exec" we might end up with a bunch of breakpoints that were disabled
++ // manually, just ignore them
++ if (!bp->IsEnabled())
++ return true;
++
+ nub_addr_t addr = bp->Address();
+ DNBLogThreadedIf(LOG_BREAKPOINTS | LOG_VERBOSE, "MachProcess::DisableBreakpoint ( breakID = %d, remove = %d ) addr = 0x%8.8llx", breakID, remove, (uint64_t)addr);
+
+@@ -1145,13 +1167,62 @@
+ DNBLogThreadedIf(LOG_EXCEPTIONS, "%s: %llu exception messages.", __PRETTY_FUNCTION__, (uint64_t)m_exception_messages.size());
+ if (!m_exception_messages.empty())
+ {
++ m_did_exec = false;
++ // First check for any SIGTRAP and make sure we didn't exec
++ const task_t task = m_task.TaskPort();
++ size_t i;
++ if (m_pid != 0)
++ {
++ for (i=0; i<m_exception_messages.size(); ++i)
++ {
++ if (m_exception_messages[i].state.task_port == task)
++ {
++ const int signo = m_exception_messages[i].state.SoftSignal();
++ if (signo == SIGTRAP)
++ {
++ // SIGTRAP could mean that we exec'ed. We need to check the
++ // dyld all_image_infos.infoArray to see if it is NULL and if
++ // so, say that we exec'ed.
++ const nub_addr_t aii_addr = GetDYLDAllImageInfosAddress();
++ if (aii_addr != INVALID_NUB_ADDRESS)
++ {
++ const nub_addr_t info_array_count_addr = aii_addr + 4;
++ uint32_t info_array_count = 0;
++ if (m_task.ReadMemory(info_array_count_addr, 4, &info_array_count) == 4)
++ {
++ DNBLog ("info_array_count is 0x%x", info_array_count);
++ if (info_array_count == 0)
++ m_did_exec = true;
++ }
++ else
++ {
++ DNBLog ("error: failed to read all_image_infos.infoArrayCount from 0x%8.8llx", info_array_count_addr);
++ }
++ }
++ break;
++ }
++ }
++ }
++
++ if (m_did_exec)
++ {
++ cpu_type_t process_cpu_type = MachProcess::GetCPUTypeForLocalProcess (m_pid);
++ if (m_cpu_type != process_cpu_type)
++ {
++ DNBLog ("arch changed from 0x%8.8x to 0x%8.8x", m_cpu_type, process_cpu_type);
++ m_cpu_type = process_cpu_type;
++ DNBArchProtocol::SetArchitecture (process_cpu_type);
++ }
++ m_thread_list.Clear();
++ m_breakpoints.DisableAll();
++ }
++ }
++
+ // Let all threads recover from stopping and do any clean up based
+ // on the previous thread state (if any).
+ m_thread_list.ProcessDidStop(this);
+
+ // Let each thread know of any exceptions
+- task_t task = m_task.TaskPort();
+- size_t i;
+ for (i=0; i<m_exception_messages.size(); ++i)
+ {
+ // Let the thread list figure use the MachProcess to forward all exceptions
+Index: tools/debugserver/source/MacOSX/MachTask.cpp
+===================================================================
+--- tools/debugserver/source/MacOSX/MachTask.cpp (revision 183906)
++++ tools/debugserver/source/MacOSX/MachTask.cpp (working copy)
+@@ -364,7 +364,9 @@
+ mach_vm_size_t vprvt = 0;
+ mach_vm_size_t vsize = 0;
+ mach_vm_size_t dirty_size = 0;
+- if (m_vm_memory.GetMemoryProfile(scanType, task, task_info, m_process->GetCPUType(), m_process->ProcessID(), vm_stats, physical_memory, rprvt, rsize, vprvt, vsize, dirty_size))
++ mach_vm_size_t purgeable = 0;
++ mach_vm_size_t anonymous = 0;
++ if (m_vm_memory.GetMemoryProfile(scanType, task, task_info, m_process->GetCPUType(), m_process->ProcessID(), vm_stats, physical_memory, rprvt, rsize, vprvt, vsize, dirty_size, purgeable, anonymous))
+ {
+ std::ostringstream profile_data_stream;
+
+@@ -439,6 +441,12 @@
+
+ if (scanType & eProfileMemoryDirtyPage)
+ profile_data_stream << "dirty:" << dirty_size << ';';
++
++ if (scanType & eProfileMemoryAnonymous)
++ {
++ profile_data_stream << "purgeable:" << purgeable << ';';
++ profile_data_stream << "anonymous:" << anonymous << ';';
++ }
+ }
+
+ profile_data_stream << "--end--;";
+Index: tools/debugserver/source/DNBDefs.h
+===================================================================
+--- tools/debugserver/source/DNBDefs.h (revision 183906)
++++ tools/debugserver/source/DNBDefs.h (working copy)
+@@ -121,13 +121,11 @@
+ eEventSharedLibsStateChange = 1 << 2, // Shared libraries loaded/unloaded state has changed
+ eEventStdioAvailable = 1 << 3, // Something is available on stdout/stderr
+ eEventProfileDataAvailable = 1 << 4, // Profile data ready for retrieval
+- eEventProcessAsyncInterrupt = 1 << 5, // Gives the ability for any infinite wait calls to be interrupted
+ kAllEventsMask = eEventProcessRunningStateChanged |
+ eEventProcessStoppedStateChanged |
+ eEventSharedLibsStateChange |
+ eEventStdioAvailable |
+- eEventProfileDataAvailable |
+- eEventProcessAsyncInterrupt
++ eEventProfileDataAvailable
+ };
+
+ #define LOG_VERBOSE (1u << 0)
+@@ -239,7 +237,8 @@
+ {
+ eStopTypeInvalid = 0,
+ eStopTypeSignal,
+- eStopTypeException
++ eStopTypeException,
++ eStopTypeExec
+ };
+
+ enum DNBMemoryPermissions
+@@ -357,6 +356,7 @@
+
+ eProfileMemory = (1 << 6), // By default, excludes eProfileMemoryDirtyPage.
+ eProfileMemoryDirtyPage = (1 << 7), // Assume eProfileMemory, get Dirty Page size as well.
++ eProfileMemoryAnonymous = (1 << 8), // Assume eProfileMemory, get Anonymous memory as well.
+
+ eProfileAll = 0xffffffff
+ };
+Index: tools/debugserver/source/DNBBreakpoint.cpp
+===================================================================
+--- tools/debugserver/source/DNBBreakpoint.cpp (revision 183906)
++++ tools/debugserver/source/DNBBreakpoint.cpp (working copy)
+@@ -288,6 +288,15 @@
+ return NULL;
+ }
+
++void
++DNBBreakpointList::DisableAll ()
++{
++ iterator pos, end = m_breakpoints.end();
++ for (pos = m_breakpoints.begin(); pos != end; ++pos)
++ (*pos).SetEnabled(false);
++}
++
++
+ const DNBBreakpoint *
+ DNBBreakpointList::GetByIndex (uint32_t i) const
+ {
+Index: tools/debugserver/source/RNBRemote.h
+===================================================================
+--- tools/debugserver/source/RNBRemote.h (revision 183906)
++++ tools/debugserver/source/RNBRemote.h (working copy)
+@@ -129,7 +129,7 @@
+
+ void Initialize();
+
+- bool InitializeRegisters ();
++ bool InitializeRegisters (bool force = false);
+
+ rnb_err_t HandleAsyncPacket(PacketEnum *type = NULL);
+ rnb_err_t HandleReceivedPacket(PacketEnum *type = NULL);
+Index: tools/debugserver/source/DNB.cpp
+===================================================================
+--- tools/debugserver/source/DNB.cpp (revision 183906)
++++ tools/debugserver/source/DNB.cpp (working copy)
+@@ -900,15 +900,6 @@
+ procSP->Events().ResetEvents(event_mask);
+ }
+
+-void
+-DNBProcessInterruptEvents (nub_process_t pid)
+-{
+- MachProcessSP procSP;
+- if (GetProcessSP (pid, procSP))
+- procSP->Events().SetEvents(eEventProcessAsyncInterrupt);
+-}
+-
+-
+ // Breakpoints
+ nub_break_t
+ DNBBreakpointSet (nub_process_t pid, nub_addr_t addr, nub_size_t size, nub_bool_t hardware)
+Index: tools/debugserver/source/DNBBreakpoint.h
+===================================================================
+--- tools/debugserver/source/DNBBreakpoint.h (revision 183906)
++++ tools/debugserver/source/DNBBreakpoint.h (working copy)
+@@ -145,6 +145,7 @@
+ size_t Size() const { return m_breakpoints.size(); }
+ DNBBreakpoint * GetByIndex (uint32_t i);
+ const DNBBreakpoint * GetByIndex (uint32_t i) const;
++ void DisableAll ();
+
+ protected:
+ typedef std::list<DNBBreakpoint> collection;
+Index: tools/debugserver/source/RNBRemote.cpp
+===================================================================
+--- tools/debugserver/source/RNBRemote.cpp (revision 183906)
++++ tools/debugserver/source/RNBRemote.cpp (working copy)
+@@ -1079,7 +1079,7 @@
+
+
+ bool
+-RNBRemote::InitializeRegisters ()
++RNBRemote::InitializeRegisters (bool force)
+ {
+ pid_t pid = m_ctx.ProcessID();
+ if (pid == INVALID_NUB_PROCESS)
+@@ -1093,6 +1093,13 @@
+ // registers to be discovered using multiple qRegisterInfo calls to get
+ // all register information after the architecture for the process is
+ // determined.
++ if (force)
++ {
++ g_dynamic_register_map.clear();
++ g_reg_entries = NULL;
++ g_num_reg_entries = 0;
++ }
++
+ if (g_dynamic_register_map.empty())
+ {
+ nub_size_t num_reg_sets = 0;
+@@ -2381,6 +2388,10 @@
+
+ if (DNBThreadGetStopReason (pid, tid, &tid_stop_info))
+ {
++ const bool did_exec = tid_stop_info.reason == eStopTypeExec;
++ if (did_exec)
++ RNBRemote::InitializeRegisters(true);
++
+ std::ostringstream ostrm;
+ // Output the T packet with the thread
+ ostrm << 'T';
+@@ -2478,9 +2489,13 @@
+ }
+ }
+ }
+-
+- if (tid_stop_info.details.exception.type)
++
++ if (did_exec)
+ {
++ ostrm << "reason:exec;";
++ }
++ else if (tid_stop_info.details.exception.type)
++ {
+ ostrm << "metype:" << std::hex << tid_stop_info.details.exception.type << ";";
+ ostrm << "mecount:" << std::hex << tid_stop_info.details.exception.data_count << ";";
+ for (int i = 0; i < tid_stop_info.details.exception.data_count; ++i)
+Index: tools/debugserver/debugserver.xcodeproj/project.pbxproj
+===================================================================
+--- tools/debugserver/debugserver.xcodeproj/project.pbxproj (revision 183906)
++++ tools/debugserver/debugserver.xcodeproj/project.pbxproj (working copy)
+@@ -97,8 +97,6 @@
+ 26C637E80C71334A0024798E /* dbgnub-mig.defs */ = {isa = PBXFileReference; explicitFileType = sourcecode.mig; fileEncoding = 30; path = "dbgnub-mig.defs"; sourceTree = "<group>"; };
+ 26C637EA0C71334A0024798E /* DNBArchImplI386.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DNBArchImplI386.cpp; sourceTree = "<group>"; };
+ 26C637EB0C71334A0024798E /* DNBArchImplI386.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DNBArchImplI386.h; sourceTree = "<group>"; };
+- 26C637EC0C71334A0024798E /* MachDYLD.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = MachDYLD.cpp; sourceTree = "<group>"; };
+- 26C637ED0C71334A0024798E /* MachDYLD.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MachDYLD.h; sourceTree = "<group>"; };
+ 26C637EE0C71334A0024798E /* MachException.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = MachException.cpp; sourceTree = "<group>"; };
+ 26C637EF0C71334A0024798E /* MachException.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MachException.h; sourceTree = "<group>"; };
+ 26C637F00C71334A0024798E /* MachProcess.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = MachProcess.cpp; sourceTree = "<group>"; };
+@@ -277,8 +275,6 @@
+ 4971AE7013D10F4F00649E37 /* HasAVX.h */,
+ 4971AE7113D10F4F00649E37 /* HasAVX.s */,
+ 26C637E80C71334A0024798E /* dbgnub-mig.defs */,
+- 26C637ED0C71334A0024798E /* MachDYLD.h */,
+- 26C637EC0C71334A0024798E /* MachDYLD.cpp */,
+ 26C637EF0C71334A0024798E /* MachException.h */,
+ 26C637EE0C71334A0024798E /* MachException.cpp */,
+ 26C637F10C71334A0024798E /* MachProcess.h */,
+Index: source/Core/Module.cpp
+===================================================================
+--- source/Core/Module.cpp (revision 183906)
++++ source/Core/Module.cpp (working copy)
+@@ -218,6 +218,9 @@
+
+ Module::~Module()
+ {
++ // Lock our module down while we tear everything down to make sure
++ // we don't get any access to the module while it is being destroyed
++ Mutex::Locker locker (m_mutex);
+ // Scope for locker below...
+ {
+ Mutex::Locker locker (GetAllocationModuleCollectionMutex());
+@@ -1235,7 +1238,7 @@
+ }
+
+ bool
+-Module::LoadScriptingResourceInTarget (Target *target, Error& error)
++Module::LoadScriptingResourceInTarget (Target *target, Error& error, Stream* feedback_stream)
+ {
+ if (!target)
+ {
+@@ -1243,7 +1246,7 @@
+ return false;
+ }
+
+- bool shoud_load = target->TargetProperties::GetLoadScriptFromSymbolFile();
++ LoadScriptFromSymFile shoud_load = target->TargetProperties::GetLoadScriptFromSymbolFile();
+
+ Debugger &debugger = target->GetDebugger();
+ const ScriptLanguage script_language = debugger.GetScriptLanguage();
+@@ -1273,14 +1276,18 @@
+ FileSpec scripting_fspec (file_specs.GetFileSpecAtIndex(i));
+ if (scripting_fspec && scripting_fspec.Exists())
+ {
+- if (!shoud_load)
++ if (shoud_load == eLoadScriptFromSymFileFalse)
++ return false;
++ if (shoud_load == eLoadScriptFromSymFileWarn)
+ {
+- error.SetErrorString("Target doesn't allow loading scripting resource. Please set target.load-script-from-symbol-file and retry.");
++ if (feedback_stream)
++ feedback_stream->Printf("warning: '%s' contains a debug script. To run this script in this debug session:\n\n command script import \"%s\"\n\nTo run all discovered debug scripts in this session:\n\n settings set target.load-script-from-symbol-file true\n"
++ ,GetFileSpec().GetFileNameStrippingExtension().GetCString(),scripting_fspec.GetPath().c_str());
+ return false;
+ }
+ StreamString scripting_stream;
+ scripting_fspec.Dump(&scripting_stream);
+- const bool can_reload = false;
++ const bool can_reload = true;
+ const bool init_lldb_globals = false;
+ bool did_load = script_interpreter->LoadScriptingModule(scripting_stream.GetData(), can_reload, init_lldb_globals, error);
+ if (!did_load)
+@@ -1438,8 +1445,19 @@
+ if (ObjCLanguageRuntime::IsPossibleObjCSelector(name_cstr))
+ lookup_name_type_mask |= eFunctionNameTypeSelector;
+
+- if (CPPLanguageRuntime::IsPossibleCPPCall(name_cstr, base_name_start, base_name_end))
++ CPPLanguageRuntime::MethodName cpp_method (name);
++ llvm::StringRef basename (cpp_method.GetBasename());
++ if (basename.empty())
++ {
++ if (CPPLanguageRuntime::StripNamespacesFromVariableName (name_cstr, base_name_start, base_name_end))
++ lookup_name_type_mask |= (eFunctionNameTypeMethod | eFunctionNameTypeBase);
++ }
++ else
++ {
++ base_name_start = basename.data();
++ base_name_end = base_name_start + basename.size();
+ lookup_name_type_mask |= (eFunctionNameTypeMethod | eFunctionNameTypeBase);
++ }
+ }
+ }
+ else
+@@ -1449,12 +1467,31 @@
+ {
+ // If they've asked for a CPP method or function name and it can't be that, we don't
+ // even need to search for CPP methods or names.
+- if (!CPPLanguageRuntime::IsPossibleCPPCall(name_cstr, base_name_start, base_name_end))
++ CPPLanguageRuntime::MethodName cpp_method (name);
++ if (cpp_method.IsValid())
+ {
+- lookup_name_type_mask &= ~(eFunctionNameTypeMethod | eFunctionNameTypeBase);
+- if (lookup_name_type_mask == eFunctionNameTypeNone)
+- return;
++ llvm::StringRef basename (cpp_method.GetBasename());
++ base_name_start = basename.data();
++ base_name_end = base_name_start + basename.size();
++
++ if (!cpp_method.GetQualifiers().empty())
++ {
++ // There is a "const" or other qualifer following the end of the fucntion parens,
++ // this can't be a eFunctionNameTypeBase
++ lookup_name_type_mask &= ~(eFunctionNameTypeBase);
++ if (lookup_name_type_mask == eFunctionNameTypeNone)
++ return;
++ }
+ }
++ else
++ {
++ if (!CPPLanguageRuntime::StripNamespacesFromVariableName (name_cstr, base_name_start, base_name_end))
++ {
++ lookup_name_type_mask &= ~(eFunctionNameTypeMethod | eFunctionNameTypeBase);
++ if (lookup_name_type_mask == eFunctionNameTypeNone)
++ return;
++ }
++ }
+ }
+
+ if (lookup_name_type_mask & eFunctionNameTypeSelector)
+Index: source/Core/ValueObjectVariable.cpp
+===================================================================
+--- source/Core/ValueObjectVariable.cpp (revision 183906)
++++ source/Core/ValueObjectVariable.cpp (working copy)
+@@ -186,10 +186,8 @@
+
+ switch (value_type)
+ {
+- default:
+- assert(!"Unhandled expression result value kind...");
+- break;
+-
++ case Value::eValueTypeVector:
++ // fall through
+ case Value::eValueTypeScalar:
+ // The variable value is in the Scalar value inside the m_value.
+ // We can point our m_data right to it.
+Index: source/Core/Disassembler.cpp
+===================================================================
+--- source/Core/Disassembler.cpp (revision 183906)
++++ source/Core/Disassembler.cpp (working copy)
+@@ -194,10 +194,7 @@
+ {
+ module->FindFunctions (name,
+ NULL,
+- eFunctionNameTypeBase |
+- eFunctionNameTypeFull |
+- eFunctionNameTypeMethod |
+- eFunctionNameTypeSelector,
++ eFunctionNameTypeAuto,
+ include_symbols,
+ include_inlines,
+ true,
+@@ -206,10 +203,7 @@
+ else if (exe_ctx.GetTargetPtr())
+ {
+ exe_ctx.GetTargetPtr()->GetImages().FindFunctions (name,
+- eFunctionNameTypeBase |
+- eFunctionNameTypeFull |
+- eFunctionNameTypeMethod |
+- eFunctionNameTypeSelector,
++ eFunctionNameTypeAuto,
+ include_symbols,
+ include_inlines,
+ false,
+Index: source/Core/RegularExpression.cpp
+===================================================================
+--- source/Core/RegularExpression.cpp (revision 183906)
++++ source/Core/RegularExpression.cpp (working copy)
+@@ -129,7 +129,7 @@
+ RegularExpression::Execute(const char* s, Match *match, int execute_flags) const
+ {
+ int err = 1;
+- if (m_comp_err == 0)
++ if (s != NULL && m_comp_err == 0)
+ {
+ if (match)
+ {
+Index: source/Core/UUID.cpp
+===================================================================
+--- source/Core/UUID.cpp (revision 183906)
++++ source/Core/UUID.cpp (working copy)
+@@ -22,29 +22,30 @@
+
+ namespace lldb_private {
+
+-UUID::UUID()
++UUID::UUID() : m_num_uuid_bytes(16)
+ {
+ ::memset (m_uuid, 0, sizeof(m_uuid));
+ }
+
+ UUID::UUID(const UUID& rhs)
+ {
++ m_num_uuid_bytes = rhs.m_num_uuid_bytes;
+ ::memcpy (m_uuid, rhs.m_uuid, sizeof (m_uuid));
+ }
+
+ UUID::UUID (const void *uuid_bytes, uint32_t num_uuid_bytes)
+ {
+- if (uuid_bytes && num_uuid_bytes >= 16)
+- ::memcpy (m_uuid, uuid_bytes, sizeof (m_uuid));
+- else
+- ::memset (m_uuid, 0, sizeof(m_uuid));
++ SetBytes (uuid_bytes, num_uuid_bytes);
+ }
+
+ const UUID&
+ UUID::operator=(const UUID& rhs)
+ {
+ if (this != &rhs)
++ {
++ m_num_uuid_bytes = rhs.m_num_uuid_bytes;
+ ::memcpy (m_uuid, rhs.m_uuid, sizeof (m_uuid));
++ }
+ return *this;
+ }
+
+@@ -55,6 +56,7 @@
+ void
+ UUID::Clear()
+ {
++ m_num_uuid_bytes = 16;
+ ::memset (m_uuid, 0, sizeof(m_uuid));
+ }
+
+@@ -70,12 +72,17 @@
+ std::string result;
+ char buf[64];
+ const uint8_t *u = (const uint8_t *)GetBytes();
+- if (sizeof (buf) > snprintf (buf,
++ if (sizeof (buf) > (size_t)snprintf (buf,
+ sizeof (buf),
+ "%2.2X%2.2X%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X",
+ u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7],u[8],u[9],u[10],u[11],u[12],u[13],u[14],u[15]))
+ {
+ result.append (buf);
++ if (m_num_uuid_bytes == 20)
++ {
++ if (sizeof (buf) > (size_t)snprintf (buf, sizeof (buf), "-%2.2X%2.2X%2.2X%2.2X", u[16],u[17],u[18],u[19]))
++ result.append (buf);
++ }
+ }
+ return result;
+ }
+@@ -86,21 +93,37 @@
+ const uint8_t *u = (const uint8_t *)GetBytes();
+ s->Printf ("%2.2X%2.2X%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X",
+ u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7],u[8],u[9],u[10],u[11],u[12],u[13],u[14],u[15]);
++ if (m_num_uuid_bytes == 20)
++ {
++ s->Printf ("-%2.2X%2.2X%2.2X%2.2X", u[16],u[17],u[18],u[19]);
++ }
+ }
+
+ void
+-UUID::SetBytes (const void *uuid_bytes)
++UUID::SetBytes (const void *uuid_bytes, uint32_t num_uuid_bytes)
+ {
+- if (uuid_bytes)
+- ::memcpy (m_uuid, uuid_bytes, sizeof (m_uuid));
++ if (uuid_bytes && num_uuid_bytes >= 20)
++ {
++ m_num_uuid_bytes = 20;
++ ::memcpy (m_uuid, uuid_bytes, m_num_uuid_bytes);
++ }
++ else if (uuid_bytes && num_uuid_bytes >= 16)
++ {
++ m_num_uuid_bytes = 16;
++ ::memcpy (m_uuid, uuid_bytes, m_num_uuid_bytes);
++ m_uuid[16] = m_uuid[17] = m_uuid[18] = m_uuid[19] = 0;
++ }
+ else
++ {
++ m_num_uuid_bytes = 16;
+ ::memset (m_uuid, 0, sizeof(m_uuid));
++ }
+ }
+
+ size_t
+ UUID::GetByteSize()
+ {
+- return sizeof(UUID::ValueType);
++ return m_num_uuid_bytes;
+ }
+
+ bool
+@@ -121,7 +144,11 @@
+ m_uuid[12] ||
+ m_uuid[13] ||
+ m_uuid[14] ||
+- m_uuid[15];
++ m_uuid[15] ||
++ m_uuid[16] ||
++ m_uuid[17] ||
++ m_uuid[18] ||
++ m_uuid[19];
+ }
+
+ static inline int
+@@ -134,7 +161,7 @@
+ }
+
+ size_t
+-UUID::DecodeUUIDBytesFromCString (const char *p, ValueType &uuid_bytes, const char **end)
++UUID::DecodeUUIDBytesFromCString (const char *p, ValueType &uuid_bytes, const char **end, uint32_t num_uuid_bytes)
+ {
+ size_t uuid_byte_idx = 0;
+ if (p)
+@@ -153,7 +180,7 @@
+
+ // Increment the byte that we are decoding within the UUID value
+ // and break out if we are done
+- if (++uuid_byte_idx == 16)
++ if (++uuid_byte_idx == num_uuid_bytes)
+ break;
+ }
+ else if (*p == '-')
+@@ -170,10 +197,13 @@
+ }
+ if (end)
+ *end = p;
++ // Clear trailing bytes to 0.
++ for (uint32_t i = uuid_byte_idx; i < sizeof(ValueType); i++)
++ uuid_bytes[i] = 0;
+ return uuid_byte_idx;
+ }
+ size_t
+-UUID::SetFromCString (const char *cstr)
++UUID::SetFromCString (const char *cstr, uint32_t num_uuid_bytes)
+ {
+ if (cstr == NULL)
+ return 0;
+@@ -184,11 +214,11 @@
+ while (isspace(*p))
+ ++p;
+
+- const size_t uuid_byte_idx = UUID::DecodeUUIDBytesFromCString (p, m_uuid, &p);
++ const size_t uuid_byte_idx = UUID::DecodeUUIDBytesFromCString (p, m_uuid, &p, num_uuid_bytes);
+
+ // If we successfully decoded a UUID, return the amount of characters that
+ // were consumed
+- if (uuid_byte_idx == 16)
++ if (uuid_byte_idx == num_uuid_bytes)
+ return p - cstr;
+
+ // Else return zero to indicate we were not able to parse a UUID value
+@@ -200,35 +230,35 @@
+ bool
+ lldb_private::operator == (const lldb_private::UUID &lhs, const lldb_private::UUID &rhs)
+ {
+- return ::memcmp (lhs.GetBytes(), rhs.GetBytes(), lldb_private::UUID::GetByteSize()) == 0;
++ return ::memcmp (lhs.GetBytes(), rhs.GetBytes(), sizeof (lldb_private::UUID::ValueType)) == 0;
+ }
+
+ bool
+ lldb_private::operator != (const lldb_private::UUID &lhs, const lldb_private::UUID &rhs)
+ {
+- return ::memcmp (lhs.GetBytes(), rhs.GetBytes(), lldb_private::UUID::GetByteSize()) != 0;
++ return ::memcmp (lhs.GetBytes(), rhs.GetBytes(), sizeof (lldb_private::UUID::ValueType)) != 0;
+ }
+
+ bool
+ lldb_private::operator < (const lldb_private::UUID &lhs, const lldb_private::UUID &rhs)
+ {
+- return ::memcmp (lhs.GetBytes(), rhs.GetBytes(), lldb_private::UUID::GetByteSize()) < 0;
++ return ::memcmp (lhs.GetBytes(), rhs.GetBytes(), sizeof (lldb_private::UUID::ValueType)) < 0;
+ }
+
+ bool
+ lldb_private::operator <= (const lldb_private::UUID &lhs, const lldb_private::UUID &rhs)
+ {
+- return ::memcmp (lhs.GetBytes(), rhs.GetBytes(), lldb_private::UUID::GetByteSize()) <= 0;
++ return ::memcmp (lhs.GetBytes(), rhs.GetBytes(), sizeof (lldb_private::UUID::ValueType)) <= 0;
+ }
+
+ bool
+ lldb_private::operator > (const lldb_private::UUID &lhs, const lldb_private::UUID &rhs)
+ {
+- return ::memcmp (lhs.GetBytes(), rhs.GetBytes(), lldb_private::UUID::GetByteSize()) > 0;
++ return ::memcmp (lhs.GetBytes(), rhs.GetBytes(), sizeof (lldb_private::UUID::ValueType)) > 0;
+ }
+
+ bool
+ lldb_private::operator >= (const lldb_private::UUID &lhs, const lldb_private::UUID &rhs)
+ {
+- return ::memcmp (lhs.GetBytes(), rhs.GetBytes(), lldb_private::UUID::GetByteSize()) >= 0;
++ return ::memcmp (lhs.GetBytes(), rhs.GetBytes(), sizeof (lldb_private::UUID::ValueType)) >= 0;
+ }
+Index: source/Core/ModuleList.cpp
+===================================================================
+--- source/Core/ModuleList.cpp (revision 183906)
++++ source/Core/ModuleList.cpp (working copy)
+@@ -1008,4 +1008,33 @@
+ return GetSharedModuleList ().RemoveIfOrphaned (module_ptr);
+ }
+
+-
++bool
++ModuleList::LoadScriptingResourcesInTarget (Target *target,
++ std::list<Error>& errors,
++ Stream *feedback_stream,
++ bool continue_on_error)
++{
++ if (!target)
++ return false;
++ Mutex::Locker locker(m_modules_mutex);
++ for (auto module : m_modules)
++ {
++ Error error;
++ if (module)
++ {
++ if (!module->LoadScriptingResourceInTarget(target, error, feedback_stream))
++ {
++ if (error.Fail() && error.AsCString())
++ {
++ error.SetErrorStringWithFormat("unable to load scripting data for module %s - error reported was %s",
++ module->GetFileSpec().GetFileNameStrippingExtension().GetCString(),
++ error.AsCString());
++ errors.push_back(error);
++ }
++ if (!continue_on_error)
++ return false;
++ }
++ }
++ }
++ return errors.size() == 0;
++}
+Index: source/Core/ValueObject.cpp
+===================================================================
+--- source/Core/ValueObject.cpp (revision 183906)
++++ source/Core/ValueObject.cpp (working copy)
+@@ -82,6 +82,7 @@
+ m_synthetic_value(NULL),
+ m_deref_valobj(NULL),
+ m_format (eFormatDefault),
++ m_last_format (eFormatDefault),
+ m_last_format_mgr_revision(0),
+ m_type_summary_sp(),
+ m_type_format_sp(),
+@@ -127,6 +128,7 @@
+ m_synthetic_value(NULL),
+ m_deref_valobj(NULL),
+ m_format (eFormatDefault),
++ m_last_format (eFormatDefault),
+ m_last_format_mgr_revision(0),
+ m_type_summary_sp(),
+ m_type_format_sp(),
+@@ -1441,7 +1443,7 @@
+ const char *
+ ValueObject::GetValueAsCString ()
+ {
+- if (UpdateValueIfNeeded(true) && m_value_str.empty())
++ if (UpdateValueIfNeeded(true))
+ {
+ lldb::Format my_format = GetFormat();
+ if (my_format == lldb::eFormatDefault)
+@@ -1468,13 +1470,17 @@
+ }
+ }
+ }
+- if (GetValueAsCString(my_format, m_value_str))
++ if (my_format != m_last_format || m_value_str.empty())
+ {
+- if (!m_value_did_change && m_old_value_valid)
++ m_last_format = my_format;
++ if (GetValueAsCString(my_format, m_value_str))
+ {
+- // The value was gotten successfully, so we consider the
+- // value as changed if the value string differs
+- SetValueDidChange (m_old_value_str != m_value_str);
++ if (!m_value_did_change && m_old_value_valid)
++ {
++ // The value was gotten successfully, so we consider the
++ // value as changed if the value string differs
++ SetValueDidChange (m_old_value_str != m_value_str);
++ }
+ }
+ }
+ }
+@@ -4315,6 +4321,7 @@
+ }
+ return lldb::eNoDynamicValues;
+ }
++
+ lldb::Format
+ ValueObject::GetFormat () const
+ {
+Index: source/Core/Mangled.cpp
+===================================================================
+--- source/Core/Mangled.cpp (revision 183906)
++++ source/Core/Mangled.cpp (working copy)
+@@ -30,6 +30,7 @@
+ #include "lldb/Core/Timer.h"
+ #include <ctype.h>
+ #include <string.h>
++#include <stdlib.h>
+
+ using namespace lldb_private;
+
+Index: source/Core/AddressResolverName.cpp
+===================================================================
+--- source/Core/AddressResolverName.cpp (revision 183906)
++++ source/Core/AddressResolverName.cpp (working copy)
+@@ -120,7 +120,7 @@
+ sym_list);
+ context.module_sp->FindFunctions (m_func_name,
+ NULL,
+- eFunctionNameTypeBase | eFunctionNameTypeFull | eFunctionNameTypeMethod | eFunctionNameTypeSelector,
++ eFunctionNameTypeAuto,
+ include_symbols,
+ include_inlines,
+ append,
+Index: source/Core/Debugger.cpp
+===================================================================
+--- source/Core/Debugger.cpp (revision 183906)
++++ source/Core/Debugger.cpp (working copy)
+@@ -47,6 +47,7 @@
+ #include "lldb/Target/Process.h"
+ #include "lldb/Target/RegisterContext.h"
+ #include "lldb/Target/StopInfo.h"
++#include "lldb/Target/Target.h"
+ #include "lldb/Target/Thread.h"
+ #include "lldb/Utility/AnsiTerminal.h"
+
+@@ -130,6 +131,7 @@
+ { "term-width", OptionValue::eTypeSInt64 , true, 80 , NULL, NULL, "The maximum number of columns to use for displaying text." },
+ { "thread-format", OptionValue::eTypeString , true, 0 , DEFAULT_THREAD_FORMAT, NULL, "The default thread format string to use when displaying thread information." },
+ { "use-external-editor", OptionValue::eTypeBoolean, true, false, NULL, NULL, "Whether to use an external editor or not." },
++{ "use-color", OptionValue::eTypeBoolean, true, true , NULL, NULL, "Whether to use Ansi color codes or not." },
+
+ { NULL, OptionValue::eTypeInvalid, true, 0 , NULL, NULL, NULL }
+ };
+@@ -147,7 +149,8 @@
+ ePropertyStopLineCountBefore,
+ ePropertyTerminalWidth,
+ ePropertyThreadFormat,
+- ePropertyUseExternalEditor
++ ePropertyUseExternalEditor,
++ ePropertyUseColor,
+ };
+
+ //
+@@ -170,15 +173,49 @@
+ const char *property_path,
+ const char *value)
+ {
++ bool is_load_script = strcmp(property_path,"target.load-script-from-symbol-file") == 0;
++ TargetSP target_sp;
++ LoadScriptFromSymFile load_script_old_value;
++ if (is_load_script && exe_ctx->GetTargetSP())
++ {
++ target_sp = exe_ctx->GetTargetSP();
++ load_script_old_value = target_sp->TargetProperties::GetLoadScriptFromSymbolFile();
++ }
+ Error error (Properties::SetPropertyValue (exe_ctx, op, property_path, value));
+ if (error.Success())
+ {
++ // FIXME it would be nice to have "on-change" callbacks for properties
+ if (strcmp(property_path, g_properties[ePropertyPrompt].name) == 0)
+ {
+ const char *new_prompt = GetPrompt();
++ std::string str = lldb_utility::ansi::FormatAnsiTerminalCodes (new_prompt, GetUseColor());
++ if (str.length())
++ new_prompt = str.c_str();
+ EventSP prompt_change_event_sp (new Event(CommandInterpreter::eBroadcastBitResetPrompt, new EventDataBytes (new_prompt)));
+ GetCommandInterpreter().BroadcastEvent (prompt_change_event_sp);
+ }
++ else if (strcmp(property_path, g_properties[ePropertyUseColor].name) == 0)
++ {
++ // use-color changed. Ping the prompt so it can reset the ansi terminal codes.
++ SetPrompt (GetPrompt());
++ }
++ else if (is_load_script && target_sp && load_script_old_value == eLoadScriptFromSymFileWarn)
++ {
++ if (target_sp->TargetProperties::GetLoadScriptFromSymbolFile() == eLoadScriptFromSymFileTrue)
++ {
++ std::list<Error> errors;
++ StreamString feedback_stream;
++ if (!target_sp->LoadScriptingResources(errors,&feedback_stream))
++ {
++ for (auto error : errors)
++ {
++ GetErrorStream().Printf("%s\n",error.AsCString());
++ }
++ if (feedback_stream.GetSize())
++ GetErrorStream().Printf("%s",feedback_stream.GetData());
++ }
++ }
++ }
+ }
+ return error;
+ }
+@@ -217,6 +254,9 @@
+ const uint32_t idx = ePropertyPrompt;
+ m_collection_sp->SetPropertyAtIndexAsString (NULL, idx, p);
+ const char *new_prompt = GetPrompt();
++ std::string str = lldb_utility::ansi::FormatAnsiTerminalCodes (new_prompt, GetUseColor());
++ if (str.length())
++ new_prompt = str.c_str();
+ EventSP prompt_change_event_sp (new Event(CommandInterpreter::eBroadcastBitResetPrompt, new EventDataBytes (new_prompt)));;
+ GetCommandInterpreter().BroadcastEvent (prompt_change_event_sp);
+ }
+@@ -270,6 +310,22 @@
+ return m_collection_sp->SetPropertyAtIndexAsBoolean (NULL, idx, b);
+ }
+
++bool
++Debugger::GetUseColor () const
++{
++ const uint32_t idx = ePropertyUseColor;
++ return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
++}
++
++bool
++Debugger::SetUseColor (bool b)
++{
++ const uint32_t idx = ePropertyUseColor;
++ bool ret = m_collection_sp->SetPropertyAtIndexAsBoolean (NULL, idx, b);
++ SetPrompt (GetPrompt());
++ return ret;
++}
++
+ uint32_t
+ Debugger::GetStopSourceLineCount (bool before) const
+ {
+@@ -602,6 +658,11 @@
+ OptionValueSInt64 *term_width = m_collection_sp->GetPropertyAtIndexAsOptionValueSInt64 (NULL, ePropertyTerminalWidth);
+ term_width->SetMinimumValue(10);
+ term_width->SetMaximumValue(1024);
++
++ // Turn off use-color if this is a dumb terminal.
++ const char *term = getenv ("TERM");
++ if (term && !strcmp (term, "dumb"))
++ SetUseColor (false);
+ }
+
+ Debugger::~Debugger ()
+@@ -1112,14 +1173,12 @@
+ SymbolContext sc (frame->GetSymbolContext(eSymbolContextEverything));
+ ExecutionContext exe_ctx;
+ frame->CalculateExecutionContext(exe_ctx);
+- const char *end = NULL;
+- if (Debugger::FormatPrompt (prompt_format, &sc, &exe_ctx, &sc.line_entry.range.GetBaseAddress(), s, &end))
++ if (Debugger::FormatPrompt (prompt_format, &sc, &exe_ctx, &sc.line_entry.range.GetBaseAddress(), s))
+ {
+ printf("%s\n", s.GetData());
+ }
+ else
+ {
+- printf ("error: at '%s'\n", end);
+ printf ("what we got: %s\n", s.GetData());
+ }
+ }
+@@ -1296,8 +1355,8 @@
+ return item;
+ }
+
+-bool
+-Debugger::FormatPrompt
++static bool
++FormatPromptRecurse
+ (
+ const char *format,
+ const SymbolContext *sc,
+@@ -1312,6 +1371,7 @@
+ bool success = true;
+ const char *p;
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES));
++
+ for (p = format; *p != '\0'; ++p)
+ {
+ if (realvalobj)
+@@ -1345,8 +1405,8 @@
+ StreamString sub_strm;
+
+ ++p; // Skip the '{'
+-
+- if (FormatPrompt (p, sc, exe_ctx, addr, sub_strm, &p, valobj))
++
++ if (FormatPromptRecurse (p, sc, exe_ctx, addr, sub_strm, &p, valobj))
+ {
+ // The stream had all it needed
+ s.Write(sub_strm.GetData(), sub_strm.GetSize());
+@@ -1684,7 +1744,7 @@
+ if (!special_directions)
+ var_success &= item->DumpPrintableRepresentation(s,val_obj_display, custom_format);
+ else
+- var_success &= FormatPrompt(special_directions, sc, exe_ctx, addr, s, NULL, item);
++ var_success &= FormatPromptRecurse(special_directions, sc, exe_ctx, addr, s, NULL, item);
+
+ if (--max_num_children == 0)
+ {
+@@ -1708,214 +1768,6 @@
+ format_addr = *addr;
+ }
+ }
+- else if (::strncmp (var_name_begin, "ansi.", strlen("ansi.")) == 0)
+- {
+- var_success = true;
+- var_name_begin += strlen("ansi."); // Skip the "ansi."
+- if (::strncmp (var_name_begin, "fg.", strlen("fg.")) == 0)
+- {
+- var_name_begin += strlen("fg."); // Skip the "fg."
+- if (::strncmp (var_name_begin, "black}", strlen("black}")) == 0)
+- {
+- s.Printf ("%s%s%s",
+- lldb_utility::ansi::k_escape_start,
+- lldb_utility::ansi::k_fg_black,
+- lldb_utility::ansi::k_escape_end);
+- }
+- else if (::strncmp (var_name_begin, "red}", strlen("red}")) == 0)
+- {
+- s.Printf ("%s%s%s",
+- lldb_utility::ansi::k_escape_start,
+- lldb_utility::ansi::k_fg_red,
+- lldb_utility::ansi::k_escape_end);
+- }
+- else if (::strncmp (var_name_begin, "green}", strlen("green}")) == 0)
+- {
+- s.Printf ("%s%s%s",
+- lldb_utility::ansi::k_escape_start,
+- lldb_utility::ansi::k_fg_green,
+- lldb_utility::ansi::k_escape_end);
+- }
+- else if (::strncmp (var_name_begin, "yellow}", strlen("yellow}")) == 0)
+- {
+- s.Printf ("%s%s%s",
+- lldb_utility::ansi::k_escape_start,
+- lldb_utility::ansi::k_fg_yellow,
+- lldb_utility::ansi::k_escape_end);
+- }
+- else if (::strncmp (var_name_begin, "blue}", strlen("blue}")) == 0)
+- {
+- s.Printf ("%s%s%s",
+- lldb_utility::ansi::k_escape_start,
+- lldb_utility::ansi::k_fg_blue,
+- lldb_utility::ansi::k_escape_end);
+- }
+- else if (::strncmp (var_name_begin, "purple}", strlen("purple}")) == 0)
+- {
+- s.Printf ("%s%s%s",
+- lldb_utility::ansi::k_escape_start,
+- lldb_utility::ansi::k_fg_purple,
+- lldb_utility::ansi::k_escape_end);
+- }
+- else if (::strncmp (var_name_begin, "cyan}", strlen("cyan}")) == 0)
+- {
+- s.Printf ("%s%s%s",
+- lldb_utility::ansi::k_escape_start,
+- lldb_utility::ansi::k_fg_cyan,
+- lldb_utility::ansi::k_escape_end);
+- }
+- else if (::strncmp (var_name_begin, "white}", strlen("white}")) == 0)
+- {
+- s.Printf ("%s%s%s",
+- lldb_utility::ansi::k_escape_start,
+- lldb_utility::ansi::k_fg_white,
+- lldb_utility::ansi::k_escape_end);
+- }
+- else
+- {
+- var_success = false;
+- }
+- }
+- else if (::strncmp (var_name_begin, "bg.", strlen("bg.")) == 0)
+- {
+- var_name_begin += strlen("bg."); // Skip the "bg."
+- if (::strncmp (var_name_begin, "black}", strlen("black}")) == 0)
+- {
+- s.Printf ("%s%s%s",
+- lldb_utility::ansi::k_escape_start,
+- lldb_utility::ansi::k_bg_black,
+- lldb_utility::ansi::k_escape_end);
+- }
+- else if (::strncmp (var_name_begin, "red}", strlen("red}")) == 0)
+- {
+- s.Printf ("%s%s%s",
+- lldb_utility::ansi::k_escape_start,
+- lldb_utility::ansi::k_bg_red,
+- lldb_utility::ansi::k_escape_end);
+- }
+- else if (::strncmp (var_name_begin, "green}", strlen("green}")) == 0)
+- {
+- s.Printf ("%s%s%s",
+- lldb_utility::ansi::k_escape_start,
+- lldb_utility::ansi::k_bg_green,
+- lldb_utility::ansi::k_escape_end);
+- }
+- else if (::strncmp (var_name_begin, "yellow}", strlen("yellow}")) == 0)
+- {
+- s.Printf ("%s%s%s",
+- lldb_utility::ansi::k_escape_start,
+- lldb_utility::ansi::k_bg_yellow,
+- lldb_utility::ansi::k_escape_end);
+- }
+- else if (::strncmp (var_name_begin, "blue}", strlen("blue}")) == 0)
+- {
+- s.Printf ("%s%s%s",
+- lldb_utility::ansi::k_escape_start,
+- lldb_utility::ansi::k_bg_blue,
+- lldb_utility::ansi::k_escape_end);
+- }
+- else if (::strncmp (var_name_begin, "purple}", strlen("purple}")) == 0)
+- {
+- s.Printf ("%s%s%s",
+- lldb_utility::ansi::k_escape_start,
+- lldb_utility::ansi::k_bg_purple,
+- lldb_utility::ansi::k_escape_end);
+- }
+- else if (::strncmp (var_name_begin, "cyan}", strlen("cyan}")) == 0)
+- {
+- s.Printf ("%s%s%s",
+- lldb_utility::ansi::k_escape_start,
+- lldb_utility::ansi::k_bg_cyan,
+- lldb_utility::ansi::k_escape_end);
+- }
+- else if (::strncmp (var_name_begin, "white}", strlen("white}")) == 0)
+- {
+- s.Printf ("%s%s%s",
+- lldb_utility::ansi::k_escape_start,
+- lldb_utility::ansi::k_bg_white,
+- lldb_utility::ansi::k_escape_end);
+- }
+- else
+- {
+- var_success = false;
+- }
+- }
+- else if (::strncmp (var_name_begin, "normal}", strlen ("normal}")) == 0)
+- {
+- s.Printf ("%s%s%s",
+- lldb_utility::ansi::k_escape_start,
+- lldb_utility::ansi::k_ctrl_normal,
+- lldb_utility::ansi::k_escape_end);
+- }
+- else if (::strncmp (var_name_begin, "bold}", strlen("bold}")) == 0)
+- {
+- s.Printf ("%s%s%s",
+- lldb_utility::ansi::k_escape_start,
+- lldb_utility::ansi::k_ctrl_bold,
+- lldb_utility::ansi::k_escape_end);
+- }
+- else if (::strncmp (var_name_begin, "faint}", strlen("faint}")) == 0)
+- {
+- s.Printf ("%s%s%s",
+- lldb_utility::ansi::k_escape_start,
+- lldb_utility::ansi::k_ctrl_faint,
+- lldb_utility::ansi::k_escape_end);
+- }
+- else if (::strncmp (var_name_begin, "italic}", strlen("italic}")) == 0)
+- {
+- s.Printf ("%s%s%s",
+- lldb_utility::ansi::k_escape_start,
+- lldb_utility::ansi::k_ctrl_italic,
+- lldb_utility::ansi::k_escape_end);
+- }
+- else if (::strncmp (var_name_begin, "underline}", strlen("underline}")) == 0)
+- {
+- s.Printf ("%s%s%s",
+- lldb_utility::ansi::k_escape_start,
+- lldb_utility::ansi::k_ctrl_underline,
+- lldb_utility::ansi::k_escape_end);
+- }
+- else if (::strncmp (var_name_begin, "slow-blink}", strlen("slow-blink}")) == 0)
+- {
+- s.Printf ("%s%s%s",
+- lldb_utility::ansi::k_escape_start,
+- lldb_utility::ansi::k_ctrl_slow_blink,
+- lldb_utility::ansi::k_escape_end);
+- }
+- else if (::strncmp (var_name_begin, "fast-blink}", strlen("fast-blink}")) == 0)
+- {
+- s.Printf ("%s%s%s",
+- lldb_utility::ansi::k_escape_start,
+- lldb_utility::ansi::k_ctrl_fast_blink,
+- lldb_utility::ansi::k_escape_end);
+- }
+- else if (::strncmp (var_name_begin, "negative}", strlen("negative}")) == 0)
+- {
+- s.Printf ("%s%s%s",
+- lldb_utility::ansi::k_escape_start,
+- lldb_utility::ansi::k_ctrl_negative,
+- lldb_utility::ansi::k_escape_end);
+- }
+- else if (::strncmp (var_name_begin, "conceal}", strlen("conceal}")) == 0)
+- {
+- s.Printf ("%s%s%s",
+- lldb_utility::ansi::k_escape_start,
+- lldb_utility::ansi::k_ctrl_conceal,
+- lldb_utility::ansi::k_escape_end);
+-
+- }
+- else if (::strncmp (var_name_begin, "crossed-out}", strlen("crossed-out}")) == 0)
+- {
+- s.Printf ("%s%s%s",
+- lldb_utility::ansi::k_escape_start,
+- lldb_utility::ansi::k_ctrl_crossed_out,
+- lldb_utility::ansi::k_escape_end);
+- }
+- else
+- {
+- var_success = false;
+- }
+- }
+ break;
+
+ case 'p':
+@@ -2604,6 +2456,24 @@
+ return success;
+ }
+
++bool
++Debugger::FormatPrompt
++(
++ const char *format,
++ const SymbolContext *sc,
++ const ExecutionContext *exe_ctx,
++ const Address *addr,
++ Stream &s,
++ ValueObject* valobj
++)
++{
++ bool use_color = exe_ctx ? exe_ctx->GetTargetRef().GetDebugger().GetUseColor() : true;
++ std::string format_str = lldb_utility::ansi::FormatAnsiTerminalCodes (format, use_color);
++ if (format_str.length())
++ format = format_str.c_str();
++ return FormatPromptRecurse (format, sc, exe_ctx, addr, s, NULL, valobj);
++}
++
+ void
+ Debugger::SetLoggingCallback (lldb::LogOutputCallback log_callback, void *baton)
+ {
+Index: source/Core/Makefile
+===================================================================
+--- source/Core/Makefile (revision 183906)
++++ source/Core/Makefile (working copy)
+@@ -17,7 +17,7 @@
+ # (cxa_demangle.cpp) uses dynamic_cast<> and GCC (at least 4.6 and 4.7)
+ # complain if we try to compile it with -fno-rtti.
+ $(info shell basename CXX is $(shell basename $(CXX)))
+-ifeq (g++,$(shell basename $(CXX)))
++ifeq (g++,$(shell basename $(CXX) | colrm 4))
+ $(ObjDir)/cxa_demangle.o: Compile.CXX := $(filter-out -fno-rtti,$(Compile.CXX)) -frtti
+ endif
+
+Index: source/Core/Scalar.cpp
+===================================================================
+--- source/Core/Scalar.cpp (revision 183906)
++++ source/Core/Scalar.cpp (working copy)
+@@ -715,6 +715,28 @@
+ return success;
+ }
+
++bool
++Scalar::MakeSigned ()
++{
++ bool success = false;
++
++ switch (m_type)
++ {
++ case e_void: break;
++ case e_sint: success = true; break;
++ case e_uint: m_type = e_sint; success = true; break;
++ case e_slong: success = true; break;
++ case e_ulong: m_type = e_slong; success = true; break;
++ case e_slonglong: success = true; break;
++ case e_ulonglong: m_type = e_slonglong; success = true; break;
++ case e_float: success = true; break;
++ case e_double: success = true; break;
++ case e_long_double: success = true; break;
++ }
++
++ return success;
++}
++
+ int
+ Scalar::SInt(int fail_value) const
+ {
+Index: source/Core/Value.cpp
+===================================================================
+--- source/Core/Value.cpp (revision 183906)
++++ source/Core/Value.cpp (working copy)
+@@ -339,8 +339,16 @@
+ Address file_so_addr;
+ switch (m_value_type)
+ {
+- default:
+- error.SetErrorStringWithFormat("invalid value type %i", m_value_type);
++ case eValueTypeVector:
++ if (m_context_type == eContextTypeClangType && ast_context)
++ {
++ ClangASTType ptr_type (ast_context, ClangASTContext::GetVoidPtrType(ast_context, false));
++ uint64_t ptr_byte_size = ptr_type.GetClangTypeByteSize();
++ data.SetAddressByteSize (ptr_byte_size);
++ }
++ else
++ data.SetAddressByteSize(sizeof(void *));
++ data.SetData(m_vector.bytes, m_vector.length, m_vector.byte_order);
+ break;
+
+ case eValueTypeScalar:
+Index: source/Breakpoint/BreakpointLocation.cpp
+===================================================================
+--- source/Breakpoint/BreakpointLocation.cpp (revision 183906)
++++ source/Breakpoint/BreakpointLocation.cpp (working copy)
+@@ -46,7 +46,8 @@
+ m_address (addr),
+ m_owner (owner),
+ m_options_ap (),
+- m_bp_site_sp ()
++ m_bp_site_sp (),
++ m_condition_mutex ()
+ {
+ SetThreadID (tid);
+ m_being_created = false;
+@@ -249,6 +250,8 @@
+ BreakpointLocation::ConditionSaysStop (ExecutionContext &exe_ctx, Error &error)
+ {
+ Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS);
++
++ Mutex::Locker evaluation_locker(m_condition_mutex);
+
+ size_t condition_hash;
+ const char *condition_text = GetConditionText(&condition_hash);
+@@ -312,6 +315,12 @@
+
+ if (result_code == eExecutionCompleted)
+ {
++ if (!result_variable_sp)
++ {
++ ret = false;
++ error.SetErrorString("Expression did not return a result");
++ }
++
+ result_value_sp = result_variable_sp->GetValueObject();
+
+ if (result_value_sp)
+Index: source/Expression/Materializer.cpp
+===================================================================
+--- source/Expression/Materializer.cpp (revision 183906)
++++ source/Expression/Materializer.cpp (working copy)
+@@ -89,8 +89,7 @@
+
+ if (!allocate_error.Success())
+ {
+- err.SetErrorToGenericError();
+- err.SetErrorStringWithFormat("Couldn't allocate a memory area to store %s: %s", m_persistent_variable_sp->GetName().GetCString(), allocate_error.AsCString());
++ err.SetErrorStringWithFormat("couldn't allocate a memory area to store %s: %s", m_persistent_variable_sp->GetName().GetCString(), allocate_error.AsCString());
+ return;
+ }
+
+@@ -110,7 +109,11 @@
+ // Clear the flag if the variable will never be deallocated.
+
+ if (m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVKeepInTarget)
++ {
++ Error leak_error;
++ map.Leak(mem, leak_error);
+ m_persistent_variable_sp->m_flags &= ~ClangExpressionVariable::EVNeedsAllocation;
++ }
+
+ // Write the contents of the variable to the area.
+
+@@ -123,8 +126,7 @@
+
+ if (!write_error.Success())
+ {
+- err.SetErrorToGenericError();
+- err.SetErrorStringWithFormat ("Couldn't write %s to the target: %s", m_persistent_variable_sp->GetName().AsCString(),
++ err.SetErrorStringWithFormat ("couldn't write %s to the target: %s", m_persistent_variable_sp->GetName().AsCString(),
+ write_error.AsCString());
+ return;
+ }
+@@ -140,8 +142,7 @@
+
+ if (!deallocate_error.Success())
+ {
+- err.SetErrorToGenericError();
+- err.SetErrorStringWithFormat ("Couldn't deallocate memory for %s: %s", m_persistent_variable_sp->GetName().GetCString(), deallocate_error.AsCString());
++ err.SetErrorStringWithFormat ("couldn't deallocate memory for %s: %s", m_persistent_variable_sp->GetName().GetCString(), deallocate_error.AsCString());
+ }
+ }
+
+@@ -151,7 +152,7 @@
+
+ if (log)
+ {
+- log->Printf("EntityPersistentVariable::Materialize [process_address = 0x%llx, m_name = %s, m_flags = 0x%hx]",
++ log->Printf("EntityPersistentVariable::Materialize [process_address = 0x%" PRIx64 ", m_name = %s, m_flags = 0x%hx]",
+ (uint64_t)process_address,
+ m_persistent_variable_sp->GetName().AsCString(),
+ m_persistent_variable_sp->m_flags);
+@@ -178,14 +179,12 @@
+
+ if (!write_error.Success())
+ {
+- err.SetErrorToGenericError();
+- err.SetErrorStringWithFormat("Couldn't write the location of %s to memory: %s", m_persistent_variable_sp->GetName().AsCString(), write_error.AsCString());
++ err.SetErrorStringWithFormat("couldn't write the location of %s to memory: %s", m_persistent_variable_sp->GetName().AsCString(), write_error.AsCString());
+ }
+ }
+ else
+ {
+- err.SetErrorToGenericError();
+- err.SetErrorStringWithFormat("No materialization happened for persistent variable %s", m_persistent_variable_sp->GetName().AsCString());
++ err.SetErrorStringWithFormat("no materialization happened for persistent variable %s", m_persistent_variable_sp->GetName().AsCString());
+ return;
+ }
+ }
+@@ -197,7 +196,7 @@
+
+ if (log)
+ {
+- log->Printf("EntityPersistentVariable::Dematerialize [process_address = 0x%llx, m_name = %s, m_flags = 0x%hx]",
++ log->Printf("EntityPersistentVariable::Dematerialize [process_address = 0x%" PRIx64 ", m_name = %s, m_flags = 0x%hx]",
+ (uint64_t)process_address,
+ m_persistent_variable_sp->GetName().AsCString(),
+ m_persistent_variable_sp->m_flags);
+@@ -219,8 +218,7 @@
+
+ if (!read_error.Success())
+ {
+- err.SetErrorToGenericError();
+- err.SetErrorStringWithFormat("Couldn't read the address of program-allocated variable %s: %s", m_persistent_variable_sp->GetName().GetCString(), read_error.AsCString());
++ err.SetErrorStringWithFormat("couldn't read the address of program-allocated variable %s: %s", m_persistent_variable_sp->GetName().GetCString(), read_error.AsCString());
+ return;
+ }
+
+@@ -251,15 +249,13 @@
+
+ if (!m_persistent_variable_sp->m_live_sp)
+ {
+- err.SetErrorToGenericError();
+- err.SetErrorStringWithFormat("Couldn't find the memory area used to store %s", m_persistent_variable_sp->GetName().GetCString());
++ err.SetErrorStringWithFormat("couldn't find the memory area used to store %s", m_persistent_variable_sp->GetName().GetCString());
+ return;
+ }
+
+ if (m_persistent_variable_sp->m_live_sp->GetValue().GetValueAddressType() != eAddressTypeLoad)
+ {
+- err.SetErrorToGenericError();
+- err.SetErrorStringWithFormat("The address of the memory area for %s is in an incorrect format", m_persistent_variable_sp->GetName().GetCString());
++ err.SetErrorStringWithFormat("the address of the memory area for %s is in an incorrect format", m_persistent_variable_sp->GetName().GetCString());
+ return;
+ }
+
+@@ -282,8 +278,7 @@
+
+ if (!read_error.Success())
+ {
+- err.SetErrorToGenericError();
+- err.SetErrorStringWithFormat ("Couldn't read the contents of %s from memory: %s", m_persistent_variable_sp->GetName().GetCString(), read_error.AsCString());
++ err.SetErrorStringWithFormat ("couldn't read the contents of %s from memory: %s", m_persistent_variable_sp->GetName().GetCString(), read_error.AsCString());
+ return;
+ }
+
+@@ -292,8 +287,7 @@
+ }
+ else
+ {
+- err.SetErrorToGenericError();
+- err.SetErrorStringWithFormat("No dematerialization happened for persistent variable %s", m_persistent_variable_sp->GetName().AsCString());
++ err.SetErrorStringWithFormat("no dematerialization happened for persistent variable %s", m_persistent_variable_sp->GetName().AsCString());
+ return;
+ }
+
+@@ -324,7 +318,7 @@
+
+ Error err;
+
+- dump_stream.Printf("0x%llx: EntityPersistentVariable (%s)\n", (unsigned long long)process_address + m_offset, m_persistent_variable_sp->GetName().AsCString());
++ dump_stream.Printf("0x%" PRIx64 ": EntityPersistentVariable (%s)\n", process_address + m_offset, m_persistent_variable_sp->GetName().AsCString());
+
+ {
+ dump_stream.Printf("Pointer:\n");
+@@ -421,7 +415,7 @@
+
+ if (log)
+ {
+- log->Printf("EntityVariable::Materialize [process_address = 0x%llx, m_variable_sp = %s]",
++ log->Printf("EntityVariable::Materialize [process_address = 0x%" PRIx64 ", m_variable_sp = %s]",
+ (uint64_t)process_address,
+ m_variable_sp->GetName().AsCString());
+ }
+@@ -435,8 +429,7 @@
+
+ if (!valobj_sp)
+ {
+- err.SetErrorToGenericError();
+- err.SetErrorStringWithFormat("Couldn't get a value object for variable %s", m_variable_sp->GetName().AsCString());
++ err.SetErrorStringWithFormat("couldn't get a value object for variable %s", m_variable_sp->GetName().AsCString());
+ return;
+ }
+
+@@ -452,8 +445,7 @@
+
+ if (!write_error.Success())
+ {
+- err.SetErrorToGenericError();
+- err.SetErrorStringWithFormat("Couldn't write the contents of reference variable %s to memory: %s", m_variable_sp->GetName().AsCString(), write_error.AsCString());
++ err.SetErrorStringWithFormat("couldn't write the contents of reference variable %s to memory: %s", m_variable_sp->GetName().AsCString(), write_error.AsCString());
+ return;
+ }
+ }
+@@ -473,8 +465,7 @@
+
+ if (!write_error.Success())
+ {
+- err.SetErrorToGenericError();
+- err.SetErrorStringWithFormat("Couldn't write the address of variable %s to memory: %s", m_variable_sp->GetName().AsCString(), write_error.AsCString());
++ err.SetErrorStringWithFormat("couldn't write the address of variable %s to memory: %s", m_variable_sp->GetName().AsCString(), write_error.AsCString());
+ return;
+ }
+ }
+@@ -485,15 +476,20 @@
+
+ if (m_temporary_allocation != LLDB_INVALID_ADDRESS)
+ {
+- err.SetErrorToGenericError();
+- err.SetErrorStringWithFormat("Trying to create a temporary region for %s but one exists", m_variable_sp->GetName().AsCString());
++ err.SetErrorStringWithFormat("trying to create a temporary region for %s but one exists", m_variable_sp->GetName().AsCString());
+ return;
+ }
+
+ if (data.GetByteSize() != m_variable_sp->GetType()->GetByteSize())
+ {
+- err.SetErrorToGenericError();
+- err.SetErrorStringWithFormat("Size of variable %s disagrees with the ValueObject's size", m_variable_sp->GetName().AsCString());
++ if (data.GetByteSize() == 0 && m_variable_sp->LocationExpression().IsValid() == false)
++ {
++ err.SetErrorStringWithFormat("the variable '%s' has no location, it may have been optimized out", m_variable_sp->GetName().AsCString());
++ }
++ else
++ {
++ err.SetErrorStringWithFormat("size of variable %s disagrees with the ValueObject's size", m_variable_sp->GetName().AsCString());
++ }
+ return;
+ }
+
+@@ -507,8 +503,7 @@
+
+ if (!alloc_error.Success())
+ {
+- err.SetErrorToGenericError();
+- err.SetErrorStringWithFormat("Couldn't allocate a temporary region for %s: %s", m_variable_sp->GetName().AsCString(), alloc_error.AsCString());
++ err.SetErrorStringWithFormat("couldn't allocate a temporary region for %s: %s", m_variable_sp->GetName().AsCString(), alloc_error.AsCString());
+ return;
+ }
+
+@@ -518,8 +513,7 @@
+
+ if (!write_error.Success())
+ {
+- err.SetErrorToGenericError();
+- err.SetErrorStringWithFormat("Couldn't write to the temporary region for %s: %s", m_variable_sp->GetName().AsCString(), write_error.AsCString());
++ err.SetErrorStringWithFormat("couldn't write to the temporary region for %s: %s", m_variable_sp->GetName().AsCString(), write_error.AsCString());
+ return;
+ }
+
+@@ -529,8 +523,7 @@
+
+ if (!pointer_write_error.Success())
+ {
+- err.SetErrorToGenericError();
+- err.SetErrorStringWithFormat("Couldn't write the address of the temporary region for %s: %s", m_variable_sp->GetName().AsCString(), pointer_write_error.AsCString());
++ err.SetErrorStringWithFormat("couldn't write the address of the temporary region for %s: %s", m_variable_sp->GetName().AsCString(), pointer_write_error.AsCString());
+ }
+ }
+ }
+@@ -543,7 +536,7 @@
+
+ if (log)
+ {
+- log->Printf("EntityVariable::Dematerialize [process_address = 0x%llx, m_variable_sp = %s]",
++ log->Printf("EntityVariable::Dematerialize [process_address = 0x%" PRIx64 ", m_variable_sp = %s]",
+ (uint64_t)process_address,
+ m_variable_sp->GetName().AsCString());
+ }
+@@ -559,8 +552,7 @@
+
+ if (!valobj_sp)
+ {
+- err.SetErrorToGenericError();
+- err.SetErrorStringWithFormat("Couldn't get a value object for variable %s", m_variable_sp->GetName().AsCString());
++ err.SetErrorStringWithFormat("couldn't get a value object for variable %s", m_variable_sp->GetName().AsCString());
+ return;
+ }
+
+@@ -572,8 +564,7 @@
+
+ if (!extract_error.Success())
+ {
+- err.SetErrorToGenericError();
+- err.SetErrorStringWithFormat("Couldn't get the data for variable %s", m_variable_sp->GetName().AsCString());
++ err.SetErrorStringWithFormat("couldn't get the data for variable %s", m_variable_sp->GetName().AsCString());
+ return;
+ }
+
+@@ -583,8 +574,7 @@
+
+ if (!set_error.Success())
+ {
+- err.SetErrorToGenericError();
+- err.SetErrorStringWithFormat("Couldn't write the new contents of %s back into the variable", m_variable_sp->GetName().AsCString());
++ err.SetErrorStringWithFormat("couldn't write the new contents of %s back into the variable", m_variable_sp->GetName().AsCString());
+ return;
+ }
+
+@@ -594,8 +584,7 @@
+
+ if (!free_error.Success())
+ {
+- err.SetErrorToGenericError();
+- err.SetErrorStringWithFormat("Couldn't free the temporary region for %s: %s", m_variable_sp->GetName().AsCString(), free_error.AsCString());
++ err.SetErrorStringWithFormat("couldn't free the temporary region for %s: %s", m_variable_sp->GetName().AsCString(), free_error.AsCString());
+ return;
+ }
+
+@@ -608,7 +597,7 @@
+ {
+ StreamString dump_stream;
+
+- dump_stream.Printf("0x%llx: EntityVariable\n", (unsigned long long)process_address + m_offset);
++ dump_stream.Printf("0x%" PRIx64 ": EntityVariable\n", process_address + m_offset);
+
+ Error err;
+
+@@ -727,7 +716,6 @@
+ {
+ if (m_temporary_allocation != LLDB_INVALID_ADDRESS)
+ {
+- err.SetErrorToGenericError();
+ err.SetErrorString("Trying to create a temporary region for the result but one exists");
+ return;
+ }
+@@ -743,8 +731,7 @@
+
+ if (!alloc_error.Success())
+ {
+- err.SetErrorToGenericError();
+- err.SetErrorStringWithFormat("Couldn't allocate a temporary region for the result: %s", alloc_error.AsCString());
++ err.SetErrorStringWithFormat("couldn't allocate a temporary region for the result: %s", alloc_error.AsCString());
+ return;
+ }
+
+@@ -754,8 +741,7 @@
+
+ if (!pointer_write_error.Success())
+ {
+- err.SetErrorToGenericError();
+- err.SetErrorStringWithFormat("Couldn't write the address of the temporary region for the result: %s", pointer_write_error.AsCString());
++ err.SetErrorStringWithFormat("couldn't write the address of the temporary region for the result: %s", pointer_write_error.AsCString());
+ }
+ }
+ }
+@@ -763,7 +749,6 @@
+ void Dematerialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address,
+ lldb::addr_t frame_top, lldb::addr_t frame_bottom, Error &err)
+ {
+- err.SetErrorToGenericError();
+ err.SetErrorString("Tried to detmaterialize a result variable with the normal Dematerialize method");
+ }
+
+@@ -777,7 +762,6 @@
+
+ if (!exe_scope)
+ {
+- err.SetErrorToGenericError();
+ err.SetErrorString("Couldn't dematerialize a result variable: invalid execution context scope");
+ return;
+ }
+@@ -789,7 +773,6 @@
+
+ if (!read_error.Success())
+ {
+- err.SetErrorToGenericError();
+ err.SetErrorString("Couldn't dematerialize a result variable: couldn't read its address");
+ return;
+ }
+@@ -798,7 +781,6 @@
+
+ if (!target_sp)
+ {
+- err.SetErrorToGenericError();
+ err.SetErrorString("Couldn't dematerialize a result variable: no target");
+ return;
+ }
+@@ -815,8 +797,7 @@
+
+ if (!ret)
+ {
+- err.SetErrorToGenericError();
+- err.SetErrorStringWithFormat("Couldn't dematerialize a result variable: failed to make persistent variable %s", name.AsCString());
++ err.SetErrorStringWithFormat("couldn't dematerialize a result variable: failed to make persistent variable %s", name.AsCString());
+ return;
+ }
+
+@@ -844,7 +825,6 @@
+
+ if (!read_error.Success())
+ {
+- err.SetErrorToGenericError();
+ err.SetErrorString("Couldn't dematerialize a result variable: couldn't read its memory");
+ return;
+ }
+@@ -874,7 +854,7 @@
+ {
+ StreamString dump_stream;
+
+- dump_stream.Printf("0x%llx: EntityResultVariable\n", (unsigned long long)process_address + m_offset);
++ dump_stream.Printf("0x%" PRIx64 ": EntityResultVariable\n", process_address + m_offset);
+
+ Error err;
+
+@@ -991,7 +971,7 @@
+
+ if (log)
+ {
+- log->Printf("EntitySymbol::Materialize [process_address = 0x%llx, m_symbol = %s]",
++ log->Printf("EntitySymbol::Materialize [process_address = 0x%" PRIx64 ", m_symbol = %s]",
+ (uint64_t)process_address,
+ m_symbol.GetName().AsCString());
+ }
+@@ -1007,8 +987,7 @@
+
+ if (!target_sp)
+ {
+- err.SetErrorToGenericError();
+- err.SetErrorStringWithFormat("Couldn't resolve symbol %s because there is no target", m_symbol.GetName().AsCString());
++ err.SetErrorStringWithFormat("couldn't resolve symbol %s because there is no target", m_symbol.GetName().AsCString());
+ return;
+ }
+
+@@ -1023,8 +1002,7 @@
+
+ if (!pointer_write_error.Success())
+ {
+- err.SetErrorToGenericError();
+- err.SetErrorStringWithFormat("Couldn't write the address of symbol %s: %s", m_symbol.GetName().AsCString(), pointer_write_error.AsCString());
++ err.SetErrorStringWithFormat("couldn't write the address of symbol %s: %s", m_symbol.GetName().AsCString(), pointer_write_error.AsCString());
+ return;
+ }
+ }
+@@ -1036,7 +1014,7 @@
+
+ if (log)
+ {
+- log->Printf("EntitySymbol::Dematerialize [process_address = 0x%llx, m_symbol = %s]",
++ log->Printf("EntitySymbol::Dematerialize [process_address = 0x%" PRIx64 ", m_symbol = %s]",
+ (uint64_t)process_address,
+ m_symbol.GetName().AsCString());
+ }
+@@ -1050,7 +1028,7 @@
+
+ Error err;
+
+- dump_stream.Printf("0x%llx: EntitySymbol (%s)\n", (unsigned long long)process_address + m_offset, m_symbol.GetName().AsCString());
++ dump_stream.Printf("0x%" PRIx64 ": EntitySymbol (%s)\n", process_address + m_offset, m_symbol.GetName().AsCString());
+
+ {
+ dump_stream.Printf("Pointer:\n");
+@@ -1111,7 +1089,7 @@
+
+ if (log)
+ {
+- log->Printf("EntityRegister::Materialize [process_address = 0x%llx, m_register_info = %s]",
++ log->Printf("EntityRegister::Materialize [process_address = 0x%" PRIx64 ", m_register_info = %s]",
+ (uint64_t)process_address,
+ m_register_info.name);
+ }
+@@ -1120,8 +1098,7 @@
+
+ if (!frame_sp.get())
+ {
+- err.SetErrorToGenericError();
+- err.SetErrorStringWithFormat("Couldn't materialize register %s without a stack frame", m_register_info.name);
++ err.SetErrorStringWithFormat("couldn't materialize register %s without a stack frame", m_register_info.name);
+ return;
+ }
+
+@@ -1129,8 +1106,7 @@
+
+ if (!reg_context_sp->ReadRegister(&m_register_info, reg_value))
+ {
+- err.SetErrorToGenericError();
+- err.SetErrorStringWithFormat("Couldn't read the value of register %s", m_register_info.name);
++ err.SetErrorStringWithFormat("couldn't read the value of register %s", m_register_info.name);
+ return;
+ }
+
+@@ -1138,15 +1114,13 @@
+
+ if (!reg_value.GetData(register_data))
+ {
+- err.SetErrorToGenericError();
+- err.SetErrorStringWithFormat("Couldn't get the data for register %s", m_register_info.name);
++ err.SetErrorStringWithFormat("couldn't get the data for register %s", m_register_info.name);
+ return;
+ }
+
+ if (register_data.GetByteSize() != m_register_info.byte_size)
+ {
+- err.SetErrorToGenericError();
+- err.SetErrorStringWithFormat("Data for register %s had size %llu but we expected %llu", m_register_info.name, (unsigned long long)register_data.GetByteSize(), (unsigned long long)m_register_info.byte_size);
++ err.SetErrorStringWithFormat("data for register %s had size %llu but we expected %llu", m_register_info.name, (unsigned long long)register_data.GetByteSize(), (unsigned long long)m_register_info.byte_size);
+ return;
+ }
+
+@@ -1156,8 +1130,7 @@
+
+ if (!write_error.Success())
+ {
+- err.SetErrorToGenericError();
+- err.SetErrorStringWithFormat("Couldn't write the contents of register %s: %s", m_register_info.name, write_error.AsCString());
++ err.SetErrorStringWithFormat("couldn't write the contents of register %s: %s", m_register_info.name, write_error.AsCString());
+ return;
+ }
+ }
+@@ -1169,7 +1142,7 @@
+
+ if (log)
+ {
+- log->Printf("EntityRegister::Dematerialize [process_address = 0x%llx, m_register_info = %s]",
++ log->Printf("EntityRegister::Dematerialize [process_address = 0x%" PRIx64 ", m_register_info = %s]",
+ (uint64_t)process_address,
+ m_register_info.name);
+ }
+@@ -1180,8 +1153,7 @@
+
+ if (!frame_sp.get())
+ {
+- err.SetErrorToGenericError();
+- err.SetErrorStringWithFormat("Couldn't dematerialize register %s without a stack frame", m_register_info.name);
++ err.SetErrorStringWithFormat("couldn't dematerialize register %s without a stack frame", m_register_info.name);
+ return;
+ }
+
+@@ -1191,8 +1163,7 @@
+
+ if (!extract_error.Success())
+ {
+- err.SetErrorToGenericError();
+- err.SetErrorStringWithFormat("Couldn't get the data for register %s: %s", m_register_info.name, extract_error.AsCString());
++ err.SetErrorStringWithFormat("couldn't get the data for register %s: %s", m_register_info.name, extract_error.AsCString());
+ return;
+ }
+
+@@ -1200,8 +1171,7 @@
+
+ if (!reg_context_sp->WriteRegister(&m_register_info, register_value))
+ {
+- err.SetErrorToGenericError();
+- err.SetErrorStringWithFormat("Couldn't write the value of register %s", m_register_info.name);
++ err.SetErrorStringWithFormat("couldn't write the value of register %s", m_register_info.name);
+ return;
+ }
+ }
+@@ -1212,7 +1182,7 @@
+
+ Error err;
+
+- dump_stream.Printf("0x%llx: EntityRegister (%s)\n", (unsigned long long)process_address + m_offset, m_register_info.name);
++ dump_stream.Printf("0x%" PRIx64 ": EntityRegister (%s)\n", process_address + m_offset, m_register_info.name);
+
+ {
+ dump_stream.Printf("Value:\n");
+@@ -1305,7 +1275,7 @@
+
+ if (Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
+ {
+- log->Printf("Materializer::Materialize (frame_sp = %p, process_address = 0x%llx) materialized:", frame_sp.get(), process_address);
++ log->Printf("Materializer::Materialize (frame_sp = %p, process_address = 0x%" PRIx64 ") materialized:", frame_sp.get(), process_address);
+ for (EntityUP &entity_up : m_entities)
+ entity_up->DumpToLog(map, process_address, log);
+ }
+@@ -1337,7 +1307,7 @@
+ {
+ if (Log *log =lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
+ {
+- log->Printf("Materializer::Dematerialize (frame_sp = %p, process_address = 0x%llx) about to dematerialize:", frame_sp.get(), m_process_address);
++ log->Printf("Materializer::Dematerialize (frame_sp = %p, process_address = 0x%" PRIx64 ") about to dematerialize:", frame_sp.get(), m_process_address);
+ for (EntityUP &entity_up : m_materializer->m_entities)
+ entity_up->DumpToLog(*m_map, m_process_address, log);
+ }
+Index: source/Expression/ClangExpressionDeclMap.cpp
+===================================================================
+--- source/Expression/ClangExpressionDeclMap.cpp (revision 183906)
++++ source/Expression/ClangExpressionDeclMap.cpp (working copy)
+@@ -1493,13 +1493,7 @@
+ return NULL;
+ }
+ }
+- else if (!var_location_expr.Evaluate(&m_parser_vars->m_exe_ctx, ast, NULL, NULL, NULL, loclist_base_load_addr, NULL, *var_location.get(), &err))
+- {
+- if (log)
+- log->Printf("Error evaluating location: %s", err.AsCString());
+- return NULL;
+- }
+-
++
+ void *type_to_use = NULL;
+
+ if (parser_ast_context)
+Index: source/Expression/IRInterpreter.cpp
+===================================================================
+--- source/Expression/IRInterpreter.cpp (revision 183906)
++++ source/Expression/IRInterpreter.cpp (working copy)
+@@ -151,10 +151,12 @@
+
+ if (constant)
+ {
+- if (const ConstantInt *constant_int = dyn_cast<ConstantInt>(constant))
+- {
+- return AssignToMatchType(scalar, constant_int->getLimitedValue(), value->getType());
+- }
++ APInt value_apint;
++
++ if (!ResolveConstantValue(value_apint, constant))
++ return false;
++
++ return AssignToMatchType(scalar, value_apint.getLimitedValue(), value->getType());
+ }
+ else
+ {
+@@ -496,6 +498,7 @@
+ case Instruction::Or:
+ case Instruction::Ret:
+ case Instruction::SDiv:
++ case Instruction::SExt:
+ case Instruction::Shl:
+ case Instruction::SRem:
+ case Instruction::Store:
+@@ -662,12 +665,16 @@
+ result = L - R;
+ break;
+ case Instruction::SDiv:
++ L.MakeSigned();
++ R.MakeSigned();
+ result = L / R;
+ break;
+ case Instruction::UDiv:
+ result = L.GetRawBits64(0) / R.GetRawBits64(1);
+ break;
+ case Instruction::SRem:
++ L.MakeSigned();
++ R.MakeSigned();
+ result = L % R;
+ break;
+ case Instruction::URem:
+@@ -778,8 +785,8 @@
+ if (log)
+ {
+ log->Printf("Interpreted an AllocaInst");
+- log->Printf(" R : 0x%llx", R);
+- log->Printf(" P : 0x%llx", P);
++ log->Printf(" R : 0x%" PRIx64, R);
++ log->Printf(" P : 0x%" PRIx64, P);
+ }
+ }
+ break;
+@@ -813,6 +820,39 @@
+ frame.AssignValue(inst, S, module);
+ }
+ break;
++ case Instruction::SExt:
++ {
++ const CastInst *cast_inst = dyn_cast<CastInst>(inst);
++
++ if (!cast_inst)
++ {
++ if (log)
++ log->Printf("getOpcode() returns %s, but instruction is not a BitCastInst", cast_inst->getOpcodeName());
++ error.SetErrorToGenericError();
++ error.SetErrorString(interpreter_internal_error);
++ return false;
++ }
++
++ Value *source = cast_inst->getOperand(0);
++
++ lldb_private::Scalar S;
++
++ if (!frame.EvaluateValue(S, source, module))
++ {
++ if (log)
++ log->Printf("Couldn't evaluate %s", PrintValue(source).c_str());
++ error.SetErrorToGenericError();
++ error.SetErrorString(bad_value_error);
++ return false;
++ }
++
++ S.MakeSigned();
++
++ lldb_private::Scalar S_signextend(S.SLongLong());
++
++ frame.AssignValue(inst, S_signextend, module);
++ }
++ break;
+ case Instruction::Br:
+ {
+ const BranchInst *br_inst = dyn_cast<BranchInst>(inst);
+@@ -1004,15 +1044,23 @@
+ result = (L.GetRawBits64(0) <= R.GetRawBits64(0));
+ break;
+ case CmpInst::ICMP_SGT:
++ L.MakeSigned();
++ R.MakeSigned();
+ result = (L > R);
+ break;
+ case CmpInst::ICMP_SGE:
++ L.MakeSigned();
++ R.MakeSigned();
+ result = (L >= R);
+ break;
+ case CmpInst::ICMP_SLT:
++ L.MakeSigned();
++ R.MakeSigned();
+ result = (L < R);
+ break;
+ case CmpInst::ICMP_SLE:
++ L.MakeSigned();
++ R.MakeSigned();
+ result = (L <= R);
+ break;
+ }
+@@ -1195,9 +1243,9 @@
+ if (log)
+ {
+ log->Printf("Interpreted a LoadInst");
+- log->Printf(" P : 0x%llx", P);
+- log->Printf(" R : 0x%llx", R);
+- log->Printf(" D : 0x%llx", D);
++ log->Printf(" P : 0x%" PRIx64, P);
++ log->Printf(" R : 0x%" PRIx64, R);
++ log->Printf(" D : 0x%" PRIx64, D);
+ }
+ }
+ break;
+@@ -1295,9 +1343,9 @@
+ if (log)
+ {
+ log->Printf("Interpreted a StoreInst");
+- log->Printf(" D : 0x%llx", D);
+- log->Printf(" P : 0x%llx", P);
+- log->Printf(" R : 0x%llx", R);
++ log->Printf(" D : 0x%" PRIx64, D);
++ log->Printf(" P : 0x%" PRIx64, P);
++ log->Printf(" R : 0x%" PRIx64, R);
+ }
+ }
+ break;
+Index: source/Expression/IRMemoryMap.cpp
+===================================================================
+--- source/Expression/IRMemoryMap.cpp (revision 183906)
++++ source/Expression/IRMemoryMap.cpp (working copy)
+@@ -31,19 +31,17 @@
+
+ if (process_sp)
+ {
+- for (AllocationMap::value_type &allocation : m_allocations)
++ AllocationMap::iterator iter;
++
++ Error err;
++
++ while ((iter = m_allocations.begin()) != m_allocations.end())
+ {
+- if (allocation.second.m_policy == eAllocationPolicyMirror ||
+- allocation.second.m_policy == eAllocationPolicyProcessOnly ||
+- (allocation.second.m_policy == eAllocationPolicyHostOnly && process_sp->CanJIT()))
+- process_sp->DeallocateMemory(allocation.second.m_process_alloc);
+-
+- if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
+- {
+- log->Printf("IRMemoryMap::~IRMemoryMap deallocated [0x%llx..0x%llx)",
+- (uint64_t)allocation.second.m_process_start,
+- (uint64_t)allocation.second.m_process_start + (uint64_t)allocation.second.m_size);
+- }
++ err.Clear();
++ if (iter->second.m_leak)
++ m_allocations.erase(iter);
++ else
++ Free(iter->first, err);
+ }
+ }
+ }
+@@ -68,6 +66,14 @@
+ return ret;
+ }
+
++ if (process_sp)
++ {
++ ret = process_sp->GetReservationCache().Find(size);
++
++ if (ret != LLDB_INVALID_ADDRESS)
++ return ret;
++ }
++
+ for (int iterations = 0; iterations < 16; ++iterations)
+ {
+ lldb::addr_t candidate = LLDB_INVALID_ADDRESS;
+@@ -106,6 +112,11 @@
+ continue;
+
+ ret = candidate;
++
++ if (process_sp)
++ process_sp->GetReservationCache().Reserve(candidate, size);
++
++ return ret;
+ }
+
+ return ret;
+@@ -349,7 +360,7 @@
+ break;
+ }
+
+- log->Printf("IRMemoryMap::Malloc (%llu, 0x%llx, 0x%llx, %s) -> 0x%llx",
++ log->Printf("IRMemoryMap::Malloc (%" PRIu64 ", 0x%" PRIx64 ", 0x%" PRIx64 ", %s) -> 0x%" PRIx64,
+ (uint64_t)allocation_size,
+ (uint64_t)alignment,
+ (uint64_t)permissions,
+@@ -361,6 +372,25 @@
+ }
+
+ void
++IRMemoryMap::Leak (lldb::addr_t process_address, Error &error)
++{
++ error.Clear();
++
++ AllocationMap::iterator iter = m_allocations.find(process_address);
++
++ if (iter == m_allocations.end())
++ {
++ error.SetErrorToGenericError();
++ error.SetErrorString("Couldn't leak: allocation doesn't exist");
++ return;
++ }
++
++ Allocation &allocation = iter->second;
++
++ allocation.m_leak = true;
++}
++
++void
+ IRMemoryMap::Free (lldb::addr_t process_address, Error &error)
+ {
+ error.Clear();
+@@ -382,9 +412,14 @@
+ case eAllocationPolicyHostOnly:
+ {
+ lldb::ProcessSP process_sp = m_process_wp.lock();
+- if (process_sp && process_sp->CanJIT())
+- process_sp->DeallocateMemory(allocation.m_process_alloc); // FindSpace allocated this for real
+-
++ if (process_sp)
++ {
++ if (process_sp->CanJIT())
++ process_sp->DeallocateMemory(allocation.m_process_alloc); // FindSpace allocated this for real
++ else
++ process_sp->GetReservationCache().Unreserve(allocation.m_process_alloc); // FindSpace registered this memory
++ }
++
+ break;
+ }
+ case eAllocationPolicyMirror:
+@@ -398,7 +433,7 @@
+
+ if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
+ {
+- log->Printf("IRMemoryMap::Free (0x%llx) freed [0x%llx..0x%llx)",
++ log->Printf("IRMemoryMap::Free (0x%" PRIx64 ") freed [0x%" PRIx64 "..0x%" PRIx64 ")",
+ (uint64_t)process_address,
+ iter->second.m_process_start,
+ iter->second.m_process_start + iter->second.m_size);
+@@ -479,7 +514,7 @@
+
+ if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
+ {
+- log->Printf("IRMemoryMap::WriteMemory (0x%llx, 0x%llx, 0x%lld) went to [0x%llx..0x%llx)",
++ log->Printf("IRMemoryMap::WriteMemory (0x%" PRIx64 ", 0x%" PRIx64 ", 0x%" PRId64 ") went to [0x%" PRIx64 "..0x%" PRIx64 ")",
+ (uint64_t)process_address,
+ (uint64_t)bytes,
+ (uint64_t)size,
+@@ -612,7 +647,7 @@
+
+ if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
+ {
+- log->Printf("IRMemoryMap::ReadMemory (0x%llx, 0x%llx, 0x%lld) came from [0x%llx..0x%llx)",
++ log->Printf("IRMemoryMap::ReadMemory (0x%" PRIx64 ", 0x%" PRIx64 ", 0x%" PRId64 ") came from [0x%" PRIx64 "..0x%" PRIx64 ")",
+ (uint64_t)process_address,
+ (uint64_t)bytes,
+ (uint64_t)size,
+@@ -642,7 +677,7 @@
+ {
+ default:
+ error.SetErrorToGenericError();
+- error.SetErrorStringWithFormat("Couldn't read scalar: unsupported size %lld", (unsigned long long)size);
++ error.SetErrorStringWithFormat("Couldn't read scalar: unsupported size %" PRIu64, (uint64_t)size);
+ return;
+ case 1: scalar = extractor.GetU8(&offset); break;
+ case 2: scalar = extractor.GetU16(&offset); break;
+@@ -686,7 +721,7 @@
+ if (iter == m_allocations.end())
+ {
+ error.SetErrorToGenericError();
+- error.SetErrorStringWithFormat("Couldn't find an allocation containing [0x%llx..0x%llx)", (unsigned long long)process_address, (unsigned long long)(process_address + size));
++ error.SetErrorStringWithFormat("Couldn't find an allocation containing [0x%" PRIx64 "..0x%" PRIx64 ")", process_address, process_address + size);
+ return;
+ }
+
+Index: source/Expression/ClangExpressionParser.cpp
+===================================================================
+--- source/Expression/ClangExpressionParser.cpp (revision 183906)
++++ source/Expression/ClangExpressionParser.cpp (working copy)
+@@ -550,27 +550,30 @@
+
+ if (execution_policy == eExecutionPolicyAlways || !can_interpret)
+ {
+- if (m_expr.NeedsValidation() && (process && (!process->GetDynamicCheckers())))
+- {
+- DynamicCheckerFunctions *dynamic_checkers = new DynamicCheckerFunctions();
+-
+- StreamString install_errors;
+-
+- if (!dynamic_checkers->Install(install_errors, exe_ctx))
++ if (m_expr.NeedsValidation() && process)
++ {
++ if (!process->GetDynamicCheckers())
+ {
+- if (install_errors.GetString().empty())
+- err.SetErrorString ("couldn't install checkers, unknown error");
+- else
+- err.SetErrorString (install_errors.GetString().c_str());
++ DynamicCheckerFunctions *dynamic_checkers = new DynamicCheckerFunctions();
+
+- return err;
++ StreamString install_errors;
++
++ if (!dynamic_checkers->Install(install_errors, exe_ctx))
++ {
++ if (install_errors.GetString().empty())
++ err.SetErrorString ("couldn't install checkers, unknown error");
++ else
++ err.SetErrorString (install_errors.GetString().c_str());
++
++ return err;
++ }
++
++ process->SetDynamicCheckers(dynamic_checkers);
++
++ if (log)
++ log->Printf("== [ClangUserExpression::Evaluate] Finished installing dynamic checkers ==");
+ }
+
+- process->SetDynamicCheckers(dynamic_checkers);
+-
+- if (log)
+- log->Printf("== [ClangUserExpression::Evaluate] Finished installing dynamic checkers ==");
+-
+ IRDynamicChecks ir_dynamic_checks(*process->GetDynamicCheckers(), function_name.AsCString());
+
+ if (!ir_dynamic_checks.runOnModule(*m_execution_unit->GetModule()))
+Index: source/Expression/DWARFExpression.cpp
+===================================================================
+--- source/Expression/DWARFExpression.cpp (revision 183906)
++++ source/Expression/DWARFExpression.cpp (working copy)
+@@ -1303,6 +1303,13 @@
+ Error *error_ptr
+ )
+ {
++
++ if (opcodes_length == 0)
++ {
++ if (error_ptr)
++ error_ptr->SetErrorString ("no location, value may have been optimized out");
++ return false;
++ }
+ std::vector<Value> stack;
+
+ Process *process = NULL;
+@@ -1328,7 +1335,7 @@
+ if (!opcodes.ValidOffsetForDataOfSize(opcodes_offset, opcodes_length))
+ {
+ if (error_ptr)
+- error_ptr->SetErrorString ("Invalid offset and/or length for opcodes buffer.");
++ error_ptr->SetErrorString ("invalid offset and/or length for opcodes buffer.");
+ return false;
+ }
+ Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
+Index: source/Commands/CommandObjectSettings.cpp
+===================================================================
+--- source/Commands/CommandObjectSettings.cpp (revision 183906)
++++ source/Commands/CommandObjectSettings.cpp (working copy)
+@@ -255,7 +255,14 @@
+
+ if (error.Success())
+ {
+- error = m_interpreter.GetDebugger().SetPropertyValue (&m_exe_ctx,
++ // FIXME this is the same issue as the one in commands script import
++ // we could be setting target.load-script-from-symbol-file which would cause
++ // Python scripts to be loaded, which could run LLDB commands
++ // (e.g. settings set target.process.python-os-plugin-path) and cause a crash
++ // if we did not clear the command's exe_ctx first
++ ExecutionContext exe_ctx(m_exe_ctx);
++ m_exe_ctx.Clear();
++ error = m_interpreter.GetDebugger().SetPropertyValue (&exe_ctx,
+ eVarSetOperationAssign,
+ var_name,
+ var_value_cstr);
+Index: source/Commands/CommandObjectMemory.cpp
+===================================================================
+--- source/Commands/CommandObjectMemory.cpp (revision 183906)
++++ source/Commands/CommandObjectMemory.cpp (working copy)
+@@ -44,7 +44,7 @@
+ { LLDB_OPT_SET_3, true , "type" ,'t', required_argument, NULL, 0, eArgTypeNone ,"The name of a type to view memory as."},
+ { LLDB_OPT_SET_1|
+ LLDB_OPT_SET_2|
+- LLDB_OPT_SET_3, false, "force" ,'r', no_argument, NULL, 0, eArgTypeNone ,"Necessary if reading over 1024 bytes of memory."},
++ LLDB_OPT_SET_3, false, "force" ,'r', no_argument, NULL, 0, eArgTypeNone ,"Necessary if reading over target.max-memory-read-size bytes."},
+ };
+
+
+@@ -119,6 +119,7 @@
+ m_num_per_line.Clear();
+ m_output_as_binary = false;
+ m_view_as_type.Clear();
++ m_force = false;
+ }
+
+ Error
+@@ -642,15 +643,16 @@
+ item_count = total_byte_size / item_byte_size;
+ }
+
+- if (total_byte_size > 1024 && !m_memory_options.m_force)
++ uint32_t max_unforced_size = target->GetMaximumMemReadSize();
++
++ if (total_byte_size > max_unforced_size && !m_memory_options.m_force)
+ {
+- result.AppendErrorWithFormat("Normally, \'memory read\' will not read over 1Kbyte of data.\n");
+- result.AppendErrorWithFormat("Please use --force to override this restriction.\n");
++ result.AppendErrorWithFormat("Normally, \'memory read\' will not read over %" PRIu32 " bytes of data.\n",max_unforced_size);
++ result.AppendErrorWithFormat("Please use --force to override this restriction just once.\n");
++ result.AppendErrorWithFormat("or set target.max-memory-read-size if you will often need a larger limit.\n");
+ return false;
+ }
+
+-
+-
+ DataBufferSP data_sp;
+ size_t bytes_read = 0;
+ if (clang_ast_type.GetOpaqueQualType())
+@@ -827,12 +829,25 @@
+ DataExtractor data (data_sp,
+ target->GetArchitecture().GetByteOrder(),
+ target->GetArchitecture().GetAddressByteSize());
++
++ Format format = m_format_options.GetFormat();
++ if ( ( (format == eFormatChar) || (format == eFormatCharPrintable) )
++ && (item_byte_size != 1)
++ && (item_count == 1))
++ {
++ // this turns requests such as
++ // memory read -fc -s10 -c1 *charPtrPtr
++ // which make no sense (what is a char of size 10?)
++ // into a request for fetching 10 chars of size 1 from the same memory location
++ format = eFormatCharArray;
++ item_count = item_byte_size;
++ item_byte_size = 1;
++ }
+
+-
+ assert (output_stream);
+ size_t bytes_dumped = data.Dump (output_stream,
+ 0,
+- m_format_options.GetFormat(),
++ format,
+ item_byte_size,
+ item_count,
+ num_per_line,
+Index: source/Commands/CommandObjectTarget.cpp
+===================================================================
+--- source/Commands/CommandObjectTarget.cpp (revision 183906)
++++ source/Commands/CommandObjectTarget.cpp (working copy)
+@@ -1676,7 +1676,7 @@
+ ConstString function_name (name);
+ num_matches = module->FindFunctions (function_name,
+ NULL,
+- eFunctionNameTypeBase | eFunctionNameTypeFull | eFunctionNameTypeMethod | eFunctionNameTypeSelector,
++ eFunctionNameTypeAuto,
+ include_symbols,
+ include_inlines,
+ append,
+@@ -4376,11 +4376,14 @@
+ // Make sure we load any scripting resources that may be embedded
+ // in the debug info files in case the platform supports that.
+ Error error;
+- module_sp->LoadScriptingResourceInTarget (target, error);
+- if (error.Fail())
++ StreamString feedback_stream;
++ module_sp->LoadScriptingResourceInTarget (target, error,&feedback_stream);
++ if (error.Fail() && error.AsCString())
+ result.AppendWarningWithFormat("unable to load scripting data for module %s - error reported was %s",
+ module_sp->GetFileSpec().GetFileNameStrippingExtension().GetCString(),
+ error.AsCString());
++ else if (feedback_stream.GetSize())
++ result.AppendWarningWithFormat("%s",feedback_stream.GetData());
+
+ flush = true;
+ result.SetStatus (eReturnStatusSuccessFinishResult);
+Index: source/Commands/CommandObjectBreakpointCommand.cpp
+===================================================================
+--- source/Commands/CommandObjectBreakpointCommand.cpp (revision 183906)
++++ source/Commands/CommandObjectBreakpointCommand.cpp (working copy)
+@@ -167,6 +167,12 @@
+ (lldb)\n\
+ \n\
+ \n\
++Your Python code, however organized, can optionally return a value.\n\
++If the returned value is False, that tells LLDB not to stop at the breakpoint\n\
++to which the code is associated. Returning anything other than False, or even\n\
++returning None, or even omitting a return statement entirely, will cause\n\
++LLDB to stop.\n\
++\n\
+ Final Note: If you get a warning that no breakpoint command was generated, but\n\
+ you did not get any syntax errors, you probably forgot to add a call to your\n\
+ functions.\n\
+Index: source/Commands/CommandObjectSource.cpp
+===================================================================
+--- source/Commands/CommandObjectSource.cpp (revision 183906)
++++ source/Commands/CommandObjectSource.cpp (working copy)
+@@ -296,6 +296,149 @@
+ }
+
+ protected:
++
++ struct SourceInfo
++ {
++ ConstString function;
++ LineEntry line_entry;
++
++ SourceInfo (const ConstString &name, const LineEntry &line_entry) :
++ function(name),
++ line_entry(line_entry)
++ {
++ }
++
++ SourceInfo () :
++ function(),
++ line_entry()
++ {
++ }
++
++ bool
++ IsValid () const
++ {
++ return (bool)function && line_entry.IsValid();
++ }
++
++ bool
++ operator == (const SourceInfo &rhs) const
++ {
++ return function == rhs.function &&
++ line_entry.file == rhs.line_entry.file &&
++ line_entry.line == rhs.line_entry.line;
++ }
++
++ bool
++ operator != (const SourceInfo &rhs) const
++ {
++ return function != rhs.function ||
++ line_entry.file != rhs.line_entry.file ||
++ line_entry.line != rhs.line_entry.line;
++ }
++
++ bool
++ operator < (const SourceInfo &rhs) const
++ {
++ if (function.GetCString() < rhs.function.GetCString())
++ return true;
++ if (line_entry.file.GetDirectory().GetCString() < rhs.line_entry.file.GetDirectory().GetCString())
++ return true;
++ if (line_entry.file.GetFilename().GetCString() < rhs.line_entry.file.GetFilename().GetCString())
++ return true;
++ if (line_entry.line < rhs.line_entry.line)
++ return true;
++ return false;
++ }
++ };
++
++ size_t
++ DisplayFunctionSource (const SymbolContext &sc,
++ SourceInfo &source_info,
++ CommandReturnObject &result)
++ {
++ if (!source_info.IsValid())
++ {
++ source_info.function = sc.GetFunctionName();
++ source_info.line_entry = sc.GetFunctionStartLineEntry();
++ }
++
++ if (sc.function)
++ {
++ Target *target = m_exe_ctx.GetTargetPtr();
++
++ FileSpec start_file;
++ uint32_t start_line;
++ uint32_t end_line;
++ FileSpec end_file;
++
++ if (sc.block == NULL)
++ {
++ // Not an inlined function
++ sc.function->GetStartLineSourceInfo (start_file, start_line);
++ if (start_line == 0)
++ {
++ result.AppendErrorWithFormat("Could not find line information for start of function: \"%s\".\n", source_info.function.GetCString());
++ result.SetStatus (eReturnStatusFailed);
++ return 0;
++ }
++ sc.function->GetEndLineSourceInfo (end_file, end_line);
++ }
++ else
++ {
++ // We have an inlined function
++ start_file = source_info.line_entry.file;
++ start_line = source_info.line_entry.line;
++ end_line = start_line + m_options.num_lines;
++ }
++
++ // This is a little hacky, but the first line table entry for a function points to the "{" that
++ // starts the function block. It would be nice to actually get the function
++ // declaration in there too. So back up a bit, but not further than what you're going to display.
++ uint32_t extra_lines;
++ if (m_options.num_lines >= 10)
++ extra_lines = 5;
++ else
++ extra_lines = m_options.num_lines/2;
++ uint32_t line_no;
++ if (start_line <= extra_lines)
++ line_no = 1;
++ else
++ line_no = start_line - extra_lines;
++
++ // For fun, if the function is shorter than the number of lines we're supposed to display,
++ // only display the function...
++ if (end_line != 0)
++ {
++ if (m_options.num_lines > end_line - line_no)
++ m_options.num_lines = end_line - line_no + extra_lines;
++ }
++
++ m_breakpoint_locations.Clear();
++
++ if (m_options.show_bp_locs)
++ {
++ const bool show_inlines = true;
++ m_breakpoint_locations.Reset (start_file, 0, show_inlines);
++ SearchFilter target_search_filter (m_exe_ctx.GetTargetSP());
++ target_search_filter.Search (m_breakpoint_locations);
++ }
++
++ result.AppendMessageWithFormat("File: %s\n", start_file.GetPath().c_str());
++ return target->GetSourceManager().DisplaySourceLinesWithLineNumbers (start_file,
++ line_no,
++ 0,
++ m_options.num_lines,
++ "",
++ &result.GetOutputStream(),
++ GetBreakpointLocations ());
++ }
++ else
++ {
++ result.AppendErrorWithFormat("Could not find function info for: \"%s\".\n", m_options.symbol_name.c_str());
++ }
++ return 0;
++ }
++
+ bool
+ DoExecute (Args& command, CommandReturnObject &result)
+ {
+@@ -353,123 +496,48 @@
+ return false;
+ }
+
+- sc_list.GetContextAtIndex (0, sc);
+- FileSpec start_file;
+- uint32_t start_line;
+- uint32_t end_line;
+- FileSpec end_file;
+- if (sc.function != NULL)
+- {
+- sc.function->GetStartLineSourceInfo (start_file, start_line);
+- if (start_line == 0)
+- {
+- result.AppendErrorWithFormat("Could not find line information for start of function: \"%s\".\n", m_options.symbol_name.c_str());
+- result.SetStatus (eReturnStatusFailed);
+- return false;
+- }
+- sc.function->GetEndLineSourceInfo (end_file, end_line);
+- }
+- else
+- {
+- result.AppendErrorWithFormat("Could not find function info for: \"%s\".\n", m_options.symbol_name.c_str());
+- result.SetStatus (eReturnStatusFailed);
+- return false;
+- }
+-
+ if (num_matches > 1)
+ {
+- // This could either be because there are multiple functions of this name, in which case
+- // we'll have to specify this further... Or it could be because there are multiple inlined instances
+- // of one function. So run through the matches and if they all have the same file & line then we can just
+- // list one.
++ std::set<SourceInfo> source_match_set;
+
+- bool found_multiple = false;
+-
+- for (size_t i = 1; i < num_matches; i++)
++ bool displayed_something = false;
++ for (size_t i = 0; i < num_matches; i++)
+ {
+- SymbolContext scratch_sc;
+- sc_list.GetContextAtIndex (i, scratch_sc);
+- if (scratch_sc.function != NULL)
++ sc_list.GetContextAtIndex (i, sc);
++ SourceInfo source_info (sc.GetFunctionName(),
++ sc.GetFunctionStartLineEntry());
++
++ if (source_info.IsValid())
+ {
+- FileSpec scratch_file;
+- uint32_t scratch_line;
+- scratch_sc.function->GetStartLineSourceInfo (scratch_file, scratch_line);
+- if (scratch_file != start_file
+- || scratch_line != start_line)
++ if (source_match_set.find(source_info) == source_match_set.end())
+ {
+- found_multiple = true;
+- break;
++ source_match_set.insert(source_info);
++ if (DisplayFunctionSource (sc, source_info, result))
++ displayed_something = true;
+ }
+ }
+ }
+- if (found_multiple)
+- {
+- StreamString s;
+- for (size_t i = 0; i < num_matches; i++)
+- {
+- SymbolContext scratch_sc;
+- sc_list.GetContextAtIndex (i, scratch_sc);
+- if (scratch_sc.function != NULL)
+- {
+- s.Printf("\n%lu: ", i);
+- scratch_sc.function->Dump (&s, true);
+- }
+- }
+- result.AppendErrorWithFormat("Multiple functions found matching: %s: \n%s\n",
+- m_options.symbol_name.c_str(),
+- s.GetData());
++
++ if (displayed_something)
++ result.SetStatus (eReturnStatusSuccessFinishResult);
++ else
+ result.SetStatus (eReturnStatusFailed);
+- return false;
+- }
+ }
+-
+- // This is a little hacky, but the first line table entry for a function points to the "{" that
+- // starts the function block. It would be nice to actually get the function
+- // declaration in there too. So back up a bit, but not further than what you're going to display.
+- uint32_t extra_lines;
+- if (m_options.num_lines >= 10)
+- extra_lines = 5;
+ else
+- extra_lines = m_options.num_lines/2;
+- uint32_t line_no;
+- if (start_line <= extra_lines)
+- line_no = 1;
+- else
+- line_no = start_line - extra_lines;
++ {
++ sc_list.GetContextAtIndex (0, sc);
++ SourceInfo source_info;
+
+- // For fun, if the function is shorter than the number of lines we're supposed to display,
+- // only display the function...
+- if (end_line != 0)
+- {
+- if (m_options.num_lines > end_line - line_no)
+- m_options.num_lines = end_line - line_no + extra_lines;
++ if (DisplayFunctionSource (sc, source_info, result))
++ {
++ result.SetStatus (eReturnStatusSuccessFinishResult);
++ }
++ else
++ {
++ result.SetStatus (eReturnStatusFailed);
++ }
+ }
+-
+- char path_buf[PATH_MAX];
+- start_file.GetPath(path_buf, sizeof(path_buf));
+-
+- if (m_options.show_bp_locs)
+- {
+- const bool show_inlines = true;
+- m_breakpoint_locations.Reset (start_file, 0, show_inlines);
+- SearchFilter target_search_filter (m_exe_ctx.GetTargetSP());
+- target_search_filter.Search (m_breakpoint_locations);
+- }
+- else
+- m_breakpoint_locations.Clear();
+-
+- result.AppendMessageWithFormat("File: %s\n", path_buf);
+- target->GetSourceManager().DisplaySourceLinesWithLineNumbers (start_file,
+- line_no,
+- 0,
+- m_options.num_lines,
+- "",
+- &result.GetOutputStream(),
+- GetBreakpointLocations ());
+-
+- result.SetStatus (eReturnStatusSuccessFinishResult);
+- return true;
+-
++ return result.Succeeded();
+ }
+ else if (m_options.address != LLDB_INVALID_ADDRESS)
+ {
+Index: source/Commands/CommandObjectCommands.cpp
+===================================================================
+--- source/Commands/CommandObjectCommands.cpp (revision 183906)
++++ source/Commands/CommandObjectCommands.cpp (working copy)
+@@ -1355,7 +1355,7 @@
+ void
+ OptionParsingStarting ()
+ {
+- m_allow_reload = false;
++ m_allow_reload = true;
+ }
+
+ const OptionDefinition*
+@@ -1426,7 +1426,7 @@
+ OptionDefinition
+ CommandObjectCommandsScriptImport::CommandOptions::g_option_table[] =
+ {
+- { LLDB_OPT_SET_1, false, "allow-reload", 'r', no_argument, NULL, 0, eArgTypeNone, "Allow the script to be loaded even if it was already loaded before (for Python, the __lldb_init_module function will be called again, but the module will not be reloaded from disk)."},
++ { LLDB_OPT_SET_1, false, "allow-reload", 'r', no_argument, NULL, 0, eArgTypeNone, "Allow the script to be loaded even if it was already loaded before. This argument exists for backwards compatibility, but reloading is always allowed, whether you specify it or not."},
+ { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
+ };
+
+Index: source/Commands/CommandObjectType.cpp
+===================================================================
+--- source/Commands/CommandObjectType.cpp (revision 183906)
++++ source/Commands/CommandObjectType.cpp (working copy)
+@@ -179,7 +179,7 @@
+ }
+
+ static bool
+- AddSummary(const ConstString& type_name,
++ AddSummary(ConstString type_name,
+ lldb::TypeSummaryImplSP entry,
+ SummaryFormatType type,
+ std::string category,
+@@ -324,7 +324,7 @@
+ }
+
+ static bool
+- AddSynth(const ConstString& type_name,
++ AddSynth(ConstString type_name,
+ lldb::SyntheticChildrenSP entry,
+ SynthFormatType type,
+ std::string category_name,
+@@ -744,7 +744,9 @@
+ //-------------------------------------------------------------------------
+
+ static const char *g_summary_addreader_instructions = "Enter your Python command(s). Type 'DONE' to end.\n"
+- "def function (valobj,internal_dict):";
++ "def function (valobj,internal_dict):\n"
++ " \"\"\"valobj: an SBValue which you want to provide a summary for\n"
++ " internal_dict: an LLDB support object not to be used\"\"\"";
+
+ class TypeScriptAddInputReader : public InputReaderEZ
+ {
+@@ -1338,7 +1340,7 @@
+ }
+
+ bool
+-CommandObjectTypeSummaryAdd::AddSummary(const ConstString& type_name,
++CommandObjectTypeSummaryAdd::AddSummary(ConstString type_name,
+ TypeSummaryImplSP entry,
+ SummaryFormatType type,
+ std::string category_name,
+@@ -1347,6 +1349,21 @@
+ lldb::TypeCategoryImplSP category;
+ DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()), category);
+
++ if (type == eRegularSummary)
++ {
++ std::string type_name_str(type_name.GetCString());
++ if (type_name_str.compare(type_name_str.length() - 2, 2, "[]") == 0)
++ {
++ type_name_str.resize(type_name_str.length()-2);
++ if (type_name_str.back() != ' ')
++ type_name_str.append(" \\[[0-9]+\\]");
++ else
++ type_name_str.append("\\[[0-9]+\\]");
++ type_name.SetCString(type_name_str.c_str());
++ type = eRegexSummary;
++ }
++ }
++
+ if (type == eRegexSummary)
+ {
+ RegularExpressionSP typeRX(new RegularExpression());
+@@ -3573,15 +3590,30 @@
+ }
+
+ bool
+-CommandObjectTypeSynthAdd::AddSynth(const ConstString& type_name,
+- SyntheticChildrenSP entry,
+- SynthFormatType type,
+- std::string category_name,
+- Error* error)
++CommandObjectTypeSynthAdd::AddSynth(ConstString type_name,
++ SyntheticChildrenSP entry,
++ SynthFormatType type,
++ std::string category_name,
++ Error* error)
+ {
+ lldb::TypeCategoryImplSP category;
+ DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()), category);
+
++ if (type == eRegularSynth)
++ {
++ std::string type_name_str(type_name.GetCString());
++ if (type_name_str.compare(type_name_str.length() - 2, 2, "[]") == 0)
++ {
++ type_name_str.resize(type_name_str.length()-2);
++ if (type_name_str.back() != ' ')
++ type_name_str.append(" \\[[0-9]+\\]");
++ else
++ type_name_str.append("\\[[0-9]+\\]");
++ type_name.SetCString(type_name_str.c_str());
++ type = eRegularSynth;
++ }
++ }
++
+ if (category->AnyMatches(type_name,
+ eFormatCategoryItemFilter | eFormatCategoryItemRegexFilter,
+ false))
+@@ -3752,7 +3784,7 @@
+ };
+
+ bool
+- AddFilter(const ConstString& type_name,
++ AddFilter(ConstString type_name,
+ SyntheticChildrenSP entry,
+ FilterFormatType type,
+ std::string category_name,
+@@ -3761,6 +3793,21 @@
+ lldb::TypeCategoryImplSP category;
+ DataVisualization::Categories::GetCategory(ConstString(category_name.c_str()), category);
+
++ if (type == eRegularFilter)
++ {
++ std::string type_name_str(type_name.GetCString());
++ if (type_name_str.compare(type_name_str.length() - 2, 2, "[]") == 0)
++ {
++ type_name_str.resize(type_name_str.length()-2);
++ if (type_name_str.back() != ' ')
++ type_name_str.append(" \\[[0-9]+\\]");
++ else
++ type_name_str.append("\\[[0-9]+\\]");
++ type_name.SetCString(type_name_str.c_str());
++ type = eRegexFilter;
++ }
++ }
++
+ if (category->AnyMatches(type_name,
+ eFormatCategoryItemSynth | eFormatCategoryItemRegexSynth,
+ false))
+Index: source/Commands/CommandObjectApropos.cpp
+===================================================================
+--- source/Commands/CommandObjectApropos.cpp (revision 183906)
++++ source/Commands/CommandObjectApropos.cpp (working copy)
+@@ -68,29 +68,59 @@
+ // is private.
+ StringList commands_found;
+ StringList commands_help;
+- m_interpreter.FindCommandsForApropos (search_word, commands_found, commands_help);
+- if (commands_found.GetSize() == 0)
++ StringList user_commands_found;
++ StringList user_commands_help;
++
++ m_interpreter.FindCommandsForApropos (search_word, commands_found, commands_help, true, false);
++ m_interpreter.FindCommandsForApropos (search_word, user_commands_found, user_commands_help, false, true);
++
++ if (commands_found.GetSize() == 0 && user_commands_found.GetSize() == 0)
+ {
+ result.AppendMessageWithFormat ("No commands found pertaining to '%s'. Try 'help' to see a complete list of debugger commands.\n", search_word);
+ }
+ else
+ {
+- result.AppendMessageWithFormat ("The following commands may relate to '%s':\n", search_word);
+- size_t max_len = 0;
++ if (commands_found.GetSize() > 0)
++ {
++ result.AppendMessageWithFormat ("The following built-in commands may relate to '%s':\n", search_word);
++ size_t max_len = 0;
+
+- for (size_t i = 0; i < commands_found.GetSize(); ++i)
++ for (size_t i = 0; i < commands_found.GetSize(); ++i)
++ {
++ size_t len = strlen (commands_found.GetStringAtIndex (i));
++ if (len > max_len)
++ max_len = len;
++ }
++
++ for (size_t i = 0; i < commands_found.GetSize(); ++i)
++ m_interpreter.OutputFormattedHelpText (result.GetOutputStream(),
++ commands_found.GetStringAtIndex(i),
++ "--",
++ commands_help.GetStringAtIndex(i),
++ max_len);
++ if (user_commands_found.GetSize() > 0)
++ result.AppendMessage("");
++ }
++
++ if (user_commands_found.GetSize() > 0)
+ {
+- size_t len = strlen (commands_found.GetStringAtIndex (i));
+- if (len > max_len)
+- max_len = len;
++ result.AppendMessageWithFormat ("The following user commands may relate to '%s':\n", search_word);
++ size_t max_len = 0;
++
++ for (size_t i = 0; i < user_commands_found.GetSize(); ++i)
++ {
++ size_t len = strlen (user_commands_found.GetStringAtIndex (i));
++ if (len > max_len)
++ max_len = len;
++ }
++
++ for (size_t i = 0; i < user_commands_found.GetSize(); ++i)
++ m_interpreter.OutputFormattedHelpText (result.GetOutputStream(),
++ user_commands_found.GetStringAtIndex(i),
++ "--",
++ user_commands_help.GetStringAtIndex(i),
++ max_len);
+ }
+-
+- for (size_t i = 0; i < commands_found.GetSize(); ++i)
+- m_interpreter.OutputFormattedHelpText (result.GetOutputStream(),
+- commands_found.GetStringAtIndex(i),
+- "--",
+- commands_help.GetStringAtIndex(i),
+- max_len);
+
+ }
+
+Index: source/Commands/CommandObjectExpression.cpp
+===================================================================
+--- source/Commands/CommandObjectExpression.cpp (revision 183906)
++++ source/Commands/CommandObjectExpression.cpp (working copy)
+@@ -54,7 +54,7 @@
+ {
+ { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "all-threads", 'a', required_argument, NULL, 0, eArgTypeBoolean, "Should we run all threads if the execution doesn't complete on one thread."},
+ { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "ignore-breakpoints", 'i', required_argument, NULL, 0, eArgTypeBoolean, "Ignore breakpoint hits while running expressions"},
+- { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "timeout", 't', required_argument, NULL, 0, eArgTypeUnsignedInteger, "Timeout value for running the expression."},
++ { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "timeout", 't', required_argument, NULL, 0, eArgTypeUnsignedInteger, "Timeout value (in microseconds) for running the expression."},
+ { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "unwind-on-error", 'u', required_argument, NULL, 0, eArgTypeBoolean, "Clean up program state if the expression causes a crash, or raises a signal. Note, unlike gdb hitting a breakpoint is controlled by another option (-i)."},
+ };
+
+Index: source/Interpreter/CommandInterpreter.cpp
+===================================================================
+--- source/Interpreter/CommandInterpreter.cpp (revision 183906)
++++ source/Interpreter/CommandInterpreter.cpp (working copy)
+@@ -2804,27 +2804,52 @@
+
+ void
+ CommandInterpreter::FindCommandsForApropos (const char *search_word, StringList &commands_found,
+- StringList &commands_help)
++ StringList &commands_help, bool search_builtin_commands, bool search_user_commands)
+ {
+ CommandObject::CommandMap::const_iterator pos;
+
+- for (pos = m_command_dict.begin(); pos != m_command_dict.end(); ++pos)
++ if (search_builtin_commands)
+ {
+- const char *command_name = pos->first.c_str();
+- CommandObject *cmd_obj = pos->second.get();
++ for (pos = m_command_dict.begin(); pos != m_command_dict.end(); ++pos)
++ {
++ const char *command_name = pos->first.c_str();
++ CommandObject *cmd_obj = pos->second.get();
+
+- if (cmd_obj->HelpTextContainsWord (search_word))
++ if (cmd_obj->HelpTextContainsWord (search_word))
++ {
++ commands_found.AppendString (command_name);
++ commands_help.AppendString (cmd_obj->GetHelp());
++ }
++
++ if (cmd_obj->IsMultiwordObject())
++ cmd_obj->AproposAllSubCommands (command_name,
++ search_word,
++ commands_found,
++ commands_help);
++
++ }
++ }
++
++ if (search_user_commands)
++ {
++ for (pos = m_user_dict.begin(); pos != m_user_dict.end(); ++pos)
+ {
+- commands_found.AppendString (command_name);
+- commands_help.AppendString (cmd_obj->GetHelp());
++ const char *command_name = pos->first.c_str();
++ CommandObject *cmd_obj = pos->second.get();
++
++ if (cmd_obj->HelpTextContainsWord (search_word))
++ {
++ commands_found.AppendString (command_name);
++ commands_help.AppendString (cmd_obj->GetHelp());
++ }
++
++ if (cmd_obj->IsMultiwordObject())
++ cmd_obj->AproposAllSubCommands (command_name,
++ search_word,
++ commands_found,
++ commands_help);
++
+ }
+-
+- if (cmd_obj->IsMultiwordObject())
+- cmd_obj->AproposAllSubCommands (command_name,
+- search_word,
+- commands_found,
+- commands_help);
+-
+ }
+ }
+
+Index: source/Interpreter/PythonDataObjects.cpp
+===================================================================
+--- source/Interpreter/PythonDataObjects.cpp (revision 183906)
++++ source/Interpreter/PythonDataObjects.cpp (working copy)
+@@ -21,6 +21,10 @@
+ #include <Python.h>
+ #endif
+
++#include <stdio.h>
++
++#include "lldb/Core/Stream.h"
++#include "lldb/Host/File.h"
+ #include "lldb/Interpreter/PythonDataObjects.h"
+ #include "lldb/Interpreter/ScriptInterpreter.h"
+
+@@ -37,6 +41,31 @@
+ Reset ((PyObject *)script_object_sp->GetObject());
+ }
+
++void
++PythonObject::Dump (Stream &strm) const
++{
++ if (m_py_obj)
++ {
++ FILE *file = ::tmpfile();
++ if (file)
++ {
++ ::PyObject_Print (m_py_obj, file, 0);
++ const long length = ftell (file);
++ if (length)
++ {
++ ::rewind(file);
++ std::vector<char> file_contents (length,'\0');
++ const size_t length_read = ::fread (file_contents.data(), 1, file_contents.size(), file);
++ if (length_read > 0)
++ strm.Write (file_contents.data(), length_read);
++ }
++ ::fclose (file);
++ }
++ }
++ else
++ strm.PutCString ("NULL");
++}
++
+ //----------------------------------------------------------------------
+ // PythonString
+ //----------------------------------------------------------------------
+Index: source/Interpreter/ScriptInterpreterPython.cpp
+===================================================================
+--- source/Interpreter/ScriptInterpreterPython.cpp (revision 183906)
++++ source/Interpreter/ScriptInterpreterPython.cpp (working copy)
+@@ -1248,6 +1248,12 @@
+
+ static const char *g_reader_instructions = "Enter your Python command(s). Type 'DONE' to end.";
+
++static const char *g_bkpt_command_reader_instructions = "Enter your Python command(s). Type 'DONE' to end.\n"
++ "def function(frame,bp_loc,internal_dict):\n"
++ " \"\"\"frame: the SBFrame for the location at which you stopped\n"
++ " bp_loc: an SBBreakpointLocation for the breakpoint location information\n"
++ " internal_dict: an LLDB support object not to be used\"\"\"";
++
+ size_t
+ ScriptInterpreterPython::GenerateBreakpointOptionsCommandCallback
+ (
+@@ -1270,7 +1276,7 @@
+ commands_in_progress.Clear();
+ if (!batch_mode)
+ {
+- out_stream->Printf ("%s\n", g_reader_instructions);
++ out_stream->Printf ("%s\n", g_bkpt_command_reader_instructions);
+ if (reader.GetPrompt())
+ out_stream->Printf ("%s", reader.GetPrompt());
+ out_stream->Flush ();
+@@ -1497,7 +1503,7 @@
+ bp_options, // baton
+ eInputReaderGranularityLine, // token size, for feeding data to callback function
+ "DONE", // end token
+- "> ", // prompt
++ " ", // prompt
+ true); // echo input
+
+ if (err.Success())
+@@ -2666,7 +2672,10 @@
+
+ // now actually do the import
+ command_stream.Clear();
+- command_stream.Printf("import %s",basename.c_str());
++ if (was_imported)
++ command_stream.Printf("reload(%s)",basename.c_str());
++ else
++ command_stream.Printf("import %s",basename.c_str());
+ bool import_retval = ExecuteMultipleLines(command_stream.GetData(), ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false).SetSetLLDBGlobals(false).SetMaskoutErrors(false));
+ PyObject* py_error = PyErr_Occurred(); // per Python docs: "you do not need to Py_DECREF()" the return of this function
+
+Index: source/Utility/StringExtractor.h
+===================================================================
+--- source/Utility/StringExtractor.h (revision 183906)
++++ source/Utility/StringExtractor.h (working copy)
+@@ -73,6 +73,12 @@
+ return m_packet;
+ }
+
++ const std::string &
++ GetStringRef () const
++ {
++ return m_packet;
++ }
++
+ bool
+ Empty()
+ {
+Index: source/Symbol/SymbolContext.cpp
+===================================================================
+--- source/Symbol/SymbolContext.cpp (revision 183906)
++++ source/Symbol/SymbolContext.cpp (working copy)
+@@ -319,7 +319,6 @@
+ return resolved_mask;
+ }
+
+-
+ void
+ SymbolContext::Dump(Stream *s, Target *target) const
+ {
+@@ -593,7 +592,7 @@
+ }
+
+ ConstString
+-SymbolContext::GetFunctionName (Mangled::NamePreference preference)
++SymbolContext::GetFunctionName (Mangled::NamePreference preference) const
+ {
+ if (function)
+ {
+@@ -621,6 +620,33 @@
+ }
+ }
+
++LineEntry
++SymbolContext::GetFunctionStartLineEntry () const
++{
++ LineEntry line_entry;
++ Address start_addr;
++ if (block)
++ {
++ Block *inlined_block = block->GetContainingInlinedBlock();
++ if (inlined_block)
++ {
++ if (inlined_block->GetStartAddress (start_addr))
++ {
++ if (start_addr.CalculateSymbolContextLineEntry (line_entry))
++ return line_entry;
++ }
++ return LineEntry();
++ }
++ }
++
++ if (function)
++ {
++ if (function->GetAddressRange().GetBaseAddress().CalculateSymbolContextLineEntry(line_entry))
++ return line_entry;
++ }
++ return LineEntry();
++}
++
+ //----------------------------------------------------------------------
+ //
+ // SymbolContextSpecifier
+Index: source/Symbol/Variable.cpp
+===================================================================
+--- source/Symbol/Variable.cpp (revision 183906)
++++ source/Symbol/Variable.cpp (working copy)
+@@ -416,8 +416,8 @@
+ ValueObjectSP variable_valobj_sp(ValueObjectVariable::Create (scope, var_sp));
+ if (variable_valobj_sp)
+ {
+- variable_expr_path += variable_name.size();
+- if (*variable_expr_path)
++ const char *variable_sub_expr_path = variable_expr_path + variable_name.size();
++ if (*variable_sub_expr_path)
+ {
+ const char* first_unparsed = NULL;
+ ValueObject::ExpressionPathScanEndReason reason_to_stop;
+@@ -425,7 +425,7 @@
+ ValueObject::GetValueForExpressionPathOptions options;
+ ValueObject::ExpressionPathAftermath final_task_on_target;
+
+- valobj_sp = variable_valobj_sp->GetValueForExpressionPath (variable_expr_path,
++ valobj_sp = variable_valobj_sp->GetValueForExpressionPath (variable_sub_expr_path,
+ &first_unparsed,
+ &reason_to_stop,
+ &final_value_type,
+@@ -434,7 +434,7 @@
+ if (!valobj_sp)
+ {
+ error.SetErrorStringWithFormat ("invalid expression path '%s' for variable '%s'",
+- variable_expr_path,
++ variable_sub_expr_path,
+ var_sp->GetName().GetCString());
+ }
+ }
+@@ -465,7 +465,7 @@
+ }
+ }
+ }
+- error.SetErrorStringWithFormat ("unable to extracta variable name from '%s'", variable_expr_path);
++ error.SetErrorStringWithFormat ("unable to extract a variable name from '%s'", variable_expr_path);
+ }
+ break;
+ }
+Index: source/Symbol/Symtab.cpp
+===================================================================
+--- source/Symbol/Symtab.cpp (revision 183906)
++++ source/Symbol/Symtab.cpp (working copy)
+@@ -320,7 +320,7 @@
+ entry.cstring[2] != 'Z')) // named local entities (if we eventually handle eSymbolTypeData, we will want this back)
+ {
+ CPPLanguageRuntime::MethodName cxx_method (mangled.GetDemangledName());
+- entry.cstring = cxx_method.GetBasename ().GetCString();
++ entry.cstring = ConstString(cxx_method.GetBasename()).GetCString();
+ if (entry.cstring && entry.cstring[0])
+ {
+ // ConstString objects permanently store the string in the pool so calling
+Index: source/API/SBDebugger.cpp
+===================================================================
+--- source/API/SBDebugger.cpp (revision 183906)
++++ source/API/SBDebugger.cpp (working copy)
+@@ -1057,6 +1057,22 @@
+ }
+
+ bool
++SBDebugger::SetUseColor (bool value)
++{
++ if (m_opaque_sp)
++ return m_opaque_sp->SetUseColor (value);
++ return false;
++}
++
++bool
++SBDebugger::GetUseColor () const
++{
++ if (m_opaque_sp)
++ return m_opaque_sp->GetUseColor ();
++ return false;
++}
++
++bool
+ SBDebugger::GetDescription (SBStream &description)
+ {
+ Stream &strm = description.ref();
+Index: source/lldb-log.cpp
+===================================================================
+--- source/lldb-log.cpp (revision 183906)
++++ source/lldb-log.cpp (working copy)
+@@ -142,6 +142,7 @@
+ else if (0 == ::strncasecmp(arg, "symbol", 6)) flag_bits &= ~LIBLLDB_LOG_SYMBOLS;
+ else if (0 == ::strncasecmp(arg, "module", 6)) flag_bits &= ~LIBLLDB_LOG_MODULES;
+ else if (0 == ::strncasecmp(arg, "mmap", 4)) flag_bits &= ~LIBLLDB_LOG_MMAP;
++ else if (0 == ::strcasecmp(arg, "os")) flag_bits &= ~LIBLLDB_LOG_OS;
+ else
+ {
+ feedback_strm->Printf ("error: unrecognized log category '%s'\n", arg);
+@@ -211,6 +212,7 @@
+ else if (0 == ::strncasecmp(arg, "symbol", 6)) flag_bits |= LIBLLDB_LOG_SYMBOLS;
+ else if (0 == ::strncasecmp(arg, "module", 6)) flag_bits |= LIBLLDB_LOG_MODULES;
+ else if (0 == ::strncasecmp(arg, "mmap", 4)) flag_bits |= LIBLLDB_LOG_MMAP;
++ else if (0 == ::strcasecmp(arg, "os")) flag_bits |= LIBLLDB_LOG_OS;
+ else
+ {
+ feedback_strm->Printf("error: unrecognized log category '%s'\n", arg);
+Index: source/Host/macosx/launcherXPCService/LauncherRootXPCService-Info.plist
+===================================================================
+--- source/Host/macosx/launcherXPCService/LauncherRootXPCService-Info.plist (revision 183906)
++++ source/Host/macosx/launcherXPCService/LauncherRootXPCService-Info.plist (working copy)
+@@ -39,6 +39,8 @@
+ <string>root</string>
+ <key>ServiceType</key>
+ <string>Application</string>
++ <key>JoinExistingSession</key>
++ <true/>
+ </dict>
+ </dict>
+ </plist>
+Index: source/Host/linux/Host.cpp
+===================================================================
+--- source/Host/linux/Host.cpp (revision 183906)
++++ source/Host/linux/Host.cpp (working copy)
+@@ -25,6 +25,9 @@
+ #include "lldb/Core/DataBufferHeap.h"
+ #include "lldb/Core/DataExtractor.h"
+
++#include "lldb/Core/ModuleSpec.h"
++#include "lldb/Symbol/ObjectFile.h"
++
+ using namespace lldb;
+ using namespace lldb_private;
+
+@@ -47,6 +50,7 @@
+ // Get the process info with additional information from /proc/$PID/stat (like process state, and tracer pid).
+ static bool GetProcessAndStatInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info, ProcessStatInfo &stat_info, lldb::pid_t &tracerpid);
+
++
+ namespace
+ {
+
+@@ -291,7 +295,62 @@
+ return process_infos.GetSize();
+ }
+
++bool
++Host::FindProcessThreads (const lldb::pid_t pid, TidMap &tids_to_attach)
++{
++ bool tids_changed = false;
++ static const char procdir[] = "/proc/";
++ static const char taskdir[] = "/task/";
++ std::string process_task_dir = procdir + std::to_string(pid) + taskdir;
++ DIR *dirproc = opendir (process_task_dir.c_str());
++
++ if (dirproc)
++ {
++ struct dirent *direntry = NULL;
++ while ((direntry = readdir (dirproc)) != NULL)
++ {
++ if (direntry->d_type != DT_DIR || !IsDirNumeric (direntry->d_name))
++ continue;
++
++ lldb::tid_t tid = atoi(direntry->d_name);
++ TidMap::iterator it = tids_to_attach.find(tid);
++ if (it == tids_to_attach.end())
++ {
++ tids_to_attach.insert(TidPair(tid, false));
++ tids_changed = true;
++ }
++ }
++ closedir (dirproc);
++ }
++
++ return tids_changed;
++}
++
+ static bool
++GetELFProcessCPUType (const char *exe_path, ProcessInstanceInfo &process_info)
++{
++ // Clear the architecture.
++ process_info.GetArchitecture().Clear();
++
++ ModuleSpecList specs;
++ FileSpec filespec (exe_path, false);
++ const size_t num_specs = ObjectFile::GetModuleSpecifications (filespec, 0, specs);
++ // GetModuleSpecifications() could fail if the executable has been deleted or is locked.
++ // But it shouldn't return more than 1 architecture.
++ assert(num_specs <= 1 && "Linux plugin supports only a single architecture");
++ if (num_specs == 1)
++ {
++ ModuleSpec module_spec;
++ if (specs.GetModuleSpecAtIndex (0, module_spec) && module_spec.GetArchitecture().IsValid())
++ {
++ process_info.GetArchitecture () = module_spec.GetArchitecture();
++ return true;
++ }
++ }
++ return false;
++}
++
++static bool
+ GetProcessAndStatInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info, ProcessStatInfo &stat_info, lldb::pid_t &tracerpid)
+ {
+ tracerpid = 0;
+@@ -299,9 +358,6 @@
+ ::memset (&stat_info, 0, sizeof(stat_info));
+ stat_info.ppid = LLDB_INVALID_PROCESS_ID;
+
+- // Architecture is intentionally omitted because that's better resolved
+- // in other places (see ProcessPOSIX::DoAttachWithID().
+-
+ // Use special code here because proc/[pid]/exe is a symbolic link.
+ char link_path[PATH_MAX];
+ char exe_path[PATH_MAX] = "";
+@@ -323,6 +379,10 @@
+ {
+ exe_path[len - deleted_len] = 0;
+ }
++ else
++ {
++ GetELFProcessCPUType (exe_path, process_info);
++ }
+
+ process_info.SetProcessID(pid);
+ process_info.GetExecutableFile().SetFile(exe_path, false);
+Index: source/Host/common/Host.cpp
+===================================================================
+--- source/Host/common/Host.cpp (revision 183906)
++++ source/Host/common/Host.cpp (working copy)
+@@ -173,7 +173,11 @@
+ if (errno == EINTR)
+ continue;
+ else
++ {
++ if (log)
++ log->Printf ("%s (arg = %p) thread exiting because waitpid failed (%s)...", __FUNCTION__, arg, strerror(errno));
+ break;
++ }
+ }
+ else if (wait_pid > 0)
+ {
+@@ -190,8 +194,7 @@
+ {
+ exit_status = WEXITSTATUS(status);
+ status_cstr = "EXITED";
+- if (wait_pid == pid)
+- exited = true;
++ exited = true;
+ }
+ else if (WIFSIGNALED(status))
+ {
+@@ -230,12 +233,20 @@
+ callback_return = callback (callback_baton, wait_pid, exited, signal, exit_status);
+
+ // If our process exited, then this thread should exit
+- if (exited)
++ if (exited && wait_pid == pid)
++ {
++ if (log)
++ log->Printf ("%s (arg = %p) thread exiting because pid received exit signal...", __FUNCTION__, arg);
+ break;
++ }
+ // If the callback returns true, it means this process should
+ // exit
+ if (callback_return)
++ {
++ if (log)
++ log->Printf ("%s (arg = %p) thread exiting because callback returned true...", __FUNCTION__, arg);
+ break;
++ }
+ }
+ }
+ }
+@@ -1227,6 +1238,14 @@
+ }
+ #endif
+
++#if !defined(__linux__)
++bool
++Host::FindProcessThreads (const lldb::pid_t pid, TidMap &tids_to_attach)
++{
++ return false;
++}
++#endif
++
+ lldb::TargetSP
+ Host::GetDummyTarget (lldb_private::Debugger &debugger)
+ {
+Index: source/Host/common/File.cpp
+===================================================================
+--- source/Host/common/File.cpp (revision 183906)
++++ source/Host/common/File.cpp (working copy)
+@@ -318,58 +318,109 @@
+ return error;
+ }
+
+-Error
+-File::SeekFromStart (off_t& offset)
++off_t
++File::SeekFromStart (off_t offset, Error *error_ptr)
+ {
+- Error error;
++ off_t result = 0;
+ if (DescriptorIsValid())
+ {
+- offset = ::lseek (m_descriptor, offset, SEEK_SET);
++ result = ::lseek (m_descriptor, offset, SEEK_SET);
+
+- if (offset == -1)
+- error.SetErrorToErrno();
++ if (error_ptr)
++ {
++ if (result == -1)
++ error_ptr->SetErrorToErrno();
++ else
++ error_ptr->Clear();
++ }
+ }
+- else
++ else if (StreamIsValid ())
+ {
+- error.SetErrorString("invalid file handle");
++ result = ::fseek(m_stream, offset, SEEK_SET);
++
++ if (error_ptr)
++ {
++ if (result == -1)
++ error_ptr->SetErrorToErrno();
++ else
++ error_ptr->Clear();
++ }
+ }
+- return error;
++ else if (error_ptr)
++ {
++ error_ptr->SetErrorString("invalid file handle");
++ }
++ return result;
+ }
+
+-Error
+-File::SeekFromCurrent (off_t& offset)
++off_t
++File::SeekFromCurrent (off_t offset, Error *error_ptr)
+ {
+- Error error;
++ off_t result = -1;
+ if (DescriptorIsValid())
+ {
+- offset = ::lseek (m_descriptor, offset, SEEK_CUR);
++ result = ::lseek (m_descriptor, offset, SEEK_CUR);
+
+- if (offset == -1)
+- error.SetErrorToErrno();
++ if (error_ptr)
++ {
++ if (result == -1)
++ error_ptr->SetErrorToErrno();
++ else
++ error_ptr->Clear();
++ }
+ }
+- else
++ else if (StreamIsValid ())
+ {
+- error.SetErrorString("invalid file handle");
++ result = ::fseek(m_stream, offset, SEEK_CUR);
++
++ if (error_ptr)
++ {
++ if (result == -1)
++ error_ptr->SetErrorToErrno();
++ else
++ error_ptr->Clear();
++ }
+ }
+- return error;
++ else if (error_ptr)
++ {
++ error_ptr->SetErrorString("invalid file handle");
++ }
++ return result;
+ }
+
+-Error
+-File::SeekFromEnd (off_t& offset)
++off_t
++File::SeekFromEnd (off_t offset, Error *error_ptr)
+ {
+- Error error;
++ off_t result = -1;
+ if (DescriptorIsValid())
+ {
+- offset = ::lseek (m_descriptor, offset, SEEK_END);
++ result = ::lseek (m_descriptor, offset, SEEK_END);
+
+- if (offset == -1)
+- error.SetErrorToErrno();
++ if (error_ptr)
++ {
++ if (result == -1)
++ error_ptr->SetErrorToErrno();
++ else
++ error_ptr->Clear();
++ }
+ }
+- else
++ else if (StreamIsValid ())
+ {
+- error.SetErrorString("invalid file handle");
++ result = ::fseek(m_stream, offset, SEEK_END);
++
++ if (error_ptr)
++ {
++ if (result == -1)
++ error_ptr->SetErrorToErrno();
++ else
++ error_ptr->Clear();
++ }
+ }
+- return error;
++ else if (error_ptr)
++ {
++ error_ptr->SetErrorString("invalid file handle");
++ }
++ return result;
+ }
+
+ Error
+Index: source/Host/common/Mutex.cpp
+===================================================================
+--- source/Host/common/Mutex.cpp (revision 183906)
++++ source/Host/common/Mutex.cpp (working copy)
+@@ -239,6 +239,7 @@
+ Mutex::~Mutex()
+ {
+ int err = ::pthread_mutex_destroy (&m_mutex);
++ assert(err == 0);
+ #if ENABLE_MUTEX_ERROR_CHECKING
+ if (err == 0)
+ error_check_mutex (&m_mutex, eMutexActionDestroyed);
+Index: source/CMakeLists.txt
+===================================================================
+--- source/CMakeLists.txt (revision 183906)
++++ source/CMakeLists.txt (working copy)
+@@ -7,6 +7,13 @@
+ )
+ 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)
+@@ -85,12 +92,27 @@
+ )
+ endif ()
+
++# FreeBSD-only libraries
++if ( CMAKE_SYSTEM_NAME MATCHES "FreeBSD" )
++ list(APPEND LLDB_USED_LIBS
++ lldbHostFreeBSD
++ lldbPluginProcessFreeBSD
++ lldbPluginProcessPOSIX
++ )
++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
+- lldbPluginOSDarwinKernel
+ lldbPluginProcessMacOSXKernel
+ lldbPluginSymbolVendorMacOSX
+ )
+@@ -143,9 +165,17 @@
+ lldb.cpp
+ lldb-log.cpp
+ ${LLDB_BINARY_DIR}/scripts/LLDBWrapPython.cpp
++ ${LLDB_VERS_GENERATED_FILE}
+ )
+-set_target_properties(liblldb PROPERTIES OUTPUT_NAME lldb)
+-add_dependencies(liblldb ${LLDB_BINARY_DIR}/scripts/LLDBWrapPython.cpp)
++set_target_properties(liblldb
++ PROPERTIES
++ OUTPUT_NAME lldb
++ VERSION ${LLDB_VERSION}
++ )
++add_dependencies(liblldb
++ ${LLDB_BINARY_DIR}/scripts/LLDBWrapPython.cpp
++ ${LLDB_VERS_GENERATED_FILE}
++ )
+ target_link_libraries(liblldb ${LLDB_SYSTEM_LIBS})
+
+ # Determine LLDB revision and repository. GetSourceVersion and GetRepositoryPath are shell-scripts, and as
+Index: source/DataFormatters/CXXFormatterFunctions.cpp
+===================================================================
+--- source/DataFormatters/CXXFormatterFunctions.cpp (revision 183906)
++++ source/DataFormatters/CXXFormatterFunctions.cpp (working copy)
+@@ -7,6 +7,8 @@
+ //
+ //===----------------------------------------------------------------------===//
+
++#include "lldb/lldb-python.h"
++
+ #include "lldb/DataFormatters/CXXFormatterFunctions.h"
+
+ #include "llvm/Support/ConvertUTF.h"
+@@ -902,7 +904,7 @@
+ stream.Printf("%s%" PRIu64 " byte%s%s",
+ (needs_at ? "@\"" : ""),
+ value,
+- (value > 1 ? "s" : ""),
++ (value != 1 ? "s" : ""),
+ (needs_at ? "\"" : ""));
+
+ return true;
+@@ -939,9 +941,14 @@
+
+ if (my_error.Fail())
+ return false;
++
++ dest.Printf("%c%c",prefix_token,quote);
++
+ if (my_data_read)
+- dest.Printf("%c%c%s%c",prefix_token,quote,(char*)buffer_sp->GetBytes(),quote);
++ dest.Printf("%s",(char*)buffer_sp->GetBytes());
+
++ dest.Printf("%c",quote);
++
+ return true;
+ }
+
+Index: source/DataFormatters/FormatManager.cpp
+===================================================================
+--- source/DataFormatters/FormatManager.cpp (revision 183906)
++++ source/DataFormatters/FormatManager.cpp (working copy)
+@@ -627,6 +627,9 @@
+ AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibcxxStdListSyntheticFrontEndCreator, "libc++ std::list synthetic children", ConstString("^std::__1::list<.+>(( )?&)?$"), stl_synth_flags, true);
+ AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator, "libc++ std::map synthetic children", ConstString("^std::__1::map<.+> >(( )?&)?$"), stl_synth_flags, true);
+ AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibcxxVectorBoolSyntheticFrontEndCreator, "libc++ std::vector<bool> synthetic children", ConstString("std::__1::vector<std::__1::allocator<bool> >"), stl_synth_flags);
++ AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator, "libc++ std::set synthetic children", ConstString("^std::__1::set<.+> >(( )?&)?$"), stl_synth_flags, true);
++ AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator, "libc++ std::multiset synthetic children", ConstString("^std::__1::multiset<.+> >(( )?&)?$"), stl_synth_flags, true);
++ AddCXXSynthetic(libcxx_category_sp, lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator, "libc++ std::multimap synthetic children", ConstString("^std::__1::multimap<.+> >(( )?&)?$"), stl_synth_flags, true);
+
+ libcxx_category_sp->GetRegexSyntheticNavigator()->Add(RegularExpressionSP(new RegularExpression("^(std::__1::)deque<.+>(( )?&)?$")),
+ SyntheticChildrenSP(new ScriptedSyntheticChildren(stl_synth_flags,
+@@ -642,6 +645,9 @@
+ AddCXXSummary(libcxx_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::map summary provider", ConstString("^std::__1::map<.+>(( )?&)?$"), stl_summary_flags, true);
+ AddCXXSummary(libcxx_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::deque summary provider", ConstString("^std::__1::deque<.+>(( )?&)?$"), stl_summary_flags, true);
+ AddCXXSummary(libcxx_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::vector<bool> summary provider", ConstString("std::__1::vector<std::__1::allocator<bool> >"), stl_summary_flags);
++ AddCXXSummary(libcxx_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::set summary provider", ConstString("^std::__1::set<.+>(( )?&)?$"), stl_summary_flags, true);
++ AddCXXSummary(libcxx_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::multiset summary provider", ConstString("^std::__1::multiset<.+>(( )?&)?$"), stl_summary_flags, true);
++ AddCXXSummary(libcxx_category_sp, lldb_private::formatters::LibcxxContainerSummaryProvider, "libc++ std::multimap summary provider", ConstString("^std::__1::multimap<.+>(( )?&)?$"), stl_summary_flags, true);
+
+ stl_summary_flags.SetSkipPointers(true);
+ AddStringSummary(libcxx_category_sp, "{${var.__ptr_%S}} (strong=${var.count} weak=${var.weak_count})}", ConstString("^std::__1::shared_ptr<.+>(( )?&)?$"), stl_summary_flags, true);
+@@ -685,6 +691,8 @@
+
+ sys_category_sp->GetSummaryNavigator()->Add(ConstString("char *"), string_format);
+ sys_category_sp->GetSummaryNavigator()->Add(ConstString("const char *"), string_format);
++ sys_category_sp->GetSummaryNavigator()->Add(ConstString("unsigned char *"), string_format);
++ sys_category_sp->GetSummaryNavigator()->Add(ConstString("const unsigned char *"), string_format);
+ sys_category_sp->GetRegexSummaryNavigator()->Add(any_size_char_arr, string_array_format);
+
+ lldb::TypeSummaryImplSP ostype_summary(new StringSummaryFormat(TypeSummaryImpl::Flags().SetCascades(false)
+Index: source/DataFormatters/Cocoa.cpp
+===================================================================
+--- source/DataFormatters/Cocoa.cpp (revision 183906)
++++ source/DataFormatters/Cocoa.cpp (working copy)
+@@ -7,6 +7,8 @@
+ //
+ //===----------------------------------------------------------------------===//
+
++#include "lldb/lldb-python.h"
++
+ #include "lldb/DataFormatters/CXXFormatterFunctions.h"
+
+ #include "lldb/Core/DataBufferHeap.h"
+@@ -284,7 +286,7 @@
+ return false;
+ }
+ } while (false);
+- stream.Printf("%llu index%s",
++ stream.Printf("%" PRIu64 " index%s",
+ count,
+ (count == 1 ? "" : "es"));
+ return true;
+Index: source/DataFormatters/LibCxxList.cpp
+===================================================================
+--- source/DataFormatters/LibCxxList.cpp (revision 183906)
++++ source/DataFormatters/LibCxxList.cpp (working copy)
+@@ -7,6 +7,8 @@
+ //
+ //===----------------------------------------------------------------------===//
+
++#include "lldb/lldb-python.h"
++
+ #include "lldb/DataFormatters/CXXFormatterFunctions.h"
+
+ #include "lldb/Core/DataBufferHeap.h"
+Index: source/DataFormatters/LibCxxMap.cpp
+===================================================================
+--- source/DataFormatters/LibCxxMap.cpp (revision 183906)
++++ source/DataFormatters/LibCxxMap.cpp (working copy)
+@@ -7,6 +7,8 @@
+ //
+ //===----------------------------------------------------------------------===//
+
++#include "lldb/lldb-python.h"
++
+ #include "lldb/DataFormatters/CXXFormatterFunctions.h"
+
+ #include "lldb/Core/DataBufferHeap.h"
+@@ -378,7 +380,7 @@
+ m_children.clear();
+ m_tree = m_backend.GetChildMemberWithName(ConstString("__tree_"), true).get();
+ if (!m_tree)
+- return NULL;
++ return false;
+ m_root_node = m_tree->GetChildMemberWithName(ConstString("__begin_node_"), true).get();
+ return false;
+ }
+Index: source/DataFormatters/CF.cpp
+===================================================================
+--- source/DataFormatters/CF.cpp (revision 183906)
++++ source/DataFormatters/CF.cpp (working copy)
+@@ -7,6 +7,8 @@
+ //
+ //===----------------------------------------------------------------------===//
+
++#include "lldb/lldb-python.h"
++
+ #include "lldb/DataFormatters/CXXFormatterFunctions.h"
+
+ #include "lldb/Core/DataBufferHeap.h"
+Index: source/DataFormatters/LibCxx.cpp
+===================================================================
+--- source/DataFormatters/LibCxx.cpp (revision 183906)
++++ source/DataFormatters/LibCxx.cpp (working copy)
+@@ -514,7 +514,7 @@
+ uint64_t value = valobj.GetValueAsUnsigned(0);
+ if (!value)
+ return false;
+- stream.Printf("0x%016llx ", value);
++ stream.Printf("0x%016" PRIx64 " ", value);
+ }
+- return Debugger::FormatPrompt("size=${svar%#}", NULL, NULL, NULL, stream, NULL, &valobj);
++ return Debugger::FormatPrompt("size=${svar%#}", NULL, NULL, NULL, stream, &valobj);
+ }
+Index: source/DataFormatters/TypeSummary.cpp
+===================================================================
+--- source/DataFormatters/TypeSummary.cpp (revision 183906)
++++ source/DataFormatters/TypeSummary.cpp (working copy)
+@@ -113,7 +113,7 @@
+ }
+ else
+ {
+- if (Debugger::FormatPrompt(m_format.c_str(), &sc, &exe_ctx, &sc.line_entry.range.GetBaseAddress(), s, NULL, valobj))
++ if (Debugger::FormatPrompt(m_format.c_str(), &sc, &exe_ctx, &sc.line_entry.range.GetBaseAddress(), s, valobj))
+ {
+ retval.assign(s.GetString());
+ return true;
+Index: source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
+===================================================================
+--- source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp (revision 183906)
++++ source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp (working copy)
+@@ -2599,7 +2599,7 @@
+ Error error;
+ uintptr_t slot_data = process->ReadPointerFromMemory(slot_ptr, error);
+ if (error.Fail() || slot_data == 0 || slot_data == LLDB_INVALID_ADDRESS)
+- return false;
++ return nullptr;
+ actual_class_descriptor_sp = m_runtime.GetClassDescriptor(slot_data);
+ if (!actual_class_descriptor_sp)
+ return ObjCLanguageRuntime::ClassDescriptorSP();
+Index: source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp
+===================================================================
+--- source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp (revision 183906)
++++ source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp (working copy)
+@@ -38,6 +38,8 @@
+ using namespace lldb;
+ using namespace lldb_private;
+
++#define PO_FUNCTION_TIMEOUT_USEC 15*1000*1000
++
+ bool
+ AppleObjCRuntime::GetObjectDescription (Stream &str, ValueObject &valobj)
+ {
+@@ -143,7 +145,7 @@
+ &wrapper_struct_addr,
+ error_stream,
+ stop_others,
+- 0 /* no timeout */,
++ PO_FUNCTION_TIMEOUT_USEC /* 15 secs timeout */,
+ try_all_threads,
+ unwind_on_error,
+ ignore_breakpoints,
+Index: source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp
+===================================================================
+--- source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp (revision 183906)
++++ source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp (working copy)
+@@ -21,6 +21,7 @@
+ #include "lldb/Core/Module.h"
+ #include "lldb/Core/PluginManager.h"
+ #include "lldb/Core/RegisterValue.h"
++#include "lldb/Core/StreamString.h"
+ #include "lldb/Core/ValueObjectVariable.h"
+ #include "lldb/Interpreter/CommandInterpreter.h"
+ #include "lldb/Interpreter/PythonDataObjects.h"
+@@ -134,7 +135,7 @@
+ {
+ if (!m_interpreter || !m_python_object_sp)
+ return NULL;
+- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
++ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OS));
+
+ if (log)
+ log->Printf ("OperatingSystemPython::GetDynamicRegisterInfo() fetching thread register definitions from python for pid %" PRIu64, m_process->GetID());
+@@ -173,7 +174,7 @@
+ if (!m_interpreter || !m_python_object_sp)
+ return false;
+
+- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
++ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OS));
+
+ // First thing we have to do is get the API lock, and the run lock. We're going to change the thread
+ // content of the process, and we're going to use python, which requires the API lock to do it.
+@@ -191,6 +192,12 @@
+ PythonList threads_list(m_interpreter->OSPlugin_ThreadsInfo(m_python_object_sp));
+ if (threads_list)
+ {
++ if (log)
++ {
++ StreamString strm;
++ threads_list.Dump(strm);
++ log->Printf("threads_list = %s", strm.GetString().c_str());
++ }
+ uint32_t i;
+ const uint32_t num_threads = threads_list.GetSize();
+ if (num_threads > 0)
+@@ -200,21 +207,6 @@
+ PythonDictionary thread_dict(threads_list.GetItemAtIndex(i));
+ if (thread_dict)
+ {
+- if (thread_dict.GetItemForKey("core"))
+- {
+- // We have some threads that are saying they are on a "core", which means
+- // they map the threads that are gotten from the lldb_private::Process subclass
+- // so clear the new threads list so the core threads don't show up
+- new_thread_list.Clear();
+- break;
+- }
+- }
+- }
+- for (i=0; i<num_threads; ++i)
+- {
+- PythonDictionary thread_dict(threads_list.GetItemAtIndex(i));
+- if (thread_dict)
+- {
+ ThreadSP thread_sp (CreateThreadFromThreadInfo (thread_dict, core_thread_list, old_thread_list, NULL));
+ if (thread_sp)
+ new_thread_list.AddThread(thread_sp);
+@@ -223,8 +215,10 @@
+ }
+ }
+
++ // No new threads added from the thread info array gotten from python, just
++ // display the core threads.
+ if (new_thread_list.GetSize(false) == 0)
+- new_thread_list = old_thread_list;
++ new_thread_list = core_thread_list;
+
+ return new_thread_list.GetSize(false) > 0;
+ }
+Index: source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+===================================================================
+--- source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp (revision 183906)
++++ source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp (working copy)
+@@ -7175,175 +7175,172 @@
+ }
+ }
+
+- if (location.IsValid())
+- {
+- ValueType scope = eValueTypeInvalid;
++ ValueType scope = eValueTypeInvalid;
+
+- const DWARFDebugInfoEntry *sc_parent_die = GetParentSymbolContextDIE(die);
+- dw_tag_t parent_tag = sc_parent_die ? sc_parent_die->Tag() : 0;
+- SymbolContextScope * symbol_context_scope = NULL;
++ const DWARFDebugInfoEntry *sc_parent_die = GetParentSymbolContextDIE(die);
++ dw_tag_t parent_tag = sc_parent_die ? sc_parent_die->Tag() : 0;
++ SymbolContextScope * symbol_context_scope = NULL;
+
+- // DWARF doesn't specify if a DW_TAG_variable is a local, global
+- // or static variable, so we have to do a little digging by
+- // looking at the location of a varaible to see if it contains
+- // a DW_OP_addr opcode _somewhere_ in the definition. I say
+- // somewhere because clang likes to combine small global variables
+- // into the same symbol and have locations like:
+- // DW_OP_addr(0x1000), DW_OP_constu(2), DW_OP_plus
+- // So if we don't have a DW_TAG_formal_parameter, we can look at
+- // the location to see if it contains a DW_OP_addr opcode, and
+- // then we can correctly classify our variables.
+- if (tag == DW_TAG_formal_parameter)
+- scope = eValueTypeVariableArgument;
+- else
++ // DWARF doesn't specify if a DW_TAG_variable is a local, global
++ // or static variable, so we have to do a little digging by
++ // looking at the location of a varaible to see if it contains
++ // a DW_OP_addr opcode _somewhere_ in the definition. I say
++ // somewhere because clang likes to combine small global variables
++ // into the same symbol and have locations like:
++ // DW_OP_addr(0x1000), DW_OP_constu(2), DW_OP_plus
++ // So if we don't have a DW_TAG_formal_parameter, we can look at
++ // the location to see if it contains a DW_OP_addr opcode, and
++ // then we can correctly classify our variables.
++ if (tag == DW_TAG_formal_parameter)
++ scope = eValueTypeVariableArgument;
++ else
++ {
++ bool op_error = false;
++ // Check if the location has a DW_OP_addr with any address value...
++ lldb::addr_t location_DW_OP_addr = LLDB_INVALID_ADDRESS;
++ if (!location_is_const_value_data)
+ {
+- bool op_error = false;
+- // Check if the location has a DW_OP_addr with any address value...
+- lldb::addr_t location_DW_OP_addr = LLDB_INVALID_ADDRESS;
+- if (!location_is_const_value_data)
++ location_DW_OP_addr = location.GetLocation_DW_OP_addr (0, op_error);
++ if (op_error)
+ {
+- location_DW_OP_addr = location.GetLocation_DW_OP_addr (0, op_error);
+- if (op_error)
+- {
+- StreamString strm;
+- location.DumpLocationForAddress (&strm, eDescriptionLevelFull, 0, 0, NULL);
+- GetObjectFile()->GetModule()->ReportError ("0x%8.8x: %s has an invalid location: %s", die->GetOffset(), DW_TAG_value_to_name(die->Tag()), strm.GetString().c_str());
+- }
++ StreamString strm;
++ location.DumpLocationForAddress (&strm, eDescriptionLevelFull, 0, 0, NULL);
++ GetObjectFile()->GetModule()->ReportError ("0x%8.8x: %s has an invalid location: %s", die->GetOffset(), DW_TAG_value_to_name(die->Tag()), strm.GetString().c_str());
+ }
++ }
+
+- if (location_DW_OP_addr != LLDB_INVALID_ADDRESS)
++ if (location_DW_OP_addr != LLDB_INVALID_ADDRESS)
++ {
++ if (is_external)
++ scope = eValueTypeVariableGlobal;
++ else
++ scope = eValueTypeVariableStatic;
++
++
++ SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile ();
++
++ if (debug_map_symfile)
+ {
+- if (is_external)
+- scope = eValueTypeVariableGlobal;
+- else
+- scope = eValueTypeVariableStatic;
+-
+-
+- SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile ();
+-
+- if (debug_map_symfile)
++ // When leaving the DWARF in the .o files on darwin,
++ // when we have a global variable that wasn't initialized,
++ // the .o file might not have allocated a virtual
++ // address for the global variable. In this case it will
++ // have created a symbol for the global variable
++ // that is undefined/data and external and the value will
++ // be the byte size of the variable. When we do the
++ // address map in SymbolFileDWARFDebugMap we rely on
++ // having an address, we need to do some magic here
++ // so we can get the correct address for our global
++ // variable. The address for all of these entries
++ // will be zero, and there will be an undefined symbol
++ // in this object file, and the executable will have
++ // a matching symbol with a good address. So here we
++ // dig up the correct address and replace it in the
++ // location for the variable, and set the variable's
++ // symbol context scope to be that of the main executable
++ // so the file address will resolve correctly.
++ bool linked_oso_file_addr = false;
++ if (is_external && location_DW_OP_addr == 0)
+ {
+- // When leaving the DWARF in the .o files on darwin,
+- // when we have a global variable that wasn't initialized,
+- // the .o file might not have allocated a virtual
+- // address for the global variable. In this case it will
+- // have created a symbol for the global variable
+- // that is undefined/data and external and the value will
+- // be the byte size of the variable. When we do the
+- // address map in SymbolFileDWARFDebugMap we rely on
+- // having an address, we need to do some magic here
+- // so we can get the correct address for our global
+- // variable. The address for all of these entries
+- // will be zero, and there will be an undefined symbol
+- // in this object file, and the executable will have
+- // a matching symbol with a good address. So here we
+- // dig up the correct address and replace it in the
+- // location for the variable, and set the variable's
+- // symbol context scope to be that of the main executable
+- // so the file address will resolve correctly.
+- bool linked_oso_file_addr = false;
+- if (is_external && location_DW_OP_addr == 0)
++
++ // we have a possible uninitialized extern global
++ ConstString const_name(mangled ? mangled : name);
++ ObjectFile *debug_map_objfile = debug_map_symfile->GetObjectFile();
++ if (debug_map_objfile)
+ {
+-
+- // we have a possible uninitialized extern global
+- ConstString const_name(mangled ? mangled : name);
+- ObjectFile *debug_map_objfile = debug_map_symfile->GetObjectFile();
+- if (debug_map_objfile)
++ Symtab *debug_map_symtab = debug_map_objfile->GetSymtab();
++ if (debug_map_symtab)
+ {
+- Symtab *debug_map_symtab = debug_map_objfile->GetSymtab();
+- if (debug_map_symtab)
++ Symbol *exe_symbol = debug_map_symtab->FindFirstSymbolWithNameAndType (const_name,
++ eSymbolTypeData,
++ Symtab::eDebugYes,
++ Symtab::eVisibilityExtern);
++ if (exe_symbol)
+ {
+- Symbol *exe_symbol = debug_map_symtab->FindFirstSymbolWithNameAndType (const_name,
+- eSymbolTypeData,
+- Symtab::eDebugYes,
+- Symtab::eVisibilityExtern);
+- if (exe_symbol)
++ if (exe_symbol->ValueIsAddress())
+ {
+- if (exe_symbol->ValueIsAddress())
++ const addr_t exe_file_addr = exe_symbol->GetAddress().GetFileAddress();
++ if (exe_file_addr != LLDB_INVALID_ADDRESS)
+ {
+- const addr_t exe_file_addr = exe_symbol->GetAddress().GetFileAddress();
+- if (exe_file_addr != LLDB_INVALID_ADDRESS)
++ if (location.Update_DW_OP_addr (exe_file_addr))
+ {
+- if (location.Update_DW_OP_addr (exe_file_addr))
+- {
+- linked_oso_file_addr = true;
+- symbol_context_scope = exe_symbol;
+- }
++ linked_oso_file_addr = true;
++ symbol_context_scope = exe_symbol;
+ }
+ }
+ }
+ }
+ }
+ }
++ }
+
+- if (!linked_oso_file_addr)
++ if (!linked_oso_file_addr)
++ {
++ // The DW_OP_addr is not zero, but it contains a .o file address which
++ // needs to be linked up correctly.
++ const lldb::addr_t exe_file_addr = debug_map_symfile->LinkOSOFileAddress(this, location_DW_OP_addr);
++ if (exe_file_addr != LLDB_INVALID_ADDRESS)
+ {
+- // The DW_OP_addr is not zero, but it contains a .o file address which
+- // needs to be linked up correctly.
+- const lldb::addr_t exe_file_addr = debug_map_symfile->LinkOSOFileAddress(this, location_DW_OP_addr);
+- if (exe_file_addr != LLDB_INVALID_ADDRESS)
+- {
+- // Update the file address for this variable
+- location.Update_DW_OP_addr (exe_file_addr);
+- }
+- else
+- {
+- // Variable didn't make it into the final executable
+- return var_sp;
+- }
++ // Update the file address for this variable
++ location.Update_DW_OP_addr (exe_file_addr);
+ }
++ else
++ {
++ // Variable didn't make it into the final executable
++ return var_sp;
++ }
+ }
+ }
+- else
+- {
+- scope = eValueTypeVariableLocal;
+- }
+ }
++ else
++ {
++ scope = eValueTypeVariableLocal;
++ }
++ }
+
+- if (symbol_context_scope == NULL)
++ if (symbol_context_scope == NULL)
++ {
++ switch (parent_tag)
+ {
+- switch (parent_tag)
++ case DW_TAG_subprogram:
++ case DW_TAG_inlined_subroutine:
++ case DW_TAG_lexical_block:
++ if (sc.function)
+ {
+- case DW_TAG_subprogram:
+- case DW_TAG_inlined_subroutine:
+- case DW_TAG_lexical_block:
+- if (sc.function)
+- {
+- symbol_context_scope = sc.function->GetBlock(true).FindBlockByID(MakeUserID(sc_parent_die->GetOffset()));
+- if (symbol_context_scope == NULL)
+- symbol_context_scope = sc.function;
+- }
+- break;
+-
+- default:
+- symbol_context_scope = sc.comp_unit;
+- break;
++ symbol_context_scope = sc.function->GetBlock(true).FindBlockByID(MakeUserID(sc_parent_die->GetOffset()));
++ if (symbol_context_scope == NULL)
++ symbol_context_scope = sc.function;
+ }
++ break;
++
++ default:
++ symbol_context_scope = sc.comp_unit;
++ break;
+ }
++ }
+
+- if (symbol_context_scope)
+- {
+- var_sp.reset (new Variable (MakeUserID(die->GetOffset()),
+- name,
+- mangled,
+- SymbolFileTypeSP (new SymbolFileType(*this, type_uid)),
+- scope,
+- symbol_context_scope,
+- &decl,
+- location,
+- is_external,
+- is_artificial));
+-
+- var_sp->SetLocationIsConstantValueData (location_is_const_value_data);
+- }
+- else
+- {
+- // Not ready to parse this variable yet. It might be a global
+- // or static variable that is in a function scope and the function
+- // in the symbol context wasn't filled in yet
+- return var_sp;
+- }
++ if (symbol_context_scope)
++ {
++ var_sp.reset (new Variable (MakeUserID(die->GetOffset()),
++ name,
++ mangled,
++ SymbolFileTypeSP (new SymbolFileType(*this, type_uid)),
++ scope,
++ symbol_context_scope,
++ &decl,
++ location,
++ is_external,
++ is_artificial));
++
++ var_sp->SetLocationIsConstantValueData (location_is_const_value_data);
+ }
++ else
++ {
++ // Not ready to parse this variable yet. It might be a global
++ // or static variable that is in a function scope and the function
++ // in the symbol context wasn't filled in yet
++ return var_sp;
++ }
+ }
+ // Cache var_sp even if NULL (the variable was just a specification or
+ // was missing vital information to be able to be displayed in the debugger
+Index: source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
+===================================================================
+--- source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp (revision 183906)
++++ source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp (working copy)
+@@ -54,6 +54,8 @@
+ return file_range_map;
+
+ ObjectFile *oso_objfile = oso_module->GetObjectFile();
++ if (!oso_objfile)
++ return file_range_map;
+
+ Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_MAP));
+ if (log)
+Index: source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
+===================================================================
+--- source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp (revision 183906)
++++ source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp (working copy)
+@@ -994,8 +994,9 @@
+ lc_segment_name,
+ load_cmd.fileoff,
+ m_length);
+- m_sections_ap->Clear();
+- return 0;
++
++ load_cmd.fileoff = 0;
++ load_cmd.filesize = 0;
+ }
+
+ if (load_cmd.fileoff + load_cmd.filesize > m_length)
+@@ -1006,13 +1007,14 @@
+ // is null out the SectionList vector and if a process has been set up, dump a message
+ // to stdout. The most common case here is core file debugging with a truncated file.
+ const char *lc_segment_name = load_cmd.cmd == LoadCommandSegment64 ? "LC_SEGMENT_64" : "LC_SEGMENT";
+- GetModule()->ReportError("is a corrupt mach-o file: load command %u %s has a fileoff + filesize (0x%" PRIx64 ") that extends beyond the end of the file (0x%" PRIx64 ")",
++ GetModule()->ReportError("is a corrupt mach-o file: load command %u %s has a fileoff + filesize (0x%" PRIx64 ") that extends beyond the end of the file (0x%" PRIx64 "), the segment will be truncated",
+ i,
+ lc_segment_name,
+ load_cmd.fileoff + load_cmd.filesize,
+ m_length);
+- m_sections_ap->Clear();
+- return 0;
++
++ // Tuncase the length
++ load_cmd.filesize = m_length - load_cmd.fileoff;
+ }
+ }
+ if (m_data.GetU32(&offset, &load_cmd.maxprot, 4))
+Index: source/Plugins/ObjectFile/ELF/ObjectFileELF.h
+===================================================================
+--- source/Plugins/ObjectFile/ELF/ObjectFileELF.h (revision 183906)
++++ source/Plugins/ObjectFile/ELF/ObjectFileELF.h (working copy)
+@@ -16,6 +16,7 @@
+ #include "lldb/lldb-private.h"
+ #include "lldb/Host/FileSpec.h"
+ #include "lldb/Symbol/ObjectFile.h"
++#include "lldb/Core/UUID.h"
+
+ #include "ELFHeader.h"
+
+@@ -65,6 +66,12 @@
+ lldb::offset_t file_offset,
+ lldb::offset_t length,
+ lldb_private::ModuleSpecList &specs);
++
++ static bool
++ MagicBytesMatch (lldb::DataBufferSP& data_sp,
++ lldb::addr_t offset,
++ lldb::addr_t length);
++
+ //------------------------------------------------------------------
+ // PluginInterface protocol
+ //------------------------------------------------------------------
+@@ -148,6 +155,9 @@
+ /// ELF file header.
+ elf::ELFHeader m_header;
+
++ /// ELF build ID
++ lldb_private::UUID m_uuid;
++
+ /// Collection of program headers.
+ ProgramHeaderColl m_program_headers;
+
+Index: source/Plugins/ObjectFile/ELF/ELFHeader.h
+===================================================================
+--- source/Plugins/ObjectFile/ELF/ELFHeader.h (revision 183906)
++++ source/Plugins/ObjectFile/ELF/ELFHeader.h (working copy)
+@@ -107,7 +107,7 @@
+ GetRelocationJumpSlotType() const;
+
+ //--------------------------------------------------------------------------
+- /// Parse an ELFSectionHeader entry starting at position \p offset and
++ /// Parse an ELFHeader entry starting at position \p offset and
+ /// update the data extractor with the address size and byte order
+ /// attributes as defined by the header.
+ ///
+@@ -120,7 +120,7 @@
+ /// advanced by the number of bytes read.
+ ///
+ /// @return
+- /// True if the ELFSectionHeader was successfully read and false
++ /// True if the ELFHeader was successfully read and false
+ /// otherwise.
+ bool
+ Parse(lldb_private::DataExtractor &data, lldb::offset_t *offset);
+Index: source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+===================================================================
+--- source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp (revision 183906)
++++ source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp (working copy)
+@@ -222,6 +222,18 @@
+ return NULL;
+ }
+
++bool
++ObjectFileELF::MagicBytesMatch (DataBufferSP& data_sp,
++ lldb::addr_t data_offset,
++ lldb::addr_t data_length)
++{
++ if (data_sp && data_sp->GetByteSize() > (llvm::ELF::EI_NIDENT + data_offset))
++ {
++ const uint8_t *magic = data_sp->GetBytes() + data_offset;
++ return ELFHeader::MagicBytesMatch(magic);
++ }
++ return false;
++}
+
+ size_t
+ ObjectFileELF::GetModuleSpecifications (const lldb_private::FileSpec& file,
+@@ -231,7 +243,39 @@
+ lldb::offset_t length,
+ lldb_private::ModuleSpecList &specs)
+ {
+- return 0;
++ const size_t initial_count = specs.GetSize();
++
++ if (ObjectFileELF::MagicBytesMatch(data_sp, 0, data_sp->GetByteSize()))
++ {
++ DataExtractor data;
++ data.SetData(data_sp);
++ elf::ELFHeader header;
++ if (header.Parse(data, &data_offset))
++ {
++ if (data_sp)
++ {
++ ModuleSpec spec;
++ spec.GetFileSpec() = file;
++ spec.GetArchitecture().SetArchitecture(eArchTypeELF,
++ header.e_machine,
++ LLDB_INVALID_CPUTYPE);
++ if (spec.GetArchitecture().IsValid())
++ {
++ // We could parse the ABI tag information (in .note, .notes, or .note.ABI-tag) to get the
++ // machine information. However, we'd have to read a good bit of the rest of the file,
++ // and this info isn't guaranteed to exist or be correct. More details here:
++ // http://refspecs.linuxfoundation.org/LSB_1.2.0/gLSB/noteabitag.html
++ // Instead of passing potentially incorrect information down the pipeline, grab
++ // the host information and use it.
++ spec.GetArchitecture().GetTriple().setOSName (Host::GetOSString().GetCString());
++ spec.GetArchitecture().GetTriple().setVendorName(Host::GetVendorString().GetCString());
++ specs.Append(spec);
++ }
++ }
++ }
++ }
++
++ return specs.GetSize() - initial_count;
+ }
+
+ //------------------------------------------------------------------
+@@ -311,14 +355,19 @@
+ bool
+ ObjectFileELF::ParseHeader()
+ {
+- lldb::offset_t offset = GetFileOffset();
++ lldb::offset_t offset = 0;
+ return m_header.Parse(m_data, &offset);
+ }
+
+ bool
+ ObjectFileELF::GetUUID(lldb_private::UUID* uuid)
+ {
+- // FIXME: Return MD5 sum here. See comment in ObjectFile.h.
++ if (m_uuid.IsValid())
++ {
++ *uuid = m_uuid;
++ return true;
++ }
++ // FIXME: Return MD5 sum here. See comment in ObjectFile.h.
+ return false;
+ }
+
+@@ -619,6 +668,51 @@
+ return NULL;
+ }
+
++static bool
++ParseNoteGNUBuildID(DataExtractor& data, lldb_private::UUID& uuid)
++{
++ // Try to parse the note section (ie .note.gnu.build-id|.notes|.note|...) and get the build id.
++ // BuildID documentation: https://fedoraproject.org/wiki/Releases/FeatureBuildId
++ struct
++ {
++ uint32_t name_len; // Length of note name
++ uint32_t desc_len; // Length of note descriptor
++ uint32_t type; // Type of note (1 is ABI_TAG, 3 is BUILD_ID)
++ } notehdr;
++ lldb::offset_t offset = 0;
++ static const uint32_t g_gnu_build_id = 3; // NT_GNU_BUILD_ID from elf.h
++
++ while (true)
++ {
++ if (data.GetU32 (&offset, ¬ehdr, 3) == NULL)
++ return false;
++
++ notehdr.name_len = llvm::RoundUpToAlignment (notehdr.name_len, 4);
++ notehdr.desc_len = llvm::RoundUpToAlignment (notehdr.desc_len, 4);
++
++ lldb::offset_t offset_next_note = offset + notehdr.name_len + notehdr.desc_len;
++
++ // 16 bytes is UUID|MD5, 20 bytes is SHA1
++ if ((notehdr.type == g_gnu_build_id) && (notehdr.name_len == 4) &&
++ (notehdr.desc_len == 16 || notehdr.desc_len == 20))
++ {
++ char name[4];
++ if (data.GetU8 (&offset, name, 4) == NULL)
++ return false;
++ if (!strcmp(name, "GNU"))
++ {
++ uint8_t uuidbuf[20];
++ if (data.GetU8 (&offset, &uuidbuf, notehdr.desc_len) == NULL)
++ return false;
++ uuid.SetBytes (uuidbuf, notehdr.desc_len);
++ return true;
++ }
++ }
++ offset = offset_next_note;
++ }
++ return false;
++}
++
+ SectionList *
+ ObjectFileELF::GetSectionList()
+ {
+@@ -685,8 +779,18 @@
+ else if (name == g_sect_name_dwarf_debug_ranges) sect_type = eSectionTypeDWARFDebugRanges;
+ else if (name == g_sect_name_dwarf_debug_str) sect_type = eSectionTypeDWARFDebugStr;
+ else if (name == g_sect_name_eh_frame) sect_type = eSectionTypeEHFrame;
++ else if (header.sh_type == SHT_NOTE)
++ {
++ if (!m_uuid.IsValid())
++ {
++ DataExtractor data;
++ if (vm_size && (GetData (header.sh_offset, vm_size, data) == vm_size))
++ {
++ ParseNoteGNUBuildID (data, m_uuid);
++ }
++ }
++ }
+
+-
+ SectionSP section_sp(new Section(
+ GetModule(), // Module to which this section belongs.
+ SectionIndex(I), // Section ID.
+@@ -1301,16 +1405,18 @@
+ void
+ ObjectFileELF::DumpELFProgramHeader_p_type(Stream *s, elf_word p_type)
+ {
+- const int kStrWidth = 10;
++ const int kStrWidth = 15;
+ switch (p_type)
+ {
+- CASE_AND_STREAM(s, PT_NULL , kStrWidth);
+- CASE_AND_STREAM(s, PT_LOAD , kStrWidth);
+- CASE_AND_STREAM(s, PT_DYNAMIC , kStrWidth);
+- CASE_AND_STREAM(s, PT_INTERP , kStrWidth);
+- CASE_AND_STREAM(s, PT_NOTE , kStrWidth);
+- CASE_AND_STREAM(s, PT_SHLIB , kStrWidth);
+- CASE_AND_STREAM(s, PT_PHDR , kStrWidth);
++ CASE_AND_STREAM(s, PT_NULL , kStrWidth);
++ CASE_AND_STREAM(s, PT_LOAD , kStrWidth);
++ CASE_AND_STREAM(s, PT_DYNAMIC , kStrWidth);
++ CASE_AND_STREAM(s, PT_INTERP , kStrWidth);
++ CASE_AND_STREAM(s, PT_NOTE , kStrWidth);
++ CASE_AND_STREAM(s, PT_SHLIB , kStrWidth);
++ CASE_AND_STREAM(s, PT_PHDR , kStrWidth);
++ CASE_AND_STREAM(s, PT_TLS , kStrWidth);
++ CASE_AND_STREAM(s, PT_GNU_EH_FRAME, kStrWidth);
+ default:
+ s->Printf("0x%8.8x%*s", p_type, kStrWidth - 10, "");
+ break;
+@@ -1344,9 +1450,9 @@
+ if (ParseProgramHeaders())
+ {
+ s->PutCString("Program Headers\n");
+- s->PutCString("IDX p_type p_offset p_vaddr p_paddr "
++ s->PutCString("IDX p_type p_offset p_vaddr p_paddr "
+ "p_filesz p_memsz p_flags p_align\n");
+- s->PutCString("==== ---------- -------- -------- -------- "
++ s->PutCString("==== --------------- -------- -------- -------- "
+ "-------- -------- ------------------------- --------\n");
+
+ uint32_t idx = 0;
+Index: source/Plugins/ObjectFile/ELF/ELFHeader.cpp
+===================================================================
+--- source/Plugins/ObjectFile/ELF/ELFHeader.cpp (revision 183906)
++++ source/Plugins/ObjectFile/ELF/ELFHeader.cpp (working copy)
+@@ -305,7 +305,7 @@
+ const lldb_private::DataExtractor *strtab_data,
+ const lldb_private::SectionList *section_list)
+ {
+- s->Printf("[%3u] 0x%16.16llx 0x%16.16llx 0x%8.8x 0x%2.2x (%-10s %-13s) 0x%2.2x 0x%4.4x (%-10s) %s\n",
++ s->Printf("[%3u] 0x%16.16" PRIx64 " 0x%16.16" PRIx64 " 0x%8.8x 0x%2.2x (%-10s %-13s) 0x%2.2x 0x%4.4x (%-10s) %s\n",
+ idx,
+ st_value,
+ st_size,
+Index: source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp
+===================================================================
+--- source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp (revision 183906)
++++ source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp (working copy)
+@@ -457,7 +457,7 @@
+ module_sp->GetObjectModificationTime());
+ if (object)
+ {
+- lldb::offset_t data_offset = m_offset + object->ar_file_offset;
++ lldb::offset_t data_offset = object->ar_file_offset;
+ return ObjectFile::FindPlugin (module_sp,
+ file,
+ m_offset + object->ar_file_offset,
+Index: source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h
+===================================================================
+--- source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h (revision 183906)
++++ source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h (working copy)
+@@ -52,9 +52,6 @@
+
+ DynamicLoaderDarwinKernel (lldb_private::Process *process, lldb::addr_t kernel_addr);
+
+- static lldb::addr_t
+- SearchForDarwinKernel (lldb_private::Process *process);
+-
+ virtual
+ ~DynamicLoaderDarwinKernel ();
+
+@@ -344,6 +341,9 @@
+ KextImageInfo::collection &image_infos);
+
+ static lldb::addr_t
++ SearchForDarwinKernel (lldb_private::Process *process);
++
++ static lldb::addr_t
+ SearchForKernelAtSameLoadAddr (lldb_private::Process *process);
+
+ static lldb::addr_t
+Index: source/Plugins/Process/POSIX/ProcessPOSIX.h
+===================================================================
+--- source/Plugins/Process/POSIX/ProcessPOSIX.h (revision 183906)
++++ source/Plugins/Process/POSIX/ProcessPOSIX.h (working copy)
+@@ -152,6 +152,11 @@
+ GetFilePath(const lldb_private::ProcessLaunchInfo::FileAction *file_action,
+ const char *default_path);
+
++ /// Stops all threads in the process.
++ /// The \p stop_tid parameter indicates the thread which initiated the stop.
++ virtual void
++ StopAllThreads(lldb::tid_t stop_tid);
++
+ protected:
+ /// Target byte order.
+ lldb::ByteOrder m_byte_order;
+Index: source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.h
+===================================================================
+--- source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.h (revision 183906)
++++ source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.h (working copy)
+@@ -17,7 +17,6 @@
+ {
+ public:
+ RegisterContextFreeBSD_x86_64(lldb_private::Thread &thread, uint32_t concrete_frame_idx);
+- virtual ~RegisterContextFreeBSD_x86_64();
+
+ size_t
+ GetGPRSize();
+@@ -28,9 +27,6 @@
+
+ virtual void
+ UpdateRegisterInfo();
+-
+-private:
+- static lldb_private::RegisterInfo *m_register_infos;
+ };
+
+ #endif
+Index: source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp
+===================================================================
+--- source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp (revision 183906)
++++ source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp (working copy)
+@@ -1242,6 +1242,8 @@
+ bool is_vacant = false;
+ RegisterValue value;
+
++ assert(hw_index < NumSupportedHardwareWatchpoints());
++
+ if (ReadRegister(dr7, value))
+ {
+ uint64_t val = value.GetAsUInt64();
+@@ -1282,23 +1284,47 @@
+ bool read, bool write)
+ {
+ const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
++ uint32_t hw_index;
+
+- if (num_hw_watchpoints == 0)
+- return LLDB_INVALID_INDEX32;
++ for (hw_index = 0; hw_index < num_hw_watchpoints; ++hw_index)
++ {
++ if (IsWatchpointVacant(hw_index))
++ return SetHardwareWatchpointWithIndex(addr, size,
++ read, write,
++ hw_index);
++ }
+
++ return LLDB_INVALID_INDEX32;
++}
++
++bool
++RegisterContext_x86_64::SetHardwareWatchpointWithIndex(addr_t addr, size_t size,
++ bool read, bool write,
++ uint32_t hw_index)
++{
++ const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
++
++ if (num_hw_watchpoints == 0 || hw_index >= num_hw_watchpoints)
++ return false;
++
+ if (!(size == 1 || size == 2 || size == 4 || size == 8))
+- return LLDB_INVALID_INDEX32;
++ return false;
+
+ if (read == false && write == false)
+- return LLDB_INVALID_INDEX32;
++ return false;
+
+- uint32_t hw_index = 0;
+- for (hw_index = 0; hw_index < num_hw_watchpoints; ++hw_index)
++ if (m_watchpoints_initialized == false)
+ {
+- if (IsWatchpointVacant(hw_index))
+- break;
++ // Reset the debug status and debug control registers
++ RegisterValue zero_bits = RegisterValue(uint64_t(0));
++ if (!WriteRegister(dr6, zero_bits) || !WriteRegister(dr7, zero_bits))
++ return false;
++ m_watchpoints_initialized = true;
+ }
+
++ if (!IsWatchpointVacant(hw_index))
++ return false;
++
+ // Set both dr7 (debug control register) and dri (debug address register).
+
+ // dr7{7-0} encodes the local/gloabl enable bits:
+@@ -1335,11 +1361,11 @@
+
+ if (WriteRegister(dr0 + hw_index, RegisterValue(addr)) &&
+ WriteRegister(dr7, RegisterValue(new_dr7_bits)))
+- return hw_index;
++ return true;
+ }
+ }
+
+- return LLDB_INVALID_INDEX32;
++ return false;
+ }
+
+ bool
+Index: source/Plugins/Process/POSIX/RegisterContext_x86_64.h
+===================================================================
+--- source/Plugins/Process/POSIX/RegisterContext_x86_64.h (revision 183906)
++++ source/Plugins/Process/POSIX/RegisterContext_x86_64.h (working copy)
+@@ -193,6 +193,10 @@
+ SetHardwareWatchpoint(lldb::addr_t, size_t size, bool read, bool write);
+
+ bool
++ SetHardwareWatchpointWithIndex(lldb::addr_t, size_t size, bool read,
++ bool write, uint32_t hw_index);
++
++ bool
+ ClearHardwareWatchpoint(uint32_t hw_index);
+
+ bool
+Index: source/Plugins/Process/POSIX/RegisterContextPOSIX.h
+===================================================================
+--- source/Plugins/Process/POSIX/RegisterContextPOSIX.h (revision 183906)
++++ source/Plugins/Process/POSIX/RegisterContextPOSIX.h (working copy)
+@@ -25,7 +25,8 @@
+ public:
+ RegisterContextPOSIX(lldb_private::Thread &thread,
+ uint32_t concrete_frame_idx)
+- : RegisterContext(thread, concrete_frame_idx) { }
++ : RegisterContext(thread, concrete_frame_idx)
++ { m_watchpoints_initialized = false; }
+
+ /// Updates the register state of the associated thread after hitting a
+ /// breakpoint (if that make sense for the architecture). Default
+@@ -52,7 +53,18 @@
+ // Returns the watchpoint address associated with a watchpoint hardware
+ // index.
+ virtual lldb::addr_t
+- GetWatchpointAddress (uint32_t hw_index) {return LLDB_INVALID_ADDRESS; }
++ GetWatchpointAddress (uint32_t hw_index) { return LLDB_INVALID_ADDRESS; }
++
++ virtual bool
++ IsWatchpointVacant (uint32_t hw_index) { return false; }
++
++ virtual bool
++ SetHardwareWatchpointWithIndex (lldb::addr_t addr, size_t size,
++ bool read, bool write,
++ uint32_t hw_index) { return false; }
++
++protected:
++ bool m_watchpoints_initialized;
+ };
+
+ #endif // #ifndef liblldb_RegisterContextPOSIX_H_
+Index: source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.cpp
+===================================================================
+--- source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.cpp (revision 183906)
++++ source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.cpp (working copy)
+@@ -8,6 +8,7 @@
+ //===---------------------------------------------------------------------===//
+
+ #include "RegisterContextLinux_x86_64.h"
++#include <vector>
+
+ using namespace lldb_private;
+
+@@ -18,13 +19,13 @@
+ // Update the Linux specific information (offset and size).
+ #define UPDATE_GPR_INFO(reg) \
+ do { \
+- m_register_infos[gpr_##reg].byte_size = sizeof(GPR::reg); \
+- m_register_infos[gpr_##reg].byte_offset = GPR_OFFSET(reg); \
++ GetRegisterContext()[gpr_##reg].byte_size = sizeof(GPR::reg); \
++ GetRegisterContext()[gpr_##reg].byte_offset = GPR_OFFSET(reg); \
+ } while(false);
+
+ #define UPDATE_I386_GPR_INFO(i386_reg, reg) \
+ do { \
+- m_register_infos[gpr_##i386_reg].byte_offset = GPR_OFFSET(reg); \
++ GetRegisterContext()[gpr_##i386_reg].byte_offset = GPR_OFFSET(reg); \
+ } while(false);
+
+ #define DR_OFFSET(reg_index) \
+@@ -32,8 +33,8 @@
+
+ #define UPDATE_DR_INFO(reg_index) \
+ do { \
+- m_register_infos[dr##reg_index].byte_size = sizeof(UserArea::u_debugreg[0]); \
+- m_register_infos[dr##reg_index].byte_offset = DR_OFFSET(reg_index); \
++ GetRegisterContext()[dr##reg_index].byte_size = sizeof(UserArea::u_debugreg[0]); \
++ GetRegisterContext()[dr##reg_index].byte_offset = DR_OFFSET(reg_index); \
+ } while(false);
+
+ typedef struct _GPR
+@@ -92,20 +93,17 @@
+ uint64_t fault_address; // Control register CR3.
+ };
+
+-RegisterInfo *RegisterContextLinux_x86_64::m_register_infos = nullptr;
++// Use a singleton function to avoid global constructors in shared libraries.
++static std::vector<RegisterInfo> & GetRegisterContext () {
++ static std::vector<RegisterInfo> g_register_infos;
++ return g_register_infos;
++}
+
+ RegisterContextLinux_x86_64::RegisterContextLinux_x86_64(Thread &thread, uint32_t concrete_frame_idx):
+ RegisterContext_x86_64(thread, concrete_frame_idx)
+ {
+ }
+
+-RegisterContextLinux_x86_64::~RegisterContextLinux_x86_64()
+-{
+- if (m_register_infos)
+- delete m_register_infos;
+- m_register_infos = nullptr;
+-}
+-
+ size_t
+ RegisterContextLinux_x86_64::GetGPRSize()
+ {
+@@ -116,19 +114,18 @@
+ RegisterContextLinux_x86_64::GetRegisterInfo()
+ {
+ // Allocate RegisterInfo only once
+- if (!m_register_infos)
++ if (GetRegisterContext().empty())
+ {
+- m_register_infos = new RegisterInfo[k_num_registers];
+ // Copy the register information from base class
+- if (m_register_infos)
++ const RegisterInfo *base_info = RegisterContext_x86_64::GetRegisterInfo();
++ if (base_info)
+ {
+- memcpy(m_register_infos, RegisterContext_x86_64::GetRegisterInfo(),
+- sizeof(RegisterInfo) * k_num_registers);
++ GetRegisterContext().insert(GetRegisterContext().end(), &base_info[0], &base_info[k_num_registers]);
+ // Update the Linux specific register information (offset and size).
+ UpdateRegisterInfo();
+ }
+ }
+- return m_register_infos;
++ return &GetRegisterContext()[0];
+ }
+
+ void
+Index: source/Plugins/Process/POSIX/ProcessMessage.h
+===================================================================
+--- source/Plugins/Process/POSIX/ProcessMessage.h (revision 183906)
++++ source/Plugins/Process/POSIX/ProcessMessage.h (working copy)
+@@ -117,11 +117,16 @@
+ return message;
+ }
+
+- /// Indicates that the thread @p tid was spawned.
++ /// Indicates that the thread @p child_tid was spawned.
+ static ProcessMessage NewThread(lldb::tid_t parent_tid, lldb::tid_t child_tid) {
+ return ProcessMessage(parent_tid, eNewThreadMessage, child_tid);
+ }
+
++ /// Indicates that the thread @p tid is about to exit with status @p status.
++ static ProcessMessage Exit(lldb::tid_t tid, int status) {
++ return ProcessMessage(tid, eExitMessage, status);
++ }
++
+ int GetExitStatus() const {
+ assert(GetKind() == eExitMessage || GetKind() == eLimboMessage);
+ return m_status;
+Index: source/Plugins/Process/POSIX/POSIXThread.cpp
+===================================================================
+--- source/Plugins/Process/POSIX/POSIXThread.cpp (revision 183906)
++++ source/Plugins/Process/POSIX/POSIXThread.cpp (working copy)
+@@ -17,6 +17,7 @@
+ // Project includes
+ #include "lldb/Breakpoint/Watchpoint.h"
+ #include "lldb/Core/Debugger.h"
++#include "lldb/Core/State.h"
+ #include "lldb/Host/Host.h"
+ #include "lldb/Target/Process.h"
+ #include "lldb/Target/StopInfo.h"
+@@ -45,6 +46,20 @@
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
+ if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
+ log->Printf ("POSIXThread::%s (tid = %" PRIi64 ")", __FUNCTION__, tid);
++
++ // Set the current watchpoints for this thread.
++ Target &target = GetProcess()->GetTarget();
++ const WatchpointList &wp_list = target.GetWatchpointList();
++ size_t wp_size = wp_list.GetSize();
++
++ for (uint32_t wp_idx = 0; wp_idx < wp_size; wp_idx++)
++ {
++ lldb::WatchpointSP wp = wp_list.GetByIndex(wp_idx);
++ if (wp.get() && wp->IsEnabled())
++ {
++ assert(EnableHardwareWatchpoint(wp.get()));
++ }
++ }
+ }
+
+ POSIXThread::~POSIXThread()
+@@ -63,15 +78,24 @@
+ void
+ POSIXThread::RefreshStateAfterStop()
+ {
++ // Invalidate all registers in our register context. We don't set "force" to
++ // true because the stop reply packet might have had some register values
++ // that were expedited and these will already be copied into the register
++ // context by the time this function gets called. The KDPRegisterContext
++ // class has been made smart enough to detect when it needs to invalidate
++ // which registers are valid by putting hooks in the register read and
++ // register supply functions where they check the process stop ID and do
++ // the right thing.
++ //if (StateIsStoppedState(GetState())
++ {
++ const bool force = false;
++ GetRegisterContext()->InvalidateIfNeeded (force);
++ }
++ // FIXME: This should probably happen somewhere else.
++ SetResumeState(eStateRunning);
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
+- if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
+- log->Printf ("POSIXThread::%s ()", __FUNCTION__);
+-
+- // Let all threads recover from stopping and do any clean up based
+- // on the previous thread state (if any).
+- ProcessSP base = GetProcess();
+- ProcessPOSIX &process = static_cast<ProcessPOSIX&>(*base);
+- process.GetThreadList().RefreshStateAfterStop();
++ if (log)
++ log->Printf ("POSIXThread::%s (tid = %" PRIi64 ") setting thread resume state to running", __FUNCTION__, GetID());
+ }
+
+ const char *
+@@ -157,11 +181,20 @@
+ void
+ POSIXThread::WillResume(lldb::StateType resume_state)
+ {
+- // TODO: the line below shouldn't really be done, but
++ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
++ if (log)
++ log->Printf ("POSIXThread::%s (tid = %" PRIi64 ") setting thread resume state to %s", __FUNCTION__, GetID(), StateAsCString(resume_state));
++ // TODO: the line below shouldn't really be done, but
+ // the POSIXThread might rely on this so I will leave this in for now
+ SetResumeState(resume_state);
+ }
+
++void
++POSIXThread::DidStop()
++{
++ // Don't set the thread state to stopped unless we really stopped.
++}
++
+ bool
+ POSIXThread::Resume()
+ {
+@@ -170,8 +203,9 @@
+ bool status;
+
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
+- if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
+- log->Printf ("POSIXThread::%s ()", __FUNCTION__);
++ if (log)
++ log->Printf ("POSIXThread::%s (), resume_state = %s", __FUNCTION__,
++ StateAsCString(resume_state));
+
+ switch (resume_state)
+ {
+@@ -211,10 +245,14 @@
+ assert(false && "Unexpected message kind!");
+ break;
+
++ case ProcessMessage::eExitMessage:
++ // Nothing to be done.
++ break;
++
+ case ProcessMessage::eLimboMessage:
+ LimboNotify(message);
+ break;
+-
++
+ case ProcessMessage::eSignalMessage:
+ SignalNotify(message);
+ break;
+@@ -248,27 +286,21 @@
+ bool
+ POSIXThread::EnableHardwareWatchpoint(Watchpoint *wp)
+ {
+- bool result = false;
++ bool wp_set = false;
+ if (wp)
+ {
+ addr_t wp_addr = wp->GetLoadAddress();
+ size_t wp_size = wp->GetByteSize();
+ bool wp_read = wp->WatchpointRead();
+ bool wp_write = wp->WatchpointWrite();
+- uint32_t wp_hw_index;
+- lldb::RegisterContextSP reg_ctx_sp = GetRegisterContext();
+- if (reg_ctx_sp.get())
+- {
+- wp_hw_index = reg_ctx_sp->SetHardwareWatchpoint(wp_addr, wp_size,
+- wp_read, wp_write);
+- if (wp_hw_index != LLDB_INVALID_INDEX32)
+- {
+- wp->SetHardwareIndex(wp_hw_index);
+- result = true;
+- }
+- }
++ uint32_t wp_hw_index = wp->GetHardwareIndex();
++ RegisterContextPOSIX* reg_ctx = GetRegisterContextPOSIX();
++ if (reg_ctx)
++ wp_set = reg_ctx->SetHardwareWatchpointWithIndex(wp_addr, wp_size,
++ wp_read, wp_write,
++ wp_hw_index);
+ }
+- return result;
++ return wp_set;
+ }
+
+ bool
+@@ -279,11 +311,7 @@
+ {
+ lldb::RegisterContextSP reg_ctx_sp = GetRegisterContext();
+ if (reg_ctx_sp.get())
+- {
+ result = reg_ctx_sp->ClearHardwareWatchpoint(wp->GetHardwareIndex());
+- if (result == true)
+- wp->SetHardwareIndex(LLDB_INVALID_INDEX32);
+- }
+ }
+ return result;
+ }
+@@ -297,6 +325,27 @@
+ return 0;
+ }
+
++uint32_t
++POSIXThread::FindVacantWatchpointIndex()
++{
++ uint32_t hw_index = LLDB_INVALID_INDEX32;
++ uint32_t num_hw_wps = NumSupportedHardwareWatchpoints();
++ uint32_t wp_idx;
++ RegisterContextPOSIX* reg_ctx = GetRegisterContextPOSIX();
++ if (reg_ctx)
++ {
++ for (wp_idx = 0; wp_idx < num_hw_wps; wp_idx++)
++ {
++ if (reg_ctx->IsWatchpointVacant(wp_idx))
++ {
++ hw_index = wp_idx;
++ break;
++ }
++ }
++ }
++ return hw_index;
++}
++
+ void
+ POSIXThread::BreakNotify(const ProcessMessage &message)
+ {
+@@ -318,6 +367,9 @@
+ lldb::break_id_t bp_id = bp_site->GetID();
+ assert(bp_site && bp_site->ValidForThisThread(this));
+
++ // Make this thread the selected thread
++ GetProcess()->GetThreadList().SetSelectedThreadByID(GetID());
++
+ m_breakpoint = bp_site;
+ SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id));
+ }
+@@ -408,6 +460,7 @@
+ void
+ POSIXThread::CrashNotify(const ProcessMessage &message)
+ {
++ // FIXME: Update stop reason as per bugzilla 14598
+ int signo = message.GetSignal();
+
+ assert(message.GetKind() == ProcessMessage::eCrashMessage);
+Index: source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.h
+===================================================================
+--- source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.h (revision 183906)
++++ source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.h (working copy)
+@@ -17,7 +17,6 @@
+ {
+ public:
+ RegisterContextLinux_x86_64(lldb_private::Thread &thread, uint32_t concrete_frame_idx);
+- virtual ~RegisterContextLinux_x86_64();
+
+ size_t
+ GetGPRSize();
+@@ -28,9 +27,6 @@
+
+ virtual void
+ UpdateRegisterInfo();
+-
+-private:
+- static lldb_private::RegisterInfo *m_register_infos;
+ };
+
+ #endif
+Index: source/Plugins/Process/POSIX/POSIXThread.h
+===================================================================
+--- source/Plugins/Process/POSIX/POSIXThread.h (revision 183906)
++++ source/Plugins/Process/POSIX/POSIXThread.h (working copy)
+@@ -39,6 +39,10 @@
+ virtual void
+ WillResume(lldb::StateType resume_state);
+
++ // This notifies the thread when a private stop occurs.
++ virtual void
++ DidStop ();
++
+ const char *
+ GetInfo();
+
+@@ -78,6 +82,8 @@
+
+ uint32_t NumSupportedHardwareWatchpoints();
+
++ uint32_t FindVacantWatchpointIndex();
++
+ private:
+ RegisterContextPOSIX *
+ GetRegisterContextPOSIX ()
+@@ -108,6 +114,7 @@
+ void SignalDeliveredNotify(const ProcessMessage &message);
+ void CrashNotify(const ProcessMessage &message);
+ void ThreadNotify(const ProcessMessage &message);
++ void ExitNotify(const ProcessMessage &message);
+
+ lldb_private::Unwind *
+ GetUnwinder();
+Index: source/Plugins/Process/POSIX/ProcessPOSIX.cpp
+===================================================================
+--- source/Plugins/Process/POSIX/ProcessPOSIX.cpp (revision 183906)
++++ source/Plugins/Process/POSIX/ProcessPOSIX.cpp (working copy)
+@@ -75,6 +75,7 @@
+ m_byte_order(lldb::endian::InlHostByteOrder()),
+ m_monitor(NULL),
+ m_module(NULL),
++ m_message_mutex (Mutex::eMutexTypeRecursive),
+ m_in_limbo(false),
+ m_exit_now(false)
+ {
+@@ -328,7 +329,14 @@
+ return error;
+ }
+
+- error = m_monitor->Detach();
++ uint32_t thread_count = m_thread_list.GetSize(false);
++ for (uint32_t i = 0; i < thread_count; ++i)
++ {
++ POSIXThread *thread = static_cast<POSIXThread*>(
++ m_thread_list.GetThreadAtIndex(i, false).get());
++ error = m_monitor->Detach(thread->GetID());
++ }
++
+ if (error.Success())
+ SetPrivateState(eStateDetached);
+
+@@ -374,31 +382,58 @@
+ {
+ Mutex::Locker lock(m_message_mutex);
+
++ POSIXThread *thread = static_cast<POSIXThread*>(
++ m_thread_list.FindThreadByID(message.GetTID(), false).get());
++
+ switch (message.GetKind())
+ {
+ case ProcessMessage::eInvalidMessage:
+ return;
+
+ case ProcessMessage::eLimboMessage:
+- m_in_limbo = true;
+- m_exit_status = message.GetExitStatus();
+- if (m_exit_now)
++ assert(thread);
++ thread->SetState(eStateStopped);
++ if (message.GetTID() == GetID())
+ {
+- SetPrivateState(eStateExited);
+- m_monitor->Detach();
++ m_in_limbo = true;
++ m_exit_status = message.GetExitStatus();
++ if (m_exit_now)
++ {
++ SetPrivateState(eStateExited);
++ m_monitor->Detach(GetID());
++ }
++ else
++ {
++ StopAllThreads(message.GetTID());
++ SetPrivateState(eStateStopped);
++ }
+ }
+ else
++ {
++ StopAllThreads(message.GetTID());
+ SetPrivateState(eStateStopped);
++ }
+ break;
+
+ case ProcessMessage::eExitMessage:
+- m_exit_status = message.GetExitStatus();
+- SetExitStatus(m_exit_status, NULL);
++ assert(thread);
++ thread->SetState(eStateExited);
++ // FIXME: I'm not sure we need to do this.
++ if (message.GetTID() == GetID())
++ {
++ m_exit_status = message.GetExitStatus();
++ SetExitStatus(m_exit_status, NULL);
++ }
+ break;
+
++ case ProcessMessage::eBreakpointMessage:
+ case ProcessMessage::eTraceMessage:
+- case ProcessMessage::eBreakpointMessage:
+ case ProcessMessage::eWatchpointMessage:
++ case ProcessMessage::eNewThreadMessage:
++ case ProcessMessage::eCrashMessage:
++ assert(thread);
++ thread->SetState(eStateStopped);
++ StopAllThreads(message.GetTID());
+ SetPrivateState(eStateStopped);
+ break;
+
+@@ -408,6 +443,9 @@
+ lldb::tid_t tid = message.GetTID();
+ lldb::tid_t pid = GetID();
+ if (tid == pid) {
++ assert(thread);
++ thread->SetState(eStateStopped);
++ StopAllThreads(message.GetTID());
+ SetPrivateState(eStateStopped);
+ break;
+ } else {
+@@ -416,51 +454,65 @@
+ }
+ }
+
+- case ProcessMessage::eCrashMessage:
+- // FIXME: Update stop reason as per bugzilla 14598
+- SetPrivateState(eStateStopped);
+- break;
+-
+- case ProcessMessage::eNewThreadMessage:
+- SetPrivateState(eStateStopped);
+- break;
+ }
+
+ m_message_queue.push(message);
+ }
+
++void
++ProcessPOSIX::StopAllThreads(lldb::tid_t stop_tid)
++{
++ // FIXME: Will this work the same way on FreeBSD and Linux?
++}
++
+ void
+ ProcessPOSIX::RefreshStateAfterStop()
+ {
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
+ if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
+- log->Printf ("ProcessPOSIX::%s()", __FUNCTION__);
++ log->Printf ("ProcessPOSIX::%s(), message_queue size = %d", __FUNCTION__, (int)m_message_queue.size());
+
+ Mutex::Locker lock(m_message_mutex);
+- if (m_message_queue.empty())
+- return;
+
+- ProcessMessage &message = m_message_queue.front();
++ // This method used to only handle one message. Changing it to loop allows
++ // it to handle the case where we hit a breakpoint while handling a different
++ // breakpoint.
++ while (!m_message_queue.empty())
++ {
++ ProcessMessage &message = m_message_queue.front();
+
+- // Resolve the thread this message corresponds to and pass it along.
+- // FIXME: we're really dealing with the pid here. This should get
+- // fixed when this code is fixed to handle multiple threads.
+- lldb::tid_t tid = message.GetTID();
+- if (log)
+- log->Printf ("ProcessPOSIX::%s() pid = %" PRIi64, __FUNCTION__, tid);
+- POSIXThread *thread = static_cast<POSIXThread*>(
+- GetThreadList().FindThreadByID(tid, false).get());
++ // Resolve the thread this message corresponds to and pass it along.
++ lldb::tid_t tid = message.GetTID();
++ if (log)
++ log->Printf ("ProcessPOSIX::%s(), message_queue size = %d, pid = %" PRIi64, __FUNCTION__, (int)m_message_queue.size(), tid);
++ POSIXThread *thread = static_cast<POSIXThread*>(
++ GetThreadList().FindThreadByID(tid, false).get());
+
+- if (message.GetKind() == ProcessMessage::eNewThreadMessage) {
+- ThreadSP thread_sp;
+- thread_sp.reset(new POSIXThread(*this, message.GetChildTID()));
+- m_thread_list.AddThread(thread_sp);
+- }
++ if (message.GetKind() == ProcessMessage::eNewThreadMessage)
++ {
++ if (log)
++ log->Printf ("ProcessPOSIX::%s() adding thread, tid = %" PRIi64, __FUNCTION__, message.GetChildTID());
++ ThreadSP thread_sp;
++ thread_sp.reset(new POSIXThread(*this, message.GetChildTID()));
++ m_thread_list.AddThread(thread_sp);
++ }
+
+- assert(thread);
+- thread->Notify(message);
++ m_thread_list.RefreshStateAfterStop();
+
+- m_message_queue.pop();
++ if (thread)
++ thread->Notify(message);
++
++ if (message.GetKind() == ProcessMessage::eExitMessage)
++ {
++ // FIXME: We should tell the user about this, but the limbo message is probably better for that.
++ if (log)
++ log->Printf ("ProcessPOSIX::%s() removing thread, tid = %" PRIi64, __FUNCTION__, tid);
++ ThreadSP thread_sp = m_thread_list.RemoveThreadByID(tid, false);
++ thread_sp.reset();
++ }
++
++ m_message_queue.pop();
++ }
+ }
+
+ bool
+@@ -602,32 +654,45 @@
+ return error;
+ }
+
+- bool wp_enabled = true;
+- uint32_t thread_count = m_thread_list.GetSize(false);
+- for (uint32_t i = 0; i < thread_count; ++i)
++ // Try to find a vacant watchpoint slot in the inferiors' main thread
++ uint32_t wp_hw_index = LLDB_INVALID_INDEX32;
++ POSIXThread *thread = static_cast<POSIXThread*>(
++ m_thread_list.GetThreadAtIndex(0, false).get());
++
++ if (thread)
++ wp_hw_index = thread->FindVacantWatchpointIndex();
++
++ if (wp_hw_index == LLDB_INVALID_INDEX32)
+ {
+- POSIXThread *thread = static_cast<POSIXThread*>(
+- m_thread_list.GetThreadAtIndex(i, false).get());
+- if (thread)
+- wp_enabled &= thread->EnableHardwareWatchpoint(wp);
++ error.SetErrorString("Setting hardware watchpoint failed.");
++ }
++ else
++ {
++ wp->SetHardwareIndex(wp_hw_index);
++ bool wp_enabled = true;
++ uint32_t thread_count = m_thread_list.GetSize(false);
++ for (uint32_t i = 0; i < thread_count; ++i)
++ {
++ thread = static_cast<POSIXThread*>(
++ m_thread_list.GetThreadAtIndex(i, false).get());
++ if (thread)
++ wp_enabled &= thread->EnableHardwareWatchpoint(wp);
++ else
++ wp_enabled = false;
++ }
++ if (wp_enabled)
++ {
++ wp->SetEnabled(true, notify);
++ return error;
++ }
+ else
+ {
+- wp_enabled = false;
+- break;
++ // Watchpoint enabling failed on at least one
++ // of the threads so roll back all of them
++ DisableWatchpoint(wp, false);
++ error.SetErrorString("Setting hardware watchpoint failed");
+ }
+ }
+- if (wp_enabled)
+- {
+- wp->SetEnabled(true, notify);
+- return error;
+- }
+- else
+- {
+- // Watchpoint enabling failed on at least one
+- // of the threads so roll back all of them
+- DisableWatchpoint(wp, false);
+- error.SetErrorString("Setting hardware watchpoint failed");
+- }
+ }
+ else
+ error.SetErrorString("Watchpoint argument was NULL.");
+@@ -672,6 +737,7 @@
+ }
+ if (wp_disabled)
+ {
++ wp->SetHardwareIndex(LLDB_INVALID_INDEX32);
+ wp->SetEnabled(false, notify);
+ return error;
+ }
+Index: source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.cpp
+===================================================================
+--- source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.cpp (revision 183906)
++++ source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.cpp (working copy)
+@@ -8,6 +8,7 @@
+ //===---------------------------------------------------------------------===//
+
+ #include "RegisterContextFreeBSD_x86_64.h"
++#include <vector>
+
+ using namespace lldb_private;
+
+@@ -18,13 +19,13 @@
+ // Update the FreeBSD specific information (offset and size).
+ #define UPDATE_GPR_INFO(reg) \
+ do { \
+- m_register_infos[gpr_##reg].byte_size = sizeof(GPR::reg); \
+- m_register_infos[gpr_##reg].byte_offset = GPR_OFFSET(reg); \
++ GetRegisterContext()[gpr_##reg].byte_size = sizeof(GPR::reg); \
++ GetRegisterContext()[gpr_##reg].byte_offset = GPR_OFFSET(reg); \
+ } while(false);
+
+ #define UPDATE_I386_GPR_INFO(i386_reg, reg) \
+ do { \
+- m_register_infos[gpr_##i386_reg].byte_offset = GPR_OFFSET(reg); \
++ GetRegisterContext()[gpr_##i386_reg].byte_offset = GPR_OFFSET(reg); \
+ } while(false);
+
+ typedef struct _GPR
+@@ -57,20 +58,18 @@
+ uint64_t ss;
+ } GPR;
+
+-RegisterInfo *RegisterContextFreeBSD_x86_64::m_register_infos = nullptr;
++// Use a singleton function to avoid global constructors in shared libraries.
++static std::vector<RegisterInfo> & GetRegisterContext () {
++ static std::vector<RegisterInfo> g_register_infos;
++ return g_register_infos;
++}
+
++
+ RegisterContextFreeBSD_x86_64::RegisterContextFreeBSD_x86_64(Thread &thread, uint32_t concrete_frame_idx):
+ RegisterContext_x86_64(thread, concrete_frame_idx)
+ {
+ }
+
+-RegisterContextFreeBSD_x86_64::~RegisterContextFreeBSD_x86_64()
+-{
+- if (m_register_infos)
+- delete m_register_infos;
+- m_register_infos = nullptr;
+-}
+-
+ size_t
+ RegisterContextFreeBSD_x86_64::GetGPRSize()
+ {
+@@ -81,19 +80,18 @@
+ RegisterContextFreeBSD_x86_64::GetRegisterInfo()
+ {
+ // Allocate RegisterInfo only once
+- if (!m_register_infos)
++ if (GetRegisterContext().empty())
+ {
+- m_register_infos = new RegisterInfo[k_num_registers];
+ // Copy the register information from base class
+- if (m_register_infos)
++ const RegisterInfo *base_info = RegisterContext_x86_64::GetRegisterInfo();
++ if (base_info)
+ {
+- memcpy(m_register_infos, RegisterContext_x86_64::GetRegisterInfo(),
+- sizeof(RegisterInfo) * k_num_registers);
+- // Update the Linux specific register information (offset and size).
++ GetRegisterContext().insert(GetRegisterContext().end(), &base_info[0], &base_info[k_num_registers]);
++ // Update the FreeBSD specific register information (offset and size).
+ UpdateRegisterInfo();
+ }
+ }
+- return m_register_infos;
++ return &GetRegisterContext()[0];
+ }
+
+ void
+Index: source/Plugins/Process/Utility/RegisterContextLLDB.cpp
+===================================================================
+--- source/Plugins/Process/Utility/RegisterContextLLDB.cpp (revision 183906)
++++ source/Plugins/Process/Utility/RegisterContextLLDB.cpp (working copy)
+@@ -1305,21 +1305,20 @@
+ return false;
+ }
+
+- bool pc_or_return_address = false;
++ bool pc_register = false;
+ uint32_t generic_regnum;
+- if (register_kind == eRegisterKindGeneric
+- && (regnum == LLDB_REGNUM_GENERIC_PC || regnum == LLDB_REGNUM_GENERIC_RA))
++ if (register_kind == eRegisterKindGeneric && regnum == LLDB_REGNUM_GENERIC_PC)
+ {
+- pc_or_return_address = true;
++ pc_register = true;
+ }
+ else if (m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (register_kind, regnum, eRegisterKindGeneric, generic_regnum)
+- && (generic_regnum == LLDB_REGNUM_GENERIC_PC || generic_regnum == LLDB_REGNUM_GENERIC_RA))
++ && generic_regnum == LLDB_REGNUM_GENERIC_PC)
+ {
+- pc_or_return_address = true;
++ pc_register = true;
+ }
+
+ lldb_private::UnwindLLDB::RegisterLocation regloc;
+- if (!m_parent_unwind.SearchForSavedLocationForRegister (lldb_regnum, regloc, m_frame_number - 1, pc_or_return_address))
++ if (!m_parent_unwind.SearchForSavedLocationForRegister (lldb_regnum, regloc, m_frame_number - 1, pc_register))
+ {
+ return false;
+ }
+Index: source/Plugins/Process/Utility/UnwindLLDB.cpp
+===================================================================
+--- source/Plugins/Process/Utility/UnwindLLDB.cpp (revision 183906)
++++ source/Plugins/Process/Utility/UnwindLLDB.cpp (working copy)
+@@ -278,7 +278,7 @@
+ }
+
+ bool
+-UnwindLLDB::SearchForSavedLocationForRegister (uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation ®loc, uint32_t starting_frame_num, bool pc_or_return_address_reg)
++UnwindLLDB::SearchForSavedLocationForRegister (uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation ®loc, uint32_t starting_frame_num, bool pc_reg)
+ {
+ int64_t frame_num = starting_frame_num;
+ if (frame_num >= m_frames.size())
+@@ -286,7 +286,7 @@
+
+ // Never interrogate more than one level while looking for the saved pc value. If the value
+ // isn't saved by frame_num, none of the frames lower on the stack will have a useful value.
+- if (pc_or_return_address_reg)
++ if (pc_reg)
+ {
+ UnwindLLDB::RegisterSearchResult result;
+ result = m_frames[frame_num]->reg_ctx_lldb_sp->SavedLocationForRegister (lldb_regnum, regloc);
+Index: source/Plugins/Process/Utility/UnwindLLDB.h
+===================================================================
+--- source/Plugins/Process/Utility/UnwindLLDB.h (revision 183906)
++++ source/Plugins/Process/Utility/UnwindLLDB.h (working copy)
+@@ -87,7 +87,7 @@
+ // Iterate over the RegisterContextLLDB's in our m_frames vector, look for the first one that
+ // has a saved location for this reg.
+ bool
+- SearchForSavedLocationForRegister (uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation ®loc, uint32_t starting_frame_num, bool pc_or_return_address_reg);
++ SearchForSavedLocationForRegister (uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation ®loc, uint32_t starting_frame_num, bool pc_register);
+
+
+ private:
+Index: source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+===================================================================
+--- source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp (revision 183906)
++++ source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp (working copy)
+@@ -1005,17 +1005,7 @@
+ DidLaunchOrAttach ();
+ }
+
+-void
+-ProcessGDBRemote::DoDidExec ()
+-{
+- // The process exec'ed itself, figure out the dynamic loader, etc...
+- BuildDynamicRegisterInfo (true);
+- m_gdb_comm.ResetDiscoverableSettings();
+- DidLaunchOrAttach ();
+-}
+
+-
+-
+ Error
+ ProcessGDBRemote::WillResume ()
+ {
+@@ -1350,7 +1340,13 @@
+ case 'T':
+ case 'S':
+ {
+- if (GetStopID() == 0)
++ // This is a bit of a hack, but is is required. If we did exec, we
++ // need to clear our thread lists and also know to rebuild our dynamic
++ // register info before we lookup and threads and populate the expedited
++ // register values so we need to know this right away so we can cleanup
++ // and update our registers.
++ const uint32_t stop_id = GetStopID();
++ if (stop_id == 0)
+ {
+ // Our first stop, make sure we have a process ID, and also make
+ // sure we know about our registers
+@@ -1507,6 +1503,7 @@
+ else
+ {
+ bool handled = false;
++ bool did_exec = false;
+ if (!reason.empty())
+ {
+ if (reason.compare("trace") == 0)
+@@ -1552,9 +1549,15 @@
+ thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithException(*thread_sp, description.c_str()));
+ handled = true;
+ }
++ else if (reason.compare("exec") == 0)
++ {
++ did_exec = true;
++ thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithExec(*thread_sp));
++ handled = true;
++ }
+ }
+
+- if (signo)
++ if (signo && did_exec == false)
+ {
+ if (signo == SIGTRAP)
+ {
+@@ -1881,6 +1884,26 @@
+ return error;
+ }
+
++void
++ProcessGDBRemote::SetLastStopPacket (const StringExtractorGDBRemote &response)
++{
++ lldb_private::Mutex::Locker locker (m_last_stop_packet_mutex);
++ const bool did_exec = response.GetStringRef().find(";reason:exec;") != std::string::npos;
++ if (did_exec)
++ {
++ Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
++ if (log)
++ log->Printf ("ProcessGDBRemote::SetLastStopPacket () - detected exec");
++
++ m_thread_list_real.Clear();
++ m_thread_list.Clear();
++ BuildDynamicRegisterInfo (true);
++ m_gdb_comm.ResetDiscoverableSettings();
++ }
++ m_last_stop_packet = response;
++}
++
++
+ //------------------------------------------------------------------
+ // Process Queries
+ //------------------------------------------------------------------
+@@ -1931,7 +1954,7 @@
+ }
+ else
+ {
+- error.SetErrorStringWithFormat("failed to sent packet: '%s'", packet);
++ error.SetErrorStringWithFormat("failed to send packet: '%s'", packet);
+ }
+ return 0;
+ }
+@@ -1967,7 +1990,7 @@
+ }
+ else
+ {
+- error.SetErrorStringWithFormat("failed to sent packet: '%s'", packet.GetString().c_str());
++ error.SetErrorStringWithFormat("failed to send packet: '%s'", packet.GetString().c_str());
+ }
+ return 0;
+ }
+Index: source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
+===================================================================
+--- source/Plugins/Process/gdb-remote/ProcessGDBRemote.h (revision 183906)
++++ source/Plugins/Process/gdb-remote/ProcessGDBRemote.h (working copy)
+@@ -114,9 +114,6 @@
+ virtual void
+ DidAttach ();
+
+- virtual void
+- DoDidExec ();
+-
+ //------------------------------------------------------------------
+ // PluginInterface protocol
+ //------------------------------------------------------------------
+@@ -289,11 +286,7 @@
+ BuildDynamicRegisterInfo (bool force);
+
+ void
+- SetLastStopPacket (const StringExtractorGDBRemote &response)
+- {
+- lldb_private::Mutex::Locker locker (m_last_stop_packet_mutex);
+- m_last_stop_packet = response;
+- }
++ SetLastStopPacket (const StringExtractorGDBRemote &response);
+
+ //------------------------------------------------------------------
+ /// Broadcaster event bits definitions.
+Index: source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
+===================================================================
+--- source/Plugins/Process/FreeBSD/ProcessMonitor.cpp (revision 183906)
++++ source/Plugins/Process/FreeBSD/ProcessMonitor.cpp (working copy)
+@@ -1551,7 +1551,7 @@
+ }
+
+ Error
+-ProcessMonitor::Detach()
++ProcessMonitor::Detach(lldb::tid_t tid)
+ {
+ Error result;
+ DetachOperation op(result);
+Index: source/Plugins/Process/FreeBSD/ProcessMonitor.h
+===================================================================
+--- source/Plugins/Process/FreeBSD/ProcessMonitor.h (revision 183906)
++++ source/Plugins/Process/FreeBSD/ProcessMonitor.h (working copy)
+@@ -188,7 +188,7 @@
+ BringProcessIntoLimbo();
+
+ lldb_private::Error
+- Detach();
++ Detach(lldb::tid_t tid);
+
+
+ private:
+Index: source/Plugins/Process/FreeBSD/CMakeLists.txt
+===================================================================
+--- source/Plugins/Process/FreeBSD/CMakeLists.txt (revision 183906)
++++ source/Plugins/Process/FreeBSD/CMakeLists.txt (working copy)
+@@ -1,5 +1,8 @@
+ set(LLVM_NO_RTTI 1)
+
++include_directories(.)
++include_directories(../POSIX)
++
+ add_lldb_library(lldbPluginProcessFreeBSD
+ ProcessFreeBSD.cpp
+ ProcessMonitor.cpp
+Index: source/Plugins/Process/CMakeLists.txt
+===================================================================
+--- source/Plugins/Process/CMakeLists.txt (revision 183906)
++++ source/Plugins/Process/CMakeLists.txt (working copy)
+@@ -2,7 +2,7 @@
+ add_subdirectory(Linux)
+ add_subdirectory(POSIX)
+ elseif (CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
+- #add_subdirectory(FreeBSD)
++ add_subdirectory(FreeBSD)
+ add_subdirectory(POSIX)
+ elseif (CMAKE_SYSTEM_NAME MATCHES "Darwin")
+ add_subdirectory(MacOSX-Kernel)
+Index: source/Plugins/Process/mach-core/ProcessMachCore.cpp
+===================================================================
+--- source/Plugins/Process/mach-core/ProcessMachCore.cpp (revision 183906)
++++ source/Plugins/Process/mach-core/ProcessMachCore.cpp (working copy)
+@@ -32,6 +32,7 @@
+ #include "ThreadMachCore.h"
+ #include "StopInfoMachException.h"
+
++// Needed for the plug-in names for the dynamic loaders.
+ #include "Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h"
+ #include "Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.h"
+
+@@ -212,6 +213,13 @@
+ error.SetErrorString ("invalid core object file");
+ return error;
+ }
++
++ if (core_objfile->GetNumThreadContexts() == 0)
++ {
++ error.SetErrorString ("core file doesn't contain any LC_THREAD load commands, or the LC_THREAD architecture is not supported in this lldb");
++ return error;
++ }
++
+ SectionList *section_list = core_objfile->GetSectionList();
+ if (section_list == NULL)
+ {
+@@ -296,10 +304,26 @@
+
+ if (m_dyld_addr == LLDB_INVALID_ADDRESS)
+ {
+- addr_t kernel_load_address = DynamicLoaderDarwinKernel::SearchForDarwinKernel (this);
+- if (kernel_load_address != LLDB_INVALID_ADDRESS)
++ // We need to locate the main executable in the memory ranges
++ // we have in the core file. We already checked the first address
++ // in each memory zone above, so we just need to check each page
++ // except the first page in each range and stop once we have found
++ // our main executable
++ const size_t num_core_aranges = m_core_aranges.GetSize();
++ for (size_t i=0; i<num_core_aranges && m_dyld_addr == LLDB_INVALID_ADDRESS; ++i)
+ {
+- GetDynamicLoaderAddress (kernel_load_address);
++ const VMRangeToFileOffset::Entry *entry = m_core_aranges.GetEntryAtIndex(i);
++ lldb::addr_t section_vm_addr_start = entry->GetRangeBase();
++ lldb::addr_t section_vm_addr_end = entry->GetRangeEnd();
++ for (lldb::addr_t section_vm_addr = section_vm_addr_start + 0x1000;
++ section_vm_addr < section_vm_addr_end;
++ section_vm_addr += 0x1000)
++ {
++ if (GetDynamicLoaderAddress (section_vm_addr))
++ {
++ break;
++ }
++ }
+ }
+ }
+ return error;
+Index: source/Plugins/Process/Linux/ProcessLinux.h
+===================================================================
+--- source/Plugins/Process/Linux/ProcessLinux.h (revision 183906)
++++ source/Plugins/Process/Linux/ProcessLinux.h (working copy)
+@@ -75,11 +75,28 @@
+ EnablePluginLogging(lldb_private::Stream *strm,
+ lldb_private::Args &command);
+
++ //------------------------------------------------------------------
++ // Plug-in process overrides
++ //------------------------------------------------------------------
++ virtual lldb_private::UnixSignals &
++ GetUnixSignals ()
++ {
++ return m_linux_signals;
++ }
++
++ //------------------------------------------------------------------
++ // ProcessPOSIX overrides
++ //------------------------------------------------------------------
++ virtual void
++ StopAllThreads(lldb::tid_t stop_tid);
++
+ private:
+
+ /// Linux-specific signal set.
+ LinuxSignals m_linux_signals;
+
++ // Flag to avoid recursion when stopping all threads.
++ bool m_stopping_threads;
+ };
+
+ #endif // liblldb_MacOSXProcess_H_
+Index: source/Plugins/Process/Linux/ProcessMonitor.cpp
+===================================================================
+--- source/Plugins/Process/Linux/ProcessMonitor.cpp (revision 183906)
++++ source/Plugins/Process/Linux/ProcessMonitor.cpp (working copy)
+@@ -17,6 +17,7 @@
+ #include <unistd.h>
+ #include <sys/ptrace.h>
+ #include <sys/socket.h>
++#include <sys/syscall.h>
+ #include <sys/types.h>
+ #include <sys/wait.h>
+
+@@ -52,6 +53,10 @@
+ #define TRAP_HWBKPT 4
+ #endif
+
++// Try to define a macro to encapsulate the tgkill syscall
++// fall back on kill() if tgkill isn't available
++#define tgkill(pid, tid, sig) syscall(SYS_tgkill, pid, tid, sig)
++
+ using namespace lldb_private;
+
+ // FIXME: this code is host-dependent with respect to types and
+@@ -724,7 +729,13 @@
+ data = m_signo;
+
+ if (PTRACE(PTRACE_CONT, m_tid, NULL, (void*)data, 0))
++ {
++ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
++
++ if (log)
++ log->Printf ("ResumeOperation (%" PRIu64 ") failed: %s", m_tid, strerror(errno));
+ m_result = false;
++ }
+ else
+ m_result = true;
+ }
+@@ -846,22 +857,20 @@
+ class DetachOperation : public Operation
+ {
+ public:
+- DetachOperation(Error &result) : m_error(result) { }
++ DetachOperation(lldb::tid_t tid, Error &result) : m_tid(tid), m_error(result) { }
+
+ void Execute(ProcessMonitor *monitor);
+
+ private:
++ lldb::tid_t m_tid;
+ Error &m_error;
+ };
+
+ void
+ DetachOperation::Execute(ProcessMonitor *monitor)
+ {
+- lldb::pid_t pid = monitor->GetPID();
+-
+- if (ptrace(PT_DETACH, pid, NULL, 0) < 0)
++ if (ptrace(PT_DETACH, m_tid, NULL, 0) < 0)
+ m_error.SetErrorToErrno();
+-
+ }
+
+ ProcessMonitor::OperationArgs::OperationArgs(ProcessMonitor *monitor)
+@@ -1087,7 +1096,6 @@
+ const size_t err_len = 1024;
+ char err_str[err_len];
+ lldb::pid_t pid;
+- long ptrace_opts = 0;
+
+ lldb::ThreadSP inferior;
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
+@@ -1203,14 +1211,7 @@
+ assert(WIFSTOPPED(status) && wpid == pid &&
+ "Could not sync with inferior process.");
+
+- // Have the child raise an event on exit. This is used to keep the child in
+- // limbo until it is destroyed.
+- ptrace_opts |= PTRACE_O_TRACEEXIT;
+-
+- // Have the tracer trace threads which spawn in the inferior process.
+- ptrace_opts |= PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK | PTRACE_O_TRACECLONE;
+-
+- if (PTRACE(PTRACE_SETOPTIONS, pid, NULL, (void*)ptrace_opts, 0) < 0)
++ if (!SetDefaultPtraceOpts(pid))
+ {
+ args->m_error.SetErrorToErrno();
+ goto FINISH;
+@@ -1291,6 +1292,9 @@
+ lldb::ThreadSP inferior;
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
+
++ // Use a map to keep track of the threads which we have attached/need to attach.
++ Host::TidMap tids_to_attach;
++
+ if (pid <= 1)
+ {
+ args->m_error.SetErrorToGenericError();
+@@ -1298,33 +1302,103 @@
+ goto FINISH;
+ }
+
+- // Attach to the requested process.
+- if (PTRACE(PTRACE_ATTACH, pid, NULL, NULL, 0) < 0)
++ while (Host::FindProcessThreads(pid, tids_to_attach))
+ {
+- args->m_error.SetErrorToErrno();
+- goto FINISH;
++ for (Host::TidMap::iterator it = tids_to_attach.begin();
++ it != tids_to_attach.end(); ++it)
++ {
++ if (it->second == false)
++ {
++ lldb::tid_t tid = it->first;
++
++ // Attach to the requested process.
++ // An attach will cause the thread to stop with a SIGSTOP.
++ if (PTRACE(PTRACE_ATTACH, tid, NULL, NULL, 0) < 0)
++ {
++ // No such thread. The thread may have exited.
++ // More error handling may be needed.
++ if (errno == ESRCH)
++ {
++ tids_to_attach.erase(it);
++ continue;
++ }
++ else
++ {
++ args->m_error.SetErrorToErrno();
++ goto FINISH;
++ }
++ }
++
++ int status;
++ // Need to use __WALL otherwise we receive an error with errno=ECHLD
++ // At this point we should have a thread stopped if waitpid succeeds.
++ if ((status = waitpid(tid, NULL, __WALL)) < 0)
++ {
++ // No such thread. The thread may have exited.
++ // More error handling may be needed.
++ if (errno == ESRCH)
++ {
++ tids_to_attach.erase(it);
++ continue;
++ }
++ else
++ {
++ args->m_error.SetErrorToErrno();
++ goto FINISH;
++ }
++ }
++
++ if (!SetDefaultPtraceOpts(tid))
++ {
++ args->m_error.SetErrorToErrno();
++ goto FINISH;
++ }
++
++ // Update the process thread list with the attached thread.
++ inferior.reset(new POSIXThread(process, tid));
++ if (log)
++ log->Printf ("ProcessMonitor::%s() adding tid = %" PRIu64, __FUNCTION__, tid);
++ process.GetThreadList().AddThread(inferior);
++ it->second = true;
++ }
++ }
+ }
+
+- int status;
+- if ((status = waitpid(pid, NULL, 0)) < 0)
++ if (tids_to_attach.size() > 0)
+ {
+- args->m_error.SetErrorToErrno();
+- goto FINISH;
++ monitor->m_pid = pid;
++ // Let our process instance know the thread has stopped.
++ process.SendMessage(ProcessMessage::Trace(pid));
+ }
++ else
++ {
++ args->m_error.SetErrorToGenericError();
++ args->m_error.SetErrorString("No such process.");
++ }
+
+- monitor->m_pid = pid;
++ FINISH:
++ return args->m_error.Success();
++}
+
+- // Update the process thread list with the attached thread.
+- inferior.reset(new POSIXThread(process, pid));
+- if (log)
+- log->Printf ("ProcessMonitor::%s() adding tid = %" PRIu64, __FUNCTION__, pid);
+- process.GetThreadList().AddThread(inferior);
++bool
++ProcessMonitor::SetDefaultPtraceOpts(lldb::pid_t pid)
++{
++ long ptrace_opts = 0;
+
+- // Let our process instance know the thread has stopped.
+- process.SendMessage(ProcessMessage::Trace(pid));
++ // Have the child raise an event on exit. This is used to keep the child in
++ // limbo until it is destroyed.
++ ptrace_opts |= PTRACE_O_TRACEEXIT;
+
+- FINISH:
+- return args->m_error.Success();
++ // Have the tracer trace threads which spawn in the inferior process.
++ // TODO: if we want to support tracing the inferiors' child, add the
++ // appropriate ptrace flags here (PTRACE_O_TRACEFORK, PTRACE_O_TRACEVFORK)
++ ptrace_opts |= PTRACE_O_TRACECLONE;
++
++ // Have the tracer notify us before execve returns
++ // (needed to disable legacy SIGTRAP generation)
++ ptrace_opts |= PTRACE_O_TRACEEXEC;
++
++ return PTRACE(PTRACE_SETOPTIONS, pid, NULL, (void*)ptrace_opts, 0) >= 0;
+ }
+
+ bool
+@@ -1342,8 +1416,21 @@
+ siginfo_t info;
+ int ptrace_err;
+
++ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
++
++ if (exited)
++ {
++ if (log)
++ log->Printf ("ProcessMonitor::%s() got exit signal, tid = %" PRIu64, __FUNCTION__, pid);
++ message = ProcessMessage::Exit(pid, status);
++ process->SendMessage(message);
++ return pid == process->GetID();
++ }
++
+ if (!monitor->GetSignalInfo(pid, &info, ptrace_err)) {
+ if (ptrace_err == EINVAL) {
++ if (log)
++ log->Printf ("ProcessMonitor::%s() resuming from group-stop", __FUNCTION__);
+ // inferior process is in 'group-stop', so deliver SIGSTOP signal
+ if (!monitor->Resume(pid, SIGSTOP)) {
+ assert(0 && "SIGSTOP delivery failed while in 'group-stop' state");
+@@ -1352,8 +1439,11 @@
+ } else {
+ // ptrace(GETSIGINFO) failed (but not due to group-stop). Most likely,
+ // this means the child pid is gone (or not being debugged) therefore
+- // stop the monitor thread.
+- stop_monitoring = true;
++ // stop the monitor thread if this is the main pid.
++ if (log)
++ log->Printf ("ProcessMonitor::%s() GetSignalInfo failed: %s, tid = %" PRIu64 ", signal = %d, status = %d",
++ __FUNCTION__, strerror(ptrace_err), pid, signal, status);
++ stop_monitoring = pid == monitor->m_process->GetID();
+ }
+ }
+ else {
+@@ -1369,7 +1459,7 @@
+ }
+
+ process->SendMessage(message);
+- stop_monitoring = !process->IsAlive();
++ stop_monitoring = false;
+ }
+
+ return stop_monitoring;
+@@ -1381,6 +1471,8 @@
+ {
+ ProcessMessage message;
+
++ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
++
+ assert(monitor);
+ assert(info && info->si_signo == SIGTRAP && "Unexpected child signal!");
+
+@@ -1390,10 +1482,16 @@
+ assert(false && "Unexpected SIGTRAP code!");
+ break;
+
+- case (SIGTRAP | (PTRACE_EVENT_FORK << 8)):
+- case (SIGTRAP | (PTRACE_EVENT_VFORK << 8)):
++ // TODO: these two cases are required if we want to support tracing
++ // of the inferiors' children
++ // case (SIGTRAP | (PTRACE_EVENT_FORK << 8)):
++ // case (SIGTRAP | (PTRACE_EVENT_VFORK << 8)):
++
+ case (SIGTRAP | (PTRACE_EVENT_CLONE << 8)):
+ {
++ if (log)
++ log->Printf ("ProcessMonitor::%s() received thread creation event, code = %d", __FUNCTION__, info->si_code ^ SIGTRAP);
++
+ unsigned long tid = 0;
+ if (!monitor->GetEventMessage(pid, &tid))
+ tid = -1;
+@@ -1401,29 +1499,42 @@
+ break;
+ }
+
++ case (SIGTRAP | (PTRACE_EVENT_EXEC << 8)):
++ // Don't follow the child by default and resume
++ monitor->Resume(pid, SIGCONT);
++ break;
++
+ case (SIGTRAP | (PTRACE_EVENT_EXIT << 8)):
+ {
+- // The inferior process is about to exit. Maintain the process in a
+- // state of "limbo" until we are explicitly commanded to detach,
+- // destroy, resume, etc.
++ // The inferior process or one of its threads is about to exit.
++ // Maintain the process or thread in a state of "limbo" until we are
++ // explicitly commanded to detach, destroy, resume, etc.
+ unsigned long data = 0;
+ if (!monitor->GetEventMessage(pid, &data))
+ data = -1;
++ if (log)
++ log->Printf ("ProcessMonitor::%s() received exit event, data = %lx, pid = %" PRIu64, __FUNCTION__, data, pid);
+ message = ProcessMessage::Limbo(pid, (data >> 8));
+ break;
+ }
+
+ case 0:
+ case TRAP_TRACE:
++ if (log)
++ log->Printf ("ProcessMonitor::%s() received trace event, pid = %" PRIu64, __FUNCTION__, pid);
+ message = ProcessMessage::Trace(pid);
+ break;
+
+ case SI_KERNEL:
+ case TRAP_BRKPT:
++ if (log)
++ log->Printf ("ProcessMonitor::%s() received breakpoint event, pid = %" PRIu64, __FUNCTION__, pid);
+ message = ProcessMessage::Break(pid);
+ break;
+
+ case TRAP_HWBKPT:
++ if (log)
++ log->Printf ("ProcessMonitor::%s() received watchpoint event, pid = %" PRIu64, __FUNCTION__, pid);
+ message = ProcessMessage::Watch(pid, (lldb::addr_t)info->si_addr);
+ break;
+ }
+@@ -1438,6 +1549,8 @@
+ ProcessMessage message;
+ int signo = info->si_signo;
+
++ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
++
+ // POSIX says that process behaviour is undefined after it ignores a SIGFPE,
+ // SIGILL, SIGSEGV, or SIGBUS *unless* that signal was generated by a
+ // kill(2) or raise(3). Similarly for tgkill(2) on Linux.
+@@ -1448,12 +1561,22 @@
+ // Similarly, ACK signals generated by this monitor.
+ if (info->si_code == SI_TKILL || info->si_code == SI_USER)
+ {
++ if (log)
++ log->Printf ("ProcessMonitor::%s() received signal %s with code %s, pid = %d",
++ __FUNCTION__,
++ monitor->m_process->GetUnixSignals().GetSignalAsCString (signo),
++ (info->si_code == SI_TKILL ? "SI_TKILL" : "SI_USER"),
++ info->si_pid);
++
+ if (info->si_pid == getpid())
+ return ProcessMessage::SignalDelivered(pid, signo);
+ else
+ return ProcessMessage::Signal(pid, signo);
+ }
+
++ if (log)
++ log->Printf ("ProcessMonitor::%s() received signal %s", __FUNCTION__, monitor->m_process->GetUnixSignals().GetSignalAsCString (signo));
++
+ if (signo == SIGSEGV) {
+ lldb::addr_t fault_addr = reinterpret_cast<lldb::addr_t>(info->si_addr);
+ ProcessMessage::CrashReason reason = GetCrashReasonForSIGSEGV(info);
+@@ -1483,6 +1606,144 @@
+ return ProcessMessage::Signal(pid, signo);
+ }
+
++bool
++ProcessMonitor::StopThread(lldb::tid_t tid)
++{
++ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
++
++ // FIXME: Try to use tgkill or tkill
++ int ret = tgkill(m_pid, tid, SIGSTOP);
++ if (log)
++ log->Printf ("ProcessMonitor::%s(bp) stopping thread, tid = %" PRIu64 ", ret = %d", __FUNCTION__, tid, ret);
++
++ // This can happen if a thread exited while we were trying to stop it. That's OK.
++ // We'll get the signal for that later.
++ if (ret < 0)
++ return false;
++
++ // Wait for the thread to stop
++ while (true)
++ {
++ int status = -1;
++ if (log)
++ log->Printf ("ProcessMonitor::%s(bp) waitpid...", __FUNCTION__);
++ lldb::pid_t wait_pid = ::waitpid (-1*m_pid, &status, __WALL);
++ if (log)
++ log->Printf ("ProcessMonitor::%s(bp) waitpid, pid = %" PRIu64 ", status = %d", __FUNCTION__, wait_pid, status);
++
++ if (wait_pid == -1)
++ {
++ // If we got interrupted by a signal (in our process, not the
++ // inferior) try again.
++ if (errno == EINTR)
++ continue;
++ else
++ return false; // This is bad, but there's nothing we can do.
++ }
++
++ // If this is a thread exit, we won't get any more information.
++ if (WIFEXITED(status))
++ {
++ m_process->SendMessage(ProcessMessage::Exit(wait_pid, WEXITSTATUS(status)));
++ if (wait_pid == tid)
++ return true;
++ continue;
++ }
++
++ siginfo_t info;
++ int ptrace_err;
++ if (!GetSignalInfo(wait_pid, &info, ptrace_err))
++ {
++ if (log)
++ {
++ log->Printf ("ProcessMonitor::%s() GetSignalInfo failed.", __FUNCTION__);
++
++ // This would be a particularly interesting case
++ if (ptrace_err == EINVAL)
++ log->Printf ("ProcessMonitor::%s() in group-stop", __FUNCTION__);
++ }
++ return false;
++ }
++
++ // Handle events from other threads
++ if (log)
++ log->Printf ("ProcessMonitor::%s(bp) handling event, tid == %" PRIu64, __FUNCTION__, wait_pid);
++
++ ProcessMessage message;
++ if (info.si_signo == SIGTRAP)
++ message = MonitorSIGTRAP(this, &info, wait_pid);
++ else
++ message = MonitorSignal(this, &info, wait_pid);
++
++ POSIXThread *thread = static_cast<POSIXThread*>(m_process->GetThreadList().FindThreadByID(wait_pid).get());
++
++ // When a new thread is created, we may get a SIGSTOP for the new thread
++ // just before we get the SIGTRAP that we use to add the thread to our
++ // process thread list. We don't need to worry about that signal here.
++ assert(thread || message.GetKind() == ProcessMessage::eSignalMessage);
++
++ if (!thread)
++ {
++ m_process->SendMessage(message);
++ continue;
++ }
++
++ switch (message.GetKind())
++ {
++ case ProcessMessage::eInvalidMessage:
++ break;
++
++ // These need special handling because we don't want to send a
++ // resume even if we already sent a SIGSTOP to this thread. In
++ // this case the resume will cause the thread to disappear. It is
++ // unlikely that we'll ever get eExitMessage here, but the same
++ // reasoning applies.
++ case ProcessMessage::eLimboMessage:
++ case ProcessMessage::eExitMessage:
++ if (log)
++ log->Printf ("ProcessMonitor::%s(bp) handling message", __FUNCTION__);
++ // SendMessage will set the thread state as needed.
++ m_process->SendMessage(message);
++ // If this is the thread we're waiting for, stop waiting. Even
++ // though this wasn't the signal we expected, it's the last
++ // signal we'll see while this thread is alive.
++ if (wait_pid == tid)
++ return true;
++ break;
++
++ case ProcessMessage::eSignalDeliveredMessage:
++ // This is the stop we're expecting.
++ if (wait_pid == tid && WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP && info.si_code == SI_TKILL)
++ {
++ if (log)
++ log->Printf ("ProcessMonitor::%s(bp) received signal, done waiting", __FUNCTION__);
++ thread->SetState(lldb::eStateStopped);
++ return true;
++ }
++ // else fall-through
++ case ProcessMessage::eSignalMessage:
++ case ProcessMessage::eBreakpointMessage:
++ case ProcessMessage::eTraceMessage:
++ case ProcessMessage::eWatchpointMessage:
++ case ProcessMessage::eCrashMessage:
++ case ProcessMessage::eNewThreadMessage:
++ if (log)
++ log->Printf ("ProcessMonitor::%s(bp) handling message", __FUNCTION__);
++ // SendMessage will set the thread state as needed.
++ m_process->SendMessage(message);
++ // This isn't the stop we were expecting, but the thread is
++ // stopped. SendMessage will handle processing of this event,
++ // but we need to resume here to get the stop we are waiting
++ // for (otherwise the thread will stop again immediately when
++ // we try to resume).
++ if (wait_pid == tid)
++ Resume(wait_pid, eResumeSignalNone);
++ break;
++ }
++ }
++ return false;
++}
++
+ ProcessMessage::CrashReason
+ ProcessMonitor::GetCrashReasonForSIGSEGV(const siginfo_t *info)
+ {
+@@ -1794,8 +2055,15 @@
+ ProcessMonitor::Resume(lldb::tid_t tid, uint32_t signo)
+ {
+ bool result;
++ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
++
++ if (log)
++ log->Printf ("ProcessMonitor::%s() resuming thread = %" PRIu64 " with signal %s", __FUNCTION__, tid,
++ m_process->GetUnixSignals().GetSignalAsCString (signo));
+ ResumeOperation op(tid, signo, result);
+ DoOperation(&op);
++ if (log)
++ log->Printf ("ProcessMonitor::%s() resuming result = %s", __FUNCTION__, result ? "true" : "false");
+ return result;
+ }
+
+@@ -1836,11 +2104,12 @@
+ }
+
+ lldb_private::Error
+-ProcessMonitor::Detach()
++ProcessMonitor::Detach(lldb::tid_t tid)
+ {
+ lldb_private::Error error;
+- if (m_pid != LLDB_INVALID_PROCESS_ID) {
+- DetachOperation op(error);
++ if (tid != LLDB_INVALID_THREAD_ID)
++ {
++ DetachOperation op(tid, error);
+ DoOperation(&op);
+ }
+ return error;
+Index: source/Plugins/Process/Linux/ProcessMonitor.h
+===================================================================
+--- source/Plugins/Process/Linux/ProcessMonitor.h (revision 183906)
++++ source/Plugins/Process/Linux/ProcessMonitor.h (working copy)
+@@ -63,6 +63,11 @@
+
+ ~ProcessMonitor();
+
++ enum ResumeSignals
++ {
++ eResumeSignalNone = 0
++ };
++
+ /// Provides the process number of debugee.
+ lldb::pid_t
+ GetPID() const { return m_pid; }
+@@ -170,8 +175,11 @@
+ BringProcessIntoLimbo();
+
+ lldb_private::Error
+- Detach();
++ Detach(lldb::tid_t tid);
+
++ /// Stops the requested thread and waits for the stop signal.
++ bool
++ StopThread(lldb::tid_t tid);
+
+ private:
+ ProcessLinux *m_process;
+@@ -254,6 +262,9 @@
+ static bool
+ Attach(AttachArgs *args);
+
++ static bool
++ SetDefaultPtraceOpts(const lldb::pid_t);
++
+ static void
+ ServeOperation(OperationArgs *args);
+
+Index: source/Plugins/Process/Linux/ProcessLinux.cpp
+===================================================================
+--- source/Plugins/Process/Linux/ProcessLinux.cpp (revision 183906)
++++ source/Plugins/Process/Linux/ProcessLinux.cpp (working copy)
+@@ -64,7 +64,7 @@
+ // Constructors and destructors.
+
+ ProcessLinux::ProcessLinux(Target& target, Listener &listener)
+- : ProcessPOSIX(target, listener)
++ : ProcessPOSIX(target, listener), m_stopping_threads(false)
+ {
+ #if 0
+ // FIXME: Putting this code in the ctor and saving the byte order in a
+@@ -134,3 +134,39 @@
+ {
+ return NULL;
+ }
++
++// ProcessPOSIX override
++void
++ProcessLinux::StopAllThreads(lldb::tid_t stop_tid)
++{
++ // If a breakpoint occurs while we're stopping threads, we'll get back
++ // here, but we don't want to do it again. Only the MonitorChildProcess
++ // thread calls this function, so we don't need to protect this flag.
++ if (m_stopping_threads)
++ return;
++ m_stopping_threads = true;
++
++ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
++ if (log)
++ log->Printf ("ProcessLinux::%s() stopping all threads", __FUNCTION__);
++
++ // Walk the thread list and stop the other threads. The thread that caused
++ // the stop should already be marked as stopped before we get here.
++ Mutex::Locker thread_list_lock(m_thread_list.GetMutex());
++
++ uint32_t thread_count = m_thread_list.GetSize(false);
++ for (uint32_t i = 0; i < thread_count; ++i)
++ {
++ POSIXThread *thread = static_cast<POSIXThread*>(
++ m_thread_list.GetThreadAtIndex(i, false).get());
++ assert(thread);
++ lldb::tid_t tid = thread->GetID();
++ if (!StateIsStoppedState(thread->GetState(), false))
++ m_monitor->StopThread(tid);
++ }
++
++ m_stopping_threads = false;
++
++ if (log)
++ log->Printf ("ProcessLinux::%s() finished", __FUNCTION__);
++}
+Index: source/Plugins/Platform/Linux/PlatformLinux.cpp
+===================================================================
+--- source/Plugins/Platform/Linux/PlatformLinux.cpp (revision 183906)
++++ source/Plugins/Platform/Linux/PlatformLinux.cpp (working copy)
+@@ -208,6 +208,29 @@
+ NULL,
+ NULL,
+ NULL);
++ if (error.Fail())
++ {
++ // If we failed, it may be because the vendor and os aren't known. If that is the
++ // case, try setting them to the host architecture and give it another try.
++ llvm::Triple &module_triple = module_spec.GetArchitecture().GetTriple();
++ bool is_vendor_specified = (module_triple.getVendor() != llvm::Triple::UnknownVendor);
++ bool is_os_specified = (module_triple.getOS() != llvm::Triple::UnknownOS);
++ if (!is_vendor_specified || !is_os_specified)
++ {
++ const llvm::Triple &host_triple = Host::GetArchitecture (Host::eSystemDefaultArchitecture).GetTriple();
++
++ if (!is_vendor_specified)
++ module_triple.setVendorName (host_triple.getVendorName());
++ if (!is_os_specified)
++ module_triple.setOSName (host_triple.getOSName());
++
++ error = ModuleList::GetSharedModule (module_spec,
++ exe_module_sp,
++ NULL,
++ NULL,
++ NULL);
++ }
++ }
+
+ // TODO find out why exe_module_sp might be NULL
+ if (!exe_module_sp || exe_module_sp->GetObjectFile() == NULL)
+@@ -336,12 +359,14 @@
+ {
+ struct utsname un;
+
+- if (uname(&un)) {
+- strm << "Linux";
++ Platform::GetStatus(strm);
++
++ if (uname(&un))
+ return;
+- }
+
+- strm << un.sysname << ' ' << un.release << ' ' << un.version << '\n';
++ strm.Printf (" Kernel: %s\n", un.sysname);
++ strm.Printf (" Release: %s\n", un.release);
++ strm.Printf (" Version: %s\n", un.version);
+ }
+
+ size_t
+Index: source/Target/ThreadPlanBase.cpp
+===================================================================
+--- source/Target/ThreadPlanBase.cpp (revision 183906)
++++ source/Target/ThreadPlanBase.cpp (working copy)
+@@ -102,10 +102,10 @@
+
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
+
+- StopInfoSP stop_info_sp = GetPrivateStopReason();
++ StopInfoSP stop_info_sp = GetPrivateStopInfo ();
+ if (stop_info_sp)
+ {
+- StopReason reason = stop_info_sp->GetStopReason();
++ StopReason reason = stop_info_sp->GetStopReason ();
+ switch (reason)
+ {
+ case eStopReasonInvalid:
+Index: source/Target/Process.cpp
+===================================================================
+--- source/Target/Process.cpp (revision 183906)
++++ source/Target/Process.cpp (working copy)
+@@ -996,6 +996,7 @@
+ ProcessProperties (false),
+ UserID (LLDB_INVALID_PROCESS_ID),
+ Broadcaster (&(target.GetDebugger()), "lldb.process"),
++ m_reservation_cache (*this),
+ m_target (target),
+ m_public_state (eStateUnloaded),
+ m_private_state (eStateUnloaded),
+@@ -1719,7 +1720,7 @@
+ else
+ m_private_run_lock.WriteLock();
+ }
+-
++
+ if (state_changed)
+ {
+ m_private_state.SetValueNoLock (new_state);
+@@ -5582,10 +5583,69 @@
+ m_dynamic_checkers_ap.reset();
+ m_abi_sp.reset();
+ m_os_ap.reset();
+- m_dyld_ap.reset();
++ m_dyld_ap.reset();
+ m_image_tokens.clear();
+ m_allocated_memory_cache.Clear();
+ m_language_runtimes.clear();
++ m_thread_list.DiscardThreadPlans();
++ m_memory_cache.Clear(true);
+ DoDidExec();
+ CompleteAttach ();
+ }
++
++Process::ReservationCache::ReservationCache (Process &process) : m_process(process)
++{
++ m_mod_id = process.GetModID();
++}
++
++void
++Process::ReservationCache::Reserve (lldb::addr_t addr, size_t size)
++{
++ CheckModID();
++ m_reserved_cache[addr] = size;
++}
++
++void
++Process::ReservationCache::Unreserve (lldb::addr_t addr)
++{
++ CheckModID();
++ ReservedMap::iterator iter = m_reserved_cache.find(addr);
++
++ if (iter != m_reserved_cache.end())
++ {
++ size_t size = iter->second;
++ m_reserved_cache.erase(iter);
++ m_free_cache[size].push_back(addr);
++ }
++}
++
++lldb::addr_t
++Process::ReservationCache::Find (size_t size)
++{
++ CheckModID();
++ lldb::addr_t ret = LLDB_INVALID_ADDRESS;
++ FreeMap::iterator map_iter = m_free_cache.find(size);
++ if (map_iter != m_free_cache.end())
++ {
++ if (!map_iter->second.empty())
++ {
++ ret = map_iter->second.back();
++ map_iter->second.pop_back();
++ m_reserved_cache[ret] = size;
++ }
++ }
++
++ return ret;
++}
++
++void
++Process::ReservationCache::CheckModID()
++{
++ if (m_mod_id != m_process.GetModID())
++ {
++ // wipe all our caches, they're invalid
++ m_reserved_cache.clear();
++ m_free_cache.clear();
++ m_mod_id = m_process.GetModID();
++ }
++}
+Index: source/Target/Target.cpp
+===================================================================
+--- source/Target/Target.cpp (revision 183906)
++++ source/Target/Target.cpp (working copy)
+@@ -984,11 +984,16 @@
+ LoadScriptingResourceForModule (const ModuleSP &module_sp, Target *target)
+ {
+ Error error;
+- if (module_sp && !module_sp->LoadScriptingResourceInTarget(target, error))
++ StreamString feedback_stream;
++ if (module_sp && !module_sp->LoadScriptingResourceInTarget(target, error, &feedback_stream))
+ {
+- target->GetDebugger().GetOutputStream().Printf("unable to load scripting data for module %s - error reported was %s\n",
+- module_sp->GetFileSpec().GetFileNameStrippingExtension().GetCString(),
+- error.AsCString());
++ if (error.AsCString())
++ target->GetDebugger().GetErrorStream().Printf("unable to load scripting data for module %s - error reported was %s\n",
++ module_sp->GetFileSpec().GetFileNameStrippingExtension().GetCString(),
++ error.AsCString());
++ if (feedback_stream.GetSize())
++ target->GetDebugger().GetOutputStream().Printf("%s\n",
++ feedback_stream.GetData());
+ }
+ }
+
+@@ -1140,18 +1145,21 @@
+ void
+ Target::SymbolsDidLoad (ModuleList &module_list)
+ {
+- if (module_list.GetSize() == 0)
+- return;
+- if (m_process_sp)
++ if (module_list.GetSize())
+ {
+- LanguageRuntime* runtime = m_process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
+- if (runtime)
++ if (m_process_sp)
+ {
+- ObjCLanguageRuntime *objc_runtime = (ObjCLanguageRuntime*)runtime;
+- objc_runtime->SymbolsDidLoad(module_list);
++ LanguageRuntime* runtime = m_process_sp->GetLanguageRuntime(lldb::eLanguageTypeObjC);
++ if (runtime)
++ {
++ ObjCLanguageRuntime *objc_runtime = (ObjCLanguageRuntime*)runtime;
++ objc_runtime->SymbolsDidLoad(module_list);
++ }
+ }
++
++ m_breakpoint_list.UpdateBreakpoints (module_list, true);
++ BroadcastEvent(eBroadcastBitSymbolsLoaded, NULL);
+ }
+- BroadcastEvent(eBroadcastBitSymbolsLoaded, NULL);
+ }
+
+ void
+@@ -2265,6 +2273,15 @@
+ { 0, NULL, NULL }
+ };
+
++static OptionEnumValueElement
++g_load_script_from_sym_file_values[] =
++{
++ { eLoadScriptFromSymFileTrue, "true", "Load debug scripts inside symbol files"},
++ { eLoadScriptFromSymFileFalse, "false", "Do not load debug scripts inside symbol files."},
++ { eLoadScriptFromSymFileWarn, "warn", "Warn about debug scripts inside symbol files but do not load them."},
++ { 0, NULL, NULL }
++};
++
+ static PropertyDefinition
+ g_properties[] =
+ {
+@@ -2281,6 +2298,7 @@
+ { "exec-search-paths" , OptionValue::eTypeFileSpecList, false, 0 , NULL, NULL, "Executable search paths to use when locating executable files whose paths don't match the local file system." },
+ { "max-children-count" , OptionValue::eTypeSInt64 , false, 256 , NULL, NULL, "Maximum number of children to expand in any level of depth." },
+ { "max-string-summary-length" , OptionValue::eTypeSInt64 , false, 1024 , NULL, NULL, "Maximum number of characters to show when using %s in summary strings." },
++ { "max-memory-read-size" , OptionValue::eTypeSInt64 , false, 1024 , NULL, NULL, "Maximum number of bytes that 'memory read' will fetch before --force must be specified." },
+ { "breakpoints-use-platform-avoid-list", OptionValue::eTypeBoolean , false, true , NULL, NULL, "Consult the platform module avoid list when setting non-module specific breakpoints." },
+ { "arg0" , OptionValue::eTypeString , false, 0 , NULL, NULL, "The first argument passed to the program in the argument array which can be different from the executable itself." },
+ { "run-args" , OptionValue::eTypeArgs , false, 0 , NULL, NULL, "A list containing all the arguments to be passed to the executable when it is run. Note that this does NOT include the argv[0] which is in target.arg0." },
+@@ -2301,7 +2319,7 @@
+ // FIXME: This is the wrong way to do per-architecture settings, but we don't have a general per architecture settings system in place yet.
+ { "x86-disassembly-flavor" , OptionValue::eTypeEnum , false, eX86DisFlavorDefault, NULL, g_x86_dis_flavor_value_types, "The default disassembly flavor to use for x86 or x86-64 targets." },
+ { "use-fast-stepping" , OptionValue::eTypeBoolean , false, true, NULL, NULL, "Use a fast stepping algorithm based on running from branch to branch rather than instruction single-stepping." },
+- { "load-script-from-symbol-file" , OptionValue::eTypeBoolean , false, false, NULL, NULL, "Allow LLDB to load scripting resources embedded in symbol files when available." },
++ { "load-script-from-symbol-file" , OptionValue::eTypeEnum , false, eLoadScriptFromSymFileWarn, NULL, g_load_script_from_sym_file_values, "Allow LLDB to load scripting resources embedded in symbol files when available." },
+ { NULL , OptionValue::eTypeInvalid , false, 0 , NULL, NULL, NULL }
+ };
+ enum
+@@ -2315,6 +2333,7 @@
+ ePropertyExecutableSearchPaths,
+ ePropertyMaxChildrenCount,
+ ePropertyMaxSummaryLength,
++ ePropertyMaxMemReadSize,
+ ePropertyBreakpointUseAvoidList,
+ ePropertyArg0,
+ ePropertyRunArgs,
+@@ -2328,7 +2347,7 @@
+ ePropertyInlineStrategy,
+ ePropertyDisassemblyFlavor,
+ ePropertyUseFastStepping,
+- ePropertyLoadScriptFromSymbolFile
++ ePropertyLoadScriptFromSymbolFile,
+ };
+
+
+@@ -2373,6 +2392,13 @@
+ }
+ return ProtectedGetPropertyAtIndex (idx);
+ }
++
++ lldb::TargetSP
++ GetTargetSP ()
++ {
++ return m_target->shared_from_this();
++ }
++
+ protected:
+
+ void
+@@ -2603,6 +2629,13 @@
+ return m_collection_sp->GetPropertyAtIndexAsSInt64 (NULL, idx, g_properties[idx].default_uint_value);
+ }
+
++uint32_t
++TargetProperties::GetMaximumMemReadSize () const
++{
++ const uint32_t idx = ePropertyMaxMemReadSize;
++ return m_collection_sp->GetPropertyAtIndexAsSInt64 (NULL, idx, g_properties[idx].default_uint_value);
++}
++
+ FileSpec
+ TargetProperties::GetStandardInputPath () const
+ {
+@@ -2674,20 +2707,13 @@
+ return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
+ }
+
+-bool
++LoadScriptFromSymFile
+ TargetProperties::GetLoadScriptFromSymbolFile () const
+ {
+ const uint32_t idx = ePropertyLoadScriptFromSymbolFile;
+- return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
++ return (LoadScriptFromSymFile)m_collection_sp->GetPropertyAtIndexAsEnumeration(NULL, idx, g_properties[idx].default_uint_value);
+ }
+
+-void
+-TargetProperties::SetLoadScriptFromSymbolFile (bool b)
+-{
+- const uint32_t idx = ePropertyLoadScriptFromSymbolFile;
+- m_collection_sp->SetPropertyAtIndexAsBoolean(NULL, idx, b);
+-}
+-
+ const TargetPropertiesSP &
+ Target::GetGlobalProperties()
+ {
+Index: source/Target/ThreadPlanStepOverRange.cpp
+===================================================================
+--- source/Target/ThreadPlanStepOverRange.cpp (revision 183906)
++++ source/Target/ThreadPlanStepOverRange.cpp (working copy)
+@@ -300,7 +300,7 @@
+ // unexplained breakpoint/crash.
+
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
+- StopInfoSP stop_info_sp = GetPrivateStopReason();
++ StopInfoSP stop_info_sp = GetPrivateStopInfo ();
+ bool return_value;
+
+ if (stop_info_sp)
+Index: source/Target/ThreadPlanStepOverBreakpoint.cpp
+===================================================================
+--- source/Target/ThreadPlanStepOverBreakpoint.cpp (revision 183906)
++++ source/Target/ThreadPlanStepOverBreakpoint.cpp (working copy)
+@@ -61,7 +61,7 @@
+ bool
+ ThreadPlanStepOverBreakpoint::DoPlanExplainsStop (Event *event_ptr)
+ {
+- StopInfoSP stop_info_sp = GetPrivateStopReason();
++ StopInfoSP stop_info_sp = GetPrivateStopInfo ();
+ if (stop_info_sp)
+ {
+ StopReason reason = stop_info_sp->GetStopReason();
+Index: source/Target/CPPLanguageRuntime.cpp
+===================================================================
+--- source/Target/CPPLanguageRuntime.cpp (revision 183906)
++++ source/Target/CPPLanguageRuntime.cpp (working copy)
+@@ -9,6 +9,8 @@
+
+ #include "lldb/Target/CPPLanguageRuntime.h"
+
++#include <string.h>
++
+ #include "lldb/Core/PluginManager.h"
+ #include "lldb/Core/UniqueCStringMap.h"
+ #include "lldb/Target/ExecutionContext.h"
+@@ -193,15 +195,7 @@
+ if (base_name_end == NULL)
+ base_name_end = name + strlen (name);
+
+- const char *last_colon = NULL;
+- for (const char *ptr = base_name_end; ptr != name; ptr--)
+- {
+- if (*ptr == ':')
+- {
+- last_colon = ptr;
+- break;
+- }
+- }
++ const char *last_colon = strrchr (name, ':');
+
+ if (last_colon == NULL)
+ {
+@@ -221,36 +215,6 @@
+ return true;
+ }
+ }
+-bool
+-CPPLanguageRuntime::IsPossibleCPPCall (const char *name, const char *&base_name_start, const char *&base_name_end)
+-{
+- if (!name)
+- return false;
+- // For now, I really can't handle taking template names apart, so if you
+- // have < or > I'll say "could be CPP but leave the base_name empty which
+- // means I couldn't figure out what to use for that.
+- // FIXME: Do I need to do more sanity checking here?
+-
+- if (strchr(name, '>') != NULL || strchr (name, '>') != NULL)
+- return true;
+-
+- size_t name_len = strlen (name);
+-
+- if (name[name_len - 1] == ')')
+- {
+- // We've got arguments.
+- base_name_end = strchr (name, '(');
+- if (base_name_end == NULL)
+- return false;
+-
+- // FIXME: should check that this parenthesis isn't a template specialized
+- // on a function type or something gross like that...
+- }
+- else
+- base_name_end = name + strlen (name);
+-
+- return StripNamespacesFromVariableName (name, base_name_start, base_name_end);
+-}
+
+ uint32_t
+ CPPLanguageRuntime::FindEquivalentNames(ConstString type_name, std::vector<ConstString>& equivalents)
+@@ -272,7 +236,7 @@
+ CPPLanguageRuntime::MethodName::Clear()
+ {
+ m_full.Clear();
+- m_basename.Clear();
++ m_basename = llvm::StringRef();
+ m_context = llvm::StringRef();
+ m_arguments = llvm::StringRef();
+ m_qualifiers = llvm::StringRef();
+@@ -356,12 +320,12 @@
+ context_end = full.rfind(':', basename_end);
+
+ if (context_end == llvm::StringRef::npos)
+- m_basename.SetString(full.substr(0, basename_end));
++ m_basename = full.substr(0, basename_end);
+ else
+ {
+ m_context = full.substr(0, context_end - 1);
+ const size_t basename_begin = context_end + 1;
+- m_basename.SetString(full.substr(basename_begin, basename_end - basename_begin));
++ m_basename = full.substr(basename_begin, basename_end - basename_begin);
+ }
+ m_type = eTypeUnknownMethod;
+ }
+@@ -388,7 +352,7 @@
+ }
+ }
+
+-const ConstString &
++llvm::StringRef
+ CPPLanguageRuntime::MethodName::GetBasename ()
+ {
+ if (!m_parsed)
+Index: source/Target/ThreadPlanCallUserExpression.cpp
+===================================================================
+--- source/Target/ThreadPlanCallUserExpression.cpp (revision 183906)
++++ source/Target/ThreadPlanCallUserExpression.cpp (working copy)
+@@ -67,12 +67,16 @@
+ ThreadPlanCallUserExpression::GetRealStopInfo()
+ {
+ StopInfoSP stop_info_sp = ThreadPlanCallFunction::GetRealStopInfo();
+- lldb::addr_t addr = GetStopAddress();
+- DynamicCheckerFunctions *checkers = m_thread.GetProcess()->GetDynamicCheckers();
+- StreamString s;
+
+- if (checkers && checkers->DoCheckersExplainStop(addr, s))
+- stop_info_sp->SetDescription(s.GetData());
++ if (stop_info_sp)
++ {
++ lldb::addr_t addr = GetStopAddress();
++ DynamicCheckerFunctions *checkers = m_thread.GetProcess()->GetDynamicCheckers();
++ StreamString s;
++
++ if (checkers && checkers->DoCheckersExplainStop(addr, s))
++ stop_info_sp->SetDescription(s.GetData());
++ }
+
+ return stop_info_sp;
+ }
+Index: source/Target/ThreadPlanStepOut.cpp
+===================================================================
+--- source/Target/ThreadPlanStepOut.cpp (revision 183906)
++++ source/Target/ThreadPlanStepOut.cpp (working copy)
+@@ -200,7 +200,7 @@
+ // We don't explain signals or breakpoints (breakpoints that handle stepping in or
+ // out will be handled by a child plan.
+
+- StopInfoSP stop_info_sp = GetPrivateStopReason();
++ StopInfoSP stop_info_sp = GetPrivateStopInfo ();
+ if (stop_info_sp)
+ {
+ StopReason reason = stop_info_sp->GetStopReason();
+Index: source/Target/StackFrameList.cpp
+===================================================================
+--- source/Target/StackFrameList.cpp (revision 183906)
++++ source/Target/StackFrameList.cpp (working copy)
+@@ -595,19 +595,42 @@
+ return frame_sp;
+ }
+
++static bool
++CompareStackID (const StackFrameSP &stack_sp, const StackID &stack_id)
++{
++ return stack_sp->GetStackID() < stack_id;
++}
++
+ StackFrameSP
+ StackFrameList::GetFrameWithStackID (const StackID &stack_id)
+ {
+- uint32_t frame_idx = 0;
+ StackFrameSP frame_sp;
+- do
++
++ if (stack_id.IsValid())
+ {
+- frame_sp = GetFrameAtIndex (frame_idx);
+- if (frame_sp && frame_sp->GetStackID() == stack_id)
+- break;
+- frame_idx++;
++ Mutex::Locker locker (m_mutex);
++ uint32_t frame_idx = 0;
++ // Do a binary search in case the stack frame is already in our cache
++ collection::const_iterator begin = m_frames.begin();
++ collection::const_iterator end = m_frames.end();
++ if (begin != end)
++ {
++ collection::const_iterator pos = std::lower_bound (begin, end, stack_id, CompareStackID);
++ if (pos != end && (*pos)->GetStackID() == stack_id)
++ return *pos;
++
++ if (m_frames.back()->GetStackID() < stack_id)
++ frame_idx = m_frames.size();
++ }
++ do
++ {
++ frame_sp = GetFrameAtIndex (frame_idx);
++ if (frame_sp && frame_sp->GetStackID() == stack_id)
++ break;
++ frame_idx++;
++ }
++ while (frame_sp);
+ }
+- while (frame_sp);
+ return frame_sp;
+ }
+
+Index: source/Target/StackFrame.cpp
+===================================================================
+--- source/Target/StackFrame.cpp (revision 183906)
++++ source/Target/StackFrame.cpp (working copy)
+@@ -1282,13 +1282,12 @@
+
+ GetSymbolContext(eSymbolContextEverything);
+ ExecutionContext exe_ctx (shared_from_this());
+- const char *end = NULL;
+ StreamString s;
+ const char *frame_format = NULL;
+ Target *target = exe_ctx.GetTargetPtr();
+ if (target)
+ frame_format = target->GetDebugger().GetFrameFormat();
+- if (frame_format && Debugger::FormatPrompt (frame_format, &m_sc, &exe_ctx, NULL, s, &end))
++ if (frame_format && Debugger::FormatPrompt (frame_format, &m_sc, &exe_ctx, NULL, s))
+ {
+ strm->Write(s.GetData(), s.GetSize());
+ }
+Index: source/Target/ThreadPlanStepInstruction.cpp
+===================================================================
+--- source/Target/ThreadPlanStepInstruction.cpp (revision 183906)
++++ source/Target/ThreadPlanStepInstruction.cpp (working copy)
+@@ -83,7 +83,7 @@
+ bool
+ ThreadPlanStepInstruction::DoPlanExplainsStop (Event *event_ptr)
+ {
+- StopInfoSP stop_info_sp = GetPrivateStopReason();
++ StopInfoSP stop_info_sp = GetPrivateStopInfo ();
+ if (stop_info_sp)
+ {
+ StopReason reason = stop_info_sp->GetStopReason();
+Index: source/Target/ThreadPlanStepInRange.cpp
+===================================================================
+--- source/Target/ThreadPlanStepInRange.cpp (revision 183906)
++++ source/Target/ThreadPlanStepInRange.cpp (working copy)
+@@ -403,7 +403,7 @@
+ }
+ else
+ {
+- StopInfoSP stop_info_sp = GetPrivateStopReason();
++ StopInfoSP stop_info_sp = GetPrivateStopInfo ();
+ if (stop_info_sp)
+ {
+ StopReason reason = stop_info_sp->GetStopReason();
+Index: source/Target/Platform.cpp
+===================================================================
+--- source/Target/Platform.cpp (revision 183906)
++++ source/Target/Platform.cpp (working copy)
+@@ -118,7 +118,7 @@
+ {
+ for (uint32_t idx = 0; (create_callback = PluginManager::GetPlatformCreateCallbackAtIndex(idx)) != NULL; ++idx)
+ {
+- std::unique_ptr<Platform> instance_ap(create_callback(process, false));
++ std::unique_ptr<Platform> instance_ap(create_callback(process, nullptr));
+ if (instance_ap.get())
+ return instance_ap.release();
+ }
+Index: source/Target/ThreadPlanCallFunction.cpp
+===================================================================
+--- source/Target/ThreadPlanCallFunction.cpp (revision 183906)
++++ source/Target/ThreadPlanCallFunction.cpp (working copy)
+@@ -298,7 +298,7 @@
+ log->Printf ("ThreadPlanCallFunction(%p): DoTakedown called for thread 0x%4.4" PRIx64 ", m_valid: %d complete: %d.\n", this, m_thread.GetID(), m_valid, IsPlanComplete());
+ m_takedown_done = true;
+ m_stop_address = m_thread.GetStackFrameAtIndex(0)->GetRegisterContext()->GetPC();
+- m_real_stop_info_sp = GetPrivateStopReason();
++ m_real_stop_info_sp = GetPrivateStopInfo ();
+ m_thread.RestoreRegisterStateFromCheckpoint(m_stored_thread_state);
+ SetPlanComplete(success);
+ ClearBreakpoints();
+@@ -365,7 +365,7 @@
+ ThreadPlanCallFunction::DoPlanExplainsStop (Event *event_ptr)
+ {
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_STEP|LIBLLDB_LOG_PROCESS));
+- m_real_stop_info_sp = GetPrivateStopReason();
++ m_real_stop_info_sp = GetPrivateStopInfo ();
+
+ // If our subplan knows why we stopped, even if it's done (which would forward the question to us)
+ // we answer yes.
+@@ -584,14 +584,22 @@
+ bool
+ ThreadPlanCallFunction::BreakpointsExplainStop()
+ {
+- StopInfoSP stop_info_sp = GetPrivateStopReason();
++ StopInfoSP stop_info_sp = GetPrivateStopInfo ();
+
+ if ((m_cxx_language_runtime &&
+ m_cxx_language_runtime->ExceptionBreakpointsExplainStop(stop_info_sp))
+ ||(m_objc_language_runtime &&
+ m_objc_language_runtime->ExceptionBreakpointsExplainStop(stop_info_sp)))
+ {
++ Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_STEP));
++ if (log)
++ log->Printf ("ThreadPlanCallFunction::BreakpointsExplainStop - Hit an exception breakpoint, setting plan complete.");
++
+ SetPlanComplete(false);
++
++ // If the user has set the ObjC language breakpoint, it would normally get priority over our internal
++ // catcher breakpoint, but in this case we can't let that happen, so force the ShouldStop here.
++ stop_info_sp->OverrideShouldStop (true);
+ return true;
+ }
+
+Index: source/Target/ThreadPlanStepUntil.cpp
+===================================================================
+--- source/Target/ThreadPlanStepUntil.cpp (revision 183906)
++++ source/Target/ThreadPlanStepUntil.cpp (working copy)
+@@ -176,7 +176,7 @@
+ if (m_ran_analyze)
+ return;
+
+- StopInfoSP stop_info_sp = GetPrivateStopReason();
++ StopInfoSP stop_info_sp = GetPrivateStopInfo ();
+ m_should_stop = true;
+ m_explains_stop = false;
+
+@@ -320,7 +320,7 @@
+ // do so here. Otherwise, as long as this thread has stopped for a reason,
+ // we will stop.
+
+- StopInfoSP stop_info_sp = GetPrivateStopReason();
++ StopInfoSP stop_info_sp = GetPrivateStopInfo ();
+ if (!stop_info_sp || stop_info_sp->GetStopReason() == eStopReasonNone)
+ return false;
+
+Index: source/Target/Thread.cpp
+===================================================================
+--- source/Target/Thread.cpp (revision 183906)
++++ source/Target/Thread.cpp (working copy)
+@@ -442,6 +442,9 @@
+ m_stop_info_stop_id = process_sp->GetStopID();
+ else
+ m_stop_info_stop_id = UINT32_MAX;
++ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
++ if (log)
++ log->Printf("%p: tid = 0x%" PRIx64 ": stop info = %s (stop_id = %u)\n", this, GetID(), stop_info_sp ? stop_info_sp->GetDescription() : "<NULL>", m_stop_info_stop_id);
+ }
+
+ void
+@@ -1744,13 +1747,11 @@
+
+ const char *thread_format = exe_ctx.GetTargetRef().GetDebugger().GetThreadFormat();
+ assert (thread_format);
+- const char *end = NULL;
+ Debugger::FormatPrompt (thread_format,
+ frame_sp ? &frame_sc : NULL,
+ &exe_ctx,
+ NULL,
+- strm,
+- &end);
++ strm);
+ }
+
+ void
+Index: source/Target/Memory.cpp
+===================================================================
+--- source/Target/Memory.cpp (revision 183906)
++++ source/Target/Memory.cpp (working copy)
+@@ -40,10 +40,12 @@
+ }
+
+ void
+-MemoryCache::Clear()
++MemoryCache::Clear(bool clear_invalid_ranges)
+ {
+ Mutex::Locker locker (m_mutex);
+ m_cache.clear();
++ if (clear_invalid_ranges)
++ m_invalid_ranges.Clear();
+ }
+
+ void
+Index: source/Target/ExecutionContext.cpp
+===================================================================
+--- source/Target/ExecutionContext.cpp (revision 183906)
++++ source/Target/ExecutionContext.cpp (working copy)
+@@ -806,9 +806,12 @@
+ lldb::StackFrameSP
+ ExecutionContextRef::GetFrameSP () const
+ {
+- lldb::ThreadSP thread_sp (GetThreadSP());
+- if (thread_sp)
+- return thread_sp->GetFrameWithStackID (m_stack_id);
++ if (m_stack_id.IsValid())
++ {
++ lldb::ThreadSP thread_sp (GetThreadSP());
++ if (thread_sp)
++ return thread_sp->GetFrameWithStackID (m_stack_id);
++ }
+ return lldb::StackFrameSP();
+ }
+
+Index: lib/Makefile
+===================================================================
+--- lib/Makefile (revision 183906)
++++ lib/Makefile (working copy)
+@@ -71,7 +71,7 @@
+ # Because GCC requires RTTI enabled for lldbCore (see source/Core/Makefile) it is
+ # necessary to also link the clang rewriter libraries so vtable references can
+ # be resolved correctly, if we are building with GCC.
+-ifeq (g++,$(shell basename $(CXX)))
++ifeq (g++,$(shell basename $(CXX) | colrm 4))
+ USEDLIBS += clangRewriteCore.a \
+ clangRewriteFrontend.a
+ endif
+Index: lldb.xcodeproj/project.pbxproj
+===================================================================
+--- lldb.xcodeproj/project.pbxproj (revision 183906)
++++ lldb.xcodeproj/project.pbxproj (working copy)
+@@ -519,6 +519,7 @@
+ 4CF52AF8142829390051E832 /* SBFileSpecList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CF52AF7142829390051E832 /* SBFileSpecList.cpp */; };
+ 94031A9E13CF486700DCFF3C /* InputReaderEZ.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94031A9D13CF486600DCFF3C /* InputReaderEZ.cpp */; };
+ 94094C6B163B6F840083A547 /* ValueObjectCast.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94094C69163B6CD90083A547 /* ValueObjectCast.cpp */; };
++ 94145431175E63B500284436 /* lldb-versioning.h in Headers */ = {isa = PBXBuildFile; fileRef = 94145430175D7FDE00284436 /* lldb-versioning.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 941BCC7F14E48C4000BB969C /* SBTypeFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 9461568614E355F2003A195C /* SBTypeFilter.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 941BCC8014E48C4000BB969C /* SBTypeFormat.h in Headers */ = {isa = PBXBuildFile; fileRef = 9461568714E355F2003A195C /* SBTypeFormat.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 941BCC8114E48C4000BB969C /* SBTypeSummary.h in Headers */ = {isa = PBXBuildFile; fileRef = 9461568814E355F2003A195C /* SBTypeSummary.h */; settings = {ATTRIBUTES = (Public, ); }; };
+@@ -1560,6 +1561,7 @@
+ 940DB8E116EA674000D3C2F1 /* Xcode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Xcode.cpp; sourceTree = "<group>"; };
+ 940DB8E216EA674000D3C2F1 /* Xcode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Xcode.h; sourceTree = "<group>"; };
+ 940DB8E616EA709400D3C2F1 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = "<group>"; };
++ 94145430175D7FDE00284436 /* lldb-versioning.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "lldb-versioning.h"; path = "include/lldb/lldb-versioning.h"; sourceTree = "<group>"; };
+ 944372DA171F6B4300E57C32 /* RegisterContextDummy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RegisterContextDummy.cpp; path = Utility/RegisterContextDummy.cpp; sourceTree = "<group>"; };
+ 944372DB171F6B4300E57C32 /* RegisterContextDummy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RegisterContextDummy.h; path = Utility/RegisterContextDummy.h; sourceTree = "<group>"; };
+ 9443B120140C18A90013457C /* SBData.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SBData.h; path = include/lldb/API/SBData.h; sourceTree = "<group>"; };
+@@ -2160,6 +2162,7 @@
+ 26DE1E6A11616C2E00A093E2 /* lldb-forward.h */,
+ 26651A14133BEC76005B64B7 /* lldb-public.h */,
+ 26BC7C2910F1B3BC00F91463 /* lldb-types.h */,
++ 94145430175D7FDE00284436 /* lldb-versioning.h */,
+ 26B42C4C1187ABA50079C8C8 /* LLDB.h */,
+ 9A9830FC1125FC5800A56CB0 /* SBDefines.h */,
+ 26DE204211618ACA00A093E2 /* SBAddress.h */,
+@@ -3505,6 +3508,7 @@
+ 2668020F115FD12C008E1FE4 /* lldb-enumerations.h in Headers */,
+ 26DE1E6C11616C2E00A093E2 /* lldb-forward.h in Headers */,
+ 26680214115FD12C008E1FE4 /* lldb-types.h in Headers */,
++ 94145431175E63B500284436 /* lldb-versioning.h in Headers */,
+ 26B42C4D1187ABA50079C8C8 /* LLDB.h in Headers */,
+ 26DE204311618ACA00A093E2 /* SBAddress.h in Headers */,
+ 26DE205711618FC500A093E2 /* SBBlock.h in Headers */,
+Index: lldb.xcodeproj/xcshareddata/xcschemes/lldb-tool.xcscheme
+===================================================================
+--- lldb.xcodeproj/xcshareddata/xcschemes/lldb-tool.xcscheme (revision 183906)
++++ lldb.xcodeproj/xcshareddata/xcschemes/lldb-tool.xcscheme (working copy)
+@@ -84,7 +84,7 @@
+ <LaunchAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+- launchStyle = "0"
++ launchStyle = "1"
+ useCustomWorkingDirectory = "NO"
+ customWorkingDirectory = "/Volumes/work/gclayton/Documents/devb/attach"
+ buildConfiguration = "Debug"
+Index: .arcconfig
+===================================================================
+--- .arcconfig (revision 0)
++++ .arcconfig (revision 0)
+@@ -0,0 +1,4 @@
++{
++ "project_id" : "lldb",
++ "conduit_uri" : "http://llvm-reviews.chandlerc.com/"
++}
+Index: CMakeLists.txt
+===================================================================
+--- CMakeLists.txt (revision 183906)
++++ CMakeLists.txt (working copy)
+@@ -147,6 +147,11 @@
+ "`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)
+@@ -170,7 +175,7 @@
+ #endif()
+
+ if(LLDB_USED_LIBS)
+- if (CMAKE_SYSTEM_NAME MATCHES "Linux")
++ if (CMAKE_SYSTEM_NAME MATCHES "Linux" OR CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
+ target_link_libraries(${name} -Wl,--start-group ${LLDB_USED_LIBS} -Wl,--end-group)
+ else()
+ target_link_libraries(${name} ${LLDB_USED_LIBS})
+@@ -241,7 +246,13 @@
+ ${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)
+ add_subdirectory(scripts)
+ add_subdirectory(source)
+ add_subdirectory(test)
+Index: examples/python/diagnose_unwind.py
+===================================================================
+--- examples/python/diagnose_unwind.py (revision 183906)
++++ examples/python/diagnose_unwind.py (working copy)
+@@ -1,8 +1,10 @@
+-# This implements the "diagnose-unwind" command, usually installed in the debug session like
+-# script import lldb.macosx
+-# it is used when lldb's backtrace fails -- it collects and prints information about the stack frames,
+-# and tries an alternate unwind algorithm, that will help to understand why lldb's unwind algorithm did
+-# not succeed.
++# This implements the "diagnose-unwind" command, usually installed
++# in the debug session like
++# command script import lldb.diagnose
++# it is used when lldb's backtrace fails -- it collects and prints
++# information about the stack frames, and tries an alternate unwind
++# algorithm, that will help to understand why lldb's unwind algorithm
++# did not succeed.
+
+ import optparse
+ import lldb
+@@ -88,8 +90,14 @@
+ backtrace_print_frame (target, frame_num, cur_pc, cur_fp)
+
+ def diagnose_unwind(debugger, command, result, dict):
+- # Use the Shell Lexer to properly parse up command options just like a
+- # shell would
++ """
++Gather diagnostic information to help debug incorrect unwind (backtrace)
++behavior in lldb. When there is a backtrace that doesn't look
++correct, run this command with the correct thread selected and a
++large amount of diagnostic information will be printed, it is likely
++to be helpful when reporting the problem.
++ """
++
+ command_args = shlex.split(command)
+ parser = create_diagnose_unwind_options()
+ try:
+@@ -110,6 +118,7 @@
+ if len(lldb_versions_match.groups()) >= 5 and lldb_versions_match.groups()[4]:
+ lldb_minor = int(lldb_versions_match.groups()[4])
+
++ print 'LLDB version %s' % debugger.GetVersionString()
+ print 'Unwind diagnostics for thread %d' % thread.GetIndexID()
+ print ""
+ print "lldb's unwind algorithm:"
+Index: examples/python/diagnose_nsstring.py
+===================================================================
+--- examples/python/diagnose_nsstring.py (revision 0)
++++ examples/python/diagnose_nsstring.py (revision 0)
+@@ -0,0 +1,171 @@
++# This implements the "diagnose-nsstring" command, usually installed in the debug session like
++# command script import lldb.diagnose
++# it is used when NSString summary formatter fails to replicate the logic that went into LLDB making the
++# decisions it did and providing some useful context information that can be used for improving the formatter
++
++import lldb
++
++def read_memory(process,location,size):
++ data = ""
++ error = lldb.SBError()
++ for x in range(0,size-1):
++ byte = process.ReadUnsignedFromMemory(x+location,1,error)
++ if error.fail:
++ data = data + "err%s" % "" if x == size-2 else ":"
++ else:
++ try:
++ data = data + "0x%x" % byte
++ if byte == 0:
++ data = data + "(\\0)"
++ elif byte == 0xa:
++ data = data + "(\\a)"
++ elif byte == 0xb:
++ data = data + "(\\b)"
++ elif byte == 0xc:
++ data = data + "(\\c)"
++ elif byte == '\n':
++ data = data + "(\\n)"
++ else:
++ data = data + "(%s)" % chr(byte)
++ if x < size-2:
++ data = data + ":"
++ except Exception as e:
++ print e
++ return data
++
++def diagnose_nsstring_Command_Impl(debugger,command,result,internal_dict):
++ """
++ A command to diagnose the LLDB NSString data formatter
++ invoke as
++ (lldb) diagnose-nsstring <expr returning NSString>
++ e.g.
++ (lldb) diagnose-nsstring @"Hello world"
++ """
++ target = debugger.GetSelectedTarget()
++ process = target.GetProcess()
++ thread = process.GetSelectedThread()
++ frame = thread.GetSelectedFrame()
++ if not target.IsValid() or not process.IsValid():
++ return "unable to get target/process - cannot proceed"
++ options = lldb.SBExpressionOptions()
++ options.SetFetchDynamicValue()
++ error = lldb.SBError()
++ if frame.IsValid():
++ nsstring = frame.EvaluateExpression(command,options)
++ else:
++ nsstring = target.EvaluateExpression(command,options)
++ print >>result,str(nsstring)
++ nsstring_address = nsstring.GetValueAsUnsigned(0)
++ if nsstring_address == 0:
++ return "unable to obtain the string - cannot proceed"
++ expression = "\
++struct $__lldb__notInlineMutable {\
++ char* buffer;\
++ signed long length;\
++ signed long capacity;\
++ unsigned int hasGap:1;\
++ unsigned int isFixedCapacity:1;\
++ unsigned int isExternalMutable:1;\
++ unsigned int capacityProvidedExternally:1;\n\
++#if __LP64__\n\
++ unsigned long desiredCapacity:60;\n\
++#else\n\
++ unsigned long desiredCapacity:28;\n\
++#endif\n\
++ void* contentsAllocator;\
++};\
++\
++struct $__lldb__CFString {\
++ void* _cfisa;\
++ uint8_t _cfinfo[4];\
++ uint32_t _rc;\
++ union {\
++ struct __inline1 {\
++ signed long length;\
++ } inline1;\
++ struct __notInlineImmutable1 {\
++ char* buffer;\
++ signed long length;\
++ void* contentsDeallocator;\
++ } notInlineImmutable1;\
++ struct __notInlineImmutable2 {\
++ char* buffer;\
++ void* contentsDeallocator;\
++ } notInlineImmutable2;\
++ struct $__lldb__notInlineMutable notInlineMutable;\
++ } variants;\
++};\
++"
++
++ expression = expression + "*(($__lldb__CFString*) %d)" % nsstring_address
++ # print expression
++ dumped = target.EvaluateExpression(expression,options)
++ print >>result, str(dumped)
++
++ little_endian = (target.byte_order == lldb.eByteOrderLittle)
++ ptr_size = target.addr_size
++
++ info_bits = dumped.GetChildMemberWithName("_cfinfo").GetChildAtIndex(0 if little_endian else 3).GetValueAsUnsigned(0)
++ is_mutable = (info_bits & 1) == 1
++ is_inline = (info_bits & 0x60) == 0
++ has_explicit_length = (info_bits & (1 | 4)) != 4
++ is_unicode = (info_bits & 0x10) == 0x10
++ is_special = (nsstring.GetDynamicValue(lldb.eDynamicCanRunTarget).GetTypeName() == "NSPathStore2")
++ has_null = (info_bits & 8) == 8
++
++ print >>result,"\nInfo=%d\nMutable=%s\nInline=%s\nExplicit=%s\nUnicode=%s\nSpecial=%s\nNull=%s\n" % \
++ (info_bits, "yes" if is_mutable else "no","yes" if is_inline else "no","yes" if has_explicit_length else "no","yes" if is_unicode else "no","yes" if is_special else "no","yes" if has_null else "no")
++
++
++ explicit_length_offset = 0
++ if not has_null and has_explicit_length and not is_special:
++ explicit_length_offset = 2*ptr_size
++ if is_mutable and not is_inline:
++ explicit_length_offset = explicit_length_offset + ptr_size
++ elif is_inline:
++ pass
++ elif not is_inline and not is_mutable:
++ explicit_length_offset = explicit_length_offset + ptr_size
++ else:
++ explicit_length_offset = 0
++
++ if explicit_length_offset == 0:
++ print >>result,"There is no explicit length marker - skipping this step\n"
++ else:
++ explicit_length_offset = nsstring_address + explicit_length_offset
++ explicit_length = process.ReadUnsignedFromMemory(explicit_length_offset, 4, error)
++ print >>result,"Explicit length location is at 0x%x - read value is %d\n" % (explicit_length_offset,explicit_length)
++
++ if is_mutable:
++ location = 2 * ptr_size + nsstring_address
++ location = process.ReadPointerFromMemory(location,error)
++ elif is_inline and has_explicit_length and not is_unicode and not is_special and not is_mutable:
++ location = 3 * ptr_size + nsstring_address
++ elif is_unicode:
++ location = 2 * ptr_size + nsstring_address
++ if is_inline:
++ if not has_explicit_length:
++ print >>result,"Unicode & Inline & !Explicit is a new combo - no formula for it"
++ else:
++ location += ptr_size
++ else:
++ location = process.ReadPointerFromMemory(location,error)
++ elif is_special:
++ location = nsstring_address + ptr_size + 4
++ elif is_inline:
++ location = 2 * ptr_size + nsstring_address
++ if not has_explicit_length:
++ location += 1
++ else:
++ location = 2 * ptr_size + nsstring_address
++ location = process.ReadPointerFromMemory(location,error)
++ print >>result,"Expected data location: 0x%x\n" % (location)
++ print >>result,"1K of data around location: %s\n" % read_memory(process,location,1024)
++ print >>result,"5K of data around string pointer: %s\n" % read_memory(process,nsstring_address,1024*5)
++
++def __lldb_init_module(debugger, internal_dict):
++ debugger.HandleCommand("command script add -f %s.diagnose_nsstring_Command_Impl diagnose-nsstring" % __name__)
++ print 'The "diagnose-nsstring" command has been installed, type "help diagnose-nsstring" for detailed help.'
++
++__lldb_init_module(lldb.debugger,None)
++__lldb_init_module = None
+\ No newline at end of file
+Index: test/dotest.py
+===================================================================
+--- test/dotest.py (revision 183906)
++++ test/dotest.py (working copy)
+@@ -1071,7 +1071,7 @@
+ raise Exception('log enable failed (check GDB_REMOTE_LOG env variable.')
+
+ def getMyCommandLine():
+- ps = subprocess.Popen(['ps', '-o', "command=CMD", str(os.getpid())], stdout=subprocess.PIPE).communicate()[0]
++ ps = subprocess.Popen([which('ps'), '-o', "command=CMD", str(os.getpid())], stdout=subprocess.PIPE).communicate()[0]
+ lines = ps.split('\n')
+ cmd_line = lines[1]
+ return cmd_line
+Index: test/expression_command/persistent_variables/TestPersistentVariables.py
+===================================================================
+--- test/expression_command/persistent_variables/TestPersistentVariables.py (revision 183906)
++++ test/expression_command/persistent_variables/TestPersistentVariables.py (working copy)
+@@ -17,31 +17,39 @@
+
+ self.runCmd("file a.out", CURRENT_EXECUTABLE_SET)
+
+- self.runCmd("breakpoint set --name main")
++ self.runCmd("breakpoint set --source-pattern-regexp break")
+
+ self.runCmd("run", RUN_SUCCEEDED)
+
+- self.expect("expression int $i = 5; $i + 1",
+- startstr = "(int) $0 = 6")
+- # (int) $0 = 6
++ self.runCmd("expression int $i = i")
+
++ self.expect("expression $i == i",
++ startstr = "(bool) $0 = true")
++
++ self.expect("expression $i + 1",
++ startstr = "(int) $1 = 6")
++
+ self.expect("expression $i + 3",
+- startstr = "(int) $1 = 8")
+- # (int) $1 = 8
++ startstr = "(int) $2 = 8")
+
+- self.expect("expression $1 + $0",
+- startstr = "(int) $2 = 14")
+- # (int) $2 = 14
++ self.expect("expression $2 + $1",
++ startstr = "(int) $3 = 14")
+
++ self.expect("expression $3",
++ startstr = "(int) $3 = 14")
++
+ self.expect("expression $2",
+- startstr = "(int) $2 = 14")
+- # (int) $2 = 14
++ startstr = "(int) $2 = 8")
+
+- self.expect("expression $1",
+- startstr = "(int) $1 = 8")
+- # (int) $1 = 8
++ self.expect("expression (int)-2",
++ startstr = "(int) $4 = -2")
+
++ self.expect("expression $4 > (int)31",
++ startstr = "(bool) $5 = false")
+
++ self.expect("expression (long)$4",
++ startstr = "(long) $6 = -2")
++
+ if __name__ == '__main__':
+ import atexit
+ lldb.SBDebugger.Initialize()
+Index: test/expression_command/persistent_variables/main.c
+===================================================================
+--- test/expression_command/persistent_variables/main.c (revision 183906)
++++ test/expression_command/persistent_variables/main.c (working copy)
+@@ -9,5 +9,6 @@
+
+ int main (int argc, char const *argv[])
+ {
+- return 0;
++ int i = 5;
++ return 0; // Set breakpoint here
+ }
+Index: test/expression_command/call-throws/TestCallThatThrows.py
+===================================================================
+--- test/expression_command/call-throws/TestCallThatThrows.py (revision 183906)
++++ test/expression_command/call-throws/TestCallThatThrows.py (working copy)
+@@ -1,5 +1,5 @@
+ """
+-Test calling a function that hits a signal set to auto-restart, make sure the call completes.
++Test calling a function that throws an ObjC exception, make sure that it doesn't propagate the exception.
+ """
+
+ import unittest2
+@@ -7,7 +7,7 @@
+ import lldbutil
+ from lldbtest import *
+
+-class ExprCommandWithTimeoutsTestCase(TestBase):
++class ExprCommandWithThrowTestCase(TestBase):
+
+ mydir = os.path.join("expression_command", "call-throws")
+
+@@ -22,14 +22,14 @@
+ @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
+ @dsym_test
+ def test_with_dsym(self):
+- """Test calling std::String member function."""
++ """Test calling a function that throws and ObjC exception."""
+ self.buildDsym()
+ self.call_function()
+
+ @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin due to ObjC test case")
+ @dwarf_test
+ def test_with_dwarf(self):
+- """Test calling std::String member function."""
++ """Test calling a function that throws and ObjC exception."""
+ self.buildDwarf()
+ self.call_function()
+
+@@ -40,7 +40,7 @@
+
+
+ def call_function(self):
+- """Test calling function with timeout."""
++ """Test calling function that throws."""
+ exe_name = "a.out"
+ exe = os.path.join(os.getcwd(), exe_name)
+
+@@ -86,6 +86,18 @@
+ self.assertTrue (value.IsValid() and value.GetError().Success() == False)
+ self.check_after_call()
+
++ # Now set the ObjC language breakpoint and make sure that doesn't interfere with the call:
++ exception_bkpt = target.BreakpointCreateForException (lldb.eLanguageTypeObjC, False, True)
++ self.assertTrue(exception_bkpt.GetNumLocations() > 0)
++
++ options.SetIgnoreBreakpoints(True)
++ options.SetUnwindOnError(True)
++
++ value = frame.EvaluateExpression ("[my_class callMeIThrow]", options)
++
++ self.assertTrue (value.IsValid() and value.GetError().Success() == False)
++ self.check_after_call()
++
+ # Now set this unwind on error to false, and make sure that we stop where the exception was thrown
+ options.SetUnwindOnError(False)
+ value = frame.EvaluateExpression ("[my_class callMeIThrow]", options)
+Index: test/python_api/watchpoint/watchlocation/TestTargetWatchAddress.py
+===================================================================
+--- test/python_api/watchpoint/watchlocation/TestTargetWatchAddress.py (revision 183906)
++++ test/python_api/watchpoint/watchlocation/TestTargetWatchAddress.py (working copy)
+@@ -30,7 +30,7 @@
+ self.buildDsym()
+ self.do_set_watchaddress()
+
+- @expectedFailureLinux # llvm.org/pr14416
++ @skipIfLinux # llvm.org/pr14323 - skip due to incomplete multi-threaded debug support
+ @python_api_test
+ @dwarf_test
+ def test_watch_address_with_dwarf(self):
+Index: test/python_api/watchpoint/watchlocation/TestSetWatchlocation.py
+===================================================================
+--- test/python_api/watchpoint/watchlocation/TestSetWatchlocation.py (revision 183906)
++++ test/python_api/watchpoint/watchlocation/TestSetWatchlocation.py (working copy)
+@@ -30,7 +30,7 @@
+ self.buildDsym()
+ self.do_set_watchlocation()
+
+- @expectedFailureLinux # llvm.org/pr14416
++ @skipIfLinux # Sometimes passes, sometimes not.
+ @python_api_test
+ @dwarf_test
+ def test_watch_location_with_dwarf(self):
+Index: test/functionalities/inferior-crashing/recursive-inferior/TestRecursiveInferior.py
+===================================================================
+--- test/functionalities/inferior-crashing/recursive-inferior/TestRecursiveInferior.py (revision 0)
++++ test/functionalities/inferior-crashing/recursive-inferior/TestRecursiveInferior.py (revision 0)
+@@ -0,0 +1,242 @@
++"""Test that lldb functions correctly after the inferior has crashed while in a recursive routine."""
++
++import os, time
++import unittest2
++import lldb, lldbutil
++from lldbtest import *
++
++class CrashingRecursiveInferiorTestCase(TestBase):
++
++ mydir = os.path.join("functionalities", "inferior-crashing", "recursive-inferior")
++
++ @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
++ def test_recursive_inferior_crashing_dsym(self):
++ """Test that lldb reliably catches the inferior crashing (command)."""
++ self.buildDsym()
++ self.recursive_inferior_crashing()
++
++ @expectedFailureLinux('llvm.org/pr15415', ['gcc', 'clang']) # partial backtrace with -fomit-frame-pointer with tool-chains that support this option
++ def test_recursive_inferior_crashing_dwarf(self):
++ """Test that lldb reliably catches the inferior crashing (command)."""
++ self.buildDwarf()
++ self.recursive_inferior_crashing()
++
++ @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
++ def test_recursive_inferior_crashing_registers_dsym(self):
++ """Test that lldb reliably reads registers from the inferior after crashing (command)."""
++ self.buildDsym()
++ self.recursive_inferior_crashing_registers()
++
++ def test_recursive_inferior_crashing_register_dwarf(self):
++ """Test that lldb reliably reads registers from the inferior after crashing (command)."""
++ self.buildDwarf()
++ self.recursive_inferior_crashing_registers()
++
++ @python_api_test
++ def test_recursive_inferior_crashing_python(self):
++ """Test that lldb reliably catches the inferior crashing (Python API)."""
++ self.buildDefault()
++ self.recursive_inferior_crashing_python()
++
++ @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
++ def test_recursive_inferior_crashing_expr_dsym(self):
++ """Test that the lldb expression interpreter can read from the inferior after crashing (command)."""
++ self.buildDsym()
++ self.recursive_inferior_crashing_expr()
++
++ def test_recursive_inferior_crashing_expr_dwarf(self):
++ """Test that the lldb expression interpreter can read from the inferior after crashing (command)."""
++ self.buildDwarf()
++ self.recursive_inferior_crashing_expr()
++
++ @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
++ def test_recursive_inferior_crashing_step_dsym(self):
++ """Test that lldb functions correctly after stepping through a crash."""
++ self.buildDsym()
++ self.recursive_inferior_crashing_step()
++
++ def test_recursive_inferior_crashing_step_dwarf(self):
++ """Test that stepping after a crash behaves correctly."""
++ self.buildDwarf()
++ self.recursive_inferior_crashing_step()
++
++ @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
++ def test_recursive_inferior_crashing_step_after_break_dsym(self):
++ """Test that stepping after a crash behaves correctly."""
++ self.buildDsym()
++ self.recursive_inferior_crashing_step_after_break()
++
++ def test_recursive_inferior_crashing_step_after_break_dwarf(self):
++ """Test that lldb functions correctly after stepping through a crash."""
++ self.buildDwarf()
++ self.recursive_inferior_crashing_step_after_break()
++
++ @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
++ def test_recursive_inferior_crashing_expr_step_and_expr_dsym(self):
++ """Test that lldb expressions work before and after stepping after a crash."""
++ self.buildDsym()
++ self.recursive_inferior_crashing_expr_step_expr()
++
++ @expectedFailureLinux # due to llvm.org/pr15415 with -fomit-frame-pointer, and pr15989 with ebp/rbp
++ def test_recursive_inferior_crashing_expr_step_and_expr_dwarf(self):
++ """Test that lldb expressions work before and after stepping after a crash."""
++ self.buildDwarf()
++ self.recursive_inferior_crashing_expr_step_expr()
++
++ def set_breakpoint(self, line):
++ lldbutil.run_break_set_by_file_and_line (self, "main.c", line, num_expected_locations=1, loc_exact=True)
++
++ def check_stop_reason(self):
++ if sys.platform.startswith("darwin"):
++ stop_reason = 'stop reason = EXC_BAD_ACCESS'
++ else:
++ stop_reason = 'stop reason = invalid address'
++
++ # The stop reason of the thread should be a bad access exception.
++ self.expect("thread list", STOPPED_DUE_TO_EXC_BAD_ACCESS,
++ substrs = ['stopped',
++ stop_reason])
++
++ return stop_reason
++
++ def setUp(self):
++ # Call super's setUp().
++ TestBase.setUp(self)
++ # Find the line number of the crash.
++ self.line = line_number('main.c', '// Crash here.')
++
++ def recursive_inferior_crashing(self):
++ """Inferior crashes upon launching; lldb should catch the event and stop."""
++ exe = os.path.join(os.getcwd(), "a.out")
++ self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
++
++ self.runCmd("run", RUN_SUCCEEDED)
++ stop_reason = self.check_stop_reason()
++
++ # And it should report a backtrace that includes main and the crash site.
++ self.expect("thread backtrace all",
++ substrs = [stop_reason, 'main', 'argc', 'argv', 'recursive_function'])
++
++ # And it should report the correct line number.
++ self.expect("thread backtrace all",
++ substrs = [stop_reason,
++ 'main.c:%d' % self.line])
++
++ def recursive_inferior_crashing_python(self):
++ """Inferior crashes upon launching; lldb should catch the event and stop."""
++ exe = os.path.join(os.getcwd(), "a.out")
++
++ target = self.dbg.CreateTarget(exe)
++ self.assertTrue(target, VALID_TARGET)
++
++ # Now launch the process, and do not stop at entry point.
++ # Both argv and envp are null.
++ process = target.LaunchSimple(None, None, os.getcwd())
++
++ if process.GetState() != lldb.eStateStopped:
++ self.fail("Process should be in the 'stopped' state, "
++ "instead the actual state is: '%s'" %
++ lldbutil.state_type_to_str(process.GetState()))
++
++ thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonException)
++ if not thread:
++ self.fail("Fail to stop the thread upon bad access exception")
++
++ if self.TraceOn():
++ lldbutil.print_stacktrace(thread)
++
++ def recursive_inferior_crashing_registers(self):
++ """Test that lldb can read registers after crashing."""
++ exe = os.path.join(os.getcwd(), "a.out")
++ self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
++
++ self.runCmd("run", RUN_SUCCEEDED)
++ self.check_stop_reason()
++
++ # lldb should be able to read from registers from the inferior after crashing.
++ self.expect("register read eax",
++ substrs = ['eax = 0x'])
++
++ def recursive_inferior_crashing_expr(self):
++ """Test that the lldb expression interpreter can read symbols after crashing."""
++ exe = os.path.join(os.getcwd(), "a.out")
++ self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
++
++ self.runCmd("run", RUN_SUCCEEDED)
++ self.check_stop_reason()
++
++ # The lldb expression interpreter should be able to read from addresses of the inferior after a crash.
++ self.expect("p i",
++ startstr = '(int) $0 =')
++
++ def recursive_inferior_crashing_step(self):
++ """Test that lldb functions correctly after stepping through a crash."""
++ exe = os.path.join(os.getcwd(), "a.out")
++ self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
++
++ self.set_breakpoint(self.line)
++ self.runCmd("run", RUN_SUCCEEDED)
++
++ self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
++ substrs = ['main.c:%d' % self.line,
++ 'stop reason = breakpoint'])
++
++ self.runCmd("next")
++ stop_reason = self.check_stop_reason()
++
++ # The lldb expression interpreter should be able to read from addresses of the inferior after a crash.
++ self.expect("p i",
++ substrs = ['(int) $0 ='])
++
++ # lldb should be able to read from registers from the inferior after crashing.
++ self.expect("register read eax",
++ substrs = ['eax = 0x'])
++
++ # And it should report the correct line number.
++ self.expect("thread backtrace all",
++ substrs = [stop_reason,
++ 'main.c:%d' % self.line])
++
++ def recursive_inferior_crashing_step_after_break(self):
++ """Test that lldb behaves correctly when stepping after a crash."""
++ exe = os.path.join(os.getcwd(), "a.out")
++ self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
++
++ self.runCmd("run", RUN_SUCCEEDED)
++ self.check_stop_reason()
++
++ expected_state = 'exited' # Provide the exit code.
++ if sys.platform.startswith("darwin"):
++ expected_state = 'stopped' # TODO: Determine why 'next' and 'continue' have no effect after a crash.
++
++ self.expect("next",
++ substrs = ['Process', expected_state])
++
++ self.expect("thread list", error=True,
++ substrs = ['Process must be launched'])
++
++ def recursive_inferior_crashing_expr_step_expr(self):
++ """Test that lldb expressions work before and after stepping after a crash."""
++ exe = os.path.join(os.getcwd(), "a.out")
++ self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
++
++ self.runCmd("run", RUN_SUCCEEDED)
++ self.check_stop_reason()
++
++ # The lldb expression interpreter should be able to read from addresses of the inferior after a crash.
++ self.expect("p null",
++ startstr = '(char *) $0 = 0x0')
++
++ self.runCmd("next")
++
++ # The lldb expression interpreter should be able to read from addresses of the inferior after a step.
++ self.expect("p null",
++ startstr = '(char *) $1 = 0x0')
++
++ self.check_stop_reason()
++
++if __name__ == '__main__':
++ import atexit
++ lldb.SBDebugger.Initialize()
++ atexit.register(lambda: lldb.SBDebugger.Terminate())
++ unittest2.main()
+Index: test/functionalities/inferior-crashing/recursive-inferior/Makefile
+===================================================================
+--- test/functionalities/inferior-crashing/recursive-inferior/Makefile (revision 0)
++++ test/functionalities/inferior-crashing/recursive-inferior/Makefile (revision 0)
+@@ -0,0 +1,7 @@
++LEVEL = ../../../make
++
++C_SOURCES := main.c
++
++CFLAGS_EXTRAS += -fomit-frame-pointer
++
++include $(LEVEL)/Makefile.rules
+Index: test/functionalities/inferior-crashing/recursive-inferior/main.c
+===================================================================
+--- test/functionalities/inferior-crashing/recursive-inferior/main.c (revision 0)
++++ test/functionalities/inferior-crashing/recursive-inferior/main.c (revision 0)
+@@ -0,0 +1,19 @@
++void recursive_function(int i)
++{
++ if (i < 10)
++ {
++ recursive_function(i + 1);
++ }
++ else
++ {
++ char *null=0;
++ *null = 0; // Crash here.
++ }
++}
++
++int main(int argc, char *argv[])
++{
++ recursive_function(0);
++ return 0;
++}
++
+Index: test/functionalities/inferior-crashing/TestInferiorCrashing.py
+===================================================================
+--- test/functionalities/inferior-crashing/TestInferiorCrashing.py (revision 183906)
++++ test/functionalities/inferior-crashing/TestInferiorCrashing.py (working copy)
+@@ -86,6 +86,19 @@
+ def set_breakpoint(self, line):
+ lldbutil.run_break_set_by_file_and_line (self, "main.c", line, num_expected_locations=1, loc_exact=True)
+
++ def check_stop_reason(self):
++ if sys.platform.startswith("darwin"):
++ stop_reason = 'stop reason = EXC_BAD_ACCESS'
++ else:
++ stop_reason = 'stop reason = invalid address'
++
++ # The stop reason of the thread should be a bad access exception.
++ self.expect("thread list", STOPPED_DUE_TO_EXC_BAD_ACCESS,
++ substrs = ['stopped',
++ stop_reason])
++
++ return stop_reason
++
+ def setUp(self):
+ # Call super's setUp().
+ TestBase.setUp(self)
+@@ -98,17 +111,8 @@
+ self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
+
+ self.runCmd("run", RUN_SUCCEEDED)
++ stop_reason = self.check_stop_reason()
+
+- if sys.platform.startswith("darwin"):
+- stop_reason = 'stop reason = EXC_BAD_ACCESS'
+- else:
+- stop_reason = 'stop reason = invalid address'
+-
+- # The stop reason of the thread should be a bad access exception.
+- self.expect("thread list", STOPPED_DUE_TO_EXC_BAD_ACCESS,
+- substrs = ['stopped',
+- stop_reason])
+-
+ # And it should report the correct line number.
+ self.expect("thread backtrace all",
+ substrs = [stop_reason,
+@@ -125,7 +129,6 @@
+ # Both argv and envp are null.
+ process = target.LaunchSimple(None, None, os.getcwd())
+
+- import lldbutil
+ if process.GetState() != lldb.eStateStopped:
+ self.fail("Process should be in the 'stopped' state, "
+ "instead the actual state is: '%s'" %
+@@ -144,12 +147,8 @@
+ self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
+
+ self.runCmd("run", RUN_SUCCEEDED)
++ self.check_stop_reason()
+
+- if sys.platform.startswith("darwin"):
+- stop_reason = 'stop reason = EXC_BAD_ACCESS'
+- else:
+- stop_reason = 'stop reason = invalid address'
+-
+ # lldb should be able to read from registers from the inferior after crashing.
+ self.expect("register read eax",
+ substrs = ['eax = 0x'])
+@@ -160,16 +159,8 @@
+ self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
+
+ self.runCmd("run", RUN_SUCCEEDED)
++ self.check_stop_reason()
+
+- if sys.platform.startswith("darwin"):
+- stop_reason = 'stop reason = EXC_BAD_ACCESS'
+- else:
+- stop_reason = 'stop reason = invalid address'
+-
+- # The stop reason of the thread should be a bad access exception.
+- self.expect("thread list", STOPPED_DUE_TO_EXC_BAD_ACCESS,
+- substrs = ['stopped', stop_reason])
+-
+ # The lldb expression interpreter should be able to read from addresses of the inferior after a crash.
+ self.expect("p argc",
+ startstr = '(int) $0 = 1')
+@@ -190,16 +181,8 @@
+ 'stop reason = breakpoint'])
+
+ self.runCmd("next")
++ stop_reason = self.check_stop_reason()
+
+- if sys.platform.startswith("darwin"):
+- stop_reason = 'stop reason = EXC_BAD_ACCESS'
+- else:
+- stop_reason = 'stop reason = invalid address'
+-
+- # The stop reason of the thread should be a bad access exception.
+- self.expect("thread list", STOPPED_DUE_TO_EXC_BAD_ACCESS,
+- substrs = ['stopped', stop_reason])
+-
+ # The lldb expression interpreter should be able to read from addresses of the inferior after a crash.
+ self.expect("p argv[0]",
+ substrs = ['a.out'])
+@@ -221,41 +204,26 @@
+ self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
+
+ self.runCmd("run", RUN_SUCCEEDED)
++ self.check_stop_reason()
+
+- if sys.platform.startswith("darwin"):
+- stop_reason = 'stop reason = EXC_BAD_ACCESS'
+- else:
+- stop_reason = 'stop reason = invalid address'
+-
+ self.runCmd("next")
++ self.check_stop_reason()
+
+- # The stop reason of the thread should still be a bad access exception.
+- self.expect("thread list", STOPPED_DUE_TO_EXC_BAD_ACCESS,
+- substrs = ['stopped', stop_reason])
+-
+ def inferior_crashing_expr_step_expr(self):
+ """Test that lldb expressions work before and after stepping after a crash."""
+ exe = os.path.join(os.getcwd(), "a.out")
+ self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
+
+ self.runCmd("run", RUN_SUCCEEDED)
++ self.check_stop_reason()
+
+- if sys.platform.startswith("darwin"):
+- stop_reason = 'stop reason = EXC_BAD_ACCESS'
+- else:
+- stop_reason = 'stop reason = invalid address'
+-
+ # The lldb expression interpreter should be able to read from addresses of the inferior after a crash.
+ self.expect("p argv[0]",
+ substrs = ['a.out'])
+
+ self.runCmd("next")
++ self.check_stop_reason()
+
+- if sys.platform.startswith("darwin"):
+- stop_reason = 'stop reason = EXC_BAD_ACCESS'
+- else:
+- stop_reason = 'stop reason = invalid address'
+-
+ # The lldb expression interpreter should be able to read from addresses of the inferior after a crash.
+ self.expect("p argv[0]",
+ substrs = ['a.out'])
+Index: test/functionalities/inferior-assert/main.c
+===================================================================
+--- test/functionalities/inferior-assert/main.c (revision 0)
++++ test/functionalities/inferior-assert/main.c (revision 0)
+@@ -0,0 +1,19 @@
++//===-- main.c --------------------------------------------------*- C++ -*-===//
++//
++// The LLVM Compiler Infrastructure
++//
++// This file is distributed under the University of Illinois Open Source
++// License. See LICENSE.TXT for details.
++//
++//===----------------------------------------------------------------------===//
++#include <stdio.h>
++#include <assert.h>
++
++const char *hello_world = "Hello, assertion!";
++
++int main(int argc, const char* argv[])
++{
++ int *null_ptr = 0;
++ printf("%s\n", hello_world);
++ assert(null_ptr); // Assert here.
++}
+Index: test/functionalities/inferior-assert/TestInferiorAssert.py
+===================================================================
+--- test/functionalities/inferior-assert/TestInferiorAssert.py (revision 0)
++++ test/functionalities/inferior-assert/TestInferiorAssert.py (revision 0)
+@@ -0,0 +1,221 @@
++"""Test that lldb functions correctly after the inferior has asserted."""
++
++import os, time
++import unittest2
++import lldb, lldbutil
++from lldbtest import *
++
++class AssertingInferiorTestCase(TestBase):
++
++ mydir = os.path.join("functionalities", "inferior-assert")
++
++ @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
++ def test_inferior_asserting_dsym(self):
++ """Test that lldb reliably catches the inferior asserting (command)."""
++ self.buildDsym()
++ self.inferior_asserting()
++
++ @skipIfGcc # avoid an xpass on the buildbots where libc was not built with -fomit-frame-pointer
++ @expectedFailureLinux # llvm.org/pr15671 - backtrace does not include the assert site
++ def test_inferior_asserting_dwarf(self):
++ """Test that lldb reliably catches the inferior asserting (command)."""
++ self.buildDwarf()
++ self.inferior_asserting()
++
++ @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
++ def test_inferior_asserting_registers_dsym(self):
++ """Test that lldb reliably reads registers from the inferior after asserting (command)."""
++ self.buildDsym()
++ self.inferior_asserting_registers()
++
++ def test_inferior_asserting_register_dwarf(self):
++ """Test that lldb reliably reads registers from the inferior after asserting (command)."""
++ self.buildDwarf()
++ self.inferior_asserting_registers()
++
++ @python_api_test
++ def test_inferior_asserting_python(self):
++ """Test that lldb reliably catches the inferior asserting (Python API)."""
++ self.buildDefault()
++ self.inferior_asserting_python()
++
++ @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
++ def test_inferior_asserting_expr(self):
++ """Test that the lldb expression interpreter can read from the inferior after asserting (command)."""
++ self.buildDsym()
++ self.inferior_asserting_expr()
++
++ @skipIfGcc # avoid an xpass on the buildbots where libc was not built with -fomit-frame-pointer
++ @expectedFailureLinux # llvm.org/pr15671 - backtrace does not include the assert site
++ def test_inferior_asserting_expr(self):
++ """Test that the lldb expression interpreter can read from the inferior after asserting (command)."""
++ self.buildDwarf()
++ self.inferior_asserting_expr()
++
++ @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
++ def test_inferior_asserting_step(self):
++ """Test that lldb functions correctly after stepping through a call to assert()."""
++ self.buildDsym()
++ self.inferior_asserting_step()
++
++ @skipIfGcc # avoid an xpass on the buildbots where libc was not built with -fomit-frame-pointer
++ @expectedFailureLinux # llvm.org/pr15671 - backtrace does not include the assert site
++ def test_inferior_asserting_step(self):
++ """Test that lldb functions correctly after stepping through a call to assert()."""
++ self.buildDwarf()
++ self.inferior_asserting_step()
++
++ def set_breakpoint(self, line):
++ lldbutil.run_break_set_by_file_and_line (self, "main.c", line, num_expected_locations=1, loc_exact=True)
++
++ def check_stop_reason(self):
++ stop_reason = 'stop reason = signal SIGABRT'
++
++ # The stop reason of the thread should be an abort signal or exception.
++ self.expect("thread list", STOPPED_DUE_TO_ASSERT,
++ substrs = ['stopped',
++ stop_reason])
++
++ return stop_reason
++
++ def setUp(self):
++ # Call super's setUp().
++ TestBase.setUp(self)
++ # Find the line number of the call to assert.
++ self.line = line_number('main.c', '// Assert here.')
++
++ def inferior_asserting(self):
++ """Inferior asserts upon launching; lldb should catch the event and stop."""
++ exe = os.path.join(os.getcwd(), "a.out")
++ self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
++
++ self.runCmd("run", RUN_SUCCEEDED)
++ stop_reason = self.check_stop_reason()
++
++ # And it should report a backtrace that includes the assert site.
++ self.expect("thread backtrace all",
++ substrs = [stop_reason, 'main', 'argc', 'argv'])
++
++ # And it should report the correct line number.
++ self.expect("thread backtrace all",
++ substrs = [stop_reason,
++ 'main.c:%d' % self.line])
++
++ def inferior_asserting_python(self):
++ """Inferior asserts upon launching; lldb should catch the event and stop."""
++ exe = os.path.join(os.getcwd(), "a.out")
++
++ target = self.dbg.CreateTarget(exe)
++ self.assertTrue(target, VALID_TARGET)
++
++ # Now launch the process, and do not stop at entry point.
++ # Both argv and envp are null.
++ process = target.LaunchSimple(None, None, os.getcwd())
++
++ if process.GetState() != lldb.eStateStopped:
++ self.fail("Process should be in the 'stopped' state, "
++ "instead the actual state is: '%s'" %
++ lldbutil.state_type_to_str(process.GetState()))
++
++ thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonSignal)
++ if not thread:
++ self.fail("Fail to stop the thread upon assert")
++
++ if self.TraceOn():
++ lldbutil.print_stacktrace(thread)
++
++ def inferior_asserting_registers(self):
++ """Test that lldb can read registers after asserting."""
++ exe = os.path.join(os.getcwd(), "a.out")
++ self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
++
++ self.runCmd("run", RUN_SUCCEEDED)
++ self.check_stop_reason()
++
++ # lldb should be able to read from registers from the inferior after asserting.
++ self.expect("register read eax",
++ substrs = ['eax = 0x'])
++
++ def check_expr_in_main(self, thread):
++ depth = thread.GetNumFrames()
++ for i in range(depth):
++ frame = thread.GetFrameAtIndex(i)
++ self.assertTrue(frame.IsValid(), "current frame is valid")
++ if self.TraceOn():
++ print "Checking if function %s is main" % frame.GetFunctionName()
++
++ if 'main' == frame.GetFunctionName():
++ frame_id = frame.GetFrameID()
++ self.runCmd("frame select " + str(frame_id), RUN_SUCCEEDED)
++ self.expect("p argc", substrs = ['(int)', ' = 1'])
++ self.expect("p hello_world", substrs = ['Hello'])
++ self.expect("p argv[0]", substrs = ['a.out'])
++ self.expect("p null_ptr", substrs = ['= 0x0'])
++ return True
++ return False
++
++ def inferior_asserting_expr(self):
++ """Test that the lldb expression interpreter can read symbols after asserting."""
++ exe = os.path.join(os.getcwd(), "a.out")
++
++ # Create a target by the debugger.
++ target = self.dbg.CreateTarget(exe)
++ self.assertTrue(target, VALID_TARGET)
++
++ # Launch the process, and do not stop at the entry point.
++ target.LaunchSimple(None, None, os.getcwd())
++ self.check_stop_reason()
++
++ process = target.GetProcess()
++ self.assertTrue(process.IsValid(), "current process is valid")
++
++ thread = process.GetThreadAtIndex(0)
++ self.assertTrue(thread.IsValid(), "current thread is valid")
++
++ # The lldb expression interpreter should be able to read from addresses of the inferior after a call to assert().
++ self.assertTrue(self.check_expr_in_main(thread), "cannot find 'main' in the backtrace")
++
++ def inferior_asserting_step(self):
++ """Test that lldb functions correctly after stepping through a call to assert()."""
++ exe = os.path.join(os.getcwd(), "a.out")
++
++ # Create a target by the debugger.
++ target = self.dbg.CreateTarget(exe)
++ self.assertTrue(target, VALID_TARGET)
++
++ # Launch the process, and do not stop at the entry point.
++ self.set_breakpoint(self.line)
++ target.LaunchSimple(None, None, os.getcwd())
++
++ self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
++ substrs = ['main.c:%d' % self.line,
++ 'stop reason = breakpoint'])
++
++ self.runCmd("next")
++ stop_reason = self.check_stop_reason()
++
++ # lldb should be able to read from registers from the inferior after asserting.
++ if "x86_64" in self.getArchitecture():
++ self.expect("register read rbp", substrs = ['rbp = 0x'])
++ if "i386" in self.getArchitecture():
++ self.expect("register read ebp", substrs = ['ebp = 0x'])
++
++ process = target.GetProcess()
++ self.assertTrue(process.IsValid(), "current process is valid")
++
++ thread = process.GetThreadAtIndex(0)
++ self.assertTrue(thread.IsValid(), "current thread is valid")
++
++ # The lldb expression interpreter should be able to read from addresses of the inferior after a call to assert().
++ self.assertTrue(self.check_expr_in_main(thread), "cannot find 'main' in the backtrace")
++
++ # And it should report the correct line number.
++ self.expect("thread backtrace all",
++ substrs = [stop_reason,
++ 'main.c:%d' % self.line])
++
++if __name__ == '__main__':
++ import atexit
++ lldb.SBDebugger.Initialize()
++ atexit.register(lambda: lldb.SBDebugger.Terminate())
++ unittest2.main()
+Index: test/functionalities/inferior-assert/Makefile
+===================================================================
+--- test/functionalities/inferior-assert/Makefile (revision 0)
++++ test/functionalities/inferior-assert/Makefile (revision 0)
+@@ -0,0 +1,5 @@
++LEVEL = ../../make
++
++C_SOURCES := main.c
++
++include $(LEVEL)/Makefile.rules
+Index: test/functionalities/watchpoint/hello_watchlocation/TestWatchLocation.py
+===================================================================
+--- test/functionalities/watchpoint/hello_watchlocation/TestWatchLocation.py (revision 183906)
++++ test/functionalities/watchpoint/hello_watchlocation/TestWatchLocation.py (working copy)
+@@ -21,7 +21,6 @@
+ self.setTearDownCleanup(dictionary=self.d)
+ self.hello_watchlocation()
+
+- @expectedFailureLinux # llvm.org/pr14416
+ @dwarf_test
+ def test_hello_watchlocation_with_dwarf(self):
+ """Test watching a location with '-x size' option."""
+Index: test/functionalities/watchpoint/multiple_threads/TestWatchpointMultipleThreads.py
+===================================================================
+--- test/functionalities/watchpoint/multiple_threads/TestWatchpointMultipleThreads.py (revision 183906)
++++ test/functionalities/watchpoint/multiple_threads/TestWatchpointMultipleThreads.py (working copy)
+@@ -21,7 +21,7 @@
+ self.setTearDownCleanup(dictionary=self.d)
+ self.hello_multiple_threads()
+
+- @skipIfLinux # llvm.org/pr14323 - skip due to incomplete multi-threaded debug support
++ @skipIfGcc # causes intermittent gcc debian buildbot failures, skip until we can investigate
+ @dwarf_test
+ def test_watchpoint_multiple_threads_with_dwarf(self):
+ """Test that lldb watchpoint works for multiple threads."""
+@@ -37,7 +37,7 @@
+ self.setTearDownCleanup(dictionary=self.d)
+ self.hello_multiple_threads_wp_set_and_then_delete()
+
+- @skipIfLinux # llvm.org/pr14323 - skip due to incomplete multi-threaded debug support
++ @skipIfGcc # causes intermittent gcc debian buildbot failures, skip until we can investigate
+ @dwarf_test
+ def test_watchpoint_multiple_threads_wp_set_and_then_delete_with_dwarf(self):
+ """Test that lldb watchpoint works for multiple threads, and after the watchpoint is deleted, the watchpoint event should no longer fires."""
+Index: test/functionalities/watchpoint/watchpoint_set_command/TestWatchLocationWithWatchSet.py
+===================================================================
+--- test/functionalities/watchpoint/watchpoint_set_command/TestWatchLocationWithWatchSet.py (revision 183906)
++++ test/functionalities/watchpoint/watchpoint_set_command/TestWatchLocationWithWatchSet.py (working copy)
+@@ -20,7 +20,6 @@
+ self.setTearDownCleanup(dictionary=self.d)
+ self.watchlocation_using_watchpoint_set()
+
+- @expectedFailureLinux # llvm.org/pr14416
+ @dwarf_test
+ def test_watchlocation_with_dwarf_using_watchpoint_set(self):
+ """Test watching a location with 'watchpoint set expression -w write -x size' option."""
+Index: test/functionalities/register/TestRegisters.py
+===================================================================
+--- test/functionalities/register/TestRegisters.py (revision 183906)
++++ test/functionalities/register/TestRegisters.py (working copy)
+@@ -55,7 +55,6 @@
+
+ def common_setup(self):
+ exe = os.path.join(os.getcwd(), "a.out")
+- self.log_file = exe + ".log"
+
+ self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
+
+@@ -77,10 +76,11 @@
+ self.platform = "linux"
+
+ if self.platform != "":
+- self.runCmd("log enable " + self.platform + " " + str(category) + " registers -v -f " + self.log_file, RUN_SUCCEEDED)
++ log_file = os.path.join(os.getcwd(), 'TestRegisters.log')
++ self.runCmd("log enable " + self.platform + " " + str(category) + " registers -v -f " + log_file, RUN_SUCCEEDED)
+ if not self.has_teardown:
+ self.has_teardown = True
+- self.addTearDownHook(lambda: os.remove(self.log_file))
++ self.addTearDownHook(lambda: os.remove(log_file))
+
+ def register_commands(self):
+ """Test commands related to registers, in particular vector registers."""
+Index: test/functionalities/platform/TestPlatformCommand.py
+===================================================================
+--- test/functionalities/platform/TestPlatformCommand.py (revision 183906)
++++ test/functionalities/platform/TestPlatformCommand.py (working copy)
+@@ -27,7 +27,6 @@
+ self.expect("platform process info", error=True,
+ substrs = ['one or more process id(s) must be specified'])
+
+- @expectedFailureLinux # due to llvm.org/pr14806 -- "platform status" prints more information on Mac OS X than on Linux
+ def test_status(self):
+ self.expect("platform status",
+ substrs = ['Platform', 'Triple', 'OS Version', 'Kernel', 'Hostname'])
+Index: test/functionalities/command_script/import/TestImport.py
+===================================================================
+--- test/functionalities/command_script/import/TestImport.py (revision 183906)
++++ test/functionalities/command_script/import/TestImport.py (working copy)
+@@ -45,17 +45,15 @@
+ error=True, startstr='error: module importing failed')
+ self.expect("command script import ./nosuchfolder/",
+ error=True, startstr='error: module importing failed')
+- self.expect("command script import ./foo/foo.py",
+- error=True, startstr='error: module importing failed')
++ self.expect("command script import ./foo/foo.py", error=False)
+
+ self.runCmd("command script import --allow-reload ./thepackage")
+ self.expect("TPcommandA",substrs=["hello world A"])
+ self.expect("TPcommandB",substrs=["hello world B"])
+
+ self.runCmd("script import dummymodule")
+- self.expect("command script import ./dummymodule.py",
+- error=True, startstr='error: module importing failed')
+- self.runCmd("command script import --allow-reload ./dummymodule.py")
++ self.expect("command script import ./dummymodule.py", error=False)
++ self.expect("command script import --allow-reload ./dummymodule.py", error=False)
+
+ self.runCmd("command script add -f foo.foo_function foocmd")
+ self.runCmd("command script add -f foobar.foo_function foobarcmd")
+Index: test/functionalities/thread/create_during_step/TestCreateDuringStep.py
+===================================================================
+--- test/functionalities/thread/create_during_step/TestCreateDuringStep.py (revision 0)
++++ test/functionalities/thread/create_during_step/TestCreateDuringStep.py (revision 0)
+@@ -0,0 +1,155 @@
++"""
++Test number of threads.
++"""
++
++import os, time
++import unittest2
++import lldb
++from lldbtest import *
++import lldbutil
++
++class CreateDuringStepTestCase(TestBase):
++
++ mydir = os.path.join("functionalities", "thread", "create_during_step")
++
++ @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
++ @expectedFailureDarwin("llvm.org/pr15824") # thread states not properly maintained
++ @dsym_test
++ def test_step_inst_with_dsym(self):
++ """Test thread creation during step-inst handling."""
++ self.buildDsym(dictionary=self.getBuildFlags())
++ self.create_during_step_inst_test()
++
++ @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
++ @expectedFailureDarwin("llvm.org/pr15824") # thread states not properly maintained
++ @dsym_test
++ def test_step_over_with_dsym(self):
++ """Test thread creation during step-over handling."""
++ self.buildDsym(dictionary=self.getBuildFlags())
++ self.create_during_step_over_test()
++
++ @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
++ @expectedFailureDarwin("llvm.org/pr15824") # thread states not properly maintained
++ @dsym_test
++ def test_step_in_with_dsym(self):
++ """Test thread creation during step-in handling."""
++ self.buildDsym(dictionary=self.getBuildFlags())
++ self.create_during_step_in_test()
++
++ @expectedFailureDarwin("llvm.org/pr15824") # thread states not properly maintained
++ @dwarf_test
++ def test_step_inst_with_dwarf(self):
++ """Test thread creation during step-inst handling."""
++ self.buildDwarf(dictionary=self.getBuildFlags())
++ self.create_during_step_inst_test()
++
++ @expectedFailureDarwin("llvm.org/pr15824") # thread states not properly maintained
++ @dwarf_test
++ def test_step_over_with_dwarf(self):
++ """Test thread creation during step-over handling."""
++ self.buildDwarf(dictionary=self.getBuildFlags())
++ self.create_during_step_over_test()
++
++ @expectedFailureDarwin("llvm.org/pr15824") # thread states not properly maintained
++ @dwarf_test
++ def test_step_in_with_dwarf(self):
++ """Test thread creation during step-in handling."""
++ self.buildDwarf(dictionary=self.getBuildFlags())
++ self.create_during_step_in_test()
++
++ def setUp(self):
++ # Call super's setUp().
++ TestBase.setUp(self)
++ # Find the line numbers to break and continue.
++ self.breakpoint = line_number('main.cpp', '// Set breakpoint here')
++ self.continuepoint = line_number('main.cpp', '// Continue from here')
++
++ def create_during_step_inst_test(self):
++ """Test thread creation while using step-inst."""
++ self.create_during_step_base("thread step-inst -m all-threads", 'stop reason = instruction step')
++
++ def create_during_step_over_test(self):
++ """Test thread creation while using step-over."""
++ self.create_during_step_base("thread step-over -m all-threads", 'stop reason = step over')
++
++ def create_during_step_in_test(self):
++ """Test thread creation while using step-in."""
++ self.create_during_step_base("thread step-in -m all-threads", 'stop reason = step in')
++
++ def create_during_step_base(self, step_cmd, step_stop_reason):
++ """Test thread creation while using step-in."""
++ exe = os.path.join(os.getcwd(), "a.out")
++ self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
++
++ # This should create a breakpoint in the stepping thread.
++ lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.breakpoint, num_expected_locations=1)
++
++ # The breakpoint list should show 1 location.
++ self.expect("breakpoint list -f", "Breakpoint location shown correctly",
++ substrs = ["1: file ='main.cpp', line = %d, locations = 1" % self.breakpoint])
++
++ # Run the program.
++ self.runCmd("run", RUN_SUCCEEDED)
++
++ # The stop reason of the thread should be breakpoint.
++ self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
++ substrs = ['stopped',
++ 'stop reason = breakpoint'])
++
++ # Get the target process
++ target = self.dbg.GetSelectedTarget()
++ process = target.GetProcess()
++
++ # Get the number of threads
++ num_threads = process.GetNumThreads()
++
++ # Make sure we see only two threads
++ self.assertTrue(num_threads == 2, 'Number of expected threads and actual threads do not match.')
++
++ # Get the thread objects
++ thread1 = process.GetThreadAtIndex(0)
++ thread2 = process.GetThreadAtIndex(1)
++
++ # Make sure both threads are stopped
++ self.assertTrue(thread1.IsStopped(), "Thread 1 didn't stop during breakpoint")
++ self.assertTrue(thread2.IsStopped(), "Thread 2 didn't stop during breakpoint")
++
++ # Keep stepping until we've reached our designated continue point
++ stepping_thread = process.GetSelectedThread()
++ current_line = self.breakpoint
++ while current_line != self.continuepoint:
++ self.runCmd(step_cmd)
++
++ # The thread creation may change the selected thread.
++ # If it does, we just change it back here.
++ if stepping_thread != process.GetSelectedThread():
++ process.SetSelectedThread(stepping_thread)
++
++ frame = stepping_thread.GetFrameAtIndex(0)
++ current_line = frame.GetLineEntry().GetLine()
++
++ # Make sure we're still where we thought we were
++ self.assertTrue(current_line >= self.breakpoint, "Stepped to unexpected line, " + str(current_line))
++ self.assertTrue(current_line <= self.continuepoint, "Stepped to unexpected line, " + str(current_line))
++
++ # Update the number of threads
++ num_threads = process.GetNumThreads()
++
++ # Check to see that we increased the number of threads as expected
++ self.assertTrue(num_threads == 3, 'Number of expected threads and actual threads do not match after thread exit.')
++
++ self.expect("thread list", 'Process state is stopped due to step',
++ substrs = ['stopped',
++ step_stop_reason])
++
++ # Run to completion
++ self.runCmd("process continue")
++
++ # At this point, the inferior process should have exited.
++ self.assertTrue(process.GetState() == lldb.eStateExited, PROCESS_EXITED)
++
++if __name__ == '__main__':
++ import atexit
++ lldb.SBDebugger.Initialize()
++ atexit.register(lambda: lldb.SBDebugger.Terminate())
++ unittest2.main()
+Index: test/functionalities/thread/create_during_step/main.cpp
+===================================================================
+--- test/functionalities/thread/create_during_step/main.cpp (revision 0)
++++ test/functionalities/thread/create_during_step/main.cpp (revision 0)
+@@ -0,0 +1,92 @@
++//===-- main.cpp ------------------------------------------------*- C++ -*-===//
++//
++// The LLVM Compiler Infrastructure
++//
++// This file is distributed under the University of Illinois Open Source
++// License. See LICENSE.TXT for details.
++//
++//===----------------------------------------------------------------------===//
++
++// This test is intended to create a situation in which one thread will be
++// created while a the debugger is stepping in another thread.
++
++#include <pthread.h>
++#include <atomic>
++
++// Note that although hogging the CPU while waiting for a variable to change
++// would be terrible in production code, it's great for testing since it
++// avoids a lot of messy context switching to get multiple threads synchronized.
++#define do_nothing()
++
++#define pseudo_barrier_wait(bar) \
++ --bar; \
++ while (bar > 0) \
++ do_nothing();
++
++#define pseudo_barrier_init(bar, count) (bar = count)
++
++std::atomic_int g_barrier;
++
++volatile int g_thread_created = 0;
++volatile int g_test = 0;
++
++void *
++step_thread_func (void *input)
++{
++ g_test = 0; // Set breakpoint here
++
++ while (!g_thread_created)
++ g_test++;
++
++ // One more time to provide a continue point
++ g_test++; // Continue from here
++
++ // Return
++ return NULL;
++}
++
++void *
++create_thread_func (void *input)
++{
++ pthread_t *step_thread = (pthread_t*)input;
++
++ // Wait until the main thread knows this thread is started.
++ pseudo_barrier_wait(g_barrier);
++
++ // Wait until the other thread is done.
++ pthread_join(*step_thread, NULL);
++
++ // Return
++ return NULL;
++}
++
++int main ()
++{
++ pthread_t thread_1;
++ pthread_t thread_2;
++
++ // Use a simple count to simulate a barrier.
++ pseudo_barrier_init(g_barrier, 2);
++
++ // Create a thread to hit the breakpoint.
++ pthread_create (&thread_1, NULL, step_thread_func, NULL);
++
++ // Wait until the step thread is stepping
++ while (g_test < 1)
++ do_nothing();
++
++ // Create a thread to exit while we're stepping.
++ pthread_create (&thread_2, NULL, create_thread_func, &thread_1);
++
++ // Wait until that thread is started
++ pseudo_barrier_wait(g_barrier);
++
++ // Let the stepping thread know the other thread is there
++ g_thread_created = 1;
++
++ // Wait for the threads to finish.
++ pthread_join(thread_2, NULL);
++ pthread_join(thread_1, NULL);
++
++ return 0;
++}
+Index: test/functionalities/thread/create_during_step/Makefile
+===================================================================
+--- test/functionalities/thread/create_during_step/Makefile (revision 0)
++++ test/functionalities/thread/create_during_step/Makefile (revision 0)
+@@ -0,0 +1,4 @@
++LEVEL = ../../../make
++
++CXX_SOURCES := main.cpp
++include $(LEVEL)/Makefile.rules
+Index: test/functionalities/thread/create_after_attach/Makefile
+===================================================================
+--- test/functionalities/thread/create_after_attach/Makefile (revision 0)
++++ test/functionalities/thread/create_after_attach/Makefile (revision 0)
+@@ -0,0 +1,4 @@
++LEVEL = ../../../make
++
++C_SOURCES := main.c
++include $(LEVEL)/Makefile.rules
+Index: test/functionalities/thread/create_after_attach/TestCreateAfterAttach.py
+===================================================================
+--- test/functionalities/thread/create_after_attach/TestCreateAfterAttach.py (revision 0)
++++ test/functionalities/thread/create_after_attach/TestCreateAfterAttach.py (revision 0)
+@@ -0,0 +1,124 @@
++"""
++Test thread creation after process attach.
++"""
++
++import os, time
++import unittest2
++import lldb
++from lldbtest import *
++import lldbutil
++
++class CreateAfterAttachTestCase(TestBase):
++
++ mydir = os.path.join("functionalities", "thread", "create_after_attach")
++
++ @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
++ @dsym_test
++ def test_create_after_attach_with_dsym(self):
++ """Test thread creation after process attach."""
++ self.buildDsym(dictionary=self.getBuildFlags(use_cpp11=False))
++ self.create_after_attach(use_fork=False)
++
++ @skipIfLinux # Hangs, see llvm.org/pr16229
++ @dwarf_test
++ def test_create_after_attach_with_dwarf_and_popen(self):
++ """Test thread creation after process attach."""
++ self.buildDwarf(dictionary=self.getBuildFlags(use_cpp11=False))
++ self.create_after_attach(use_fork=False)
++
++ @dwarf_test
++ def test_create_after_attach_with_dwarf_and_fork(self):
++ """Test thread creation after process attach."""
++ self.buildDwarf(dictionary=self.getBuildFlags(use_cpp11=False))
++ self.create_after_attach(use_fork=True)
++
++ def setUp(self):
++ # Call super's setUp().
++ TestBase.setUp(self)
++ # Find the line numbers for our breakpoints.
++ self.break_1 = line_number('main.c', '// Set first breakpoint here')
++ self.break_2 = line_number('main.c', '// Set second breakpoint here')
++ self.break_3 = line_number('main.c', '// Set third breakpoint here')
++
++ def create_after_attach(self, use_fork):
++ """Test thread creation after process attach."""
++
++ exe = os.path.join(os.getcwd(), "a.out")
++
++ # Spawn a new process
++ if use_fork:
++ pid = self.forkSubprocess(exe)
++ else:
++ popen = self.spawnSubprocess(exe)
++ pid = popen.pid
++ self.addTearDownHook(self.cleanupSubprocesses)
++
++ # Attach to the spawned process
++ self.runCmd("process attach -p " + str(pid))
++
++ target = self.dbg.GetSelectedTarget()
++
++ process = target.GetProcess()
++ self.assertTrue(process, PROCESS_IS_VALID)
++
++ # This should create a breakpoint in the main thread.
++ lldbutil.run_break_set_by_file_and_line (self, "main.c", self.break_1, num_expected_locations=1)
++
++ # This should create a breakpoint in the second child thread.
++ lldbutil.run_break_set_by_file_and_line (self, "main.c", self.break_2, num_expected_locations=1)
++
++ # This should create a breakpoint in the first child thread.
++ lldbutil.run_break_set_by_file_and_line (self, "main.c", self.break_3, num_expected_locations=1)
++
++ # Run to the first breakpoint
++ self.runCmd("continue")
++
++ # The stop reason of the thread should be breakpoint.
++ self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
++ substrs = ['stopped',
++ '* thread #1',
++ 'stop reason = breakpoint',
++ 'thread #2'])
++
++ # Change a variable to escape the loop
++ self.runCmd("expression main_thread_continue = 1")
++
++ # Run to the second breakpoint
++ self.runCmd("continue")
++ self.runCmd("thread select 3")
++
++ # The stop reason of the thread should be breakpoint.
++ self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
++ substrs = ['stopped',
++ 'thread #1',
++ 'thread #2',
++ '* thread #3',
++ 'stop reason = breakpoint'])
++
++ # Change a variable to escape the loop
++ self.runCmd("expression child_thread_continue = 1")
++
++ # Run to the third breakpoint
++ self.runCmd("continue")
++ self.runCmd("thread select 2")
++
++ # The stop reason of the thread should be breakpoint.
++ # Thread 3 may or may not have already exited.
++ self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
++ substrs = ['stopped',
++ 'thread #1',
++ '* thread #2',
++ 'stop reason = breakpoint'])
++
++ # Run to completion
++ self.runCmd("continue")
++
++ # At this point, the inferior process should have exited.
++ self.assertTrue(process.GetState() == lldb.eStateExited, PROCESS_EXITED)
++
++
++if __name__ == '__main__':
++ import atexit
++ lldb.SBDebugger.Initialize()
++ atexit.register(lambda: lldb.SBDebugger.Terminate())
++ unittest2.main()
+Index: test/functionalities/thread/create_after_attach/main.c
+===================================================================
+--- test/functionalities/thread/create_after_attach/main.c (revision 0)
++++ test/functionalities/thread/create_after_attach/main.c (revision 0)
+@@ -0,0 +1,60 @@
++#include <stdio.h>
++#include <unistd.h>
++#include <pthread.h>
++
++volatile int g_thread_2_continuing = 0;
++
++void *
++thread_1_func (void *input)
++{
++ // Waiting to be released by the debugger.
++ while (!g_thread_2_continuing) // The debugger will change this value
++ {
++ usleep(1);
++ }
++
++ // Return
++ return NULL; // Set third breakpoint here
++}
++
++void *
++thread_2_func (void *input)
++{
++ // Waiting to be released by the debugger.
++ int child_thread_continue = 0;
++ while (!child_thread_continue) // The debugger will change this value
++ {
++ usleep(1); // Set second breakpoint here
++ }
++
++ // Release thread 1
++ g_thread_2_continuing = 1;
++
++ // Return
++ return NULL;
++}
++
++int main(int argc, char const *argv[])
++{
++ pthread_t thread_1;
++ pthread_t thread_2;
++
++ // Create a new thread
++ pthread_create (&thread_1, NULL, thread_1_func, NULL);
++
++ // Waiting to be attached by the debugger.
++ int main_thread_continue = 0;
++ while (!main_thread_continue) // The debugger will change this value
++ {
++ usleep(1); // Set first breakpoint here
++ }
++
++ // Create another new thread
++ pthread_create (&thread_2, NULL, thread_2_func, NULL);
++
++ // Wait for the threads to finish.
++ pthread_join(thread_1, NULL);
++ pthread_join(thread_2, NULL);
++
++ printf("Exiting now\n");
++}
+Index: test/functionalities/thread/exit_during_step/main.cpp
+===================================================================
+--- test/functionalities/thread/exit_during_step/main.cpp (revision 0)
++++ test/functionalities/thread/exit_during_step/main.cpp (revision 0)
+@@ -0,0 +1,91 @@
++//===-- main.cpp ------------------------------------------------*- C++ -*-===//
++//
++// The LLVM Compiler Infrastructure
++//
++// This file is distributed under the University of Illinois Open Source
++// License. See LICENSE.TXT for details.
++//
++//===----------------------------------------------------------------------===//
++
++// This test is intended to create a situation in which one thread will exit
++// while a the debugger is stepping in another thread.
++
++#include <pthread.h>
++#include <unistd.h>
++
++// Note that although hogging the CPU while waiting for a variable to change
++// would be terrible in production code, it's great for testing since it
++// avoids a lot of messy context switching to get multiple threads synchronized.
++#define do_nothing()
++
++#define pseudo_barrier_wait(bar) \
++ --bar; \
++ while (bar > 0) \
++ do_nothing();
++
++#define pseudo_barrier_init(bar, count) (bar = count)
++
++// A barrier to synchronize thread start.
++volatile int g_barrier;
++
++volatile int g_thread_exited = 0;
++
++volatile int g_test = 0;
++
++void *
++step_thread_func (void *input)
++{
++ // Wait until both threads are started.
++ pseudo_barrier_wait(g_barrier);
++
++ g_test = 0; // Set breakpoint here
++
++ while (!g_thread_exited)
++ g_test++;
++
++ // One more time to provide a continue point
++ g_test++; // Continue from here
++
++ // Return
++ return NULL;
++}
++
++void *
++exit_thread_func (void *input)
++{
++ // Wait until both threads are started.
++ pseudo_barrier_wait(g_barrier);
++
++ // Wait until the other thread is stepping.
++ while (g_test == 0)
++ do_nothing();
++
++ // Return
++ return NULL;
++}
++
++int main ()
++{
++ pthread_t thread_1;
++ pthread_t thread_2;
++
++ // Synchronize thread start so that doesn't happen during stepping.
++ pseudo_barrier_init(g_barrier, 2);
++
++ // Create a thread to hit the breakpoint.
++ pthread_create (&thread_1, NULL, step_thread_func, NULL);
++
++ // Create a thread to exit while we're stepping.
++ pthread_create (&thread_2, NULL, exit_thread_func, NULL);
++
++ // Wait for the exit thread to finish.
++ pthread_join(thread_2, NULL);
++
++ // Let the stepping thread know the other thread is gone.
++ g_thread_exited = 1;
++
++ // Wait for the stepping thread to finish.
++ pthread_join(thread_1, NULL);
++
++ return 0;
++}
+Index: test/functionalities/thread/exit_during_step/TestExitDuringStep.py
+===================================================================
+--- test/functionalities/thread/exit_during_step/TestExitDuringStep.py (revision 0)
++++ test/functionalities/thread/exit_during_step/TestExitDuringStep.py (revision 0)
+@@ -0,0 +1,159 @@
++"""
++Test number of threads.
++"""
++
++import os, time
++import unittest2
++import lldb
++from lldbtest import *
++import lldbutil
++
++class ExitDuringStepTestCase(TestBase):
++
++ mydir = os.path.join("functionalities", "thread", "exit_during_step")
++
++ @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
++ @expectedFailureDarwin("llvm.org/pr15824") # thread states not properly maintained
++ @dsym_test
++ def test_with_dsym(self):
++ """Test thread exit during step handling."""
++ self.buildDsym(dictionary=self.getBuildFlags())
++ self.exit_during_step_inst_test()
++
++ @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
++ @expectedFailureDarwin("llvm.org/pr15824") # thread states not properly maintained
++ @dsym_test
++ def test_step_over_with_dsym(self):
++ """Test thread exit during step-over handling."""
++ self.buildDsym(dictionary=self.getBuildFlags())
++ self.exit_during_step_over_test()
++
++ @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
++ @expectedFailureDarwin("llvm.org/pr15824") # thread states not properly maintained
++ @dsym_test
++ def test_step_in_with_dsym(self):
++ """Test thread exit during step-in handling."""
++ self.buildDsym(dictionary=self.getBuildFlags())
++ self.exit_during_step_in_test()
++
++ @expectedFailureDarwin("llvm.org/pr15824") # thread states not properly maintained
++ @dwarf_test
++ def test_with_dwarf(self):
++ """Test thread exit during step handling."""
++ self.buildDwarf(dictionary=self.getBuildFlags())
++ self.exit_during_step_inst_test()
++
++ @expectedFailureDarwin("llvm.org/pr15824") # thread states not properly maintained
++ @dwarf_test
++ def test_step_over_with_dwarf(self):
++ """Test thread exit during step-over handling."""
++ self.buildDwarf(dictionary=self.getBuildFlags())
++ self.exit_during_step_over_test()
++
++ @expectedFailureDarwin("llvm.org/pr15824") # thread states not properly maintained
++ @dwarf_test
++ def test_step_in_with_dwarf(self):
++ """Test thread exit during step-in handling."""
++ self.buildDwarf(dictionary=self.getBuildFlags())
++ self.exit_during_step_in_test()
++
++ def setUp(self):
++ # Call super's setUp().
++ TestBase.setUp(self)
++ # Find the line numbers to break and continue.
++ self.breakpoint = line_number('main.cpp', '// Set breakpoint here')
++ self.continuepoint = line_number('main.cpp', '// Continue from here')
++
++ def exit_during_step_inst_test(self):
++ """Test thread exit while using step-inst."""
++ self.exit_during_step_base("thread step-inst -m all-threads", 'stop reason = instruction step')
++
++ def exit_during_step_over_test(self):
++ """Test thread exit while using step-over."""
++ self.exit_during_step_base("thread step-over -m all-threads", 'stop reason = step over')
++
++ def exit_during_step_in_test(self):
++ """Test thread exit while using step-in."""
++ self.exit_during_step_base("thread step-in -m all-threads", 'stop reason = step in')
++
++ def exit_during_step_base(self, step_cmd, step_stop_reason):
++ """Test thread exit during step handling."""
++ exe = os.path.join(os.getcwd(), "a.out")
++ self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
++
++ # This should create a breakpoint in the main thread.
++ lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.breakpoint, num_expected_locations=1)
++
++ # The breakpoint list should show 1 location.
++ self.expect("breakpoint list -f", "Breakpoint location shown correctly",
++ substrs = ["1: file ='main.cpp', line = %d, locations = 1" % self.breakpoint])
++
++ # Run the program.
++ self.runCmd("run", RUN_SUCCEEDED)
++
++ # The stop reason of the thread should be breakpoint.
++ self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
++ substrs = ['stopped',
++ 'stop reason = breakpoint'])
++
++ # Get the target process
++ target = self.dbg.GetSelectedTarget()
++ process = target.GetProcess()
++
++ # Get the number of threads
++ num_threads = process.GetNumThreads()
++
++ # Make sure we see all three threads
++ self.assertTrue(num_threads == 3, 'Number of expected threads and actual threads do not match.')
++
++ # Get the thread objects
++ thread1 = process.GetThreadAtIndex(0)
++ thread2 = process.GetThreadAtIndex(1)
++ thread3 = process.GetThreadAtIndex(2)
++
++ # Make sure all threads are stopped
++ self.assertTrue(thread1.IsStopped(), "Thread 1 didn't stop during breakpoint")
++ self.assertTrue(thread2.IsStopped(), "Thread 2 didn't stop during breakpoint")
++ self.assertTrue(thread3.IsStopped(), "Thread 3 didn't stop during breakpoint")
++
++ # Keep stepping until we've reached our designated continue point
++ stepping_thread = process.GetSelectedThread()
++ current_line = self.breakpoint
++ stepping_frame = stepping_thread.GetFrameAtIndex(0)
++ self.assertTrue(current_line == stepping_frame.GetLineEntry().GetLine(), "Starting line for stepping doesn't match breakpoint line.")
++ while current_line != self.continuepoint:
++ self.runCmd(step_cmd)
++
++ if stepping_thread != process.GetSelectedThread():
++ process.SetSelectedThread(stepping_thread)
++
++ frame = stepping_thread.GetFrameAtIndex(0)
++
++ current_line = frame.GetLineEntry().GetLine()
++
++ self.assertTrue(current_line >= self.breakpoint, "Stepped to unexpected line, " + str(current_line))
++ self.assertTrue(current_line <= self.continuepoint, "Stepped to unexpected line, " + str(current_line))
++
++ self.runCmd("thread list")
++
++ # Update the number of threads
++ num_threads = process.GetNumThreads()
++
++ # Check to see that we reduced the number of threads as expected
++ self.assertTrue(num_threads == 2, 'Number of expected threads and actual threads do not match after thread exit.')
++
++ self.expect("thread list", 'Process state is stopped due to step',
++ substrs = ['stopped',
++ step_stop_reason])
++
++ # Run to completion
++ self.runCmd("continue")
++
++ # At this point, the inferior process should have exited.
++ self.assertTrue(process.GetState() == lldb.eStateExited, PROCESS_EXITED)
++
++if __name__ == '__main__':
++ import atexit
++ lldb.SBDebugger.Initialize()
++ atexit.register(lambda: lldb.SBDebugger.Terminate())
++ unittest2.main()
+Index: test/functionalities/thread/exit_during_step/Makefile
+===================================================================
+--- test/functionalities/thread/exit_during_step/Makefile (revision 0)
++++ test/functionalities/thread/exit_during_step/Makefile (revision 0)
+@@ -0,0 +1,4 @@
++LEVEL = ../../../make
++
++CXX_SOURCES := main.cpp
++include $(LEVEL)/Makefile.rules
+Index: test/functionalities/thread/multi_break/TestMultipleBreakpoints.py
+===================================================================
+--- test/functionalities/thread/multi_break/TestMultipleBreakpoints.py (revision 0)
++++ test/functionalities/thread/multi_break/TestMultipleBreakpoints.py (revision 0)
+@@ -0,0 +1,90 @@
++"""
++Test number of threads.
++"""
++
++import os, time
++import unittest2
++import lldb
++from lldbtest import *
++import lldbutil
++
++class MultipleBreakpointTestCase(TestBase):
++
++ mydir = os.path.join("functionalities", "thread", "multi_break")
++
++ @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
++ @expectedFailureDarwin("llvm.org/pr15824") # thread states not properly maintained
++ @dsym_test
++ def test_with_dsym(self):
++ """Test simultaneous breakpoints in multiple threads."""
++ self.buildDsym(dictionary=self.getBuildFlags())
++ self.multiple_breakpoint_test()
++
++ @expectedFailureDarwin("llvm.org/pr15824") # thread states not properly maintained
++ @dwarf_test
++ def test_with_dwarf(self):
++ """Test simultaneous breakpoints in multiple threads."""
++ self.buildDwarf(dictionary=self.getBuildFlags())
++ self.multiple_breakpoint_test()
++
++ def setUp(self):
++ # Call super's setUp().
++ TestBase.setUp(self)
++ # Find the line number for our breakpoint.
++ self.breakpoint = line_number('main.cpp', '// Set breakpoint here')
++
++ def multiple_breakpoint_test(self):
++ """Test simultaneous breakpoints in multiple threads."""
++ exe = os.path.join(os.getcwd(), "a.out")
++ self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
++
++ # This should create a breakpoint in the main thread.
++ lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.breakpoint, num_expected_locations=1)
++
++ # The breakpoint list should show 1 location.
++ self.expect("breakpoint list -f", "Breakpoint location shown correctly",
++ substrs = ["1: file ='main.cpp', line = %d, locations = 1" % self.breakpoint])
++
++ # Run the program.
++ self.runCmd("run", RUN_SUCCEEDED)
++
++ # The stop reason of the thread should be breakpoint.
++ # The breakpoint may be hit in either thread 2 or thread 3.
++ self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
++ substrs = ['stopped',
++ 'stop reason = breakpoint'])
++
++ # Get the target process
++ target = self.dbg.GetSelectedTarget()
++ process = target.GetProcess()
++
++ # Get the number of threads
++ num_threads = process.GetNumThreads()
++
++ # Make sure we see all three threads
++ self.assertTrue(num_threads == 3, 'Number of expected threads and actual threads do not match.')
++
++ # Get the thread objects
++ thread1 = process.GetThreadAtIndex(0)
++ thread2 = process.GetThreadAtIndex(1)
++ thread3 = process.GetThreadAtIndex(2)
++
++ # Make sure both threads are stopped
++ self.assertTrue(thread1.IsStopped(), "Primary thread didn't stop during breakpoint")
++ self.assertTrue(thread2.IsStopped(), "Secondary thread didn't stop during breakpoint")
++ self.assertTrue(thread3.IsStopped(), "Tertiary thread didn't stop during breakpoint")
++
++ # Delete the first breakpoint then continue
++ self.runCmd("breakpoint delete 1")
++
++ # Run to completion
++ self.runCmd("continue")
++
++ # At this point, the inferior process should have exited.
++ self.assertTrue(process.GetState() == lldb.eStateExited, PROCESS_EXITED)
++
++if __name__ == '__main__':
++ import atexit
++ lldb.SBDebugger.Initialize()
++ atexit.register(lambda: lldb.SBDebugger.Terminate())
++ unittest2.main()
+Index: test/functionalities/thread/multi_break/main.cpp
+===================================================================
+--- test/functionalities/thread/multi_break/main.cpp (revision 0)
++++ test/functionalities/thread/multi_break/main.cpp (revision 0)
+@@ -0,0 +1,64 @@
++//===-- main.cpp ------------------------------------------------*- C++ -*-===//
++//
++// The LLVM Compiler Infrastructure
++//
++// This file is distributed under the University of Illinois Open Source
++// License. See LICENSE.TXT for details.
++//
++//===----------------------------------------------------------------------===//
++
++// This test is intended to create a situation in which a breakpoint will be
++// hit in two threads at nearly the same moment. The expected result is that
++// the breakpoint in the second thread will be hit while the breakpoint handler
++// in the first thread is trying to stop all threads.
++
++#include <pthread.h>
++#include <atomic>
++
++// Note that although hogging the CPU while waiting for a variable to change
++// would be terrible in production code, it's great for testing since it
++// avoids a lot of messy context switching to get multiple threads synchronized.
++#define do_nothing()
++
++#define pseudo_barrier_wait(bar) \
++ --bar; \
++ while (bar > 0) \
++ do_nothing();
++
++#define pseudo_barrier_init(bar, count) (bar = count)
++
++std::atomic_int g_barrier;
++
++volatile int g_test = 0;
++
++void *
++thread_func (void *input)
++{
++ // Wait until both threads are running
++ pseudo_barrier_wait(g_barrier);
++
++ // Do something
++ g_test++; // Set breakpoint here
++
++ // Return
++ return NULL;
++}
++
++int main ()
++{
++ pthread_t thread_1;
++ pthread_t thread_2;
++
++ // Don't let either thread do anything until they're both ready.
++ pseudo_barrier_init(g_barrier, 2);
++
++ // Create two threads
++ pthread_create (&thread_1, NULL, thread_func, NULL);
++ pthread_create (&thread_2, NULL, thread_func, NULL);
++
++ // Wait for the threads to finish
++ pthread_join(thread_1, NULL);
++ pthread_join(thread_2, NULL);
++
++ return 0;
++}
+Index: test/functionalities/thread/multi_break/Makefile
+===================================================================
+--- test/functionalities/thread/multi_break/Makefile (revision 0)
++++ test/functionalities/thread/multi_break/Makefile (revision 0)
+@@ -0,0 +1,4 @@
++LEVEL = ../../../make
++
++CXX_SOURCES := main.cpp
++include $(LEVEL)/Makefile.rules
+Index: test/functionalities/thread/state/TestThreadStates.py
+===================================================================
+--- test/functionalities/thread/state/TestThreadStates.py (revision 183906)
++++ test/functionalities/thread/state/TestThreadStates.py (working copy)
+@@ -8,7 +8,7 @@
+ from lldbtest import *
+ import lldbutil
+
+-class StopThreadsTestCase(TestBase):
++class ThreadStateTestCase(TestBase):
+
+ mydir = os.path.join("functionalities", "thread", "state")
+
+@@ -16,54 +16,54 @@
+ @dsym_test
+ def test_state_after_breakpoint_with_dsym(self):
+ """Test thread state after breakpoint."""
+- self.buildDsym()
++ self.buildDsym(dictionary=self.getBuildFlags(use_cpp11=False))
+ self.thread_state_after_breakpoint_test()
+
+ @dwarf_test
+ def test_state_after_breakpoint_with_dwarf(self):
+ """Test thread state after breakpoint."""
+- self.buildDwarf()
++ self.buildDwarf(dictionary=self.getBuildFlags(use_cpp11=False))
+ self.thread_state_after_breakpoint_test()
+
+ @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
+ @dsym_test
+ def test_state_after_continue_with_dsym(self):
+ """Test thread state after continue."""
+- self.buildDsym()
++ self.buildDsym(dictionary=self.getBuildFlags(use_cpp11=False))
+ self.thread_state_after_continue_test()
+
+ @dwarf_test
+ def test_state_after_continue_with_dwarf(self):
+ """Test thread state after continue."""
+- self.buildDwarf()
++ self.buildDwarf(dictionary=self.getBuildFlags(use_cpp11=False))
+ self.thread_state_after_continue_test()
+
+ @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
+ @dsym_test
+ def test_state_after_expression_with_dsym(self):
+ """Test thread state after expression."""
+- self.buildDsym()
++ self.buildDsym(dictionary=self.getBuildFlags(use_cpp11=False))
+ self.thread_state_after_continue_test()
+
+ @dwarf_test
+ def test_state_after_expression_with_dwarf(self):
+ """Test thread state after expression."""
+- self.buildDwarf()
++ self.buildDwarf(dictionary=self.getBuildFlags(use_cpp11=False))
+ self.thread_state_after_continue_test()
+
+ @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
+ @dsym_test
+- @unittest2.expectedFailure("llvm.org/pr15824") # thread states not properly maintained
++ @unittest2.expectedFailure("llvm.org/pr16172") # thread states not properly maintained
+ def test_process_interrupt_with_dsym(self):
+ """Test process interrupt."""
+- self.buildDsym()
++ self.buildDsym(dictionary=self.getBuildFlags(use_cpp11=False))
+ self.process_interrupt_test()
+
+ @dwarf_test
+- @unittest2.expectedFailure("llvm.org/pr15824") # thread states not properly maintained
++ @unittest2.expectedFailure("llvm.org/pr16712") # thread states not properly maintained
+ def test_process_interrupt_with_dwarf(self):
+ """Test process interrupt."""
+- self.buildDwarf()
++ self.buildDwarf(dictionary=self.getBuildFlags(use_cpp11=False))
+ self.process_interrupt_test()
+
+ @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
+@@ -71,14 +71,14 @@
+ @unittest2.expectedFailure("llvm.org/pr15824") # thread states not properly maintained
+ def test_process_state_with_dsym(self):
+ """Test thread states (comprehensive)."""
+- self.buildDsym()
++ self.buildDsym(dictionary=self.getBuildFlags(use_cpp11=False))
+ self.thread_states_test()
+
+ @dwarf_test
+ @unittest2.expectedFailure("llvm.org/pr15824") # thread states not properly maintained
+ def test_process_state_with_dwarf(self):
+ """Test thread states (comprehensive)."""
+- self.buildDwarf()
++ self.buildDwarf(dictionary=self.getBuildFlags(use_cpp11=False))
+ self.thread_states_test()
+
+ def setUp(self):
+Index: test/functionalities/thread/state/Makefile
+===================================================================
+--- test/functionalities/thread/state/Makefile (revision 183906)
++++ test/functionalities/thread/state/Makefile (working copy)
+@@ -1,5 +1,4 @@
+ LEVEL = ../../../make
+
+ C_SOURCES := main.c
+-LD_EXTRAS := -lpthread
+ include $(LEVEL)/Makefile.rules
+Index: test/functionalities/thread/thread_exit/main.cpp
+===================================================================
+--- test/functionalities/thread/thread_exit/main.cpp (revision 0)
++++ test/functionalities/thread/thread_exit/main.cpp (revision 0)
+@@ -0,0 +1,89 @@
++//===-- main.cpp ------------------------------------------------*- C++ -*-===//
++//
++// The LLVM Compiler Infrastructure
++//
++// This file is distributed under the University of Illinois Open Source
++// License. See LICENSE.TXT for details.
++//
++//===----------------------------------------------------------------------===//
++
++// This test verifies the correct handling of child thread exits.
++
++#include <pthread.h>
++#include <atomic>
++
++// Note that although hogging the CPU while waiting for a variable to change
++// would be terrible in production code, it's great for testing since it
++// avoids a lot of messy context switching to get multiple threads synchronized.
++#define do_nothing()
++
++#define pseudo_barrier_wait(bar) \
++ --bar; \
++ while (bar > 0) \
++ do_nothing();
++
++#define pseudo_barrier_init(bar, count) (bar = count)
++
++std::atomic_int g_barrier1;
++std::atomic_int g_barrier2;
++std::atomic_int g_barrier3;
++
++void *
++thread1 (void *input)
++{
++ // Synchronize with the main thread.
++ pseudo_barrier_wait(g_barrier1);
++
++ // Synchronize with the main thread and thread2.
++ pseudo_barrier_wait(g_barrier2);
++
++ // Return
++ return NULL; // Set second breakpoint here
++}
++
++void *
++thread2 (void *input)
++{
++ // Synchronize with thread1 and the main thread.
++ pseudo_barrier_wait(g_barrier2);
++
++ // Synchronize with the main thread.
++ pseudo_barrier_wait(g_barrier3);
++
++ // Return
++ return NULL;
++}
++
++int main ()
++{
++ pthread_t thread_1;
++ pthread_t thread_2;
++ pthread_t thread_3;
++
++ pseudo_barrier_init(g_barrier1, 2);
++ pseudo_barrier_init(g_barrier2, 3);
++ pseudo_barrier_init(g_barrier3, 2);
++
++ // Create a thread.
++ pthread_create (&thread_1, NULL, thread1, NULL);
++
++ // Wait for thread1 to start.
++ pseudo_barrier_wait(g_barrier1);
++
++ // Create another thread.
++ pthread_create (&thread_2, NULL, thread2, NULL); // Set first breakpoint here
++
++ // Wait for thread2 to start.
++ pseudo_barrier_wait(g_barrier2);
++
++ // Wait for the first thread to finish
++ pthread_join(thread_1, NULL);
++
++ // Synchronize with the remaining thread
++ pseudo_barrier_wait(g_barrier3); // Set third breakpoint here
++
++ // Wait for the second thread to finish
++ pthread_join(thread_2, NULL);
++
++ return 0; // Set fourth breakpoint here
++}
+Index: test/functionalities/thread/thread_exit/TestThreadExit.py
+===================================================================
+--- test/functionalities/thread/thread_exit/TestThreadExit.py (revision 0)
++++ test/functionalities/thread/thread_exit/TestThreadExit.py (revision 0)
+@@ -0,0 +1,132 @@
++"""
++Test number of threads.
++"""
++
++import os, time
++import unittest2
++import lldb
++from lldbtest import *
++import lldbutil
++
++class ThreadExitTestCase(TestBase):
++
++ mydir = os.path.join("functionalities", "thread", "thread_exit")
++
++ @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
++ @expectedFailureDarwin("llvm.org/pr15824") # thread states not properly maintained
++ @dsym_test
++ def test_with_dsym(self):
++ """Test thread exit handling."""
++ self.buildDsym(dictionary=self.getBuildFlags())
++ self.thread_exit_test()
++
++ @expectedFailureDarwin("llvm.org/pr15824") # thread states not properly maintained
++ @dwarf_test
++ def test_with_dwarf(self):
++ """Test thread exit handling."""
++ self.buildDwarf(dictionary=self.getBuildFlags())
++ self.thread_exit_test()
++
++ def setUp(self):
++ # Call super's setUp().
++ TestBase.setUp(self)
++ # Find the line numbers for our breakpoints.
++ self.break_1 = line_number('main.cpp', '// Set first breakpoint here')
++ self.break_2 = line_number('main.cpp', '// Set second breakpoint here')
++ self.break_3 = line_number('main.cpp', '// Set third breakpoint here')
++ self.break_4 = line_number('main.cpp', '// Set fourth breakpoint here')
++
++ def thread_exit_test(self):
++ """Test thread exit handling."""
++ exe = os.path.join(os.getcwd(), "a.out")
++ self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
++
++ # This should create a breakpoint with 1 location.
++ lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.break_1, num_expected_locations=1)
++ lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.break_2, num_expected_locations=1)
++ lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.break_3, num_expected_locations=1)
++ lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.break_4, num_expected_locations=1)
++
++ # The breakpoint list should show 1 locations.
++ self.expect("breakpoint list -f", "Breakpoint location shown correctly",
++ substrs = ["1: file ='main.cpp', line = %d, locations = 1" % self.break_1,
++ "2: file ='main.cpp', line = %d, locations = 1" % self.break_2,
++ "3: file ='main.cpp', line = %d, locations = 1" % self.break_3,
++ "4: file ='main.cpp', line = %d, locations = 1" % self.break_4])
++
++ # Run the program.
++ self.runCmd("run", RUN_SUCCEEDED)
++
++ # The stop reason of the thread should be breakpoint 1.
++ self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT + " 1",
++ substrs = ['stopped',
++ '* thread #1',
++ 'stop reason = breakpoint 1',
++ 'thread #2'])
++
++ # Get the target process
++ target = self.dbg.GetSelectedTarget()
++ process = target.GetProcess()
++
++ # Get the number of threads
++ num_threads = process.GetNumThreads()
++
++ self.assertTrue(num_threads == 2, 'Number of expected threads and actual threads do not match at breakpoint 1.')
++
++ # Run to the second breakpoint
++ self.runCmd("continue")
++
++ # The stop reason of the thread should be breakpoint 1.
++ self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT + " 2",
++ substrs = ['stopped',
++ 'thread #1',
++ '* thread #2',
++ 'stop reason = breakpoint 2',
++ 'thread #3'])
++
++ # Update the number of threads
++ num_threads = process.GetNumThreads()
++
++ self.assertTrue(num_threads == 3, 'Number of expected threads and actual threads do not match at breakpoint 2.')
++
++ # Run to the third breakpoint
++ self.runCmd("continue")
++
++ # The stop reason of the thread should be breakpoint 3.
++ self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT + " 3",
++ substrs = ['stopped',
++ '* thread #1',
++ 'stop reason = breakpoint 3',
++ 'thread #3',
++ ])
++
++ # Update the number of threads
++ num_threads = process.GetNumThreads()
++
++ self.assertTrue(num_threads == 2, 'Number of expected threads and actual threads do not match at breakpoint 3.')
++
++ # Run to the fourth breakpoint
++ self.runCmd("continue")
++
++ # The stop reason of the thread should be breakpoint 4.
++ self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT + " 4",
++ substrs = ['stopped',
++ '* thread #1',
++ 'stop reason = breakpoint 4'])
++
++ # Update the number of threads
++ num_threads = process.GetNumThreads()
++
++ self.assertTrue(num_threads == 1, 'Number of expected threads and actual threads do not match at breakpoint 4.')
++
++ # Run to completion
++ self.runCmd("continue")
++
++ # At this point, the inferior process should have exited.
++ self.assertTrue(process.GetState() == lldb.eStateExited, PROCESS_EXITED)
++
++if __name__ == '__main__':
++ import atexit
++ lldb.SBDebugger.Initialize()
++ atexit.register(lambda: lldb.SBDebugger.Terminate())
++ unittest2.main()
+Index: test/functionalities/thread/thread_exit/Makefile
+===================================================================
+--- test/functionalities/thread/thread_exit/Makefile (revision 0)
++++ test/functionalities/thread/thread_exit/Makefile (revision 0)
+@@ -0,0 +1,4 @@
++LEVEL = ../../../make
++
++CXX_SOURCES := main.cpp
++include $(LEVEL)/Makefile.rules
+Index: test/functionalities/thread/break_after_join/main.cpp
+===================================================================
+--- test/functionalities/thread/break_after_join/main.cpp (revision 0)
++++ test/functionalities/thread/break_after_join/main.cpp (revision 0)
+@@ -0,0 +1,125 @@
++//===-- main.cpp ------------------------------------------------*- C++ -*-===//
++//
++// The LLVM Compiler Infrastructure
++//
++// This file is distributed under the University of Illinois Open Source
++// License. See LICENSE.TXT for details.
++//
++//===----------------------------------------------------------------------===//
++
++// This test is intended to create a situation in which one thread will exit
++// while a breakpoint is being handled in another thread. This may not always
++// happen because it's possible that the exiting thread will exit before the
++// breakpoint is hit. The test case should be flexible enough to treat that
++// as success.
++
++#include <pthread.h>
++#include <unistd.h>
++#include <atomic>
++
++volatile int g_test = 0;
++
++// Note that although hogging the CPU while waiting for a variable to change
++// would be terrible in production code, it's great for testing since it
++// avoids a lot of messy context switching to get multiple threads synchronized.
++#define do_nothing()
++
++#define pseudo_barrier_wait(bar) \
++ --bar; \
++ while (bar > 0) \
++ do_nothing();
++
++#define pseudo_barrier_init(bar, count) (bar = count)
++
++// A barrier to synchronize all the threads.
++std::atomic_int g_barrier1;
++
++// A barrier to keep the threads from exiting until after the breakpoint has
++// been passed.
++std::atomic_int g_barrier2;
++
++void *
++break_thread_func (void *input)
++{
++ // Wait until all the threads are running
++ pseudo_barrier_wait(g_barrier1);
++
++ // Wait for the join thread to join
++ usleep(50);
++
++ // Do something
++ g_test++; // Set breakpoint here
++
++ // Synchronize after the breakpoint
++ pseudo_barrier_wait(g_barrier2);
++
++ // Return
++ return NULL;
++}
++
++void *
++wait_thread_func (void *input)
++{
++ // Wait until the entire first group of threads is running
++ pseudo_barrier_wait(g_barrier1);
++
++ // Wait until the breakpoint has been passed
++ pseudo_barrier_wait(g_barrier2);
++
++ // Return
++ return NULL;
++}
++
++void *
++join_thread_func (void *input)
++{
++ pthread_t *thread_to_join = (pthread_t*)input;
++
++ // Sync up with the rest of the threads.
++ pseudo_barrier_wait(g_barrier1);
++
++ // Join the other thread
++ pthread_join(*thread_to_join, NULL);
++
++ // Return
++ return NULL;
++}
++
++int main ()
++{
++ pthread_t thread_1;
++ pthread_t thread_2;
++ pthread_t thread_3;
++ pthread_t thread_4;
++ pthread_t thread_5;
++
++ // The first barrier waits for the non-joining threads to start.
++ // This thread will also participate in that barrier.
++ // The idea here is to guarantee that the joining thread will be
++ // last in the internal list maintained by the debugger.
++ pseudo_barrier_init(g_barrier1, 5);
++
++ // The second barrier keeps the waiting threads around until the breakpoint
++ // has been passed.
++ pseudo_barrier_init(g_barrier2, 4);
++
++ // Create a thread to hit the breakpoint
++ pthread_create (&thread_1, NULL, break_thread_func, NULL);
++
++ // Create more threads to slow the debugger down during processing.
++ pthread_create (&thread_2, NULL, wait_thread_func, NULL);
++ pthread_create (&thread_3, NULL, wait_thread_func, NULL);
++ pthread_create (&thread_4, NULL, wait_thread_func, NULL);
++
++ // Create a thread to join the breakpoint thread
++ pthread_create (&thread_5, NULL, join_thread_func, &thread_4);
++
++ // Wait for the threads to finish
++ pthread_join(thread_5, NULL);
++ pthread_join(thread_4, NULL);
++ pthread_join(thread_3, NULL);
++ pthread_join(thread_2, NULL);
++ pthread_join(thread_1, NULL);
++
++ return 0;
++}
+Index: test/functionalities/thread/break_after_join/TestBreakAfterJoin.py
+===================================================================
+--- test/functionalities/thread/break_after_join/TestBreakAfterJoin.py (revision 0)
++++ test/functionalities/thread/break_after_join/TestBreakAfterJoin.py (revision 0)
+@@ -0,0 +1,102 @@
++"""
++Test number of threads.
++"""
++
++import os, time
++import unittest2
++import lldb
++from lldbtest import *
++import lldbutil
++
++class BreakpointAfterJoinTestCase(TestBase):
++
++ mydir = os.path.join("functionalities", "thread", "break_after_join")
++
++ @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
++ @expectedFailureDarwin("llvm.org/pr15824") # thread states not properly maintained
++ @dsym_test
++ def test_with_dsym(self):
++ """Test breakpoint handling after a thread join."""
++ self.buildDsym(dictionary=self.getBuildFlags())
++ self.breakpoint_after_join_test()
++
++ @expectedFailureDarwin("llvm.org/pr15824") # thread states not properly maintained
++ @skipIfLinux # Causes hangs (llvm.org/pr16170) when run using "make check"
++ @dwarf_test
++ def test_with_dwarf(self):
++ """Test breakpoint handling after a thread join."""
++ self.buildDwarf(dictionary=self.getBuildFlags())
++ self.breakpoint_after_join_test()
++
++ def setUp(self):
++ # Call super's setUp().
++ TestBase.setUp(self)
++ # Find the line number for our breakpoint.
++ self.breakpoint = line_number('main.cpp', '// Set breakpoint here')
++
++ def breakpoint_after_join_test(self):
++ """Test breakpoint handling after a thread join."""
++ exe = os.path.join(os.getcwd(), "a.out")
++ self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
++
++ # This should create a breakpoint in the main thread.
++ lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.breakpoint, num_expected_locations=1)
++
++ # The breakpoint list should show 1 location.
++ self.expect("breakpoint list -f", "Breakpoint location shown correctly",
++ substrs = ["1: file ='main.cpp', line = %d, locations = 1" % self.breakpoint])
++
++ # Run the program.
++ self.runCmd("run", RUN_SUCCEEDED)
++
++ # The stop reason of the thread should be breakpoint.
++ self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
++ substrs = ['stopped',
++ 'stop reason = breakpoint'])
++
++ # Get the target process
++ target = self.dbg.GetSelectedTarget()
++ process = target.GetProcess()
++
++ # The exit probably occured during breakpoint handling, but it isn't
++ # guaranteed. The main thing we're testing here is that the debugger
++ # handles this cleanly is some way.
++
++ # Get the number of threads
++ num_threads = process.GetNumThreads()
++
++ # Make sure we see six threads
++ self.assertTrue(num_threads == 6, 'Number of expected threads and actual threads do not match.')
++
++ # Get the thread objects
++ thread1 = process.GetThreadAtIndex(0)
++ thread2 = process.GetThreadAtIndex(1)
++ thread3 = process.GetThreadAtIndex(2)
++ thread4 = process.GetThreadAtIndex(3)
++ thread5 = process.GetThreadAtIndex(4)
++ thread6 = process.GetThreadAtIndex(5)
++
++ # Make sure all threads are stopped
++ self.assertTrue(thread1.IsStopped(), "Thread 1 didn't stop during breakpoint")
++ self.assertTrue(thread2.IsStopped(), "Thread 2 didn't stop during breakpoint")
++ self.assertTrue(thread3.IsStopped(), "Thread 3 didn't stop during breakpoint")
++ self.assertTrue(thread4.IsStopped(), "Thread 4 didn't stop during breakpoint")
++ self.assertTrue(thread5.IsStopped(), "Thread 5 didn't stop during breakpoint")
++ self.assertTrue(thread6.IsStopped(), "Thread 6 didn't stop during breakpoint")
++
++ # Run to completion
++ self.runCmd("continue")
++
++ # If the process hasn't exited, collect some information
++ if process.GetState() != lldb.eStateExited:
++ self.runCmd("thread list")
++ self.runCmd("process status")
++
++ # At this point, the inferior process should have exited.
++ self.assertTrue(process.GetState() == lldb.eStateExited, PROCESS_EXITED)
++
++if __name__ == '__main__':
++ import atexit
++ lldb.SBDebugger.Initialize()
++ atexit.register(lambda: lldb.SBDebugger.Terminate())
++ unittest2.main()
+Index: test/functionalities/thread/break_after_join/Makefile
+===================================================================
+--- test/functionalities/thread/break_after_join/Makefile (revision 0)
++++ test/functionalities/thread/break_after_join/Makefile (revision 0)
+@@ -0,0 +1,4 @@
++LEVEL = ../../../make
++
++CXX_SOURCES := main.cpp
++include $(LEVEL)/Makefile.rules
+Index: test/functionalities/thread/exit_during_break/Makefile
+===================================================================
+--- test/functionalities/thread/exit_during_break/Makefile (revision 0)
++++ test/functionalities/thread/exit_during_break/Makefile (revision 0)
+@@ -0,0 +1,4 @@
++LEVEL = ../../../make
++
++CXX_SOURCES := main.cpp
++include $(LEVEL)/Makefile.rules
+Index: test/functionalities/thread/exit_during_break/TestExitDuringBreak.py
+===================================================================
+--- test/functionalities/thread/exit_during_break/TestExitDuringBreak.py (revision 0)
++++ test/functionalities/thread/exit_during_break/TestExitDuringBreak.py (revision 0)
+@@ -0,0 +1,94 @@
++"""
++Test number of threads.
++"""
++
++import os, time
++import unittest2
++import lldb
++from lldbtest import *
++import lldbutil
++
++class ExitDuringBreakpointTestCase(TestBase):
++
++ mydir = os.path.join("functionalities", "thread", "exit_during_break")
++
++ @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
++ @expectedFailureDarwin("llvm.org/pr15824") # thread states not properly maintained
++ @dsym_test
++ def test_with_dsym(self):
++ """Test thread exit during breakpoint handling."""
++ self.buildDsym(dictionary=self.getBuildFlags())
++ self.exit_during_breakpoint_test()
++
++ @expectedFailureDarwin("llvm.org/pr15824") # thread states not properly maintained
++ @dwarf_test
++ def test_with_dwarf(self):
++ """Test thread exit during breakpoint handling."""
++ self.buildDwarf(dictionary=self.getBuildFlags())
++ self.exit_during_breakpoint_test()
++
++ def setUp(self):
++ # Call super's setUp().
++ TestBase.setUp(self)
++ # Find the line number for our breakpoint.
++ self.breakpoint = line_number('main.cpp', '// Set breakpoint here')
++
++ def exit_during_breakpoint_test(self):
++ """Test thread exit during breakpoint handling."""
++ exe = os.path.join(os.getcwd(), "a.out")
++ self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
++
++ # This should create a breakpoint in the main thread.
++ lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.breakpoint, num_expected_locations=1)
++
++ # The breakpoint list should show 1 location.
++ self.expect("breakpoint list -f", "Breakpoint location shown correctly",
++ substrs = ["1: file ='main.cpp', line = %d, locations = 1" % self.breakpoint])
++
++ # Run the program.
++ self.runCmd("run", RUN_SUCCEEDED)
++
++ # The stop reason of the thread should be breakpoint.
++ self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
++ substrs = ['stopped',
++ 'stop reason = breakpoint'])
++
++ # Get the target process
++ target = self.dbg.GetSelectedTarget()
++ process = target.GetProcess()
++
++ # The exit probably occured during breakpoint handling, but it isn't
++ # guaranteed. The main thing we're testing here is that the debugger
++ # handles this cleanly is some way.
++
++ # Get the number of threads
++ num_threads = process.GetNumThreads()
++
++ # Make sure we see at least five threads
++ self.assertTrue(num_threads >= 5, 'Number of expected threads and actual threads do not match.')
++
++ # Get the thread objects
++ thread1 = process.GetThreadAtIndex(0)
++ thread2 = process.GetThreadAtIndex(1)
++ thread3 = process.GetThreadAtIndex(2)
++ thread4 = process.GetThreadAtIndex(3)
++ thread5 = process.GetThreadAtIndex(4)
++
++ # Make sure all threads are stopped
++ self.assertTrue(thread1.IsStopped(), "Thread 1 didn't stop during breakpoint")
++ self.assertTrue(thread2.IsStopped(), "Thread 2 didn't stop during breakpoint")
++ self.assertTrue(thread3.IsStopped(), "Thread 3 didn't stop during breakpoint")
++ self.assertTrue(thread4.IsStopped(), "Thread 4 didn't stop during breakpoint")
++ self.assertTrue(thread5.IsStopped(), "Thread 5 didn't stop during breakpoint")
++
++ # Run to completion
++ self.runCmd("continue")
++
++ # At this point, the inferior process should have exited.
++ self.assertTrue(process.GetState() == lldb.eStateExited, PROCESS_EXITED)
++
++if __name__ == '__main__':
++ import atexit
++ lldb.SBDebugger.Initialize()
++ atexit.register(lambda: lldb.SBDebugger.Terminate())
++ unittest2.main()
+Index: test/functionalities/thread/exit_during_break/main.cpp
+===================================================================
+--- test/functionalities/thread/exit_during_break/main.cpp (revision 0)
++++ test/functionalities/thread/exit_during_break/main.cpp (revision 0)
+@@ -0,0 +1,135 @@
++//===-- main.cpp ------------------------------------------------*- C++ -*-===//
++//
++// The LLVM Compiler Infrastructure
++//
++// This file is distributed under the University of Illinois Open Source
++// License. See LICENSE.TXT for details.
++//
++//===----------------------------------------------------------------------===//
++
++// This test is intended to create a situation in which one thread will exit
++// while a breakpoint is being handled in another thread. This may not always
++// happen because it's possible that the exiting thread will exit before the
++// breakpoint is hit. The test case should be flexible enough to treat that
++// as success.
++
++#include <pthread.h>
++#include <unistd.h>
++#include <atomic>
++
++volatile int g_test = 0;
++
++// Note that although hogging the CPU while waiting for a variable to change
++// would be terrible in production code, it's great for testing since it
++// avoids a lot of messy context switching to get multiple threads synchronized.
++#define do_nothing()
++
++#define pseudo_barrier_wait(bar) \
++ --bar; \
++ while (bar > 0) \
++ do_nothing();
++
++#define pseudo_barrier_init(bar, count) (bar = count)
++
++// A barrier to synchronize all the threads except the one that will exit.
++std::atomic_int g_barrier1;
++
++// A barrier to synchronize all the threads including the one that will exit.
++std::atomic_int g_barrier2;
++
++// A barrier to keep the first group of threads from exiting until after the
++// breakpoint has been passed.
++std::atomic_int g_barrier3;
++
++void *
++break_thread_func (void *input)
++{
++ // Wait until the entire first group of threads is running
++ pseudo_barrier_wait(g_barrier1);
++
++ // Wait for the exiting thread to start
++ pseudo_barrier_wait(g_barrier2);
++
++ // Do something
++ g_test++; // Set breakpoint here
++
++ // Synchronize after the breakpoint
++ pseudo_barrier_wait(g_barrier3);
++
++ // Return
++ return NULL;
++}
++
++void *
++wait_thread_func (void *input)
++{
++ // Wait until the entire first group of threads is running
++ pseudo_barrier_wait(g_barrier1);
++
++ // Wait for the exiting thread to start
++ pseudo_barrier_wait(g_barrier2);
++
++ // Wait until the breakpoint has been passed
++ pseudo_barrier_wait(g_barrier3);
++
++ // Return
++ return NULL;
++}
++
++void *
++exit_thread_func (void *input)
++{
++ // Sync up with the rest of the threads.
++ pseudo_barrier_wait(g_barrier2);
++
++ // Try to make sure this thread doesn't exit until the breakpoint is hit.
++ usleep(1);
++
++ // Return
++ return NULL;
++}
++
++int main ()
++{
++ pthread_t thread_1;
++ pthread_t thread_2;
++ pthread_t thread_3;
++ pthread_t thread_4;
++ pthread_t thread_5;
++
++ // The first barrier waits for the non-exiting threads to start.
++ // This thread will also participate in that barrier.
++ // The idea here is to guarantee that the exiting thread will be
++ // last in the internal list maintained by the debugger.
++ pseudo_barrier_init(g_barrier1, 5);
++
++ // The second break synchronyizes thread exection with the breakpoint.
++ pseudo_barrier_init(g_barrier2, 5);
++
++ // The third barrier keeps the waiting threads around until the breakpoint
++ // has been passed.
++ pseudo_barrier_init(g_barrier3, 4);
++
++ // Create a thread to hit the breakpoint
++ pthread_create (&thread_1, NULL, break_thread_func, NULL);
++
++ // Create more threads to slow the debugger down during processing.
++ pthread_create (&thread_2, NULL, wait_thread_func, NULL);
++ pthread_create (&thread_3, NULL, wait_thread_func, NULL);
++ pthread_create (&thread_4, NULL, wait_thread_func, NULL);
++
++ // Wait for all these threads to get started.
++ pseudo_barrier_wait(g_barrier1);
++
++ // Create a thread to exit during the breakpoint
++ pthread_create (&thread_5, NULL, exit_thread_func, NULL);
++
++ // Wait for the threads to finish
++ pthread_join(thread_5, NULL);
++ pthread_join(thread_4, NULL);
++ pthread_join(thread_3, NULL);
++ pthread_join(thread_2, NULL);
++ pthread_join(thread_1, NULL);
++
++ return 0;
++}
+Index: test/functionalities/data-formatter/format-propagation/Makefile
+===================================================================
+--- test/functionalities/data-formatter/format-propagation/Makefile (revision 0)
++++ test/functionalities/data-formatter/format-propagation/Makefile (revision 0)
+@@ -0,0 +1,5 @@
++LEVEL = ../../../make
++
++CXX_SOURCES := main.cpp
++
++include $(LEVEL)/Makefile.rules
+Index: test/functionalities/data-formatter/format-propagation/TestFormatPropagation.py
+===================================================================
+--- test/functionalities/data-formatter/format-propagation/TestFormatPropagation.py (revision 0)
++++ test/functionalities/data-formatter/format-propagation/TestFormatPropagation.py (revision 0)
+@@ -0,0 +1,91 @@
++"""
++Check if changing Format on an SBValue correctly propagates that new format to children as it should
++"""
++
++import os, time
++import unittest2
++import lldb
++from lldbtest import *
++import lldbutil
++
++class FormatPropagationTestCase(TestBase):
++
++ mydir = os.path.join("functionalities", "data-formatter", "format-propagation")
++
++ # rdar://problem/14035604
++ @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
++ @dsym_test
++ def test_with_dsym_and_run_command(self):
++ """Check if changing Format on an SBValue correctly propagates that new format to children as it should"""
++ self.buildDsym()
++ self.propagate_test_commands()
++
++ # rdar://problem/14035604
++ @dwarf_test
++ def test_with_dwarf_and_run_command(self):
++ """Check if changing Format on an SBValue correctly propagates that new format to children as it should"""
++ self.buildDwarf()
++ self.propagate_test_commands()
++
++ def setUp(self):
++ # Call super's setUp().
++ TestBase.setUp(self)
++ # Find the line number to break at.
++ self.line = line_number('main.cpp', '// Set break point at this line.')
++
++ def propagate_test_commands(self):
++ """Check for an issue where capping does not work because the Target pointer appears to be changing behind our backs."""
++ self.runCmd("file a.out", CURRENT_EXECUTABLE_SET)
++
++ lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True)
++
++ self.runCmd("run", RUN_SUCCEEDED)
++
++ # The stop reason of the thread should be breakpoint.
++ self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
++ substrs = ['stopped',
++ 'stop reason = breakpoint'])
++
++ # This is the function to remove the custom formats in order to have a
++ # clean slate for the next test case.
++ def cleanup():
++ pass
++
++ # Execute the cleanup function during test case tear down.
++ self.addTearDownHook(cleanup)
++
++ # extract the parent and the children
++ frame = self.frame()
++ parent = self.frame().FindVariable("f")
++ self.assertTrue(parent != None and parent.IsValid(),"could not find f")
++ X = parent.GetChildMemberWithName("X")
++ self.assertTrue(X != None and X.IsValid(),"could not find X")
++ Y = parent.GetChildMemberWithName("Y")
++ self.assertTrue(Y != None and Y.IsValid(),"could not find Y")
++ # check their values now
++ self.assertTrue(X.GetValue() == "1", "X has an invalid value")
++ self.assertTrue(Y.GetValue() == "2", "Y has an invalid value")
++ # set the format on the parent
++ parent.SetFormat(lldb.eFormatHex)
++ self.assertTrue(X.GetValue() == "0x00000001", "X has not changed format")
++ self.assertTrue(Y.GetValue() == "0x00000002", "Y has not changed format")
++ # Step and check if the values make sense still
++ self.runCmd("next")
++ self.assertTrue(X.GetValue() == "0x00000004", "X has not become 4")
++ self.assertTrue(Y.GetValue() == "0x00000002", "Y has not stuck as hex")
++ # Check that children can still make their own choices
++ Y.SetFormat(lldb.eFormatDecimal)
++ self.assertTrue(X.GetValue() == "0x00000004", "X is still hex")
++ self.assertTrue(Y.GetValue() == "2", "Y has not been reset")
++ # Make a few more changes
++ parent.SetFormat(lldb.eFormatDefault)
++ X.SetFormat(lldb.eFormatHex)
++ Y.SetFormat(lldb.eFormatDefault)
++ self.assertTrue(X.GetValue() == "0x00000004", "X is not hex as it asked")
++ self.assertTrue(Y.GetValue() == "2", "Y is not defaulted")
++
++if __name__ == '__main__':
++ import atexit
++ lldb.SBDebugger.Initialize()
++ atexit.register(lambda: lldb.SBDebugger.Terminate())
++ unittest2.main()
+Index: test/functionalities/data-formatter/format-propagation/main.cpp
+===================================================================
+--- test/functionalities/data-formatter/format-propagation/main.cpp (revision 0)
++++ test/functionalities/data-formatter/format-propagation/main.cpp (revision 0)
+@@ -0,0 +1,13 @@
++struct foo
++{
++ int X;
++ int Y;
++ foo(int a, int b) : X(a), Y(b) {}
++};
++
++int main()
++{
++ foo f(1,2);
++ f.X = 4; // Set break point at this line.
++ return 0;
++}
+Index: test/functionalities/data-formatter/data-formatter-stl/libstdcpp/list/Makefile
+===================================================================
+--- test/functionalities/data-formatter/data-formatter-stl/libstdcpp/list/Makefile (revision 183906)
++++ test/functionalities/data-formatter/data-formatter-stl/libstdcpp/list/Makefile (working copy)
+@@ -2,7 +2,7 @@
+
+ CXX_SOURCES := main.cpp
+
++CFLAGS_EXTRAS := -O0
++USE_LIBSTDCPP := 1
++
+ include $(LEVEL)/Makefile.rules
+-
+-CXXFLAGS += -stdlib=libstdc++ -O0
+-LDFLAGS += -stdlib=libstdc++
+\ No newline at end of file
+Index: test/functionalities/data-formatter/data-formatter-stl/libstdcpp/list/main.cpp
+===================================================================
+--- test/functionalities/data-formatter/data-formatter-stl/libstdcpp/list/main.cpp (revision 183906)
++++ test/functionalities/data-formatter/data-formatter-stl/libstdcpp/list/main.cpp (working copy)
+@@ -23,11 +23,12 @@
+ numbers_list.push_back(4);
+
+ string_list text_list;
+- text_list.push_back(std::string("goofy"));
++ text_list.push_back(std::string("goofy")); // Optional break point at this line.
+ text_list.push_back(std::string("is"));
+ text_list.push_back(std::string("smart"));
+
+ text_list.push_back(std::string("!!!"));
+
+- return 0;
+-}
+\ No newline at end of file
++ return 0; // Set final break point at this line.
++}
++
+Index: test/functionalities/data-formatter/data-formatter-stl/libstdcpp/list/TestDataFormatterStdList.py
+===================================================================
+--- test/functionalities/data-formatter/data-formatter-stl/libstdcpp/list/TestDataFormatterStdList.py (revision 183906)
++++ test/functionalities/data-formatter/data-formatter-stl/libstdcpp/list/TestDataFormatterStdList.py (working copy)
+@@ -20,17 +20,33 @@
+ self.data_formatter_commands()
+
+ @dwarf_test
+- @expectedFailureGcc # llvm.org/pr15301 LLDB prints incorrect sizes of STL containers
++ @expectedFailureLinux('llvm.org/pr15301', ['gcc', 'icc']) # LLDB prints incorrect sizes of STL containers
+ def test_with_dwarf_and_run_command(self):
+ """Test data formatter commands."""
+ self.buildDwarf()
+ self.data_formatter_commands()
+
++ @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
++ @dsym_test
++ def test_with_dsym_and_run_command(self):
++ """Test data formatter commands."""
++ self.buildDsym()
++ self.data_formatter_commands_after_steps()
++
++ @dwarf_test
++ @expectedFailureLinux # llvm.org/pr15301 Multiple LLDB steps do not all complete synchronously.
++ def test_with_dwarf_and_run_command_after_steps(self):
++ """Test data formatter commands with multiple steps."""
++ self.buildDwarf()
++ self.data_formatter_commands_after_steps()
++
+ def setUp(self):
+ # Call super's setUp().
+ TestBase.setUp(self)
+- # Find the line number to break at.
++ # Find the line numbers to break at for the different tests.
+ self.line = line_number('main.cpp', '// Set break point at this line.')
++ self.optional_line = line_number('main.cpp', '// Optional break point at this line.')
++ self.final_line = line_number('main.cpp', '// Set final break point at this line.')
+
+ def data_formatter_commands(self):
+ """Test that that file and class static variables display correctly."""
+@@ -159,8 +175,15 @@
+ substrs = ['list has 0 items',
+ '{}'])
+
+- self.runCmd("n");self.runCmd("n");self.runCmd("n");self.runCmd("n");
++ lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.final_line, num_expected_locations=-1)
+
++ self.runCmd("c", RUN_SUCCEEDED)
++
++ # The stop reason of the thread should be breakpoint.
++ self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
++ substrs = ['stopped',
++ 'stop reason = breakpoint'])
++
+ self.expect("frame variable text_list",
+ substrs = ['list has 4 items',
+ '[0]', 'goofy',
+@@ -188,6 +211,46 @@
+ # check that MightHaveChildren() gets it right
+ self.assertTrue(self.frame().FindVariable("text_list").MightHaveChildren(), "text_list.MightHaveChildren() says False for non empty!")
+
++ def data_formatter_commands_after_steps(self):
++ """Test that that file and class static variables display correctly after multiple step instructions."""
++ self.runCmd("file a.out", CURRENT_EXECUTABLE_SET)
++
++ lldbutil.run_break_set_by_file_and_line (self, "main.cpp", self.optional_line, num_expected_locations=-1)
++
++ self.runCmd("run", RUN_SUCCEEDED)
++
++ # The stop reason of the thread should be breakpoint.
++ self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
++ substrs = ['stopped',
++ 'stop reason = breakpoint'])
++
++ self.expect("frame variable text_list",
++ substrs = ['{}'])
++
++ # Verify that steps in rapid succession are processed prior to inspecting text_list.
++ self.runCmd("n");self.runCmd("n");self.runCmd("n");self.runCmd("n");
++
++ self.expect("frame variable text_list",
++ substrs = ['list has 4 items',
++ '[0]', 'goofy',
++ '[1]', 'is',
++ '[2]', 'smart',
++ '[3]', '!!!'])
++
++ self.expect("p text_list",
++ substrs = ['list has 4 items',
++ '\"goofy\"',
++ '\"is\"',
++ '\"smart\"',
++ '\"!!!\"'])
++
++ # check access-by-index
++ self.expect("frame variable text_list[0]",
++ substrs = ['goofy']);
++ self.expect("frame variable text_list[3]",
++ substrs = ['!!!']);
++
++
+ if __name__ == '__main__':
+ import atexit
+ lldb.SBDebugger.Initialize()
+Index: test/functionalities/data-formatter/data-formatter-stl/libstdcpp/map/Makefile
+===================================================================
+--- test/functionalities/data-formatter/data-formatter-stl/libstdcpp/map/Makefile (revision 183906)
++++ test/functionalities/data-formatter/data-formatter-stl/libstdcpp/map/Makefile (working copy)
+@@ -2,7 +2,6 @@
+
+ CXX_SOURCES := main.cpp
+
+-include $(LEVEL)/Makefile.rules
++USE_LIBSTDCPP := 1
+
+-CXXFLAGS += -stdlib=libstdc++ -O0
+-LDFLAGS += -stdlib=libstdc++
++include $(LEVEL)/Makefile.rules
+Index: test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vbool/Makefile
+===================================================================
+--- test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vbool/Makefile (revision 183906)
++++ test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vbool/Makefile (working copy)
+@@ -2,10 +2,7 @@
+
+ CXX_SOURCES := main.cpp
+
+-include $(LEVEL)/Makefile.rules
++CFLAGS_EXTRAS := -O0
++USE_LIBSTDCPP := 1
+
+-CXXFLAGS += -O0
+-ifeq (,$(findstring gcc,$(CC)))
+-CXXFLAGS += -stdlib=libstdc++
+-LDFLAGS += -stdlib=libstdc++
+-endif
++include $(LEVEL)/Makefile.rules
+Index: test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vector/Makefile
+===================================================================
+--- test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vector/Makefile (revision 183906)
++++ test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vector/Makefile (working copy)
+@@ -2,7 +2,7 @@
+
+ CXX_SOURCES := main.cpp
+
++CXXFLAGS := -O0
++USE_LIBSTDCPP := 1
++
+ include $(LEVEL)/Makefile.rules
+-
+-CXXFLAGS += -stdlib=libstdc++ -O0
+-LDFLAGS += -stdlib=libstdc++
+\ No newline at end of file
+Index: test/functionalities/data-formatter/data-formatter-stl/libstdcpp/string/Makefile
+===================================================================
+--- test/functionalities/data-formatter/data-formatter-stl/libstdcpp/string/Makefile (revision 183906)
++++ test/functionalities/data-formatter/data-formatter-stl/libstdcpp/string/Makefile (working copy)
+@@ -2,7 +2,7 @@
+
+ CXX_SOURCES := main.cpp
+
++CFLAGS_EXTRAS := -O0
++USE_LIBSTDCPP := 1
++
+ include $(LEVEL)/Makefile.rules
+-
+-CXXFLAGS += -stdlib=libstdc++ -O0
+-LDFLAGS += -stdlib=libstdc++
+Index: test/functionalities/data-formatter/data-formatter-stl/libstdcpp/iterator/Makefile
+===================================================================
+--- test/functionalities/data-formatter/data-formatter-stl/libstdcpp/iterator/Makefile (revision 183906)
++++ test/functionalities/data-formatter/data-formatter-stl/libstdcpp/iterator/Makefile (working copy)
+@@ -2,7 +2,7 @@
+
+ CXX_SOURCES := main.cpp
+
++CFLAGS_EXTRAS := -O0
++USE_LIBSTDCPP := 1
++
+ include $(LEVEL)/Makefile.rules
+-
+-CXXFLAGS += -stdlib=libstdc++ -O0
+-LDFLAGS += -stdlib=libstdc++
+Index: test/functionalities/data-formatter/data-formatter-stl/libcxx/multiset/Makefile
+===================================================================
+--- test/functionalities/data-formatter/data-formatter-stl/libcxx/multiset/Makefile (revision 0)
++++ test/functionalities/data-formatter/data-formatter-stl/libcxx/multiset/Makefile (revision 0)
+@@ -0,0 +1,8 @@
++LEVEL = ../../../../../make
++
++CXX_SOURCES := main.cpp
++
++include $(LEVEL)/Makefile.rules
++
++CXXFLAGS += -stdlib=libc++ -O0
++LDFLAGS += -stdlib=libc++
+\ No newline at end of file
+Index: test/functionalities/data-formatter/data-formatter-stl/libcxx/multiset/TestDataFormatterLibcxxMultiSet.py
+===================================================================
+--- test/functionalities/data-formatter/data-formatter-stl/libcxx/multiset/TestDataFormatterLibcxxMultiSet.py (revision 0)
++++ test/functionalities/data-formatter/data-formatter-stl/libcxx/multiset/TestDataFormatterLibcxxMultiSet.py (revision 0)
+@@ -0,0 +1,85 @@
++"""
++Test lldb data formatter subsystem.
++"""
++
++import os, time
++import unittest2
++import lldb
++from lldbtest import *
++import lldbutil
++
++class LibcxxMultiSetDataFormatterTestCase(TestBase):
++
++ mydir = os.path.join("functionalities", "data-formatter", "data-formatter-stl", "libcxx", "multiset")
++
++ @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
++ @dsym_test
++ def test_with_dsym_and_run_command(self):
++ """Test data formatter commands."""
++ self.buildDsym()
++ self.data_formatter_commands()
++
++ @skipIfLinux # No standard locations for libc++ on Linux, so skip for now
++ @dwarf_test
++ def test_with_dwarf_and_run_command(self):
++ """Test data formatter commands."""
++ self.buildDwarf()
++ self.data_formatter_commands()
++
++ def setUp(self):
++ # Call super's setUp().
++ TestBase.setUp(self)
++
++ def data_formatter_commands(self):
++ """Test that that file and class static variables display correctly."""
++ self.runCmd("file a.out", CURRENT_EXECUTABLE_SET)
++
++ lldbutil.run_break_set_by_source_regexp (self, "Set break point at this line.")
++
++ self.runCmd("run", RUN_SUCCEEDED)
++
++ # The stop reason of the thread should be breakpoint.
++ self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
++ substrs = ['stopped',
++ 'stop reason = breakpoint'])
++
++ # This is the function to remove the custom formats in order to have a
++ # clean slate for the next test case.
++ def cleanup():
++ self.runCmd('type format clear', check=False)
++ self.runCmd('type summary clear', check=False)
++ self.runCmd('type filter clear', check=False)
++ self.runCmd('type synth clear', check=False)
++ self.runCmd("settings set target.max-children-count 256", check=False)
++
++ # Execute the cleanup function during test case tear down.
++ self.addTearDownHook(cleanup)
++
++ self.expect('image list',substrs=['libc++.1.dylib','libc++abi.dylib'])
++
++ self.expect("frame variable ii",substrs = ["size=0","{}"])
++ self.runCmd("continue")
++ self.expect("frame variable ii",substrs = ["size=6","[0] = 0","[1] = 1", "[2] = 2", "[3] = 3", "[4] = 4", "[5] = 5"])
++ self.runCmd("continue")
++ self.expect("frame variable ii",substrs = ["size=7","[2] = 2", "[3] = 3", "[6] = 6"])
++ self.expect("p ii",substrs = ["size=7","[2] = 2", "[3] = 3", "[6] = 6"])
++ self.expect("frame variable ii[2]",substrs = [" = 2"])
++ self.runCmd("continue")
++ self.expect("frame variable ii",substrs = ["size=0","{}"])
++ self.runCmd("continue")
++ self.expect("frame variable ii",substrs = ["size=0","{}"])
++ self.expect("frame variable ss",substrs = ["size=0","{}"])
++ self.runCmd("continue")
++ self.expect("frame variable ss",substrs = ["size=2",'[0] = "a"','[1] = "a very long string is right here"'])
++ self.runCmd("continue")
++ self.expect("frame variable ss",substrs = ["size=4",'[2] = "b"','[3] = "c"','[0] = "a"','[1] = "a very long string is right here"'])
++ self.expect("p ss",substrs = ["size=4",'[2] = "b"','[3] = "c"','[0] = "a"','[1] = "a very long string is right here"'])
++ self.expect("frame variable ss[2]",substrs = [' = "b"'])
++ self.runCmd("continue")
++ self.expect("frame variable ss",substrs = ["size=3",'[0] = "a"','[1] = "a very long string is right here"','[2] = "c"'])
++
++if __name__ == '__main__':
++ import atexit
++ lldb.SBDebugger.Initialize()
++ atexit.register(lambda: lldb.SBDebugger.Terminate())
++ unittest2.main()
+Index: test/functionalities/data-formatter/data-formatter-stl/libcxx/multiset/main.cpp
+===================================================================
+--- test/functionalities/data-formatter/data-formatter-stl/libcxx/multiset/main.cpp (revision 0)
++++ test/functionalities/data-formatter/data-formatter-stl/libcxx/multiset/main.cpp (revision 0)
+@@ -0,0 +1,57 @@
++#include <string>
++#ifdef _LIBCPP_INLINE_VISIBILITY
++#undef _LIBCPP_INLINE_VISIBILITY
++#endif
++#define _LIBCPP_INLINE_VISIBILITY
++#include <set>
++
++typedef std::multiset<int> intset;
++typedef std::multiset<std::string> stringset;
++
++int g_the_foo = 0;
++
++int thefoo_rw(int arg = 1)
++{
++ if (arg < 0)
++ arg = 0;
++ if (!arg)
++ arg = 1;
++ g_the_foo += arg;
++ return g_the_foo;
++}
++
++int main()
++{
++ intset ii;
++ thefoo_rw(1); // Set break point at this line.
++
++ ii.insert(0);
++ ii.insert(1);
++ ii.insert(2);
++ ii.insert(3);
++ ii.insert(4);
++ ii.insert(5);
++ thefoo_rw(1); // Set break point at this line.
++
++ ii.insert(6);
++ thefoo_rw(1); // Set break point at this line.
++
++ ii.clear();
++ thefoo_rw(1); // Set break point at this line.
++
++ stringset ss;
++ thefoo_rw(1); // Set break point at this line.
++
++ ss.insert("a");
++ ss.insert("a very long string is right here");
++ thefoo_rw(1); // Set break point at this line.
++
++ ss.insert("b");
++ ss.insert("c");
++ thefoo_rw(1); // Set break point at this line.
++
++ ss.erase("b");
++ thefoo_rw(1); // Set break point at this line.
++
++ return 0;
++}
+Index: test/functionalities/data-formatter/data-formatter-stl/libcxx/multimap/Makefile
+===================================================================
+--- test/functionalities/data-formatter/data-formatter-stl/libcxx/multimap/Makefile (revision 0)
++++ test/functionalities/data-formatter/data-formatter-stl/libcxx/multimap/Makefile (revision 0)
+@@ -0,0 +1,8 @@
++LEVEL = ../../../../../make
++
++CXX_SOURCES := main.cpp
++
++include $(LEVEL)/Makefile.rules
++
++CXXFLAGS += -stdlib=libc++ -O0 -std=c++11
++LDFLAGS += -stdlib=libc++
+\ No newline at end of file
+Index: test/functionalities/data-formatter/data-formatter-stl/libcxx/multimap/main.cpp
+===================================================================
+--- test/functionalities/data-formatter/data-formatter-stl/libcxx/multimap/main.cpp (revision 0)
++++ test/functionalities/data-formatter/data-formatter-stl/libcxx/multimap/main.cpp (revision 0)
+@@ -0,0 +1,81 @@
++#include <string>
++#ifdef _LIBCPP_INLINE_VISIBILITY
++#undef _LIBCPP_INLINE_VISIBILITY
++#endif
++#define _LIBCPP_INLINE_VISIBILITY
++#include <map>
++
++#define intint_map std::multimap<int, int>
++#define strint_map std::multimap<std::string, int>
++#define intstr_map std::multimap<int, std::string>
++#define strstr_map std::multimap<std::string, std::string>
++
++int g_the_foo = 0;
++
++int thefoo_rw(int arg = 1)
++{
++ if (arg < 0)
++ arg = 0;
++ if (!arg)
++ arg = 1;
++ g_the_foo += arg;
++ return g_the_foo;
++}
++
++int main()
++{
++ intint_map ii;
++
++ ii.emplace(0,0); // Set break point at this line.
++ ii.emplace(1,1);
++ thefoo_rw(1); // Set break point at this line.
++ ii.emplace(2,0);
++ ii.emplace(3,1);
++ thefoo_rw(1); // Set break point at this line.
++ ii.emplace(4,0);
++ ii.emplace(5,1);
++ ii.emplace(6,0);
++ ii.emplace(7,1);
++ thefoo_rw(1); // Set break point at this line.
++ ii.emplace(85,1234567);
++
++ ii.clear();
++
++ strint_map si;
++ thefoo_rw(1); // Set break point at this line.
++
++ si.emplace("zero",0);
++ thefoo_rw(1); // Set break point at this line.
++ si.emplace("one",1);
++ si.emplace("two",2);
++ si.emplace("three",3);
++ thefoo_rw(1); // Set break point at this line.
++ si.emplace("four",4);
++
++ si.clear();
++ thefoo_rw(1); // Set break point at this line.
++
++ intstr_map is;
++ thefoo_rw(1); // Set break point at this line.
++ is.emplace(85,"goofy");
++ is.emplace(1,"is");
++ is.emplace(2,"smart");
++ is.emplace(3,"!!!");
++ thefoo_rw(1); // Set break point at this line.
++
++ is.clear();
++ thefoo_rw(1); // Set break point at this line.
++
++ strstr_map ss;
++ thefoo_rw(1); // Set break point at this line.
++
++ ss.emplace("ciao","hello");
++ ss.emplace("casa","house");
++ ss.emplace("gatto","cat");
++ thefoo_rw(1); // Set break point at this line.
++ ss.emplace("a Mac..","..is always a Mac!");
++
++ ss.clear();
++ thefoo_rw(1); // Set break point at this line.
++ return 0;
++}
+\ No newline at end of file
+Index: test/functionalities/data-formatter/data-formatter-stl/libcxx/multimap/TestDataFormatterLibccMultiMap.py
+===================================================================
+--- test/functionalities/data-formatter/data-formatter-stl/libcxx/multimap/TestDataFormatterLibccMultiMap.py (revision 0)
++++ test/functionalities/data-formatter/data-formatter-stl/libcxx/multimap/TestDataFormatterLibccMultiMap.py (revision 0)
+@@ -0,0 +1,320 @@
++"""
++Test lldb data formatter subsystem.
++"""
++
++import os, time
++import unittest2
++import lldb
++from lldbtest import *
++import lldbutil
++
++class LibcxxMultiMapDataFormatterTestCase(TestBase):
++
++ mydir = os.path.join("functionalities", "data-formatter", "data-formatter-stl", "libcxx", "multimap")
++
++ @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
++ @dsym_test
++ def test_with_dsym_and_run_command(self):
++ """Test data formatter commands."""
++ self.buildDsym()
++ self.data_formatter_commands()
++
++ @skipIfLinux # No standard locations for libc++ on Linux, so skip for now
++ @dwarf_test
++ def test_with_dwarf_and_run_command(self):
++ """Test data formatter commands."""
++ self.buildDwarf()
++ self.data_formatter_commands()
++
++ def setUp(self):
++ # Call super's setUp().
++ TestBase.setUp(self)
++
++ def data_formatter_commands(self):
++ """Test that that file and class static variables display correctly."""
++ self.runCmd("file a.out", CURRENT_EXECUTABLE_SET)
++
++ lldbutil.run_break_set_by_source_regexp (self, "Set break point at this line.")
++
++ self.runCmd("run", RUN_SUCCEEDED)
++
++ # The stop reason of the thread should be breakpoint.
++ self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
++ substrs = ['stopped',
++ 'stop reason = breakpoint'])
++
++ # This is the function to remove the custom formats in order to have a
++ # clean slate for the next test case.
++ def cleanup():
++ self.runCmd('type format clear', check=False)
++ self.runCmd('type summary clear', check=False)
++ self.runCmd('type filter clear', check=False)
++ self.runCmd('type synth clear', check=False)
++ self.runCmd("settings set target.max-children-count 256", check=False)
++
++ # Execute the cleanup function during test case tear down.
++ self.addTearDownHook(cleanup)
++
++ self.expect('image list',substrs=['libc++.1.dylib','libc++abi.dylib'])
++
++ self.runCmd("frame variable ii --show-types")
++
++ self.expect('frame variable ii',
++ substrs = ['size=0',
++ '{}'])
++
++ self.runCmd("continue");
++
++ self.expect('frame variable ii',
++ substrs = ['size=2',
++ '[0] = {',
++ 'first = 0',
++ 'second = 0',
++ '[1] = {',
++ 'first = 1',
++ 'second = 1'])
++
++ self.runCmd("continue");
++
++ self.expect('frame variable ii',
++ substrs = ['size=4',
++ '[2] = {',
++ 'first = 2',
++ 'second = 0',
++ '[3] = {',
++ 'first = 3',
++ 'second = 1'])
++
++ self.runCmd("continue");
++
++ self.expect("frame variable ii",
++ substrs = ['size=8',
++ '[5] = {',
++ 'first = 5',
++ 'second = 0',
++ '[7] = {',
++ 'first = 7',
++ 'second = 1'])
++
++ self.expect("p ii",
++ substrs = ['size=8',
++ '[5] = {',
++ 'first = 5',
++ 'second = 0',
++ '[7] = {',
++ 'first = 7',
++ 'second = 1'])
++
++ # check access-by-index
++ self.expect("frame variable ii[0]",
++ substrs = ['first = 0',
++ 'second = 0']);
++ self.expect("frame variable ii[3]",
++ substrs = ['first =',
++ 'second =']);
++
++ # check that MightHaveChildren() gets it right
++ self.assertTrue(self.frame().FindVariable("ii").MightHaveChildren(), "ii.MightHaveChildren() says False for non empty!")
++
++ # check that the expression parser does not make use of
++ # synthetic children instead of running code
++ # TOT clang has a fix for this, which makes the expression command here succeed
++ # since this would make the test fail or succeed depending on clang version in use
++ # this is safer commented for the time being
++ #self.expect("expression ii[8]", matching=False, error=True,
++ # substrs = ['1234567'])
++
++ self.runCmd("continue");
++
++ self.expect('frame variable ii',
++ substrs = ['size=0',
++ '{}'])
++
++ self.runCmd("frame variable si --show-types")
++
++ self.expect('frame variable si',
++ substrs = ['size=0',
++ '{}'])
++
++ self.runCmd("continue");
++
++ self.expect('frame variable si',
++ substrs = ['size=1',
++ '[0] = ',
++ 'first = \"zero\"',
++ 'second = 0'])
++
++ self.runCmd("continue");
++
++ self.expect("frame variable si",
++ substrs = ['size=4',
++ '[0] = ',
++ 'first = \"zero\"',
++ 'second = 0',
++ '[1] = ',
++ 'first = \"one\"',
++ 'second = 1',
++ '[2] = ',
++ 'first = \"two\"',
++ 'second = 2',
++ '[3] = ',
++ 'first = \"three\"',
++ 'second = 3'])
++
++ self.expect("p si",
++ substrs = ['size=4',
++ '[0] = ',
++ 'first = \"zero\"',
++ 'second = 0',
++ '[1] = ',
++ 'first = \"one\"',
++ 'second = 1',
++ '[2] = ',
++ 'first = \"two\"',
++ 'second = 2',
++ '[3] = ',
++ 'first = \"three\"',
++ 'second = 3'])
++
++ # check that MightHaveChildren() gets it right
++ self.assertTrue(self.frame().FindVariable("si").MightHaveChildren(), "si.MightHaveChildren() says False for non empty!")
++
++ # check access-by-index
++ self.expect("frame variable si[0]",
++ substrs = ['first = ', 'one',
++ 'second = 1']);
++
++ # check that the expression parser does not make use of
++ # synthetic children instead of running code
++ # TOT clang has a fix for this, which makes the expression command here succeed
++ # since this would make the test fail or succeed depending on clang version in use
++ # this is safer commented for the time being
++ #self.expect("expression si[0]", matching=False, error=True,
++ # substrs = ['first = ', 'zero'])
++
++ self.runCmd("continue");
++
++ self.expect('frame variable si',
++ substrs = ['size=0',
++ '{}'])
++
++ self.runCmd("continue");
++ self.runCmd("frame variable is --show-types")
++
++ self.expect('frame variable is',
++ substrs = ['size=0',
++ '{}'])
++
++ self.runCmd("continue");
++
++ self.expect("frame variable is",
++ substrs = ['size=4',
++ '[0] = ',
++ 'second = \"goofy\"',
++ 'first = 85',
++ '[1] = ',
++ 'second = \"is\"',
++ 'first = 1',
++ '[2] = ',
++ 'second = \"smart\"',
++ 'first = 2',
++ '[3] = ',
++ 'second = \"!!!\"',
++ 'first = 3'])
++
++ self.expect("p is",
++ substrs = ['size=4',
++ '[0] = ',
++ 'second = \"goofy\"',
++ 'first = 85',
++ '[1] = ',
++ 'second = \"is\"',
++ 'first = 1',
++ '[2] = ',
++ 'second = \"smart\"',
++ 'first = 2',
++ '[3] = ',
++ 'second = \"!!!\"',
++ 'first = 3'])
++
++ # check that MightHaveChildren() gets it right
++ self.assertTrue(self.frame().FindVariable("is").MightHaveChildren(), "is.MightHaveChildren() says False for non empty!")
++
++ # check access-by-index
++ self.expect("frame variable is[0]",
++ substrs = ['first = ',
++ 'second =']);
++
++ # check that the expression parser does not make use of
++ # synthetic children instead of running code
++ # TOT clang has a fix for this, which makes the expression command here succeed
++ # since this would make the test fail or succeed depending on clang version in use
++ # this is safer commented for the time being
++ #self.expect("expression is[0]", matching=False, error=True,
++ # substrs = ['first = ', 'goofy'])
++
++ self.runCmd("continue");
++
++ self.expect('frame variable is',
++ substrs = ['size=0',
++ '{}'])
++
++ self.runCmd("continue");
++ self.runCmd("frame variable ss --show-types")
++
++ self.expect('frame variable ss',
++ substrs = ['size=0',
++ '{}'])
++
++ self.runCmd("continue");
++
++ self.expect("frame variable ss",
++ substrs = ['size=3',
++ '[0] = ',
++ 'second = \"hello\"',
++ 'first = \"ciao\"',
++ '[1] = ',
++ 'second = \"house\"',
++ 'first = \"casa\"',
++ '[2] = ',
++ 'second = \"cat\"',
++ 'first = \"gatto\"'])
++
++ self.expect("p ss",
++ substrs = ['size=3',
++ '[0] = ',
++ 'second = \"hello\"',
++ 'first = \"ciao\"',
++ '[1] = ',
++ 'second = \"house\"',
++ 'first = \"casa\"',
++ '[2] = ',
++ 'second = \"cat\"',
++ 'first = \"gatto\"'])
++
++ # check that MightHaveChildren() gets it right
++ self.assertTrue(self.frame().FindVariable("ss").MightHaveChildren(), "ss.MightHaveChildren() says False for non empty!")
++
++ # check access-by-index
++ self.expect("frame variable ss[2]",
++ substrs = ['gatto', 'cat']);
++
++ # check that the expression parser does not make use of
++ # synthetic children instead of running code
++ # TOT clang has a fix for this, which makes the expression command here succeed
++ # since this would make the test fail or succeed depending on clang version in use
++ # this is safer commented for the time being
++ #self.expect("expression ss[3]", matching=False, error=True,
++ # substrs = ['gatto'])
++
++ self.runCmd("continue");
++
++ self.expect('frame variable ss',
++ substrs = ['size=0',
++ '{}'])
++
++if __name__ == '__main__':
++ import atexit
++ lldb.SBDebugger.Initialize()
++ atexit.register(lambda: lldb.SBDebugger.Terminate())
++ unittest2.main()
+Index: test/functionalities/data-formatter/data-formatter-stl/libcxx/set/TestDataFormatterLibcxxSet.py
+===================================================================
+--- test/functionalities/data-formatter/data-formatter-stl/libcxx/set/TestDataFormatterLibcxxSet.py (revision 0)
++++ test/functionalities/data-formatter/data-formatter-stl/libcxx/set/TestDataFormatterLibcxxSet.py (revision 0)
+@@ -0,0 +1,85 @@
++"""
++Test lldb data formatter subsystem.
++"""
++
++import os, time
++import unittest2
++import lldb
++from lldbtest import *
++import lldbutil
++
++class LibcxxSetDataFormatterTestCase(TestBase):
++
++ mydir = os.path.join("functionalities", "data-formatter", "data-formatter-stl", "libcxx", "set")
++
++ @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
++ @dsym_test
++ def test_with_dsym_and_run_command(self):
++ """Test data formatter commands."""
++ self.buildDsym()
++ self.data_formatter_commands()
++
++ @skipIfLinux # No standard locations for libc++ on Linux, so skip for now
++ @dwarf_test
++ def test_with_dwarf_and_run_command(self):
++ """Test data formatter commands."""
++ self.buildDwarf()
++ self.data_formatter_commands()
++
++ def setUp(self):
++ # Call super's setUp().
++ TestBase.setUp(self)
++
++ def data_formatter_commands(self):
++ """Test that that file and class static variables display correctly."""
++ self.runCmd("file a.out", CURRENT_EXECUTABLE_SET)
++
++ lldbutil.run_break_set_by_source_regexp (self, "Set break point at this line.")
++
++ self.runCmd("run", RUN_SUCCEEDED)
++
++ # The stop reason of the thread should be breakpoint.
++ self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
++ substrs = ['stopped',
++ 'stop reason = breakpoint'])
++
++ # This is the function to remove the custom formats in order to have a
++ # clean slate for the next test case.
++ def cleanup():
++ self.runCmd('type format clear', check=False)
++ self.runCmd('type summary clear', check=False)
++ self.runCmd('type filter clear', check=False)
++ self.runCmd('type synth clear', check=False)
++ self.runCmd("settings set target.max-children-count 256", check=False)
++
++ # Execute the cleanup function during test case tear down.
++ self.addTearDownHook(cleanup)
++
++ self.expect('image list',substrs=['libc++.1.dylib','libc++abi.dylib'])
++
++ self.expect("frame variable ii",substrs = ["size=0","{}"])
++ self.runCmd("continue")
++ self.expect("frame variable ii",substrs = ["size=6","[0] = 0","[1] = 1", "[2] = 2", "[3] = 3", "[4] = 4", "[5] = 5"])
++ self.runCmd("continue")
++ self.expect("frame variable ii",substrs = ["size=7","[2] = 2", "[3] = 3", "[6] = 6"])
++ self.expect("frame variable ii[2]",substrs = [" = 2"])
++ self.expect("p ii",substrs = ["size=7","[2] = 2", "[3] = 3", "[6] = 6"])
++ self.runCmd("continue")
++ self.expect("frame variable ii",substrs = ["size=0","{}"])
++ self.runCmd("continue")
++ self.expect("frame variable ii",substrs = ["size=0","{}"])
++ self.expect("frame variable ss",substrs = ["size=0","{}"])
++ self.runCmd("continue")
++ self.expect("frame variable ss",substrs = ["size=2",'[0] = "a"','[1] = "a very long string is right here"'])
++ self.runCmd("continue")
++ self.expect("frame variable ss",substrs = ["size=4",'[2] = "b"','[3] = "c"','[0] = "a"','[1] = "a very long string is right here"'])
++ self.expect("p ss",substrs = ["size=4",'[2] = "b"','[3] = "c"','[0] = "a"','[1] = "a very long string is right here"'])
++ self.expect("frame variable ss[2]",substrs = [' = "b"'])
++ self.runCmd("continue")
++ self.expect("frame variable ss",substrs = ["size=3",'[0] = "a"','[1] = "a very long string is right here"','[2] = "c"'])
++
++if __name__ == '__main__':
++ import atexit
++ lldb.SBDebugger.Initialize()
++ atexit.register(lambda: lldb.SBDebugger.Terminate())
++ unittest2.main()
+Index: test/functionalities/data-formatter/data-formatter-stl/libcxx/set/Makefile
+===================================================================
+--- test/functionalities/data-formatter/data-formatter-stl/libcxx/set/Makefile (revision 0)
++++ test/functionalities/data-formatter/data-formatter-stl/libcxx/set/Makefile (revision 0)
+@@ -0,0 +1,8 @@
++LEVEL = ../../../../../make
++
++CXX_SOURCES := main.cpp
++
++include $(LEVEL)/Makefile.rules
++
++CXXFLAGS += -stdlib=libc++ -O0
++LDFLAGS += -stdlib=libc++
+\ No newline at end of file
+Index: test/functionalities/data-formatter/data-formatter-stl/libcxx/set/main.cpp
+===================================================================
+--- test/functionalities/data-formatter/data-formatter-stl/libcxx/set/main.cpp (revision 0)
++++ test/functionalities/data-formatter/data-formatter-stl/libcxx/set/main.cpp (revision 0)
+@@ -0,0 +1,57 @@
++#include <string>
++#ifdef _LIBCPP_INLINE_VISIBILITY
++#undef _LIBCPP_INLINE_VISIBILITY
++#endif
++#define _LIBCPP_INLINE_VISIBILITY
++#include <set>
++
++typedef std::set<int> intset;
++typedef std::set<std::string> stringset;
++
++int g_the_foo = 0;
++
++int thefoo_rw(int arg = 1)
++{
++ if (arg < 0)
++ arg = 0;
++ if (!arg)
++ arg = 1;
++ g_the_foo += arg;
++ return g_the_foo;
++}
++
++int main()
++{
++ intset ii;
++ thefoo_rw(1); // Set break point at this line.
++
++ ii.insert(0);
++ ii.insert(1);
++ ii.insert(2);
++ ii.insert(3);
++ ii.insert(4);
++ ii.insert(5);
++ thefoo_rw(1); // Set break point at this line.
++
++ ii.insert(6);
++ thefoo_rw(1); // Set break point at this line.
++
++ ii.clear();
++ thefoo_rw(1); // Set break point at this line.
++
++ stringset ss;
++ thefoo_rw(1); // Set break point at this line.
++
++ ss.insert("a");
++ ss.insert("a very long string is right here");
++ thefoo_rw(1); // Set break point at this line.
++
++ ss.insert("b");
++ ss.insert("c");
++ thefoo_rw(1); // Set break point at this line.
++
++ ss.erase("b");
++ thefoo_rw(1); // Set break point at this line.
++
++ return 0;
++}
+Index: test/functionalities/data-formatter/data-formatter-stl/libcxx/map/TestDataFormatterLibccMap.py
+===================================================================
+--- test/functionalities/data-formatter/data-formatter-stl/libcxx/map/TestDataFormatterLibccMap.py (revision 183906)
++++ test/functionalities/data-formatter/data-formatter-stl/libcxx/map/TestDataFormatterLibccMap.py (working copy)
+@@ -58,17 +58,15 @@
+ self.expect('image list',substrs=['libc++.1.dylib','libc++abi.dylib'])
+
+ self.runCmd("frame variable ii --show-types")
+-
+- self.runCmd("type summary add -x \"std::__1::map<\" --summary-string \"map has ${svar%#} items\" -e")
+-
++
+ self.expect('frame variable ii',
+- substrs = ['map has 0 items',
++ substrs = ['size=0',
+ '{}'])
+
+ self.runCmd("continue");
+
+ self.expect('frame variable ii',
+- substrs = ['map has 2 items',
++ substrs = ['size=2',
+ '[0] = {',
+ 'first = 0',
+ 'second = 0',
+@@ -79,7 +77,7 @@
+ self.runCmd("continue");
+
+ self.expect('frame variable ii',
+- substrs = ['map has 4 items',
++ substrs = ['size=4',
+ '[2] = {',
+ 'first = 2',
+ 'second = 0',
+@@ -90,7 +88,7 @@
+ self.runCmd("continue");
+
+ self.expect("frame variable ii",
+- substrs = ['map has 8 items',
++ substrs = ['size=8',
+ '[5] = {',
+ 'first = 5',
+ 'second = 0',
+@@ -99,7 +97,7 @@
+ 'second = 1'])
+
+ self.expect("p ii",
+- substrs = ['map has 8 items',
++ substrs = ['size=8',
+ '[5] = {',
+ 'first = 5',
+ 'second = 0',
+@@ -129,19 +127,19 @@
+ self.runCmd("continue");
+
+ self.expect('frame variable ii',
+- substrs = ['map has 0 items',
++ substrs = ['size=0',
+ '{}'])
+
+ self.runCmd("frame variable si --show-types")
+
+ self.expect('frame variable si',
+- substrs = ['map has 0 items',
++ substrs = ['size=0',
+ '{}'])
+
+ self.runCmd("continue");
+
+ self.expect('frame variable si',
+- substrs = ['map has 1 items',
++ substrs = ['size=1',
+ '[0] = ',
+ 'first = \"zero\"',
+ 'second = 0'])
+@@ -149,7 +147,7 @@
+ self.runCmd("continue");
+
+ self.expect("frame variable si",
+- substrs = ['map has 4 items',
++ substrs = ['size=4',
+ '[0] = ',
+ 'first = \"zero\"',
+ 'second = 0',
+@@ -164,7 +162,7 @@
+ 'second = 3'])
+
+ self.expect("p si",
+- substrs = ['map has 4 items',
++ substrs = ['size=4',
+ '[0] = ',
+ 'first = \"zero\"',
+ 'second = 0',
+@@ -197,20 +195,20 @@
+ self.runCmd("continue");
+
+ self.expect('frame variable si',
+- substrs = ['map has 0 items',
++ substrs = ['size=0',
+ '{}'])
+
+ self.runCmd("continue");
+ self.runCmd("frame variable is --show-types")
+
+ self.expect('frame variable is',
+- substrs = ['map has 0 items',
++ substrs = ['size=0',
+ '{}'])
+
+ self.runCmd("continue");
+
+ self.expect("frame variable is",
+- substrs = ['map has 4 items',
++ substrs = ['size=4',
+ '[0] = ',
+ 'second = \"goofy\"',
+ 'first = 85',
+@@ -225,7 +223,7 @@
+ 'first = 3'])
+
+ self.expect("p is",
+- substrs = ['map has 4 items',
++ substrs = ['size=4',
+ '[0] = ',
+ 'second = \"goofy\"',
+ 'first = 85',
+@@ -258,20 +256,20 @@
+ self.runCmd("continue");
+
+ self.expect('frame variable is',
+- substrs = ['map has 0 items',
++ substrs = ['size=0',
+ '{}'])
+
+ self.runCmd("continue");
+ self.runCmd("frame variable ss --show-types")
+
+ self.expect('frame variable ss',
+- substrs = ['map has 0 items',
++ substrs = ['size=0',
+ '{}'])
+
+ self.runCmd("continue");
+
+ self.expect("frame variable ss",
+- substrs = ['map has 3 items',
++ substrs = ['size=3',
+ '[0] = ',
+ 'second = \"hello\"',
+ 'first = \"ciao\"',
+@@ -283,7 +281,7 @@
+ 'first = \"gatto\"'])
+
+ self.expect("p ss",
+- substrs = ['map has 3 items',
++ substrs = ['size=3',
+ '[0] = ',
+ 'second = \"hello\"',
+ 'first = \"ciao\"',
+@@ -312,7 +310,7 @@
+ self.runCmd("continue");
+
+ self.expect('frame variable ss',
+- substrs = ['map has 0 items',
++ substrs = ['size=0',
+ '{}'])
+
+ if __name__ == '__main__':
+Index: test/functionalities/data-formatter/data-formatter-advanced/TestDataFormatterAdv.py
+===================================================================
+--- test/functionalities/data-formatter/data-formatter-advanced/TestDataFormatterAdv.py (revision 183906)
++++ test/functionalities/data-formatter/data-formatter-advanced/TestDataFormatterAdv.py (working copy)
+@@ -77,7 +77,8 @@
+ self.expect("frame variable int_array",
+ substrs = ['1,2,3,4,5'])
+
+- self.runCmd("type summary add --summary-string \"${var[].integer}\" -x \"i_am_cool \\[[0-9]\\]")
++ # this will fail if we don't do [] as regex correctly
++ self.runCmd('type summary add --summary-string "${var[].integer}" "i_am_cool[]')
+
+ self.expect("frame variable cool_array",
+ substrs = ['1,1,1,1,6'])
+@@ -122,11 +123,16 @@
+
+ self.runCmd("type summary clear")
+
+- self.runCmd("type summary add --summary-string \"${var[0-1]}\" -x \"int \[[0-9]\]\"")
++ self.runCmd('type summary add --summary-string \"${var[0-1]}\" -x \"int \[[0-9]\]\"')
+
+ self.expect("frame variable int_array",
+ substrs = ['1,2'])
+
++ self.runCmd('type summary add --summary-string \"${var[0-1]}\" "int []"')
++
++ self.expect("frame variable int_array",
++ substrs = ['1,2'])
++
+ self.runCmd("type summary clear")
+
+ self.runCmd("type summary add -c -x \"i_am_cool \[[0-9]\]\"")
+Index: test/functionalities/data-formatter/rdar-9973865/Test-rdar-9973865.py
+===================================================================
+--- test/functionalities/data-formatter/rdar-9973865/Test-rdar-9973865.py (revision 183906)
++++ test/functionalities/data-formatter/rdar-9973865/Test-rdar-9973865.py (working copy)
+@@ -23,6 +23,7 @@
+ @dwarf_test
+ def test_with_dwarf_and_run_command(self):
+ """Test data formatter commands."""
++
+ self.buildDwarf()
+ self.data_formatter_commands()
+
+Index: test/functionalities/data-formatter/rdar-9973865/Makefile
+===================================================================
+--- test/functionalities/data-formatter/rdar-9973865/Makefile (revision 183906)
++++ test/functionalities/data-formatter/rdar-9973865/Makefile (working copy)
+@@ -2,4 +2,10 @@
+
+ CXX_SOURCES := main.cpp
+
++# Workaround for llvm.org/pr16214: clang doesn't emit structure definition DWARF
++# information without the flag below.
++ifneq (,$(findstring clang,$(CC)))
++ CFLAGS_EXTRAS := -fno-limit-debug-info
++endif
++
+ include $(LEVEL)/Makefile.rules
+Index: test/functionalities/exec/TestExec.py
+===================================================================
+--- test/functionalities/exec/TestExec.py (revision 0)
++++ test/functionalities/exec/TestExec.py (revision 0)
+@@ -0,0 +1,105 @@
++"""
++Test some lldb command abbreviations.
++"""
++import commands
++import lldb
++import os
++import time
++import unittest2
++from lldbtest import *
++import lldbutil
++
++def execute_command (command):
++ #print '%% %s' % (command)
++ (exit_status, output) = commands.getstatusoutput (command)
++ #if output:
++ # print output
++ #print 'status = %u' % (exit_status)
++ return exit_status
++
++class ExecTestCase(TestBase):
++
++ mydir = os.path.join("functionalities", "exec")
++
++
++ @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
++ @dsym_test
++ def test_with_dsym (self):
++ if self.getArchitecture() == 'x86_64':
++ source = os.path.join (os.getcwd(), "main.cpp")
++ o_file = os.path.join (os.getcwd(), "main.o")
++ execute_command ("'%s' -g -O0 -arch i386 -arch x86_64 '%s' -c -o '%s'" % (os.environ["CC"], source, o_file))
++ execute_command ("'%s' -g -O0 -arch i386 -arch x86_64 '%s'" % (os.environ["CC"], o_file))
++ else:
++ self.buildDsym()
++ self.do_test ()
++
++
++ @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
++ @dwarf_test
++ def test_with_dwarf (self):
++ if self.getArchitecture() == 'x86_64':
++ source = os.path.join (os.getcwd(), "main.cpp")
++ o_file = os.path.join (os.getcwd(), "main.o")
++ dsym_path = os.path.join (os.getcwd(), "a.out.dSYM")
++ execute_command ("'%s' -g -O0 -arch i386 -arch x86_64 '%s' -c -o '%s'" % (os.environ["CC"], source, o_file))
++ execute_command ("'%s' -g -O0 -arch i386 -arch x86_64 '%s'" % (os.environ["CC"], o_file))
++ execute_command ("rm -rf '%s'" % (dsym_path))
++ else:
++ self.buildDwarf()
++ self.do_test ()
++
++ def do_test (self):
++ exe = os.path.join (os.getcwd(), "a.out")
++
++ # Create the target
++ target = self.dbg.CreateTarget(exe)
++
++ # Create any breakpoints we need
++ breakpoint = target.BreakpointCreateBySourceRegex ('Set breakpoint 1 here', lldb.SBFileSpec ("main.cpp", False))
++ self.assertTrue(breakpoint, VALID_BREAKPOINT)
++
++ # Launch the process
++ process = target.LaunchSimple(None, None, os.getcwd())
++ self.assertTrue(process, PROCESS_IS_VALID)
++
++ for i in range(6):
++ # The stop reason of the thread should be breakpoint.
++ self.assertTrue(process.GetState() == lldb.eStateStopped,
++ STOPPED_DUE_TO_BREAKPOINT)
++
++ thread = process.GetThreadAtIndex (0)
++
++ self.assertTrue (thread.IsValid(),
++ "Process stopped at 'main' should have a valid thread");
++
++ stop_reason = thread.GetStopReason()
++
++ self.assertTrue (stop_reason == lldb.eStopReasonBreakpoint,
++ "Thread in process stopped in 'main' should have a stop reason of eStopReasonBreakpoint");
++
++ # Run and we should stop due to exec
++ process.Continue()
++
++ self.assertTrue(process.GetState() == lldb.eStateStopped,
++ "Process should be stopped at __dyld_start")
++
++ thread = process.GetThreadAtIndex (0)
++
++ self.assertTrue (thread.IsValid(),
++ "Process stopped at exec should have a valid thread");
++
++ stop_reason = thread.GetStopReason()
++
++ self.assertTrue (stop_reason == lldb.eStopReasonExec,
++ "Thread in process stopped on exec should have a stop reason of eStopReasonExec");
++
++ # Run and we should stop at breakpoint in main after exec
++ process.Continue()
++
++if __name__ == '__main__':
++ import atexit
++ lldb.SBDebugger.Initialize()
++ atexit.register(lambda: lldb.SBDebugger.Terminate())
++ unittest2.main()
++
+Index: test/functionalities/exec/Makefile
+===================================================================
+--- test/functionalities/exec/Makefile (revision 0)
++++ test/functionalities/exec/Makefile (revision 0)
+@@ -0,0 +1,5 @@
++LEVEL = ../../make
++
++CXX_SOURCES := main.cpp
++
++include $(LEVEL)/Makefile.rules
+Index: test/functionalities/exec/main.cpp
+===================================================================
+--- test/functionalities/exec/main.cpp (revision 0)
++++ test/functionalities/exec/main.cpp (revision 0)
+@@ -0,0 +1,94 @@
++#include <errno.h>
++#include <mach/mach.h>
++#include <signal.h>
++#include <stdio.h>
++#include <stdint.h>
++#include <stdlib.h>
++#include <spawn.h>
++#include <unistd.h>
++
++static void
++exit_with_errno (int err, const char *prefix)
++{
++ if (err)
++ {
++ fprintf (stderr,
++ "%s%s",
++ prefix ? prefix : "",
++ strerror(err));
++ exit (err);
++ }
++}
++
++static pid_t
++spawn_process (const char **argv,
++ const char **envp,
++ cpu_type_t cpu_type,
++ int &err)
++{
++ pid_t pid = 0;
++
++ const posix_spawn_file_actions_t *file_actions = NULL;
++ posix_spawnattr_t attr;
++ err = posix_spawnattr_init (&attr);
++ if (err)
++ return pid;
++
++ short flags = POSIX_SPAWN_SETEXEC | POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK;
++ err = posix_spawnattr_setflags (&attr, flags);
++ if (err == 0)
++ {
++ // Use the default signal masks
++ sigset_t no_signals;
++ sigset_t all_signals;
++ sigemptyset (&no_signals);
++ sigfillset (&all_signals);
++ posix_spawnattr_setsigmask(&attr, &no_signals);
++ posix_spawnattr_setsigdefault(&attr, &all_signals);
++
++ if (cpu_type != 0)
++ {
++ size_t ocount = 0;
++ err = posix_spawnattr_setbinpref_np (&attr, 1, &cpu_type, &ocount);
++ }
++
++ if (err == 0)
++ {
++ err = posix_spawn (&pid,
++ argv[0],
++ file_actions,
++ &attr,
++ (char * const *)argv,
++ (char * const *)envp);
++ }
++
++ posix_spawnattr_destroy(&attr);
++ }
++ return pid;
++}
++
++int
++main (int argc, char const **argv)
++{
++ printf ("pid %i: Pointer size is %zu.\n", getpid(), sizeof(void *));
++ int err = 0; // Set breakpoint 1 here
++#if defined (__x86_64__)
++ if (sizeof(void *) == 8)
++ {
++ spawn_process (argv, NULL, CPU_TYPE_I386, err);
++ if (err)
++ exit_with_errno (err, "posix_spawn i386 error");
++ }
++ else
++ {
++ spawn_process (argv, NULL, CPU_TYPE_X86_64, err);
++ if (err)
++ exit_with_errno (err, "posix_spawn x86_64 error");
++ }
++#else
++ spawn_process (argv, NULL, 0, err);
++ if (err)
++ exit_with_errno (err, "posix_spawn x86_64 error");
++#endif
++ return 0;
++}
+Index: test/functionalities/fat_archives/Makefile
+===================================================================
+--- test/functionalities/fat_archives/Makefile (revision 0)
++++ test/functionalities/fat_archives/Makefile (revision 0)
+@@ -0,0 +1,12 @@
++all: clean
++ $(CC) -arch i386 -g -c a.c
++ ar -q liba-i386.a a.o
++ $(CC) -arch x86_64 -g -c a.c
++ ar -q liba-x86_64.a a.o
++ lipo -create -output liba.a liba-i386.a liba-x86_64.a
++ $(CC) -g -c main.c
++ $(CC) -o a.out main.o -L. -la
++
++clean:
++ rm -rf a.o a.out liba-i386.a liba-x86_64.a liba.a *un~ .*un~ main.o *.pyc
++
+Index: test/functionalities/fat_archives/a.c
+===================================================================
+--- test/functionalities/fat_archives/a.c (revision 0)
++++ test/functionalities/fat_archives/a.c (revision 0)
+@@ -0,0 +1,4 @@
++int foo ()
++{
++ return 5;
++}
+Index: test/functionalities/fat_archives/main.c
+===================================================================
+--- test/functionalities/fat_archives/main.c (revision 0)
++++ test/functionalities/fat_archives/main.c (revision 0)
+@@ -0,0 +1,6 @@
++#include "a.h"
++#include <stdio.h>
++int main()
++{
++ printf ("%d\n", foo());
++}
+Index: test/functionalities/fat_archives/a.h
+===================================================================
+--- test/functionalities/fat_archives/a.h (revision 0)
++++ test/functionalities/fat_archives/a.h (revision 0)
+@@ -0,0 +1 @@
++int foo ();
+Index: test/functionalities/fat_archives/TestFatArchives.py
+===================================================================
+--- test/functionalities/fat_archives/TestFatArchives.py (revision 0)
++++ test/functionalities/fat_archives/TestFatArchives.py (revision 0)
+@@ -0,0 +1,63 @@
++"""
++Test some lldb command abbreviations.
++"""
++import commands
++import lldb
++import os
++import time
++import unittest2
++from lldbtest import *
++import lldbutil
++
++def execute_command (command):
++ # print '%% %s' % (command)
++ (exit_status, output) = commands.getstatusoutput (command)
++ # if output:
++ # print output
++ # print 'status = %u' % (exit_status)
++ return exit_status
++
++class FatArchiveTestCase(TestBase):
++
++ mydir = os.path.join("functionalities", "fat_archives")
++
++ @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
++ @dwarf_test
++ def test_with_dwarf (self):
++ if self.getArchitecture() == 'x86_64':
++ execute_command ("make CC='%s'" % (os.environ["CC"]))
++ self.main ()
++ else:
++ self.skipTest("This test requires x86_64 as the architecture for the inferior")
++
++ def main (self):
++ '''This test compiles a quick example by making a fat file (universal) full of
++ skinny .o files and makes sure we can use them to resolve breakpoints when doing
++ DWARF in .o file debugging. The only thing this test needs to do is to compile and
++ set a breakpoint in the target and verify any breakpoint locations have valid debug
++ info for the function, and source file and line.'''
++ exe = os.path.join (os.getcwd(), "a.out")
++
++ # Create the target
++ target = self.dbg.CreateTarget(exe)
++
++ # Create a breakpoint by name
++ breakpoint = target.BreakpointCreateByName ('foo', exe)
++ self.assertTrue(breakpoint, VALID_BREAKPOINT)
++
++ # Make sure the breakpoint resolves to a function, file and line
++ for bp_loc in breakpoint:
++ # Get a section offset address (lldb.SBAddress) from the breakpoint location
++ bp_loc_addr = bp_loc.GetAddress()
++ line_entry = bp_loc_addr.GetLineEntry()
++ function = bp_loc_addr.GetFunction()
++ self.assertTrue(function.IsValid(), "Verify breakpoint in fat BSD archive has valid function debug info")
++ self.assertTrue(line_entry.GetFileSpec(), "Verify breakpoint in fat BSD archive has source file information")
++ self.assertTrue(line_entry.GetLine() != 0, "Verify breakpoint in fat BSD archive has source line information")
++
++if __name__ == '__main__':
++ import atexit
++ lldb.SBDebugger.Initialize()
++ atexit.register(lambda: lldb.SBDebugger.Terminate())
++ unittest2.main()
++
+Index: test/functionalities/abbreviation/TestAbbreviations.py
+===================================================================
+--- test/functionalities/abbreviation/TestAbbreviations.py (revision 183906)
++++ test/functionalities/abbreviation/TestAbbreviations.py (working copy)
+@@ -14,7 +14,7 @@
+
+ def test_nonrunning_command_abbreviations (self):
+ self.expect("ap script",
+- startstr = "The following commands may relate to 'script':",
++ startstr = "The following built-in commands may relate to 'script':",
+ substrs = ['breakpoint command add',
+ 'breakpoint command list',
+ 'breakpoint list',
+Index: test/lldbtest.py
+===================================================================
+--- test/lldbtest.py (revision 183906)
++++ test/lldbtest.py (working copy)
+@@ -34,6 +34,7 @@
+ import os, sys, traceback
+ import os.path
+ import re
++import signal
+ from subprocess import *
+ import StringIO
+ import time
+@@ -101,6 +102,8 @@
+
+ STOPPED_DUE_TO_EXC_BAD_ACCESS = "Process should be stopped due to bad access exception"
+
++STOPPED_DUE_TO_ASSERT = "Process should be stopped due to an assertion"
++
+ STOPPED_DUE_TO_BREAKPOINT = "Process should be stopped due to breakpoint"
+
+ STOPPED_DUE_TO_BREAKPOINT_WITH_STOP_REASON_AS = "%s, %s" % (
+@@ -368,7 +371,7 @@
+ wrapper.__dwarf_test__ = True
+ return wrapper
+
+-def expectedFailureGcc(bugnumber=None):
++def expectedFailureGcc(bugnumber=None, compiler_version=["=", None]):
+ if callable(bugnumber):
+ @wraps(bugnumber)
+ def expectedFailureGcc_easy_wrapper(*args, **kwargs):
+@@ -378,7 +381,7 @@
+ try:
+ bugnumber(*args, **kwargs)
+ except Exception:
+- if "gcc" in test_compiler:
++ if "gcc" in test_compiler and self.expectedCompilerVersion(compiler_version):
+ raise case._ExpectedFailure(sys.exc_info(),None)
+ else:
+ raise
+@@ -395,7 +398,7 @@
+ try:
+ func(*args, **kwargs)
+ except Exception:
+- if "gcc" in test_compiler:
++ if "gcc" in test_compiler and self.expectedCompilerVersion(compiler_version):
+ raise case._ExpectedFailure(sys.exc_info(),bugnumber)
+ else:
+ raise
+@@ -513,7 +516,7 @@
+ return wrapper
+ return expectedFailurei386_impl
+
+-def expectedFailureLinux(bugnumber=None):
++def expectedFailureLinux(bugnumber=None, compilers=None):
+ if callable(bugnumber):
+ @wraps(bugnumber)
+ def expectedFailureLinux_easy_wrapper(*args, **kwargs):
+@@ -523,11 +526,11 @@
+ try:
+ bugnumber(*args, **kwargs)
+ except Exception:
+- if "linux" in platform:
++ if "linux" in platform and self.expectedCompiler(compilers):
+ raise case._ExpectedFailure(sys.exc_info(),None)
+ else:
+ raise
+- if "linux" in platform:
++ if "linux" in platform and self.expectedCompiler(compilers):
+ raise case._UnexpectedSuccess(sys.exc_info(),None)
+ return expectedFailureLinux_easy_wrapper
+ else:
+@@ -540,11 +543,11 @@
+ try:
+ func(*args, **kwargs)
+ except Exception:
+- if "linux" in platform:
++ if "linux" in platform and self.expectedCompiler(compilers):
+ raise case._ExpectedFailure(sys.exc_info(),bugnumber)
+ else:
+ raise
+- if "linux" in platform:
++ if "linux" in platform and self.expectedCompiler(compilers):
+ raise case._UnexpectedSuccess(sys.exc_info(),bugnumber)
+ return wrapper
+ return expectedFailureLinux_impl
+@@ -818,6 +821,9 @@
+ # List of spawned subproces.Popen objects
+ self.subprocesses = []
+
++ # List of forked process PIDs
++ self.forkedProcessPids = []
++
+ # Create a string buffer to record the session info, to be dumped into a
+ # test case specific file if test failure is encountered.
+ self.session = StringIO.StringIO()
+@@ -884,6 +890,10 @@
+ p.terminate()
+ del p
+ del self.subprocesses[:]
++ # Ensure any forked processes are cleaned up
++ for pid in self.forkedProcessPids:
++ if os.path.exists("/proc/" + str(pid)):
++ os.kill(pid, signal.SIGTERM)
+
+ def spawnSubprocess(self, executable, args=[]):
+ """ Creates a subprocess.Popen object with the specified executable and arguments,
+@@ -902,6 +912,29 @@
+ self.subprocesses.append(proc)
+ return proc
+
++ def forkSubprocess(self, executable, args=[]):
++ """ Fork a subprocess with its own group ID.
++ NOTE: if using this function, ensure you also call:
++
++ self.addTearDownHook(self.cleanupSubprocesses)
++
++ otherwise the test suite will leak processes.
++ """
++ child_pid = os.fork()
++ if child_pid == 0:
++ # If more I/O support is required, this can be beefed up.
++ fd = os.open(os.devnull, os.O_RDWR)
++ os.dup2(fd, 0)
++ os.dup2(fd, 1)
++ os.dup2(fd, 2)
++ # This call causes the child to have its of group ID
++ os.setpgid(0,0)
++ os.execvp(executable, [executable] + args)
++ # Give the child time to get through the execvp() call
++ time.sleep(0.1)
++ self.forkedProcessPids.append(child_pid)
++ return child_pid
++
+ def HideStdout(self):
+ """Hide output to stdout from the user.
+
+@@ -1149,6 +1182,42 @@
+ version = m.group(1)
+ return version
+
++ def expectedCompilerVersion(self, compiler_version):
++ """Returns True iff compiler_version[1] matches the current compiler version.
++ Use compiler_version[0] to specify the operator used to determine if a match has occurred.
++ Any operator other than the following defaults to an equality test:
++ '>', '>=', "=>", '<', '<=', '=<', '!=', "!" or 'not'
++ """
++ if (compiler_version == None):
++ return True
++ operator = str(compiler_version[0])
++ version = compiler_version[1]
++
++ if (version == None):
++ return True
++ if (operator == '>'):
++ return self.getCompilerVersion() > version
++ if (operator == '>=' or operator == '=>'):
++ return self.getCompilerVersion() >= version
++ if (operator == '<'):
++ return self.getCompilerVersion() < version
++ if (operator == '<=' or operator == '=<'):
++ return self.getCompilerVersion() <= version
++ if (operator == '!=' or operator == '!' or operator == 'not'):
++ return str(version) not in str(self.getCompilerVersion())
++ return str(version) in str(self.getCompilerVersion())
++
++ def expectedCompiler(self, compilers):
++ """Returns True iff any element of compilers is a sub-string of the current compiler."""
++ if (compilers == None):
++ return True
++
++ for compiler in compilers:
++ if compiler in self.getCompiler():
++ return True
++
++ return False
++
+ def getRunOptions(self):
+ """Command line option for -A and -C to run this test again, called from
+ self.dumpSessionInfo()."""
+@@ -1223,6 +1292,29 @@
+ if not module.buildDwarf(self, architecture, compiler, dictionary, clean):
+ raise Exception("Don't know how to build binary with dwarf")
+
++ def getBuildFlags(self, use_cpp11=True, use_pthreads=True):
++ """ Returns a dictionary (which can be provided to build* functions above) which
++ contains OS-specific build flags.
++ """
++ cflags = ""
++ if use_cpp11:
++ cflags += "-std="
++ if "gcc" in self.getCompiler() and "4.6" in self.getCompilerVersion():
++ cflags += "c++0x"
++ else:
++ cflags += "c++11"
++ if sys.platform.startswith("darwin"):
++ cflags += " -stdlib=libc++"
++ elif "clang" in self.getCompiler():
++ cflags += " -stdlib=libstdc++"
++
++ if use_pthreads:
++ ldflags = "-lpthread"
++
++ return {'CFLAGS_EXTRAS' : cflags,
++ 'LD_EXTRAS' : ldflags,
++ }
++
+ def cleanup(self, dictionary=None):
+ """Platform specific way to do cleanup after build."""
+ if lldb.skip_build_and_cleanup:
+Index: test/make/Makefile.rules
+===================================================================
+--- test/make/Makefile.rules (revision 183906)
++++ test/make/Makefile.rules (working copy)
+@@ -112,6 +112,17 @@
+ cxx_linker = $(if $(findstring clang,$(1)), $(subst clang,clang++,$(1)), $(if $(findstring icc,$(1)), $(subst icc,icpc,$(1)), $(if $(findstring llvm-gcc,$(1)), $(subst llvm-gcc,llvm-g++,$(1)), $(subst gcc,g++,$(1)))))
+
+ #----------------------------------------------------------------------
++# C++ standard library options
++#----------------------------------------------------------------------
++ifeq (1,$(USE_LIBSTDCPP))
++ # Clang requires an extra flag: -stdlib=libstdc++
++ ifneq (,$(findstring clang,$(CC)))
++ CFLAGS += -stdlib=libstdc++
++ LDFLAGS += -stdlib=libstdc++
++ endif
++endif
++
++#----------------------------------------------------------------------
+ # dylib settings
+ #----------------------------------------------------------------------
+ ifneq "$(strip $(DYLIB_C_SOURCES))" ""
+Index: test/lang/c/strings/TestCStrings.py
+===================================================================
+--- test/lang/c/strings/TestCStrings.py (revision 183906)
++++ test/lang/c/strings/TestCStrings.py (working copy)
+@@ -66,6 +66,9 @@
+ self.expect("p (int)strlen(\"\")",
+ substrs = ['(int) $', ' = 0'])
+
++ self.expect("expression !z",
++ substrs = ['false'])
++
+ if __name__ == '__main__':
+ import atexit
+ lldb.SBDebugger.Initialize()
+Index: test/lang/c/struct_types/TestStructTypes.py
+===================================================================
+--- test/lang/c/struct_types/TestStructTypes.py (revision 183906)
++++ test/lang/c/struct_types/TestStructTypes.py (working copy)
+@@ -89,8 +89,9 @@
+ DATA_TYPES_DISPLAYED_CORRECTLY,
+ substrs = ['padding[]']) # Once rdar://problem/12566646 is fixed, this should display correctly
+
++ self.expect("expression -- &pt == (struct point_tag*)0",
++ substrs = ['false'])
+
+-
+ if __name__ == '__main__':
+ import atexit
+ lldb.SBDebugger.Initialize()
+Index: test/lang/objc/objc-stepping/TestObjCStepping.py
+===================================================================
+--- test/lang/objc/objc-stepping/TestObjCStepping.py (revision 183906)
++++ test/lang/objc/objc-stepping/TestObjCStepping.py (working copy)
+@@ -94,7 +94,7 @@
+ self.assertTrue(mySource, "Found mySource local variable.")
+ mySource_isa = mySource.GetChildMemberWithName ("isa")
+ self.assertTrue(mySource_isa, "Found mySource->isa local variable.")
+- mySource_isa.GetValue ()
++ className = mySource_isa.GetSummary ()
+
+ if self.TraceOn():
+ print mySource_isa
+@@ -135,14 +135,13 @@
+
+ threads = lldbutil.continue_to_breakpoint (process, break3)
+ self.assertTrue (len(threads) == 1, "Continued to third breakpoint in main, our object should now be swizzled.")
+-
+- mySource_isa.GetValue ()
+- did_change = mySource_isa.GetValueDidChange ()
+
++ newClassName = mySource_isa.GetSummary ()
++
+ if self.TraceOn():
+ print mySource_isa
+
+- self.assertTrue (did_change, "The isa did indeed change, swizzled!")
++ self.assertTrue (newClassName != className, "The isa did indeed change, swizzled!")
+
+ # Now step in, that should leave us in the Source randomMethod:
+ thread = threads[0]
Added: www-releases/trunk/3.3/merge-lldb33.patch.sig
URL: http://llvm.org/viewvc/llvm-project/www-releases/trunk/3.3/merge-lldb33.patch.sig?rev=184289&view=auto
==============================================================================
Binary file - no diff available.
Propchange: www-releases/trunk/3.3/merge-lldb33.patch.sig
------------------------------------------------------------------------------
svn:mime-type = application/octet-stream
Modified: www-releases/trunk/download.html
URL: http://llvm.org/viewvc/llvm-project/www-releases/trunk/download.html?rev=184289&r1=184288&r2=184289&view=diff
==============================================================================
--- www-releases/trunk/download.html (original)
+++ www-releases/trunk/download.html Wed Jun 19 03:20:36 2013
@@ -31,15 +31,16 @@ next release.</p>
<p><b>Sources:</b></p>
<ul>
- <li><a href="3.3/cfe-3.3.src.tar.gz">Clang source code</a> (9.4M) <a href="3.3/cfe-3.3.src.tar.gz.sig">(.sig)</a>
- <li><a href="3.3/llvm-3.3.src.tar.gz">LLVM source code</a> (13.6M) <a href="3.3/llvm-3.3.src.tar.gz.sig">(.sig)</a>
- <li><a href="3.3/compiler-rt-3.3.src.tar.gz">Compiler RT source code</a> (1.5M) <a href="3.3/compiler-rt-3.3.src.tar.gz.sig">(.sig)</a>
- <li><a href="3.3/dragonegg-3.3.src.tar.gz">Dragonegg source code</a> (457K) <a href="3.3/dragonegg-3.3.src.tar.gz.sig">(.sig)</a>
- <li><a href="3.3/libcxx-3.3.src.tar.gz">LibC++ source code</a> (1.2M) <a href="3.3/libcxx-3.3.src.tar.gz.sig">(.sig)</a>
+ <li><a href="3.3/cfe-3.3.src.tar.gz">Clang source code</a> (9.4M) <a href="3.3/cfe-3.3.src.tar.gz.sig">(.sig)</a></li>
+ <li><a href="3.3/llvm-3.3.src.tar.gz">LLVM source code</a> (13.6M) <a href="3.3/llvm-3.3.src.tar.gz.sig">(.sig)</a></li>
+ <li><a href="3.3/compiler-rt-3.3.src.tar.gz">Compiler RT source code</a> (1.5M) <a href="3.3/compiler-rt-3.3.src.tar.gz.sig">(.sig)</a></li>
+ <li><a href="3.3/dragonegg-3.3.src.tar.gz">Dragonegg source code</a> (457K) <a href="3.3/dragonegg-3.3.src.tar.gz.sig">(.sig)</a></li>
+ <li><a href="3.3/libcxx-3.3.src.tar.gz">LibC++ source code</a> (1.2M) <a href="3.3/libcxx-3.3.src.tar.gz.sig">(.sig)</a></li>
<li><a href="3.3/lldb-3.3.src.tar.gz">LLDB source code</a> (3.5M) <a href="3.3/lldb-3.3.src.tar.gz.sig">(.sig)</a>
- <li><a href="3.3/polly-3.3.src.tar.gz">Polly source code</a><a href="3.3/polly-3.3.src.tar.gz.sig">(.sig)</a>
- <li><a href="3.3/clang-tools-extra-3.3.src.tar.gz">Clang Tools Extra source code</a> (108K) <a href="3.3/clang-tools-extra-3.3.src.tar.gz.sig">(.sig)</a>
- <li><a href="3.3/test-suite-3.3.src.tar.gz">LLVM Test Suite</a> (76M) <a href="3.3/test-suite-3.3.src.tar.gz.sig">(.sig)</a>
+ (<a href="3.3/merge-lldb33.patch">LLDB 3.3 patch</a> <a href="3.3/merge-lldb33.patch.sig">(.sig)</a>)</li>
+ <li><a href="3.3/polly-3.3.src.tar.gz">Polly source code</a><a href="3.3/polly-3.3.src.tar.gz.sig">(.sig)</a></li>
+ <li><a href="3.3/clang-tools-extra-3.3.src.tar.gz">Clang Tools Extra source code</a> (108K) <a href="3.3/clang-tools-extra-3.3.src.tar.gz.sig">(.sig)</a></li>
+ <li><a href="3.3/test-suite-3.3.src.tar.gz">LLVM Test Suite</a> (76M) <a href="3.3/test-suite-3.3.src.tar.gz.sig">(.sig)</a></li>
</ul>
<p><b>Pre-built Binaries:</b></p>
More information about the llvm-commits
mailing list