From f034231a6a1fd5d6395206c1651de8cd9402cca3 Mon Sep 17 00:00:00 2001
From: Ed Maste <emaste@FreeBSD.org>
Date: Fri, 23 Aug 2013 17:46:38 +0000
Subject: Import lldb as of SVN r188801

(A number of files not required for the FreeBSD build have been removed.)

Sponsored by:	DARPA, AFRL
---
 source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp    |   861 ++
 source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h      |   138 +
 source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp  |   977 ++
 source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h    |   139 +
 source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp  |  1288 ++
 source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h    |   138 +
 .../Disassembler/llvm/DisassemblerLLVMC.cpp        |   864 ++
 .../Plugins/Disassembler/llvm/DisassemblerLLVMC.h  |   166 +
 .../Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp |   177 +
 .../Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h   |   115 +
 .../DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp    |   336 +
 .../DynamicLoader/POSIX-DYLD/DYLDRendezvous.h      |   230 +
 .../POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp          |   481 +
 .../POSIX-DYLD/DynamicLoaderPOSIXDYLD.h            |   170 +
 .../DynamicLoader/Static/DynamicLoaderStatic.cpp   |   209 +
 .../DynamicLoader/Static/DynamicLoaderStatic.h     |    88 +
 .../Instruction/ARM/EmulateInstructionARM.cpp      | 13625 +++++++++++++++++++
 .../Instruction/ARM/EmulateInstructionARM.h        |   990 ++
 .../Plugins/Instruction/ARM/EmulationStateARM.cpp  |   406 +
 source/Plugins/Instruction/ARM/EmulationStateARM.h |   100 +
 .../ItaniumABI/ItaniumABILanguageRuntime.cpp       |   461 +
 .../ItaniumABI/ItaniumABILanguageRuntime.h         |   101 +
 .../BSD-Archive/ObjectContainerBSDArchive.cpp      |   585 +
 .../BSD-Archive/ObjectContainerBSDArchive.h        |   229 +
 source/Plugins/ObjectFile/ELF/ELFHeader.cpp        |   465 +
 source/Plugins/ObjectFile/ELF/ELFHeader.h          |   433 +
 source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp    |  1893 +++
 source/Plugins/ObjectFile/ELF/ObjectFileELF.h      |   333 +
 .../Python/OperatingSystemPython.cpp               |   417 +
 .../OperatingSystem/Python/OperatingSystemPython.h |   109 +
 .../Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp   |   648 +
 source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h  |   162 +
 .../gdb-server/PlatformRemoteGDBServer.cpp         |   418 +
 .../Platform/gdb-server/PlatformRemoteGDBServer.h  |   147 +
 source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp  |   132 +
 source/Plugins/Process/FreeBSD/ProcessFreeBSD.h    |    82 +
 source/Plugins/Process/FreeBSD/ProcessMonitor.cpp  |  1677 +++
 source/Plugins/Process/FreeBSD/ProcessMonitor.h    |   322 +
 source/Plugins/Process/POSIX/POSIXStopInfo.cpp     |    89 +
 source/Plugins/Process/POSIX/POSIXStopInfo.h       |   120 +
 source/Plugins/Process/POSIX/POSIXThread.cpp       |   578 +
 source/Plugins/Process/POSIX/POSIXThread.h         |   133 +
 source/Plugins/Process/POSIX/ProcessMessage.cpp    |   258 +
 source/Plugins/Process/POSIX/ProcessMessage.h      |   207 +
 source/Plugins/Process/POSIX/ProcessPOSIX.cpp      |   911 ++
 source/Plugins/Process/POSIX/ProcessPOSIX.h        |   211 +
 source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp   |   193 +
 source/Plugins/Process/POSIX/ProcessPOSIXLog.h     |   111 +
 .../POSIX/RegisterContextFreeBSD_x86_64.cpp        |   136 +
 .../Process/POSIX/RegisterContextFreeBSD_x86_64.h  |    32 +
 .../Process/POSIX/RegisterContextLinux_x86_64.cpp  |   180 +
 .../Process/POSIX/RegisterContextLinux_x86_64.h    |    32 +
 .../Plugins/Process/POSIX/RegisterContextPOSIX.h   |    70 +
 .../Plugins/Process/POSIX/RegisterContext_i386.cpp |   551 +
 .../Plugins/Process/POSIX/RegisterContext_i386.h   |   169 +
 source/Plugins/Process/POSIX/RegisterContext_x86.h |   110 +
 .../Process/POSIX/RegisterContext_x86_64.cpp       |  1563 +++
 .../Plugins/Process/POSIX/RegisterContext_x86_64.h |   347 +
 source/Plugins/Process/Utility/ARMDefines.h        |   110 +
 source/Plugins/Process/Utility/ARMUtils.h          |   394 +
 .../Process/Utility/DynamicRegisterInfo.cpp        |   279 +
 .../Plugins/Process/Utility/DynamicRegisterInfo.h  |    85 +
 .../Plugins/Process/Utility/InferiorCallPOSIX.cpp  |   274 +
 source/Plugins/Process/Utility/InferiorCallPOSIX.h |    43 +
 source/Plugins/Process/Utility/InstructionUtils.h  |   136 +
 .../Process/Utility/RegisterContextDarwin_arm.cpp  |  1226 ++
 .../Process/Utility/RegisterContextDarwin_arm.h    |   333 +
 .../Process/Utility/RegisterContextDarwin_i386.cpp |   980 ++
 .../Process/Utility/RegisterContextDarwin_i386.h   |   269 +
 .../Utility/RegisterContextDarwin_x86_64.cpp       |  1066 ++
 .../Process/Utility/RegisterContextDarwin_x86_64.h |   274 +
 .../Process/Utility/RegisterContextDummy.cpp       |   137 +
 .../Plugins/Process/Utility/RegisterContextDummy.h |    77 +
 .../Process/Utility/RegisterContextLLDB.cpp        |  1541 +++
 .../Plugins/Process/Utility/RegisterContextLLDB.h  |   212 +
 .../RegisterContextMacOSXFrameBackchain.cpp        |   206 +
 .../Utility/RegisterContextMacOSXFrameBackchain.h  |    77 +
 .../Process/Utility/RegisterContextMach_arm.cpp    |    87 +
 .../Process/Utility/RegisterContextMach_arm.h      |    56 +
 .../Process/Utility/RegisterContextMach_i386.cpp   |    72 +
 .../Process/Utility/RegisterContextMach_i386.h     |    49 +
 .../Process/Utility/RegisterContextMach_x86_64.cpp |    72 +
 .../Process/Utility/RegisterContextMach_x86_64.h   |    49 +
 .../Process/Utility/RegisterContextMemory.cpp      |   174 +
 .../Process/Utility/RegisterContextMemory.h        |   102 +
 .../Utility/RegisterContextThreadMemory.cpp        |   261 +
 .../Process/Utility/RegisterContextThreadMemory.h  |   114 +
 .../Process/Utility/StopInfoMachException.cpp      |   482 +
 .../Process/Utility/StopInfoMachException.h        |    77 +
 source/Plugins/Process/Utility/ThreadMemory.cpp    |   140 +
 source/Plugins/Process/Utility/ThreadMemory.h      |   152 +
 source/Plugins/Process/Utility/UnwindLLDB.cpp      |   322 +
 source/Plugins/Process/Utility/UnwindLLDB.h        |   125 +
 .../Process/Utility/UnwindMacOSXFrameBackchain.cpp |   275 +
 .../Process/Utility/UnwindMacOSXFrameBackchain.h   |    74 +
 source/Plugins/Process/elf-core/ProcessElfCore.cpp |   619 +
 source/Plugins/Process/elf-core/ProcessElfCore.h   |   171 +
 .../elf-core/RegisterContextCoreFreeBSD_x86_64.cpp |    68 +
 .../elf-core/RegisterContextCoreFreeBSD_x86_64.h   |    47 +
 .../elf-core/RegisterContextCoreLinux_x86_64.cpp   |    68 +
 .../elf-core/RegisterContextCoreLinux_x86_64.h     |    54 +
 source/Plugins/Process/elf-core/ThreadElfCore.cpp  |   176 +
 source/Plugins/Process/elf-core/ThreadElfCore.h    |   174 +
 .../Process/gdb-remote/GDBRemoteCommunication.cpp  |   643 +
 .../Process/gdb-remote/GDBRemoteCommunication.h    |   268 +
 .../gdb-remote/GDBRemoteCommunicationClient.cpp    |  2348 ++++
 .../gdb-remote/GDBRemoteCommunicationClient.h      |   430 +
 .../gdb-remote/GDBRemoteCommunicationServer.cpp    |   839 ++
 .../gdb-remote/GDBRemoteCommunicationServer.h      |   147 +
 .../gdb-remote/GDBRemoteRegisterContext.cpp        |   971 ++
 .../Process/gdb-remote/GDBRemoteRegisterContext.h  |   311 +
 .../Process/gdb-remote/ProcessGDBRemote.cpp        |  3291 +++++
 .../Plugins/Process/gdb-remote/ProcessGDBRemote.h  |   396 +
 .../Process/gdb-remote/ProcessGDBRemoteLog.cpp     |   196 +
 .../Process/gdb-remote/ProcessGDBRemoteLog.h       |    57 +
 .../Plugins/Process/gdb-remote/ThreadGDBRemote.cpp |   214 +
 .../Plugins/Process/gdb-remote/ThreadGDBRemote.h   |   107 +
 .../DWARF/DWARFAbbreviationDeclaration.cpp         |   211 +
 .../DWARF/DWARFAbbreviationDeclaration.h           |    81 +
 source/Plugins/SymbolFile/DWARF/DWARFAttribute.h   |    45 +
 .../Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp  |  1027 ++
 source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h |   210 +
 .../SymbolFile/DWARF/DWARFDIECollection.cpp        |    62 +
 .../Plugins/SymbolFile/DWARF/DWARFDIECollection.h  |    51 +
 .../Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.cpp  |   202 +
 source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.h |    74 +
 .../SymbolFile/DWARF/DWARFDebugArangeSet.cpp       |   274 +
 .../Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.h |    76 +
 .../Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp |   177 +
 .../Plugins/SymbolFile/DWARF/DWARFDebugAranges.h   |    94 +
 source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp |   797 ++
 source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h   |    89 +
 .../SymbolFile/DWARF/DWARFDebugInfoEntry.cpp       |  2317 ++++
 .../Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h |   457 +
 source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp |  1436 ++
 source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h   |   225 +
 .../Plugins/SymbolFile/DWARF/DWARFDebugMacinfo.cpp |    48 +
 .../Plugins/SymbolFile/DWARF/DWARFDebugMacinfo.h   |    29 +
 .../SymbolFile/DWARF/DWARFDebugMacinfoEntry.cpp    |   132 +
 .../SymbolFile/DWARF/DWARFDebugMacinfoEntry.h      |    57 +
 .../SymbolFile/DWARF/DWARFDebugPubnames.cpp        |   296 +
 .../Plugins/SymbolFile/DWARF/DWARFDebugPubnames.h  |    38 +
 .../SymbolFile/DWARF/DWARFDebugPubnamesSet.cpp     |   166 +
 .../SymbolFile/DWARF/DWARFDebugPubnamesSet.h       |    99 +
 .../Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp  |   192 +
 source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h |    46 +
 .../Plugins/SymbolFile/DWARF/DWARFDeclContext.cpp  |   104 +
 source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h |   109 +
 source/Plugins/SymbolFile/DWARF/DWARFDefines.cpp   |   497 +
 source/Plugins/SymbolFile/DWARF/DWARFDefines.h     |   116 +
 source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp |   599 +
 source/Plugins/SymbolFile/DWARF/DWARFFormValue.h   |    81 +
 .../SymbolFile/DWARF/DWARFLocationDescription.cpp  |   172 +
 .../SymbolFile/DWARF/DWARFLocationDescription.h    |    24 +
 .../Plugins/SymbolFile/DWARF/DWARFLocationList.cpp |    94 +
 .../Plugins/SymbolFile/DWARF/DWARFLocationList.h   |    34 +
 source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h  |   933 ++
 .../Plugins/SymbolFile/DWARF/LogChannelDWARF.cpp   |   232 +
 source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h  |    89 +
 source/Plugins/SymbolFile/DWARF/NameToDIE.cpp      |    87 +
 source/Plugins/SymbolFile/DWARF/NameToDIE.h        |    65 +
 .../Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp   |  7973 +++++++++++
 source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h  |   622 +
 .../SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp   |  1586 +++
 .../SymbolFile/DWARF/SymbolFileDWARFDebugMap.h     |   420 +
 .../SymbolFile/DWARF/UniqueDWARFASTType.cpp        |    94 +
 .../Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h  |   175 +
 .../Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp |   407 +
 .../Plugins/SymbolFile/Symtab/SymbolFileSymtab.h   |   142 +
 .../Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp   |   199 +
 source/Plugins/SymbolVendor/ELF/SymbolVendorELF.h  |    58 +
 .../InstEmulation/UnwindAssemblyInstEmulation.cpp  |   670 +
 .../InstEmulation/UnwindAssemblyInstEmulation.h    |   185 +
 .../UnwindAssembly/x86/UnwindAssembly-x86.cpp      |   973 ++
 .../UnwindAssembly/x86/UnwindAssembly-x86.h        |    73 +
 175 files changed, 83931 insertions(+)
 create mode 100644 source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp
 create mode 100644 source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h
 create mode 100644 source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp
 create mode 100644 source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h
 create mode 100644 source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp
 create mode 100644 source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h
 create mode 100644 source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp
 create mode 100644 source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h
 create mode 100644 source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp
 create mode 100644 source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h
 create mode 100644 source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
 create mode 100644 source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h
 create mode 100644 source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
 create mode 100644 source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h
 create mode 100644 source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.cpp
 create mode 100644 source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.h
 create mode 100644 source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
 create mode 100644 source/Plugins/Instruction/ARM/EmulateInstructionARM.h
 create mode 100644 source/Plugins/Instruction/ARM/EmulationStateARM.cpp
 create mode 100644 source/Plugins/Instruction/ARM/EmulationStateARM.h
 create mode 100644 source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
 create mode 100644 source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h
 create mode 100644 source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp
 create mode 100644 source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h
 create mode 100644 source/Plugins/ObjectFile/ELF/ELFHeader.cpp
 create mode 100644 source/Plugins/ObjectFile/ELF/ELFHeader.h
 create mode 100644 source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
 create mode 100644 source/Plugins/ObjectFile/ELF/ObjectFileELF.h
 create mode 100644 source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp
 create mode 100644 source/Plugins/OperatingSystem/Python/OperatingSystemPython.h
 create mode 100644 source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp
 create mode 100644 source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h
 create mode 100644 source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
 create mode 100644 source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h
 create mode 100644 source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp
 create mode 100644 source/Plugins/Process/FreeBSD/ProcessFreeBSD.h
 create mode 100644 source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
 create mode 100644 source/Plugins/Process/FreeBSD/ProcessMonitor.h
 create mode 100644 source/Plugins/Process/POSIX/POSIXStopInfo.cpp
 create mode 100644 source/Plugins/Process/POSIX/POSIXStopInfo.h
 create mode 100644 source/Plugins/Process/POSIX/POSIXThread.cpp
 create mode 100644 source/Plugins/Process/POSIX/POSIXThread.h
 create mode 100644 source/Plugins/Process/POSIX/ProcessMessage.cpp
 create mode 100644 source/Plugins/Process/POSIX/ProcessMessage.h
 create mode 100644 source/Plugins/Process/POSIX/ProcessPOSIX.cpp
 create mode 100644 source/Plugins/Process/POSIX/ProcessPOSIX.h
 create mode 100644 source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp
 create mode 100644 source/Plugins/Process/POSIX/ProcessPOSIXLog.h
 create mode 100644 source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.cpp
 create mode 100644 source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.h
 create mode 100644 source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.cpp
 create mode 100644 source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.h
 create mode 100644 source/Plugins/Process/POSIX/RegisterContextPOSIX.h
 create mode 100644 source/Plugins/Process/POSIX/RegisterContext_i386.cpp
 create mode 100644 source/Plugins/Process/POSIX/RegisterContext_i386.h
 create mode 100644 source/Plugins/Process/POSIX/RegisterContext_x86.h
 create mode 100644 source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp
 create mode 100644 source/Plugins/Process/POSIX/RegisterContext_x86_64.h
 create mode 100644 source/Plugins/Process/Utility/ARMDefines.h
 create mode 100644 source/Plugins/Process/Utility/ARMUtils.h
 create mode 100644 source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
 create mode 100644 source/Plugins/Process/Utility/DynamicRegisterInfo.h
 create mode 100644 source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
 create mode 100644 source/Plugins/Process/Utility/InferiorCallPOSIX.h
 create mode 100644 source/Plugins/Process/Utility/InstructionUtils.h
 create mode 100644 source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp
 create mode 100644 source/Plugins/Process/Utility/RegisterContextDarwin_arm.h
 create mode 100644 source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp
 create mode 100644 source/Plugins/Process/Utility/RegisterContextDarwin_i386.h
 create mode 100644 source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp
 create mode 100644 source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.h
 create mode 100644 source/Plugins/Process/Utility/RegisterContextDummy.cpp
 create mode 100644 source/Plugins/Process/Utility/RegisterContextDummy.h
 create mode 100644 source/Plugins/Process/Utility/RegisterContextLLDB.cpp
 create mode 100644 source/Plugins/Process/Utility/RegisterContextLLDB.h
 create mode 100644 source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp
 create mode 100644 source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.h
 create mode 100644 source/Plugins/Process/Utility/RegisterContextMach_arm.cpp
 create mode 100644 source/Plugins/Process/Utility/RegisterContextMach_arm.h
 create mode 100644 source/Plugins/Process/Utility/RegisterContextMach_i386.cpp
 create mode 100644 source/Plugins/Process/Utility/RegisterContextMach_i386.h
 create mode 100644 source/Plugins/Process/Utility/RegisterContextMach_x86_64.cpp
 create mode 100644 source/Plugins/Process/Utility/RegisterContextMach_x86_64.h
 create mode 100644 source/Plugins/Process/Utility/RegisterContextMemory.cpp
 create mode 100644 source/Plugins/Process/Utility/RegisterContextMemory.h
 create mode 100644 source/Plugins/Process/Utility/RegisterContextThreadMemory.cpp
 create mode 100644 source/Plugins/Process/Utility/RegisterContextThreadMemory.h
 create mode 100644 source/Plugins/Process/Utility/StopInfoMachException.cpp
 create mode 100644 source/Plugins/Process/Utility/StopInfoMachException.h
 create mode 100644 source/Plugins/Process/Utility/ThreadMemory.cpp
 create mode 100644 source/Plugins/Process/Utility/ThreadMemory.h
 create mode 100644 source/Plugins/Process/Utility/UnwindLLDB.cpp
 create mode 100644 source/Plugins/Process/Utility/UnwindLLDB.h
 create mode 100644 source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp
 create mode 100644 source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.h
 create mode 100644 source/Plugins/Process/elf-core/ProcessElfCore.cpp
 create mode 100644 source/Plugins/Process/elf-core/ProcessElfCore.h
 create mode 100644 source/Plugins/Process/elf-core/RegisterContextCoreFreeBSD_x86_64.cpp
 create mode 100644 source/Plugins/Process/elf-core/RegisterContextCoreFreeBSD_x86_64.h
 create mode 100644 source/Plugins/Process/elf-core/RegisterContextCoreLinux_x86_64.cpp
 create mode 100644 source/Plugins/Process/elf-core/RegisterContextCoreLinux_x86_64.h
 create mode 100644 source/Plugins/Process/elf-core/ThreadElfCore.cpp
 create mode 100644 source/Plugins/Process/elf-core/ThreadElfCore.h
 create mode 100644 source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
 create mode 100644 source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
 create mode 100644 source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
 create mode 100644 source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
 create mode 100644 source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
 create mode 100644 source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
 create mode 100644 source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
 create mode 100644 source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
 create mode 100644 source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
 create mode 100644 source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
 create mode 100644 source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.cpp
 create mode 100644 source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h
 create mode 100644 source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
 create mode 100644 source/Plugins/Process/gdb-remote/ThreadGDBRemote.h
 create mode 100644 source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp
 create mode 100644 source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.h
 create mode 100644 source/Plugins/SymbolFile/DWARF/DWARFAttribute.h
 create mode 100644 source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
 create mode 100644 source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h
 create mode 100644 source/Plugins/SymbolFile/DWARF/DWARFDIECollection.cpp
 create mode 100644 source/Plugins/SymbolFile/DWARF/DWARFDIECollection.h
 create mode 100644 source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.cpp
 create mode 100644 source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.h
 create mode 100644 source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.cpp
 create mode 100644 source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.h
 create mode 100644 source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp
 create mode 100644 source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.h
 create mode 100644 source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
 create mode 100644 source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h
 create mode 100644 source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
 create mode 100644 source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h
 create mode 100644 source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp
 create mode 100644 source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h
 create mode 100644 source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfo.cpp
 create mode 100644 source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfo.h
 create mode 100644 source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfoEntry.cpp
 create mode 100644 source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfoEntry.h
 create mode 100644 source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp
 create mode 100644 source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.h
 create mode 100644 source/Plugins/SymbolFile/DWARF/DWARFDebugPubnamesSet.cpp
 create mode 100644 source/Plugins/SymbolFile/DWARF/DWARFDebugPubnamesSet.h
 create mode 100644 source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp
 create mode 100644 source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h
 create mode 100644 source/Plugins/SymbolFile/DWARF/DWARFDeclContext.cpp
 create mode 100644 source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h
 create mode 100644 source/Plugins/SymbolFile/DWARF/DWARFDefines.cpp
 create mode 100644 source/Plugins/SymbolFile/DWARF/DWARFDefines.h
 create mode 100644 source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
 create mode 100644 source/Plugins/SymbolFile/DWARF/DWARFFormValue.h
 create mode 100644 source/Plugins/SymbolFile/DWARF/DWARFLocationDescription.cpp
 create mode 100644 source/Plugins/SymbolFile/DWARF/DWARFLocationDescription.h
 create mode 100644 source/Plugins/SymbolFile/DWARF/DWARFLocationList.cpp
 create mode 100644 source/Plugins/SymbolFile/DWARF/DWARFLocationList.h
 create mode 100644 source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h
 create mode 100644 source/Plugins/SymbolFile/DWARF/LogChannelDWARF.cpp
 create mode 100644 source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h
 create mode 100644 source/Plugins/SymbolFile/DWARF/NameToDIE.cpp
 create mode 100644 source/Plugins/SymbolFile/DWARF/NameToDIE.h
 create mode 100644 source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
 create mode 100644 source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
 create mode 100644 source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
 create mode 100644 source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
 create mode 100644 source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp
 create mode 100644 source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h
 create mode 100644 source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp
 create mode 100644 source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h
 create mode 100644 source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp
 create mode 100644 source/Plugins/SymbolVendor/ELF/SymbolVendorELF.h
 create mode 100644 source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
 create mode 100644 source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h
 create mode 100644 source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp
 create mode 100644 source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.h

(limited to 'source/Plugins')

diff --git a/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp
new file mode 100644
index 000000000000..4685c3e759e0
--- /dev/null
+++ b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.cpp
@@ -0,0 +1,861 @@
+//===-- ABIMacOSX_arm.cpp --------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ABIMacOSX_arm.h"
+
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/RegisterValue.h"
+#include "lldb/Core/Scalar.h"
+#include "lldb/Core/Value.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/UnwindPlan.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+
+#include "llvm/ADT/Triple.h"
+
+#include "Utility/ARM_DWARF_Registers.h"
+#include "Utility/ARM_GCC_Registers.h"
+#include "Plugins/Process/Utility/ARMDefines.h"
+
+#include <vector>
+
+using namespace lldb;
+using namespace lldb_private;
+
+static RegisterInfo g_register_infos[] =
+{
+    //  NAME       ALT       SZ OFF ENCODING         FORMAT          COMPILER                DWARF               GENERIC                     GDB                     LLDB NATIVE            VALUE REGS    INVALIDATE REGS
+    //  ========== =======   == === =============    ============    ======================= =================== =========================== ======================= ====================== ==========    ===============
+    {   "r0",      "arg1",    4, 0, eEncodingUint    , eFormatHex,   { gcc_r0,               dwarf_r0,           LLDB_REGNUM_GENERIC_ARG1,   gdb_arm_r0,             LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "r1",      "arg2",    4, 0, eEncodingUint    , eFormatHex,   { gcc_r1,               dwarf_r1,           LLDB_REGNUM_GENERIC_ARG2,   gdb_arm_r1,             LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "r2",      "arg3",    4, 0, eEncodingUint    , eFormatHex,   { gcc_r2,               dwarf_r2,           LLDB_REGNUM_GENERIC_ARG3,   gdb_arm_r2,             LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "r3",      "arg4",    4, 0, eEncodingUint    , eFormatHex,   { gcc_r3,               dwarf_r3,           LLDB_REGNUM_GENERIC_ARG4,   gdb_arm_r3,             LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "r4",      NULL,      4, 0, eEncodingUint    , eFormatHex,   { gcc_r4,               dwarf_r4,           LLDB_INVALID_REGNUM,        gdb_arm_r4,             LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "r5",      NULL,      4, 0, eEncodingUint    , eFormatHex,   { gcc_r5,               dwarf_r5,           LLDB_INVALID_REGNUM,        gdb_arm_r5,             LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "r6",      NULL,      4, 0, eEncodingUint    , eFormatHex,   { gcc_r6,               dwarf_r6,           LLDB_INVALID_REGNUM,        gdb_arm_r6,             LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "r7",      NULL,      4, 0, eEncodingUint    , eFormatHex,   { gcc_r7,               dwarf_r7,           LLDB_REGNUM_GENERIC_FP,     gdb_arm_r7,             LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "r8",      NULL,      4, 0, eEncodingUint    , eFormatHex,   { gcc_r8,               dwarf_r8,           LLDB_INVALID_REGNUM,        gdb_arm_r8,             LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "r9",      NULL,      4, 0, eEncodingUint    , eFormatHex,   { gcc_r9,               dwarf_r9,           LLDB_INVALID_REGNUM,        gdb_arm_r9,             LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "r10",     NULL,      4, 0, eEncodingUint    , eFormatHex,   { gcc_r10,              dwarf_r10,          LLDB_INVALID_REGNUM,        gdb_arm_r10,            LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "r11",     NULL,      4, 0, eEncodingUint    , eFormatHex,   { gcc_r11,              dwarf_r11,          LLDB_INVALID_REGNUM,        gdb_arm_r11,            LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "r12",     NULL,      4, 0, eEncodingUint    , eFormatHex,   { gcc_r12,              dwarf_r12,          LLDB_INVALID_REGNUM,        gdb_arm_r12,            LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "sp",      "r13",     4, 0, eEncodingUint    , eFormatHex,   { gcc_sp,               dwarf_sp,           LLDB_REGNUM_GENERIC_SP,     gdb_arm_sp,             LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "lr",      "r14",     4, 0, eEncodingUint    , eFormatHex,   { gcc_lr,               dwarf_lr,           LLDB_REGNUM_GENERIC_RA,     gdb_arm_lr,             LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "pc",      "r15",     4, 0, eEncodingUint    , eFormatHex,   { gcc_pc,               dwarf_pc,           LLDB_REGNUM_GENERIC_PC,     gdb_arm_pc,             LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "cpsr",    "psr",     4, 0, eEncodingUint    , eFormatHex,   { gcc_cpsr,             dwarf_cpsr,         LLDB_REGNUM_GENERIC_FLAGS,  gdb_arm_cpsr,           LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "s0",      NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s0,           LLDB_INVALID_REGNUM,        gdb_arm_s0,             LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "s1",      NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s1,           LLDB_INVALID_REGNUM,        gdb_arm_s1,             LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "s2",      NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s2,           LLDB_INVALID_REGNUM,        gdb_arm_s2,             LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "s3",      NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s3,           LLDB_INVALID_REGNUM,        gdb_arm_s3,             LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "s4",      NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s4,           LLDB_INVALID_REGNUM,        gdb_arm_s4,             LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "s5",      NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s5,           LLDB_INVALID_REGNUM,        gdb_arm_s5,             LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "s6",      NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s6,           LLDB_INVALID_REGNUM,        gdb_arm_s6,             LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "s7",      NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s7,           LLDB_INVALID_REGNUM,        gdb_arm_s7,             LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "s8",      NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s8,           LLDB_INVALID_REGNUM,        gdb_arm_s8,             LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "s9",      NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s9,           LLDB_INVALID_REGNUM,        gdb_arm_s9,             LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "s10",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s10,          LLDB_INVALID_REGNUM,        gdb_arm_s10,            LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "s11",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s11,          LLDB_INVALID_REGNUM,        gdb_arm_s11,            LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "s12",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s12,          LLDB_INVALID_REGNUM,        gdb_arm_s12,            LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "s13",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s13,          LLDB_INVALID_REGNUM,        gdb_arm_s13,            LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "s14",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s14,          LLDB_INVALID_REGNUM,        gdb_arm_s14,            LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "s15",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s15,          LLDB_INVALID_REGNUM,        gdb_arm_s15,            LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "s16",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s16,          LLDB_INVALID_REGNUM,        gdb_arm_s16,            LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "s17",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s17,          LLDB_INVALID_REGNUM,        gdb_arm_s17,            LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "s18",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s18,          LLDB_INVALID_REGNUM,        gdb_arm_s18,            LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "s19",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s19,          LLDB_INVALID_REGNUM,        gdb_arm_s19,            LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "s20",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s20,          LLDB_INVALID_REGNUM,        gdb_arm_s20,            LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "s21",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s21,          LLDB_INVALID_REGNUM,        gdb_arm_s21,            LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "s22",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s22,          LLDB_INVALID_REGNUM,        gdb_arm_s22,            LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "s23",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s23,          LLDB_INVALID_REGNUM,        gdb_arm_s23,            LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "s24",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s24,          LLDB_INVALID_REGNUM,        gdb_arm_s24,            LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "s25",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s25,          LLDB_INVALID_REGNUM,        gdb_arm_s25,            LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "s26",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s26,          LLDB_INVALID_REGNUM,        gdb_arm_s26,            LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "s27",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s27,          LLDB_INVALID_REGNUM,        gdb_arm_s27,            LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "s28",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s28,          LLDB_INVALID_REGNUM,        gdb_arm_s28,            LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "s29",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s29,          LLDB_INVALID_REGNUM,        gdb_arm_s29,            LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "s30",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s30,          LLDB_INVALID_REGNUM,        gdb_arm_s30,            LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "s31",     NULL,      4, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_s31,          LLDB_INVALID_REGNUM,        gdb_arm_s31,            LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "fpscr",   NULL,      4, 0, eEncodingUint    , eFormatHex  , { LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM,        gdb_arm_fpscr,          LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "d0",      NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d0,           LLDB_INVALID_REGNUM,        gdb_arm_d0,             LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "d1",      NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d1,           LLDB_INVALID_REGNUM,        gdb_arm_d1,             LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "d2",      NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d2,           LLDB_INVALID_REGNUM,        gdb_arm_d2,             LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "d3",      NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d3,           LLDB_INVALID_REGNUM,        gdb_arm_d3,             LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "d4",      NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d4,           LLDB_INVALID_REGNUM,        gdb_arm_d4,             LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "d5",      NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d5,           LLDB_INVALID_REGNUM,        gdb_arm_d5,             LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "d6",      NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d6,           LLDB_INVALID_REGNUM,        gdb_arm_d6,             LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "d7",      NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d7,           LLDB_INVALID_REGNUM,        gdb_arm_d7,             LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "d8",      NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d8,           LLDB_INVALID_REGNUM,        gdb_arm_d8,             LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "d9",      NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d9,           LLDB_INVALID_REGNUM,        gdb_arm_d9,             LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "d10",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d10,          LLDB_INVALID_REGNUM,        gdb_arm_d10,            LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "d11",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d11,          LLDB_INVALID_REGNUM,        gdb_arm_d11,            LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "d12",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d12,          LLDB_INVALID_REGNUM,        gdb_arm_d12,            LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "d13",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d13,          LLDB_INVALID_REGNUM,        gdb_arm_d13,            LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "d14",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d14,          LLDB_INVALID_REGNUM,        gdb_arm_d14,            LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "d15",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d15,          LLDB_INVALID_REGNUM,        gdb_arm_d15,            LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "d16",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d16,          LLDB_INVALID_REGNUM,        gdb_arm_d16,            LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "d17",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d17,          LLDB_INVALID_REGNUM,        gdb_arm_d17,            LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "d18",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d18,          LLDB_INVALID_REGNUM,        gdb_arm_d18,            LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "d19",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d19,          LLDB_INVALID_REGNUM,        gdb_arm_d19,            LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "d20",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d20,          LLDB_INVALID_REGNUM,        gdb_arm_d20,            LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "d21",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d21,          LLDB_INVALID_REGNUM,        gdb_arm_d21,            LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "d22",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d22,          LLDB_INVALID_REGNUM,        gdb_arm_d22,            LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "d23",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d23,          LLDB_INVALID_REGNUM,        gdb_arm_d23,            LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "d24",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d24,          LLDB_INVALID_REGNUM,        gdb_arm_d24,            LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "d25",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d25,          LLDB_INVALID_REGNUM,        gdb_arm_d25,            LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "d26",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d26,          LLDB_INVALID_REGNUM,        gdb_arm_d26,            LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "d27",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d27,          LLDB_INVALID_REGNUM,        gdb_arm_d27,            LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "d28",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d28,          LLDB_INVALID_REGNUM,        gdb_arm_d28,            LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "d29",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d29,          LLDB_INVALID_REGNUM,        gdb_arm_d29,            LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "d30",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d30,          LLDB_INVALID_REGNUM,        gdb_arm_d30,            LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "d31",     NULL,      8, 0, eEncodingIEEE754 , eFormatFloat, { LLDB_INVALID_REGNUM,  dwarf_d31,          LLDB_INVALID_REGNUM,        gdb_arm_d31,            LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "r8_usr",  NULL,      4, 0, eEncodingUint    , eFormatHex,   { LLDB_INVALID_REGNUM,  dwarf_r8_usr,       LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "r9_usr",  NULL,      4, 0, eEncodingUint    , eFormatHex,   { LLDB_INVALID_REGNUM,  dwarf_r9_usr,       LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "r10_usr", NULL,      4, 0, eEncodingUint    , eFormatHex,   { LLDB_INVALID_REGNUM,  dwarf_r10_usr,      LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "r11_usr", NULL,      4, 0, eEncodingUint    , eFormatHex,   { LLDB_INVALID_REGNUM,  dwarf_r11_usr,      LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "r12_usr", NULL,      4, 0, eEncodingUint    , eFormatHex,   { LLDB_INVALID_REGNUM,  dwarf_r12_usr,      LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "r13_usr", "sp_usr",  4, 0, eEncodingUint    , eFormatHex,   { LLDB_INVALID_REGNUM,  dwarf_r13_usr,      LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "r14_usr", "lr_usr",  4, 0, eEncodingUint    , eFormatHex,   { LLDB_INVALID_REGNUM,  dwarf_r14_usr,      LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "r8_fiq",  NULL,      4, 0, eEncodingUint    , eFormatHex,   { LLDB_INVALID_REGNUM,  dwarf_r8_fiq,       LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "r9_fiq",  NULL,      4, 0, eEncodingUint    , eFormatHex,   { LLDB_INVALID_REGNUM,  dwarf_r9_fiq,       LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "r10_fiq", NULL,      4, 0, eEncodingUint    , eFormatHex,   { LLDB_INVALID_REGNUM,  dwarf_r10_fiq,      LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "r11_fiq", NULL,      4, 0, eEncodingUint    , eFormatHex,   { LLDB_INVALID_REGNUM,  dwarf_r11_fiq,      LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "r12_fiq", NULL,      4, 0, eEncodingUint    , eFormatHex,   { LLDB_INVALID_REGNUM,  dwarf_r12_fiq,      LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "r13_fiq", "sp_fiq",  4, 0, eEncodingUint    , eFormatHex,   { LLDB_INVALID_REGNUM,  dwarf_r13_fiq,      LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "r14_fiq", "lr_fiq",  4, 0, eEncodingUint    , eFormatHex,   { LLDB_INVALID_REGNUM,  dwarf_r14_fiq,      LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "r13_irq", "sp_irq",  4, 0, eEncodingUint    , eFormatHex,   { LLDB_INVALID_REGNUM,  dwarf_r13_irq,      LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "r14_irq", "lr_irq",  4, 0, eEncodingUint    , eFormatHex,   { LLDB_INVALID_REGNUM,  dwarf_r14_irq,      LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "r13_abt", "sp_abt",  4, 0, eEncodingUint    , eFormatHex,   { LLDB_INVALID_REGNUM,  dwarf_r13_abt,      LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "r14_abt", "lr_abt",  4, 0, eEncodingUint    , eFormatHex,   { LLDB_INVALID_REGNUM,  dwarf_r14_abt,      LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "r13_und", "sp_und",  4, 0, eEncodingUint    , eFormatHex,   { LLDB_INVALID_REGNUM,  dwarf_r13_und,      LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "r14_und", "lr_und",  4, 0, eEncodingUint    , eFormatHex,   { LLDB_INVALID_REGNUM,  dwarf_r14_und,      LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "r13_svc", "sp_svc",  4, 0, eEncodingUint    , eFormatHex,   { LLDB_INVALID_REGNUM,  dwarf_r13_svc,      LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL},
+    {   "r14_svc", "lr_svc",  4, 0, eEncodingUint    , eFormatHex,   { LLDB_INVALID_REGNUM,  dwarf_r14_svc,      LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    LLDB_INVALID_REGNUM },      NULL,              NULL}
+};
+static const uint32_t k_num_register_infos = sizeof(g_register_infos)/sizeof(RegisterInfo);
+static bool g_register_info_names_constified = false;
+
+const lldb_private::RegisterInfo *
+ABIMacOSX_arm::GetRegisterInfoArray (uint32_t &count)
+{
+    // Make the C-string names and alt_names for the register infos into const 
+    // C-string values by having the ConstString unique the names in the global
+    // constant C-string pool.
+    if (!g_register_info_names_constified)
+    {
+        g_register_info_names_constified = true;
+        for (uint32_t i=0; i<k_num_register_infos; ++i)
+        {
+            if (g_register_infos[i].name)
+                g_register_infos[i].name = ConstString(g_register_infos[i].name).GetCString();
+            if (g_register_infos[i].alt_name)
+                g_register_infos[i].alt_name = ConstString(g_register_infos[i].alt_name).GetCString();
+        }
+    }
+    count = k_num_register_infos;
+    return g_register_infos;
+}
+
+
+size_t
+ABIMacOSX_arm::GetRedZoneSize () const
+{
+    return 0;
+}
+
+//------------------------------------------------------------------
+// Static Functions
+//------------------------------------------------------------------
+ABISP
+ABIMacOSX_arm::CreateInstance (const ArchSpec &arch)
+{
+    static ABISP g_abi_sp;
+    const llvm::Triple::ArchType arch_type = arch.GetTriple().getArch();
+    if ((arch_type == llvm::Triple::arm) ||
+        (arch_type == llvm::Triple::thumb))
+    {
+        if (!g_abi_sp)
+            g_abi_sp.reset (new ABIMacOSX_arm);
+        return g_abi_sp;
+    }
+    return ABISP();
+}
+
+bool
+ABIMacOSX_arm::PrepareTrivialCall (Thread &thread, 
+                                   addr_t sp, 
+                                   addr_t function_addr, 
+                                   addr_t return_addr, 
+                                   addr_t *arg1_ptr,
+                                   addr_t *arg2_ptr,
+                                   addr_t *arg3_ptr,
+                                   addr_t *arg4_ptr,
+                                   addr_t *arg5_ptr,
+                                   addr_t *arg6_ptr) const
+{
+    RegisterContext *reg_ctx = thread.GetRegisterContext().get();
+    if (!reg_ctx)
+        return false;    
+
+    const uint32_t pc_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
+    const uint32_t sp_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
+    const uint32_t ra_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA);
+
+    RegisterValue reg_value;
+
+    if (arg1_ptr)
+    {
+        reg_value.SetUInt32(*arg1_ptr);
+        if (!reg_ctx->WriteRegister (reg_ctx->GetRegisterInfoByName("r0"), reg_value))
+            return false;
+
+        if (arg2_ptr)
+        {
+            reg_value.SetUInt32(*arg2_ptr);
+            if (!reg_ctx->WriteRegister (reg_ctx->GetRegisterInfoByName("r1"), reg_value))
+                return false;
+
+            if (arg3_ptr)
+            {
+                reg_value.SetUInt32(*arg3_ptr);
+                if (!reg_ctx->WriteRegister (reg_ctx->GetRegisterInfoByName("r2"), reg_value))
+                    return false;
+                if (arg4_ptr)
+                {
+                    reg_value.SetUInt32(*arg4_ptr);
+                    const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName("r3");
+                    if (!reg_ctx->WriteRegister (reg_info, reg_value))
+                        return false;
+                    if (arg5_ptr)
+                    {
+                        // Keep the stack 8 byte aligned, not that we need to
+                        sp -= 8;
+                        sp &= ~(8ull-1ull);
+                        reg_value.SetUInt32(*arg5_ptr);
+                        if (reg_ctx->WriteRegisterValueToMemory (reg_info, sp, reg_info->byte_size, reg_value).Fail())
+                            return false;
+                        if (arg6_ptr)
+                        {
+                            reg_value.SetUInt32(*arg6_ptr);
+                            if (reg_ctx->WriteRegisterValueToMemory (reg_info, sp + 4, reg_info->byte_size, reg_value).Fail())
+                                return false;
+                        }
+                    }
+                }
+            }            
+        }
+    }
+    
+
+    TargetSP target_sp (thread.CalculateTarget());
+    Address so_addr;
+
+    // Figure out if our return address is ARM or Thumb by using the 
+    // Address::GetCallableLoadAddress(Target*) which will figure out the ARM
+    // thumb-ness and set the correct address bits for us.
+    so_addr.SetLoadAddress (return_addr, target_sp.get());
+    return_addr = so_addr.GetCallableLoadAddress (target_sp.get());
+
+    // Set "lr" to the return address
+    if (!reg_ctx->WriteRegisterFromUnsigned (ra_reg_num, return_addr))
+        return false;
+
+    // Set "sp" to the requested value
+    if (!reg_ctx->WriteRegisterFromUnsigned (sp_reg_num, sp))
+        return false;
+    
+    // If bit zero or 1 is set, this must be a thumb function, no need to figure
+    // this out from the symbols.
+    so_addr.SetLoadAddress (function_addr, target_sp.get());
+    function_addr = so_addr.GetCallableLoadAddress (target_sp.get());
+    
+    const RegisterInfo *cpsr_reg_info = reg_ctx->GetRegisterInfoByName("cpsr");
+    const uint32_t curr_cpsr = reg_ctx->ReadRegisterAsUnsigned(cpsr_reg_info, 0);
+
+    // Make a new CPSR and mask out any Thumb IT (if/then) bits
+    uint32_t new_cpsr = curr_cpsr & ~MASK_CPSR_IT_MASK;
+    // If bit zero or 1 is set, this must be thumb...
+    if (function_addr & 1ull)
+        new_cpsr |= MASK_CPSR_T;    // Set T bit in CPSR
+    else
+        new_cpsr &= ~MASK_CPSR_T;   // Clear T bit in CPSR
+
+    if (new_cpsr != curr_cpsr)
+    {
+        if (!reg_ctx->WriteRegisterFromUnsigned (cpsr_reg_info, new_cpsr))
+            return false;
+    }
+
+    function_addr &= ~1ull;   // clear bit zero since the CPSR will take care of the mode for us
+    
+    // Set "pc" to the address requested
+    if (!reg_ctx->WriteRegisterFromUnsigned (pc_reg_num, function_addr))
+        return false;
+
+    return true;
+}
+
+bool
+ABIMacOSX_arm::GetArgumentValues (Thread &thread,
+                                  ValueList &values) const
+{
+    uint32_t num_values = values.GetSize();
+    
+    
+    ExecutionContext exe_ctx (thread.shared_from_this());
+    // For now, assume that the types in the AST values come from the Target's 
+    // scratch AST.    
+    
+    // Extract the register context so we can read arguments from registers
+    
+    RegisterContext *reg_ctx = thread.GetRegisterContext().get();
+    
+    if (!reg_ctx)
+        return false;
+        
+    addr_t sp = 0;
+
+    for (uint32_t value_idx = 0; value_idx < num_values; ++value_idx)
+    {
+        // We currently only support extracting values with Clang QualTypes.
+        // Do we care about others?
+        Value *value = values.GetValueAtIndex(value_idx);
+        
+        if (!value)
+            return false;
+        
+        ClangASTType clang_type = value->GetClangType();
+        if (clang_type)
+        {
+            bool is_signed = false;
+            size_t bit_width = 0;
+            if (clang_type.IsIntegerType (is_signed))
+            {
+                bit_width = clang_type.GetBitSize();
+            }
+            else if (clang_type.IsPointerOrReferenceType ())
+            {
+                bit_width = clang_type.GetBitSize();
+            }
+            else
+            {
+                // We only handle integer, pointer and reference types currently...
+                return false;
+            }
+            
+            if (bit_width <= (exe_ctx.GetProcessRef().GetAddressByteSize() * 8))
+            {
+                if (value_idx < 4)
+                {
+                    // Arguments 1-4 are in r0-r3...
+                    const RegisterInfo *arg_reg_info = NULL;
+                    // Search by generic ID first, then fall back to by name
+                    uint32_t arg_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + value_idx);
+                    if (arg_reg_num != LLDB_INVALID_REGNUM)
+                    {
+                        arg_reg_info = reg_ctx->GetRegisterInfoAtIndex(arg_reg_num);
+                    }
+                    else
+                    {
+                        switch (value_idx)
+                        {
+                            case 0: arg_reg_info = reg_ctx->GetRegisterInfoByName("r0"); break;
+                            case 1: arg_reg_info = reg_ctx->GetRegisterInfoByName("r1"); break;
+                            case 2: arg_reg_info = reg_ctx->GetRegisterInfoByName("r2"); break;
+                            case 3: arg_reg_info = reg_ctx->GetRegisterInfoByName("r3"); break;
+                        }
+                    }
+
+                    if (arg_reg_info)
+                    {
+                        RegisterValue reg_value;
+                        
+                        if (reg_ctx->ReadRegister(arg_reg_info, reg_value))
+                        {
+                            if (is_signed)
+                                reg_value.SignExtend(bit_width);
+                            if (!reg_value.GetScalarValue(value->GetScalar()))
+                                return false;
+                            continue;
+                        }
+                    }
+                    return false;
+                }
+                else
+                {
+                    if (sp == 0)
+                    {
+                        // Read the stack pointer if it already hasn't been read
+                        sp = reg_ctx->GetSP(0);
+                        if (sp == 0)
+                            return false;
+                    }
+
+                    // Arguments 5 on up are on the stack
+                    const uint32_t arg_byte_size = (bit_width + (8-1)) / 8;
+                    Error error;
+                    if (!exe_ctx.GetProcessRef().ReadScalarIntegerFromMemory(sp, arg_byte_size, is_signed, value->GetScalar(), error))
+                        return false;
+
+                    sp += arg_byte_size;
+                }
+            }
+        }
+    }
+    return true;
+}
+
+ValueObjectSP
+ABIMacOSX_arm::GetReturnValueObjectImpl (Thread &thread,
+                                         lldb_private::ClangASTType &clang_type) const
+{
+    Value value;
+    ValueObjectSP return_valobj_sp;
+    
+    if (!clang_type)
+        return return_valobj_sp;
+    
+    clang::ASTContext *ast_context = clang_type.GetASTContext();
+    if (!ast_context)
+        return return_valobj_sp;
+
+    //value.SetContext (Value::eContextTypeClangType, clang_type.GetOpaqueQualType());
+    value.SetClangType (clang_type);
+            
+    RegisterContext *reg_ctx = thread.GetRegisterContext().get();
+    if (!reg_ctx)
+        return return_valobj_sp;
+        
+    bool is_signed;
+    
+    // Get the pointer to the first stack argument so we have a place to start 
+    // when reading data
+    
+    const RegisterInfo *r0_reg_info = reg_ctx->GetRegisterInfoByName("r0", 0);
+    if (clang_type.IsIntegerType (is_signed))
+    {
+        size_t bit_width = clang_type.GetBitSize();
+        
+        switch (bit_width)
+        {
+            default:
+                return return_valobj_sp;
+            case 64:
+            {
+                const RegisterInfo *r1_reg_info = reg_ctx->GetRegisterInfoByName("r1", 0);
+                uint64_t raw_value;
+                raw_value = reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX;
+                raw_value |= ((uint64_t)(reg_ctx->ReadRegisterAsUnsigned(r1_reg_info, 0) & UINT32_MAX)) << 32;
+                if (is_signed)
+                    value.GetScalar() = (int64_t)raw_value;
+                else
+                    value.GetScalar() = (uint64_t)raw_value;
+            }
+                break;
+            case 32:
+                if (is_signed)
+                    value.GetScalar() = (int32_t)(reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX);
+                else
+                    value.GetScalar() = (uint32_t)(reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX);
+                break;
+            case 16:
+                if (is_signed)
+                    value.GetScalar() = (int16_t)(reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT16_MAX);
+                else
+                    value.GetScalar() = (uint16_t)(reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT16_MAX);
+                break;
+            case 8:
+                if (is_signed)
+                    value.GetScalar() = (int8_t)(reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT8_MAX);
+                else
+                    value.GetScalar() = (uint8_t)(reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT8_MAX);
+                break;
+        }
+    }
+    else if (clang_type.IsPointerType ())
+    {
+        uint32_t ptr = thread.GetRegisterContext()->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX;
+        value.GetScalar() = ptr;
+    }
+    else
+    {
+        // not handled yet
+        return return_valobj_sp;
+    }
+    
+    // If we get here, we have a valid Value, so make our ValueObject out of it:
+    
+    return_valobj_sp = ValueObjectConstResult::Create(thread.GetStackFrameAtIndex(0).get(),
+                                                      value,
+                                                      ConstString(""));
+    return return_valobj_sp;
+}
+
+Error
+ABIMacOSX_arm::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value_sp)
+{
+    Error error;
+    if (!new_value_sp)
+    {
+        error.SetErrorString("Empty value object for return value.");
+        return error;
+    }
+    
+    ClangASTType clang_type = new_value_sp->GetClangType();
+    if (!clang_type)
+    {
+        error.SetErrorString ("Null clang type for return value.");
+        return error;
+    }
+    
+    Thread *thread = frame_sp->GetThread().get();
+    
+    bool is_signed;
+    uint32_t count;
+    bool is_complex;
+    
+    RegisterContext *reg_ctx = thread->GetRegisterContext().get();
+
+    bool set_it_simple = false;
+    if (clang_type.IsIntegerType (is_signed) || clang_type.IsPointerType())
+    {
+        DataExtractor data;
+        size_t num_bytes = new_value_sp->GetData(data);
+        lldb::offset_t offset = 0;
+        if (num_bytes <= 8)
+        {
+            const RegisterInfo *r0_info = reg_ctx->GetRegisterInfoByName("r0", 0);
+            if (num_bytes <= 4)
+            {
+                uint32_t raw_value = data.GetMaxU32(&offset, num_bytes);
+        
+                if (reg_ctx->WriteRegisterFromUnsigned (r0_info, raw_value))
+                    set_it_simple = true;
+            }
+            else
+            {
+                uint32_t raw_value = data.GetMaxU32(&offset, 4);
+        
+                if (reg_ctx->WriteRegisterFromUnsigned (r0_info, raw_value))
+                {
+                    const RegisterInfo *r1_info = reg_ctx->GetRegisterInfoByName("r1", 0);
+                    uint32_t raw_value = data.GetMaxU32(&offset, num_bytes - offset);
+                
+                    if (reg_ctx->WriteRegisterFromUnsigned (r1_info, raw_value))
+                        set_it_simple = true;
+                }
+            }
+        }
+        else
+        {
+            error.SetErrorString("We don't support returning longer than 64 bit integer values at present.");
+        }
+    }
+    else if (clang_type.IsFloatingPointType (count, is_complex))
+    {
+        if (is_complex)
+            error.SetErrorString ("We don't support returning complex values at present");
+        else
+            error.SetErrorString ("We don't support returning float values at present");
+    }
+    
+    if (!set_it_simple)
+        error.SetErrorString ("We only support setting simple integer return types at present.");
+    
+    return error;
+}
+
+bool
+ABIMacOSX_arm::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)
+{
+    uint32_t reg_kind = unwind_plan.GetRegisterKind();
+    uint32_t lr_reg_num = LLDB_INVALID_REGNUM;
+    uint32_t sp_reg_num = LLDB_INVALID_REGNUM;
+    uint32_t pc_reg_num = LLDB_INVALID_REGNUM;
+    
+    switch (reg_kind)
+    {
+        case eRegisterKindDWARF:
+        case eRegisterKindGCC:
+            lr_reg_num = dwarf_lr;
+            sp_reg_num = dwarf_sp;
+            pc_reg_num = dwarf_pc;
+            break;
+            
+        case eRegisterKindGeneric:
+            lr_reg_num = LLDB_REGNUM_GENERIC_RA;
+            sp_reg_num = LLDB_REGNUM_GENERIC_SP;
+            pc_reg_num = LLDB_REGNUM_GENERIC_PC;
+            break;
+    }
+    
+    if (lr_reg_num == LLDB_INVALID_REGNUM ||
+        sp_reg_num == LLDB_INVALID_REGNUM ||
+        pc_reg_num == LLDB_INVALID_REGNUM)
+        return false;
+
+    UnwindPlan::RowSP row(new UnwindPlan::Row);
+    
+    // Our Call Frame Address is the stack pointer value
+    row->SetCFARegister (sp_reg_num);
+    
+    // The previous PC is in the LR
+    row->SetRegisterLocationToRegister(pc_reg_num, lr_reg_num, true);
+    unwind_plan.AppendRow (row);
+    
+    // All other registers are the same.
+    
+    unwind_plan.SetSourceName ("arm at-func-entry default");
+    unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
+
+    return true;
+}
+
+bool
+ABIMacOSX_arm::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)
+{
+    uint32_t fp_reg_num = dwarf_r7; // apple uses r7 for all frames. Normal arm uses r11;
+    uint32_t pc_reg_num = dwarf_pc;
+    
+    UnwindPlan::RowSP row(new UnwindPlan::Row);
+    const int32_t ptr_size = 4;
+    
+    unwind_plan.Clear ();
+    unwind_plan.SetRegisterKind (eRegisterKindDWARF);
+    row->SetCFARegister (fp_reg_num);
+    row->SetCFAOffset (2 * ptr_size);
+    row->SetOffset (0);
+    
+    row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
+    row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true);
+    
+    unwind_plan.AppendRow (row);
+    unwind_plan.SetSourceName ("arm-apple-ios default unwind plan");
+    unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
+    unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo);
+
+    return true;
+}
+
+// ARMv7 on iOS general purpose reg rules:
+//    r0-r3 not preserved  (used for argument passing)
+//    r4-r6 preserved
+//    r7    preserved (frame pointer)
+//    r8    preserved
+//    r9    not preserved (usable as volatile scratch register with iOS 3.x and later)
+//    r10-r11 preserved
+//    r12   not presrved
+//    r13   preserved (stack pointer)
+//    r14   not preserved (link register)
+//    r15   preserved (pc)
+//    cpsr  not preserved (different rules for different bits)
+
+// ARMv7 on iOS floating point rules:
+//    d0-d7   not preserved   (aka s0-s15, q0-q3)
+//    d8-d15  preserved       (aka s16-s31, q4-q7)
+//    d16-d31 not preserved   (aka q8-q15)
+
+bool
+ABIMacOSX_arm::RegisterIsVolatile (const RegisterInfo *reg_info)
+{
+    if (reg_info)
+    {
+        // Volatile registers include: r0, r1, r2, r3, r9, r12, r13
+        const char *name = reg_info->name;
+        if (name[0] == 'r')
+        {
+            switch (name[1])
+            {
+                case '0': return name[2] == '\0'; // r0
+                case '1': 
+                    switch (name[2])
+                    {
+                    case '\0':
+                        return true; // r1
+                    case '2':
+                    case '3':
+                        return name[2] == '\0'; // r12 - r13
+                    default:
+                        break;
+                    }
+                    break;
+
+                case '2': return name[2] == '\0'; // r2
+                case '3': return name[2] == '\0'; // r3
+                case '9': return name[2] == '\0'; // r9 (apple-ios only...)
+                    
+                break;
+            }
+        }
+        else if (name[0] == 'd')
+        {
+            switch (name[1])
+            {
+                case '0': 
+                    return name[2] == '\0'; // d0 is volatile
+
+                case '1':
+                    switch (name[2])
+                    {
+                    case '\0':
+                        return true; // d1 is volatile
+                    case '6':
+                    case '7':
+                    case '8':
+                    case '9':
+                        return name[3] == '\0'; // d16 - d19 are volatile
+                    default:
+                        break;
+                    }
+                    break;
+
+                case '2':
+                    switch (name[2])
+                    {
+                    case '\0':
+                        return true; // d2 is volatile
+                    case '0':
+                    case '1':
+                    case '2':
+                    case '3':
+                    case '4':
+                    case '5':
+                    case '6':
+                    case '7':
+                    case '8':
+                    case '9':
+                        return name[3] == '\0'; // d20 - d29 are volatile
+                    default:
+                        break;
+                    }
+                    break;
+
+                case '3':
+                    switch (name[2])
+                    {
+                    case '\0':
+                        return true; // d3 is volatile
+                    case '0':
+                    case '1':
+                        return name[3] == '\0'; // d30 - d31 are volatile
+                    default:
+                        break;
+                    }
+                case '4':
+                case '5':
+                case '6':
+                case '7':
+                    return name[2] == '\0'; // d4 - d7 are volatile
+
+                default:
+                    break;
+            }
+        }
+        else if (name[0] == 's')
+        {
+            switch (name[1])
+            {
+                case '0': 
+                    return name[2] == '\0'; // s0 is volatile
+
+                case '1':
+                    switch (name[2])
+                    {
+                    case '\0':
+                        return true; // s1 is volatile
+                    case '0':
+                    case '1':
+                    case '2':
+                    case '3':
+                    case '4':
+                    case '5':
+                        return name[3] == '\0'; // s10 - s15 are volatile
+                    default:
+                        break;
+                    }
+                    break;
+
+                case '2':
+                    switch (name[2])
+                    {
+                    case '\0':
+                        return true; // s2 is volatile
+                    default:
+                        break;
+                    }
+                    break;
+
+                case '3':
+                    switch (name[2])
+                    {
+                    case '\0':
+                        return true; // s3 is volatile
+                    default:
+                        break;
+                    }
+                case '4':
+                case '5':
+                case '6':
+                case '7':
+                case '8':
+                case '9':
+                    return name[2] == '\0'; // s4 - s9 are volatile
+
+                default:
+                    break;
+            }
+        }
+        else if (name[0] == 's' && name[1] == 'p' && name[2] == '\0')
+            return true;
+    }
+    return false;
+}
+
+void
+ABIMacOSX_arm::Initialize()
+{
+    PluginManager::RegisterPlugin (GetPluginNameStatic(),
+                                   "Mac OS X ABI for arm targets",
+                                   CreateInstance);    
+}
+
+void
+ABIMacOSX_arm::Terminate()
+{
+    PluginManager::UnregisterPlugin (CreateInstance);
+}
+
+lldb_private::ConstString
+ABIMacOSX_arm::GetPluginNameStatic()
+{
+    static ConstString g_name("macosx-arm");
+    return g_name;
+}
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+lldb_private::ConstString
+ABIMacOSX_arm::GetPluginName()
+{
+    return GetPluginNameStatic();
+}
+
+uint32_t
+ABIMacOSX_arm::GetPluginVersion()
+{
+    return 1;
+}
+
diff --git a/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h
new file mode 100644
index 000000000000..27cea85aaf6f
--- /dev/null
+++ b/source/Plugins/ABI/MacOSX-arm/ABIMacOSX_arm.h
@@ -0,0 +1,138 @@
+//===-- ABIMacOSX_arm.h ----------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ABIMacOSX_arm_h_
+#define liblldb_ABIMacOSX_arm_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Target/ABI.h"
+
+class ABIMacOSX_arm : public lldb_private::ABI
+{
+public:
+    ~ABIMacOSX_arm() { }
+    
+    virtual size_t 
+    GetRedZoneSize () const;
+    
+    virtual bool
+    PrepareTrivialCall (lldb_private::Thread &thread, 
+                        lldb::addr_t sp,
+                        lldb::addr_t func_addr,
+                        lldb::addr_t returnAddress, 
+                        lldb::addr_t *arg1_ptr = NULL,
+                        lldb::addr_t *arg2_ptr = NULL,
+                        lldb::addr_t *arg3_ptr = NULL,
+                        lldb::addr_t *arg4_ptr = NULL,
+                        lldb::addr_t *arg5_ptr = NULL,
+                        lldb::addr_t *arg6_ptr = NULL) const;
+    
+    virtual bool
+    GetArgumentValues (lldb_private::Thread &thread,
+                       lldb_private::ValueList &values) const;
+    
+    virtual lldb_private::Error
+    SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value);
+
+protected:
+    virtual lldb::ValueObjectSP
+    GetReturnValueObjectImpl (lldb_private::Thread &thread,
+                    lldb_private::ClangASTType &ast_type) const;
+
+public:
+    virtual bool
+    CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan);
+    
+    virtual bool
+    CreateDefaultUnwindPlan (lldb_private::UnwindPlan &unwind_plan);
+    
+    virtual bool
+    RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info);
+    
+    virtual bool
+    StackUsesFrames ()
+    {
+        return true;
+    }
+    
+    virtual bool
+    CallFrameAddressIsValid (lldb::addr_t cfa)
+    {
+        // Make sure the stack call frame addresses are are 4 byte aligned
+        if (cfa & (4ull - 1ull))
+            return false;   // Not 4 byte aligned
+        if (cfa == 0)
+            return false;   // Zero is not a valid stack address
+        return true;
+    }
+    
+    virtual bool
+    CodeAddressIsValid (lldb::addr_t pc)
+    {
+        // Just make sure the address is a valid 32 bit address. Bit zero
+        // might be set due to Thumb function calls, so don't enforce 2 byte
+        // alignment
+        return pc <= UINT32_MAX;
+    }
+    
+    virtual lldb::addr_t
+    FixCodeAddress (lldb::addr_t pc)
+    {
+        // ARM uses bit zero to signify a code address is thumb, so we must
+        // strip bit zero in any code addresses.
+        return pc & ~(lldb::addr_t)1;
+    }
+
+    virtual bool
+    FunctionCallsChangeCFA ()
+    {
+        return false;
+    }
+
+    virtual const lldb_private::RegisterInfo *
+    GetRegisterInfoArray (uint32_t &count);
+
+    //------------------------------------------------------------------
+    // Static Functions
+    //------------------------------------------------------------------
+    static void
+    Initialize();
+    
+    static void
+    Terminate();
+    
+    static lldb::ABISP
+    CreateInstance (const lldb_private::ArchSpec &arch);
+    
+    static lldb_private::ConstString
+    GetPluginNameStatic();
+    
+    //------------------------------------------------------------------
+    // PluginInterface protocol
+    //------------------------------------------------------------------
+    virtual lldb_private::ConstString
+    GetPluginName();
+    
+    virtual uint32_t
+    GetPluginVersion();
+    
+protected:
+private:
+    ABIMacOSX_arm() : 
+        lldb_private::ABI() 
+    {
+         // Call CreateInstance instead.
+    }
+};
+
+#endif  // liblldb_ABIMacOSX_arm_h_
diff --git a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp
new file mode 100644
index 000000000000..deb531d937a0
--- /dev/null
+++ b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp
@@ -0,0 +1,977 @@
+//===-- ABIMacOSX_i386.cpp --------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ABIMacOSX_i386.h"
+
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/RegisterValue.h"
+#include "lldb/Core/Scalar.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/UnwindPlan.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+
+#include "llvm/ADT/Triple.h"
+
+#include <vector>
+
+using namespace lldb;
+using namespace lldb_private;
+
+enum
+{
+    gcc_eax = 0,
+    gcc_ecx,
+    gcc_edx,
+    gcc_ebx,
+    gcc_ebp,
+    gcc_esp,
+    gcc_esi,
+    gcc_edi,
+    gcc_eip,
+    gcc_eflags
+};
+
+enum
+{
+    dwarf_eax = 0,
+    dwarf_ecx,
+    dwarf_edx,
+    dwarf_ebx,
+    dwarf_esp,
+    dwarf_ebp,
+    dwarf_esi,
+    dwarf_edi,
+    dwarf_eip,
+    dwarf_eflags,
+    dwarf_stmm0 = 11,
+    dwarf_stmm1,
+    dwarf_stmm2,
+    dwarf_stmm3,
+    dwarf_stmm4,
+    dwarf_stmm5,
+    dwarf_stmm6,
+    dwarf_stmm7,
+    dwarf_xmm0 = 21,
+    dwarf_xmm1,
+    dwarf_xmm2,
+    dwarf_xmm3,
+    dwarf_xmm4,
+    dwarf_xmm5,
+    dwarf_xmm6,
+    dwarf_xmm7,
+    dwarf_ymm0 = dwarf_xmm0,
+    dwarf_ymm1 = dwarf_xmm1,
+    dwarf_ymm2 = dwarf_xmm2,
+    dwarf_ymm3 = dwarf_xmm3,
+    dwarf_ymm4 = dwarf_xmm4,
+    dwarf_ymm5 = dwarf_xmm5,
+    dwarf_ymm6 = dwarf_xmm6,
+    dwarf_ymm7 = dwarf_xmm7
+};
+
+enum
+{
+    gdb_eax        =  0,
+    gdb_ecx        =  1,
+    gdb_edx        =  2,
+    gdb_ebx        =  3,
+    gdb_esp        =  4,
+    gdb_ebp        =  5,
+    gdb_esi        =  6,
+    gdb_edi        =  7,
+    gdb_eip        =  8,
+    gdb_eflags     =  9,
+    gdb_cs         = 10,
+    gdb_ss         = 11,
+    gdb_ds         = 12,
+    gdb_es         = 13,
+    gdb_fs         = 14,
+    gdb_gs         = 15,
+    gdb_stmm0      = 16,
+    gdb_stmm1      = 17,
+    gdb_stmm2      = 18,
+    gdb_stmm3      = 19,
+    gdb_stmm4      = 20,
+    gdb_stmm5      = 21,
+    gdb_stmm6      = 22,
+    gdb_stmm7      = 23,
+    gdb_fctrl      = 24,    gdb_fcw     = gdb_fctrl,
+    gdb_fstat      = 25,    gdb_fsw     = gdb_fstat,
+    gdb_ftag       = 26,    gdb_ftw     = gdb_ftag,
+    gdb_fiseg      = 27,    gdb_fpu_cs  = gdb_fiseg,
+    gdb_fioff      = 28,    gdb_ip      = gdb_fioff,
+    gdb_foseg      = 29,    gdb_fpu_ds  = gdb_foseg,
+    gdb_fooff      = 30,    gdb_dp      = gdb_fooff,
+    gdb_fop        = 31,
+    gdb_xmm0       = 32,
+    gdb_xmm1       = 33,
+    gdb_xmm2       = 34,
+    gdb_xmm3       = 35,
+    gdb_xmm4       = 36,
+    gdb_xmm5       = 37,
+    gdb_xmm6       = 38,
+    gdb_xmm7       = 39,
+    gdb_mxcsr      = 40,
+    gdb_mm0        = 41,
+    gdb_mm1        = 42,
+    gdb_mm2        = 43,
+    gdb_mm3        = 44,
+    gdb_mm4        = 45,
+    gdb_mm5        = 46,
+    gdb_mm6        = 47,
+    gdb_mm7        = 48,
+    gdb_ymm0       = gdb_xmm0,
+    gdb_ymm1       = gdb_xmm1,
+    gdb_ymm2       = gdb_xmm2,
+    gdb_ymm3       = gdb_xmm3,
+    gdb_ymm4       = gdb_xmm4,
+    gdb_ymm5       = gdb_xmm5,
+    gdb_ymm6       = gdb_xmm6,
+    gdb_ymm7       = gdb_xmm7
+};
+
+
+static RegisterInfo g_register_infos[] = 
+{
+  //  NAME      ALT      SZ OFF ENCODING         FORMAT                COMPILER              DWARF                 GENERIC                      GDB                   LLDB NATIVE            VALUE REGS    INVALIDATE REGS
+  //  ======    =======  == === =============    ============          ===================== ===================== ============================ ====================  ====================== ==========    ===============
+    { "eax",    NULL,    4,  0, eEncodingUint  , eFormatHex          , { gcc_eax             , dwarf_eax           , LLDB_INVALID_REGNUM       , gdb_eax            , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "ebx"   , NULL,    4,  0, eEncodingUint  , eFormatHex          , { gcc_ebx             , dwarf_ebx           , LLDB_INVALID_REGNUM       , gdb_ebx            , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "ecx"   , NULL,    4,  0, eEncodingUint  , eFormatHex          , { gcc_ecx             , dwarf_ecx           , LLDB_REGNUM_GENERIC_ARG4  , gdb_ecx            , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "edx"   , NULL,    4,  0, eEncodingUint  , eFormatHex          , { gcc_edx             , dwarf_edx           , LLDB_REGNUM_GENERIC_ARG3  , gdb_edx            , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "esi"   , NULL,    4,  0, eEncodingUint  , eFormatHex          , { gcc_esi             , dwarf_esi           , LLDB_REGNUM_GENERIC_ARG2  , gdb_esi            , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "edi"   , NULL,    4,  0, eEncodingUint  , eFormatHex          , { gcc_edi             , dwarf_edi           , LLDB_REGNUM_GENERIC_ARG1  , gdb_edi            , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "ebp"   , "fp",    4,  0, eEncodingUint  , eFormatHex          , { gcc_ebp             , dwarf_ebp           , LLDB_REGNUM_GENERIC_FP    , gdb_ebp            , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "esp"   , "sp",    4,  0, eEncodingUint  , eFormatHex          , { gcc_esp             , dwarf_esp           , LLDB_REGNUM_GENERIC_SP    , gdb_esp            , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "eip"   , "pc",    4,  0, eEncodingUint  , eFormatHex          , { gcc_eip             , dwarf_eip           , LLDB_REGNUM_GENERIC_PC    , gdb_eip            , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "eflags", NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_REGNUM_GENERIC_FLAGS , gdb_eflags         , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "cs"    , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_cs             , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "ss"    , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_ss             , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "ds"    , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_ds             , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "es"    , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_es             , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "fs"    , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_fs             , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "gs"    , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_gs             , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "stmm0" , NULL,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm0         , LLDB_INVALID_REGNUM       , gdb_stmm0          , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "stmm1" , NULL,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm1         , LLDB_INVALID_REGNUM       , gdb_stmm1          , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "stmm2" , NULL,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm2         , LLDB_INVALID_REGNUM       , gdb_stmm2          , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "stmm3" , NULL,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm3         , LLDB_INVALID_REGNUM       , gdb_stmm3          , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "stmm4" , NULL,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm4         , LLDB_INVALID_REGNUM       , gdb_stmm4          , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "stmm5" , NULL,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm5         , LLDB_INVALID_REGNUM       , gdb_stmm5          , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "stmm6" , NULL,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm6         , LLDB_INVALID_REGNUM       , gdb_stmm6          , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "stmm7" , NULL,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_stmm7         , LLDB_INVALID_REGNUM       , gdb_stmm7          , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "fctrl" , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_fctrl          , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "fstat" , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_fstat          , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "ftag"  , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_ftag           , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "fiseg" , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_fiseg          , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "fioff" , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_fioff          , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "foseg" , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_foseg          , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "fooff" , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_fooff          , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "fop"   , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_fop            , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "xmm0"  , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm0          , LLDB_INVALID_REGNUM       , gdb_xmm0           , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "xmm1"  , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm1          , LLDB_INVALID_REGNUM       , gdb_xmm1           , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "xmm2"  , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm2          , LLDB_INVALID_REGNUM       , gdb_xmm2           , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "xmm3"  , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm3          , LLDB_INVALID_REGNUM       , gdb_xmm3           , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "xmm4"  , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm4          , LLDB_INVALID_REGNUM       , gdb_xmm4           , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "xmm5"  , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm5          , LLDB_INVALID_REGNUM       , gdb_xmm5           , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "xmm6"  , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm6          , LLDB_INVALID_REGNUM       , gdb_xmm6           , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "xmm7"  , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_xmm7          , LLDB_INVALID_REGNUM       , gdb_xmm7           , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "mxcsr" , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_mxcsr          , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "ymm0"  , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm0          , LLDB_INVALID_REGNUM       , gdb_ymm0           , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "ymm1"  , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm1          , LLDB_INVALID_REGNUM       , gdb_ymm1           , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "ymm2"  , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm2          , LLDB_INVALID_REGNUM       , gdb_ymm2           , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "ymm3"  , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm3          , LLDB_INVALID_REGNUM       , gdb_ymm3           , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "ymm4"  , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm4          , LLDB_INVALID_REGNUM       , gdb_ymm4           , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "ymm5"  , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm5          , LLDB_INVALID_REGNUM       , gdb_ymm5           , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "ymm6"  , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm6          , LLDB_INVALID_REGNUM       , gdb_ymm6           , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "ymm7"  , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM , dwarf_ymm7          , LLDB_INVALID_REGNUM       , gdb_ymm7           , LLDB_INVALID_REGNUM },      NULL,              NULL}
+};
+
+static const uint32_t k_num_register_infos = sizeof(g_register_infos)/sizeof(RegisterInfo);
+static bool g_register_info_names_constified = false;
+
+const lldb_private::RegisterInfo *
+ABIMacOSX_i386::GetRegisterInfoArray (uint32_t &count)
+{
+    // Make the C-string names and alt_names for the register infos into const 
+    // C-string values by having the ConstString unique the names in the global
+    // constant C-string pool.
+    if (!g_register_info_names_constified)
+    {
+        g_register_info_names_constified = true;
+        for (uint32_t i=0; i<k_num_register_infos; ++i)
+        {
+            if (g_register_infos[i].name)
+                g_register_infos[i].name = ConstString(g_register_infos[i].name).GetCString();
+            if (g_register_infos[i].alt_name)
+                g_register_infos[i].alt_name = ConstString(g_register_infos[i].alt_name).GetCString();
+        }
+    }
+    count = k_num_register_infos;
+    return g_register_infos;
+}
+
+size_t
+ABIMacOSX_i386::GetRedZoneSize () const
+{
+    return 0;
+}
+
+//------------------------------------------------------------------
+// Static Functions
+//------------------------------------------------------------------
+ABISP
+ABIMacOSX_i386::CreateInstance (const ArchSpec &arch)
+{
+    static ABISP g_abi_sp;
+    if (arch.GetTriple().getArch() == llvm::Triple::x86)
+    {
+        if (!g_abi_sp)
+            g_abi_sp.reset (new ABIMacOSX_i386);
+        return g_abi_sp;
+    }
+    return ABISP();
+}
+
+bool
+ABIMacOSX_i386::PrepareTrivialCall (Thread &thread, 
+                                    addr_t sp, 
+                                    addr_t func_addr, 
+                                    addr_t return_addr, 
+                                    addr_t *arg1_ptr,
+                                    addr_t *arg2_ptr,
+                                    addr_t *arg3_ptr,
+                                    addr_t *arg4_ptr,
+                                    addr_t *arg5_ptr,
+                                    addr_t *arg6_ptr) const
+{
+    RegisterContext *reg_ctx = thread.GetRegisterContext().get();
+    if (!reg_ctx)
+        return false;    
+    uint32_t pc_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
+    uint32_t sp_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
+    
+    // When writing a register value down to memory, the register info used 
+    // to write memory just needs to have the correct size of a 32 bit register, 
+    // the actual register it pertains to is not important, just the size needs 
+    // to be correct. Here we use "eax"...
+    const RegisterInfo *reg_info_32 = reg_ctx->GetRegisterInfoByName("eax");
+    if (!reg_info_32)
+        return false; // TODO this should actually never happen
+
+    // Make room for the argument(s) on the stack
+
+    Error error;
+    RegisterValue reg_value;
+    
+    // Write any arguments onto the stack
+    if (arg1_ptr)
+    {
+        sp -= 4;
+        if (arg2_ptr)
+        {
+            sp -= 4;
+            if (arg3_ptr)
+            {
+                sp -= 4;
+                if (arg4_ptr)
+                {
+                    sp -= 4;
+                    if (arg5_ptr)
+                    {
+                        sp -= 4;
+                        if (arg6_ptr)
+                        {
+                            sp -= 4;
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    // Align the SP    
+    sp &= ~(16ull-1ull); // 16-byte alignment
+    
+    if (arg1_ptr)
+    {
+        reg_value.SetUInt32(*arg1_ptr);
+        error = reg_ctx->WriteRegisterValueToMemory (reg_info_32, 
+                                                     sp, 
+                                                     reg_info_32->byte_size, 
+                                                     reg_value);
+        if (error.Fail())
+            return false;
+
+        if (arg2_ptr)
+        {
+            reg_value.SetUInt32(*arg2_ptr);
+            // The register info used to write memory just needs to have the correct
+            // size of a 32 bit register, the actual register it pertains to is not
+            // important, just the size needs to be correct. Here we use "eax"...
+            error = reg_ctx->WriteRegisterValueToMemory (reg_info_32, 
+                                                         sp + 4, 
+                                                         reg_info_32->byte_size, 
+                                                         reg_value);
+            if (error.Fail())
+                return false;
+            
+            if (arg3_ptr)
+            {
+                reg_value.SetUInt32(*arg3_ptr);
+                // The register info used to write memory just needs to have the correct
+                // size of a 32 bit register, the actual register it pertains to is not
+                // important, just the size needs to be correct. Here we use "eax"...
+                error = reg_ctx->WriteRegisterValueToMemory (reg_info_32, 
+                                                             sp + 8, 
+                                                             reg_info_32->byte_size, 
+                                                             reg_value);
+                if (error.Fail())
+                    return false;
+
+                if (arg4_ptr)
+                {
+                    reg_value.SetUInt32(*arg4_ptr);
+                    // The register info used to write memory just needs to have the correct
+                    // size of a 32 bit register, the actual register it pertains to is not
+                    // important, just the size needs to be correct. Here we use "eax"...
+                    error = reg_ctx->WriteRegisterValueToMemory (reg_info_32, 
+                                                                 sp + 12, 
+                                                                 reg_info_32->byte_size, 
+                                                                 reg_value);
+                    if (error.Fail())
+                        return false;
+                    if (arg5_ptr)
+                    {
+                        reg_value.SetUInt32(*arg5_ptr);
+                        // The register info used to write memory just needs to have the correct
+                        // size of a 32 bit register, the actual register it pertains to is not
+                        // important, just the size needs to be correct. Here we use "eax"...
+                        error = reg_ctx->WriteRegisterValueToMemory (reg_info_32, 
+                                                                     sp + 16, 
+                                                                     reg_info_32->byte_size, 
+                                                                     reg_value);
+                        if (error.Fail())
+                            return false;
+                        if (arg6_ptr)
+                        {
+                            reg_value.SetUInt32(*arg6_ptr);
+                            // The register info used to write memory just needs to have the correct
+                            // size of a 32 bit register, the actual register it pertains to is not
+                            // important, just the size needs to be correct. Here we use "eax"...
+                            error = reg_ctx->WriteRegisterValueToMemory (reg_info_32, 
+                                                                         sp + 20, 
+                                                                         reg_info_32->byte_size, 
+                                                                         reg_value);
+                            if (error.Fail())
+                                return false;
+                        }
+                    }
+                }
+            }
+        }
+    }
+    
+    
+    // The return address is pushed onto the stack (yes after we just set the
+    // alignment above!).
+    sp -= 4;
+    reg_value.SetUInt32(return_addr);
+    error = reg_ctx->WriteRegisterValueToMemory (reg_info_32, 
+                                                 sp, 
+                                                 reg_info_32->byte_size, 
+                                                 reg_value);
+    if (error.Fail())
+        return false;
+    
+    // %esp is set to the actual stack value.
+    
+    if (!reg_ctx->WriteRegisterFromUnsigned (sp_reg_num, sp))
+        return false;
+    
+    // %eip is set to the address of the called function.
+    
+    if (!reg_ctx->WriteRegisterFromUnsigned (pc_reg_num, func_addr))
+        return false;
+    
+    return true;
+}
+
+bool
+ABIMacOSX_i386::PrepareNormalCall (Thread &thread,
+                                   addr_t sp,
+                                   addr_t func_addr,
+                                   addr_t return_addr,
+                                   ValueList &args) const
+{
+    ExecutionContext exe_ctx (thread.shared_from_this());
+    RegisterContext *reg_ctx = thread.GetRegisterContext().get();
+    if (!reg_ctx)
+        return false;
+    
+    Process *process = exe_ctx.GetProcessPtr();
+    Error error;
+    uint32_t fp_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP);
+    uint32_t pc_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
+    uint32_t sp_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
+    
+    // Do the argument layout
+    
+    std::vector <uint32_t> argLayout;   // 4-byte chunks, as discussed in the ABI Function Call Guide
+    
+    size_t numArgs = args.GetSize();
+    size_t index;
+    
+    for (index = 0; index < numArgs; ++index)
+    {
+        Value *val = args.GetValueAtIndex(index);
+        
+        if (!val)
+            return false;
+        
+        switch (val->GetValueType())
+        {
+        case Value::eValueTypeScalar:
+            {
+                Scalar &scalar = val->GetScalar();
+                switch (scalar.GetType())
+                {
+                case Scalar::e_void:
+                    return false;
+                case Scalar::e_sint: 
+                case Scalar::e_uint:
+                case Scalar::e_slong:
+                case Scalar::e_ulong:
+                case Scalar::e_slonglong:
+                case Scalar::e_ulonglong:
+                    {
+                        uint64_t data = scalar.ULongLong();
+                        
+                        switch (scalar.GetByteSize())
+                        {
+                        default:
+                            return false;
+                        case 1:
+                            argLayout.push_back((uint32_t)(data & 0xffull));
+                            break;
+                        case 2:
+                            argLayout.push_back((uint32_t)(data & 0xffffull));
+                            break;
+                        case 4:
+                            argLayout.push_back((uint32_t)(data & 0xffffffffull));
+                            break;
+                        case 8:
+                            argLayout.push_back((uint32_t)(data & 0xffffffffull));
+                            argLayout.push_back((uint32_t)(data >> 32));
+                            break;
+                        }
+                    }
+                    break;
+                case Scalar::e_float:
+                    {
+                        float data = scalar.Float();
+                        uint32_t dataRaw = *((uint32_t*)(&data));
+                        argLayout.push_back(dataRaw);
+                    }
+                    break;
+                case Scalar::e_double:
+                    {
+                        double data = scalar.Double();
+                        uint32_t *dataRaw = ((uint32_t*)(&data));
+                        argLayout.push_back(dataRaw[0]);
+                        argLayout.push_back(dataRaw[1]);
+                    }
+                    break;
+                case Scalar::e_long_double:
+                    {
+                        long double data = scalar.Double();
+                        uint32_t *dataRaw = ((uint32_t*)(&data));
+                        while ((argLayout.size() * 4) & 0xf)
+                            argLayout.push_back(0);
+                        argLayout.push_back(dataRaw[0]);
+                        argLayout.push_back(dataRaw[1]);
+                        argLayout.push_back(dataRaw[2]);
+                        argLayout.push_back(dataRaw[3]);
+                    }
+                    break;
+                }
+            }
+            break;
+        case Value::eValueTypeHostAddress:
+            {
+                ClangASTType clang_type (val->GetClangType());
+                if (clang_type)
+                {
+                    uint32_t cstr_length = 0;
+                    if (clang_type.IsCStringType (cstr_length))
+                    {
+                        const char *cstr = (const char*)val->GetScalar().ULongLong();
+                        cstr_length = strlen(cstr);
+                        
+                        // Push the string onto the stack immediately.
+                        
+                        sp -= (cstr_length + 1);
+                        
+                        if (process->WriteMemory(sp, cstr, cstr_length + 1, error) != (cstr_length + 1))
+                            return false;
+                        
+                        // Put the address of the string into the argument array.
+                        
+                        argLayout.push_back((uint32_t)(sp & 0xffffffff));
+                    }
+                    else
+                    {
+                        return false;
+                    }
+                }
+                break;
+            }
+            break;
+        case Value::eValueTypeFileAddress:
+        case Value::eValueTypeLoadAddress:
+        default:
+            return false;
+        }
+    }
+    
+    // Make room for the arguments on the stack
+    
+    sp -= 4 * argLayout.size();
+    
+    // Align the SP
+    
+    sp &= ~(16ull-1ull); // 16-byte alignment
+    
+    // Write the arguments on the stack
+    
+    size_t numChunks = argLayout.size();
+
+    for (index = 0; index < numChunks; ++index)
+        if (process->WriteMemory(sp + (index * 4), &argLayout[index], sizeof(uint32_t), error) != sizeof(uint32_t))
+            return false;
+    
+    // The return address is pushed onto the stack.
+    
+    sp -= 4;
+    uint32_t returnAddressU32 = return_addr;
+    if (process->WriteMemory (sp, &returnAddressU32, sizeof(returnAddressU32), error) != sizeof(returnAddressU32))
+        return false;
+    
+    // %esp is set to the actual stack value.
+    
+    if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_num, sp))
+        return false;
+    
+    // %ebp is set to a fake value, in our case 0x0x00000000
+    
+    if (!reg_ctx->WriteRegisterFromUnsigned(fp_reg_num, 0x00000000))
+        return false;
+    
+    // %eip is set to the address of the called function.
+    
+    if (!reg_ctx->WriteRegisterFromUnsigned(pc_reg_num, func_addr))
+        return false;
+    
+    return true;    
+}
+
+static bool 
+ReadIntegerArgument (Scalar           &scalar,
+                     unsigned int     bit_width,
+                     bool             is_signed,
+                     Process          *process,
+                     addr_t           &current_stack_argument)
+{
+    
+    uint32_t byte_size = (bit_width + (8-1))/8;
+    Error error;
+    if (process->ReadScalarIntegerFromMemory(current_stack_argument, byte_size, is_signed, scalar, error))
+    {
+        current_stack_argument += byte_size;
+        return true;
+    }
+    return false;
+}
+
+bool
+ABIMacOSX_i386::GetArgumentValues (Thread &thread,
+                                   ValueList &values) const
+{
+    unsigned int num_values = values.GetSize();
+    unsigned int value_index;
+    
+    // Get the pointer to the first stack argument so we have a place to start 
+    // when reading data
+    
+    RegisterContext *reg_ctx = thread.GetRegisterContext().get();
+    
+    if (!reg_ctx)
+        return false;
+    
+    addr_t sp = reg_ctx->GetSP(0);
+    
+    if (!sp)
+        return false;
+    
+    addr_t current_stack_argument = sp + 4; // jump over return address
+    
+    for (value_index = 0;
+         value_index < num_values;
+         ++value_index)
+    {
+        Value *value = values.GetValueAtIndex(value_index);
+        
+        if (!value)
+            return false;
+        
+        // We currently only support extracting values with Clang QualTypes.
+        // Do we care about others?
+        ClangASTType clang_type (value->GetClangType());
+        if (clang_type)
+        {
+            bool is_signed;
+            
+            if (clang_type.IsIntegerType (is_signed))
+            {
+                ReadIntegerArgument(value->GetScalar(),
+                                    clang_type.GetBitSize(),
+                                    is_signed,
+                                    thread.GetProcess().get(), 
+                                    current_stack_argument);
+            }
+            else if (clang_type.IsPointerType())
+            {
+                ReadIntegerArgument(value->GetScalar(),
+                                    clang_type.GetBitSize(),
+                                    false,
+                                    thread.GetProcess().get(),
+                                    current_stack_argument);
+            }
+        }
+    }
+    
+    return true;
+}
+
+Error
+ABIMacOSX_i386::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value_sp)
+{
+    Error error;
+    if (!new_value_sp)
+    {
+        error.SetErrorString("Empty value object for return value.");
+        return error;
+    }
+    
+    ClangASTType clang_type = new_value_sp->GetClangType();
+    if (!clang_type)
+    {
+        error.SetErrorString ("Null clang type for return value.");
+        return error;
+    }
+    
+    Thread *thread = frame_sp->GetThread().get();
+    
+    bool is_signed;
+    uint32_t count;
+    bool is_complex;
+    
+    RegisterContext *reg_ctx = thread->GetRegisterContext().get();
+
+    bool set_it_simple = false;
+    if (clang_type.IsIntegerType (is_signed) || clang_type.IsPointerType())
+    {
+        DataExtractor data;
+        size_t num_bytes = new_value_sp->GetData(data);
+        lldb::offset_t offset = 0;
+        if (num_bytes <= 8)
+        {
+            const RegisterInfo *eax_info = reg_ctx->GetRegisterInfoByName("eax", 0);
+            if (num_bytes <= 4)
+            {
+                uint32_t raw_value = data.GetMaxU32(&offset, num_bytes);
+        
+                if (reg_ctx->WriteRegisterFromUnsigned (eax_info, raw_value))
+                    set_it_simple = true;
+            }
+            else
+            {
+                uint32_t raw_value = data.GetMaxU32(&offset, 4);
+        
+                if (reg_ctx->WriteRegisterFromUnsigned (eax_info, raw_value))
+                {
+                    const RegisterInfo *edx_info = reg_ctx->GetRegisterInfoByName("edx", 0);
+                    uint32_t raw_value = data.GetMaxU32(&offset, num_bytes - offset);
+                
+                    if (reg_ctx->WriteRegisterFromUnsigned (edx_info, raw_value))
+                        set_it_simple = true;
+                }
+            }
+        }
+        else
+        {
+            error.SetErrorString("We don't support returning longer than 64 bit integer values at present.");
+        }
+    }
+    else if (clang_type.IsFloatingPointType (count, is_complex))
+    {
+        if (is_complex)
+            error.SetErrorString ("We don't support returning complex values at present");
+        else
+            error.SetErrorString ("We don't support returning float values at present");
+    }
+    
+    if (!set_it_simple)
+        error.SetErrorString ("We only support setting simple integer return types at present.");
+    
+    return error;
+}
+
+ValueObjectSP
+ABIMacOSX_i386::GetReturnValueObjectImpl (Thread &thread,
+                                          ClangASTType &clang_type) const
+{
+    Value value;
+    ValueObjectSP return_valobj_sp;
+    
+    if (!clang_type)
+        return return_valobj_sp;
+    
+    //value.SetContext (Value::eContextTypeClangType, clang_type.GetOpaqueQualType());
+    value.SetClangType (clang_type);
+    
+    RegisterContext *reg_ctx = thread.GetRegisterContext().get();
+        if (!reg_ctx)
+        return return_valobj_sp;
+        
+    bool is_signed;
+            
+    if (clang_type.IsIntegerType (is_signed))
+    {
+        size_t bit_width = clang_type.GetBitSize();
+        
+        unsigned eax_id = reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB];
+        unsigned edx_id = reg_ctx->GetRegisterInfoByName("edx", 0)->kinds[eRegisterKindLLDB];
+        
+        switch (bit_width)
+        {
+            default:
+            case 128:
+                // Scalar can't hold 128-bit literals, so we don't handle this
+                return return_valobj_sp;
+            case 64:
+                uint64_t raw_value;
+                raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff;
+                raw_value |= (thread.GetRegisterContext()->ReadRegisterAsUnsigned(edx_id, 0) & 0xffffffff) << 32;
+                if (is_signed)
+                    value.GetScalar() = (int64_t)raw_value;
+                else
+                    value.GetScalar() = (uint64_t)raw_value;
+                break;
+            case 32:
+                if (is_signed)
+                    value.GetScalar() = (int32_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff);
+                else
+                    value.GetScalar() = (uint32_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff);
+                break;
+            case 16:
+                if (is_signed)
+                    value.GetScalar() = (int16_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffff);
+                else
+                    value.GetScalar() = (uint16_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffff);
+                break;
+            case 8:
+                if (is_signed)
+                    value.GetScalar() = (int8_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xff);
+                else
+                    value.GetScalar() = (uint8_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xff);
+                break;
+        }
+    }
+    else if (clang_type.IsPointerType ())
+    {
+        unsigned eax_id = reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB];
+        uint32_t ptr = thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff;
+        value.GetScalar() = ptr;
+    }
+    else
+    {
+        // not handled yet
+        return return_valobj_sp;
+    }
+    
+    // If we get here, we have a valid Value, so make our ValueObject out of it:
+    
+    return_valobj_sp = ValueObjectConstResult::Create(thread.GetStackFrameAtIndex(0).get(),
+                                                      value,
+                                                      ConstString(""));
+    return return_valobj_sp;
+}
+
+bool
+ABIMacOSX_i386::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)
+{
+    uint32_t reg_kind = unwind_plan.GetRegisterKind();
+    uint32_t sp_reg_num = LLDB_INVALID_REGNUM;
+    uint32_t pc_reg_num = LLDB_INVALID_REGNUM;
+    
+    switch (reg_kind)
+    {
+        case eRegisterKindDWARF:
+            sp_reg_num = dwarf_esp;
+            pc_reg_num = dwarf_eip;
+            break;
+
+        case eRegisterKindGCC:
+            sp_reg_num = gcc_esp;
+            pc_reg_num = gcc_eip;
+            break;
+            
+        case eRegisterKindGDB:
+            sp_reg_num = gdb_esp;
+            pc_reg_num = gdb_eip;
+            break;
+            
+        case eRegisterKindGeneric:
+            sp_reg_num = LLDB_REGNUM_GENERIC_SP;
+            pc_reg_num = LLDB_REGNUM_GENERIC_PC;
+            break;
+    }
+    
+    if (sp_reg_num == LLDB_INVALID_REGNUM ||
+        pc_reg_num == LLDB_INVALID_REGNUM)
+        return false;
+
+    UnwindPlan::RowSP row(new UnwindPlan::Row);
+    row->SetCFARegister (sp_reg_num);
+    row->SetCFAOffset (4);
+    row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, -4, false);
+    unwind_plan.AppendRow (row);
+    unwind_plan.SetSourceName ("i386 at-func-entry default");
+    unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
+    return true;
+}
+
+bool
+ABIMacOSX_i386::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)
+{
+    uint32_t fp_reg_num = dwarf_ebp;
+    uint32_t sp_reg_num = dwarf_esp;
+    uint32_t pc_reg_num = dwarf_eip;
+    
+    UnwindPlan::RowSP row(new UnwindPlan::Row);
+    const int32_t ptr_size = 4;
+
+    unwind_plan.Clear ();
+    unwind_plan.SetRegisterKind (eRegisterKindDWARF);
+    row->SetCFARegister (fp_reg_num);
+    row->SetCFAOffset (2 * ptr_size);
+    row->SetOffset (0);
+    
+    row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
+    row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true);
+    row->SetRegisterLocationToAtCFAPlusOffset(sp_reg_num, ptr_size *  0, true);
+
+    unwind_plan.AppendRow (row);
+    unwind_plan.SetSourceName ("i386 default unwind plan");
+    unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
+    unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo);
+    return true;
+}
+
+bool
+ABIMacOSX_i386::RegisterIsVolatile (const RegisterInfo *reg_info)
+{
+    return !RegisterIsCalleeSaved (reg_info);
+}
+
+// v. http://developer.apple.com/library/mac/#documentation/developertools/Conceptual/LowLevelABI/130-IA-32_Function_Calling_Conventions/IA32.html#//apple_ref/doc/uid/TP40002492-SW4
+
+bool
+ABIMacOSX_i386::RegisterIsCalleeSaved (const RegisterInfo *reg_info)
+{
+    if (reg_info)
+    {
+        // Saved registers are ebx, ebp, esi, edi, esp, eip
+        const char *name = reg_info->name;
+        if (name[0] == 'e')
+        {
+            switch (name[1])
+            {
+            case 'b': 
+                if (name[2] == 'x' || name[2] == 'p')
+                    return name[3] == '\0';
+                break;
+            case 'd':
+                if (name[2] == 'i')
+                    return name[3] == '\0';
+                break;
+            case 'i': 
+                if (name[2] == 'p')
+                    return name[3] == '\0';
+                break;
+            case 's':
+                if (name[2] == 'i' || name[2] == 'p')
+                    return name[3] == '\0';
+                break;
+            }
+        }
+        if (name[0] == 's' && name[1] == 'p' && name[2] == '\0')   // sp
+            return true;
+        if (name[0] == 'f' && name[1] == 'p' && name[2] == '\0')   // fp
+            return true;
+        if (name[0] == 'p' && name[1] == 'c' && name[2] == '\0')   // pc
+            return true;
+    }
+    return false;
+}
+
+void
+ABIMacOSX_i386::Initialize()
+{
+    PluginManager::RegisterPlugin (GetPluginNameStatic(),
+                                   "Mac OS X ABI for i386 targets",
+                                   CreateInstance);    
+}
+
+void
+ABIMacOSX_i386::Terminate()
+{
+    PluginManager::UnregisterPlugin (CreateInstance);
+}
+
+lldb_private::ConstString
+ABIMacOSX_i386::GetPluginNameStatic ()
+{
+    static ConstString g_short_name("abi.macosx-i386");
+    return g_short_name;
+    
+}
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+lldb_private::ConstString
+ABIMacOSX_i386::GetPluginName()
+{
+    return GetPluginNameStatic();
+}
+
+uint32_t
+ABIMacOSX_i386::GetPluginVersion()
+{
+    return 1;
+}
+
diff --git a/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h
new file mode 100644
index 000000000000..8c2d945e6342
--- /dev/null
+++ b/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h
@@ -0,0 +1,139 @@
+//===-- ABIMacOSX_i386.h ----------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ABIMacOSX_i386_h_
+#define liblldb_ABIMacOSX_i386_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Target/ABI.h"
+#include "lldb/Core/Value.h"
+    
+class ABIMacOSX_i386 :
+    public lldb_private::ABI
+{
+public:
+
+    ~ABIMacOSX_i386() { }
+    
+    virtual size_t 
+    GetRedZoneSize () const;
+    
+    virtual bool
+    PrepareTrivialCall (lldb_private::Thread &thread, 
+                        lldb::addr_t sp,
+                        lldb::addr_t func_addr,
+                        lldb::addr_t return_addr, 
+                        lldb::addr_t *arg1_ptr = NULL,
+                        lldb::addr_t *arg2_ptr = NULL,
+                        lldb::addr_t *arg3_ptr = NULL,
+                        lldb::addr_t *arg4_ptr = NULL,
+                        lldb::addr_t *arg5_ptr = NULL,
+                        lldb::addr_t *arg6_ptr = NULL) const;
+    
+    virtual bool
+    PrepareNormalCall (lldb_private::Thread &thread,
+                       lldb::addr_t sp,
+                       lldb::addr_t func_addr,
+                       lldb::addr_t return_addr,
+                       lldb_private::ValueList &args) const;
+    
+    virtual bool
+    GetArgumentValues (lldb_private::Thread &thread,
+                       lldb_private::ValueList &values) const;
+    
+    virtual lldb_private::Error
+    SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value);
+
+protected:
+    virtual lldb::ValueObjectSP
+    GetReturnValueObjectImpl (lldb_private::Thread &thread,
+                    lldb_private::ClangASTType &ast_type) const;
+
+public:
+
+    virtual bool
+    CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan);
+    
+    virtual bool
+    CreateDefaultUnwindPlan (lldb_private::UnwindPlan &unwind_plan);
+    
+    virtual bool
+    RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info);
+    
+    virtual bool
+    StackUsesFrames ()
+    {
+        return true;
+    }
+    
+    virtual bool
+    CallFrameAddressIsValid (lldb::addr_t cfa)
+    {
+        // Make sure the stack call frame addresses are are 8 byte aligned
+        if (cfa & (8ull - 1ull))
+            return false;   // Not 8 byte aligned
+        if (cfa == 0)
+            return false;   // Zero is not a valid stack address
+        return true;
+    }
+
+    virtual bool
+    CodeAddressIsValid (lldb::addr_t pc)
+    {
+        // Just make sure the address is a valid 32 bit address. 
+        return pc <= UINT32_MAX;
+    }
+
+    virtual bool
+    FunctionCallsChangeCFA ()
+    {
+        return true;
+    }
+
+    virtual const lldb_private::RegisterInfo *
+    GetRegisterInfoArray (uint32_t &count);
+
+    //------------------------------------------------------------------
+    // Static Functions
+    //------------------------------------------------------------------
+    static void
+    Initialize();
+    
+    static void
+    Terminate();
+    
+    static lldb::ABISP
+    CreateInstance (const lldb_private::ArchSpec &arch);
+    
+    //------------------------------------------------------------------
+    // PluginInterface protocol
+    //------------------------------------------------------------------
+    static lldb_private::ConstString
+    GetPluginNameStatic ();
+
+    virtual lldb_private::ConstString
+    GetPluginName();
+    
+    virtual uint32_t
+    GetPluginVersion();
+    
+protected:
+    bool
+    RegisterIsCalleeSaved (const lldb_private::RegisterInfo *reg_info);
+
+private:
+    ABIMacOSX_i386() : lldb_private::ABI() { } // Call CreateInstance instead.
+};
+
+
+#endif  // liblldb_ABI_h_
diff --git a/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp
new file mode 100644
index 000000000000..a904d8b649ca
--- /dev/null
+++ b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp
@@ -0,0 +1,1288 @@
+//===-- ABISysV_x86_64.cpp --------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ABISysV_x86_64.h"
+
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/RegisterValue.h"
+#include "lldb/Core/Value.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/Core/ValueObjectRegister.h"
+#include "lldb/Core/ValueObjectMemory.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/UnwindPlan.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/Thread.h"
+
+#include "llvm/ADT/Triple.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+enum gcc_dwarf_regnums
+{
+    gcc_dwarf_rax = 0,
+    gcc_dwarf_rdx,
+    gcc_dwarf_rcx,
+    gcc_dwarf_rbx,
+    gcc_dwarf_rsi,
+    gcc_dwarf_rdi,
+    gcc_dwarf_rbp,
+    gcc_dwarf_rsp,
+    gcc_dwarf_r8,
+    gcc_dwarf_r9,
+    gcc_dwarf_r10,
+    gcc_dwarf_r11,
+    gcc_dwarf_r12,
+    gcc_dwarf_r13,
+    gcc_dwarf_r14,
+    gcc_dwarf_r15,
+    gcc_dwarf_rip,
+    gcc_dwarf_xmm0,
+    gcc_dwarf_xmm1,
+    gcc_dwarf_xmm2,
+    gcc_dwarf_xmm3,
+    gcc_dwarf_xmm4,
+    gcc_dwarf_xmm5,
+    gcc_dwarf_xmm6,
+    gcc_dwarf_xmm7,
+    gcc_dwarf_xmm8,
+    gcc_dwarf_xmm9,
+    gcc_dwarf_xmm10,
+    gcc_dwarf_xmm11,
+    gcc_dwarf_xmm12,
+    gcc_dwarf_xmm13,
+    gcc_dwarf_xmm14,
+    gcc_dwarf_xmm15,
+    gcc_dwarf_stmm0,
+    gcc_dwarf_stmm1,
+    gcc_dwarf_stmm2,
+    gcc_dwarf_stmm3,
+    gcc_dwarf_stmm4,
+    gcc_dwarf_stmm5,
+    gcc_dwarf_stmm6,
+    gcc_dwarf_stmm7,
+    gcc_dwarf_ymm0,
+    gcc_dwarf_ymm1,
+    gcc_dwarf_ymm2,
+    gcc_dwarf_ymm3,
+    gcc_dwarf_ymm4,
+    gcc_dwarf_ymm5,
+    gcc_dwarf_ymm6,
+    gcc_dwarf_ymm7,
+    gcc_dwarf_ymm8,
+    gcc_dwarf_ymm9,
+    gcc_dwarf_ymm10,
+    gcc_dwarf_ymm11,
+    gcc_dwarf_ymm12,
+    gcc_dwarf_ymm13,
+    gcc_dwarf_ymm14,
+    gcc_dwarf_ymm15
+};
+
+enum gdb_regnums
+{
+    gdb_rax     =   0,
+    gdb_rbx     =   1,
+    gdb_rcx     =   2,
+    gdb_rdx     =   3,
+    gdb_rsi     =   4,
+    gdb_rdi     =   5,
+    gdb_rbp     =   6,
+    gdb_rsp     =   7,
+    gdb_r8      =   8,
+    gdb_r9      =   9,
+    gdb_r10     =  10,
+    gdb_r11     =  11,
+    gdb_r12     =  12,
+    gdb_r13     =  13,
+    gdb_r14     =  14,
+    gdb_r15     =  15,
+    gdb_rip     =  16,
+    gdb_rflags  =  17,
+    gdb_cs      =  18,
+    gdb_ss      =  19,
+    gdb_ds      =  20,
+    gdb_es      =  21,
+    gdb_fs      =  22,
+    gdb_gs      =  23,
+    gdb_stmm0   =  24,
+    gdb_stmm1   =  25,
+    gdb_stmm2   =  26,
+    gdb_stmm3   =  27,
+    gdb_stmm4   =  28,
+    gdb_stmm5   =  29,
+    gdb_stmm6   =  30,
+    gdb_stmm7   =  31,
+    gdb_fctrl   =  32,  gdb_fcw = gdb_fctrl,
+    gdb_fstat   =  33,  gdb_fsw = gdb_fstat,
+    gdb_ftag    =  34,  gdb_ftw = gdb_ftag,
+    gdb_fiseg   =  35,  gdb_fpu_cs  = gdb_fiseg,
+    gdb_fioff   =  36,  gdb_ip  = gdb_fioff,
+    gdb_foseg   =  37,  gdb_fpu_ds  = gdb_foseg,
+    gdb_fooff   =  38,  gdb_dp  = gdb_fooff,
+    gdb_fop     =  39,
+    gdb_xmm0    =  40,
+    gdb_xmm1    =  41,
+    gdb_xmm2    =  42,
+    gdb_xmm3    =  43,
+    gdb_xmm4    =  44,
+    gdb_xmm5    =  45,
+    gdb_xmm6    =  46,
+    gdb_xmm7    =  47,
+    gdb_xmm8    =  48,
+    gdb_xmm9    =  49,
+    gdb_xmm10   =  50,
+    gdb_xmm11   =  51,
+    gdb_xmm12   =  52,
+    gdb_xmm13   =  53,
+    gdb_xmm14   =  54,
+    gdb_xmm15   =  55,
+    gdb_mxcsr   =  56,
+    gdb_ymm0    =  57,
+    gdb_ymm1    =  58,
+    gdb_ymm2    =  59,
+    gdb_ymm3    =  60,
+    gdb_ymm4    =  61,
+    gdb_ymm5    =  62,
+    gdb_ymm6    =  63,
+    gdb_ymm7    =  64,
+    gdb_ymm8    =  65,
+    gdb_ymm9    =  66,
+    gdb_ymm10   =  67,
+    gdb_ymm11   =  68,
+    gdb_ymm12   =  69,
+    gdb_ymm13   =  70,
+    gdb_ymm14   =  71,
+    gdb_ymm15   =  72
+};
+
+
+static RegisterInfo g_register_infos[] = 
+{
+  //  NAME      ALT      SZ OFF ENCODING         FORMAT              COMPILER                DWARF                 GENERIC                     GDB                   LLDB NATIVE            VALUE REGS    INVALIDATE REGS
+  //  ========  =======  == === =============    =================== ======================= ===================== =========================== ===================== ====================== ==========    ===============
+    { "rax"   , NULL,    8,  0, eEncodingUint  , eFormatHex          , { gcc_dwarf_rax       , gcc_dwarf_rax       , LLDB_INVALID_REGNUM       , gdb_rax            , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "rbx"   , NULL,    8,  0, eEncodingUint  , eFormatHex          , { gcc_dwarf_rbx       , gcc_dwarf_rbx       , LLDB_INVALID_REGNUM       , gdb_rbx            , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "rcx"   , "arg4",  8,  0, eEncodingUint  , eFormatHex          , { gcc_dwarf_rcx       , gcc_dwarf_rcx       , LLDB_REGNUM_GENERIC_ARG4  , gdb_rcx            , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "rdx"   , "arg3",  8,  0, eEncodingUint  , eFormatHex          , { gcc_dwarf_rdx       , gcc_dwarf_rdx       , LLDB_REGNUM_GENERIC_ARG3  , gdb_rdx            , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "rsi"   , "arg2",  8,  0, eEncodingUint  , eFormatHex          , { gcc_dwarf_rsi       , gcc_dwarf_rsi       , LLDB_REGNUM_GENERIC_ARG2  , gdb_rsi            , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "rdi"   , "arg1",  8,  0, eEncodingUint  , eFormatHex          , { gcc_dwarf_rdi       , gcc_dwarf_rdi       , LLDB_REGNUM_GENERIC_ARG1  , gdb_rdi            , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "rbp"   , "fp",    8,  0, eEncodingUint  , eFormatHex          , { gcc_dwarf_rbp       , gcc_dwarf_rbp       , LLDB_REGNUM_GENERIC_FP    , gdb_rbp            , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "rsp"   , "sp",    8,  0, eEncodingUint  , eFormatHex          , { gcc_dwarf_rsp       , gcc_dwarf_rsp       , LLDB_REGNUM_GENERIC_SP    , gdb_rsp            , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "r8"    , "arg5",  8,  0, eEncodingUint  , eFormatHex          , { gcc_dwarf_r8        , gcc_dwarf_r8        , LLDB_REGNUM_GENERIC_ARG5  , gdb_r8             , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "r9"    , "arg6",  8,  0, eEncodingUint  , eFormatHex          , { gcc_dwarf_r9        , gcc_dwarf_r9        , LLDB_REGNUM_GENERIC_ARG6  , gdb_r9             , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "r10"   , NULL,    8,  0, eEncodingUint  , eFormatHex          , { gcc_dwarf_r10       , gcc_dwarf_r10       , LLDB_INVALID_REGNUM       , gdb_r10            , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "r11"   , NULL,    8,  0, eEncodingUint  , eFormatHex          , { gcc_dwarf_r11       , gcc_dwarf_r11       , LLDB_INVALID_REGNUM       , gdb_r11            , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "r12"   , NULL,    8,  0, eEncodingUint  , eFormatHex          , { gcc_dwarf_r12       , gcc_dwarf_r12       , LLDB_INVALID_REGNUM       , gdb_r12            , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "r13"   , NULL,    8,  0, eEncodingUint  , eFormatHex          , { gcc_dwarf_r13       , gcc_dwarf_r13       , LLDB_INVALID_REGNUM       , gdb_r13            , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "r14"   , NULL,    8,  0, eEncodingUint  , eFormatHex          , { gcc_dwarf_r14       , gcc_dwarf_r14       , LLDB_INVALID_REGNUM       , gdb_r14            , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "r15"   , NULL,    8,  0, eEncodingUint  , eFormatHex          , { gcc_dwarf_r15       , gcc_dwarf_r15       , LLDB_INVALID_REGNUM       , gdb_r15            , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "rip"   , "pc",    8,  0, eEncodingUint  , eFormatHex          , { gcc_dwarf_rip       , gcc_dwarf_rip       , LLDB_REGNUM_GENERIC_PC    , gdb_rip            , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "rflags", NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_REGNUM_GENERIC_FLAGS , gdb_rflags         , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "cs"    , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_cs             , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "ss"    , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_ss             , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "ds"    , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_ds             , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "es"    , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_es             , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "fs"    , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_fs             , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "gs"    , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_gs             , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "stmm0" , NULL,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_stmm0     , gcc_dwarf_stmm0     , LLDB_INVALID_REGNUM       , gdb_stmm0          , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "stmm1" , NULL,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_stmm1     , gcc_dwarf_stmm1     , LLDB_INVALID_REGNUM       , gdb_stmm1          , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "stmm2" , NULL,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_stmm2     , gcc_dwarf_stmm2     , LLDB_INVALID_REGNUM       , gdb_stmm2          , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "stmm3" , NULL,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_stmm3     , gcc_dwarf_stmm3     , LLDB_INVALID_REGNUM       , gdb_stmm3          , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "stmm4" , NULL,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_stmm4     , gcc_dwarf_stmm4     , LLDB_INVALID_REGNUM       , gdb_stmm4          , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "stmm5" , NULL,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_stmm5     , gcc_dwarf_stmm5     , LLDB_INVALID_REGNUM       , gdb_stmm5          , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "stmm6" , NULL,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_stmm6     , gcc_dwarf_stmm6     , LLDB_INVALID_REGNUM       , gdb_stmm6          , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "stmm7" , NULL,   10,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_stmm7     , gcc_dwarf_stmm7     , LLDB_INVALID_REGNUM       , gdb_stmm7          , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "fctrl" , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_fctrl          , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "fstat" , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_fstat          , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "ftag"  , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_ftag           , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "fiseg" , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_fiseg          , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "fioff" , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_fioff          , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "foseg" , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_foseg          , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "fooff" , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_fooff          , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "fop"   , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_fop            , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "xmm0"  , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm0      , gcc_dwarf_xmm0      , LLDB_INVALID_REGNUM       , gdb_xmm0           , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "xmm1"  , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm1      , gcc_dwarf_xmm1      , LLDB_INVALID_REGNUM       , gdb_xmm1           , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "xmm2"  , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm2      , gcc_dwarf_xmm2      , LLDB_INVALID_REGNUM       , gdb_xmm2           , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "xmm3"  , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm3      , gcc_dwarf_xmm3      , LLDB_INVALID_REGNUM       , gdb_xmm3           , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "xmm4"  , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm4      , gcc_dwarf_xmm4      , LLDB_INVALID_REGNUM       , gdb_xmm4           , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "xmm5"  , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm5      , gcc_dwarf_xmm5      , LLDB_INVALID_REGNUM       , gdb_xmm5           , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "xmm6"  , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm6      , gcc_dwarf_xmm6      , LLDB_INVALID_REGNUM       , gdb_xmm6           , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "xmm7"  , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm7      , gcc_dwarf_xmm7      , LLDB_INVALID_REGNUM       , gdb_xmm7           , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "xmm8"  , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm8      , gcc_dwarf_xmm8      , LLDB_INVALID_REGNUM       , gdb_xmm8           , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "xmm9"  , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm9      , gcc_dwarf_xmm9      , LLDB_INVALID_REGNUM       , gdb_xmm9           , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "xmm10" , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm10     , gcc_dwarf_xmm10     , LLDB_INVALID_REGNUM       , gdb_xmm10          , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "xmm11" , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm11     , gcc_dwarf_xmm11     , LLDB_INVALID_REGNUM       , gdb_xmm11          , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "xmm12" , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm12     , gcc_dwarf_xmm12     , LLDB_INVALID_REGNUM       , gdb_xmm12          , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "xmm13" , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm13     , gcc_dwarf_xmm13     , LLDB_INVALID_REGNUM       , gdb_xmm13          , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "xmm14" , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm14     , gcc_dwarf_xmm14     , LLDB_INVALID_REGNUM       , gdb_xmm14          , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "xmm15" , NULL,   16,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_xmm15     , gcc_dwarf_xmm15     , LLDB_INVALID_REGNUM       , gdb_xmm15          , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "mxcsr" , NULL,    4,  0, eEncodingUint  , eFormatHex          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM       , gdb_mxcsr          , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "ymm0"  , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm0      , gcc_dwarf_ymm0      , LLDB_INVALID_REGNUM       , gdb_ymm0           , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "ymm1"  , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm1      , gcc_dwarf_ymm1      , LLDB_INVALID_REGNUM       , gdb_ymm1           , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "ymm2"  , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm2      , gcc_dwarf_ymm2      , LLDB_INVALID_REGNUM       , gdb_ymm2           , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "ymm3"  , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm3      , gcc_dwarf_ymm3      , LLDB_INVALID_REGNUM       , gdb_ymm3           , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "ymm4"  , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm4      , gcc_dwarf_ymm4      , LLDB_INVALID_REGNUM       , gdb_ymm4           , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "ymm5"  , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm5      , gcc_dwarf_ymm5      , LLDB_INVALID_REGNUM       , gdb_ymm5           , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "ymm6"  , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm6      , gcc_dwarf_ymm6      , LLDB_INVALID_REGNUM       , gdb_ymm6           , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "ymm7"  , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm7      , gcc_dwarf_ymm7      , LLDB_INVALID_REGNUM       , gdb_ymm7           , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "ymm8"  , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm8      , gcc_dwarf_ymm8      , LLDB_INVALID_REGNUM       , gdb_ymm8           , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "ymm9"  , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm9      , gcc_dwarf_ymm9      , LLDB_INVALID_REGNUM       , gdb_ymm9           , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "ymm10" , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm10     , gcc_dwarf_ymm10     , LLDB_INVALID_REGNUM       , gdb_ymm10          , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "ymm11" , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm11     , gcc_dwarf_ymm11     , LLDB_INVALID_REGNUM       , gdb_ymm11          , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "ymm12" , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm12     , gcc_dwarf_ymm12     , LLDB_INVALID_REGNUM       , gdb_ymm12          , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "ymm13" , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm13     , gcc_dwarf_ymm13     , LLDB_INVALID_REGNUM       , gdb_ymm13          , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "ymm14" , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm14     , gcc_dwarf_ymm14     , LLDB_INVALID_REGNUM       , gdb_ymm14          , LLDB_INVALID_REGNUM },      NULL,              NULL},
+    { "ymm15" , NULL,   32,  0, eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_ymm15     , gcc_dwarf_ymm15     , LLDB_INVALID_REGNUM       , gdb_ymm15          , LLDB_INVALID_REGNUM },      NULL,              NULL}
+};
+
+static const uint32_t k_num_register_infos = sizeof(g_register_infos)/sizeof(RegisterInfo);
+static bool g_register_info_names_constified = false;
+
+const lldb_private::RegisterInfo *
+ABISysV_x86_64::GetRegisterInfoArray (uint32_t &count)
+{
+    // Make the C-string names and alt_names for the register infos into const 
+    // C-string values by having the ConstString unique the names in the global
+    // constant C-string pool.
+    if (!g_register_info_names_constified)
+    {
+        g_register_info_names_constified = true;
+        for (uint32_t i=0; i<k_num_register_infos; ++i)
+        {
+            if (g_register_infos[i].name)
+                g_register_infos[i].name = ConstString(g_register_infos[i].name).GetCString();
+            if (g_register_infos[i].alt_name)
+                g_register_infos[i].alt_name = ConstString(g_register_infos[i].alt_name).GetCString();
+        }
+    }
+    count = k_num_register_infos;
+    return g_register_infos;
+}
+
+
+size_t
+ABISysV_x86_64::GetRedZoneSize () const
+{
+    return 128;
+}
+
+//------------------------------------------------------------------
+// Static Functions
+//------------------------------------------------------------------
+ABISP
+ABISysV_x86_64::CreateInstance (const ArchSpec &arch)
+{
+    static ABISP g_abi_sp;
+    if (arch.GetTriple().getArch() == llvm::Triple::x86_64)
+    {
+        if (!g_abi_sp)
+            g_abi_sp.reset (new ABISysV_x86_64);
+        return g_abi_sp;
+    }
+    return ABISP();
+}
+
+bool
+ABISysV_x86_64::PrepareTrivialCall (Thread &thread, 
+                                    addr_t sp, 
+                                    addr_t func_addr, 
+                                    addr_t return_addr, 
+                                    addr_t *arg1_ptr,
+                                    addr_t *arg2_ptr,
+                                    addr_t *arg3_ptr,
+                                    addr_t *arg4_ptr,
+                                    addr_t *arg5_ptr,
+                                    addr_t *arg6_ptr) const
+{
+    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+    
+    if (log)
+    {
+        StreamString s;
+        s.Printf("ABISysV_x86_64::PrepareTrivialCall (tid = 0x%" PRIx64 ", sp = 0x%" PRIx64 ", func_addr = 0x%" PRIx64 ", return_addr = 0x%" PRIx64,
+                    thread.GetID(),
+                    (uint64_t)sp,
+                    (uint64_t)func_addr,
+                    (uint64_t)return_addr);
+
+        if (arg1_ptr)
+        {
+            s.Printf (", arg1 = 0x%" PRIx64, (uint64_t)*arg1_ptr);
+            if (arg2_ptr)
+            {
+                s.Printf (", arg2 = 0x%" PRIx64, (uint64_t)*arg2_ptr);
+                if (arg3_ptr)
+                {
+                    s.Printf (", arg3 = 0x%" PRIx64, (uint64_t)*arg3_ptr);
+                    if (arg4_ptr)
+                    {
+                        s.Printf (", arg4 = 0x%" PRIx64, (uint64_t)*arg4_ptr);
+                        if (arg5_ptr)
+                        {
+                            s.Printf (", arg5 = 0x%" PRIx64, (uint64_t)*arg5_ptr);
+                            if (arg6_ptr)
+                                s.Printf (", arg6 = 0x%" PRIx64, (uint64_t)*arg6_ptr);
+                        }
+                    }
+                }
+            }
+        }
+        s.PutCString (")");
+        log->PutCString(s.GetString().c_str());
+    }
+    
+    RegisterContext *reg_ctx = thread.GetRegisterContext().get();
+    if (!reg_ctx)
+        return false;
+    
+    const RegisterInfo *reg_info = NULL;
+    if (arg1_ptr)
+    {
+        reg_info = reg_ctx->GetRegisterInfoByName("rdi", 0);
+        if (log)
+            log->Printf("About to write arg1 (0x%" PRIx64 ") into %s", (uint64_t)*arg1_ptr, reg_info->name);
+
+        if (!reg_ctx->WriteRegisterFromUnsigned (reg_info, *arg1_ptr))
+            return false;
+
+        if (arg2_ptr)
+        {
+            reg_info = reg_ctx->GetRegisterInfoByName("rsi", 0);
+            if (log)
+                log->Printf("About to write arg2 (0x%" PRIx64 ") into %s", (uint64_t)*arg2_ptr, reg_info->name);
+            if (!reg_ctx->WriteRegisterFromUnsigned (reg_info, *arg2_ptr))
+                return false;
+
+            if (arg3_ptr)
+            {
+                reg_info = reg_ctx->GetRegisterInfoByName("rdx", 0);
+                if (log)
+                    log->Printf("About to write arg3 (0x%" PRIx64 ") into %s", (uint64_t)*arg3_ptr, reg_info->name);
+                if (!reg_ctx->WriteRegisterFromUnsigned (reg_info, *arg3_ptr))
+                    return false;
+
+                if (arg4_ptr)
+                {
+                    reg_info = reg_ctx->GetRegisterInfoByName("rcx", 0);
+                    if (log)
+                        log->Printf("About to write arg4 (0x%" PRIx64 ") into %s", (uint64_t)*arg4_ptr, reg_info->name);
+                    if (!reg_ctx->WriteRegisterFromUnsigned (reg_info, *arg4_ptr))
+                        return false;
+
+                    if (arg5_ptr)
+                    {
+                        reg_info = reg_ctx->GetRegisterInfoByName("r8", 0);
+                        if (log)
+                            log->Printf("About to write arg5 (0x%" PRIx64 ") into %s", (uint64_t)*arg5_ptr, reg_info->name);
+                        if (!reg_ctx->WriteRegisterFromUnsigned (reg_info, *arg5_ptr))
+                            return false;
+
+                        if (arg6_ptr)
+                        {
+                            reg_info = reg_ctx->GetRegisterInfoByName("r9", 0);
+                            if (log)
+                                log->Printf("About to write arg6 (0x%" PRIx64 ") into %s", (uint64_t)*arg6_ptr, reg_info->name);
+                            if (!reg_ctx->WriteRegisterFromUnsigned (reg_info, *arg6_ptr))
+                                return false;
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+
+    // First, align the SP
+
+    if (log)
+        log->Printf("16-byte aligning SP: 0x%" PRIx64 " to 0x%" PRIx64, (uint64_t)sp, (uint64_t)(sp & ~0xfull));
+
+    sp &= ~(0xfull); // 16-byte alignment
+
+    // The return address is pushed onto the stack (yes after the alignment...)
+    sp -= 8;
+
+    RegisterValue reg_value;
+    reg_value.SetUInt64 (return_addr);
+
+    if (log)
+        log->Printf("Pushing the return address onto the stack: new SP 0x%" PRIx64 ", return address 0x%" PRIx64, (uint64_t)sp, (uint64_t)return_addr);
+
+    const RegisterInfo *pc_reg_info = reg_ctx->GetRegisterInfoByName("rip");
+    Error error (reg_ctx->WriteRegisterValueToMemory(pc_reg_info, sp, pc_reg_info->byte_size, reg_value));
+    if (error.Fail())
+        return false;
+
+    // %rsp is set to the actual stack value.
+
+    if (log)
+        log->Printf("Writing SP (0x%" PRIx64 ") down", (uint64_t)sp);
+    
+    if (!reg_ctx->WriteRegisterFromUnsigned (reg_ctx->GetRegisterInfoByName("rsp"), sp))
+        return false;
+
+    // %rip is set to the address of the called function.
+    
+    if (log)
+        log->Printf("Writing new IP (0x%" PRIx64 ") down", (uint64_t)func_addr);
+
+    if (!reg_ctx->WriteRegisterFromUnsigned (pc_reg_info, func_addr))
+        return false;
+
+    return true;
+}
+
+static bool ReadIntegerArgument(Scalar           &scalar,
+                                unsigned int     bit_width,
+                                bool             is_signed,
+                                Thread           &thread,
+                                uint32_t         *argument_register_ids,
+                                unsigned int     &current_argument_register,
+                                addr_t           &current_stack_argument)
+{
+    if (bit_width > 64)
+        return false; // Scalar can't hold large integer arguments
+    
+    if (current_argument_register < 6)
+    {
+        scalar = thread.GetRegisterContext()->ReadRegisterAsUnsigned(argument_register_ids[current_argument_register], 0);
+        current_argument_register++;
+        if (is_signed)
+            scalar.SignExtend (bit_width);
+    }
+    else
+    {
+        uint32_t byte_size = (bit_width + (8-1))/8;
+        Error error;
+        if (thread.GetProcess()->ReadScalarIntegerFromMemory(current_stack_argument, byte_size, is_signed, scalar, error))
+        {
+            current_stack_argument += byte_size;
+            return true;
+        }
+        return false;
+    }
+    return true;
+}
+
+bool
+ABISysV_x86_64::GetArgumentValues (Thread &thread,
+                                   ValueList &values) const
+{
+    unsigned int num_values = values.GetSize();
+    unsigned int value_index;
+        
+    // Extract the register context so we can read arguments from registers
+    
+    RegisterContext *reg_ctx = thread.GetRegisterContext().get();
+    
+    if (!reg_ctx)
+        return false;
+    
+    // Get the pointer to the first stack argument so we have a place to start 
+    // when reading data
+    
+    addr_t sp = reg_ctx->GetSP(0);
+    
+    if (!sp)
+        return false;
+    
+    addr_t current_stack_argument = sp + 8; // jump over return address
+    
+    uint32_t argument_register_ids[6];
+    
+    argument_register_ids[0] = reg_ctx->GetRegisterInfoByName("rdi", 0)->kinds[eRegisterKindLLDB];
+    argument_register_ids[1] = reg_ctx->GetRegisterInfoByName("rsi", 0)->kinds[eRegisterKindLLDB];
+    argument_register_ids[2] = reg_ctx->GetRegisterInfoByName("rdx", 0)->kinds[eRegisterKindLLDB];
+    argument_register_ids[3] = reg_ctx->GetRegisterInfoByName("rcx", 0)->kinds[eRegisterKindLLDB];
+    argument_register_ids[4] = reg_ctx->GetRegisterInfoByName("r8", 0)->kinds[eRegisterKindLLDB];
+    argument_register_ids[5] = reg_ctx->GetRegisterInfoByName("r9", 0)->kinds[eRegisterKindLLDB];
+    
+    unsigned int current_argument_register = 0;
+    
+    for (value_index = 0;
+         value_index < num_values;
+         ++value_index)
+    {
+        Value *value = values.GetValueAtIndex(value_index);
+    
+        if (!value)
+            return false;
+        
+        // We currently only support extracting values with Clang QualTypes.
+        // Do we care about others?
+        ClangASTType clang_type = value->GetClangType();
+        if (!clang_type)
+            return false;
+        bool is_signed;
+        
+        if (clang_type.IsIntegerType (is_signed))
+        {
+            ReadIntegerArgument(value->GetScalar(),
+                                clang_type.GetBitSize(),
+                                is_signed,
+                                thread, 
+                                argument_register_ids, 
+                                current_argument_register,
+                                current_stack_argument);
+        }
+        else if (clang_type.IsPointerType ())
+        {
+            ReadIntegerArgument(value->GetScalar(),
+                                clang_type.GetBitSize(),
+                                false,
+                                thread,
+                                argument_register_ids, 
+                                current_argument_register,
+                                current_stack_argument);
+        }
+    }
+    
+    return true;
+}
+
+Error
+ABISysV_x86_64::SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value_sp)
+{
+    Error error;
+    if (!new_value_sp)
+    {
+        error.SetErrorString("Empty value object for return value.");
+        return error;
+    }
+    
+    ClangASTType clang_type = new_value_sp->GetClangType();
+    if (!clang_type)
+    {
+        error.SetErrorString ("Null clang type for return value.");
+        return error;
+    }
+    
+    Thread *thread = frame_sp->GetThread().get();
+    
+    bool is_signed;
+    uint32_t count;
+    bool is_complex;
+    
+    RegisterContext *reg_ctx = thread->GetRegisterContext().get();
+
+    bool set_it_simple = false;
+    if (clang_type.IsIntegerType (is_signed) || clang_type.IsPointerType())
+    {
+        const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName("rax", 0);
+
+        DataExtractor data;
+        size_t num_bytes = new_value_sp->GetData(data);
+        lldb::offset_t offset = 0;
+        if (num_bytes <= 8)
+        {
+            uint64_t raw_value = data.GetMaxU64(&offset, num_bytes);
+            
+            if (reg_ctx->WriteRegisterFromUnsigned (reg_info, raw_value))
+                set_it_simple = true;
+        }
+        else
+        {
+            error.SetErrorString("We don't support returning longer than 64 bit integer values at present.");
+        }
+
+    }
+    else if (clang_type.IsFloatingPointType (count, is_complex))
+    {
+        if (is_complex)
+            error.SetErrorString ("We don't support returning complex values at present");
+        else
+        {
+            size_t bit_width = clang_type.GetBitSize();
+            if (bit_width <= 64)
+            {
+                const RegisterInfo *xmm0_info = reg_ctx->GetRegisterInfoByName("xmm0", 0);
+                RegisterValue xmm0_value;
+                DataExtractor data;
+                size_t num_bytes = new_value_sp->GetData(data);
+
+                unsigned char buffer[16];
+                ByteOrder byte_order = data.GetByteOrder();
+                
+                data.CopyByteOrderedData (0, num_bytes, buffer, 16, byte_order);
+                xmm0_value.SetBytes(buffer, 16, byte_order);
+                reg_ctx->WriteRegister(xmm0_info, xmm0_value);
+                set_it_simple = true;
+            }
+            else
+            {
+                // FIXME - don't know how to do 80 bit long doubles yet.
+                error.SetErrorString ("We don't support returning float values > 64 bits at present");
+            }
+        }
+    }
+    
+    if (!set_it_simple)
+    {
+        // Okay we've got a structure or something that doesn't fit in a simple register.
+        // We should figure out where it really goes, but we don't support this yet.
+        error.SetErrorString ("We only support setting simple integer and float return types at present.");
+    }
+    
+    return error;
+}
+
+
+ValueObjectSP
+ABISysV_x86_64::GetReturnValueObjectSimple (Thread &thread,
+                                            ClangASTType &return_clang_type) const
+{
+    ValueObjectSP return_valobj_sp;
+    Value value;
+    
+    if (!return_clang_type)
+        return return_valobj_sp;
+
+    //value.SetContext (Value::eContextTypeClangType, return_value_type);
+    value.SetClangType (return_clang_type);
+    
+    RegisterContext *reg_ctx = thread.GetRegisterContext().get();
+    if (!reg_ctx)
+        return return_valobj_sp;
+    
+    const uint32_t type_flags = return_clang_type.GetTypeInfo ();
+    if (type_flags & ClangASTType::eTypeIsScalar)
+    {
+        value.SetValueType(Value::eValueTypeScalar);
+
+        bool success = false;
+        if (type_flags & ClangASTType::eTypeIsInteger)
+        {
+            // Extract the register context so we can read arguments from registers
+            
+            const size_t byte_size = return_clang_type.GetByteSize();
+            uint64_t raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("rax", 0), 0);
+            const bool is_signed = (type_flags & ClangASTType::eTypeIsSigned) != 0;
+            switch (byte_size)
+            {
+            default:
+                break;
+
+            case sizeof(uint64_t):
+                if (is_signed)
+                    value.GetScalar() = (int64_t)(raw_value);
+                else
+                    value.GetScalar() = (uint64_t)(raw_value);
+                success = true;
+                break;
+
+            case sizeof(uint32_t):
+                if (is_signed)
+                    value.GetScalar() = (int32_t)(raw_value & UINT32_MAX);
+                else
+                    value.GetScalar() = (uint32_t)(raw_value & UINT32_MAX);
+                success = true;
+                break;
+
+            case sizeof(uint16_t):
+                if (is_signed)
+                    value.GetScalar() = (int16_t)(raw_value & UINT16_MAX);
+                else
+                    value.GetScalar() = (uint16_t)(raw_value & UINT16_MAX);
+                success = true;
+                break;
+
+            case sizeof(uint8_t):
+                if (is_signed)
+                    value.GetScalar() = (int8_t)(raw_value & UINT8_MAX);
+                else
+                    value.GetScalar() = (uint8_t)(raw_value & UINT8_MAX);
+                success = true;
+                break;
+            }
+        }
+        else if (type_flags & ClangASTType::eTypeIsFloat)
+        {
+            if (type_flags & ClangASTType::eTypeIsComplex)
+            {
+                // Don't handle complex yet.
+            }
+            else
+            {
+                const size_t byte_size = return_clang_type.GetByteSize();
+                if (byte_size <= sizeof(long double))
+                {
+                    const RegisterInfo *xmm0_info = reg_ctx->GetRegisterInfoByName("xmm0", 0);
+                    RegisterValue xmm0_value;
+                    if (reg_ctx->ReadRegister (xmm0_info, xmm0_value))
+                    {
+                        DataExtractor data;
+                        if (xmm0_value.GetData(data))
+                        {
+                            lldb::offset_t offset = 0;
+                            if (byte_size == sizeof(float))
+                            {
+                                value.GetScalar() = (float) data.GetFloat(&offset);
+                                success = true;
+                            }
+                            else if (byte_size == sizeof(double))
+                            {
+                                value.GetScalar() = (double) data.GetDouble(&offset);
+                                success = true;
+                            }
+                            else if (byte_size == sizeof(long double))
+                            {
+                                // Don't handle long double since that can be encoded as 80 bit floats...
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        
+        if (success)
+            return_valobj_sp = ValueObjectConstResult::Create (thread.GetStackFrameAtIndex(0).get(),
+                                                               value,
+                                                               ConstString(""));
+
+    }
+    else if (type_flags & ClangASTType::eTypeIsPointer)
+    {
+        unsigned rax_id = reg_ctx->GetRegisterInfoByName("rax", 0)->kinds[eRegisterKindLLDB];
+        value.GetScalar() = (uint64_t)thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id, 0);
+        value.SetValueType(Value::eValueTypeScalar);
+        return_valobj_sp = ValueObjectConstResult::Create (thread.GetStackFrameAtIndex(0).get(),
+                                                           value,
+                                                           ConstString(""));
+    }
+    else if (type_flags & ClangASTType::eTypeIsVector)
+    {
+        const size_t byte_size = return_clang_type.GetByteSize();
+        if (byte_size > 0)
+        {
+
+            const RegisterInfo *altivec_reg = reg_ctx->GetRegisterInfoByName("ymm0", 0);
+            if (altivec_reg == NULL)
+            {
+                altivec_reg = reg_ctx->GetRegisterInfoByName("xmm0", 0);
+                if (altivec_reg == NULL)
+                    altivec_reg = reg_ctx->GetRegisterInfoByName("mm0", 0);
+            }
+            
+            if (altivec_reg)
+            {
+                if (byte_size <= altivec_reg->byte_size)
+                {
+                    ProcessSP process_sp (thread.GetProcess());
+                    if (process_sp)
+                    {
+                        std::unique_ptr<DataBufferHeap> heap_data_ap (new DataBufferHeap(byte_size, 0));
+                        const ByteOrder byte_order = process_sp->GetByteOrder();
+                        RegisterValue reg_value;
+                        if (reg_ctx->ReadRegister(altivec_reg, reg_value))
+                        {
+                            Error error;
+                            if (reg_value.GetAsMemoryData (altivec_reg,
+                                                           heap_data_ap->GetBytes(),
+                                                           heap_data_ap->GetByteSize(),
+                                                           byte_order,
+                                                           error))
+                            {
+                                DataExtractor data (DataBufferSP (heap_data_ap.release()),
+                                                    byte_order,
+                                                    process_sp->GetTarget().GetArchitecture().GetAddressByteSize());
+                                return_valobj_sp = ValueObjectConstResult::Create (&thread,
+                                                                                   return_clang_type,
+                                                                                   ConstString(""),
+                                                                                   data);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    
+    return return_valobj_sp;
+}
+
+ValueObjectSP
+ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clang_type) const
+{
+    ValueObjectSP return_valobj_sp;
+
+    if (!return_clang_type)
+        return return_valobj_sp;
+    
+    ExecutionContext exe_ctx (thread.shared_from_this());
+    return_valobj_sp = GetReturnValueObjectSimple(thread, return_clang_type);
+    if (return_valobj_sp)
+        return return_valobj_sp;
+    
+    RegisterContextSP reg_ctx_sp = thread.GetRegisterContext();
+    if (!reg_ctx_sp)
+        return return_valobj_sp;
+        
+    const size_t bit_width = return_clang_type.GetBitSize();
+    if (return_clang_type.IsAggregateType())
+    {
+        Target *target = exe_ctx.GetTargetPtr();
+        bool is_memory = true;
+        if (bit_width <= 128)
+        {
+            ByteOrder target_byte_order = target->GetArchitecture().GetByteOrder();
+            DataBufferSP data_sp (new DataBufferHeap(16, 0));
+            DataExtractor return_ext (data_sp, 
+                                      target_byte_order, 
+                                      target->GetArchitecture().GetAddressByteSize());
+                                                           
+            const RegisterInfo *rax_info = reg_ctx_sp->GetRegisterInfoByName("rax", 0);
+            const RegisterInfo *rdx_info = reg_ctx_sp->GetRegisterInfoByName("rdx", 0);
+            const RegisterInfo *xmm0_info = reg_ctx_sp->GetRegisterInfoByName("xmm0", 0);
+            const RegisterInfo *xmm1_info = reg_ctx_sp->GetRegisterInfoByName("xmm1", 0);
+            
+            RegisterValue rax_value, rdx_value, xmm0_value, xmm1_value;
+            reg_ctx_sp->ReadRegister (rax_info, rax_value);
+            reg_ctx_sp->ReadRegister (rdx_info, rdx_value);
+            reg_ctx_sp->ReadRegister (xmm0_info, xmm0_value);
+            reg_ctx_sp->ReadRegister (xmm1_info, xmm1_value);
+
+            DataExtractor rax_data, rdx_data, xmm0_data, xmm1_data;
+            
+            rax_value.GetData(rax_data);
+            rdx_value.GetData(rdx_data);
+            xmm0_value.GetData(xmm0_data);
+            xmm1_value.GetData(xmm1_data);
+            
+            uint32_t fp_bytes = 0;       // Tracks how much of the xmm registers we've consumed so far
+            uint32_t integer_bytes = 0;  // Tracks how much of the rax/rds registers we've consumed so far
+            
+            const uint32_t num_children = return_clang_type.GetNumFields ();
+            
+            // Since we are in the small struct regime, assume we are not in memory.
+            is_memory = false;
+            
+            for (uint32_t idx = 0; idx < num_children; idx++)
+            {
+                std::string name;
+                uint64_t field_bit_offset = 0;
+                bool is_signed;
+                bool is_complex;
+                uint32_t count;
+                
+                ClangASTType field_clang_type = return_clang_type.GetFieldAtIndex (idx, name, &field_bit_offset, NULL, NULL);
+                const size_t field_bit_width = field_clang_type.GetBitSize();
+
+                // If there are any unaligned fields, this is stored in memory.
+                if (field_bit_offset % field_bit_width != 0)
+                {
+                    is_memory = true;
+                    break;
+                }
+                
+                uint32_t field_byte_width = field_bit_width/8;
+                uint32_t field_byte_offset = field_bit_offset/8;
+                
+
+                DataExtractor *copy_from_extractor = NULL;
+                uint32_t       copy_from_offset    = 0;
+                
+                if (field_clang_type.IsIntegerType (is_signed) || field_clang_type.IsPointerType ())
+                {
+                    if (integer_bytes < 8)
+                    {
+                        if (integer_bytes + field_byte_width <= 8)
+                        {
+                            // This is in RAX, copy from register to our result structure:
+                            copy_from_extractor = &rax_data;
+                            copy_from_offset = integer_bytes;
+                            integer_bytes += field_byte_width;
+                        }
+                        else
+                        {
+                            // The next field wouldn't fit in the remaining space, so we pushed it to rdx.
+                            copy_from_extractor = &rdx_data;
+                            copy_from_offset = 0;
+                            integer_bytes = 8 + field_byte_width;
+                        
+                        }
+                    }
+                    else if (integer_bytes + field_byte_width <= 16)
+                    {
+                        copy_from_extractor = &rdx_data;
+                        copy_from_offset = integer_bytes - 8;
+                        integer_bytes += field_byte_width;
+                    }
+                    else
+                    {
+                        // The last field didn't fit.  I can't see how that would happen w/o the overall size being 
+                        // greater than 16 bytes.  For now, return a NULL return value object.
+                        return return_valobj_sp;
+                    }
+                }
+                else if (field_clang_type.IsFloatingPointType (count, is_complex))
+                {
+                    // Structs with long doubles are always passed in memory.
+                    if (field_bit_width == 128)
+                    {
+                        is_memory = true;
+                        break;
+                    }
+                    else if (field_bit_width == 64)
+                    {
+                        // These have to be in a single xmm register.
+                        if (fp_bytes == 0)
+                            copy_from_extractor = &xmm0_data;
+                        else
+                            copy_from_extractor = &xmm1_data;
+
+                        copy_from_offset = 0;
+                        fp_bytes += field_byte_width;
+                    }
+                    else if (field_bit_width == 32)
+                    {
+                        // This one is kind of complicated.  If we are in an "eightbyte" with another float, we'll
+                        // be stuffed into an xmm register with it.  If we are in an "eightbyte" with one or more ints,
+                        // then we will be stuffed into the appropriate GPR with them.
+                        bool in_gpr;
+                        if (field_byte_offset % 8 == 0) 
+                        {
+                            // We are at the beginning of one of the eightbytes, so check the next element (if any)
+                            if (idx == num_children - 1)
+                                in_gpr = false;
+                            else
+                            {
+                                uint64_t next_field_bit_offset = 0;
+                                ClangASTType next_field_clang_type = return_clang_type.GetFieldAtIndex (idx + 1,
+                                                                                                        name,
+                                                                                                        &next_field_bit_offset,
+                                                                                                        NULL,
+                                                                                                        NULL);
+                                if (next_field_clang_type.IsIntegerType (is_signed))
+                                    in_gpr = true;
+                                else
+                                {
+                                    copy_from_offset = 0;
+                                    in_gpr = false;
+                                }
+                            }
+                                
+                        }
+                        else if (field_byte_offset % 4 == 0)
+                        {
+                            // We are inside of an eightbyte, so see if the field before us is floating point:
+                            // This could happen if somebody put padding in the structure.
+                            if (idx == 0)
+                                in_gpr = false;
+                            else
+                            {
+                                uint64_t prev_field_bit_offset = 0;
+                                ClangASTType prev_field_clang_type = return_clang_type.GetFieldAtIndex (idx - 1,
+                                                                                                        name,
+                                                                                                        &prev_field_bit_offset,
+                                                                                                        NULL,
+                                                                                                        NULL);
+                                if (prev_field_clang_type.IsIntegerType (is_signed))
+                                    in_gpr = true;
+                                else
+                                {
+                                    copy_from_offset = 4;
+                                    in_gpr = false;
+                                }
+                            }
+                            
+                        }
+                        else
+                        {
+                            is_memory = true;
+                            continue;
+                        }
+                        
+                        // Okay, we've figured out whether we are in GPR or XMM, now figure out which one.
+                        if (in_gpr)
+                        {
+                            if (integer_bytes < 8)
+                            {
+                                // This is in RAX, copy from register to our result structure:
+                                copy_from_extractor = &rax_data;
+                                copy_from_offset = integer_bytes;
+                                integer_bytes += field_byte_width;
+                            }
+                            else
+                            {
+                                copy_from_extractor = &rdx_data;
+                                copy_from_offset = integer_bytes - 8;
+                                integer_bytes += field_byte_width;
+                            }
+                        }
+                        else
+                        {
+                            if (fp_bytes < 8)
+                                copy_from_extractor = &xmm0_data;
+                            else
+                                copy_from_extractor = &xmm1_data;
+
+                            fp_bytes += field_byte_width;
+                        }
+                    } 
+                }
+                
+                // These two tests are just sanity checks.  If I somehow get the
+                // type calculation wrong above it is better to just return nothing
+                // than to assert or crash.
+                if (!copy_from_extractor)
+                    return return_valobj_sp;
+                if (copy_from_offset + field_byte_width > copy_from_extractor->GetByteSize())
+                    return return_valobj_sp;
+                    
+                copy_from_extractor->CopyByteOrderedData (copy_from_offset, 
+                                                          field_byte_width, 
+                                                          data_sp->GetBytes() + field_byte_offset, 
+                                                          field_byte_width, 
+                                                          target_byte_order);
+            }
+            
+            if (!is_memory)
+            {
+                // The result is in our data buffer.  Let's make a variable object out of it:
+                return_valobj_sp = ValueObjectConstResult::Create (&thread, 
+                                                                   return_clang_type,
+                                                                   ConstString(""),
+                                                                   return_ext);
+            }
+        }
+        
+        
+        // FIXME: This is just taking a guess, rax may very well no longer hold the return storage location.
+        // If we are going to do this right, when we make a new frame we should check to see if it uses a memory
+        // return, and if we are at the first instruction and if so stash away the return location.  Then we would
+        // only return the memory return value if we know it is valid.
+        
+        if (is_memory)
+        {
+            unsigned rax_id = reg_ctx_sp->GetRegisterInfoByName("rax", 0)->kinds[eRegisterKindLLDB];
+            lldb::addr_t storage_addr = (uint64_t)thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id, 0);
+            return_valobj_sp = ValueObjectMemory::Create (&thread,
+                                                          "",
+                                                          Address (storage_addr, NULL),
+                                                          return_clang_type); 
+        }
+    }
+        
+    return return_valobj_sp;
+}
+
+bool
+ABISysV_x86_64::CreateFunctionEntryUnwindPlan (UnwindPlan &unwind_plan)
+{
+    uint32_t reg_kind = unwind_plan.GetRegisterKind();
+    uint32_t sp_reg_num = LLDB_INVALID_REGNUM;
+    uint32_t pc_reg_num = LLDB_INVALID_REGNUM;
+    
+    switch (reg_kind)
+    {
+    case eRegisterKindDWARF:
+    case eRegisterKindGCC:
+        sp_reg_num = gcc_dwarf_rsp;
+        pc_reg_num = gcc_dwarf_rip;
+        break;
+
+    case eRegisterKindGDB:
+        sp_reg_num = gdb_rsp;
+        pc_reg_num = gdb_rip;
+        break;
+
+    case eRegisterKindGeneric:
+        sp_reg_num = LLDB_REGNUM_GENERIC_SP;
+        pc_reg_num = LLDB_REGNUM_GENERIC_PC;
+        break;
+    }
+
+    if (sp_reg_num == LLDB_INVALID_REGNUM ||
+        pc_reg_num == LLDB_INVALID_REGNUM)
+        return false;
+
+    UnwindPlan::RowSP row(new UnwindPlan::Row);
+    row->SetCFARegister (sp_reg_num);
+    row->SetCFAOffset (8);
+    row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, -8, false);
+    unwind_plan.AppendRow (row);
+    unwind_plan.SetSourceName ("x86_64 at-func-entry default");
+    unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
+    return true;
+}
+
+bool
+ABISysV_x86_64::CreateDefaultUnwindPlan (UnwindPlan &unwind_plan)
+{
+    uint32_t reg_kind = unwind_plan.GetRegisterKind();
+    uint32_t fp_reg_num = LLDB_INVALID_REGNUM;
+    uint32_t sp_reg_num = LLDB_INVALID_REGNUM;
+    uint32_t pc_reg_num = LLDB_INVALID_REGNUM;
+    
+    switch (reg_kind)
+    {
+        case eRegisterKindDWARF:
+        case eRegisterKindGCC:
+            fp_reg_num = gcc_dwarf_rbp;
+            sp_reg_num = gcc_dwarf_rsp;
+            pc_reg_num = gcc_dwarf_rip;
+            break;
+            
+        case eRegisterKindGDB:
+            fp_reg_num = gdb_rbp;
+            sp_reg_num = gdb_rsp;
+            pc_reg_num = gdb_rip;
+            break;
+            
+        case eRegisterKindGeneric:
+            fp_reg_num = LLDB_REGNUM_GENERIC_FP;
+            sp_reg_num = LLDB_REGNUM_GENERIC_SP;
+            pc_reg_num = LLDB_REGNUM_GENERIC_PC;
+            break;
+    }
+
+    if (fp_reg_num == LLDB_INVALID_REGNUM ||
+        sp_reg_num == LLDB_INVALID_REGNUM ||
+        pc_reg_num == LLDB_INVALID_REGNUM)
+        return false;
+
+    UnwindPlan::RowSP row(new UnwindPlan::Row);
+
+    const int32_t ptr_size = 8;
+    row->SetCFARegister (LLDB_REGNUM_GENERIC_FP);
+    row->SetCFAOffset (2 * ptr_size);
+    row->SetOffset (0);
+    
+    row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, ptr_size * -2, true);
+    row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, ptr_size * -1, true);
+    row->SetRegisterLocationToAtCFAPlusOffset(sp_reg_num, ptr_size *  0, true);
+
+    unwind_plan.AppendRow (row);
+    unwind_plan.SetSourceName ("x86_64 default unwind plan");
+    unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
+    unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo);
+    return true;
+}
+
+bool
+ABISysV_x86_64::RegisterIsVolatile (const RegisterInfo *reg_info)
+{
+    return !RegisterIsCalleeSaved (reg_info);
+}
+
+
+
+// See "Register Usage" in the 
+// "System V Application Binary Interface"
+// "AMD64 Architecture Processor Supplement" 
+// (or "x86-64(tm) Architecture Processor Supplement" in earlier revisions)
+// (this doc is also commonly referred to as the x86-64/AMD64 psABI)
+// Edited by Michael Matz, Jan Hubicka, Andreas Jaeger, and Mark Mitchell
+// current version is 0.99.6 released 2012-07-02 at http://refspecs.linuxfoundation.org/elf/x86-64-abi-0.99.pdf
+
+bool
+ABISysV_x86_64::RegisterIsCalleeSaved (const RegisterInfo *reg_info)
+{
+    if (reg_info)
+    {
+        // Preserved registers are :
+        //    rbx, rsp, rbp, r12, r13, r14, r15
+        //    mxcsr (partially preserved)
+        //    x87 control word
+
+        const char *name = reg_info->name;
+        if (name[0] == 'r')
+        {
+            switch (name[1])
+            {
+            case '1': // r12, r13, r14, r15
+                if (name[2] >= '2' && name[2] <= '5')
+                    return name[3] == '\0';
+                break;
+
+            default:
+                break;
+            }
+        }
+
+        // Accept shorter-variant versions, rbx/ebx, rip/ eip, etc.
+        if (name[0] == 'r' || name[0] == 'e')
+        {
+            switch (name[1])
+            {
+            case 'b': // rbp, rbx
+                if (name[2] == 'p' || name[2] == 'x')
+                    return name[3] == '\0';
+                break;
+
+            case 'i': // rip
+                if (name[2] == 'p')
+                    return name[3] == '\0'; 
+                break;
+
+            case 's': // rsp
+                if (name[2] == 'p')
+                    return name[3] == '\0';
+                break;
+
+            }
+        }
+        if (name[0] == 's' && name[1] == 'p' && name[2] == '\0')   // sp
+            return true;
+        if (name[0] == 'f' && name[1] == 'p' && name[2] == '\0')   // fp
+            return true;
+        if (name[0] == 'p' && name[1] == 'c' && name[2] == '\0')   // pc
+            return true;
+    }
+    return false;
+}
+
+
+
+void
+ABISysV_x86_64::Initialize()
+{
+    PluginManager::RegisterPlugin (GetPluginNameStatic(),
+                                   "System V ABI for x86_64 targets",
+                                   CreateInstance);
+}
+
+void
+ABISysV_x86_64::Terminate()
+{
+    PluginManager::UnregisterPlugin (CreateInstance);
+}
+
+lldb_private::ConstString
+ABISysV_x86_64::GetPluginNameStatic()
+{
+    static ConstString g_name("sysv-x86_64");
+    return g_name;
+}
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+lldb_private::ConstString
+ABISysV_x86_64::GetPluginName()
+{
+    return GetPluginNameStatic();
+}
+
+uint32_t
+ABISysV_x86_64::GetPluginVersion()
+{
+    return 1;
+}
+
diff --git a/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h
new file mode 100644
index 000000000000..b10181960e89
--- /dev/null
+++ b/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h
@@ -0,0 +1,138 @@
+//===-- ABISysV_x86_64.h ----------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ABISysV_x86_64_h_
+#define liblldb_ABISysV_x86_64_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Target/ABI.h"
+
+class ABISysV_x86_64 :
+    public lldb_private::ABI
+{
+public:
+
+    ~ABISysV_x86_64()
+    {
+    }
+
+    virtual size_t
+    GetRedZoneSize () const;
+
+    virtual bool
+    PrepareTrivialCall (lldb_private::Thread &thread, 
+                        lldb::addr_t sp,
+                        lldb::addr_t functionAddress,
+                        lldb::addr_t returnAddress, 
+                        lldb::addr_t *arg1_ptr = NULL,
+                        lldb::addr_t *arg2_ptr = NULL,
+                        lldb::addr_t *arg3_ptr = NULL,
+                        lldb::addr_t *arg4_ptr = NULL,
+                        lldb::addr_t *arg5_ptr = NULL,
+                        lldb::addr_t *arg6_ptr = NULL) const;
+    
+    virtual bool
+    GetArgumentValues (lldb_private::Thread &thread,
+                       lldb_private::ValueList &values) const;
+    
+    virtual lldb_private::Error
+    SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value);
+
+protected:
+    lldb::ValueObjectSP
+    GetReturnValueObjectSimple (lldb_private::Thread &thread,
+                                lldb_private::ClangASTType &ast_type) const;
+    
+public:    
+    virtual lldb::ValueObjectSP
+    GetReturnValueObjectImpl (lldb_private::Thread &thread,
+                          lldb_private::ClangASTType &type) const;
+
+    virtual bool
+    CreateFunctionEntryUnwindPlan (lldb_private::UnwindPlan &unwind_plan);
+    
+    virtual bool
+    CreateDefaultUnwindPlan (lldb_private::UnwindPlan &unwind_plan);
+        
+    virtual bool
+    RegisterIsVolatile (const lldb_private::RegisterInfo *reg_info);
+    
+    virtual bool
+    StackUsesFrames ()
+    {
+        return true;
+    }
+    
+    virtual bool
+    CallFrameAddressIsValid (lldb::addr_t cfa)
+    {
+        // Make sure the stack call frame addresses are are 8 byte aligned
+        if (cfa & (8ull - 1ull))
+            return false;   // Not 8 byte aligned
+        if (cfa == 0)
+            return false;   // Zero is not a valid stack address
+        return true;
+    }
+    
+    virtual bool
+    CodeAddressIsValid (lldb::addr_t pc)
+    {
+        // We have a 64 bit address space, so anything is valid as opcodes
+        // aren't fixed width...
+        return true;
+    }
+
+    virtual bool
+    FunctionCallsChangeCFA ()
+    {
+        return true;
+    }
+
+    virtual const lldb_private::RegisterInfo *
+    GetRegisterInfoArray (uint32_t &count);
+    //------------------------------------------------------------------
+    // Static Functions
+    //------------------------------------------------------------------
+    static void
+    Initialize();
+
+    static void
+    Terminate();
+
+    static lldb::ABISP
+    CreateInstance (const lldb_private::ArchSpec &arch);
+
+    static lldb_private::ConstString
+    GetPluginNameStatic();
+    
+    //------------------------------------------------------------------
+    // PluginInterface protocol
+    //------------------------------------------------------------------
+    virtual lldb_private::ConstString
+    GetPluginName();
+
+    virtual uint32_t
+    GetPluginVersion();
+
+protected:
+    void
+    CreateRegisterMapIfNeeded ();
+
+    bool
+    RegisterIsCalleeSaved (const lldb_private::RegisterInfo *reg_info);
+
+private:
+    ABISysV_x86_64() : lldb_private::ABI() { } // Call CreateInstance instead.
+};
+
+#endif  // liblldb_ABI_h_
diff --git a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp
new file mode 100644
index 000000000000..e920d70cd596
--- /dev/null
+++ b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp
@@ -0,0 +1,864 @@
+//===-- DisassemblerLLVMC.cpp -----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DisassemblerLLVMC.h"
+
+#include "llvm-c/Disassembler.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCDisassembler.h"
+#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCInstPrinter.h"
+#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCRelocationInfo.h"
+#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MemoryObject.h"
+#include "llvm/Support/TargetRegistry.h"
+#include "llvm/Support/TargetSelect.h"
+#include "llvm/ADT/SmallString.h"
+
+
+#include "lldb/Core/Address.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/StackFrame.h"
+
+#include <regex.h>
+
+using namespace lldb;
+using namespace lldb_private;
+
+class InstructionLLVMC : public lldb_private::Instruction
+{
+public:
+    InstructionLLVMC (DisassemblerLLVMC &disasm,
+                      const lldb_private::Address &address, 
+                      AddressClass addr_class) :
+        Instruction (address, addr_class),
+        m_disasm_sp (disasm.shared_from_this()),
+        m_does_branch (eLazyBoolCalculate),
+        m_is_valid (false),
+        m_using_file_addr (false)
+    {
+    }
+    
+    virtual
+    ~InstructionLLVMC ()
+    {
+    }
+    
+    virtual bool
+    DoesBranch ()
+    {
+        if (m_does_branch == eLazyBoolCalculate)
+        {
+            GetDisassemblerLLVMC().Lock(this, NULL);
+            DataExtractor data;
+            if (m_opcode.GetData(data))
+            {
+                bool is_alternate_isa;
+                lldb::addr_t pc = m_address.GetFileAddress();
+
+                DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr = GetDisasmToUse (is_alternate_isa);
+                const uint8_t *opcode_data = data.GetDataStart();
+                const size_t opcode_data_len = data.GetByteSize();
+                llvm::MCInst inst;
+                const size_t inst_size = mc_disasm_ptr->GetMCInst (opcode_data,
+                                                                   opcode_data_len,
+                                                                   pc,
+                                                                   inst);
+                // Be conservative, if we didn't understand the instruction, say it might branch...
+                if (inst_size == 0)
+                    m_does_branch = eLazyBoolYes;
+                else
+                {
+                    const bool can_branch = mc_disasm_ptr->CanBranch(inst);
+                    if (can_branch)
+                        m_does_branch = eLazyBoolYes;
+                    else
+                        m_does_branch = eLazyBoolNo;
+                }
+            }
+            GetDisassemblerLLVMC().Unlock();
+        }
+        return m_does_branch == eLazyBoolYes;
+    }
+    
+    DisassemblerLLVMC::LLVMCDisassembler *
+    GetDisasmToUse (bool &is_alternate_isa)
+    {
+        is_alternate_isa = false;
+        DisassemblerLLVMC &llvm_disasm = GetDisassemblerLLVMC();
+        if (llvm_disasm.m_alternate_disasm_ap.get() != NULL)
+        {
+            const AddressClass address_class = GetAddressClass ();
+        
+            if (address_class == eAddressClassCodeAlternateISA)
+            {
+                is_alternate_isa = true;
+                return llvm_disasm.m_alternate_disasm_ap.get();
+            }
+        }
+        return llvm_disasm.m_disasm_ap.get();
+    }
+    
+    virtual size_t
+    Decode (const lldb_private::Disassembler &disassembler,
+            const lldb_private::DataExtractor &data,
+            lldb::offset_t data_offset)
+    {
+        // All we have to do is read the opcode which can be easy for some
+        // architectures
+        bool got_op = false;
+        DisassemblerLLVMC &llvm_disasm = GetDisassemblerLLVMC();
+        const ArchSpec &arch = llvm_disasm.GetArchitecture();
+        
+        const uint32_t min_op_byte_size = arch.GetMinimumOpcodeByteSize();
+        const uint32_t max_op_byte_size = arch.GetMaximumOpcodeByteSize();
+        if (min_op_byte_size == max_op_byte_size)
+        {
+            // Fixed size instructions, just read that amount of data.
+            if (!data.ValidOffsetForDataOfSize(data_offset, min_op_byte_size))
+                return false;
+            
+            switch (min_op_byte_size)
+            {
+                case 1:
+                    m_opcode.SetOpcode8  (data.GetU8  (&data_offset));
+                    got_op = true;
+                    break;
+
+                case 2:
+                    m_opcode.SetOpcode16 (data.GetU16 (&data_offset));
+                    got_op = true;
+                    break;
+
+                case 4:
+                    m_opcode.SetOpcode32 (data.GetU32 (&data_offset));
+                    got_op = true;
+                    break;
+
+                case 8:
+                    m_opcode.SetOpcode64 (data.GetU64 (&data_offset));
+                    got_op = true;
+                    break;
+
+                default:
+                    m_opcode.SetOpcodeBytes(data.PeekData(data_offset, min_op_byte_size), min_op_byte_size);
+                    got_op = true;
+                    break;
+            }
+        }
+        if (!got_op)
+        {
+            bool is_alternate_isa = false;
+            DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr = GetDisasmToUse (is_alternate_isa);
+            
+            const llvm::Triple::ArchType machine = arch.GetMachine();
+            if (machine == llvm::Triple::arm || machine == llvm::Triple::thumb)
+            {
+                if (machine == llvm::Triple::thumb || is_alternate_isa)
+                {
+                    uint32_t thumb_opcode = data.GetU16(&data_offset);
+                    if ((thumb_opcode & 0xe000) != 0xe000 || ((thumb_opcode & 0x1800u) == 0))
+                    {
+                        m_opcode.SetOpcode16 (thumb_opcode);
+                        m_is_valid = true;
+                    }
+                    else
+                    {
+                        thumb_opcode <<= 16;
+                        thumb_opcode |= data.GetU16(&data_offset);
+                        m_opcode.SetOpcode16_2 (thumb_opcode);
+                        m_is_valid = true;
+                    }
+                }
+                else
+                {
+                    m_opcode.SetOpcode32 (data.GetU32(&data_offset));
+                    m_is_valid = true;
+                }
+            }
+            else
+            {
+                // The opcode isn't evenly sized, so we need to actually use the llvm
+                // disassembler to parse it and get the size.
+                uint8_t *opcode_data = const_cast<uint8_t *>(data.PeekData (data_offset, 1));
+                const size_t opcode_data_len = data.BytesLeft(data_offset);
+                const addr_t pc = m_address.GetFileAddress();
+                llvm::MCInst inst;
+                
+                llvm_disasm.Lock(this, NULL);
+                const size_t inst_size = mc_disasm_ptr->GetMCInst(opcode_data,
+                                                                  opcode_data_len,
+                                                                  pc,
+                                                                  inst);
+                llvm_disasm.Unlock();
+                if (inst_size == 0)
+                    m_opcode.Clear();
+                else
+                {
+                    m_opcode.SetOpcodeBytes(opcode_data, inst_size);
+                    m_is_valid = true;
+                }
+            }
+        }
+        return m_opcode.GetByteSize();
+    }
+    
+    void
+    AppendComment (std::string &description)
+    {
+        if (m_comment.empty())
+            m_comment.swap (description);
+        else
+        {
+            m_comment.append(", ");
+            m_comment.append(description);
+        }
+    }
+    
+    virtual void
+    CalculateMnemonicOperandsAndComment (const lldb_private::ExecutionContext *exe_ctx)
+    {
+        DataExtractor data;
+        const AddressClass address_class = GetAddressClass ();
+
+        if (m_opcode.GetData(data))
+        {
+            char out_string[512];
+            
+            DisassemblerLLVMC &llvm_disasm = GetDisassemblerLLVMC();
+
+            DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr;
+            
+            if (address_class == eAddressClassCodeAlternateISA)
+                mc_disasm_ptr = llvm_disasm.m_alternate_disasm_ap.get();
+            else
+                mc_disasm_ptr = llvm_disasm.m_disasm_ap.get();
+            
+            lldb::addr_t pc = m_address.GetFileAddress();
+            m_using_file_addr = true;
+            
+            const bool data_from_file = GetDisassemblerLLVMC().m_data_from_file;
+            bool use_hex_immediates = true;
+            Disassembler::HexImmediateStyle hex_style = Disassembler::eHexStyleC;
+
+            if (exe_ctx)
+            {
+                Target *target = exe_ctx->GetTargetPtr();
+                if (target)
+                {
+                    use_hex_immediates = target->GetUseHexImmediates();
+                    hex_style = target->GetHexImmediateStyle();
+
+                    if (!data_from_file)
+                    {
+                        const lldb::addr_t load_addr = m_address.GetLoadAddress(target);
+                        if (load_addr != LLDB_INVALID_ADDRESS)
+                        {
+                            pc = load_addr;
+                            m_using_file_addr = false;
+                        }
+                    }
+                }
+            }
+            
+            llvm_disasm.Lock(this, exe_ctx);
+            
+            const uint8_t *opcode_data = data.GetDataStart();
+            const size_t opcode_data_len = data.GetByteSize();
+            llvm::MCInst inst;
+            size_t inst_size = mc_disasm_ptr->GetMCInst (opcode_data,
+                                                         opcode_data_len,
+                                                         pc,
+                                                         inst);
+
+            if (inst_size > 0)
+            {
+                mc_disasm_ptr->SetStyle(use_hex_immediates, hex_style);
+                mc_disasm_ptr->PrintMCInst(inst, out_string, sizeof(out_string));
+            }
+
+            llvm_disasm.Unlock();
+            
+            if (inst_size == 0)
+            {
+                m_comment.assign ("unknown opcode");
+                inst_size = m_opcode.GetByteSize();
+                StreamString mnemonic_strm;
+                lldb::offset_t offset = 0;
+                switch (inst_size)
+                {
+                    case 1:
+                        {
+                            const uint8_t uval8 = data.GetU8 (&offset);
+                            m_opcode.SetOpcode8 (uval8);
+                            m_opcode_name.assign (".byte");
+                            mnemonic_strm.Printf("0x%2.2x", uval8);
+                        }
+                        break;
+                    case 2:
+                        {
+                            const uint16_t uval16 = data.GetU16(&offset);
+                            m_opcode.SetOpcode16(uval16);
+                            m_opcode_name.assign (".short");
+                            mnemonic_strm.Printf("0x%4.4x", uval16);
+                        }
+                        break;
+                    case 4:
+                        {
+                            const uint32_t uval32 = data.GetU32(&offset);
+                            m_opcode.SetOpcode32(uval32);
+                            m_opcode_name.assign (".long");
+                            mnemonic_strm.Printf("0x%8.8x", uval32);
+                        }
+                        break;
+                    case 8:
+                        {
+                            const uint64_t uval64 = data.GetU64(&offset);
+                            m_opcode.SetOpcode64(uval64);
+                            m_opcode_name.assign (".quad");
+                            mnemonic_strm.Printf("0x%16.16" PRIx64, uval64);
+                        }
+                        break;
+                    default:
+                        if (inst_size == 0)
+                            return;
+                        else
+                        {
+                            const uint8_t *bytes = data.PeekData(offset, inst_size);
+                            if (bytes == NULL)
+                                return;
+                            m_opcode_name.assign (".byte");
+                            m_opcode.SetOpcodeBytes(bytes, inst_size);
+                            mnemonic_strm.Printf("0x%2.2x", bytes[0]);
+                            for (uint32_t i=1; i<inst_size; ++i)
+                                mnemonic_strm.Printf(" 0x%2.2x", bytes[i]);
+                        }
+                        break;
+                }
+                m_mnemonics.swap(mnemonic_strm.GetString());
+                return;
+            }
+            else
+            {
+                if (m_does_branch == eLazyBoolCalculate)
+                {
+                    const bool can_branch = mc_disasm_ptr->CanBranch(inst);
+                    if (can_branch)
+                        m_does_branch = eLazyBoolYes;
+                    else
+                        m_does_branch = eLazyBoolNo;
+
+                }
+            }
+            
+            if (!s_regex_compiled)
+            {
+                ::regcomp(&s_regex, "[ \t]*([^ ^\t]+)[ \t]*([^ ^\t].*)?", REG_EXTENDED);
+                s_regex_compiled = true;
+            }
+            
+            ::regmatch_t matches[3];
+            
+            if (!::regexec(&s_regex, out_string, sizeof(matches) / sizeof(::regmatch_t), matches, 0))
+            {
+                if (matches[1].rm_so != -1)
+                    m_opcode_name.assign(out_string + matches[1].rm_so, matches[1].rm_eo - matches[1].rm_so);
+                if (matches[2].rm_so != -1)
+                    m_mnemonics.assign(out_string + matches[2].rm_so, matches[2].rm_eo - matches[2].rm_so);
+            }
+        }
+    }
+    
+    bool
+    IsValid () const
+    {
+        return m_is_valid;
+    }
+    
+    bool
+    UsingFileAddress() const
+    {
+        return m_using_file_addr;
+    }
+    size_t
+    GetByteSize () const
+    {
+        return m_opcode.GetByteSize();
+    }
+    
+    DisassemblerLLVMC &
+    GetDisassemblerLLVMC ()
+    {
+        return *(DisassemblerLLVMC *)m_disasm_sp.get();
+    }
+protected:
+    
+    DisassemblerSP          m_disasm_sp; // for ownership
+    LazyBool                m_does_branch;
+    bool                    m_is_valid;
+    bool                    m_using_file_addr;
+    
+    static bool             s_regex_compiled;
+    static ::regex_t        s_regex;
+};
+
+bool InstructionLLVMC::s_regex_compiled = false;
+::regex_t InstructionLLVMC::s_regex;
+
+DisassemblerLLVMC::LLVMCDisassembler::LLVMCDisassembler (const char *triple, unsigned flavor, DisassemblerLLVMC &owner):
+    m_is_valid(true)
+{
+    std::string Error;
+    const llvm::Target *curr_target = llvm::TargetRegistry::lookupTarget(triple, Error);
+    if (!curr_target)
+    {
+        m_is_valid = false;
+        return;
+    }
+    
+    m_instr_info_ap.reset(curr_target->createMCInstrInfo());
+    m_reg_info_ap.reset (curr_target->createMCRegInfo(triple));
+    
+    std::string features_str;
+
+    m_subtarget_info_ap.reset(curr_target->createMCSubtargetInfo(triple, "",
+                                                                features_str));
+    
+    m_asm_info_ap.reset(curr_target->createMCAsmInfo(*curr_target->createMCRegInfo(triple), triple));
+
+    if (m_instr_info_ap.get() == NULL || m_reg_info_ap.get() == NULL || m_subtarget_info_ap.get() == NULL || m_asm_info_ap.get() == NULL)
+    {
+        m_is_valid = false;
+        return;
+    }
+    
+    m_context_ap.reset(new llvm::MCContext(m_asm_info_ap.get(), m_reg_info_ap.get(), 0));
+    
+    m_disasm_ap.reset(curr_target->createMCDisassembler(*m_subtarget_info_ap.get()));
+    if (m_disasm_ap.get() && m_context_ap.get())
+    {
+        llvm::OwningPtr<llvm::MCRelocationInfo> RelInfo(curr_target->createMCRelocationInfo(triple, *m_context_ap.get()));
+        if (!RelInfo)
+        {
+            m_is_valid = false;
+            return;
+        }
+        m_disasm_ap->setupForSymbolicDisassembly(NULL,
+                                                 DisassemblerLLVMC::SymbolLookupCallback,
+                                                 (void *) &owner,
+                                                 m_context_ap.get(),
+                                                 RelInfo);
+        
+        unsigned asm_printer_variant;
+        if (flavor == ~0U)
+            asm_printer_variant = m_asm_info_ap->getAssemblerDialect();
+        else
+        {
+            asm_printer_variant = flavor;
+        }
+        
+        m_instr_printer_ap.reset(curr_target->createMCInstPrinter(asm_printer_variant,
+                                                                  *m_asm_info_ap.get(),
+                                                                  *m_instr_info_ap.get(),
+                                                                  *m_reg_info_ap.get(),
+                                                                  *m_subtarget_info_ap.get()));
+        if (m_instr_printer_ap.get() == NULL)
+        {
+            m_disasm_ap.reset();
+            m_is_valid = false;
+        }
+    }
+    else
+        m_is_valid = false;
+}
+
+DisassemblerLLVMC::LLVMCDisassembler::~LLVMCDisassembler()
+{
+}
+
+namespace {
+    // This is the memory object we use in GetInstruction.
+    class LLDBDisasmMemoryObject : public llvm::MemoryObject {
+      const uint8_t *m_bytes;
+      uint64_t m_size;
+      uint64_t m_base_PC;
+    public:
+      LLDBDisasmMemoryObject(const uint8_t *bytes, uint64_t size, uint64_t basePC) :
+                         m_bytes(bytes), m_size(size), m_base_PC(basePC) {}
+     
+      uint64_t getBase() const { return m_base_PC; }
+      uint64_t getExtent() const { return m_size; }
+
+      int readByte(uint64_t addr, uint8_t *byte) const {
+        if (addr - m_base_PC >= m_size)
+          return -1;
+        *byte = m_bytes[addr - m_base_PC];
+        return 0;
+      }
+    };
+} // End Anonymous Namespace
+
+uint64_t
+DisassemblerLLVMC::LLVMCDisassembler::GetMCInst (const uint8_t *opcode_data,
+                                                 size_t opcode_data_len,
+                                                 lldb::addr_t pc,
+                                                 llvm::MCInst &mc_inst)
+{
+    LLDBDisasmMemoryObject memory_object (opcode_data, opcode_data_len, pc);
+    llvm::MCDisassembler::DecodeStatus status;
+
+    uint64_t new_inst_size;
+    status = m_disasm_ap->getInstruction(mc_inst,
+                                         new_inst_size,
+                                         memory_object,
+                                         pc,
+                                         llvm::nulls(),
+                                         llvm::nulls());
+    if (status == llvm::MCDisassembler::Success)
+        return new_inst_size;
+    else
+        return 0;
+}
+
+uint64_t
+DisassemblerLLVMC::LLVMCDisassembler::PrintMCInst (llvm::MCInst &mc_inst,
+                                                   char *dst,
+                                                   size_t dst_len)
+{
+    llvm::StringRef unused_annotations;
+    llvm::SmallString<64> inst_string;
+    llvm::raw_svector_ostream inst_stream(inst_string);
+    m_instr_printer_ap->printInst (&mc_inst, inst_stream, unused_annotations);
+    inst_stream.flush();
+    const size_t output_size = std::min(dst_len - 1, inst_string.size());
+    std::memcpy(dst, inst_string.data(), output_size);
+    dst[output_size] = '\0';
+    
+    return output_size;
+}
+
+void
+DisassemblerLLVMC::LLVMCDisassembler::SetStyle (bool use_hex_immed, HexImmediateStyle hex_style)
+{
+    m_instr_printer_ap->setPrintImmHex(use_hex_immed);
+    switch(hex_style)
+    {
+    case eHexStyleC:      m_instr_printer_ap->setPrintImmHex(llvm::HexStyle::C); break;
+    case eHexStyleAsm:    m_instr_printer_ap->setPrintImmHex(llvm::HexStyle::Asm); break;
+    }
+}
+
+bool
+DisassemblerLLVMC::LLVMCDisassembler::CanBranch (llvm::MCInst &mc_inst)
+{
+    return m_instr_info_ap->get(mc_inst.getOpcode()).mayAffectControlFlow(mc_inst, *m_reg_info_ap.get());
+}
+
+bool
+DisassemblerLLVMC::FlavorValidForArchSpec (const lldb_private::ArchSpec &arch, const char *flavor)
+{
+    llvm::Triple triple = arch.GetTriple();
+    if (flavor == NULL || strcmp (flavor, "default") == 0)
+        return true;
+    
+    if (triple.getArch() == llvm::Triple::x86 || triple.getArch() == llvm::Triple::x86_64)
+    {
+        if (strcmp (flavor, "intel") == 0 || strcmp (flavor, "att") == 0)
+            return true;
+        else
+            return false;
+    }
+    else
+        return false;
+}
+    
+
+Disassembler *
+DisassemblerLLVMC::CreateInstance (const ArchSpec &arch, const char *flavor)
+{
+    if (arch.GetTriple().getArch() != llvm::Triple::UnknownArch)
+    {
+        std::unique_ptr<DisassemblerLLVMC> disasm_ap (new DisassemblerLLVMC(arch, flavor));
+    
+        if (disasm_ap.get() && disasm_ap->IsValid())
+            return disasm_ap.release();
+    }
+    return NULL;
+}
+
+DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_string) :
+    Disassembler(arch, flavor_string),
+    m_exe_ctx (NULL),
+    m_inst (NULL),
+    m_data_from_file (false)
+{
+    if (!FlavorValidForArchSpec (arch, m_flavor.c_str()))
+    {
+        m_flavor.assign("default");
+    }
+    
+    const char *triple = arch.GetTriple().getTriple().c_str();
+    unsigned flavor = ~0U;
+    
+    // So far the only supported flavor is "intel" on x86.  The base class will set this
+    // correctly coming in.
+    if (arch.GetTriple().getArch() == llvm::Triple::x86
+        || arch.GetTriple().getArch() == llvm::Triple::x86_64)
+    {
+        if (m_flavor == "intel")
+        {
+            flavor = 1;
+        }
+        else if (m_flavor == "att")
+        {
+            flavor = 0;
+        }
+    }
+    
+    ArchSpec thumb_arch(arch);
+    if (arch.GetTriple().getArch() == llvm::Triple::arm)
+    {
+        std::string thumb_arch_name (thumb_arch.GetTriple().getArchName().str());
+        // Replace "arm" with "thumb" so we get all thumb variants correct
+        if (thumb_arch_name.size() > 3)
+        {
+            thumb_arch_name.erase(0,3);
+            thumb_arch_name.insert(0, "thumb");
+        }
+        else
+        {
+            thumb_arch_name = "thumbv7";
+        }
+        thumb_arch.GetTriple().setArchName(llvm::StringRef(thumb_arch_name.c_str()));
+    }
+    
+    // Cortex-M3 devices (e.g. armv7m) can only execute thumb (T2) instructions, 
+    // so hardcode the primary disassembler to thumb mode.
+    if (arch.GetTriple().getArch() == llvm::Triple::arm
+        && (arch.GetCore() == ArchSpec::Core::eCore_arm_armv7m || arch.GetCore() == ArchSpec::Core::eCore_arm_armv7em))
+    {
+        triple = thumb_arch.GetTriple().getTriple().c_str();
+    }
+
+    m_disasm_ap.reset (new LLVMCDisassembler(triple, flavor, *this));
+    if (!m_disasm_ap->IsValid())
+    {
+        // We use m_disasm_ap.get() to tell whether we are valid or not, so if this isn't good for some reason,
+        // we reset it, and then we won't be valid and FindPlugin will fail and we won't get used.
+        m_disasm_ap.reset();
+    }
+
+    // For arm CPUs that can execute arm or thumb instructions, also create a thumb instruction disassembler.
+    if (arch.GetTriple().getArch() == llvm::Triple::arm)
+    {
+        std::string thumb_triple(thumb_arch.GetTriple().getTriple());
+        m_alternate_disasm_ap.reset(new LLVMCDisassembler(thumb_triple.c_str(), flavor, *this));
+        if (!m_alternate_disasm_ap->IsValid())
+        {
+            m_disasm_ap.reset();
+            m_alternate_disasm_ap.reset();
+        }
+    }
+}
+
+DisassemblerLLVMC::~DisassemblerLLVMC()
+{
+}
+
+size_t
+DisassemblerLLVMC::DecodeInstructions (const Address &base_addr,
+                                       const DataExtractor& data,
+                                       lldb::offset_t data_offset,
+                                       size_t num_instructions,
+                                       bool append,
+                                       bool data_from_file)
+{
+    if (!append)
+        m_instruction_list.Clear();
+    
+    if (!IsValid())
+        return 0;
+    
+    m_data_from_file = data_from_file;
+    uint32_t data_cursor = data_offset;
+    const size_t data_byte_size = data.GetByteSize();
+    uint32_t instructions_parsed = 0;
+    Address inst_addr(base_addr);
+    
+    while (data_cursor < data_byte_size && instructions_parsed < num_instructions)
+    {
+        
+        AddressClass address_class = eAddressClassCode;
+        
+        if (m_alternate_disasm_ap.get() != NULL)
+            address_class = inst_addr.GetAddressClass ();
+        
+        InstructionSP inst_sp(new InstructionLLVMC(*this,
+                                                   inst_addr, 
+                                                   address_class));
+        
+        if (!inst_sp)
+            break;
+        
+        uint32_t inst_size = inst_sp->Decode(*this, data, data_cursor);
+                
+        if (inst_size == 0)
+            break;
+
+        m_instruction_list.Append(inst_sp);
+        data_cursor += inst_size;
+        inst_addr.Slide(inst_size);
+        instructions_parsed++;
+    }
+    
+    return data_cursor - data_offset;
+}
+
+void
+DisassemblerLLVMC::Initialize()
+{
+    PluginManager::RegisterPlugin (GetPluginNameStatic(),
+                                   "Disassembler that uses LLVM MC to disassemble i386, x86_64 and ARM.",
+                                   CreateInstance);
+    
+    llvm::InitializeAllTargetInfos();
+    llvm::InitializeAllTargetMCs();
+    llvm::InitializeAllAsmParsers();
+    llvm::InitializeAllDisassemblers();
+}
+
+void
+DisassemblerLLVMC::Terminate()
+{
+    PluginManager::UnregisterPlugin (CreateInstance);
+}
+
+
+ConstString
+DisassemblerLLVMC::GetPluginNameStatic()
+{
+    static ConstString g_name("llvm-mc");
+    return g_name;
+}
+
+int DisassemblerLLVMC::OpInfoCallback (void *disassembler,
+                                       uint64_t pc,
+                                       uint64_t offset,
+                                       uint64_t size,
+                                       int tag_type,
+                                       void *tag_bug)
+{
+    return static_cast<DisassemblerLLVMC*>(disassembler)->OpInfo (pc,
+                                                                  offset,
+                                                                  size,
+                                                                  tag_type,
+                                                                  tag_bug);
+}
+
+const char *DisassemblerLLVMC::SymbolLookupCallback (void *disassembler,
+                                                     uint64_t value,
+                                                     uint64_t *type,
+                                                     uint64_t pc,
+                                                     const char **name)
+{
+    return static_cast<DisassemblerLLVMC*>(disassembler)->SymbolLookup(value,
+                                                                       type,
+                                                                       pc,
+                                                                       name);
+}
+
+int DisassemblerLLVMC::OpInfo (uint64_t PC,
+                               uint64_t Offset,
+                               uint64_t Size,
+                               int tag_type,
+                               void *tag_bug)
+{
+    switch (tag_type)
+    {
+    default:
+        break;
+    case 1:
+        bzero (tag_bug, sizeof(::LLVMOpInfo1));
+        break;
+    }
+    return 0;
+}
+
+const char *DisassemblerLLVMC::SymbolLookup (uint64_t value,
+                                             uint64_t *type_ptr,
+                                             uint64_t pc,
+                                             const char **name)
+{
+    if (*type_ptr)
+    {
+        if (m_exe_ctx && m_inst)
+        {        
+            //std::string remove_this_prior_to_checkin;
+            Target *target = m_exe_ctx ? m_exe_ctx->GetTargetPtr() : NULL;
+            Address value_so_addr;
+            if (m_inst->UsingFileAddress())
+            {
+                ModuleSP module_sp(m_inst->GetAddress().GetModule());
+                if (module_sp)
+                    module_sp->ResolveFileAddress(value, value_so_addr);
+            }
+            else if (target && !target->GetSectionLoadList().IsEmpty())
+            {
+                target->GetSectionLoadList().ResolveLoadAddress(value, value_so_addr);
+            }
+            
+            if (value_so_addr.IsValid() && value_so_addr.GetSection())
+            {
+                StreamString ss;
+                
+                value_so_addr.Dump (&ss,
+                                    target,
+                                    Address::DumpStyleResolvedDescriptionNoModule,
+                                    Address::DumpStyleSectionNameOffset);
+                
+                if (!ss.GetString().empty())
+                {
+                    m_inst->AppendComment(ss.GetString());
+                }
+            }
+        }
+    }
+
+    *type_ptr = LLVMDisassembler_ReferenceType_InOut_None;
+    *name = NULL;
+    return NULL;
+}
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+ConstString
+DisassemblerLLVMC::GetPluginName()
+{
+    return GetPluginNameStatic();
+}
+
+uint32_t
+DisassemblerLLVMC::GetPluginVersion()
+{
+    return 1;
+}
+
diff --git a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h
new file mode 100644
index 000000000000..c567791866d5
--- /dev/null
+++ b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.h
@@ -0,0 +1,166 @@
+//===-- DisassemblerLLVMC.h -------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_DisassemblerLLVMC_h_
+#define liblldb_DisassemblerLLVMC_h_
+
+#include <string>
+
+#include "llvm-c/Disassembler.h"
+
+// Opaque references to C++ Objects in LLVM's MC.
+namespace llvm
+{
+    class MCContext;
+    class MCInst;
+    class MCInstrInfo;
+    class MCRegisterInfo;
+    class MCDisassembler;
+    class MCInstPrinter;
+    class MCAsmInfo;
+    class MCSubtargetInfo;
+}
+
+#include "lldb/Core/Address.h"
+#include "lldb/Core/Disassembler.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Host/Mutex.h"
+
+class InstructionLLVMC;
+
+class DisassemblerLLVMC : public lldb_private::Disassembler
+{
+    // Since we need to make two actual MC Disassemblers for ARM (ARM & THUMB), and there's a bit of goo to set up and own
+    // in the MC disassembler world, I added this class to manage the actual disassemblers.
+    class LLVMCDisassembler
+    {
+    public:
+        LLVMCDisassembler (const char *triple, unsigned flavor, DisassemblerLLVMC &owner);
+        
+        ~LLVMCDisassembler();
+        
+        uint64_t GetMCInst (const uint8_t *opcode_data, size_t opcode_data_len, lldb::addr_t pc, llvm::MCInst &mc_inst);
+        uint64_t PrintMCInst (llvm::MCInst &mc_inst, char *output_buffer, size_t out_buffer_len);
+        void     SetStyle (bool use_hex_immed, HexImmediateStyle hex_style);
+        bool     CanBranch (llvm::MCInst &mc_inst);
+        bool     IsValid()
+        {
+            return m_is_valid;
+        }
+        
+    private:
+        bool                                     m_is_valid;
+        std::unique_ptr<llvm::MCContext>         m_context_ap;
+        std::unique_ptr<llvm::MCAsmInfo>         m_asm_info_ap;
+        std::unique_ptr<llvm::MCSubtargetInfo>   m_subtarget_info_ap;
+        std::unique_ptr<llvm::MCInstrInfo>       m_instr_info_ap;
+        std::unique_ptr<llvm::MCRegisterInfo>    m_reg_info_ap;
+        std::unique_ptr<llvm::MCInstPrinter>     m_instr_printer_ap;
+        std::unique_ptr<llvm::MCDisassembler>    m_disasm_ap;
+    };
+
+public:
+    //------------------------------------------------------------------
+    // Static Functions
+    //------------------------------------------------------------------
+    static void
+    Initialize();
+    
+    static void
+    Terminate();
+    
+    static lldb_private::ConstString
+    GetPluginNameStatic();
+    
+    static lldb_private::Disassembler *
+    CreateInstance(const lldb_private::ArchSpec &arch, const char *flavor);
+        
+    DisassemblerLLVMC(const lldb_private::ArchSpec &arch, const char *flavor /* = NULL */);
+    
+    virtual
+    ~DisassemblerLLVMC();
+    
+    virtual size_t
+    DecodeInstructions (const lldb_private::Address &base_addr,
+                        const lldb_private::DataExtractor& data,
+                        lldb::offset_t data_offset,
+                        size_t num_instructions,
+                        bool append,
+                        bool data_from_file);
+    
+    //------------------------------------------------------------------
+    // PluginInterface protocol
+    //------------------------------------------------------------------
+    virtual lldb_private::ConstString
+    GetPluginName();
+    
+    virtual uint32_t
+    GetPluginVersion();
+    
+protected:
+    friend class InstructionLLVMC;
+    
+    virtual bool
+    FlavorValidForArchSpec (const lldb_private::ArchSpec &arch, const char *flavor);
+    
+    bool
+    IsValid()
+    {
+        return (m_disasm_ap.get() != NULL && m_disasm_ap->IsValid());
+    }
+    
+    int OpInfo(uint64_t PC,
+               uint64_t Offset,
+               uint64_t Size,
+               int TagType,
+               void *TagBug);
+    
+    const char *SymbolLookup (uint64_t ReferenceValue,
+                              uint64_t *ReferenceType,
+                              uint64_t ReferencePC,
+                              const char **ReferenceName);
+    
+    static int OpInfoCallback (void *DisInfo,
+                               uint64_t PC,
+                               uint64_t Offset,
+                               uint64_t Size,
+                               int TagType,
+                               void *TagBug);
+    
+    static const char *SymbolLookupCallback(void *DisInfo,
+                                            uint64_t ReferenceValue,
+                                            uint64_t *ReferenceType,
+                                            uint64_t ReferencePC,
+                                            const char **ReferenceName);
+    
+    void Lock(InstructionLLVMC *inst, 
+              const lldb_private::ExecutionContext *exe_ctx)
+    {
+        m_mutex.Lock();
+        m_inst = inst;
+        m_exe_ctx = exe_ctx;
+    }
+    
+    void Unlock()
+    {
+        m_inst = NULL;
+        m_exe_ctx = NULL;
+        m_mutex.Unlock();
+    }
+    
+    const lldb_private::ExecutionContext *m_exe_ctx;
+    InstructionLLVMC *m_inst;
+    lldb_private::Mutex m_mutex;
+    bool m_data_from_file;
+    
+    std::unique_ptr<LLVMCDisassembler> m_disasm_ap;
+    std::unique_ptr<LLVMCDisassembler> m_alternate_disasm_ap;
+};
+
+#endif  // liblldb_DisassemblerLLVM_h_
diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp b/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp
new file mode 100644
index 000000000000..2604ae670164
--- /dev/null
+++ b/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.cpp
@@ -0,0 +1,177 @@
+//===-- AuxVector.cpp -------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+// C++ Includes
+// Other libraries and framework includes
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Target/Process.h"
+
+#if defined(__linux__) or defined(__FreeBSD__)
+#include "Plugins/Process/elf-core/ProcessElfCore.h"
+#endif
+
+#include "AuxVector.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+static bool
+GetMaxU64(DataExtractor &data,
+          lldb::offset_t *offset_ptr,
+          uint64_t *value,
+          unsigned int byte_size)
+{
+    lldb::offset_t saved_offset = *offset_ptr;
+    *value = data.GetMaxU64(offset_ptr, byte_size);
+    return *offset_ptr != saved_offset;
+}
+
+static bool
+ParseAuxvEntry(DataExtractor &data,
+               AuxVector::Entry &entry,
+               lldb::offset_t *offset_ptr,
+               unsigned int byte_size)
+{
+    if (!GetMaxU64(data, offset_ptr, &entry.type, byte_size))
+        return false;
+
+    if (!GetMaxU64(data, offset_ptr, &entry.value, byte_size))
+        return false;
+
+    return true;
+}
+
+DataBufferSP
+AuxVector::GetAuxvData()
+{
+#if defined(__linux__) or defined(__FreeBSD__)
+    if (m_process->GetPluginName() == ProcessElfCore::GetPluginNameStatic())
+        return static_cast<ProcessElfCore *>(m_process)->GetAuxvData();
+#endif
+    return lldb_private::Host::GetAuxvData(m_process);
+}
+
+void
+AuxVector::ParseAuxv(DataExtractor &data)
+{
+    const unsigned int byte_size  = m_process->GetAddressByteSize();
+    lldb::offset_t offset = 0;
+
+    for (;;) 
+    {
+        Entry entry;
+
+        if (!ParseAuxvEntry(data, entry, &offset, byte_size))
+            break;
+
+        if (entry.type == AT_NULL)
+            break;
+
+        if (entry.type == AT_IGNORE)
+            continue;
+
+        m_auxv.push_back(entry);
+    }
+}
+
+AuxVector::AuxVector(Process *process)
+    : m_process(process)
+{
+    DataExtractor data;
+    Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
+
+    data.SetData(GetAuxvData());
+    data.SetByteOrder(m_process->GetByteOrder());
+    data.SetAddressByteSize(m_process->GetAddressByteSize());
+    
+    ParseAuxv(data);
+
+    if (log)
+        DumpToLog(log);
+}
+
+AuxVector::iterator 
+AuxVector::FindEntry(EntryType type) const
+{
+    for (iterator I = begin(); I != end(); ++I)
+    {
+        if (I->type == static_cast<uint64_t>(type))
+            return I;
+    }
+
+    return end();
+}
+
+void
+AuxVector::DumpToLog(Log *log) const
+{
+    if (!log)
+        return;
+
+    log->PutCString("AuxVector: ");
+    for (iterator I = begin(); I != end(); ++I)
+    {
+        log->Printf("   %s [%" PRIu64 "]: %" PRIx64, GetEntryName(*I), I->type, I->value);
+    }
+}
+
+const char *
+AuxVector::GetEntryName(EntryType type)
+{
+    const char *name = "AT_???";
+
+#define ENTRY_NAME(_type) _type: name = #_type
+    switch (type) 
+    {
+    case ENTRY_NAME(AT_NULL);           break;
+    case ENTRY_NAME(AT_IGNORE);         break;
+    case ENTRY_NAME(AT_EXECFD);         break;
+    case ENTRY_NAME(AT_PHDR);           break;
+    case ENTRY_NAME(AT_PHENT);          break;
+    case ENTRY_NAME(AT_PHNUM);          break;
+    case ENTRY_NAME(AT_PAGESZ);         break;
+    case ENTRY_NAME(AT_BASE);           break;
+    case ENTRY_NAME(AT_FLAGS);          break;
+    case ENTRY_NAME(AT_ENTRY);          break;
+    case ENTRY_NAME(AT_NOTELF);         break;
+    case ENTRY_NAME(AT_UID);            break;
+    case ENTRY_NAME(AT_EUID);           break;
+    case ENTRY_NAME(AT_GID);            break;
+    case ENTRY_NAME(AT_EGID);           break;
+    case ENTRY_NAME(AT_CLKTCK);         break;
+    case ENTRY_NAME(AT_PLATFORM);       break;
+    case ENTRY_NAME(AT_HWCAP);          break;
+    case ENTRY_NAME(AT_FPUCW);          break;
+    case ENTRY_NAME(AT_DCACHEBSIZE);    break;
+    case ENTRY_NAME(AT_ICACHEBSIZE);    break;
+    case ENTRY_NAME(AT_UCACHEBSIZE);    break;
+    case ENTRY_NAME(AT_IGNOREPPC);      break;
+    case ENTRY_NAME(AT_SECURE);         break;
+    case ENTRY_NAME(AT_BASE_PLATFORM);  break;
+    case ENTRY_NAME(AT_RANDOM);         break;
+    case ENTRY_NAME(AT_EXECFN);         break;
+    case ENTRY_NAME(AT_SYSINFO);        break;
+    case ENTRY_NAME(AT_SYSINFO_EHDR);   break;
+    case ENTRY_NAME(AT_L1I_CACHESHAPE); break;
+    case ENTRY_NAME(AT_L1D_CACHESHAPE); break;
+    case ENTRY_NAME(AT_L2_CACHESHAPE);  break;
+    case ENTRY_NAME(AT_L3_CACHESHAPE);  break;
+    }
+#undef ENTRY_NAME
+
+    return name;
+}
+
diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h b/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h
new file mode 100644
index 000000000000..2d39eddcacc6
--- /dev/null
+++ b/source/Plugins/DynamicLoader/POSIX-DYLD/AuxVector.h
@@ -0,0 +1,115 @@
+//===-- AuxVector.h ---------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_AuxVector_H_
+#define liblldb_AuxVector_H_
+
+// C Includes
+// C++ Includes
+#include <vector>
+
+// Other libraries and framework includes
+#include "lldb/lldb-forward.h"
+
+namespace lldb_private {
+class DataExtractor;
+} 
+
+/// @class AuxVector
+/// @brief Represents a processes auxiliary vector.
+///
+/// When a process is loaded on Linux a vector of values is placed onto the
+/// stack communicating operating system specific information.  On construction
+/// this class locates and parses this information and provides a simple
+/// read-only interface to the entries found.
+class AuxVector {
+
+public:
+    AuxVector(lldb_private::Process *process);
+
+    struct Entry {
+        uint64_t type;
+        uint64_t value;
+
+        Entry() : type(0), value(0) { }
+    };
+
+    /// Constants describing the type of entry.
+    /// On Linux, running "LD_SHOW_AUXV=1 ./executable" will spew AUX information.
+    enum EntryType {
+        AT_NULL           = 0,   ///< End of auxv.
+        AT_IGNORE         = 1,   ///< Ignore entry.
+        AT_EXECFD         = 2,   ///< File descriptor of program.
+        AT_PHDR           = 3,   ///< Program headers.
+        AT_PHENT          = 4,   ///< Size of program header.
+        AT_PHNUM          = 5,   ///< Number of program headers.
+        AT_PAGESZ         = 6,   ///< Page size.
+        AT_BASE           = 7,   ///< Interpreter base address.
+        AT_FLAGS          = 8,   ///< Flags.
+        AT_ENTRY          = 9,   ///< Program entry point.
+        AT_NOTELF         = 10,  ///< Set if program is not an ELF.
+        AT_UID            = 11,  ///< UID.
+        AT_EUID           = 12,  ///< Effective UID.
+        AT_GID            = 13,  ///< GID.
+        AT_EGID           = 14,  ///< Effective GID.
+        AT_CLKTCK         = 17,  ///< Clock frequency (e.g. times(2)).
+        AT_PLATFORM       = 15,  ///< String identifying platform.
+        AT_HWCAP          = 16,  ///< Machine dependent hints about processor capabilities.
+        AT_FPUCW          = 18,  ///< Used FPU control word.
+        AT_DCACHEBSIZE    = 19,  ///< Data cache block size.
+        AT_ICACHEBSIZE    = 20,  ///< Instruction cache block size.
+        AT_UCACHEBSIZE    = 21,  ///< Unified cache block size.
+        AT_IGNOREPPC      = 22,  ///< Entry should be ignored.
+        AT_SECURE         = 23,  ///< Boolean, was exec setuid-like?
+        AT_BASE_PLATFORM  = 24,  ///< String identifying real platforms.
+        AT_RANDOM         = 25,  ///< Address of 16 random bytes.
+        AT_EXECFN         = 31,  ///< Filename of executable.
+        AT_SYSINFO        = 32,  ///< Pointer to the global system page used for system calls and other nice things.
+        AT_SYSINFO_EHDR   = 33,  
+        AT_L1I_CACHESHAPE = 34,  ///< Shapes of the caches.
+        AT_L1D_CACHESHAPE = 35,
+        AT_L2_CACHESHAPE  = 36,
+        AT_L3_CACHESHAPE  = 37,
+    };
+
+private:
+    typedef std::vector<Entry> EntryVector;
+
+public:
+    typedef EntryVector::const_iterator iterator;
+
+    iterator begin() const { return m_auxv.begin(); }
+    iterator end() const { return m_auxv.end(); }
+
+    iterator 
+    FindEntry(EntryType type) const;
+
+    static const char *
+    GetEntryName(const Entry &entry) { 
+        return GetEntryName(static_cast<EntryType>(entry.type)); 
+    }
+
+    static const char *
+    GetEntryName(EntryType type);
+
+    void
+    DumpToLog(lldb_private::Log *log) const;
+
+private:
+    lldb_private::Process *m_process;
+    EntryVector m_auxv;
+
+    lldb::DataBufferSP
+    GetAuxvData();
+
+    void
+    ParseAuxv(lldb_private::DataExtractor &data);
+};
+
+#endif
diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
new file mode 100644
index 000000000000..3e1b52938f49
--- /dev/null
+++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
@@ -0,0 +1,336 @@
+//===-- DYLDRendezvous.cpp --------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+
+#include "DYLDRendezvous.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+/// Locates the address of the rendezvous structure.  Returns the address on
+/// success and LLDB_INVALID_ADDRESS on failure.
+static addr_t
+ResolveRendezvousAddress(Process *process)
+{
+    addr_t info_location;
+    addr_t info_addr;
+    Error error;
+    size_t size;
+
+    info_location = process->GetImageInfoAddress();
+
+    if (info_location == LLDB_INVALID_ADDRESS)
+        return LLDB_INVALID_ADDRESS;
+
+    info_addr = 0;
+    size = process->DoReadMemory(info_location, &info_addr,
+                                 process->GetAddressByteSize(), error);
+    if (size != process->GetAddressByteSize() || error.Fail())
+        return LLDB_INVALID_ADDRESS;
+
+    if (info_addr == 0)
+        return LLDB_INVALID_ADDRESS;
+
+    return info_addr;
+}
+
+DYLDRendezvous::DYLDRendezvous(Process *process)
+    : m_process(process),
+      m_rendezvous_addr(LLDB_INVALID_ADDRESS),
+      m_current(),
+      m_previous(),
+      m_soentries(),
+      m_added_soentries(),
+      m_removed_soentries()
+{
+    // Cache a copy of the executable path
+    if (m_process)
+    {
+        Module *exe_mod = m_process->GetTarget().GetExecutableModulePointer();
+        if (exe_mod)
+            exe_mod->GetFileSpec().GetPath(m_exe_path, PATH_MAX);
+    }
+}
+
+bool
+DYLDRendezvous::Resolve()
+{
+    const size_t word_size = 4;
+    Rendezvous info;
+    size_t address_size;
+    size_t padding;
+    addr_t info_addr;
+    addr_t cursor;
+
+    address_size = m_process->GetAddressByteSize();
+    padding = address_size - word_size;
+
+    if (m_rendezvous_addr == LLDB_INVALID_ADDRESS)
+        cursor = info_addr = ResolveRendezvousAddress(m_process);
+    else
+        cursor = info_addr = m_rendezvous_addr;
+    
+    if (cursor == LLDB_INVALID_ADDRESS)
+        return false;
+
+    if (!(cursor = ReadMemory(cursor, &info.version, word_size)))
+        return false;
+
+    if (!(cursor = ReadMemory(cursor + padding, &info.map_addr, address_size)))
+        return false;
+
+    if (!(cursor = ReadMemory(cursor, &info.brk, address_size)))
+        return false;
+
+    if (!(cursor = ReadMemory(cursor, &info.state, word_size)))
+        return false;
+
+    if (!(cursor = ReadMemory(cursor + padding, &info.ldbase, address_size)))
+        return false;
+
+    // The rendezvous was successfully read.  Update our internal state.
+    m_rendezvous_addr = info_addr;
+    m_previous = m_current;
+    m_current = info;
+
+    return UpdateSOEntries();
+}
+
+bool
+DYLDRendezvous::IsValid()
+{
+    return m_rendezvous_addr != LLDB_INVALID_ADDRESS;
+}
+
+bool
+DYLDRendezvous::UpdateSOEntries()
+{
+    SOEntry entry;
+
+    if (m_current.map_addr == 0)
+        return false;
+
+    // When the previous and current states are consistent this is the first
+    // time we have been asked to update.  Just take a snapshot of the currently
+    // loaded modules.
+    if (m_previous.state == eConsistent && m_current.state == eConsistent) 
+        return TakeSnapshot(m_soentries);
+
+    // If we are about to add or remove a shared object clear out the current
+    // state and take a snapshot of the currently loaded images.
+    if (m_current.state == eAdd || m_current.state == eDelete)
+    {
+        assert(m_previous.state == eConsistent);
+        m_soentries.clear();
+        m_added_soentries.clear();
+        m_removed_soentries.clear();
+        return TakeSnapshot(m_soentries);
+    }
+    assert(m_current.state == eConsistent);
+
+    // Otherwise check the previous state to determine what to expect and update
+    // accordingly.
+    if (m_previous.state == eAdd)
+        return UpdateSOEntriesForAddition();
+    else if (m_previous.state == eDelete)
+        return UpdateSOEntriesForDeletion();
+
+    return false;
+}
+ 
+bool
+DYLDRendezvous::UpdateSOEntriesForAddition()
+{
+    SOEntry entry;
+    iterator pos;
+
+    assert(m_previous.state == eAdd);
+
+    if (m_current.map_addr == 0)
+        return false;
+
+    for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next)
+    {
+        if (!ReadSOEntryFromMemory(cursor, entry))
+            return false;
+
+        // Only add shared libraries and not the executable.
+        // On Linux this is indicated by an empty path in the entry.
+        // On FreeBSD it is the name of the executable.
+        if (entry.path.empty() || ::strcmp(entry.path.c_str(), m_exe_path) == 0)
+            continue;
+
+        pos = std::find(m_soentries.begin(), m_soentries.end(), entry);
+        if (pos == m_soentries.end())
+        {
+            m_soentries.push_back(entry);
+            m_added_soentries.push_back(entry);
+        }
+    }
+
+    return true;
+}
+
+bool
+DYLDRendezvous::UpdateSOEntriesForDeletion()
+{
+    SOEntryList entry_list;
+    iterator pos;
+
+    assert(m_previous.state == eDelete);
+
+    if (!TakeSnapshot(entry_list))
+        return false;
+
+    for (iterator I = begin(); I != end(); ++I)
+    {
+        pos = std::find(entry_list.begin(), entry_list.end(), *I);
+        if (pos == entry_list.end())
+            m_removed_soentries.push_back(*I);
+    }
+
+    m_soentries = entry_list;
+    return true;
+}
+
+bool
+DYLDRendezvous::TakeSnapshot(SOEntryList &entry_list)
+{
+    SOEntry entry;
+
+    if (m_current.map_addr == 0)
+        return false;
+
+    for (addr_t cursor = m_current.map_addr; cursor != 0; cursor = entry.next)
+    {
+        if (!ReadSOEntryFromMemory(cursor, entry))
+            return false;
+
+        // Only add shared libraries and not the executable.
+        // On Linux this is indicated by an empty path in the entry.
+        // On FreeBSD it is the name of the executable.
+        if (entry.path.empty() || ::strcmp(entry.path.c_str(), m_exe_path) == 0)
+            continue;
+
+        entry_list.push_back(entry);
+    }
+
+    return true;
+}
+
+addr_t
+DYLDRendezvous::ReadMemory(addr_t addr, void *dst, size_t size)
+{
+    size_t bytes_read;
+    Error error;
+
+    bytes_read = m_process->DoReadMemory(addr, dst, size, error);
+    if (bytes_read != size || error.Fail())
+        return 0;
+
+    return addr + bytes_read;
+}
+
+std::string
+DYLDRendezvous::ReadStringFromMemory(addr_t addr)
+{
+    std::string str;
+    Error error;
+    size_t size;
+    char c;
+
+    if (addr == LLDB_INVALID_ADDRESS)
+        return std::string();
+
+    for (;;) {
+        size = m_process->DoReadMemory(addr, &c, 1, error);
+        if (size != 1 || error.Fail())
+            return std::string();
+        if (c == 0)
+            break;
+        else {
+            str.push_back(c);
+            addr++;
+        }
+    }
+
+    return str;
+}
+
+bool
+DYLDRendezvous::ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry)
+{
+    size_t address_size = m_process->GetAddressByteSize();
+
+    entry.clear();
+    
+    if (!(addr = ReadMemory(addr, &entry.base_addr, address_size)))
+        return false;
+    
+    if (!(addr = ReadMemory(addr, &entry.path_addr, address_size)))
+        return false;
+    
+    if (!(addr = ReadMemory(addr, &entry.dyn_addr, address_size)))
+        return false;
+    
+    if (!(addr = ReadMemory(addr, &entry.next, address_size)))
+        return false;
+    
+    if (!(addr = ReadMemory(addr, &entry.prev, address_size)))
+        return false;
+    
+    entry.path = ReadStringFromMemory(entry.path_addr);
+    
+    return true;
+}
+
+void
+DYLDRendezvous::DumpToLog(Log *log) const
+{
+    int state = GetState();
+
+    if (!log)
+        return;
+
+    log->PutCString("DYLDRendezvous:");
+    log->Printf("   Address: %" PRIx64, GetRendezvousAddress());
+    log->Printf("   Version: %" PRIu64, GetVersion());
+    log->Printf("   Link   : %" PRIx64, GetLinkMapAddress());
+    log->Printf("   Break  : %" PRIx64, GetBreakAddress());
+    log->Printf("   LDBase : %" PRIx64, GetLDBase());
+    log->Printf("   State  : %s", 
+                (state == eConsistent) ? "consistent" :
+                (state == eAdd)        ? "add"        :
+                (state == eDelete)     ? "delete"     : "unknown");
+    
+    iterator I = begin();
+    iterator E = end();
+
+    if (I != E) 
+        log->PutCString("DYLDRendezvous SOEntries:");
+    
+    for (int i = 1; I != E; ++I, ++i) 
+    {
+        log->Printf("\n   SOEntry [%d] %s", i, I->path.c_str());
+        log->Printf("      Base : %" PRIx64, I->base_addr);
+        log->Printf("      Path : %" PRIx64, I->path_addr);
+        log->Printf("      Dyn  : %" PRIx64, I->dyn_addr);
+        log->Printf("      Next : %" PRIx64, I->next);
+        log->Printf("      Prev : %" PRIx64, I->prev);
+    }
+}
diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h
new file mode 100644
index 000000000000..67e7228a38de
--- /dev/null
+++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h
@@ -0,0 +1,230 @@
+//===-- DYLDRendezvous.h ----------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_Rendezvous_H_
+#define liblldb_Rendezvous_H_
+
+// C Includes
+// C++ Includes
+#include <list>
+#include <string>
+
+// Other libraries and framework includes
+#include "lldb/lldb-defines.h"
+#include "lldb/lldb-types.h"
+
+namespace lldb_private {
+class Process;
+}
+
+/// @class DYLDRendezvous
+/// @brief Interface to the runtime linker.
+///
+/// A structure is present in a processes memory space which is updated by the
+/// runtime liker each time a module is loaded or unloaded.  This class provides
+/// an interface to this structure and maintains a consistent snapshot of the
+/// currently loaded modules.
+class DYLDRendezvous {
+
+    // This structure is used to hold the contents of the debug rendezvous
+    // information (struct r_debug) as found in the inferiors memory.  Note that
+    // the layout of this struct is not binary compatible, it is simply large
+    // enough to hold the information on both 32 and 64 bit platforms.
+    struct Rendezvous {
+        uint64_t     version;
+        lldb::addr_t map_addr;
+        lldb::addr_t brk;
+        uint64_t     state;
+        lldb::addr_t ldbase;
+
+        Rendezvous()
+            : version(0), map_addr(0), brk(0), state(0), ldbase(0) { }
+    };
+
+public:
+    DYLDRendezvous(lldb_private::Process *process);
+
+    /// Update the internal snapshot of runtime linker rendezvous and recompute
+    /// the currently loaded modules.
+    ///
+    /// This method should be called once one start up, then once each time the
+    /// runtime linker enters the function given by GetBreakAddress().
+    ///
+    /// @returns true on success and false on failure.
+    ///
+    /// @see GetBreakAddress().
+    bool 
+    Resolve();
+
+    /// @returns true if this rendezvous has been located in the inferiors
+    /// address space and false otherwise.
+    bool 
+    IsValid();
+
+    /// @returns the address of the rendezvous structure in the inferiors
+    /// address space.
+    lldb::addr_t
+    GetRendezvousAddress() const { return m_rendezvous_addr; }
+
+    /// @returns the version of the rendezvous protocol being used.
+    uint64_t
+    GetVersion() const { return m_current.version; }
+
+    /// @returns address in the inferiors address space containing the linked
+    /// list of shared object descriptors.
+    lldb::addr_t 
+    GetLinkMapAddress() const { return m_current.map_addr; }
+
+    /// A breakpoint should be set at this address and Resolve called on each
+    /// hit.
+    ///
+    /// @returns the address of a function called by the runtime linker each
+    /// time a module is loaded/unloaded, or about to be loaded/unloaded.
+    ///
+    /// @see Resolve()
+    lldb::addr_t
+    GetBreakAddress() const { return m_current.brk; }
+
+    /// Returns the current state of the rendezvous structure.
+    uint64_t
+    GetState() const { return m_current.state; }
+
+    /// @returns the base address of the runtime linker in the inferiors address
+    /// space.
+    lldb::addr_t
+    GetLDBase() const { return m_current.ldbase; }
+
+    /// @returns true if modules have been loaded into the inferior since the
+    /// last call to Resolve().
+    bool
+    ModulesDidLoad() const { return !m_added_soentries.empty(); }
+
+    /// @returns true if modules have been unloaded from the inferior since the
+    /// last call to Resolve().
+    bool
+    ModulesDidUnload() const { return !m_removed_soentries.empty(); }
+
+    void
+    DumpToLog(lldb_private::Log *log) const;
+
+    /// @brief Constants describing the state of the rendezvous.
+    ///
+    /// @see GetState().
+    enum RendezvousState {
+        eConsistent,
+        eAdd,
+        eDelete
+    };
+
+    /// @brief Structure representing the shared objects currently loaded into
+    /// the inferior process.
+    ///
+    /// This object is a rough analogue to the struct link_map object which
+    /// actually lives in the inferiors memory.
+    struct SOEntry {
+        lldb::addr_t base_addr; ///< Base address of the loaded object.
+        lldb::addr_t path_addr; ///< String naming the shared object.
+        lldb::addr_t dyn_addr;  ///< Dynamic section of shared object.
+        lldb::addr_t next;      ///< Address of next so_entry.
+        lldb::addr_t prev;      ///< Address of previous so_entry.
+        std::string  path;      ///< File name of shared object.
+
+        SOEntry() { clear(); }
+
+        bool operator ==(const SOEntry &entry) {
+            return this->path == entry.path;
+        }
+
+        void clear() {
+            base_addr = 0;
+            path_addr = 0;
+            dyn_addr  = 0;
+            next = 0;
+            prev = 0;
+            path.clear();
+        }
+    };
+
+protected:
+    typedef std::list<SOEntry> SOEntryList;
+
+public:
+    typedef SOEntryList::const_iterator iterator;
+
+    /// Iterators over all currently loaded modules.
+    iterator begin() const { return m_soentries.begin(); }
+    iterator end() const { return m_soentries.end(); }
+
+    /// Iterators over all modules loaded into the inferior since the last call
+    /// to Resolve().
+    iterator loaded_begin() const { return m_added_soentries.begin(); }
+    iterator loaded_end() const { return m_added_soentries.end(); }
+
+    /// Iterators over all modules unloaded from the inferior since the last
+    /// call to Resolve().
+    iterator unloaded_begin() const { return m_removed_soentries.begin(); }
+    iterator unloaded_end() const { return m_removed_soentries.end(); }
+    
+protected:
+    lldb_private::Process *m_process;
+
+    // Cached copy of executable pathname
+    char m_exe_path[PATH_MAX];
+
+    /// Location of the r_debug structure in the inferiors address space.
+    lldb::addr_t m_rendezvous_addr;
+
+    /// Current and previous snapshots of the rendezvous structure.
+    Rendezvous m_current;
+    Rendezvous m_previous;
+
+    /// List of SOEntry objects corresponding to the current link map state.
+    SOEntryList m_soentries;
+
+    /// List of SOEntry's added to the link map since the last call to Resolve().
+    SOEntryList m_added_soentries;
+
+    /// List of SOEntry's removed from the link map since the last call to
+    /// Resolve().
+    SOEntryList m_removed_soentries;
+
+    /// Reads @p size bytes from the inferiors address space starting at @p
+    /// addr.
+    ///
+    /// @returns addr + size if the read was successful and false otherwise.
+    lldb::addr_t
+    ReadMemory(lldb::addr_t addr, void *dst, size_t size);
+
+    /// Reads a null-terminated C string from the memory location starting at @p
+    /// addr.
+    std::string
+    ReadStringFromMemory(lldb::addr_t addr);
+
+    /// Reads an SOEntry starting at @p addr.
+    bool
+    ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry);
+
+    /// Updates the current set of SOEntries, the set of added entries, and the
+    /// set of removed entries.
+    bool
+    UpdateSOEntries();
+
+    bool
+    UpdateSOEntriesForAddition();
+
+    bool
+    UpdateSOEntriesForDeletion();
+
+    /// Reads the current list of shared objects according to the link map
+    /// supplied by the runtime linker.
+    bool
+    TakeSnapshot(SOEntryList &entry_list);
+};
+
+#endif
diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
new file mode 100644
index 000000000000..91c7cd3dfca7
--- /dev/null
+++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
@@ -0,0 +1,481 @@
+//===-- DynamicLoaderPOSIX.h ------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Core/Section.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/ThreadPlanRunToAddress.h"
+#include "lldb/Breakpoint/BreakpointLocation.h"
+
+#include "AuxVector.h"
+#include "DynamicLoaderPOSIXDYLD.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+void
+DynamicLoaderPOSIXDYLD::Initialize()
+{
+    PluginManager::RegisterPlugin(GetPluginNameStatic(),
+                                  GetPluginDescriptionStatic(),
+                                  CreateInstance);
+}
+
+void
+DynamicLoaderPOSIXDYLD::Terminate()
+{
+}
+
+lldb_private::ConstString
+DynamicLoaderPOSIXDYLD::GetPluginName()
+{
+    return GetPluginNameStatic();
+}
+
+lldb_private::ConstString
+DynamicLoaderPOSIXDYLD::GetPluginNameStatic()
+{
+    static ConstString g_name("linux-dyld");
+    return g_name;
+}
+
+const char *
+DynamicLoaderPOSIXDYLD::GetPluginDescriptionStatic()
+{
+    return "Dynamic loader plug-in that watches for shared library "
+           "loads/unloads in POSIX processes.";
+}
+
+void
+DynamicLoaderPOSIXDYLD::GetPluginCommandHelp(const char *command, Stream *strm)
+{
+}
+
+uint32_t
+DynamicLoaderPOSIXDYLD::GetPluginVersion()
+{
+    return 1;
+}
+
+DynamicLoader *
+DynamicLoaderPOSIXDYLD::CreateInstance(Process *process, bool force)
+{
+    bool create = force;
+    if (!create)
+    {
+        const llvm::Triple &triple_ref = process->GetTarget().GetArchitecture().GetTriple();
+        if (triple_ref.getOS() == llvm::Triple::Linux ||
+            triple_ref.getOS() == llvm::Triple::FreeBSD)
+            create = true;
+    }
+    
+    if (create)
+        return new DynamicLoaderPOSIXDYLD (process);
+    return NULL;
+}
+
+DynamicLoaderPOSIXDYLD::DynamicLoaderPOSIXDYLD(Process *process)
+    : DynamicLoader(process),
+      m_rendezvous(process),
+      m_load_offset(LLDB_INVALID_ADDRESS),
+      m_entry_point(LLDB_INVALID_ADDRESS),
+      m_auxv(),
+      m_dyld_bid(LLDB_INVALID_BREAK_ID)
+{
+}
+
+DynamicLoaderPOSIXDYLD::~DynamicLoaderPOSIXDYLD()
+{
+    if (m_dyld_bid != LLDB_INVALID_BREAK_ID)
+    {
+        m_process->GetTarget().RemoveBreakpointByID (m_dyld_bid);
+        m_dyld_bid = LLDB_INVALID_BREAK_ID;
+    }
+}
+
+void
+DynamicLoaderPOSIXDYLD::DidAttach()
+{
+    ModuleSP executable;
+    addr_t load_offset;
+
+    m_auxv.reset(new AuxVector(m_process));
+
+    executable = GetTargetExecutable();
+    load_offset = ComputeLoadOffset();
+
+    if (executable.get() && load_offset != LLDB_INVALID_ADDRESS)
+    {
+        ModuleList module_list;
+        module_list.Append(executable);
+        UpdateLoadedSections(executable, load_offset);
+        LoadAllCurrentModules();
+        m_process->GetTarget().ModulesDidLoad(module_list);
+    }
+}
+
+void
+DynamicLoaderPOSIXDYLD::DidLaunch()
+{
+    ModuleSP executable;
+    addr_t load_offset;
+
+    m_auxv.reset(new AuxVector(m_process));
+
+    executable = GetTargetExecutable();
+    load_offset = ComputeLoadOffset();
+
+    if (executable.get() && load_offset != LLDB_INVALID_ADDRESS)
+    {
+        ModuleList module_list;
+        module_list.Append(executable);
+        UpdateLoadedSections(executable, load_offset);
+        ProbeEntry();
+        m_process->GetTarget().ModulesDidLoad(module_list);
+    }
+}
+
+ModuleSP
+DynamicLoaderPOSIXDYLD::GetTargetExecutable()
+{
+    Target &target = m_process->GetTarget();
+    ModuleSP executable = target.GetExecutableModule();
+
+    if (executable.get())
+    {
+        if (executable->GetFileSpec().Exists())
+        {
+            ModuleSpec module_spec (executable->GetFileSpec(), executable->GetArchitecture());
+            ModuleSP module_sp (new Module (module_spec));
+
+            // Check if the executable has changed and set it to the target executable if they differ.
+            if (module_sp.get() && module_sp->GetUUID().IsValid() && executable->GetUUID().IsValid())
+            {
+                if (module_sp->GetUUID() != executable->GetUUID())
+                    executable.reset();
+            }
+            else if (executable->FileHasChanged())
+            {
+                executable.reset();
+            }
+
+            if (!executable.get())
+            {
+                executable = target.GetSharedModule(module_spec);
+                if (executable.get() != target.GetExecutableModulePointer())
+                {
+                    // Don't load dependent images since we are in dyld where we will know
+                    // and find out about all images that are loaded
+                    const bool get_dependent_images = false;
+                    target.SetExecutableModule(executable, get_dependent_images);
+                }
+            }
+        }
+    }
+    return executable;
+}
+
+Error
+DynamicLoaderPOSIXDYLD::ExecutePluginCommand(Args &command, Stream *strm)
+{
+    return Error();
+}
+
+Log *
+DynamicLoaderPOSIXDYLD::EnablePluginLogging(Stream *strm, Args &command)
+{
+    return NULL;
+}
+
+Error
+DynamicLoaderPOSIXDYLD::CanLoadImage()
+{
+    return Error();
+}
+
+void
+DynamicLoaderPOSIXDYLD::UpdateLoadedSections(ModuleSP module, addr_t base_addr)
+{
+    ObjectFile *obj_file = module->GetObjectFile();
+    SectionList *sections = obj_file->GetSectionList();
+    SectionLoadList &load_list = m_process->GetTarget().GetSectionLoadList();
+    const size_t num_sections = sections->GetSize();
+
+    for (unsigned i = 0; i < num_sections; ++i)
+    {
+        SectionSP section_sp (sections->GetSectionAtIndex(i));
+        lldb::addr_t new_load_addr = section_sp->GetFileAddress() + base_addr;
+        lldb::addr_t old_load_addr = load_list.GetSectionLoadAddress(section_sp);
+
+        // If the file address of the section is zero then this is not an
+        // allocatable/loadable section (property of ELF sh_addr).  Skip it.
+        if (new_load_addr == base_addr)
+            continue;
+
+        if (old_load_addr == LLDB_INVALID_ADDRESS ||
+            old_load_addr != new_load_addr)
+            load_list.SetSectionLoadAddress(section_sp, new_load_addr);
+    }
+}
+
+void
+DynamicLoaderPOSIXDYLD::ProbeEntry()
+{
+    Breakpoint *entry_break;
+    addr_t entry;
+
+    if ((entry = GetEntryPoint()) == LLDB_INVALID_ADDRESS)
+        return;
+    
+    entry_break = m_process->GetTarget().CreateBreakpoint(entry, true).get();
+    entry_break->SetCallback(EntryBreakpointHit, this, true);
+    entry_break->SetBreakpointKind("shared-library-event");
+}
+
+// The runtime linker has run and initialized the rendezvous structure once the
+// process has hit its entry point.  When we hit the corresponding breakpoint we
+// interrogate the rendezvous structure to get the load addresses of all
+// dependent modules for the process.  Similarly, we can discover the runtime
+// linker function and setup a breakpoint to notify us of any dynamically loaded
+// modules (via dlopen).
+bool
+DynamicLoaderPOSIXDYLD::EntryBreakpointHit(void *baton, 
+                                           StoppointCallbackContext *context, 
+                                           user_id_t break_id, 
+                                           user_id_t break_loc_id)
+{
+    DynamicLoaderPOSIXDYLD* dyld_instance;
+
+    dyld_instance = static_cast<DynamicLoaderPOSIXDYLD*>(baton);
+    dyld_instance->LoadAllCurrentModules();
+    dyld_instance->SetRendezvousBreakpoint();
+    return false; // Continue running.
+}
+
+void
+DynamicLoaderPOSIXDYLD::SetRendezvousBreakpoint()
+{
+    addr_t break_addr = m_rendezvous.GetBreakAddress();
+    Target &target = m_process->GetTarget();
+
+    if (m_dyld_bid == LLDB_INVALID_BREAK_ID)
+    {
+        Breakpoint *dyld_break = target.CreateBreakpoint (break_addr, true).get();
+        dyld_break->SetCallback(RendezvousBreakpointHit, this, true);
+        dyld_break->SetBreakpointKind ("shared-library-event");
+        m_dyld_bid = dyld_break->GetID();
+    }
+
+    // Make sure our breakpoint is at the right address.
+    assert (target.GetBreakpointByID(m_dyld_bid)->FindLocationByAddress(break_addr)->GetBreakpoint().GetID() == m_dyld_bid);
+}
+
+bool
+DynamicLoaderPOSIXDYLD::RendezvousBreakpointHit(void *baton, 
+                                                StoppointCallbackContext *context, 
+                                                user_id_t break_id, 
+                                                user_id_t break_loc_id)
+{
+    DynamicLoaderPOSIXDYLD* dyld_instance;
+
+    dyld_instance = static_cast<DynamicLoaderPOSIXDYLD*>(baton);
+    dyld_instance->RefreshModules();
+
+    // Return true to stop the target, false to just let the target run.
+    return dyld_instance->GetStopWhenImagesChange();
+}
+
+void
+DynamicLoaderPOSIXDYLD::RefreshModules()
+{
+    if (!m_rendezvous.Resolve())
+        return;
+
+    DYLDRendezvous::iterator I;
+    DYLDRendezvous::iterator E;
+
+    ModuleList &loaded_modules = m_process->GetTarget().GetImages();
+
+    if (m_rendezvous.ModulesDidLoad()) 
+    {
+        ModuleList new_modules;
+
+        E = m_rendezvous.loaded_end();
+        for (I = m_rendezvous.loaded_begin(); I != E; ++I)
+        {
+            FileSpec file(I->path.c_str(), true);
+            ModuleSP module_sp = LoadModuleAtAddress(file, I->base_addr);
+            if (module_sp.get())
+                loaded_modules.AppendIfNeeded(module_sp);
+        }
+    }
+    
+    if (m_rendezvous.ModulesDidUnload())
+    {
+        ModuleList old_modules;
+
+        E = m_rendezvous.unloaded_end();
+        for (I = m_rendezvous.unloaded_begin(); I != E; ++I)
+        {
+            FileSpec file(I->path.c_str(), true);
+            ModuleSpec module_spec (file);
+            ModuleSP module_sp = 
+                loaded_modules.FindFirstModule (module_spec);
+            if (module_sp.get())
+                old_modules.Append(module_sp);
+        }
+        loaded_modules.Remove(old_modules);
+    }
+}
+
+ThreadPlanSP
+DynamicLoaderPOSIXDYLD::GetStepThroughTrampolinePlan(Thread &thread, bool stop)
+{
+    ThreadPlanSP thread_plan_sp;
+
+    StackFrame *frame = thread.GetStackFrameAtIndex(0).get();
+    const SymbolContext &context = frame->GetSymbolContext(eSymbolContextSymbol);
+    Symbol *sym = context.symbol;
+
+    if (sym == NULL || !sym->IsTrampoline())
+        return thread_plan_sp;
+
+    const ConstString &sym_name = sym->GetMangled().GetName(Mangled::ePreferMangled);
+    if (!sym_name)
+        return thread_plan_sp;
+
+    SymbolContextList target_symbols;
+    Target &target = thread.GetProcess()->GetTarget();
+    const ModuleList &images = target.GetImages();
+
+    images.FindSymbolsWithNameAndType(sym_name, eSymbolTypeCode, target_symbols);
+    size_t num_targets = target_symbols.GetSize();
+    if (!num_targets)
+        return thread_plan_sp;
+
+    typedef std::vector<lldb::addr_t> AddressVector;
+    AddressVector addrs;
+    for (size_t i = 0; i < num_targets; ++i)
+    {
+        SymbolContext context;
+        AddressRange range;
+        if (target_symbols.GetContextAtIndex(i, context))
+        {
+            context.GetAddressRange(eSymbolContextEverything, 0, false, range);
+            lldb::addr_t addr = range.GetBaseAddress().GetLoadAddress(&target);
+            if (addr != LLDB_INVALID_ADDRESS)
+                addrs.push_back(addr);
+        }
+    }
+
+    if (addrs.size() > 0) 
+    {
+        AddressVector::iterator start = addrs.begin();
+        AddressVector::iterator end = addrs.end();
+
+        std::sort(start, end);
+        addrs.erase(std::unique(start, end), end);
+        thread_plan_sp.reset(new ThreadPlanRunToAddress(thread, addrs, stop));
+    }
+
+    return thread_plan_sp;
+}
+
+void
+DynamicLoaderPOSIXDYLD::LoadAllCurrentModules()
+{
+    DYLDRendezvous::iterator I;
+    DYLDRendezvous::iterator E;
+    ModuleList module_list;
+    
+    if (!m_rendezvous.Resolve())
+        return;
+
+    for (I = m_rendezvous.begin(), E = m_rendezvous.end(); I != E; ++I)
+    {
+        FileSpec file(I->path.c_str(), false);
+        ModuleSP module_sp = LoadModuleAtAddress(file, I->base_addr);
+        if (module_sp.get())
+            module_list.Append(module_sp);
+    }
+
+    m_process->GetTarget().ModulesDidLoad(module_list);
+}
+
+ModuleSP
+DynamicLoaderPOSIXDYLD::LoadModuleAtAddress(const FileSpec &file, addr_t base_addr)
+{
+    Target &target = m_process->GetTarget();
+    ModuleList &modules = target.GetImages();
+    ModuleSP module_sp;
+
+    ModuleSpec module_spec (file, target.GetArchitecture());
+    if ((module_sp = modules.FindFirstModule (module_spec))) 
+    {
+        UpdateLoadedSections(module_sp, base_addr);
+    }
+    else if ((module_sp = target.GetSharedModule(module_spec))) 
+    {
+        UpdateLoadedSections(module_sp, base_addr);
+    }
+
+    return module_sp;
+}
+
+addr_t
+DynamicLoaderPOSIXDYLD::ComputeLoadOffset()
+{
+    addr_t virt_entry;
+
+    if (m_load_offset != LLDB_INVALID_ADDRESS)
+        return m_load_offset;
+
+    if ((virt_entry = GetEntryPoint()) == LLDB_INVALID_ADDRESS)
+        return LLDB_INVALID_ADDRESS;
+
+    ModuleSP module = m_process->GetTarget().GetExecutableModule();
+    if (!module)
+        return LLDB_INVALID_ADDRESS;
+
+    ObjectFile *exe = module->GetObjectFile();
+    Address file_entry = exe->GetEntryPointAddress();
+
+    if (!file_entry.IsValid())
+        return LLDB_INVALID_ADDRESS;
+            
+    m_load_offset = virt_entry - file_entry.GetFileAddress();
+    return m_load_offset;
+}
+
+addr_t
+DynamicLoaderPOSIXDYLD::GetEntryPoint()
+{
+    if (m_entry_point != LLDB_INVALID_ADDRESS)
+        return m_entry_point;
+
+    if (m_auxv.get() == NULL)
+        return LLDB_INVALID_ADDRESS;
+
+    AuxVector::iterator I = m_auxv->FindEntry(AuxVector::AT_ENTRY);
+
+    if (I == m_auxv->end())
+        return LLDB_INVALID_ADDRESS;
+
+    m_entry_point = static_cast<addr_t>(I->value);
+    return m_entry_point;
+}
diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h
new file mode 100644
index 000000000000..0476e45d0465
--- /dev/null
+++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h
@@ -0,0 +1,170 @@
+//===-- DynamicLoaderPOSIX.h ------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_DynamicLoaderPOSIX_H_
+#define liblldb_DynamicLoaderPOSIX_H_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+#include "lldb/Breakpoint/StoppointCallbackContext.h"
+#include "lldb/Target/DynamicLoader.h"
+
+#include "DYLDRendezvous.h"
+
+class AuxVector;
+
+class DynamicLoaderPOSIXDYLD : public lldb_private::DynamicLoader
+{
+public:
+
+    static void
+    Initialize();
+
+    static void
+    Terminate();
+
+    static lldb_private::ConstString
+    GetPluginNameStatic();
+
+    static const char *
+    GetPluginDescriptionStatic();
+
+    static lldb_private::DynamicLoader *
+    CreateInstance(lldb_private::Process *process, bool force);
+
+    DynamicLoaderPOSIXDYLD(lldb_private::Process *process);
+
+    virtual
+    ~DynamicLoaderPOSIXDYLD();
+
+    //------------------------------------------------------------------
+    // DynamicLoader protocol
+    //------------------------------------------------------------------
+
+    virtual void
+    DidAttach();
+
+    virtual void
+    DidLaunch();
+
+    virtual lldb::ThreadPlanSP
+    GetStepThroughTrampolinePlan(lldb_private::Thread &thread,
+                                 bool stop_others);
+
+    virtual lldb_private::Error
+    CanLoadImage();
+
+    //------------------------------------------------------------------
+    // PluginInterface protocol
+    //------------------------------------------------------------------
+    virtual lldb_private::ConstString
+    GetPluginName();
+
+    virtual uint32_t
+    GetPluginVersion();
+
+    virtual void
+    GetPluginCommandHelp(const char *command, lldb_private::Stream *strm);
+
+    virtual lldb_private::Error
+    ExecutePluginCommand(lldb_private::Args &command, lldb_private::Stream *strm);
+
+    virtual lldb_private::Log *
+    EnablePluginLogging(lldb_private::Stream *strm, lldb_private::Args &command);
+
+protected:
+    /// Runtime linker rendezvous structure.
+    DYLDRendezvous m_rendezvous;
+
+    /// Virtual load address of the inferior process.
+    lldb::addr_t m_load_offset;
+
+    /// Virtual entry address of the inferior process.
+    lldb::addr_t m_entry_point;
+
+    /// Auxiliary vector of the inferior process.
+    std::unique_ptr<AuxVector> m_auxv;
+
+    /// Rendezvous breakpoint.
+    lldb::break_id_t m_dyld_bid;
+
+    /// Enables a breakpoint on a function called by the runtime
+    /// linker each time a module is loaded or unloaded.
+    void
+    SetRendezvousBreakpoint();
+
+    /// Callback routine which updates the current list of loaded modules based
+    /// on the information supplied by the runtime linker.
+    static bool
+    RendezvousBreakpointHit(void *baton, 
+                            lldb_private::StoppointCallbackContext *context, 
+                            lldb::user_id_t break_id, 
+                            lldb::user_id_t break_loc_id);
+    
+    /// Helper method for RendezvousBreakpointHit.  Updates LLDB's current set
+    /// of loaded modules.
+    void
+    RefreshModules();
+
+    /// Updates the load address of every allocatable section in @p module.
+    ///
+    /// @param module The module to traverse.
+    ///
+    /// @param base_addr The virtual base address @p module is loaded at.
+    void
+    UpdateLoadedSections(lldb::ModuleSP module, 
+                         lldb::addr_t base_addr = 0);
+
+    /// Locates or creates a module given by @p file and updates/loads the
+    /// resulting module at the virtual base address @p base_addr.
+    lldb::ModuleSP
+    LoadModuleAtAddress(const lldb_private::FileSpec &file, lldb::addr_t base_addr);
+
+    /// Resolves the entry point for the current inferior process and sets a
+    /// breakpoint at that address.
+    void
+    ProbeEntry();
+
+    /// Callback routine invoked when we hit the breakpoint on process entry.
+    ///
+    /// This routine is responsible for resolving the load addresses of all
+    /// dependent modules required by the inferior and setting up the rendezvous
+    /// breakpoint.
+    static bool
+    EntryBreakpointHit(void *baton, 
+                       lldb_private::StoppointCallbackContext *context, 
+                       lldb::user_id_t break_id, 
+                       lldb::user_id_t break_loc_id);
+
+    /// Helper for the entry breakpoint callback.  Resolves the load addresses
+    /// of all dependent modules.
+    void
+    LoadAllCurrentModules();
+
+    /// Computes a value for m_load_offset returning the computed address on
+    /// success and LLDB_INVALID_ADDRESS on failure.
+    lldb::addr_t
+    ComputeLoadOffset();
+
+    /// Computes a value for m_entry_point returning the computed address on
+    /// success and LLDB_INVALID_ADDRESS on failure.
+    lldb::addr_t
+    GetEntryPoint();
+
+    /// Checks to see if the target module has changed, updates the target
+    /// accordingly and returns the target executable module.
+    lldb::ModuleSP
+    GetTargetExecutable();
+
+private:
+    DISALLOW_COPY_AND_ASSIGN(DynamicLoaderPOSIXDYLD);
+};
+
+#endif  // liblldb_DynamicLoaderPOSIXDYLD_H_
diff --git a/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.cpp b/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.cpp
new file mode 100644
index 000000000000..274ba328ad1f
--- /dev/null
+++ b/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.cpp
@@ -0,0 +1,209 @@
+//===-- DynamicLoaderStatic.cpp ---------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Section.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Target/Target.h"
+
+#include "DynamicLoaderStatic.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// Create an instance of this class. This function is filled into
+// the plugin info class that gets handed out by the plugin factory and
+// allows the lldb to instantiate an instance of this class.
+//----------------------------------------------------------------------
+DynamicLoader *
+DynamicLoaderStatic::CreateInstance (Process* process, bool force)
+{
+    bool create = force;
+    if (!create)
+    {
+        const llvm::Triple &triple_ref = process->GetTarget().GetArchitecture().GetTriple();
+        const llvm::Triple::OSType os_type = triple_ref.getOS();
+        if ((os_type == llvm::Triple::UnknownOS))
+            create = true;
+    }
+    
+    if (!create)
+    {
+        Module *exe_module = process->GetTarget().GetExecutableModulePointer();
+        if (exe_module)
+        {
+            ObjectFile *object_file = exe_module->GetObjectFile();
+            if (object_file)
+            {
+                create = (object_file->GetStrata() == ObjectFile::eStrataRawImage);
+            }
+        }
+    }
+    
+    if (create)
+        return new DynamicLoaderStatic (process);
+    return NULL;
+}
+
+//----------------------------------------------------------------------
+// Constructor
+//----------------------------------------------------------------------
+DynamicLoaderStatic::DynamicLoaderStatic (Process* process) :
+    DynamicLoader(process)
+{
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+DynamicLoaderStatic::~DynamicLoaderStatic()
+{
+}
+
+//------------------------------------------------------------------
+/// Called after attaching a process.
+///
+/// Allow DynamicLoader plug-ins to execute some code after
+/// attaching to a process.
+//------------------------------------------------------------------
+void
+DynamicLoaderStatic::DidAttach ()
+{
+    LoadAllImagesAtFileAddresses();
+}
+
+//------------------------------------------------------------------
+/// Called after attaching a process.
+///
+/// Allow DynamicLoader plug-ins to execute some code after
+/// attaching to a process.
+//------------------------------------------------------------------
+void
+DynamicLoaderStatic::DidLaunch ()
+{
+    LoadAllImagesAtFileAddresses();
+}
+
+void
+DynamicLoaderStatic::LoadAllImagesAtFileAddresses ()
+{
+    const ModuleList &module_list = m_process->GetTarget().GetImages();
+    
+    ModuleList loaded_module_list;
+
+    // Disable JIT for static dynamic loader targets
+    m_process->SetCanJIT(false);
+
+    Mutex::Locker mutex_locker(module_list.GetMutex());
+    
+    const size_t num_modules = module_list.GetSize();
+    for (uint32_t idx = 0; idx < num_modules; ++idx)
+    {
+        ModuleSP module_sp (module_list.GetModuleAtIndexUnlocked (idx));
+        if (module_sp)
+        {
+            bool changed = false;
+            ObjectFile *image_object_file = module_sp->GetObjectFile();
+            if (image_object_file)
+            {
+                SectionList *section_list = image_object_file->GetSectionList ();
+                if (section_list)
+                {
+                    // All sections listed in the dyld image info structure will all
+                    // either be fixed up already, or they will all be off by a single
+                    // slide amount that is determined by finding the first segment
+                    // that is at file offset zero which also has bytes (a file size
+                    // that is greater than zero) in the object file.
+
+                    // Determine the slide amount (if any)
+                    const size_t num_sections = section_list->GetSize();
+                    size_t sect_idx = 0;
+                    for (sect_idx = 0; sect_idx < num_sections; ++sect_idx)
+                    {
+                        // Iterate through the object file sections to find the
+                        // first section that starts of file offset zero and that
+                        // has bytes in the file...
+                        SectionSP section_sp (section_list->GetSectionAtIndex (sect_idx));
+                        if (section_sp)
+                        {
+                            if (m_process->GetTarget().GetSectionLoadList().SetSectionLoadAddress (section_sp, section_sp->GetFileAddress()))
+                                changed = true;
+                        }
+                    }
+                }
+            }
+            
+            if (changed)
+                loaded_module_list.AppendIfNeeded (module_sp);
+        }
+    }
+
+    m_process->GetTarget().ModulesDidLoad (loaded_module_list);
+}
+
+ThreadPlanSP
+DynamicLoaderStatic::GetStepThroughTrampolinePlan (Thread &thread, bool stop_others)
+{
+    return ThreadPlanSP();
+}
+
+Error
+DynamicLoaderStatic::CanLoadImage ()
+{
+    Error error;
+    error.SetErrorString ("can't load images on with a static debug session");
+    return error;
+}
+
+void
+DynamicLoaderStatic::Initialize()
+{
+    PluginManager::RegisterPlugin (GetPluginNameStatic(),
+                                   GetPluginDescriptionStatic(),
+                                   CreateInstance);
+}
+
+void
+DynamicLoaderStatic::Terminate()
+{
+    PluginManager::UnregisterPlugin (CreateInstance);
+}
+
+
+lldb_private::ConstString
+DynamicLoaderStatic::GetPluginNameStatic()
+{
+    static ConstString g_name("static");
+    return g_name;
+}
+
+const char *
+DynamicLoaderStatic::GetPluginDescriptionStatic()
+{
+    return "Dynamic loader plug-in that will load any images at the static addresses contained in each image.";
+}
+
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+lldb_private::ConstString
+DynamicLoaderStatic::GetPluginName()
+{
+    return GetPluginNameStatic();
+}
+
+uint32_t
+DynamicLoaderStatic::GetPluginVersion()
+{
+    return 1;
+}
+
diff --git a/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.h b/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.h
new file mode 100644
index 000000000000..a99435fa32ad
--- /dev/null
+++ b/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.h
@@ -0,0 +1,88 @@
+//===-- DynamicLoaderStatic.h -----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_DynamicLoaderStatic_h_
+#define liblldb_DynamicLoaderStatic_h_
+
+// C Includes
+// C++ Includes
+#include <map>
+#include <vector>
+#include <string>
+
+// Other libraries and framework includes
+#include "llvm/Support/MachO.h"
+
+#include "lldb/Target/DynamicLoader.h"
+#include "lldb/Host/FileSpec.h"
+#include "lldb/Core/UUID.h"
+#include "lldb/Host/Mutex.h"
+#include "lldb/Target/Process.h"
+
+class DynamicLoaderStatic : public lldb_private::DynamicLoader
+{
+public:
+    //------------------------------------------------------------------
+    // Static Functions
+    //------------------------------------------------------------------
+    static void
+    Initialize();
+
+    static void
+    Terminate();
+
+    static lldb_private::ConstString
+    GetPluginNameStatic();
+
+    static const char *
+    GetPluginDescriptionStatic();
+
+    static lldb_private::DynamicLoader *
+    CreateInstance (lldb_private::Process *process, bool force);
+
+    DynamicLoaderStatic (lldb_private::Process *process);
+
+    virtual
+    ~DynamicLoaderStatic ();
+    //------------------------------------------------------------------
+    /// Called after attaching a process.
+    ///
+    /// Allow DynamicLoader plug-ins to execute some code after
+    /// attaching to a process.
+    //------------------------------------------------------------------
+    virtual void
+    DidAttach ();
+
+    virtual void
+    DidLaunch ();
+
+    virtual lldb::ThreadPlanSP
+    GetStepThroughTrampolinePlan (lldb_private::Thread &thread,
+                                  bool stop_others);
+
+    virtual lldb_private::Error
+    CanLoadImage ();
+
+    //------------------------------------------------------------------
+    // PluginInterface protocol
+    //------------------------------------------------------------------
+    virtual lldb_private::ConstString
+    GetPluginName();
+
+    virtual uint32_t
+    GetPluginVersion();
+
+private:
+    void
+    LoadAllImagesAtFileAddresses ();
+
+    DISALLOW_COPY_AND_ASSIGN (DynamicLoaderStatic);
+};
+
+#endif  // liblldb_DynamicLoaderStatic_h_
diff --git a/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp b/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
new file mode 100644
index 000000000000..2dd04dd8733d
--- /dev/null
+++ b/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
@@ -0,0 +1,13625 @@
+//===-- EmulateInstructionARM.cpp -------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <stdlib.h>
+
+#include "EmulateInstructionARM.h"
+#include "EmulationStateARM.h"
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/Address.h"
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Interpreter/OptionValueArray.h"
+#include "lldb/Interpreter/OptionValueDictionary.h"
+#include "lldb/Symbol/UnwindPlan.h"
+
+#include "Plugins/Process/Utility/ARMDefines.h"
+#include "Plugins/Process/Utility/ARMUtils.h"
+#include "Utility/ARM_DWARF_Registers.h"
+
+#include "llvm/Support/MathExtras.h" // for SignExtend32 template function
+                                     // and countTrailingZeros function
+
+using namespace lldb;
+using namespace lldb_private;
+
+// Convenient macro definitions.
+#define APSR_C Bit32(m_opcode_cpsr, CPSR_C_POS)
+#define APSR_V Bit32(m_opcode_cpsr, CPSR_V_POS)
+
+#define AlignPC(pc_val) (pc_val & 0xFFFFFFFC)
+
+//----------------------------------------------------------------------
+//
+// ITSession implementation
+//
+//----------------------------------------------------------------------
+
+// A8.6.50
+// Valid return values are {1, 2, 3, 4}, with 0 signifying an error condition.
+static uint32_t
+CountITSize (uint32_t ITMask) {
+    // First count the trailing zeros of the IT mask.
+    uint32_t TZ = llvm::countTrailingZeros(ITMask);
+    if (TZ > 3)
+    {
+#ifdef LLDB_CONFIGURATION_DEBUG
+        printf("Encoding error: IT Mask '0000'\n");
+#endif
+        return 0;
+    }
+    return (4 - TZ);
+}
+
+// Init ITState.  Note that at least one bit is always 1 in mask.
+bool ITSession::InitIT(uint32_t bits7_0)
+{
+    ITCounter = CountITSize(Bits32(bits7_0, 3, 0));
+    if (ITCounter == 0)
+        return false;
+
+    // A8.6.50 IT
+    unsigned short FirstCond = Bits32(bits7_0, 7, 4);
+    if (FirstCond == 0xF)
+    {
+#ifdef LLDB_CONFIGURATION_DEBUG
+        printf("Encoding error: IT FirstCond '1111'\n");
+#endif
+        return false;
+    }
+    if (FirstCond == 0xE && ITCounter != 1)
+    {
+#ifdef LLDB_CONFIGURATION_DEBUG
+        printf("Encoding error: IT FirstCond '1110' && Mask != '1000'\n");
+#endif
+        return false;
+    }
+
+    ITState = bits7_0;
+    return true;
+}
+
+// Update ITState if necessary.
+void ITSession::ITAdvance()
+{
+    //assert(ITCounter);
+    --ITCounter;
+    if (ITCounter == 0)
+        ITState = 0;
+    else
+    {
+        unsigned short NewITState4_0 = Bits32(ITState, 4, 0) << 1;
+        SetBits32(ITState, 4, 0, NewITState4_0);
+    }
+}
+
+// Return true if we're inside an IT Block.
+bool ITSession::InITBlock()
+{
+    return ITCounter != 0;
+}
+
+// Return true if we're the last instruction inside an IT Block.
+bool ITSession::LastInITBlock()
+{
+    return ITCounter == 1;
+}
+
+// Get condition bits for the current thumb instruction.
+uint32_t ITSession::GetCond()
+{
+    if (InITBlock())
+        return Bits32(ITState, 7, 4);
+    else
+        return COND_AL;
+}
+
+// ARM constants used during decoding
+#define REG_RD          0
+#define LDM_REGLIST     1
+#define SP_REG          13
+#define LR_REG          14
+#define PC_REG          15
+#define PC_REGLIST_BIT  0x8000
+
+#define ARMv4     (1u << 0)
+#define ARMv4T    (1u << 1)
+#define ARMv5T    (1u << 2)
+#define ARMv5TE   (1u << 3)
+#define ARMv5TEJ  (1u << 4)
+#define ARMv6     (1u << 5)
+#define ARMv6K    (1u << 6)
+#define ARMv6T2   (1u << 7)
+#define ARMv7     (1u << 8)
+#define ARMv7S    (1u << 9)
+#define ARMv8     (1u << 10)
+#define ARMvAll   (0xffffffffu)
+
+#define ARMV4T_ABOVE  (ARMv4T|ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv7S|ARMv8)
+#define ARMV5_ABOVE   (ARMv5T|ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv7S|ARMv8)
+#define ARMV5TE_ABOVE (ARMv5TE|ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv7S|ARMv8)
+#define ARMV5J_ABOVE  (ARMv5TEJ|ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv7S|ARMv8)
+#define ARMV6_ABOVE   (ARMv6|ARMv6K|ARMv6T2|ARMv7|ARMv7S|ARMv8) 
+#define ARMV6T2_ABOVE (ARMv6T2|ARMv7|ARMv7S|ARMv8)
+#define ARMV7_ABOVE   (ARMv7|ARMv7S|ARMv8)
+
+#define No_VFP  0
+#define VFPv1   (1u << 1)
+#define VFPv2   (1u << 2)
+#define VFPv3   (1u << 3)
+#define AdvancedSIMD (1u << 4)
+
+#define VFPv1_ABOVE (VFPv1 | VFPv2 | VFPv3 | AdvancedSIMD)
+#define VFPv2_ABOVE (VFPv2 | VFPv3 | AdvancedSIMD)
+#define VFPv2v3     (VFPv2 | VFPv3)
+
+//----------------------------------------------------------------------
+//
+// EmulateInstructionARM implementation
+//
+//----------------------------------------------------------------------
+
+void
+EmulateInstructionARM::Initialize ()
+{
+    PluginManager::RegisterPlugin (GetPluginNameStatic (),
+                                   GetPluginDescriptionStatic (),
+                                   CreateInstance);
+}
+
+void
+EmulateInstructionARM::Terminate ()
+{
+    PluginManager::UnregisterPlugin (CreateInstance);
+}
+
+ConstString
+EmulateInstructionARM::GetPluginNameStatic ()
+{
+    static ConstString g_name("arm");
+    return g_name;
+}
+
+const char *
+EmulateInstructionARM::GetPluginDescriptionStatic ()
+{
+    return "Emulate instructions for the ARM architecture.";
+}
+
+EmulateInstruction *
+EmulateInstructionARM::CreateInstance (const ArchSpec &arch, InstructionType inst_type)
+{
+    if (EmulateInstructionARM::SupportsEmulatingIntructionsOfTypeStatic(inst_type))
+    {
+        if (arch.GetTriple().getArch() == llvm::Triple::arm)
+        {
+            std::unique_ptr<EmulateInstructionARM> emulate_insn_ap (new EmulateInstructionARM (arch));
+            
+            if (emulate_insn_ap.get())
+                return emulate_insn_ap.release();
+        }
+        else if (arch.GetTriple().getArch() == llvm::Triple::thumb)
+        {
+            std::unique_ptr<EmulateInstructionARM> emulate_insn_ap (new EmulateInstructionARM (arch));
+            
+            if (emulate_insn_ap.get())
+                return emulate_insn_ap.release();
+        }
+    }
+    
+    return NULL;
+}
+
+bool
+EmulateInstructionARM::SetTargetTriple (const ArchSpec &arch)
+{
+    if (arch.GetTriple().getArch () == llvm::Triple::arm)
+        return true;
+    else if (arch.GetTriple().getArch () == llvm::Triple::thumb)
+        return true;
+       
+    return false;
+}
+    
+// Write "bits (32) UNKNOWN" to memory address "address".  Helper function for many ARM instructions.
+bool
+EmulateInstructionARM::WriteBits32UnknownToMemory (addr_t address)
+{
+    EmulateInstruction::Context context;
+    context.type = EmulateInstruction::eContextWriteMemoryRandomBits;
+    context.SetNoArgs ();
+
+    uint32_t random_data = rand ();
+    const uint32_t addr_byte_size = GetAddressByteSize();
+    
+    if (!MemAWrite (context, address, random_data, addr_byte_size))
+        return false;
+    
+    return true;
+}
+
+// Write "bits (32) UNKNOWN" to register n.  Helper function for many ARM instructions.
+bool
+EmulateInstructionARM::WriteBits32Unknown (int n)
+{
+    EmulateInstruction::Context context;
+    context.type = EmulateInstruction::eContextWriteRegisterRandomBits;
+    context.SetNoArgs ();
+
+    bool success;
+    uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
+                  
+    if (!success)
+        return false;
+   
+    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
+        return false;
+    
+    return true;
+}
+
+bool
+EmulateInstructionARM::GetRegisterInfo (uint32_t reg_kind, uint32_t reg_num, RegisterInfo &reg_info)
+{
+    if (reg_kind == eRegisterKindGeneric)
+    {
+        switch (reg_num)
+        {
+            case LLDB_REGNUM_GENERIC_PC:    reg_kind = eRegisterKindDWARF; reg_num = dwarf_pc; break;
+            case LLDB_REGNUM_GENERIC_SP:    reg_kind = eRegisterKindDWARF; reg_num = dwarf_sp; break;
+            case LLDB_REGNUM_GENERIC_FP:    reg_kind = eRegisterKindDWARF; reg_num = dwarf_r7; break;
+            case LLDB_REGNUM_GENERIC_RA:    reg_kind = eRegisterKindDWARF; reg_num = dwarf_lr; break;
+            case LLDB_REGNUM_GENERIC_FLAGS: reg_kind = eRegisterKindDWARF; reg_num = dwarf_cpsr; break;
+            default: return false;
+        }
+    }
+    
+    if (reg_kind == eRegisterKindDWARF)
+        return GetARMDWARFRegisterInfo(reg_num, reg_info);
+    return false;
+}
+
+uint32_t
+EmulateInstructionARM::GetFramePointerRegisterNumber () const
+{
+    if (m_opcode_mode == eModeThumb)
+    {
+        switch (m_arch.GetTriple().getOS())
+        {
+            case llvm::Triple::Darwin:
+            case llvm::Triple::MacOSX:
+            case llvm::Triple::IOS:
+                return 7;
+            default:
+                break;
+        }
+    }
+    return 11;
+}
+
+uint32_t
+EmulateInstructionARM::GetFramePointerDWARFRegisterNumber () const
+{
+    if (m_opcode_mode == eModeThumb)
+    {
+        switch (m_arch.GetTriple().getOS())
+        {
+            case llvm::Triple::Darwin:
+            case llvm::Triple::MacOSX:
+            case llvm::Triple::IOS:
+                return dwarf_r7;
+            default:
+                break;
+        }
+    }
+    return dwarf_r11;
+}
+
+// Push Multiple Registers stores multiple registers to the stack, storing to
+// consecutive memory locations ending just below the address in SP, and updates
+// SP to point to the start of the stored data.
+bool 
+EmulateInstructionARM::EmulatePUSH (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if (ConditionPassed())
+    {
+        EncodingSpecificOperations(); 
+        NullCheckIfThumbEE(13); 
+        address = SP - 4*BitCount(registers);
+
+        for (i = 0 to 14)
+        {
+            if (registers<i> == '1')
+            {
+                if i == 13 && i != LowestSetBit(registers) // Only possible for encoding A1 
+                    MemA[address,4] = bits(32) UNKNOWN;
+                else 
+                    MemA[address,4] = R[i];
+                address = address + 4;
+            }
+        }
+
+        if (registers<15> == '1') // Only possible for encoding A1 or A2 
+            MemA[address,4] = PCStoreValue();
+        
+        SP = SP - 4*BitCount(registers);
+    }
+#endif
+
+    bool conditional = false;
+    bool success = false;
+    if (ConditionPassed(opcode, &conditional))
+    {
+        const uint32_t addr_byte_size = GetAddressByteSize();
+        const addr_t sp = ReadCoreReg (SP_REG, &success);
+        if (!success)
+            return false;
+        uint32_t registers = 0;
+        uint32_t Rt; // the source register
+        switch (encoding) {
+        case eEncodingT1:
+            registers = Bits32(opcode, 7, 0);
+            // The M bit represents LR.
+            if (Bit32(opcode, 8))
+                registers |= (1u << 14);
+            // if BitCount(registers) < 1 then UNPREDICTABLE;
+            if (BitCount(registers) < 1)
+                return false;
+            break;
+        case eEncodingT2:
+            // Ignore bits 15 & 13.
+            registers = Bits32(opcode, 15, 0) & ~0xa000;
+            // if BitCount(registers) < 2 then UNPREDICTABLE;
+            if (BitCount(registers) < 2)
+                return false;
+            break;
+        case eEncodingT3:
+            Rt = Bits32(opcode, 15, 12);
+            // if BadReg(t) then UNPREDICTABLE;
+            if (BadReg(Rt))
+                return false;
+            registers = (1u << Rt);
+            break;
+        case eEncodingA1:
+            registers = Bits32(opcode, 15, 0);
+            // Instead of return false, let's handle the following case as well,
+            // which amounts to pushing one reg onto the full descending stacks.
+            // if BitCount(register_list) < 2 then SEE STMDB / STMFD;
+            break;
+        case eEncodingA2:
+            Rt = Bits32(opcode, 15, 12);
+            // if t == 13 then UNPREDICTABLE;
+            if (Rt == dwarf_sp)
+                return false;
+            registers = (1u << Rt);
+            break;
+        default:
+            return false;
+        }
+        addr_t sp_offset = addr_byte_size * BitCount (registers);
+        addr_t addr = sp - sp_offset;
+        uint32_t i;
+        
+        EmulateInstruction::Context context;
+        if (conditional)
+            context.type = EmulateInstruction::eContextRegisterStore;
+        else
+            context.type = EmulateInstruction::eContextPushRegisterOnStack;
+        RegisterInfo reg_info;
+        RegisterInfo sp_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
+        for (i=0; i<15; ++i)
+        {
+            if (BitIsSet (registers, i))
+            {
+                GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, reg_info);
+                context.SetRegisterToRegisterPlusOffset (reg_info, sp_reg, addr - sp);
+                uint32_t reg_value = ReadCoreReg(i, &success);
+                if (!success)
+                    return false;
+                if (!MemAWrite (context, addr, reg_value, addr_byte_size))
+                    return false;
+                addr += addr_byte_size;
+            }
+        }
+        
+        if (BitIsSet (registers, 15))
+        {
+            GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, reg_info);
+            context.SetRegisterToRegisterPlusOffset (reg_info, sp_reg, addr - sp);
+            const uint32_t pc = ReadCoreReg(PC_REG, &success);
+            if (!success)
+                return false;
+            if (!MemAWrite (context, addr, pc, addr_byte_size))
+                return false;
+        }
+        
+        context.type = EmulateInstruction::eContextAdjustStackPointer;
+        context.SetImmediateSigned (-sp_offset);
+    
+        if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
+            return false;
+    }
+    return true;
+}
+
+// Pop Multiple Registers loads multiple registers from the stack, loading from
+// consecutive memory locations staring at the address in SP, and updates
+// SP to point just above the loaded data.
+bool 
+EmulateInstructionARM::EmulatePOP (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if (ConditionPassed())
+    {
+        EncodingSpecificOperations(); NullCheckIfThumbEE(13);
+        address = SP;
+        for i = 0 to 14
+            if registers<i> == '1' then
+                R[i] = if UnalignedAllowed then MemU[address,4] else MemA[address,4]; address = address + 4;
+        if registers<15> == '1' then
+            if UnalignedAllowed then
+                LoadWritePC(MemU[address,4]);
+            else 
+                LoadWritePC(MemA[address,4]);
+        if registers<13> == '0' then SP = SP + 4*BitCount(registers);
+        if registers<13> == '1' then SP = bits(32) UNKNOWN;
+    }
+#endif
+
+    bool success = false;
+
+    bool conditional = false;
+    if (ConditionPassed(opcode, &conditional))
+    {
+        const uint32_t addr_byte_size = GetAddressByteSize();
+        const addr_t sp = ReadCoreReg (SP_REG, &success);
+        if (!success)
+            return false;
+        uint32_t registers = 0;
+        uint32_t Rt; // the destination register
+        switch (encoding) {
+        case eEncodingT1:
+            registers = Bits32(opcode, 7, 0);
+            // The P bit represents PC.
+            if (Bit32(opcode, 8))
+                registers |= (1u << 15);
+            // if BitCount(registers) < 1 then UNPREDICTABLE;
+            if (BitCount(registers) < 1)
+                return false;
+            break;
+        case eEncodingT2:
+            // Ignore bit 13.
+            registers = Bits32(opcode, 15, 0) & ~0x2000;
+            // if BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
+            if (BitCount(registers) < 2 || (Bit32(opcode, 15) && Bit32(opcode, 14)))
+                return false;
+            // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
+            if (BitIsSet(registers, 15) && InITBlock() && !LastInITBlock())
+                return false;
+            break;
+        case eEncodingT3:
+            Rt = Bits32(opcode, 15, 12);
+            // if t == 13 || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
+            if (Rt == 13)
+                return false;
+            if (Rt == 15 && InITBlock() && !LastInITBlock())
+                return false;
+            registers = (1u << Rt);
+            break;
+        case eEncodingA1:
+            registers = Bits32(opcode, 15, 0);
+            // Instead of return false, let's handle the following case as well,
+            // which amounts to popping one reg from the full descending stacks.
+            // if BitCount(register_list) < 2 then SEE LDM / LDMIA / LDMFD;
+
+            // if registers<13> == '1' && ArchVersion() >= 7 then UNPREDICTABLE;
+            if (BitIsSet(opcode, 13) && ArchVersion() >= ARMv7)
+                return false;
+            break;
+        case eEncodingA2:
+            Rt = Bits32(opcode, 15, 12);
+            // if t == 13 then UNPREDICTABLE;
+            if (Rt == dwarf_sp)
+                return false;
+            registers = (1u << Rt);
+            break;
+        default:
+            return false;
+        }
+        addr_t sp_offset = addr_byte_size * BitCount (registers);
+        addr_t addr = sp;
+        uint32_t i, data;
+        
+        EmulateInstruction::Context context;
+        if (conditional)
+            context.type = EmulateInstruction::eContextRegisterLoad;
+        else
+            context.type = EmulateInstruction::eContextPopRegisterOffStack;
+        
+        RegisterInfo sp_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
+
+        for (i=0; i<15; ++i)
+        {
+            if (BitIsSet (registers, i))
+            {
+                context.SetRegisterPlusOffset (sp_reg, addr - sp);
+                data = MemARead(context, addr, 4, 0, &success);
+                if (!success)
+                    return false;    
+                if (!WriteRegisterUnsigned(context, eRegisterKindDWARF, dwarf_r0 + i, data))
+                    return false;
+                addr += addr_byte_size;
+            }
+        }
+        
+        if (BitIsSet (registers, 15))
+        {
+            context.SetRegisterPlusOffset (sp_reg, addr - sp);
+            data = MemARead(context, addr, 4, 0, &success);
+            if (!success)
+                return false;
+            // In ARMv5T and above, this is an interworking branch.
+            if (!LoadWritePC(context, data))
+                return false;
+            //addr += addr_byte_size;
+        }
+        
+        context.type = EmulateInstruction::eContextAdjustStackPointer;
+        context.SetImmediateSigned (sp_offset);
+    
+        if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
+            return false;
+    }
+    return true;
+}
+
+// Set r7 or ip to point to saved value residing within the stack.
+// ADD (SP plus immediate)
+bool
+EmulateInstructionARM::EmulateADDRdSPImm (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if (ConditionPassed())
+    {
+        EncodingSpecificOperations();
+        (result, carry, overflow) = AddWithCarry(SP, imm32, '0');
+        if d == 15 then
+           ALUWritePC(result); // setflags is always FALSE here
+        else
+            R[d] = result;
+            if setflags then
+                APSR.N = result<31>;
+                APSR.Z = IsZeroBit(result);
+                APSR.C = carry;
+                APSR.V = overflow;
+    }
+#endif
+
+    bool success = false;
+
+    if (ConditionPassed(opcode))
+    {
+        const addr_t sp = ReadCoreReg (SP_REG, &success);
+        if (!success)
+            return false;
+        uint32_t Rd; // the destination register
+        uint32_t imm32;
+        switch (encoding) {
+        case eEncodingT1:
+            Rd = 7;
+            imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32)
+            break;
+        case eEncodingA1:
+            Rd = Bits32(opcode, 15, 12);
+            imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
+            break;
+        default:
+            return false;
+        }
+        addr_t sp_offset = imm32;
+        addr_t addr = sp + sp_offset; // a pointer to the stack area
+        
+        EmulateInstruction::Context context;
+        context.type = eContextSetFramePointer;
+        RegisterInfo sp_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
+        context.SetRegisterPlusOffset (sp_reg, sp_offset);
+    
+        if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, addr))
+            return false;
+    }
+    return true;
+}
+
+// Set r7 or ip to the current stack pointer.
+// MOV (register)
+bool
+EmulateInstructionARM::EmulateMOVRdSP (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if (ConditionPassed())
+    {
+        EncodingSpecificOperations();
+        result = R[m];
+        if d == 15 then
+            ALUWritePC(result); // setflags is always FALSE here
+        else
+            R[d] = result;
+            if setflags then
+                APSR.N = result<31>;
+                APSR.Z = IsZeroBit(result);
+                // APSR.C unchanged
+                // APSR.V unchanged
+    }
+#endif
+
+    bool success = false;
+
+    if (ConditionPassed(opcode))
+    {
+        const addr_t sp = ReadCoreReg (SP_REG, &success);
+        if (!success)
+            return false;
+        uint32_t Rd; // the destination register
+        switch (encoding) {
+        case eEncodingT1:
+            Rd = 7;
+            break;
+        case eEncodingA1:
+            Rd = 12;
+            break;
+        default:
+            return false;
+        }
+                  
+        EmulateInstruction::Context context;
+        if (Rd == GetFramePointerRegisterNumber())
+            context.type = EmulateInstruction::eContextSetFramePointer;
+        else
+            context.type = EmulateInstruction::eContextRegisterPlusOffset;
+        RegisterInfo sp_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
+        context.SetRegisterPlusOffset (sp_reg, 0);
+    
+        if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rd, sp))
+            return false;
+    }
+    return true;
+}
+
+// Move from high register (r8-r15) to low register (r0-r7).
+// MOV (register)
+bool
+EmulateInstructionARM::EmulateMOVLowHigh (const uint32_t opcode, const ARMEncoding encoding)
+{
+    return EmulateMOVRdRm (opcode, encoding);
+}
+
+// Move from register to register.
+// MOV (register)
+bool
+EmulateInstructionARM::EmulateMOVRdRm (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if (ConditionPassed())
+    {
+        EncodingSpecificOperations();
+        result = R[m];
+        if d == 15 then
+            ALUWritePC(result); // setflags is always FALSE here
+        else
+            R[d] = result;
+            if setflags then
+                APSR.N = result<31>;
+                APSR.Z = IsZeroBit(result);
+                // APSR.C unchanged
+                // APSR.V unchanged
+    }
+#endif
+
+    bool success = false;
+
+    if (ConditionPassed(opcode))
+    {
+        uint32_t Rm; // the source register
+        uint32_t Rd; // the destination register
+        bool setflags;
+        switch (encoding) {
+        case eEncodingT1:
+            Rd = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
+            Rm = Bits32(opcode, 6, 3);
+            setflags = false;
+            if (Rd == 15 && InITBlock() && !LastInITBlock())
+                return false;
+            break;
+        case eEncodingT2:
+            Rd = Bits32(opcode, 2, 0);
+            Rm = Bits32(opcode, 5, 3);
+            setflags = true;
+            if (InITBlock())
+                return false;
+            break;
+        case eEncodingT3:
+            Rd = Bits32(opcode, 11, 8);
+            Rm = Bits32(opcode, 3, 0);
+            setflags = BitIsSet(opcode, 20);
+            // if setflags && (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
+            if (setflags && (BadReg(Rd) || BadReg(Rm)))
+                return false;
+            // if !setflags && (d == 15 || m == 15 || (d == 13 && m == 13)) then UNPREDICTABLE;
+            if (!setflags && (Rd == 15 || Rm == 15 || (Rd == 13 && Rm == 13)))
+                return false;
+            break;
+        case eEncodingA1:
+            Rd = Bits32(opcode, 15, 12);
+            Rm = Bits32(opcode, 3, 0);
+            setflags = BitIsSet(opcode, 20);
+
+            // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
+            if (Rd == 15 && setflags)
+                return EmulateSUBSPcLrEtc (opcode, encoding);
+            break;
+        default:
+            return false;
+        }
+        uint32_t result = ReadCoreReg(Rm, &success);
+        if (!success)
+            return false;
+        
+        // The context specifies that Rm is to be moved into Rd.
+        EmulateInstruction::Context context;
+        context.type = EmulateInstruction::eContextRegisterLoad;
+        RegisterInfo dwarf_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
+        context.SetRegister (dwarf_reg);
+
+        if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags))
+            return false;
+    }
+    return true;
+}
+
+// Move (immediate) writes an immediate value to the destination register.  It
+// can optionally update the condition flags based on the value.
+// MOV (immediate)
+bool
+EmulateInstructionARM::EmulateMOVRdImm (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if (ConditionPassed())
+    {
+        EncodingSpecificOperations();
+        result = imm32;
+        if d == 15 then         // Can only occur for ARM encoding
+            ALUWritePC(result); // setflags is always FALSE here
+        else
+            R[d] = result;
+            if setflags then
+                APSR.N = result<31>;
+                APSR.Z = IsZeroBit(result);
+                APSR.C = carry;
+                // APSR.V unchanged
+    }
+#endif
+
+    if (ConditionPassed(opcode))
+    {
+        uint32_t Rd; // the destination register
+        uint32_t imm32; // the immediate value to be written to Rd
+        uint32_t carry = 0; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C.
+                            // for setflags == false, this value is a don't care
+                            // initialized to 0 to silence the static analyzer
+        bool setflags;
+        switch (encoding) {
+            case eEncodingT1:
+                Rd = Bits32(opcode, 10, 8);
+                setflags = !InITBlock();
+                imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
+                carry = APSR_C;
+                  
+                break;
+                  
+            case eEncodingT2:
+                Rd = Bits32(opcode, 11, 8);
+                setflags = BitIsSet(opcode, 20);
+                imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
+                if (BadReg(Rd))
+                  return false;
+                  
+                break;
+                  
+            case eEncodingT3:
+            {
+                // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:i:imm3:imm8, 32);
+                Rd = Bits32 (opcode, 11, 8);
+                setflags = false;
+                uint32_t imm4 = Bits32 (opcode, 19, 16);
+                uint32_t imm3 = Bits32 (opcode, 14, 12);
+                uint32_t i = Bit32 (opcode, 26);
+                uint32_t imm8 = Bits32 (opcode, 7, 0);
+                imm32 = (imm4 << 12) | (i << 11) | (imm3 << 8) | imm8;
+                  
+                // if BadReg(d) then UNPREDICTABLE;
+                if (BadReg (Rd))
+                    return false;
+            }
+                break;
+                  
+            case eEncodingA1:
+                // d = UInt(Rd); setflags = (S == �1�); (imm32, carry) = ARMExpandImm_C(imm12, APSR.C);
+                Rd = Bits32 (opcode, 15, 12);
+                setflags = BitIsSet (opcode, 20);
+                imm32 = ARMExpandImm_C (opcode, APSR_C, carry);
+
+                // if Rd == �1111� && S == �1� then SEE SUBS PC, LR and related instructions;
+                if ((Rd == 15) && setflags)
+                    return EmulateSUBSPcLrEtc (opcode, encoding);
+                  
+                break;
+                  
+            case eEncodingA2:
+            {
+                // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm4:imm12, 32);
+                Rd = Bits32 (opcode, 15, 12);
+                setflags = false;
+                uint32_t imm4 = Bits32 (opcode, 19, 16);
+                uint32_t imm12 = Bits32 (opcode, 11, 0);
+                imm32 = (imm4 << 12) | imm12;
+                  
+                // if d == 15 then UNPREDICTABLE;
+                if (Rd == 15)
+                    return false;
+            }
+                break;
+                  
+            default:
+                return false;
+        }
+        uint32_t result = imm32;
+
+        // The context specifies that an immediate is to be moved into Rd.
+        EmulateInstruction::Context context;
+        context.type = EmulateInstruction::eContextImmediate;
+        context.SetNoArgs ();
+
+        if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
+            return false;
+    }
+    return true;
+}
+
+// MUL multiplies two register values.  The least significant 32 bits of the result are written to the destination 
+// register.  These 32 bits do not depend on whether the source register values are considered to be signed values or 
+// unsigned values.
+//
+// Optionally, it can update the condition flags based on the result.  In the Thumb instruction set, this option is 
+// limited to only a few forms of the instruction.
+bool
+EmulateInstructionARM::EmulateMUL (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    if ConditionPassed() then 
+        EncodingSpecificOperations(); 
+        operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results 
+        operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results 
+        result = operand1 * operand2; 
+        R[d] = result<31:0>; 
+        if setflags then
+            APSR.N = result<31>; 
+            APSR.Z = IsZeroBit(result); 
+            if ArchVersion() == 4 then
+                APSR.C = bit UNKNOWN; 
+            // else APSR.C unchanged 
+            // APSR.V always unchanged
+#endif
+    
+    if (ConditionPassed(opcode))
+    {
+        uint32_t d;
+        uint32_t n;
+        uint32_t m;
+        bool setflags;
+                  
+        // EncodingSpecificOperations(); 
+        switch (encoding)
+        {
+            case eEncodingT1:
+                // d = UInt(Rdm); n = UInt(Rn); m = UInt(Rdm); setflags = !InITBlock(); 
+                d = Bits32 (opcode, 2, 0);
+                n = Bits32 (opcode, 5, 3);
+                m = Bits32 (opcode, 2, 0);
+                setflags = !InITBlock();
+                  
+                // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
+                if ((ArchVersion() < ARMv6) && (d == n))
+                    return false;
+                  
+                break;
+                  
+            case eEncodingT2:
+                // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = FALSE; 
+                d = Bits32 (opcode, 11, 8);
+                n = Bits32 (opcode, 19, 16);
+                m = Bits32 (opcode, 3, 0);
+                setflags = false;
+                  
+                // if BadReg(d) || BadReg(n) || BadReg(m) then UNPREDICTABLE;
+                if (BadReg (d) || BadReg (n) || BadReg (m))
+                    return false;
+                  
+                break;
+                  
+            case eEncodingA1:
+                // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == '1'); 
+                d = Bits32 (opcode, 19, 16);
+                n = Bits32 (opcode, 3, 0);
+                m = Bits32 (opcode, 11, 8);
+                setflags = BitIsSet (opcode, 20);
+                  
+                // if d == 15 || n == 15 || m == 15 then UNPREDICTABLE; 
+                if ((d == 15) ||  (n == 15) || (m == 15))
+                    return false;
+                  
+                // if ArchVersion() < 6 && d == n then UNPREDICTABLE;
+                if ((ArchVersion() < ARMv6) && (d == n))
+                    return false;
+                  
+                break;
+                  
+            default:
+                return false;
+        }
+
+        bool success = false;
+
+        // operand1 = SInt(R[n]); // operand1 = UInt(R[n]) produces the same final results
+        uint64_t operand1 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
+        if (!success)
+            return false;
+                  
+        // operand2 = SInt(R[m]); // operand2 = UInt(R[m]) produces the same final results 
+        uint64_t operand2 = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
+        if (!success)
+            return false;
+                  
+        // result = operand1 * operand2; 
+        uint64_t result = operand1 * operand2;
+                  
+        // R[d] = result<31:0>; 
+        RegisterInfo op1_reg;
+        RegisterInfo op2_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, op1_reg);
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, op2_reg);
+                  
+        EmulateInstruction::Context context;
+        context.type = eContextArithmetic;
+        context.SetRegisterRegisterOperands (op1_reg, op2_reg);
+                  
+        if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (0x0000ffff & result)))
+            return false;
+                  
+        // if setflags then
+        if (setflags)
+        {
+            // APSR.N = result<31>; 
+            // APSR.Z = IsZeroBit(result);
+            m_new_inst_cpsr = m_opcode_cpsr;
+            SetBit32 (m_new_inst_cpsr, CPSR_N_POS, Bit32 (result, 31));
+            SetBit32 (m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
+            if (m_new_inst_cpsr != m_opcode_cpsr)
+            {
+                if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
+                    return false;
+            }
+            
+            // if ArchVersion() == 4 then
+                // APSR.C = bit UNKNOWN;   
+        }
+    }
+    return true;
+}
+                  
+// Bitwise NOT (immediate) writes the bitwise inverse of an immediate value to the destination register.
+// It can optionally update the condition flags based on the value.
+bool
+EmulateInstructionARM::EmulateMVNImm (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if (ConditionPassed())
+    {
+        EncodingSpecificOperations();
+        result = NOT(imm32);
+        if d == 15 then         // Can only occur for ARM encoding
+            ALUWritePC(result); // setflags is always FALSE here
+        else
+            R[d] = result;
+            if setflags then
+                APSR.N = result<31>;
+                APSR.Z = IsZeroBit(result);
+                APSR.C = carry;
+                // APSR.V unchanged
+    }
+#endif
+
+    if (ConditionPassed(opcode))
+    {
+        uint32_t Rd; // the destination register
+        uint32_t imm32; // the output after ThumbExpandImm_C or ARMExpandImm_C
+        uint32_t carry; // the carry bit after ThumbExpandImm_C or ARMExpandImm_C
+        bool setflags;
+        switch (encoding) {
+        case eEncodingT1:
+            Rd = Bits32(opcode, 11, 8);
+            setflags = BitIsSet(opcode, 20);
+            imm32 = ThumbExpandImm_C(opcode, APSR_C, carry);
+            break;
+        case eEncodingA1:
+            Rd = Bits32(opcode, 15, 12);
+            setflags = BitIsSet(opcode, 20);
+            imm32 = ARMExpandImm_C(opcode, APSR_C, carry);
+
+            // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
+            if (Rd == 15 && setflags)
+                return EmulateSUBSPcLrEtc (opcode, encoding);
+            break;
+        default:
+            return false;
+        }
+        uint32_t result = ~imm32;
+        
+        // The context specifies that an immediate is to be moved into Rd.
+        EmulateInstruction::Context context;
+        context.type = EmulateInstruction::eContextImmediate;
+        context.SetNoArgs ();
+
+        if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
+            return false;
+    }
+    return true;
+}
+
+// Bitwise NOT (register) writes the bitwise inverse of a register value to the destination register.
+// It can optionally update the condition flags based on the result.
+bool
+EmulateInstructionARM::EmulateMVNReg (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if (ConditionPassed())
+    {
+        EncodingSpecificOperations();
+        (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
+        result = NOT(shifted);
+        if d == 15 then         // Can only occur for ARM encoding
+            ALUWritePC(result); // setflags is always FALSE here
+        else
+            R[d] = result;
+            if setflags then
+                APSR.N = result<31>;
+                APSR.Z = IsZeroBit(result);
+                APSR.C = carry;
+                // APSR.V unchanged
+    }
+#endif
+
+    if (ConditionPassed(opcode))
+    {
+        uint32_t Rm; // the source register
+        uint32_t Rd; // the destination register
+        ARM_ShifterType shift_t;
+        uint32_t shift_n; // the shift applied to the value read from Rm
+        bool setflags;
+        uint32_t carry; // the carry bit after the shift operation
+        switch (encoding) {
+        case eEncodingT1:
+            Rd = Bits32(opcode, 2, 0);
+            Rm = Bits32(opcode, 5, 3);
+            setflags = !InITBlock();
+            shift_t = SRType_LSL;
+            shift_n = 0;
+            if (InITBlock())
+                return false;
+            break;
+        case eEncodingT2:
+            Rd = Bits32(opcode, 11, 8);
+            Rm = Bits32(opcode, 3, 0);
+            setflags = BitIsSet(opcode, 20);
+            shift_n = DecodeImmShiftThumb(opcode, shift_t);
+            // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
+            if (BadReg(Rd) || BadReg(Rm))
+                return false;
+            break;
+        case eEncodingA1:
+            Rd = Bits32(opcode, 15, 12);
+            Rm = Bits32(opcode, 3, 0);
+            setflags = BitIsSet(opcode, 20);
+            shift_n = DecodeImmShiftARM(opcode, shift_t);
+            break;
+        default:
+            return false;
+        }
+        bool success = false;
+        uint32_t value = ReadCoreReg(Rm, &success);
+        if (!success)
+            return false;
+
+        uint32_t shifted = Shift_C(value, shift_t, shift_n, APSR_C, carry, &success);
+        if (!success)
+            return false;
+        uint32_t result = ~shifted;
+        
+        // The context specifies that an immediate is to be moved into Rd.
+        EmulateInstruction::Context context;
+        context.type = EmulateInstruction::eContextImmediate;
+        context.SetNoArgs ();
+
+        if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
+            return false;
+    }
+    return true;
+}
+
+// PC relative immediate load into register, possibly followed by ADD (SP plus register).
+// LDR (literal)
+bool
+EmulateInstructionARM::EmulateLDRRtPCRelative (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if (ConditionPassed())
+    {
+        EncodingSpecificOperations(); NullCheckIfThumbEE(15);
+        base = Align(PC,4);
+        address = if add then (base + imm32) else (base - imm32);
+        data = MemU[address,4];
+        if t == 15 then
+            if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
+        elsif UnalignedSupport() || address<1:0> = '00' then
+            R[t] = data;
+        else // Can only apply before ARMv7
+            if CurrentInstrSet() == InstrSet_ARM then
+                R[t] = ROR(data, 8*UInt(address<1:0>));
+            else
+                R[t] = bits(32) UNKNOWN;
+    }
+#endif
+
+    if (ConditionPassed(opcode))
+    {
+        bool success = false;
+        const uint32_t pc = ReadCoreReg(PC_REG, &success);
+        if (!success)
+            return false;
+
+        // PC relative immediate load context
+        EmulateInstruction::Context context;
+        context.type = EmulateInstruction::eContextRegisterPlusOffset;
+        RegisterInfo pc_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg);
+        context.SetRegisterPlusOffset (pc_reg, 0);                             
+                                               
+        uint32_t Rt;    // the destination register
+        uint32_t imm32; // immediate offset from the PC
+        bool add;       // +imm32 or -imm32?
+        addr_t base;    // the base address
+        addr_t address; // the PC relative address
+        uint32_t data;  // the literal data value from the PC relative load
+        switch (encoding) {
+        case eEncodingT1:
+            Rt = Bits32(opcode, 10, 8);
+            imm32 = Bits32(opcode, 7, 0) << 2; // imm32 = ZeroExtend(imm8:'00', 32);
+            add = true;
+            break;
+        case eEncodingT2:
+            Rt = Bits32(opcode, 15, 12);
+            imm32 = Bits32(opcode, 11, 0) << 2; // imm32 = ZeroExtend(imm12, 32);
+            add = BitIsSet(opcode, 23);
+            if (Rt == 15 && InITBlock() && !LastInITBlock())
+                return false;
+            break;
+        default:
+            return false;
+        }
+
+        base = Align(pc, 4);
+        if (add)
+            address = base + imm32;
+        else
+            address = base - imm32;
+
+        context.SetRegisterPlusOffset(pc_reg, address - base);
+        data = MemURead(context, address, 4, 0, &success);
+        if (!success)
+            return false;    
+
+        if (Rt == 15)
+        {
+            if (Bits32(address, 1, 0) == 0)
+            {
+                // In ARMv5T and above, this is an interworking branch.
+                if (!LoadWritePC(context, data))
+                    return false;
+            }
+            else
+                return false;
+        }
+        else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
+        {
+            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
+                return false;
+        }
+        else // We don't handle ARM for now.
+            return false;
+
+    }
+    return true;
+}
+
+// An add operation to adjust the SP.
+// ADD (SP plus immediate)
+bool
+EmulateInstructionARM::EmulateADDSPImm (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if (ConditionPassed())
+    {
+        EncodingSpecificOperations();
+        (result, carry, overflow) = AddWithCarry(SP, imm32, '0');
+        if d == 15 then // Can only occur for ARM encoding
+            ALUWritePC(result); // setflags is always FALSE here
+        else
+            R[d] = result;
+            if setflags then
+                APSR.N = result<31>;
+                APSR.Z = IsZeroBit(result);
+                APSR.C = carry;
+                APSR.V = overflow;
+    }
+#endif
+
+    bool success = false;
+
+    if (ConditionPassed(opcode))
+    {
+        const addr_t sp = ReadCoreReg (SP_REG, &success);
+        if (!success)
+            return false;
+        uint32_t imm32; // the immediate operand
+        uint32_t d;
+        //bool setflags = false; // Add this back if/when support eEncodingT3 eEncodingA1
+        switch (encoding) 
+        {
+            case eEncodingT1:
+                // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm8:'00', 32);
+                d = Bits32 (opcode, 10, 8);
+                imm32 = (Bits32 (opcode, 7, 0) << 2);
+                  
+                break;
+                  
+            case eEncodingT2:
+                // d = 13; setflags = FALSE; imm32 = ZeroExtend(imm7:'00', 32);
+                d = 13;
+                imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
+                  
+                break;
+                  
+            default:
+                return false;
+        }
+        addr_t sp_offset = imm32;
+        addr_t addr = sp + sp_offset; // the adjusted stack pointer value
+        
+        EmulateInstruction::Context context;
+        context.type = EmulateInstruction::eContextAdjustStackPointer;
+        RegisterInfo sp_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
+        context.SetRegisterPlusOffset (sp_reg, sp_offset);
+    
+        if (d == 15)
+        {
+            if (!ALUWritePC (context, addr))
+                return false;
+        }
+        else
+        {
+            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, addr))
+                return false;
+            
+            // Add this back if/when support eEncodingT3 eEncodingA1
+            //if (setflags)
+            //{
+            //    APSR.N = result<31>;
+            //    APSR.Z = IsZeroBit(result);
+            //    APSR.C = carry;
+            //    APSR.V = overflow;
+            //}
+        }
+    }
+    return true;
+}
+
+// An add operation to adjust the SP.
+// ADD (SP plus register)
+bool
+EmulateInstructionARM::EmulateADDSPRm (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if (ConditionPassed())
+    {
+        EncodingSpecificOperations();
+        shifted = Shift(R[m], shift_t, shift_n, APSR.C);
+        (result, carry, overflow) = AddWithCarry(SP, shifted, '0');
+        if d == 15 then
+            ALUWritePC(result); // setflags is always FALSE here
+        else
+            R[d] = result;
+            if setflags then
+                APSR.N = result<31>;
+                APSR.Z = IsZeroBit(result);
+                APSR.C = carry;
+                APSR.V = overflow;
+    }
+#endif
+
+    bool success = false;
+
+    if (ConditionPassed(opcode))
+    {
+        const addr_t sp = ReadCoreReg (SP_REG, &success);
+        if (!success)
+            return false;
+        uint32_t Rm; // the second operand
+        switch (encoding) {
+        case eEncodingT2:
+            Rm = Bits32(opcode, 6, 3);
+            break;
+        default:
+            return false;
+        }
+        int32_t reg_value = ReadCoreReg(Rm, &success);
+        if (!success)
+            return false;
+
+        addr_t addr = (int32_t)sp + reg_value; // the adjusted stack pointer value
+        
+        EmulateInstruction::Context context;
+        context.type = eContextArithmetic;
+        RegisterInfo sp_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
+        
+        RegisterInfo other_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, other_reg);
+        context.SetRegisterRegisterOperands (sp_reg, other_reg);
+    
+        if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, addr))
+            return false;
+    }
+    return true;
+}
+
+// Branch with Link and Exchange Instruction Sets (immediate) calls a subroutine
+// at a PC-relative address, and changes instruction set from ARM to Thumb, or
+// from Thumb to ARM.
+// BLX (immediate)
+bool
+EmulateInstructionARM::EmulateBLXImmediate (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if (ConditionPassed())
+    {
+        EncodingSpecificOperations();
+        if CurrentInstrSet() == InstrSet_ARM then
+            LR = PC - 4;
+        else
+            LR = PC<31:1> : '1';
+        if targetInstrSet == InstrSet_ARM then
+            targetAddress = Align(PC,4) + imm32;
+        else
+            targetAddress = PC + imm32;
+        SelectInstrSet(targetInstrSet);
+        BranchWritePC(targetAddress);
+    }
+#endif
+
+    bool success = true;
+
+    if (ConditionPassed(opcode))
+    {
+        EmulateInstruction::Context context;
+        context.type = EmulateInstruction::eContextRelativeBranchImmediate;
+        const uint32_t pc = ReadCoreReg(PC_REG, &success);
+        if (!success)
+            return false;
+        addr_t lr; // next instruction address
+        addr_t target; // target address
+        int32_t imm32; // PC-relative offset
+        switch (encoding) {
+        case eEncodingT1:
+            {
+            lr = pc | 1u; // return address
+            uint32_t S = Bit32(opcode, 26);
+            uint32_t imm10 = Bits32(opcode, 25, 16);
+            uint32_t J1 = Bit32(opcode, 13);
+            uint32_t J2 = Bit32(opcode, 11);
+            uint32_t imm11 = Bits32(opcode, 10, 0);
+            uint32_t I1 = !(J1 ^ S);
+            uint32_t I2 = !(J2 ^ S);
+            uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
+            imm32 = llvm::SignExtend32<25>(imm25);
+            target = pc + imm32;
+            context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
+            if (InITBlock() && !LastInITBlock())
+                return false;
+            break;
+            }
+        case eEncodingT2:
+            {
+            lr = pc | 1u; // return address
+            uint32_t S = Bit32(opcode, 26);
+            uint32_t imm10H = Bits32(opcode, 25, 16);
+            uint32_t J1 = Bit32(opcode, 13);
+            uint32_t J2 = Bit32(opcode, 11);
+            uint32_t imm10L = Bits32(opcode, 10, 1);
+            uint32_t I1 = !(J1 ^ S);
+            uint32_t I2 = !(J2 ^ S);
+            uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10H << 12) | (imm10L << 2);
+            imm32 = llvm::SignExtend32<25>(imm25);
+            target = Align(pc, 4) + imm32;
+            context.SetISAAndImmediateSigned (eModeARM, 4 + imm32);
+            if (InITBlock() && !LastInITBlock())
+                return false;
+            break;
+            }
+        case eEncodingA1:
+            lr = pc - 4; // return address
+            imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
+            target = Align(pc, 4) + imm32;
+            context.SetISAAndImmediateSigned (eModeARM, 8 + imm32);
+            break;
+        case eEncodingA2:
+            lr = pc - 4; // return address
+            imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2 | Bits32(opcode, 24, 24) << 1);
+            target = pc + imm32;
+            context.SetISAAndImmediateSigned (eModeThumb, 8 + imm32);
+            break;
+        default:
+            return false;
+        }
+        if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
+            return false;
+        if (!BranchWritePC(context, target))
+            return false;
+    }
+    return true;
+}
+
+// Branch with Link and Exchange (register) calls a subroutine at an address and
+// instruction set specified by a register.
+// BLX (register)
+bool
+EmulateInstructionARM::EmulateBLXRm (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if (ConditionPassed())
+    {
+        EncodingSpecificOperations();
+        target = R[m];
+        if CurrentInstrSet() == InstrSet_ARM then
+            next_instr_addr = PC - 4;
+            LR = next_instr_addr;
+        else
+            next_instr_addr = PC - 2;
+            LR = next_instr_addr<31:1> : '1';
+        BXWritePC(target);
+    }
+#endif
+
+    bool success = false;
+
+    if (ConditionPassed(opcode))
+    {
+        EmulateInstruction::Context context;
+        context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
+        const uint32_t pc = ReadCoreReg(PC_REG, &success);
+        addr_t lr; // next instruction address
+        if (!success)
+            return false;
+        uint32_t Rm; // the register with the target address
+        switch (encoding) {
+        case eEncodingT1:
+            lr = (pc - 2) | 1u; // return address
+            Rm = Bits32(opcode, 6, 3);
+            // if m == 15 then UNPREDICTABLE;
+            if (Rm == 15)
+                return false;
+            if (InITBlock() && !LastInITBlock())
+                return false;
+            break;
+        case eEncodingA1:
+            lr = pc - 4; // return address
+            Rm = Bits32(opcode, 3, 0);
+            // if m == 15 then UNPREDICTABLE;
+            if (Rm == 15)
+                return false;
+            break;
+        default:
+            return false;
+        }
+        addr_t target = ReadCoreReg (Rm, &success);
+        if (!success)
+            return false;
+        RegisterInfo dwarf_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
+        context.SetRegister (dwarf_reg);
+        if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
+            return false;
+        if (!BXWritePC(context, target))
+            return false;
+    }
+    return true;
+}
+
+// Branch and Exchange causes a branch to an address and instruction set specified by a register.
+bool
+EmulateInstructionARM::EmulateBXRm (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if (ConditionPassed())
+    {
+        EncodingSpecificOperations();
+        BXWritePC(R[m]);
+    }
+#endif
+
+    if (ConditionPassed(opcode))
+    {
+        EmulateInstruction::Context context;
+        context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
+        uint32_t Rm; // the register with the target address
+        switch (encoding) {
+        case eEncodingT1:
+            Rm = Bits32(opcode, 6, 3);
+            if (InITBlock() && !LastInITBlock())
+                return false;
+            break;
+        case eEncodingA1:
+            Rm = Bits32(opcode, 3, 0);
+            break;
+        default:
+            return false;
+        }
+        bool success = false;
+        addr_t target = ReadCoreReg (Rm, &success);
+        if (!success)
+            return false;
+
+        RegisterInfo dwarf_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
+        context.SetRegister (dwarf_reg);
+        if (!BXWritePC(context, target))
+            return false;
+    }
+    return true;
+}
+
+// Branch and Exchange Jazelle attempts to change to Jazelle state. If the attempt fails, it branches to an
+// address and instruction set specified by a register as though it were a BX instruction.
+//
+// TODO: Emulate Jazelle architecture?
+//       We currently assume that switching to Jazelle state fails, thus treating BXJ as a BX operation.
+bool
+EmulateInstructionARM::EmulateBXJRm (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if (ConditionPassed())
+    {
+        EncodingSpecificOperations();
+        if JMCR.JE == '0' || CurrentInstrSet() == InstrSet_ThumbEE then
+            BXWritePC(R[m]);
+        else
+            if JazelleAcceptsExecution() then
+                SwitchToJazelleExecution();
+            else
+                SUBARCHITECTURE_DEFINED handler call;
+    }
+#endif
+
+    if (ConditionPassed(opcode))
+    {
+        EmulateInstruction::Context context;
+        context.type = EmulateInstruction::eContextAbsoluteBranchRegister;
+        uint32_t Rm; // the register with the target address
+        switch (encoding) {
+        case eEncodingT1:
+            Rm = Bits32(opcode, 19, 16);
+            if (BadReg(Rm))
+                return false;
+            if (InITBlock() && !LastInITBlock())
+                return false;
+            break;
+        case eEncodingA1:
+            Rm = Bits32(opcode, 3, 0);
+            if (Rm == 15)
+                return false;
+            break;
+        default:
+            return false;
+        }
+        bool success = false;
+        addr_t target = ReadCoreReg (Rm, &success);
+        if (!success)
+            return false;
+                  
+        RegisterInfo dwarf_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, dwarf_reg);
+        context.SetRegister (dwarf_reg);
+        if (!BXWritePC(context, target))
+            return false;
+    }
+    return true;
+}
+
+// Set r7 to point to some ip offset.
+// SUB (immediate)
+bool
+EmulateInstructionARM::EmulateSUBR7IPImm (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if (ConditionPassed())
+    {
+        EncodingSpecificOperations();
+        (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
+        if d == 15 then // Can only occur for ARM encoding
+           ALUWritePC(result); // setflags is always FALSE here
+        else
+            R[d] = result;
+            if setflags then
+                APSR.N = result<31>;
+                APSR.Z = IsZeroBit(result);
+                APSR.C = carry;
+                APSR.V = overflow;
+    }
+#endif
+
+    if (ConditionPassed(opcode))
+    {
+        bool success = false;
+        const addr_t ip = ReadCoreReg (12, &success);
+        if (!success)
+            return false;
+        uint32_t imm32;
+        switch (encoding) {
+        case eEncodingA1:
+            imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
+            break;
+        default:
+            return false;
+        }
+        addr_t ip_offset = imm32;
+        addr_t addr = ip - ip_offset; // the adjusted ip value
+        
+        EmulateInstruction::Context context;
+        context.type = EmulateInstruction::eContextRegisterPlusOffset;
+        RegisterInfo dwarf_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r12, dwarf_reg);
+        context.SetRegisterPlusOffset (dwarf_reg, -ip_offset);                             
+    
+        if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r7, addr))
+            return false;
+    }
+    return true;
+}
+
+// Set ip to point to some stack offset.
+// SUB (SP minus immediate)
+bool
+EmulateInstructionARM::EmulateSUBIPSPImm (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if (ConditionPassed())
+    {
+        EncodingSpecificOperations();
+        (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
+        if d == 15 then // Can only occur for ARM encoding
+           ALUWritePC(result); // setflags is always FALSE here
+        else
+            R[d] = result;
+            if setflags then
+                APSR.N = result<31>;
+                APSR.Z = IsZeroBit(result);
+                APSR.C = carry;
+                APSR.V = overflow;
+    }
+#endif
+
+    if (ConditionPassed(opcode))
+    {
+        bool success = false;
+        const addr_t sp = ReadCoreReg (SP_REG, &success);
+        if (!success)
+            return false;
+        uint32_t imm32;
+        switch (encoding) {
+        case eEncodingA1:
+            imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
+            break;
+        default:
+            return false;
+        }
+        addr_t sp_offset = imm32;
+        addr_t addr = sp - sp_offset; // the adjusted stack pointer value
+        
+        EmulateInstruction::Context context;
+        context.type = EmulateInstruction::eContextRegisterPlusOffset;
+        RegisterInfo dwarf_reg;
+        GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, dwarf_reg);
+        context.SetRegisterPlusOffset (dwarf_reg, -sp_offset);
+    
+        if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r12, addr))
+            return false;
+    }
+    return true;
+}
+
+// This instruction subtracts an immediate value from the SP value, and writes
+// the result to the destination register.
+//
+// If Rd == 13 => A sub operation to adjust the SP -- allocate space for local storage.
+bool
+EmulateInstructionARM::EmulateSUBSPImm (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if (ConditionPassed())
+    {
+        EncodingSpecificOperations();
+        (result, carry, overflow) = AddWithCarry(SP, NOT(imm32), '1');
+        if d == 15 then        // Can only occur for ARM encoding
+           ALUWritePC(result); // setflags is always FALSE here
+        else
+            R[d] = result;
+            if setflags then
+                APSR.N = result<31>;
+                APSR.Z = IsZeroBit(result);
+                APSR.C = carry;
+                APSR.V = overflow;
+    }
+#endif
+
+    bool success = false;
+    if (ConditionPassed(opcode))
+    {
+        const addr_t sp = ReadCoreReg (SP_REG, &success);
+        if (!success)
+            return false;
+
+        uint32_t Rd;
+        bool setflags;
+        uint32_t imm32;
+        switch (encoding) {
+        case eEncodingT1:
+            Rd = 13;
+            setflags = false;
+            imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32)
+            break;
+        case eEncodingT2:
+            Rd = Bits32(opcode, 11, 8);
+            setflags = BitIsSet(opcode, 20);
+            imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
+            if (Rd == 15 && setflags)
+                return EmulateCMPImm(opcode, eEncodingT2);
+            if (Rd == 15 && !setflags)
+                return false;
+            break;
+        case eEncodingT3:
+            Rd = Bits32(opcode, 11, 8);
+            setflags = false;
+            imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
+            if (Rd == 15)
+                return false;
+            break;
+        case eEncodingA1:
+            Rd = Bits32(opcode, 15, 12);
+            setflags = BitIsSet(opcode, 20);
+            imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
+
+            // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
+            if (Rd == 15 && setflags)
+                return EmulateSUBSPcLrEtc (opcode, encoding);
+            break;
+        default:
+            return false;
+        }
+        AddWithCarryResult res = AddWithCarry(sp, ~imm32, 1);
+
+        EmulateInstruction::Context context;
+        if (Rd == 13)
+        {
+            uint64_t imm64 = imm32;  // Need to expand it to 64 bits before attempting to negate it, or the wrong
+                                     // value gets passed down to context.SetImmediateSigned.
+            context.type = EmulateInstruction::eContextAdjustStackPointer;
+            context.SetImmediateSigned (-imm64); // the stack pointer offset
+        }
+        else
+        {
+            context.type = EmulateInstruction::eContextImmediate;
+            context.SetNoArgs ();
+        }
+
+        if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
+            return false;
+    }
+    return true;
+}
+
+// A store operation to the stack that also updates the SP.
+bool
+EmulateInstructionARM::EmulateSTRRtSP (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if (ConditionPassed())
+    {
+        EncodingSpecificOperations();
+        offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
+        address = if index then offset_addr else R[n];
+        MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
+        if wback then R[n] = offset_addr;
+    }
+#endif
+
+    bool conditional = false;
+    bool success = false;
+    if (ConditionPassed(opcode, &conditional))
+    {
+        const uint32_t addr_byte_size = GetAddressByteSize();
+        const addr_t sp = ReadCoreReg (SP_REG, &success);
+        if (!success)
+            return false;
+        uint32_t Rt; // the source register
+        uint32_t imm12;
+        uint32_t Rn;  // This function assumes Rn is the SP, but we should verify that.
+                  
+        bool index;
+        bool add;
+        bool wback;
+        switch (encoding) {
+        case eEncodingA1:
+            Rt = Bits32(opcode, 15, 12);
+            imm12 = Bits32(opcode, 11, 0);
+            Rn = Bits32 (opcode, 19, 16);
+                  
+            if (Rn != 13) // 13 is the SP reg on ARM.  Verify that Rn == SP.
+                return false;
+                  
+            index = BitIsSet (opcode, 24);
+            add = BitIsSet (opcode, 23);
+            wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
+                  
+            if (wback && ((Rn == 15) || (Rn == Rt)))
+                return false;
+            break;
+        default:
+            return false;
+        }
+        addr_t offset_addr;
+        if (add)
+            offset_addr = sp + imm12;
+        else
+            offset_addr = sp - imm12;
+                  
+        addr_t addr;
+        if (index)
+            addr = offset_addr;
+        else
+            addr = sp;
+        
+        EmulateInstruction::Context context;
+        if (conditional)
+            context.type = EmulateInstruction::eContextRegisterStore;
+        else
+            context.type = EmulateInstruction::eContextPushRegisterOnStack;
+        RegisterInfo sp_reg;
+        RegisterInfo dwarf_reg;
+
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rt, dwarf_reg);
+        context.SetRegisterToRegisterPlusOffset ( dwarf_reg, sp_reg, addr - sp);
+        if (Rt != 15)
+        {
+            uint32_t reg_value = ReadCoreReg(Rt, &success);
+            if (!success)
+                return false;
+            if (!MemUWrite (context, addr, reg_value, addr_byte_size))
+                return false;
+        }
+        else
+        {
+            const uint32_t pc = ReadCoreReg(PC_REG, &success);
+            if (!success)
+                return false;
+            if (!MemUWrite (context, addr, pc, addr_byte_size))
+                return false;
+        }
+        
+
+        if (wback)
+        {
+            context.type = EmulateInstruction::eContextAdjustStackPointer;
+            context.SetImmediateSigned (addr - sp);
+            if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, offset_addr))
+                return false;
+        }
+    }
+    return true;
+}
+
+// Vector Push stores multiple extension registers to the stack.
+// It also updates SP to point to the start of the stored data.
+bool 
+EmulateInstructionARM::EmulateVPUSH (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if (ConditionPassed())
+    {
+        EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
+        address = SP - imm32;
+        SP = SP - imm32;
+        if single_regs then
+            for r = 0 to regs-1
+                MemA[address,4] = S[d+r]; address = address+4;
+        else
+            for r = 0 to regs-1
+                // Store as two word-aligned words in the correct order for current endianness.
+                MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
+                MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
+                address = address+8;
+    }
+#endif
+
+    bool success = false;
+    bool conditional = false;
+    if (ConditionPassed(opcode, &conditional))
+    {
+        const uint32_t addr_byte_size = GetAddressByteSize();
+        const addr_t sp = ReadCoreReg (SP_REG, &success);
+        if (!success)
+            return false;
+        bool single_regs;
+        uint32_t d;     // UInt(D:Vd) or UInt(Vd:D) starting register
+        uint32_t imm32; // stack offset
+        uint32_t regs;  // number of registers
+        switch (encoding) {
+        case eEncodingT1:
+        case eEncodingA1:
+            single_regs = false;
+            d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
+            imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
+            // If UInt(imm8) is odd, see "FSTMX".
+            regs = Bits32(opcode, 7, 0) / 2;
+            // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
+            if (regs == 0 || regs > 16 || (d + regs) > 32)
+                return false;
+            break;
+        case eEncodingT2:
+        case eEncodingA2:
+            single_regs = true;
+            d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
+            imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
+            regs = Bits32(opcode, 7, 0);
+            // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
+            if (regs == 0 || regs > 16 || (d + regs) > 32)
+                return false;
+            break;
+        default:
+            return false;
+        }
+        uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
+        uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
+        addr_t sp_offset = imm32;
+        addr_t addr = sp - sp_offset;
+        uint32_t i;
+        
+        EmulateInstruction::Context context;
+        if (conditional)
+            context.type = EmulateInstruction::eContextRegisterStore;
+        else
+            context.type = EmulateInstruction::eContextPushRegisterOnStack;
+        RegisterInfo dwarf_reg;
+        RegisterInfo sp_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
+        for (i=0; i<regs; ++i)
+        {
+            GetRegisterInfo (eRegisterKindDWARF, start_reg + d + i, dwarf_reg);
+            context.SetRegisterToRegisterPlusOffset ( dwarf_reg, sp_reg, addr - sp);
+            // uint64_t to accommodate 64-bit registers.
+            uint64_t reg_value = ReadRegisterUnsigned (&dwarf_reg, 0, &success);
+            if (!success)
+                return false;
+            if (!MemAWrite (context, addr, reg_value, reg_byte_size))
+                return false;
+            addr += reg_byte_size;
+        }
+        
+        context.type = EmulateInstruction::eContextAdjustStackPointer;
+        context.SetImmediateSigned (-sp_offset);
+    
+        if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp - sp_offset))
+            return false;
+    }
+    return true;
+}
+
+// Vector Pop loads multiple extension registers from the stack.
+// It also updates SP to point just above the loaded data.
+bool 
+EmulateInstructionARM::EmulateVPOP (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if (ConditionPassed())
+    {
+        EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(13);
+        address = SP;
+        SP = SP + imm32;
+        if single_regs then
+            for r = 0 to regs-1
+                S[d+r] = MemA[address,4]; address = address+4;
+        else
+            for r = 0 to regs-1
+                word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
+                // Combine the word-aligned words in the correct order for current endianness.
+                D[d+r] = if BigEndian() then word1:word2 else word2:word1;
+    }
+#endif
+
+    bool success = false;
+    bool conditional = false;
+    if (ConditionPassed(opcode, &conditional))
+    {
+        const uint32_t addr_byte_size = GetAddressByteSize();
+        const addr_t sp = ReadCoreReg (SP_REG, &success);
+        if (!success)
+            return false;
+        bool single_regs;
+        uint32_t d;     // UInt(D:Vd) or UInt(Vd:D) starting register
+        uint32_t imm32; // stack offset
+        uint32_t regs;  // number of registers
+        switch (encoding) {
+        case eEncodingT1:
+        case eEncodingA1:
+            single_regs = false;
+            d = Bit32(opcode, 22) << 4 | Bits32(opcode, 15, 12);
+            imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
+            // If UInt(imm8) is odd, see "FLDMX".
+            regs = Bits32(opcode, 7, 0) / 2;
+            // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
+            if (regs == 0 || regs > 16 || (d + regs) > 32)
+                return false;
+            break;
+        case eEncodingT2:
+        case eEncodingA2:
+            single_regs = true;
+            d = Bits32(opcode, 15, 12) << 1 | Bit32(opcode, 22);
+            imm32 = Bits32(opcode, 7, 0) * addr_byte_size;
+            regs = Bits32(opcode, 7, 0);
+            // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
+            if (regs == 0 || regs > 16 || (d + regs) > 32)
+                return false;
+            break;
+        default:
+            return false;
+        }
+        uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
+        uint32_t reg_byte_size = single_regs ? addr_byte_size : addr_byte_size * 2;
+        addr_t sp_offset = imm32;
+        addr_t addr = sp;
+        uint32_t i;
+        uint64_t data; // uint64_t to accomodate 64-bit registers.
+        
+        EmulateInstruction::Context context;
+        if (conditional)
+            context.type = EmulateInstruction::eContextRegisterLoad;
+        else
+            context.type = EmulateInstruction::eContextPopRegisterOffStack;
+        RegisterInfo dwarf_reg;
+        RegisterInfo sp_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
+        for (i=0; i<regs; ++i)
+        {
+            GetRegisterInfo (eRegisterKindDWARF, start_reg + d + i, dwarf_reg);
+            context.SetRegisterPlusOffset (sp_reg, addr - sp);
+            data = MemARead(context, addr, reg_byte_size, 0, &success);
+            if (!success)
+                return false;    
+            if (!WriteRegisterUnsigned(context, &dwarf_reg, data))
+                return false;
+            addr += reg_byte_size;
+        }
+        
+        context.type = EmulateInstruction::eContextAdjustStackPointer;
+        context.SetImmediateSigned (sp_offset);
+    
+        if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, sp + sp_offset))
+            return false;
+    }
+    return true;
+}
+
+// SVC (previously SWI)
+bool
+EmulateInstructionARM::EmulateSVC (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if (ConditionPassed())
+    {
+        EncodingSpecificOperations();
+        CallSupervisor();
+    }
+#endif
+
+    bool success = false;
+
+    if (ConditionPassed(opcode))
+    {
+        const uint32_t pc = ReadCoreReg(PC_REG, &success);
+        addr_t lr; // next instruction address
+        if (!success)
+            return false;
+        uint32_t imm32; // the immediate constant
+        uint32_t mode;  // ARM or Thumb mode
+        switch (encoding) {
+        case eEncodingT1:
+            lr = (pc + 2) | 1u; // return address
+            imm32 = Bits32(opcode, 7, 0);
+            mode = eModeThumb;
+            break;
+        case eEncodingA1:
+            lr = pc + 4; // return address
+            imm32 = Bits32(opcode, 23, 0);
+            mode = eModeARM;
+            break;
+        default:
+            return false;
+        }
+                  
+        EmulateInstruction::Context context;
+        context.type = EmulateInstruction::eContextSupervisorCall;
+        context.SetISAAndImmediate (mode, imm32);
+        if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, lr))
+            return false;
+    }
+    return true;
+}
+
+// If Then makes up to four following instructions (the IT block) conditional.
+bool
+EmulateInstructionARM::EmulateIT (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    EncodingSpecificOperations();
+    ITSTATE.IT<7:0> = firstcond:mask;
+#endif
+
+    m_it_session.InitIT(Bits32(opcode, 7, 0));
+    return true;
+}
+
+bool
+EmulateInstructionARM::EmulateNop (const uint32_t opcode, const ARMEncoding encoding)
+{
+    // NOP, nothing to do...
+    return true;
+}
+
+// Branch causes a branch to a target address.
+bool
+EmulateInstructionARM::EmulateB (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if (ConditionPassed())
+    {
+        EncodingSpecificOperations();
+        BranchWritePC(PC + imm32);
+    }
+#endif
+
+    bool success = false;
+
+    if (ConditionPassed(opcode))
+    {
+        EmulateInstruction::Context context;
+        context.type = EmulateInstruction::eContextRelativeBranchImmediate;
+        const uint32_t pc = ReadCoreReg(PC_REG, &success);
+        if (!success)
+            return false;
+        addr_t target; // target address
+        int32_t imm32; // PC-relative offset
+        switch (encoding) {
+        case eEncodingT1:
+            // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
+            imm32 = llvm::SignExtend32<9>(Bits32(opcode, 7, 0) << 1);
+            target = pc + imm32;
+            context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
+            break;
+        case eEncodingT2:
+            imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0));
+            target = pc + imm32;
+            context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
+            break;
+        case eEncodingT3:
+            // The 'cond' field is handled in EmulateInstructionARM::CurrentCond().
+            {
+            uint32_t S = Bit32(opcode, 26);
+            uint32_t imm6 = Bits32(opcode, 21, 16);
+            uint32_t J1 = Bit32(opcode, 13);
+            uint32_t J2 = Bit32(opcode, 11);
+            uint32_t imm11 = Bits32(opcode, 10, 0);
+            uint32_t imm21 = (S << 20) | (J2 << 19) | (J1 << 18) | (imm6 << 12) | (imm11 << 1);
+            imm32 = llvm::SignExtend32<21>(imm21);
+            target = pc + imm32;
+            context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
+            break;
+            }
+        case eEncodingT4:
+            {
+            uint32_t S = Bit32(opcode, 26);
+            uint32_t imm10 = Bits32(opcode, 25, 16);
+            uint32_t J1 = Bit32(opcode, 13);
+            uint32_t J2 = Bit32(opcode, 11);
+            uint32_t imm11 = Bits32(opcode, 10, 0);
+            uint32_t I1 = !(J1 ^ S);
+            uint32_t I2 = !(J2 ^ S);
+            uint32_t imm25 = (S << 24) | (I1 << 23) | (I2 << 22) | (imm10 << 12) | (imm11 << 1);
+            imm32 = llvm::SignExtend32<25>(imm25);
+            target = pc + imm32;
+            context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
+            break;
+            }
+        case eEncodingA1:
+            imm32 = llvm::SignExtend32<26>(Bits32(opcode, 23, 0) << 2);
+            target = pc + imm32;
+            context.SetISAAndImmediateSigned (eModeARM, 8 + imm32);
+            break;
+        default:
+            return false;
+        }
+        if (!BranchWritePC(context, target))
+            return false;
+    }
+    return true;
+}
+
+// Compare and Branch on Nonzero and Compare and Branch on Zero compare the value in a register with
+// zero and conditionally branch forward a constant value.  They do not affect the condition flags.
+// CBNZ, CBZ
+bool
+EmulateInstructionARM::EmulateCB (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    EncodingSpecificOperations();
+    if nonzero ^ IsZero(R[n]) then
+        BranchWritePC(PC + imm32);
+#endif
+
+    bool success = false;
+
+    // Read the register value from the operand register Rn.
+    uint32_t reg_val = ReadCoreReg(Bits32(opcode, 2, 0), &success);
+    if (!success)
+        return false;
+                  
+    EmulateInstruction::Context context;
+    context.type = EmulateInstruction::eContextRelativeBranchImmediate;
+    const uint32_t pc = ReadCoreReg(PC_REG, &success);
+    if (!success)
+        return false;
+
+    addr_t target;  // target address
+    uint32_t imm32; // PC-relative offset to branch forward
+    bool nonzero;
+    switch (encoding) {
+    case eEncodingT1:
+        imm32 = Bit32(opcode, 9) << 6 | Bits32(opcode, 7, 3) << 1;
+        nonzero = BitIsSet(opcode, 11);
+        target = pc + imm32;
+        context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32);
+        break;
+    default:
+        return false;
+    }
+    if (nonzero ^ (reg_val == 0))
+        if (!BranchWritePC(context, target))
+            return false;
+
+    return true;
+}
+
+// Table Branch Byte causes a PC-relative forward branch using a table of single byte offsets.
+// A base register provides a pointer to the table, and a second register supplies an index into the table.
+// The branch length is twice the value of the byte returned from the table.
+//
+// Table Branch Halfword causes a PC-relative forward branch using a table of single halfword offsets.
+// A base register provides a pointer to the table, and a second register supplies an index into the table.
+// The branch length is twice the value of the halfword returned from the table.
+// TBB, TBH
+bool
+EmulateInstructionARM::EmulateTB (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    EncodingSpecificOperations(); NullCheckIfThumbEE(n);
+    if is_tbh then
+        halfwords = UInt(MemU[R[n]+LSL(R[m],1), 2]);
+    else
+        halfwords = UInt(MemU[R[n]+R[m], 1]);
+    BranchWritePC(PC + 2*halfwords);
+#endif
+
+    bool success = false;
+
+    uint32_t Rn;     // the base register which contains the address of the table of branch lengths
+    uint32_t Rm;     // the index register which contains an integer pointing to a byte/halfword in the table
+    bool is_tbh;     // true if table branch halfword
+    switch (encoding) {
+    case eEncodingT1:
+        Rn = Bits32(opcode, 19, 16);
+        Rm = Bits32(opcode, 3, 0);
+        is_tbh = BitIsSet(opcode, 4);
+        if (Rn == 13 || BadReg(Rm))
+            return false;
+        if (InITBlock() && !LastInITBlock())
+            return false;
+        break;
+    default:
+        return false;
+    }
+
+    // Read the address of the table from the operand register Rn.
+    // The PC can be used, in which case the table immediately follows this instruction.
+    uint32_t base = ReadCoreReg(Rm, &success);
+    if (!success)
+        return false;
+
+    // the table index
+    uint32_t index = ReadCoreReg(Rm, &success);
+    if (!success)
+        return false;
+
+    // the offsetted table address
+    addr_t addr = base + (is_tbh ? index*2 : index);
+
+    // PC-relative offset to branch forward
+    EmulateInstruction::Context context;
+    context.type = EmulateInstruction::eContextTableBranchReadMemory;
+    uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2;
+    if (!success)
+        return false;
+
+    const uint32_t pc = ReadCoreReg(PC_REG, &success);
+    if (!success)
+        return false;
+
+    // target address
+    addr_t target = pc + offset;
+    context.type = EmulateInstruction::eContextRelativeBranchImmediate;
+    context.SetISAAndImmediateSigned (eModeThumb, 4 + offset);
+
+    if (!BranchWritePC(context, target))
+        return false;
+
+    return true;
+}
+
+// This instruction adds an immediate value to a register value, and writes the result to the destination register.  
+// It can optionally update the condition flags based on the result.
+bool
+EmulateInstructionARM::EmulateADDImmThumb (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    if ConditionPassed() then 
+        EncodingSpecificOperations(); 
+        (result, carry, overflow) = AddWithCarry(R[n], imm32, '0'); 
+        R[d] = result; 
+        if setflags then
+            APSR.N = result<31>;  
+            APSR.Z = IsZeroBit(result); 
+            APSR.C = carry;  
+            APSR.V = overflow;
+#endif
+                  
+    bool success = false;
+                  
+    if (ConditionPassed(opcode))
+    {
+        uint32_t d;
+        uint32_t n;
+        bool setflags;
+        uint32_t imm32;
+        uint32_t carry_out;
+        
+        //EncodingSpecificOperations(); 
+        switch (encoding)
+        {
+            case eEncodingT1:
+                // d = UInt(Rd); n = UInt(Rn); setflags = !InITBlock(); imm32 = ZeroExtend(imm3, 32);
+                d = Bits32 (opcode, 2, 0);
+                n = Bits32 (opcode, 5, 3);
+                setflags = !InITBlock();
+                imm32 = Bits32 (opcode, 8,6);
+                
+                break;
+                
+            case eEncodingT2:
+                // d = UInt(Rdn); n = UInt(Rdn); setflags = !InITBlock(); imm32 = ZeroExtend(imm8, 32);
+                d = Bits32 (opcode, 10, 8);
+                n = Bits32 (opcode, 10, 8);
+                setflags = !InITBlock();
+                imm32 = Bits32 (opcode, 7, 0);
+                
+                break;
+                
+            case eEncodingT3:
+                // if Rd == '1111' && S == '1' then SEE CMN (immediate); 
+                // if Rn == '1101' then SEE ADD (SP plus immediate); 
+                // d = UInt(Rd); n = UInt(Rn); setflags = (S == '1'); imm32 = ThumbExpandImm(i:imm3:imm8); 
+                d = Bits32 (opcode, 11, 8);
+                n = Bits32 (opcode, 19, 16);
+                setflags = BitIsSet (opcode, 20);
+                imm32 = ThumbExpandImm_C (opcode, APSR_C, carry_out);
+                
+                // if BadReg(d) || n == 15 then UNPREDICTABLE;
+                if (BadReg (d) || (n == 15))
+                    return false;
+                
+                break;
+                
+            case eEncodingT4:
+            {
+                // if Rn == '1111' then SEE ADR; 
+                // if Rn == '1101' then SEE ADD (SP plus immediate); 
+                // d = UInt(Rd); n = UInt(Rn); setflags = FALSE; imm32 = ZeroExtend(i:imm3:imm8, 32); 
+                d = Bits32 (opcode, 11, 8);
+                n = Bits32 (opcode, 19, 16);
+                setflags = false;
+                uint32_t i = Bit32 (opcode, 26);
+                uint32_t imm3 = Bits32 (opcode, 14, 12);
+                uint32_t imm8 = Bits32 (opcode, 7, 0);
+                imm32 = (i << 11) | (imm3 << 8) | imm8;
+                
+                // if BadReg(d) then UNPREDICTABLE;
+                if (BadReg (d))
+                    return false;
+                    
+                break;
+            }   
+            default:
+                return false;
+        }
+        
+        uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
+        if (!success)
+            return false;
+        
+        //(result, carry, overflow) = AddWithCarry(R[n], imm32, '0'); 
+        AddWithCarryResult res = AddWithCarry (Rn, imm32, 0);
+        
+        RegisterInfo reg_n;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, reg_n);
+        
+        EmulateInstruction::Context context;
+        context.type = eContextArithmetic;
+        context.SetRegisterPlusOffset (reg_n, imm32);
+        
+        //R[d] = result; 
+        //if setflags then
+            //APSR.N = result<31>;  
+            //APSR.Z = IsZeroBit(result); 
+            //APSR.C = carry;  
+            //APSR.V = overflow;
+        if (!WriteCoreRegOptionalFlags (context, res.result, d, setflags, res.carry_out, res.overflow))
+            return false;
+        
+    }
+    return true;
+}
+                  
+// This instruction adds an immediate value to a register value, and writes the result to the destination
+// register.  It can optionally update the condition flags based on the result.
+bool
+EmulateInstructionARM::EmulateADDImmARM (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if ConditionPassed() then
+        EncodingSpecificOperations();
+        (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
+        if d == 15 then
+            ALUWritePC(result); // setflags is always FALSE here
+        else
+            R[d] = result;
+            if setflags then
+                APSR.N = result<31>;
+                APSR.Z = IsZeroBit(result);
+                APSR.C = carry;
+                APSR.V = overflow;
+#endif
+
+    bool success = false;
+
+    if (ConditionPassed(opcode))
+    {
+        uint32_t Rd, Rn;
+        uint32_t imm32; // the immediate value to be added to the value obtained from Rn
+        bool setflags;
+        switch (encoding)
+        {
+        case eEncodingA1:
+            Rd = Bits32(opcode, 15, 12);
+            Rn = Bits32(opcode, 19, 16);
+            setflags = BitIsSet(opcode, 20);
+            imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
+            break;
+        default:
+            return false;
+        }
+
+        // Read the first operand.
+        uint32_t val1 = ReadCoreReg(Rn, &success);
+        if (!success)
+            return false;
+
+        AddWithCarryResult res = AddWithCarry(val1, imm32, 0);
+
+        EmulateInstruction::Context context;
+        context.type = eContextArithmetic;
+        RegisterInfo dwarf_reg;
+        GetRegisterInfo (eRegisterKindDWARF, Rn, dwarf_reg);
+        context.SetRegisterPlusOffset (dwarf_reg, imm32);
+
+        if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
+            return false;
+    }
+    return true;
+}
+
+// This instruction adds a register value and an optionally-shifted register value, and writes the result
+// to the destination register. It can optionally update the condition flags based on the result.
+bool
+EmulateInstructionARM::EmulateADDReg (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if ConditionPassed() then
+        EncodingSpecificOperations();
+        shifted = Shift(R[m], shift_t, shift_n, APSR.C);
+        (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
+        if d == 15 then
+            ALUWritePC(result); // setflags is always FALSE here
+        else
+            R[d] = result;
+            if setflags then
+                APSR.N = result<31>;
+                APSR.Z = IsZeroBit(result);
+                APSR.C = carry;
+                APSR.V = overflow;
+#endif
+
+    bool success = false;
+
+    if (ConditionPassed(opcode))
+    {
+        uint32_t Rd, Rn, Rm;
+        ARM_ShifterType shift_t;
+        uint32_t shift_n; // the shift applied to the value read from Rm
+        bool setflags;
+        switch (encoding)
+        {
+        case eEncodingT1:
+            Rd = Bits32(opcode, 2, 0);
+            Rn = Bits32(opcode, 5, 3);
+            Rm = Bits32(opcode, 8, 6);
+            setflags = !InITBlock();
+            shift_t = SRType_LSL;
+            shift_n = 0;
+            break;
+        case eEncodingT2:
+            Rd = Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
+            Rm = Bits32(opcode, 6, 3);
+            setflags = false;
+            shift_t = SRType_LSL;
+            shift_n = 0;
+            if (Rn == 15 && Rm == 15)
+                return false;
+            if (Rd == 15 && InITBlock() && !LastInITBlock())
+                return false;
+            break;
+        case eEncodingA1:
+            Rd = Bits32(opcode, 15, 12);
+            Rn = Bits32(opcode, 19, 16);
+            Rm = Bits32(opcode, 3, 0);
+            setflags = BitIsSet(opcode, 20);
+            shift_n = DecodeImmShiftARM(opcode, shift_t);
+            break;
+        default:
+            return false;
+        }
+
+        // Read the first operand.
+        uint32_t val1 = ReadCoreReg(Rn, &success);
+        if (!success)
+            return false;
+
+        // Read the second operand.
+        uint32_t val2 = ReadCoreReg(Rm, &success);
+        if (!success)
+            return false;
+
+        uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
+        if (!success)
+            return false;
+        AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
+
+        EmulateInstruction::Context context;
+        context.type = eContextArithmetic;
+        RegisterInfo op1_reg;
+        RegisterInfo op2_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rn, op1_reg);
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rm, op2_reg);
+        context.SetRegisterRegisterOperands (op1_reg, op2_reg);
+
+        if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
+            return false;
+    }
+    return true;
+}
+
+// Compare Negative (immediate) adds a register value and an immediate value.
+// It updates the condition flags based on the result, and discards the result.
+bool
+EmulateInstructionARM::EmulateCMNImm (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if ConditionPassed() then
+        EncodingSpecificOperations();
+        (result, carry, overflow) = AddWithCarry(R[n], imm32, '0');
+        APSR.N = result<31>;
+        APSR.Z = IsZeroBit(result);
+        APSR.C = carry;
+        APSR.V = overflow;
+#endif
+
+    bool success = false;
+
+    uint32_t Rn; // the first operand
+    uint32_t imm32; // the immediate value to be compared with
+    switch (encoding) {
+    case eEncodingT1:
+        Rn = Bits32(opcode, 19, 16);
+        imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
+        if (Rn == 15)
+            return false;
+        break;
+    case eEncodingA1:
+        Rn = Bits32(opcode, 19, 16);
+        imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
+        break;
+    default:
+        return false;
+    }
+    // Read the register value from the operand register Rn.
+    uint32_t reg_val = ReadCoreReg(Rn, &success);
+    if (!success)
+        return false;
+                  
+    AddWithCarryResult res = AddWithCarry(reg_val, imm32, 0);
+
+    EmulateInstruction::Context context;
+    context.type = EmulateInstruction::eContextImmediate;
+    context.SetNoArgs ();
+    if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
+        return false;
+
+    return true;
+}
+
+// Compare Negative (register) adds a register value and an optionally-shifted register value.
+// It updates the condition flags based on the result, and discards the result.
+bool
+EmulateInstructionARM::EmulateCMNReg (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if ConditionPassed() then
+        EncodingSpecificOperations();
+        shifted = Shift(R[m], shift_t, shift_n, APSR.C);
+        (result, carry, overflow) = AddWithCarry(R[n], shifted, '0');
+        APSR.N = result<31>;
+        APSR.Z = IsZeroBit(result);
+        APSR.C = carry;
+        APSR.V = overflow;
+#endif
+
+    bool success = false;
+
+    uint32_t Rn; // the first operand
+    uint32_t Rm; // the second operand
+    ARM_ShifterType shift_t;
+    uint32_t shift_n; // the shift applied to the value read from Rm
+    switch (encoding) {
+    case eEncodingT1:
+        Rn = Bits32(opcode, 2, 0);
+        Rm = Bits32(opcode, 5, 3);
+        shift_t = SRType_LSL;
+        shift_n = 0;
+        break;
+    case eEncodingT2:
+        Rn = Bits32(opcode, 19, 16);
+        Rm = Bits32(opcode, 3, 0);
+        shift_n = DecodeImmShiftThumb(opcode, shift_t);
+        // if n == 15 || BadReg(m) then UNPREDICTABLE;
+        if (Rn == 15 || BadReg(Rm))
+            return false;
+        break;
+    case eEncodingA1:
+        Rn = Bits32(opcode, 19, 16);
+        Rm = Bits32(opcode, 3, 0);
+        shift_n = DecodeImmShiftARM(opcode, shift_t);
+        break;
+    default:
+        return false;
+    }
+    // Read the register value from register Rn.
+    uint32_t val1 = ReadCoreReg(Rn, &success);
+    if (!success)
+        return false;
+
+    // Read the register value from register Rm.
+    uint32_t val2 = ReadCoreReg(Rm, &success);
+    if (!success)
+        return false;
+                  
+    uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
+    if (!success)
+        return false;
+    AddWithCarryResult res = AddWithCarry(val1, shifted, 0);
+
+    EmulateInstruction::Context context;
+    context.type = EmulateInstruction::eContextImmediate;
+    context.SetNoArgs();
+    if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
+        return false;
+
+    return true;
+}
+
+// Compare (immediate) subtracts an immediate value from a register value.
+// It updates the condition flags based on the result, and discards the result.
+bool
+EmulateInstructionARM::EmulateCMPImm (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if ConditionPassed() then
+        EncodingSpecificOperations();
+        (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
+        APSR.N = result<31>;
+        APSR.Z = IsZeroBit(result);
+        APSR.C = carry;
+        APSR.V = overflow;
+#endif
+
+    bool success = false;
+
+    uint32_t Rn; // the first operand
+    uint32_t imm32; // the immediate value to be compared with
+    switch (encoding) {
+    case eEncodingT1:
+        Rn = Bits32(opcode, 10, 8);
+        imm32 = Bits32(opcode, 7, 0);
+        break;
+    case eEncodingT2:
+        Rn = Bits32(opcode, 19, 16);
+        imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
+        if (Rn == 15)
+            return false;
+        break;
+    case eEncodingA1:
+        Rn = Bits32(opcode, 19, 16);
+        imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
+        break;
+    default:
+        return false;
+    }
+    // Read the register value from the operand register Rn.
+    uint32_t reg_val = ReadCoreReg(Rn, &success);
+    if (!success)
+        return false;
+                  
+    AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
+
+    EmulateInstruction::Context context;
+    context.type = EmulateInstruction::eContextImmediate;
+    context.SetNoArgs ();
+    if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
+        return false;
+
+    return true;
+}
+
+// Compare (register) subtracts an optionally-shifted register value from a register value.
+// It updates the condition flags based on the result, and discards the result.
+bool
+EmulateInstructionARM::EmulateCMPReg (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if ConditionPassed() then
+        EncodingSpecificOperations();
+        shifted = Shift(R[m], shift_t, shift_n, APSR.C);
+        (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), '1');
+        APSR.N = result<31>;
+        APSR.Z = IsZeroBit(result);
+        APSR.C = carry;
+        APSR.V = overflow;
+#endif
+
+    bool success = false;
+
+    uint32_t Rn; // the first operand
+    uint32_t Rm; // the second operand
+    ARM_ShifterType shift_t;
+    uint32_t shift_n; // the shift applied to the value read from Rm
+    switch (encoding) {
+    case eEncodingT1:
+        Rn = Bits32(opcode, 2, 0);
+        Rm = Bits32(opcode, 5, 3);
+        shift_t = SRType_LSL;
+        shift_n = 0;
+        break;
+    case eEncodingT2:
+        Rn = Bit32(opcode, 7) << 3 | Bits32(opcode, 2, 0);
+        Rm = Bits32(opcode, 6, 3);
+        shift_t = SRType_LSL;
+        shift_n = 0;
+        if (Rn < 8 && Rm < 8)
+            return false;
+        if (Rn == 15 || Rm == 15)
+            return false;
+        break;
+    case eEncodingA1:
+        Rn = Bits32(opcode, 19, 16);
+        Rm = Bits32(opcode, 3, 0);
+        shift_n = DecodeImmShiftARM(opcode, shift_t);
+        break;
+    default:
+        return false;
+    }
+    // Read the register value from register Rn.
+    uint32_t val1 = ReadCoreReg(Rn, &success);
+    if (!success)
+        return false;
+
+    // Read the register value from register Rm.
+    uint32_t val2 = ReadCoreReg(Rm, &success);
+    if (!success)
+        return false;
+                  
+    uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
+    if (!success)
+        return false;
+    AddWithCarryResult res = AddWithCarry(val1, ~shifted, 1);
+
+    EmulateInstruction::Context context;
+    context.type = EmulateInstruction::eContextImmediate;
+    context.SetNoArgs();
+    if (!WriteFlags(context, res.result, res.carry_out, res.overflow))
+        return false;
+
+    return true;
+}
+
+// Arithmetic Shift Right (immediate) shifts a register value right by an immediate number of bits,
+// shifting in copies of its sign bit, and writes the result to the destination register.  It can
+// optionally update the condition flags based on the result.
+bool
+EmulateInstructionARM::EmulateASRImm (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if ConditionPassed() then
+        EncodingSpecificOperations();
+        (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
+        if d == 15 then         // Can only occur for ARM encoding
+            ALUWritePC(result); // setflags is always FALSE here
+        else
+            R[d] = result;
+            if setflags then
+                APSR.N = result<31>;
+                APSR.Z = IsZeroBit(result);
+                APSR.C = carry;
+                // APSR.V unchanged
+#endif
+
+    return EmulateShiftImm (opcode, encoding, SRType_ASR);
+}
+
+// Arithmetic Shift Right (register) shifts a register value right by a variable number of bits,
+// shifting in copies of its sign bit, and writes the result to the destination register.
+// The variable number of bits is read from the bottom byte of a register. It can optionally update
+// the condition flags based on the result.
+bool
+EmulateInstructionARM::EmulateASRReg (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if ConditionPassed() then
+        EncodingSpecificOperations();
+        shift_n = UInt(R[m]<7:0>);
+        (result, carry) = Shift_C(R[m], SRType_ASR, shift_n, APSR.C);
+        R[d] = result;
+        if setflags then
+            APSR.N = result<31>;
+            APSR.Z = IsZeroBit(result);
+            APSR.C = carry;
+            // APSR.V unchanged
+#endif
+
+    return EmulateShiftReg (opcode, encoding, SRType_ASR);
+}
+
+// Logical Shift Left (immediate) shifts a register value left by an immediate number of bits,
+// shifting in zeros, and writes the result to the destination register.  It can optionally
+// update the condition flags based on the result.
+bool
+EmulateInstructionARM::EmulateLSLImm (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if ConditionPassed() then
+        EncodingSpecificOperations();
+        (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
+        if d == 15 then         // Can only occur for ARM encoding
+            ALUWritePC(result); // setflags is always FALSE here
+        else
+            R[d] = result;
+            if setflags then
+                APSR.N = result<31>;
+                APSR.Z = IsZeroBit(result);
+                APSR.C = carry;
+                // APSR.V unchanged
+#endif
+
+    return EmulateShiftImm (opcode, encoding, SRType_LSL);
+}
+
+// Logical Shift Left (register) shifts a register value left by a variable number of bits,
+// shifting in zeros, and writes the result to the destination register.  The variable number
+// of bits is read from the bottom byte of a register. It can optionally update the condition
+// flags based on the result.
+bool
+EmulateInstructionARM::EmulateLSLReg (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if ConditionPassed() then
+        EncodingSpecificOperations();
+        shift_n = UInt(R[m]<7:0>);
+        (result, carry) = Shift_C(R[m], SRType_LSL, shift_n, APSR.C);
+        R[d] = result;
+        if setflags then
+            APSR.N = result<31>;
+            APSR.Z = IsZeroBit(result);
+            APSR.C = carry;
+            // APSR.V unchanged
+#endif
+
+    return EmulateShiftReg (opcode, encoding, SRType_LSL);
+}
+
+// Logical Shift Right (immediate) shifts a register value right by an immediate number of bits,
+// shifting in zeros, and writes the result to the destination register.  It can optionally
+// update the condition flags based on the result.
+bool
+EmulateInstructionARM::EmulateLSRImm (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if ConditionPassed() then
+        EncodingSpecificOperations();
+        (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
+        if d == 15 then         // Can only occur for ARM encoding
+            ALUWritePC(result); // setflags is always FALSE here
+        else
+            R[d] = result;
+            if setflags then
+                APSR.N = result<31>;
+                APSR.Z = IsZeroBit(result);
+                APSR.C = carry;
+                // APSR.V unchanged
+#endif
+
+    return EmulateShiftImm (opcode, encoding, SRType_LSR);
+}
+
+// Logical Shift Right (register) shifts a register value right by a variable number of bits,
+// shifting in zeros, and writes the result to the destination register.  The variable number
+// of bits is read from the bottom byte of a register. It can optionally update the condition
+// flags based on the result.
+bool
+EmulateInstructionARM::EmulateLSRReg (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if ConditionPassed() then
+        EncodingSpecificOperations();
+        shift_n = UInt(R[m]<7:0>);
+        (result, carry) = Shift_C(R[m], SRType_LSR, shift_n, APSR.C);
+        R[d] = result;
+        if setflags then
+            APSR.N = result<31>;
+            APSR.Z = IsZeroBit(result);
+            APSR.C = carry;
+            // APSR.V unchanged
+#endif
+
+    return EmulateShiftReg (opcode, encoding, SRType_LSR);
+}
+
+// Rotate Right (immediate) provides the value of the contents of a register rotated by a constant value.
+// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
+// It can optionally update the condition flags based on the result.
+bool
+EmulateInstructionARM::EmulateRORImm (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if ConditionPassed() then
+        EncodingSpecificOperations();
+        (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
+        if d == 15 then         // Can only occur for ARM encoding
+            ALUWritePC(result); // setflags is always FALSE here
+        else
+            R[d] = result;
+            if setflags then
+                APSR.N = result<31>;
+                APSR.Z = IsZeroBit(result);
+                APSR.C = carry;
+                // APSR.V unchanged
+#endif
+
+    return EmulateShiftImm (opcode, encoding, SRType_ROR);
+}
+
+// Rotate Right (register) provides the value of the contents of a register rotated by a variable number of bits.
+// The bits that are rotated off the right end are inserted into the vacated bit positions on the left.
+// The variable number of bits is read from the bottom byte of a register. It can optionally update the condition
+// flags based on the result.
+bool
+EmulateInstructionARM::EmulateRORReg (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if ConditionPassed() then
+        EncodingSpecificOperations();
+        shift_n = UInt(R[m]<7:0>);
+        (result, carry) = Shift_C(R[m], SRType_ROR, shift_n, APSR.C);
+        R[d] = result;
+        if setflags then
+            APSR.N = result<31>;
+            APSR.Z = IsZeroBit(result);
+            APSR.C = carry;
+            // APSR.V unchanged
+#endif
+
+    return EmulateShiftReg (opcode, encoding, SRType_ROR);
+}
+
+// Rotate Right with Extend provides the value of the contents of a register shifted right by one place,
+// with the carry flag shifted into bit [31].
+//
+// RRX can optionally update the condition flags based on the result.
+// In that case, bit [0] is shifted into the carry flag.
+bool
+EmulateInstructionARM::EmulateRRX (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if ConditionPassed() then
+        EncodingSpecificOperations();
+        (result, carry) = Shift_C(R[m], SRType_RRX, 1, APSR.C);
+        if d == 15 then         // Can only occur for ARM encoding
+            ALUWritePC(result); // setflags is always FALSE here
+        else
+            R[d] = result;
+            if setflags then
+                APSR.N = result<31>;
+                APSR.Z = IsZeroBit(result);
+                APSR.C = carry;
+                // APSR.V unchanged
+#endif
+
+    return EmulateShiftImm (opcode, encoding, SRType_RRX);
+}
+
+bool
+EmulateInstructionARM::EmulateShiftImm (const uint32_t opcode, const ARMEncoding encoding, ARM_ShifterType shift_type)
+{
+//    assert(shift_type == SRType_ASR 
+//           || shift_type == SRType_LSL 
+//           || shift_type == SRType_LSR 
+//           || shift_type == SRType_ROR
+//           || shift_type == SRType_RRX);
+
+    bool success = false;
+
+    if (ConditionPassed(opcode))
+    {
+        uint32_t Rd;    // the destination register
+        uint32_t Rm;    // the first operand register
+        uint32_t imm5;  // encoding for the shift amount
+        uint32_t carry; // the carry bit after the shift operation
+        bool setflags;
+
+        // Special case handling!
+        // A8.6.139 ROR (immediate) -- Encoding T1
+        ARMEncoding use_encoding = encoding;
+        if (shift_type == SRType_ROR && use_encoding == eEncodingT1)
+        {
+            // Morph the T1 encoding from the ARM Architecture Manual into T2 encoding to
+            // have the same decoding of bit fields as the other Thumb2 shift operations.
+            use_encoding = eEncodingT2;
+        }
+
+        switch (use_encoding) {
+        case eEncodingT1:
+            // Due to the above special case handling!
+            if (shift_type == SRType_ROR)
+                return false;
+
+            Rd = Bits32(opcode, 2, 0);
+            Rm = Bits32(opcode, 5, 3);
+            setflags = !InITBlock();
+            imm5 = Bits32(opcode, 10, 6);
+            break;
+        case eEncodingT2:
+            // A8.6.141 RRX
+            // There's no imm form of RRX instructions.
+            if (shift_type == SRType_RRX)
+                return false;
+
+            Rd = Bits32(opcode, 11, 8);
+            Rm = Bits32(opcode, 3, 0);
+            setflags = BitIsSet(opcode, 20);
+            imm5 = Bits32(opcode, 14, 12) << 2 | Bits32(opcode, 7, 6);
+            if (BadReg(Rd) || BadReg(Rm))
+                return false;
+            break;
+        case eEncodingA1:
+            Rd = Bits32(opcode, 15, 12);
+            Rm = Bits32(opcode, 3, 0);
+            setflags = BitIsSet(opcode, 20);
+            imm5 = Bits32(opcode, 11, 7);
+            break;
+        default:
+            return false;
+        }
+
+        // A8.6.139 ROR (immediate)
+        if (shift_type == SRType_ROR && imm5 == 0)
+            shift_type = SRType_RRX;
+
+        // Get the first operand.
+        uint32_t value = ReadCoreReg (Rm, &success);
+        if (!success)
+            return false;
+
+        // Decode the shift amount if not RRX.
+        uint32_t amt = (shift_type == SRType_RRX ? 1 : DecodeImmShift(shift_type, imm5));
+
+        uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry, &success);
+        if (!success)
+            return false;
+
+        // The context specifies that an immediate is to be moved into Rd.
+        EmulateInstruction::Context context;
+        context.type = EmulateInstruction::eContextImmediate;
+        context.SetNoArgs ();
+     
+        if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
+            return false;
+    }
+    return true;
+}
+
+bool
+EmulateInstructionARM::EmulateShiftReg (const uint32_t opcode, const ARMEncoding encoding, ARM_ShifterType shift_type)
+{
+    // assert(shift_type == SRType_ASR
+    //        || shift_type == SRType_LSL
+    //        || shift_type == SRType_LSR
+    //        || shift_type == SRType_ROR);
+
+    bool success = false;
+
+    if (ConditionPassed(opcode))
+    {
+        uint32_t Rd;    // the destination register
+        uint32_t Rn;    // the first operand register
+        uint32_t Rm;    // the register whose bottom byte contains the amount to shift by
+        uint32_t carry; // the carry bit after the shift operation
+        bool setflags;
+        switch (encoding) {
+        case eEncodingT1:
+            Rd = Bits32(opcode, 2, 0);
+            Rn = Rd;
+            Rm = Bits32(opcode, 5, 3);
+            setflags = !InITBlock();
+            break;
+        case eEncodingT2:
+            Rd = Bits32(opcode, 11, 8);
+            Rn = Bits32(opcode, 19, 16);
+            Rm = Bits32(opcode, 3, 0);
+            setflags = BitIsSet(opcode, 20);
+            if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
+                return false;
+            break;
+        case eEncodingA1:
+            Rd = Bits32(opcode, 15, 12);
+            Rn = Bits32(opcode, 3, 0);
+            Rm = Bits32(opcode, 11, 8);
+            setflags = BitIsSet(opcode, 20);
+            if (Rd == 15 || Rn == 15 || Rm == 15)
+                return false;
+            break;
+        default:
+            return false;
+        }
+
+        // Get the first operand.
+        uint32_t value = ReadCoreReg (Rn, &success);
+        if (!success)
+            return false;
+        // Get the Rm register content.
+        uint32_t val = ReadCoreReg (Rm, &success);
+        if (!success)
+            return false;
+
+        // Get the shift amount.
+        uint32_t amt = Bits32(val, 7, 0);
+
+        uint32_t result = Shift_C(value, shift_type, amt, APSR_C, carry, &success);
+        if (!success)
+            return false;
+
+        // The context specifies that an immediate is to be moved into Rd.
+        EmulateInstruction::Context context;
+        context.type = EmulateInstruction::eContextImmediate;
+        context.SetNoArgs ();
+     
+        if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
+            return false;
+    }
+    return true;
+}
+
+// LDM loads multiple registers from consecutive memory locations, using an
+// address from a base register.  Optionally the address just above the highest of those locations
+// can be written back to the base register.
+bool
+EmulateInstructionARM::EmulateLDM (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if ConditionPassed()
+        EncodingSpecificOperations(); NullCheckIfThumbEE (n);
+        address = R[n];
+                  
+        for i = 0 to 14
+            if registers<i> == '1' then
+                R[i] = MemA[address, 4]; address = address + 4;
+        if registers<15> == '1' then
+            LoadWritePC (MemA[address, 4]);
+                  
+        if wback && registers<n> == '0' then R[n] = R[n] + 4 * BitCount (registers);
+        if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
+
+#endif
+            
+    bool success = false;
+    bool conditional = false;
+    if (ConditionPassed(opcode, &conditional))
+    {
+        uint32_t n;
+        uint32_t registers = 0;
+        bool wback;
+        const uint32_t addr_byte_size = GetAddressByteSize();
+        switch (encoding)
+        {
+            case eEncodingT1:
+                // n = UInt(Rn); registers = '00000000':register_list; wback = (registers<n> == '0');
+                n = Bits32 (opcode, 10, 8);
+                registers = Bits32 (opcode, 7, 0);
+                registers = registers & 0x00ff;  // Make sure the top 8 bits are zeros.
+                wback = BitIsClear (registers, n);
+                // if BitCount(registers) < 1 then UNPREDICTABLE;
+                if (BitCount(registers) < 1)
+                    return false;
+                break;
+            case eEncodingT2:
+                // if W == '1' && Rn == '1101' then SEE POP; 
+                // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1'); 
+                n = Bits32 (opcode, 19, 16);
+                registers = Bits32 (opcode, 15, 0);
+                registers = registers & 0xdfff; // Make sure bit 13 is zero.
+                wback = BitIsSet (opcode, 21);
+                  
+                // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE; 
+                if ((n == 15)
+                    || (BitCount (registers) < 2)
+                    || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
+                    return false;
+                  
+                // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE; 
+                if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
+                    return false;
+
+                // if wback && registers<n> == '1' then UNPREDICTABLE;
+                if (wback
+                    && BitIsSet (registers, n))
+                    return false;
+                break;
+                  
+            case eEncodingA1:
+                n = Bits32 (opcode, 19, 16);
+                registers = Bits32 (opcode, 15, 0);
+                wback = BitIsSet (opcode, 21);
+                if ((n == 15)
+                    || (BitCount (registers) < 1))
+                    return false;
+                break;
+            default:
+                return false;
+        }
+        
+        int32_t offset = 0;
+        const addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
+        if (!success)
+            return false;
+
+        EmulateInstruction::Context context;
+        context.type = EmulateInstruction::eContextRegisterPlusOffset;
+        RegisterInfo dwarf_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
+        context.SetRegisterPlusOffset (dwarf_reg, offset);
+                  
+        for (int i = 0; i < 14; ++i)
+        {
+            if (BitIsSet (registers, i))
+            {
+                context.type = EmulateInstruction::eContextRegisterPlusOffset;
+                context.SetRegisterPlusOffset (dwarf_reg, offset);
+                if (wback && (n == 13)) // Pop Instruction
+                {
+                    if (conditional)
+                        context.type = EmulateInstruction::eContextRegisterLoad;
+                    else
+                        context.type = EmulateInstruction::eContextPopRegisterOffStack;
+                }
+
+                // R[i] = MemA [address, 4]; address = address + 4;
+                uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
+                if (!success)
+                    return false;
+                  
+                if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
+                    return false;
+
+                offset += addr_byte_size;
+            }
+        }
+                
+        if (BitIsSet (registers, 15))
+        {
+            //LoadWritePC (MemA [address, 4]);
+            context.type = EmulateInstruction::eContextRegisterPlusOffset;
+            context.SetRegisterPlusOffset (dwarf_reg, offset);
+            uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
+            if (!success)
+                return false;
+            // In ARMv5T and above, this is an interworking branch.
+            if (!LoadWritePC(context, data))
+                return false;
+        }
+                             
+        if (wback && BitIsClear (registers, n))
+        {
+            // R[n] = R[n] + 4 * BitCount (registers)
+            int32_t offset = addr_byte_size * BitCount (registers);
+            context.type = EmulateInstruction::eContextAdjustBaseRegister;
+            context.SetRegisterPlusOffset (dwarf_reg, offset);
+                
+            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, base_address + offset))
+                return false;
+        }
+        if (wback && BitIsSet (registers, n))
+            // R[n] bits(32) UNKNOWN;
+            return WriteBits32Unknown (n);
+    }
+    return true;
+}
+                
+// LDMDA loads multiple registers from consecutive memory locations using an address from a base register.
+// The consecutive memory locations end at this address and the address just below the lowest of those locations
+// can optionally be written back to the base register.
+bool
+EmulateInstructionARM::EmulateLDMDA (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if ConditionPassed() then 
+        EncodingSpecificOperations(); 
+        address = R[n] - 4*BitCount(registers) + 4;
+                  
+        for i = 0 to 14 
+            if registers<i> == '1' then
+                  R[i] = MemA[address,4]; address = address + 4; 
+                  
+        if registers<15> == '1' then
+            LoadWritePC(MemA[address,4]);
+                  
+        if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers); 
+        if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
+#endif
+                  
+    bool success = false;
+                  
+    if (ConditionPassed(opcode))
+    {
+        uint32_t n;
+        uint32_t registers = 0;
+        bool wback;
+        const uint32_t addr_byte_size = GetAddressByteSize();
+                  
+        // EncodingSpecificOperations(); 
+        switch (encoding)
+        {
+            case eEncodingA1:
+                // n = UInt(Rn); registers = register_list; wback = (W == '1');
+                n = Bits32 (opcode, 19, 16);
+                registers = Bits32 (opcode, 15, 0);
+                wback = BitIsSet (opcode, 21);
+                  
+                // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
+                if ((n == 15) || (BitCount (registers) < 1))
+                    return false;
+                  
+                break;
+
+            default:
+                return false;
+        }
+        // address = R[n] - 4*BitCount(registers) + 4;
+                  
+        int32_t offset = 0;
+        addr_t Rn = ReadCoreReg (n, &success);
+                  
+        if (!success)
+            return false;
+            
+        addr_t address = Rn - (addr_byte_size * BitCount (registers)) + addr_byte_size;
+                                                        
+        EmulateInstruction::Context context;
+        context.type = EmulateInstruction::eContextRegisterPlusOffset;
+        RegisterInfo dwarf_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
+        context.SetRegisterPlusOffset (dwarf_reg, offset);
+                  
+        // for i = 0 to 14 
+        for (int i = 0; i < 14; ++i)
+        {
+            // if registers<i> == '1' then
+            if (BitIsSet (registers, i))
+            {
+                  // R[i] = MemA[address,4]; address = address + 4; 
+                  context.SetRegisterPlusOffset (dwarf_reg, Rn - (address + offset));
+                  uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
+                  if (!success)
+                      return false;
+                  if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
+                      return false;
+                  offset += addr_byte_size;
+            }
+        }
+                  
+        // if registers<15> == '1' then
+        //     LoadWritePC(MemA[address,4]);
+        if (BitIsSet (registers, 15))
+        {
+            context.SetRegisterPlusOffset (dwarf_reg, offset);
+            uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
+            if (!success)
+                return false;
+            // In ARMv5T and above, this is an interworking branch.
+            if (!LoadWritePC(context, data))
+                return false;
+        }
+                  
+        // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers); 
+        if (wback && BitIsClear (registers, n))
+        {
+            if (!success)
+                return false;
+
+            offset = (addr_byte_size * BitCount (registers)) * -1;
+            context.type = EmulateInstruction::eContextAdjustBaseRegister;
+            context.SetImmediateSigned (offset);      
+            addr_t addr = Rn + offset;
+            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
+                return false;
+        }
+                  
+        // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
+        if (wback && BitIsSet (registers, n))
+            return WriteBits32Unknown (n);
+    }
+    return true;
+}
+  
+// LDMDB loads multiple registers from consecutive memory locations using an address from a base register.  The 
+// consecutive memory lcoations end just below this address, and the address of the lowest of those locations can 
+// be optionally written back to the base register.
+bool
+EmulateInstructionARM::EmulateLDMDB (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if ConditionPassed() then 
+        EncodingSpecificOperations(); NullCheckIfThumbEE(n); 
+        address = R[n] - 4*BitCount(registers);
+                  
+        for i = 0 to 14 
+            if registers<i> == '1' then
+                  R[i] = MemA[address,4]; address = address + 4; 
+        if registers<15> == '1' then
+                  LoadWritePC(MemA[address,4]);
+                  
+        if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers); 
+        if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
+#endif
+                  
+    bool success = false;
+                  
+    if (ConditionPassed(opcode))
+    {
+        uint32_t n;
+        uint32_t registers = 0;
+        bool wback;
+        const uint32_t addr_byte_size = GetAddressByteSize();
+        switch (encoding)
+        {
+            case eEncodingT1:
+                // n = UInt(Rn); registers = P:M:'0':register_list; wback = (W == '1');
+                n = Bits32 (opcode, 19, 16);
+                registers = Bits32 (opcode, 15, 0);
+                registers = registers & 0xdfff;  // Make sure bit 13 is a zero.
+                wback = BitIsSet (opcode, 21);
+
+                // if n == 15 || BitCount(registers) < 2 || (P == '1' && M == '1') then UNPREDICTABLE;
+                if ((n == 15)
+                    || (BitCount (registers) < 2)
+                    || (BitIsSet (opcode, 14) && BitIsSet (opcode, 15)))
+                    return false;
+
+                // if registers<15> == '1' && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
+                if (BitIsSet (registers, 15) && InITBlock() && !LastInITBlock())
+                    return false;
+
+                // if wback && registers<n> == '1' then UNPREDICTABLE;
+                if (wback && BitIsSet (registers, n))
+                    return false;
+                  
+                break;
+                  
+            case eEncodingA1:
+                // n = UInt(Rn); registers = register_list; wback = (W == '1');
+                n = Bits32 (opcode, 19, 16);
+                registers = Bits32 (opcode, 15, 0);
+                wback = BitIsSet (opcode, 21);
+                  
+                // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
+                if ((n == 15) || (BitCount (registers) < 1))
+                    return false;
+                  
+                break;
+                  
+            default:
+                return false;
+        }
+                  
+        // address = R[n] - 4*BitCount(registers);
+                  
+        int32_t offset = 0;
+        addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
+                  
+        if (!success)
+            return false;
+                  
+        addr_t address = Rn - (addr_byte_size * BitCount (registers));
+        EmulateInstruction::Context context;
+        context.type = EmulateInstruction::eContextRegisterPlusOffset;
+        RegisterInfo dwarf_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
+        context.SetRegisterPlusOffset (dwarf_reg, Rn - address);
+                  
+        for (int i = 0; i < 14; ++i)
+        {
+            if (BitIsSet (registers, i))
+            {
+                // R[i] = MemA[address,4]; address = address + 4;
+                context.SetRegisterPlusOffset (dwarf_reg, Rn - (address + offset));
+                uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
+                if (!success)
+                    return false;
+                  
+                if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
+                    return false;
+                  
+                offset += addr_byte_size;
+            }
+        }
+                  
+        // if registers<15> == '1' then
+        //     LoadWritePC(MemA[address,4]);
+        if (BitIsSet (registers, 15))
+        {
+            context.SetRegisterPlusOffset (dwarf_reg, offset);
+            uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
+            if (!success)
+                return false;
+            // In ARMv5T and above, this is an interworking branch.
+            if (!LoadWritePC(context, data))
+                return false;
+        }
+                  
+        // if wback && registers<n> == '0' then R[n] = R[n] - 4*BitCount(registers);
+        if (wback && BitIsClear (registers, n))
+        {
+            if (!success)
+                return false;
+            
+            offset = (addr_byte_size * BitCount (registers)) * -1;
+            context.type = EmulateInstruction::eContextAdjustBaseRegister;
+            context.SetImmediateSigned (offset);
+            addr_t addr = Rn + offset;
+            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
+                return false;
+        }
+                  
+        // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
+        if (wback && BitIsSet (registers, n))
+            return WriteBits32Unknown (n);
+    }
+    return true;
+}
+
+// LDMIB loads multiple registers from consecutive memory locations using an address from a base register.  The 
+// consecutive memory locations start just above this address, and thea ddress of the last of those locations can 
+// optinoally be written back to the base register.
+bool
+EmulateInstructionARM::EmulateLDMIB (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    if ConditionPassed() then
+        EncodingSpecificOperations(); 
+        address = R[n] + 4;
+                  
+        for i = 0 to 14 
+            if registers<i> == '1' then
+                  R[i] = MemA[address,4]; address = address + 4; 
+        if registers<15> == '1' then
+            LoadWritePC(MemA[address,4]);
+                  
+        if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers); 
+        if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN;
+#endif
+                  
+    bool success = false;
+                  
+    if (ConditionPassed(opcode))
+    {
+        uint32_t n;
+        uint32_t registers = 0;
+        bool wback;
+        const uint32_t addr_byte_size = GetAddressByteSize();
+        switch (encoding)
+        {
+            case eEncodingA1:
+                // n = UInt(Rn); registers = register_list; wback = (W == '1');
+                n = Bits32 (opcode, 19, 16);
+                registers = Bits32 (opcode, 15, 0);
+                wback = BitIsSet (opcode, 21);
+                  
+                // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
+                if ((n == 15) || (BitCount (registers) < 1))
+                    return false;
+                  
+                break;
+            default:
+                return false;
+        }
+        // address = R[n] + 4;
+                  
+        int32_t offset = 0;
+        addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
+                  
+        if (!success)
+            return false;
+                  
+        addr_t address = Rn + addr_byte_size;
+                  
+        EmulateInstruction::Context context;
+        context.type = EmulateInstruction::eContextRegisterPlusOffset;
+        RegisterInfo dwarf_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, dwarf_reg);
+        context.SetRegisterPlusOffset (dwarf_reg, offset);
+
+        for (int i = 0; i < 14; ++i)
+        {
+            if (BitIsSet (registers, i))
+            {
+                // R[i] = MemA[address,4]; address = address + 4;
+                
+                context.SetRegisterPlusOffset (dwarf_reg, offset + addr_byte_size);
+                uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
+                if (!success)
+                    return false;
+                  
+                if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + i, data))
+                    return false;
+                  
+                offset += addr_byte_size;
+            }
+        }
+                  
+        // if registers<15> == '1' then
+        //     LoadWritePC(MemA[address,4]);
+        if (BitIsSet (registers, 15))
+        {
+            context.SetRegisterPlusOffset (dwarf_reg, offset);
+            uint32_t data = MemARead (context, address + offset, addr_byte_size, 0, &success);
+            if (!success)
+                return false;
+            // In ARMv5T and above, this is an interworking branch.
+            if (!LoadWritePC(context, data))
+                return false;
+        }
+                  
+        // if wback && registers<n> == '0' then R[n] = R[n] + 4*BitCount(registers);
+        if (wback && BitIsClear (registers, n))
+        {
+            if (!success)
+                return false;
+
+            offset = addr_byte_size * BitCount (registers);
+            context.type = EmulateInstruction::eContextAdjustBaseRegister;
+            context.SetImmediateSigned (offset);
+            addr_t addr = Rn + offset;
+            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, addr))
+                return false;
+        }
+                  
+        // if wback && registers<n> == '1' then R[n] = bits(32) UNKNOWN; // Only possible for encoding A1
+        if (wback && BitIsSet (registers, n))
+            return WriteBits32Unknown (n);
+    }
+    return true;
+}
+                  
+// Load Register (immediate) calculates an address from a base register value and
+// an immediate offset, loads a word from memory, and writes to a register.
+// LDR (immediate, Thumb)
+bool
+EmulateInstructionARM::EmulateLDRRtRnImm (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if (ConditionPassed())
+    {
+        EncodingSpecificOperations(); NullCheckIfThumbEE(15);
+        offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
+        address = if index then offset_addr else R[n];
+        data = MemU[address,4];
+        if wback then R[n] = offset_addr;
+        if t == 15 then
+            if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
+        elsif UnalignedSupport() || address<1:0> = '00' then
+            R[t] = data;
+        else R[t] = bits(32) UNKNOWN; // Can only apply before ARMv7
+    }
+#endif
+
+    bool success = false;
+
+    if (ConditionPassed(opcode))
+    {
+        uint32_t Rt; // the destination register
+        uint32_t Rn; // the base register
+        uint32_t imm32; // the immediate offset used to form the address
+        addr_t offset_addr; // the offset address
+        addr_t address; // the calculated address
+        uint32_t data; // the literal data value from memory load
+        bool add, index, wback;
+        switch (encoding) {
+            case eEncodingT1:
+                Rt = Bits32(opcode, 2, 0);
+                Rn = Bits32(opcode, 5, 3);
+                imm32 = Bits32(opcode, 10, 6) << 2; // imm32 = ZeroExtend(imm5:'00', 32);
+                // index = TRUE; add = TRUE; wback = FALSE
+                add = true;
+                index = true;
+                wback = false;
+                  
+                break;
+                
+            case eEncodingT2:
+                // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
+                Rt = Bits32 (opcode, 10, 8);
+                Rn = 13;
+                imm32 = Bits32 (opcode, 7, 0) << 2;
+                  
+                // index = TRUE; add = TRUE; wback = FALSE;
+                index = true;
+                add = true;
+                wback = false;
+                  
+                break;
+                  
+            case eEncodingT3:
+                // if Rn == '1111' then SEE LDR (literal);
+                // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
+                Rt = Bits32 (opcode, 15, 12);
+                Rn = Bits32 (opcode, 19, 16);
+                imm32 = Bits32 (opcode, 11, 0);
+                  
+                // index = TRUE; add = TRUE; wback = FALSE;
+                index = true;
+                add = true;
+                wback = false;
+                  
+                // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
+                if ((Rt == 15) && InITBlock() && !LastInITBlock())
+                    return false;
+                  
+                break;
+                  
+            case eEncodingT4:
+                // if Rn == '1111' then SEE LDR (literal);
+                // if P == '1' && U == '1' && W == '0' then SEE LDRT;
+                // if Rn == '1101' && P == '0' && U == '1' && W == '1' && imm8 == '00000100' then SEE POP;
+                // if P == '0' && W == '0' then UNDEFINED;
+                if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
+                    return false;
+                  
+                // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
+                Rt = Bits32 (opcode, 15, 12);
+                Rn = Bits32 (opcode, 19, 16);
+                imm32 = Bits32 (opcode, 7, 0);
+                  
+                // index = (P == '1'); add = (U == '1'); wback = (W == '1');
+                index = BitIsSet (opcode, 10);
+                add = BitIsSet (opcode, 9);
+                wback = BitIsSet (opcode, 8);
+                  
+                // if (wback && n == t) || (t == 15 && InITBlock() && !LastInITBlock()) then UNPREDICTABLE;
+                if ((wback && (Rn == Rt)) || ((Rt == 15) && InITBlock() && !LastInITBlock()))
+                    return false;
+                    
+                break;
+                  
+            default:
+                return false;
+        }
+        uint32_t base = ReadCoreReg (Rn, &success);
+        if (!success)
+            return false;
+        if (add)
+            offset_addr = base + imm32;
+        else
+            offset_addr = base - imm32;
+
+        address = (index ? offset_addr : base);
+
+        RegisterInfo base_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + Rn, base_reg);
+        if (wback)
+        {
+            EmulateInstruction::Context ctx;
+            ctx.type = EmulateInstruction::eContextAdjustBaseRegister;
+            ctx.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base));
+
+            if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr))
+                return false;
+        }
+
+        // Prepare to write to the Rt register.
+        EmulateInstruction::Context context;
+        context.type = EmulateInstruction::eContextRegisterLoad;
+        context.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base));
+
+        // Read memory from the address.
+        data = MemURead(context, address, 4, 0, &success);
+        if (!success)
+            return false;    
+
+        if (Rt == 15)
+        {
+            if (Bits32(address, 1, 0) == 0)
+            {
+                if (!LoadWritePC(context, data))
+                    return false;
+            }
+            else
+                return false;
+        }
+        else if (UnalignedSupport() || Bits32(address, 1, 0) == 0)
+        {
+            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + Rt, data))
+                return false;
+        }
+        else
+            WriteBits32Unknown (Rt);
+    }
+    return true;
+}
+
+// STM (Store Multiple Increment After) stores multiple registers to consecutive memory locations using an address 
+// from a base register.  The consecutive memory locations start at this address, and teh address just above the last
+// of those locations can optionally be written back to the base register.
+bool
+EmulateInstructionARM::EmulateSTM (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    if ConditionPassed() then 
+        EncodingSpecificOperations(); NullCheckIfThumbEE(n); 
+        address = R[n];
+                  
+        for i = 0 to 14 
+            if registers<i> == '1' then
+                if i == n && wback && i != LowestSetBit(registers) then 
+                    MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
+                else 
+                    MemA[address,4] = R[i];
+                address = address + 4;
+                  
+        if registers<15> == '1' then // Only possible for encoding A1 
+            MemA[address,4] = PCStoreValue();
+        if wback then R[n] = R[n] + 4*BitCount(registers);
+#endif
+    
+    bool success = false;
+                  
+    if (ConditionPassed(opcode))
+    {
+        uint32_t n;
+        uint32_t registers = 0;
+        bool wback;
+        const uint32_t addr_byte_size = GetAddressByteSize();
+                  
+        // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 
+        switch (encoding)
+        {
+            case eEncodingT1:
+                // n = UInt(Rn); registers = '00000000':register_list; wback = TRUE;
+                n = Bits32 (opcode, 10, 8);
+                registers = Bits32 (opcode, 7, 0);
+                registers = registers & 0x00ff;  // Make sure the top 8 bits are zeros.
+                wback = true;
+                  
+                // if BitCount(registers) < 1 then UNPREDICTABLE;
+                if (BitCount (registers) < 1)
+                    return false;
+                  
+                break;
+                  
+            case eEncodingT2:
+                // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1');
+                n = Bits32 (opcode, 19, 16);
+                registers = Bits32 (opcode, 15, 0);
+                registers = registers & 0x5fff; // Make sure bits 15 & 13 are zeros.
+                wback = BitIsSet (opcode, 21);
+                  
+                // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
+                if ((n == 15) || (BitCount (registers) < 2))
+                    return false;
+                  
+                // if wback && registers<n> == '1' then UNPREDICTABLE;
+                if (wback && BitIsSet (registers, n))
+                    return false;
+                  
+                break;
+                  
+            case eEncodingA1:
+                // n = UInt(Rn); registers = register_list; wback = (W == '1');
+                n = Bits32 (opcode, 19, 16);
+                registers = Bits32 (opcode, 15, 0);
+                wback = BitIsSet (opcode, 21);
+                  
+                // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
+                if ((n == 15) || (BitCount (registers) < 1))
+                    return false;
+                  
+                break;
+                  
+            default:
+                return false;
+        }
+        
+        // address = R[n];
+        int32_t offset = 0;
+        const addr_t address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
+        if (!success)
+            return false;
+                  
+        EmulateInstruction::Context context;
+        context.type = EmulateInstruction::eContextRegisterStore;
+        RegisterInfo base_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
+                  
+        // for i = 0 to 14
+        uint32_t lowest_set_bit = 14;
+        for (uint32_t i = 0; i < 14; ++i)
+        {
+            // if registers<i> == '1' then
+            if (BitIsSet (registers, i))
+            {
+                  if (i < lowest_set_bit)
+                      lowest_set_bit = i;
+                  // if i == n && wback && i != LowestSetBit(registers) then 
+                  if ((i == n) && wback && (i != lowest_set_bit))
+                      // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encodings T1 and A1
+                      WriteBits32UnknownToMemory (address + offset);
+                  else
+                  {
+                     // MemA[address,4] = R[i];
+                      uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
+                      if (!success)
+                          return false;
+                  
+                      RegisterInfo data_reg;
+                      GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, data_reg);
+                      context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
+                      if (!MemAWrite (context, address + offset, data, addr_byte_size))
+                          return false;
+                  }
+                  
+                  // address = address + 4;
+                  offset += addr_byte_size;
+            }
+        }
+                  
+        // if registers<15> == '1' then // Only possible for encoding A1 
+        //     MemA[address,4] = PCStoreValue();
+        if (BitIsSet (registers, 15))
+        {
+            RegisterInfo pc_reg;
+            GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg);
+            context.SetRegisterPlusOffset (pc_reg, 8);
+            const uint32_t pc = ReadCoreReg (PC_REG, &success);
+            if (!success)
+                return false;
+                  
+            if (!MemAWrite (context, address + offset, pc, addr_byte_size))
+                return false;
+        }
+                  
+        // if wback then R[n] = R[n] + 4*BitCount(registers);
+        if (wback)
+        {
+            offset = addr_byte_size * BitCount (registers);
+            context.type = EmulateInstruction::eContextAdjustBaseRegister;
+            context.SetImmediateSigned (offset);
+            addr_t data = address + offset;
+            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
+                return false;
+        }
+    }
+    return true;
+}
+
+// STMDA (Store Multiple Decrement After) stores multiple registers to consecutive memory locations using an address
+// from a base register.  The consecutive memory locations end at this address, and the address just below the lowest
+// of those locations can optionally be written back to the base register.
+bool
+EmulateInstructionARM::EmulateSTMDA (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    if ConditionPassed() then 
+        EncodingSpecificOperations();                   
+        address = R[n] - 4*BitCount(registers) + 4;
+                  
+        for i = 0 to 14 
+            if registers<i> == '1' then
+                if i == n && wback && i != LowestSetBit(registers) then 
+                    MemA[address,4] = bits(32) UNKNOWN;
+                else 
+                    MemA[address,4] = R[i];
+                address = address + 4;
+                  
+        if registers<15> == '1' then 
+            MemA[address,4] = PCStoreValue();
+                  
+        if wback then R[n] = R[n] - 4*BitCount(registers);
+#endif
+                  
+    bool success = false;
+                  
+    if (ConditionPassed(opcode))
+    {
+        uint32_t n;
+        uint32_t registers = 0;
+        bool wback;
+        const uint32_t addr_byte_size = GetAddressByteSize();
+                  
+        // EncodingSpecificOperations();
+        switch (encoding)
+        {
+            case eEncodingA1:
+                // n = UInt(Rn); registers = register_list; wback = (W == '1');
+                n = Bits32 (opcode, 19, 16);
+                registers = Bits32 (opcode, 15, 0);
+                wback = BitIsSet (opcode, 21);
+                  
+                // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
+                if ((n == 15) || (BitCount (registers) < 1))
+                    return false;
+                break;
+            default:
+                return false;
+        }
+                  
+        // address = R[n] - 4*BitCount(registers) + 4;
+        int32_t offset = 0;
+        addr_t Rn = ReadCoreReg (n, &success);
+        if (!success)
+            return false;
+                  
+        addr_t address = Rn - (addr_byte_size * BitCount (registers)) + 4;
+                  
+        EmulateInstruction::Context context;
+        context.type = EmulateInstruction::eContextRegisterStore;
+        RegisterInfo base_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
+                  
+        // for i = 0 to 14 
+        uint32_t lowest_bit_set = 14;
+        for (uint32_t i = 0; i < 14; ++i)
+        {
+            // if registers<i> == '1' then
+            if (BitIsSet (registers, i))
+            {
+                if (i < lowest_bit_set)
+                    lowest_bit_set = i;
+                //if i == n && wback && i != LowestSetBit(registers) then
+                if ((i == n) && wback && (i != lowest_bit_set))
+                    // MemA[address,4] = bits(32) UNKNOWN;
+                    WriteBits32UnknownToMemory (address + offset);
+                else
+                {
+                    // MemA[address,4] = R[i];
+                    uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
+                    if (!success)
+                        return false;
+                  
+                    RegisterInfo data_reg;
+                    GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, data_reg);
+                    context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, Rn - (address + offset));
+                    if (!MemAWrite (context, address + offset, data, addr_byte_size))
+                        return false;
+                }
+                  
+                // address = address + 4;
+                offset += addr_byte_size;
+            }
+        }
+                  
+        // if registers<15> == '1' then 
+        //    MemA[address,4] = PCStoreValue();
+        if (BitIsSet (registers, 15))
+        {
+            RegisterInfo pc_reg;
+            GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg);
+            context.SetRegisterPlusOffset (pc_reg, 8);
+            const uint32_t pc = ReadCoreReg (PC_REG, &success);
+            if (!success)
+                return false;
+                  
+            if (!MemAWrite (context, address + offset, pc, addr_byte_size))
+                return false;
+        }
+                  
+        // if wback then R[n] = R[n] - 4*BitCount(registers);
+        if (wback)
+        {
+            offset = (addr_byte_size * BitCount (registers)) * -1;
+            context.type = EmulateInstruction::eContextAdjustBaseRegister;
+            context.SetImmediateSigned (offset);
+            addr_t data = Rn + offset;
+            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
+                return false;
+        }
+    }
+    return true;
+}
+                  
+// STMDB (Store Multiple Decrement Before) stores multiple registers to consecutive memory locations using an address
+// from a base register.  The consecutive memory locations end just below this address, and the address of the first of
+// those locations can optionally be written back to the base register.
+bool
+EmulateInstructionARM::EmulateSTMDB (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    if ConditionPassed() then 
+        EncodingSpecificOperations(); NullCheckIfThumbEE(n); 
+        address = R[n] - 4*BitCount(registers);
+                  
+        for i = 0 to 14 
+            if registers<i> == '1' then
+                if i == n && wback && i != LowestSetBit(registers) then 
+                    MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
+                else 
+                    MemA[address,4] = R[i];
+                address = address + 4;
+                  
+        if registers<15> == '1' then // Only possible for encoding A1 
+            MemA[address,4] = PCStoreValue();
+                  
+        if wback then R[n] = R[n] - 4*BitCount(registers);
+#endif
+
+                  
+    bool success = false;
+                  
+    if (ConditionPassed(opcode))
+    {
+        uint32_t n;
+        uint32_t registers = 0;
+        bool wback;
+        const uint32_t addr_byte_size = GetAddressByteSize();
+                  
+        // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
+        switch (encoding)
+        {
+            case eEncodingT1:
+                // if W == '1' && Rn == '1101' then SEE PUSH;
+                if ((BitIsSet (opcode, 21)) && (Bits32 (opcode, 19, 16) == 13))
+                { 
+                    // See PUSH 
+                }
+                // n = UInt(Rn); registers = '0':M:'0':register_list; wback = (W == '1'); 
+                n = Bits32 (opcode, 19, 16);
+                registers = Bits32 (opcode, 15, 0);
+                registers = registers & 0x5fff;  // Make sure bits 15 & 13 are zeros.
+                wback = BitIsSet (opcode, 21);
+                // if n == 15 || BitCount(registers) < 2 then UNPREDICTABLE;
+                if ((n == 15) || BitCount (registers) < 2)
+                    return false;
+                // if wback && registers<n> == '1' then UNPREDICTABLE;
+                if (wback && BitIsSet (registers, n))
+                    return false;
+                break;
+                  
+            case eEncodingA1:
+                // if W == '1' && Rn == '1101� && BitCount(register_list) >= 2 then SEE PUSH; 
+                if (BitIsSet (opcode, 21) && (Bits32 (opcode, 19, 16) == 13) && BitCount (Bits32 (opcode, 15, 0)) >= 2)
+                {
+                    // See Push
+                }
+                // n = UInt(Rn); registers = register_list; wback = (W == '1');
+                n = Bits32 (opcode, 19, 16);
+                registers = Bits32 (opcode, 15, 0);
+                wback = BitIsSet (opcode, 21);
+                // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
+                if ((n == 15) || BitCount (registers) < 1)
+                    return false;
+                break;
+                  
+            default:
+                return false;
+        }
+                  
+        // address = R[n] - 4*BitCount(registers);
+                  
+        int32_t offset = 0;
+        addr_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
+        if (!success)
+        return false;
+                  
+        addr_t address = Rn - (addr_byte_size * BitCount (registers));
+                  
+        EmulateInstruction::Context context;
+        context.type = EmulateInstruction::eContextRegisterStore;
+        RegisterInfo base_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
+                  
+        // for i = 0 to 14
+        uint32_t lowest_set_bit = 14;
+        for (uint32_t i = 0; i < 14; ++i)
+        {
+            // if registers<i> == '1' then
+            if (BitIsSet (registers, i))
+            {
+                if (i < lowest_set_bit)
+                    lowest_set_bit = i;
+                // if i == n && wback && i != LowestSetBit(registers) then 
+                if ((i == n) && wback && (i != lowest_set_bit))
+                    // MemA[address,4] = bits(32) UNKNOWN; // Only possible for encoding A1
+                    WriteBits32UnknownToMemory (address + offset);
+                else
+                {
+                    // MemA[address,4] = R[i];
+                    uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
+                    if (!success)
+                        return false;
+                  
+                    RegisterInfo data_reg;
+                    GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, data_reg);
+                    context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, Rn - (address + offset));
+                    if (!MemAWrite (context, address + offset, data, addr_byte_size))
+                        return false;
+                }
+                  
+                // address = address + 4;
+                offset += addr_byte_size;
+            }
+        }
+                  
+        // if registers<15> == '1' then // Only possible for encoding A1 
+        //     MemA[address,4] = PCStoreValue();
+        if (BitIsSet (registers, 15))
+        {
+            RegisterInfo pc_reg;
+            GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg);
+            context.SetRegisterPlusOffset (pc_reg, 8);
+            const uint32_t pc = ReadCoreReg (PC_REG, &success);
+            if (!success)
+                return false;
+                  
+            if (!MemAWrite (context, address + offset, pc, addr_byte_size))
+                return false;
+        }
+                  
+        // if wback then R[n] = R[n] - 4*BitCount(registers);
+        if (wback)
+        {
+            offset = (addr_byte_size * BitCount (registers)) * -1;
+            context.type = EmulateInstruction::eContextAdjustBaseRegister;
+            context.SetImmediateSigned (offset);
+            addr_t data = Rn + offset;
+            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
+                return false;
+        }
+    }
+    return true;
+}
+                  
+// STMIB (Store Multiple Increment Before) stores multiple registers to consecutive memory locations using an address
+// from a base register.  The consecutive memory locations start just above this address, and the address of the last
+// of those locations can optionally be written back to the base register.
+bool
+EmulateInstructionARM::EmulateSTMIB (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    if ConditionPassed() then 
+        EncodingSpecificOperations(); 
+        address = R[n] + 4;
+                  
+        for i = 0 to 14 
+            if registers<i> == '1' then
+                if i == n && wback && i != LowestSetBit(registers) then
+                    MemA[address,4] = bits(32) UNKNOWN;
+                else 
+                    MemA[address,4] = R[i];
+                address = address + 4;
+                  
+        if registers<15> == '1' then 
+            MemA[address,4] = PCStoreValue();
+                  
+        if wback then R[n] = R[n] + 4*BitCount(registers);
+#endif   
+                  
+    bool success = false;
+                  
+    if (ConditionPassed(opcode))
+    {
+        uint32_t n;
+        uint32_t registers = 0;
+        bool wback;
+        const uint32_t addr_byte_size = GetAddressByteSize();
+                  
+        // EncodingSpecificOperations(); 
+        switch (encoding)
+        {
+            case eEncodingA1:
+                // n = UInt(Rn); registers = register_list; wback = (W == '1'); 
+                n = Bits32 (opcode, 19, 16);
+                registers = Bits32 (opcode, 15, 0);
+                wback = BitIsSet (opcode, 21);
+                  
+                // if n == 15 || BitCount(registers) < 1 then UNPREDICTABLE;
+                if ((n == 15) && (BitCount (registers) < 1))
+                    return false;
+                break;
+            default:
+                return false;
+        }
+        // address = R[n] + 4;
+                  
+        int32_t offset = 0;
+        addr_t Rn = ReadCoreReg (n, &success);
+        if (!success)
+            return false;
+                  
+        addr_t address = Rn + addr_byte_size;
+                  
+        EmulateInstruction::Context context;
+        context.type = EmulateInstruction::eContextRegisterStore;
+        RegisterInfo base_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
+                
+        uint32_t lowest_set_bit = 14;
+        // for i = 0 to 14
+        for (uint32_t i = 0; i < 14; ++i)
+        {
+            // if registers<i> == '1' then
+            if (BitIsSet (registers, i))
+            {
+                if (i < lowest_set_bit)
+                    lowest_set_bit = i;
+                // if i == n && wback && i != LowestSetBit(registers) then
+                if ((i == n) && wback && (i != lowest_set_bit))
+                    // MemA[address,4] = bits(32) UNKNOWN;
+                    WriteBits32UnknownToMemory (address + offset);
+                // else
+                else
+                {
+                    // MemA[address,4] = R[i];
+                    uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + i, 0, &success);
+                    if (!success)
+                        return false;
+                  
+                    RegisterInfo data_reg;
+                    GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + i, data_reg);
+                    context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset + addr_byte_size);
+                    if (!MemAWrite (context, address + offset, data, addr_byte_size))
+                        return false;
+                }
+                  
+                // address = address + 4;
+                offset += addr_byte_size;
+            }
+        }
+                  
+        // if registers<15> == '1' then 
+            // MemA[address,4] = PCStoreValue();
+        if (BitIsSet (registers, 15))
+        {
+            RegisterInfo pc_reg;
+            GetRegisterInfo (eRegisterKindDWARF, dwarf_pc, pc_reg);
+            context.SetRegisterPlusOffset (pc_reg, 8);
+            const uint32_t pc = ReadCoreReg (PC_REG, &success);
+            if (!success)
+            return false;
+                  
+            if (!MemAWrite (context, address + offset, pc, addr_byte_size))
+                return false;
+        }
+                  
+        // if wback then R[n] = R[n] + 4*BitCount(registers);
+        if (wback)
+        {
+            offset = addr_byte_size * BitCount (registers);
+            context.type = EmulateInstruction::eContextAdjustBaseRegister;
+            context.SetImmediateSigned (offset);
+            addr_t data = Rn + offset;
+            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, data))
+                return false;
+        }
+    }
+    return true;
+}
+
+// STR (store immediate) calcualtes an address from a base register value and an immediate offset, and stores a word
+// from a register to memory.  It can use offset, post-indexed, or pre-indexed addressing.
+bool
+EmulateInstructionARM::EmulateSTRThumb (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    if ConditionPassed() then 
+        EncodingSpecificOperations(); NullCheckIfThumbEE(n); 
+        offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 
+        address = if index then offset_addr else R[n]; 
+        if UnalignedSupport() || address<1:0> == '00' then
+            MemU[address,4] = R[t]; 
+        else // Can only occur before ARMv7
+            MemU[address,4] = bits(32) UNKNOWN; 
+        if wback then R[n] = offset_addr;
+#endif
+                  
+    bool success = false;
+                  
+    if (ConditionPassed(opcode))
+    {
+        const uint32_t addr_byte_size = GetAddressByteSize();
+                  
+        uint32_t t;
+        uint32_t n;
+        uint32_t imm32;
+        bool index;
+        bool add;
+        bool wback;
+        // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
+        switch (encoding)
+        {
+            case eEncodingT1:
+                // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'00', 32);
+                t = Bits32 (opcode, 2, 0);
+                n = Bits32 (opcode, 5, 3);
+                imm32 = Bits32 (opcode, 10, 6) << 2;
+                  
+                // index = TRUE; add = TRUE; wback = FALSE;
+                index = true;
+                add = false;
+                wback = false;
+                break;
+                  
+            case eEncodingT2:
+                // t = UInt(Rt); n = 13; imm32 = ZeroExtend(imm8:'00', 32);
+                t = Bits32 (opcode, 10, 8);
+                n = 13;
+                imm32 = Bits32 (opcode, 7, 0) << 2;
+                  
+                // index = TRUE; add = TRUE; wback = FALSE;
+                index = true;
+                add = true;
+                wback = false;
+                break;
+                  
+            case eEncodingT3:
+                // if Rn == '1111' then UNDEFINED;
+                if (Bits32 (opcode, 19, 16) == 15)
+                    return false;
+                  
+                // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
+                t = Bits32 (opcode, 15, 12);
+                n = Bits32 (opcode, 19, 16);
+                imm32 = Bits32 (opcode, 11, 0);
+                  
+                // index = TRUE; add = TRUE; wback = FALSE;
+                index = true;
+                add = true;
+                wback = false;
+                  
+                // if t == 15 then UNPREDICTABLE;
+                if (t == 15)
+                    return false;
+                break;
+                  
+            case eEncodingT4:
+                // if P == '1' && U == '1' && W == '0' then SEE STRT; 
+                // if Rn == '1101' && P == '1' && U == '0' && W == '1' && imm8 == '00000100' then SEE PUSH;
+                // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED;
+                if ((Bits32 (opcode, 19, 16) == 15)
+                      || (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)))
+                    return false;
+                  
+                // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
+                t = Bits32 (opcode, 15, 12);
+                n = Bits32 (opcode, 19, 16);
+                imm32 = Bits32 (opcode, 7, 0);
+                  
+                // index = (P == '1'); add = (U == '1'); wback = (W == '1'); 
+                index = BitIsSet (opcode, 10);
+                add = BitIsSet (opcode, 9);
+                wback = BitIsSet (opcode, 8);
+                  
+                // if t == 15 || (wback && n == t) then UNPREDICTABLE;
+                if ((t == 15) || (wback && (n == t)))
+                    return false;
+                break;
+                  
+            default:
+                return false;
+        }
+    
+        addr_t offset_addr;
+        addr_t address;
+                  
+        // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
+        uint32_t base_address = ReadCoreReg (n, &success);
+        if (!success)
+            return false;
+                  
+        if (add)
+            offset_addr = base_address + imm32;
+        else
+            offset_addr = base_address - imm32;
+
+        // address = if index then offset_addr else R[n]; 
+        if (index)
+            address = offset_addr;
+        else
+            address = base_address;
+                  
+        EmulateInstruction::Context context;
+        context.type = eContextRegisterStore;
+        RegisterInfo base_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
+                  
+        // if UnalignedSupport() || address<1:0> == '00' then
+        if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
+        {
+            // MemU[address,4] = R[t]; 
+            uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
+            if (!success)
+                return false;
+                  
+            RegisterInfo data_reg;
+            GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
+            int32_t offset = address - base_address;
+            context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, offset);
+            if (!MemUWrite (context, address, data, addr_byte_size))
+                return false;
+        }
+        else
+        {
+            // MemU[address,4] = bits(32) UNKNOWN; 
+            WriteBits32UnknownToMemory (address);
+        }
+                  
+        // if wback then R[n] = offset_addr;
+        if (wback)
+        {
+            context.type = eContextRegisterLoad;
+            context.SetAddress (offset_addr);
+            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
+                return false;
+        }
+    }
+    return true;
+}
+                  
+// STR (Store Register) calculates an address from a base register value and an offset register value, stores a 
+// word from a register to memory.   The offset register value can optionally be shifted.
+bool
+EmulateInstructionARM::EmulateSTRRegister (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    if ConditionPassed() then 
+        EncodingSpecificOperations(); NullCheckIfThumbEE(n); 
+        offset = Shift(R[m], shift_t, shift_n, APSR.C); 
+        offset_addr = if add then (R[n] + offset) else (R[n] - offset); 
+        address = if index then offset_addr else R[n]; 
+        if t == 15 then // Only possible for encoding A1
+            data = PCStoreValue(); 
+        else
+            data = R[t]; 
+        if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then
+            MemU[address,4] = data; 
+        else // Can only occur before ARMv7
+            MemU[address,4] = bits(32) UNKNOWN; 
+        if wback then R[n] = offset_addr;
+#endif
+                  
+    bool success = false;
+                  
+    if (ConditionPassed(opcode))
+    {
+        const uint32_t addr_byte_size = GetAddressByteSize();
+                  
+        uint32_t t;
+        uint32_t n;
+        uint32_t m;
+        ARM_ShifterType shift_t;
+        uint32_t shift_n;
+        bool index;
+        bool add;
+        bool wback;
+                  
+        // EncodingSpecificOperations (); NullCheckIfThumbEE(n);
+        switch (encoding)
+        {
+            case eEncodingT1:
+                // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE";
+                // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
+                t = Bits32 (opcode, 2, 0);
+                n = Bits32 (opcode, 5, 3);
+                m = Bits32 (opcode, 8, 6);
+                  
+                // index = TRUE; add = TRUE; wback = FALSE;
+                index = true;
+                add = true;
+                wback = false;
+                  
+                // (shift_t, shift_n) = (SRType_LSL, 0);
+                shift_t = SRType_LSL;
+                shift_n = 0;
+                break;
+                  
+            case eEncodingT2:
+                // if Rn == '1111' then UNDEFINED; 
+                if (Bits32 (opcode, 19, 16) == 15)
+                    return false;
+                  
+                // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 
+                t = Bits32 (opcode, 15, 12);
+                n = Bits32 (opcode, 19, 16);
+                m = Bits32 (opcode, 3, 0);
+                  
+                // index = TRUE; add = TRUE; wback = FALSE; 
+                index = true;
+                add = true;
+                wback = false;
+                  
+                // (shift_t, shift_n) = (SRType_LSL, UInt(imm2));
+                shift_t = SRType_LSL;
+                shift_n = Bits32 (opcode, 5, 4);
+                  
+                // if t == 15 || BadReg(m) then UNPREDICTABLE;
+                if ((t == 15) || (BadReg (m)))
+                    return false;
+                break;
+                  
+            case eEncodingA1:
+            {
+                // if P == '0' && W == '1' then SEE STRT; 
+                // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
+                t = Bits32 (opcode, 15, 12);
+                n = Bits32 (opcode, 19, 16);
+                m = Bits32 (opcode, 3, 0);
+                  
+                // index = (P == '1');	add = (U == '1');	wback = (P == '0') || (W == '1');
+                index = BitIsSet (opcode, 24);
+                add = BitIsSet (opcode, 23);
+                wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
+                           
+                // (shift_t, shift_n) = DecodeImmShift(type, imm5);
+                uint32_t typ = Bits32 (opcode, 6, 5);
+                uint32_t imm5 = Bits32 (opcode, 11, 7);
+                shift_n = DecodeImmShift(typ, imm5, shift_t);
+                         
+                // if m == 15 then UNPREDICTABLE; 
+                if (m == 15)
+                    return false;
+                         
+                // if wback && (n == 15 || n == t) then UNPREDICTABLE;
+                if (wback && ((n == 15) || (n == t)))
+                    return false;
+
+                break;
+            }                  
+            default:
+                return false;
+        }
+                         
+        addr_t offset_addr;
+        addr_t address;
+        int32_t offset = 0;
+        
+        addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
+        if (!success)
+            return false;
+                         
+        uint32_t Rm_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
+        if (!success)
+            return false;
+                           
+        // offset = Shift(R[m], shift_t, shift_n, APSR.C); 
+        offset = Shift (Rm_data, shift_t, shift_n, APSR_C, &success);
+        if (!success)
+            return false;
+                         
+        // offset_addr = if add then (R[n] + offset) else (R[n] - offset); 
+        if (add)
+            offset_addr = base_address + offset;
+        else
+            offset_addr = base_address - offset;
+                         
+        // address = if index then offset_addr else R[n]; 
+        if (index)
+            address = offset_addr;
+        else
+            address = base_address;
+                    
+        uint32_t data;
+        // if t == 15 then // Only possible for encoding A1
+        if (t == 15)
+            // data = PCStoreValue(); 
+            data = ReadCoreReg (PC_REG, &success);
+        else
+            // data = R[t]; 
+            data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
+                         
+        if (!success)
+            return false;
+                         
+        EmulateInstruction::Context context;
+        context.type = eContextRegisterStore;
+
+        // if UnalignedSupport() || address<1:0> == '00' || CurrentInstrSet() == InstrSet_ARM then
+        if (UnalignedSupport () 
+            || (BitIsClear (address, 1) && BitIsClear (address, 0)) 
+            || CurrentInstrSet() == eModeARM)
+        {
+            // MemU[address,4] = data; 
+            
+            RegisterInfo base_reg;
+            GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 +  n, base_reg);
+            
+            RegisterInfo data_reg;
+            GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
+            
+            context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
+            if (!MemUWrite (context, address, data, addr_byte_size))
+                return false;
+            
+        }
+        else
+            // MemU[address,4] = bits(32) UNKNOWN; 
+            WriteBits32UnknownToMemory (address);
+                         
+        // if wback then R[n] = offset_addr;
+        if (wback)
+        {
+            context.type = eContextRegisterLoad;
+            context.SetAddress (offset_addr);
+            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
+                return false;
+        }
+
+    }
+    return true;
+}
+               
+bool
+EmulateInstructionARM::EmulateSTRBThumb (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    if ConditionPassed() then 
+        EncodingSpecificOperations(); NullCheckIfThumbEE(n); 
+        offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 
+        address = if index then offset_addr else R[n]; 
+        MemU[address,1] = R[t]<7:0>; 
+        if wback then R[n] = offset_addr;
+#endif
+
+                  
+    bool success = false;
+                  
+    if (ConditionPassed(opcode))
+    {
+        uint32_t t;
+        uint32_t n;
+        uint32_t imm32;
+        bool index;
+        bool add;
+        bool wback;
+        // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 
+        switch (encoding)
+        {
+            case eEncodingT1:
+                // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32);
+                t = Bits32 (opcode, 2, 0);
+                n = Bits32 (opcode, 5, 3);
+                imm32 = Bits32 (opcode, 10, 6);
+                  
+                // index = TRUE; add = TRUE; wback = FALSE;
+                index = true;
+                add = true;
+                wback = false;
+                break;
+                  
+            case eEncodingT2:
+                // if Rn == '1111' then UNDEFINED; 
+                if (Bits32 (opcode, 19, 16) == 15)
+                    return false;
+                  
+                // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 
+                t = Bits32 (opcode, 15, 12);
+                n = Bits32 (opcode, 19, 16);
+                imm32 = Bits32 (opcode, 11, 0);
+                  
+                // index = TRUE; add = TRUE; wback = FALSE;
+                index = true;
+                add = true;
+                wback = false;
+                  
+                // if BadReg(t) then UNPREDICTABLE;
+                if (BadReg (t))
+                    return false;
+                break;
+                  
+            case eEncodingT3:
+                // if P == '1' && U == '1' && W == '0' then SEE STRBT; 
+                // if Rn == '1111' || (P == '0' && W == '0') then UNDEFINED; 
+                if (Bits32 (opcode, 19, 16) == 15)
+                    return false;
+                  
+                // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
+                t = Bits32 (opcode, 15, 12);
+                n = Bits32 (opcode, 19, 16);
+                imm32 = Bits32 (opcode, 7, 0);
+                  
+                // index = (P == '1'); add = (U == '1'); wback = (W == '1');
+                index = BitIsSet (opcode, 10);
+                add = BitIsSet (opcode, 9);
+                wback = BitIsSet (opcode, 8);
+                  
+                // if BadReg(t) || (wback && n == t) then UNPREDICTABLE
+                if ((BadReg (t)) || (wback && (n == t)))
+                    return false;
+                break;
+                  
+            default:
+                return false;
+        }
+                  
+        addr_t offset_addr;
+        addr_t address;
+        addr_t base_address = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
+        if (!success)
+            return false;
+                  
+        // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 
+        if (add)
+            offset_addr = base_address + imm32;
+        else
+            offset_addr = base_address - imm32;
+                  
+        // address = if index then offset_addr else R[n];
+        if (index)
+            address = offset_addr;
+        else
+            address = base_address;
+                  
+        // MemU[address,1] = R[t]<7:0>
+        RegisterInfo base_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
+                  
+        RegisterInfo data_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
+                  
+        EmulateInstruction::Context context;
+        context.type = eContextRegisterStore;
+        context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - base_address);
+                  
+        uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
+        if (!success)
+            return false;
+                  
+        data = Bits32 (data, 7, 0);
+
+        if (!MemUWrite (context, address, data, 1))
+            return false;
+                  
+        // if wback then R[n] = offset_addr;
+        if (wback)
+        {
+            context.type = eContextRegisterLoad;
+            context.SetAddress (offset_addr);
+            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
+                return false;
+        }
+            
+    }
+
+    return true;
+}
+
+// STRH (register) calculates an address from a base register value and an offset register value, and stores a 
+// halfword from a register to memory.  The offset register alue can be shifted left by 0, 1, 2, or 3 bits.
+bool
+EmulateInstructionARM::EmulateSTRHRegister (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    if ConditionPassed() then 
+        EncodingSpecificOperations(); NullCheckIfThumbEE(n);
+        offset = Shift(R[m], shift_t, shift_n, APSR.C); 
+        offset_addr = if add then (R[n] + offset) else (R[n] - offset); 
+        address = if index then offset_addr else R[n]; 
+        if UnalignedSupport() || address<0> == '0' then
+            MemU[address,2] = R[t]<15:0>; 
+        else // Can only occur before ARMv7
+            MemU[address,2] = bits(16) UNKNOWN; 
+        if wback then R[n] = offset_addr;
+#endif
+                  
+    bool success = false;
+                  
+    if (ConditionPassed(opcode))
+    {
+        uint32_t t;
+        uint32_t n;
+        uint32_t m;
+        bool index;
+        bool add;
+        bool wback;
+        ARM_ShifterType shift_t;
+        uint32_t shift_n;
+            
+        // EncodingSpecificOperations(); NullCheckIfThumbEE(n);
+        switch (encoding)
+        {
+            case eEncodingT1:
+                // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE"; 
+                // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 
+                t = Bits32 (opcode, 2, 0);
+                n = Bits32 (opcode, 5, 3);
+                m = Bits32 (opcode, 8, 6);
+                
+                // index = TRUE; add = TRUE; wback = FALSE; 
+                index = true;
+                add = true;
+                wback = false;
+                
+                // (shift_t, shift_n) = (SRType_LSL, 0);
+                shift_t = SRType_LSL;
+                shift_n = 0;
+                
+                break;
+                
+            case eEncodingT2:
+                // if Rn == '1111' then UNDEFINED; 
+                // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 
+                t = Bits32 (opcode, 15, 12);
+                n = Bits32 (opcode, 19, 16);
+                m = Bits32 (opcode, 3, 0);
+                if (n == 15)
+                    return false;
+                    
+                // index = TRUE; add = TRUE; wback = FALSE; 
+                index = true;
+                add = true;
+                wback = false;
+                
+                // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); 
+                shift_t = SRType_LSL;
+                shift_n = Bits32 (opcode, 5, 4);
+                
+                // if BadReg(t) || BadReg(m) then UNPREDICTABLE;
+                if (BadReg (t) || BadReg (m))
+                    return false;
+                    
+                break;
+                
+            case eEncodingA1:
+                // if P == '0' && W == '1' then SEE STRHT; 
+                // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 
+                t = Bits32 (opcode, 15, 12);
+                n = Bits32 (opcode, 19, 16);
+                m = Bits32 (opcode, 3, 0);
+                
+                // index = (P == '1');	add = (U == '1');	wback = (P == '0') || (W == '1'); 
+                index = BitIsSet (opcode, 24);
+                add = BitIsSet (opcode, 23);
+                wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
+                
+                // (shift_t, shift_n) = (SRType_LSL, 0); 
+                shift_t = SRType_LSL;
+                shift_n = 0;
+                
+                // if t == 15 || m == 15 then UNPREDICTABLE; 
+                if ((t == 15) || (m == 15))
+                    return false;
+                    
+                // if wback && (n == 15 || n == t) then UNPREDICTABLE;
+                if (wback && ((n == 15) || (n == t)))
+                    return false;
+                    
+                break;
+                
+            default:
+                return false;
+        }
+        
+        uint32_t Rm = ReadCoreReg (m, &success);
+        if (!success)
+            return false;
+            
+        uint32_t Rn = ReadCoreReg (n, &success);
+        if (!success)
+            return false;
+            
+        // offset = Shift(R[m], shift_t, shift_n, APSR.C); 
+        uint32_t offset = Shift (Rm, shift_t, shift_n, APSR_C, &success);
+        if (!success)
+            return false;
+        
+        // offset_addr = if add then (R[n] + offset) else (R[n] - offset); 
+        addr_t offset_addr;
+        if (add)
+            offset_addr = Rn + offset;
+        else
+            offset_addr = Rn - offset;
+            
+        // address = if index then offset_addr else R[n]; 
+        addr_t address;
+        if (index)
+            address = offset_addr;
+        else
+            address = Rn;
+            
+        EmulateInstruction::Context context;
+        context.type = eContextRegisterStore;
+        RegisterInfo base_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
+        RegisterInfo offset_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
+
+        // if UnalignedSupport() || address<0> == '0' then
+        if (UnalignedSupport() || BitIsClear (address, 0))
+        {
+            // MemU[address,2] = R[t]<15:0>; 
+            uint32_t Rt = ReadCoreReg (t, &success);
+            if (!success)
+                return false;
+             
+            EmulateInstruction::Context context;
+            context.type = eContextRegisterStore;
+            RegisterInfo base_reg;
+            GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
+            RegisterInfo offset_reg;
+            GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
+            RegisterInfo data_reg;
+            GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
+            context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg);
+            
+            if (!MemUWrite (context, address, Bits32 (Rt, 15, 0), 2))
+                return false;
+        }
+        else // Can only occur before ARMv7
+        {
+            // MemU[address,2] = bits(16) UNKNOWN; 
+        }
+            
+        // if wback then R[n] = offset_addr;
+        if (wback)
+        {
+            context.type = eContextAdjustBaseRegister;
+            context.SetAddress (offset_addr);
+            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
+                return false;
+        }
+    }
+
+    return true;
+}
+                  
+// Add with Carry (immediate) adds an immediate value and the carry flag value to a register value,
+// and writes the result to the destination register.  It can optionally update the condition flags
+// based on the result.
+bool
+EmulateInstructionARM::EmulateADCImm (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if ConditionPassed() then
+        EncodingSpecificOperations();
+        (result, carry, overflow) = AddWithCarry(R[n], imm32, APSR.C);
+        if d == 15 then         // Can only occur for ARM encoding
+            ALUWritePC(result); // setflags is always FALSE here
+        else
+            R[d] = result;
+            if setflags then
+                APSR.N = result<31>;
+                APSR.Z = IsZeroBit(result);
+                APSR.C = carry;
+                APSR.V = overflow;
+#endif
+
+    bool success = false;
+
+    if (ConditionPassed(opcode))
+    {
+        uint32_t Rd, Rn;
+        uint32_t imm32; // the immediate value to be added to the value obtained from Rn
+        bool setflags;
+        switch (encoding)
+        {
+        case eEncodingT1:
+            Rd = Bits32(opcode, 11, 8);
+            Rn = Bits32(opcode, 19, 16);
+            setflags = BitIsSet(opcode, 20);
+            imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
+            if (BadReg(Rd) || BadReg(Rn))
+                return false;
+            break;
+        case eEncodingA1:
+            Rd = Bits32(opcode, 15, 12);
+            Rn = Bits32(opcode, 19, 16);
+            setflags = BitIsSet(opcode, 20);
+            imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
+
+            if (Rd == 15 && setflags)
+                return EmulateSUBSPcLrEtc (opcode, encoding);
+            break;
+        default:
+            return false;
+        }
+
+        // Read the first operand.
+        int32_t val1 = ReadCoreReg(Rn, &success);
+        if (!success)
+            return false;
+
+        AddWithCarryResult res = AddWithCarry(val1, imm32, APSR_C);
+
+        EmulateInstruction::Context context;
+        context.type = EmulateInstruction::eContextImmediate;
+        context.SetNoArgs ();
+
+        if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
+            return false;
+    }
+    return true;
+}
+
+// Add with Carry (register) adds a register value, the carry flag value, and an optionally-shifted
+// register value, and writes the result to the destination register.  It can optionally update the
+// condition flags based on the result.
+bool
+EmulateInstructionARM::EmulateADCReg (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if ConditionPassed() then
+        EncodingSpecificOperations();
+        shifted = Shift(R[m], shift_t, shift_n, APSR.C);
+        (result, carry, overflow) = AddWithCarry(R[n], shifted, APSR.C);
+        if d == 15 then         // Can only occur for ARM encoding
+            ALUWritePC(result); // setflags is always FALSE here
+        else
+            R[d] = result;
+            if setflags then
+                APSR.N = result<31>;
+                APSR.Z = IsZeroBit(result);
+                APSR.C = carry;
+                APSR.V = overflow;
+#endif
+
+    bool success = false;
+
+    if (ConditionPassed(opcode))
+    {
+        uint32_t Rd, Rn, Rm;
+        ARM_ShifterType shift_t;
+        uint32_t shift_n; // the shift applied to the value read from Rm
+        bool setflags;
+        switch (encoding)
+        {
+        case eEncodingT1:
+            Rd = Rn = Bits32(opcode, 2, 0);
+            Rm = Bits32(opcode, 5, 3);
+            setflags = !InITBlock();
+            shift_t = SRType_LSL;
+            shift_n = 0;
+            break;
+        case eEncodingT2:
+            Rd = Bits32(opcode, 11, 8);
+            Rn = Bits32(opcode, 19, 16);
+            Rm = Bits32(opcode, 3, 0);
+            setflags = BitIsSet(opcode, 20);
+            shift_n = DecodeImmShiftThumb(opcode, shift_t);
+            if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
+                return false;
+            break;
+        case eEncodingA1:
+            Rd = Bits32(opcode, 15, 12);
+            Rn = Bits32(opcode, 19, 16);
+            Rm = Bits32(opcode, 3, 0);
+            setflags = BitIsSet(opcode, 20);
+            shift_n = DecodeImmShiftARM(opcode, shift_t);
+
+            if (Rd == 15 && setflags)
+                return EmulateSUBSPcLrEtc (opcode, encoding);
+            break;
+        default:
+            return false;
+        }
+
+        // Read the first operand.
+        int32_t val1 = ReadCoreReg(Rn, &success);
+        if (!success)
+            return false;
+
+        // Read the second operand.
+        int32_t val2 = ReadCoreReg(Rm, &success);
+        if (!success)
+            return false;
+
+        uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
+        if (!success)
+            return false;
+        AddWithCarryResult res = AddWithCarry(val1, shifted, APSR_C);
+
+        EmulateInstruction::Context context;
+        context.type = EmulateInstruction::eContextImmediate;
+        context.SetNoArgs ();
+
+        if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
+            return false;
+    }
+    return true;
+}
+
+// This instruction adds an immediate value to the PC value to form a PC-relative address,
+// and writes the result to the destination register.
+bool
+EmulateInstructionARM::EmulateADR (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if ConditionPassed() then
+        EncodingSpecificOperations();
+        result = if add then (Align(PC,4) + imm32) else (Align(PC,4) - imm32);
+        if d == 15 then         // Can only occur for ARM encodings
+            ALUWritePC(result);
+        else
+            R[d] = result;
+#endif
+
+    bool success = false;
+
+    if (ConditionPassed(opcode))
+    {
+        uint32_t Rd;
+        uint32_t imm32; // the immediate value to be added/subtracted to/from the PC
+        bool add;
+        switch (encoding)
+        {
+        case eEncodingT1:
+            Rd = Bits32(opcode, 10, 8);
+            imm32 = ThumbImm8Scaled(opcode); // imm32 = ZeroExtend(imm8:'00', 32)
+            add = true;
+            break;
+        case eEncodingT2:
+        case eEncodingT3:
+            Rd = Bits32(opcode, 11, 8);
+            imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
+            add = (Bits32(opcode, 24, 21) == 0); // 0b0000 => ADD; 0b0101 => SUB
+            if (BadReg(Rd))
+                return false;
+            break;
+        case eEncodingA1:
+        case eEncodingA2:
+            Rd = Bits32(opcode, 15, 12);
+            imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
+            add = (Bits32(opcode, 24, 21) == 0x4); // 0b0100 => ADD; 0b0010 => SUB
+            break;
+        default:
+            return false;
+        }
+
+        // Read the PC value.
+        uint32_t pc = ReadCoreReg(PC_REG, &success);
+        if (!success)
+            return false;
+
+        uint32_t result = (add ? Align(pc, 4) + imm32 : Align(pc, 4) - imm32);
+
+        EmulateInstruction::Context context;
+        context.type = EmulateInstruction::eContextImmediate;
+        context.SetNoArgs ();
+
+        if (!WriteCoreReg(context, result, Rd))
+            return false;
+    }
+    return true;
+}
+
+// This instruction performs a bitwise AND of a register value and an immediate value, and writes the result
+// to the destination register.  It can optionally update the condition flags based on the result.
+bool
+EmulateInstructionARM::EmulateANDImm (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if ConditionPassed() then
+        EncodingSpecificOperations();
+        result = R[n] AND imm32;
+        if d == 15 then         // Can only occur for ARM encoding
+            ALUWritePC(result); // setflags is always FALSE here
+        else
+            R[d] = result;
+            if setflags then
+                APSR.N = result<31>;
+                APSR.Z = IsZeroBit(result);
+                APSR.C = carry;
+                // APSR.V unchanged
+#endif
+
+    bool success = false;
+
+    if (ConditionPassed(opcode))
+    {
+        uint32_t Rd, Rn;
+        uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
+        bool setflags;
+        uint32_t carry; // the carry bit after ARM/Thumb Expand operation
+        switch (encoding)
+        {
+        case eEncodingT1:
+            Rd = Bits32(opcode, 11, 8);
+            Rn = Bits32(opcode, 19, 16);
+            setflags = BitIsSet(opcode, 20);
+            imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
+            // if Rd == '1111' && S == '1' then SEE TST (immediate);
+            if (Rd == 15 && setflags)
+                return EmulateTSTImm(opcode, eEncodingT1);
+            if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
+                return false;
+            break;
+        case eEncodingA1:
+            Rd = Bits32(opcode, 15, 12);
+            Rn = Bits32(opcode, 19, 16);
+            setflags = BitIsSet(opcode, 20);
+            imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
+ 
+            if (Rd == 15 && setflags)
+                return EmulateSUBSPcLrEtc (opcode, encoding);
+            break;
+        default:
+            return false;
+        }
+
+        // Read the first operand.
+        uint32_t val1 = ReadCoreReg(Rn, &success);
+        if (!success)
+            return false;
+
+        uint32_t result = val1 & imm32;
+
+        EmulateInstruction::Context context;
+        context.type = EmulateInstruction::eContextImmediate;
+        context.SetNoArgs ();
+
+        if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
+            return false;
+    }
+    return true;
+}
+
+// This instruction performs a bitwise AND of a register value and an optionally-shifted register value,
+// and writes the result to the destination register.  It can optionally update the condition flags
+// based on the result.
+bool
+EmulateInstructionARM::EmulateANDReg (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if ConditionPassed() then
+        EncodingSpecificOperations();
+        (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
+        result = R[n] AND shifted;
+        if d == 15 then         // Can only occur for ARM encoding
+            ALUWritePC(result); // setflags is always FALSE here
+        else
+            R[d] = result;
+            if setflags then
+                APSR.N = result<31>;
+                APSR.Z = IsZeroBit(result);
+                APSR.C = carry;
+                // APSR.V unchanged
+#endif
+
+    bool success = false;
+
+    if (ConditionPassed(opcode))
+    {
+        uint32_t Rd, Rn, Rm;
+        ARM_ShifterType shift_t;
+        uint32_t shift_n; // the shift applied to the value read from Rm
+        bool setflags;
+        uint32_t carry;
+        switch (encoding)
+        {
+        case eEncodingT1:
+            Rd = Rn = Bits32(opcode, 2, 0);
+            Rm = Bits32(opcode, 5, 3);
+            setflags = !InITBlock();
+            shift_t = SRType_LSL;
+            shift_n = 0;
+            break;
+        case eEncodingT2:
+            Rd = Bits32(opcode, 11, 8);
+            Rn = Bits32(opcode, 19, 16);
+            Rm = Bits32(opcode, 3, 0);
+            setflags = BitIsSet(opcode, 20);
+            shift_n = DecodeImmShiftThumb(opcode, shift_t);
+            // if Rd == '1111' && S == '1' then SEE TST (register);
+            if (Rd == 15 && setflags)
+                return EmulateTSTReg(opcode, eEncodingT2);
+            if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
+                return false;
+            break;
+        case eEncodingA1:
+            Rd = Bits32(opcode, 15, 12);
+            Rn = Bits32(opcode, 19, 16);
+            Rm = Bits32(opcode, 3, 0);
+            setflags = BitIsSet(opcode, 20);
+            shift_n = DecodeImmShiftARM(opcode, shift_t);
+
+            if (Rd == 15 && setflags)
+                return EmulateSUBSPcLrEtc (opcode, encoding);
+            break;
+        default:
+            return false;
+        }
+
+        // Read the first operand.
+        uint32_t val1 = ReadCoreReg(Rn, &success);
+        if (!success)
+            return false;
+
+        // Read the second operand.
+        uint32_t val2 = ReadCoreReg(Rm, &success);
+        if (!success)
+            return false;
+
+        uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
+        if (!success)
+            return false;
+        uint32_t result = val1 & shifted;
+
+        EmulateInstruction::Context context;
+        context.type = EmulateInstruction::eContextImmediate;
+        context.SetNoArgs ();
+
+        if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
+            return false;
+    }
+    return true;
+}
+
+// Bitwise Bit Clear (immediate) performs a bitwise AND of a register value and the complement of an
+// immediate value, and writes the result to the destination register.  It can optionally update the
+// condition flags based on the result.
+bool
+EmulateInstructionARM::EmulateBICImm (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if ConditionPassed() then
+        EncodingSpecificOperations();
+        result = R[n] AND NOT(imm32);
+        if d == 15 then         // Can only occur for ARM encoding
+            ALUWritePC(result); // setflags is always FALSE here
+        else
+            R[d] = result;
+            if setflags then
+                APSR.N = result<31>;
+                APSR.Z = IsZeroBit(result);
+                APSR.C = carry;
+                // APSR.V unchanged
+#endif
+
+    bool success = false;
+
+    if (ConditionPassed(opcode))
+    {
+        uint32_t Rd, Rn;
+        uint32_t imm32; // the immediate value to be bitwise inverted and ANDed to the value obtained from Rn
+        bool setflags;
+        uint32_t carry; // the carry bit after ARM/Thumb Expand operation
+        switch (encoding)
+        {
+        case eEncodingT1:
+            Rd = Bits32(opcode, 11, 8);
+            Rn = Bits32(opcode, 19, 16);
+            setflags = BitIsSet(opcode, 20);
+            imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
+            if (BadReg(Rd) || BadReg(Rn))
+                return false;
+            break;
+        case eEncodingA1:
+            Rd = Bits32(opcode, 15, 12);
+            Rn = Bits32(opcode, 19, 16);
+            setflags = BitIsSet(opcode, 20);
+            imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
+
+            // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
+            if (Rd == 15 && setflags)
+                return EmulateSUBSPcLrEtc (opcode, encoding);
+            break;
+        default:
+            return false;
+        }
+
+        // Read the first operand.
+        uint32_t val1 = ReadCoreReg(Rn, &success);
+        if (!success)
+            return false;
+
+        uint32_t result = val1 & ~imm32;
+
+        EmulateInstruction::Context context;
+        context.type = EmulateInstruction::eContextImmediate;
+        context.SetNoArgs ();
+
+        if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
+            return false;
+    }
+    return true;
+}
+
+// Bitwise Bit Clear (register) performs a bitwise AND of a register value and the complement of an
+// optionally-shifted register value, and writes the result to the destination register.
+// It can optionally update the condition flags based on the result.
+bool
+EmulateInstructionARM::EmulateBICReg (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if ConditionPassed() then
+        EncodingSpecificOperations();
+        (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
+        result = R[n] AND NOT(shifted);
+        if d == 15 then         // Can only occur for ARM encoding
+            ALUWritePC(result); // setflags is always FALSE here
+        else
+            R[d] = result;
+            if setflags then
+                APSR.N = result<31>;
+                APSR.Z = IsZeroBit(result);
+                APSR.C = carry;
+                // APSR.V unchanged
+#endif
+
+    bool success = false;
+
+    if (ConditionPassed(opcode))
+    {
+        uint32_t Rd, Rn, Rm;
+        ARM_ShifterType shift_t;
+        uint32_t shift_n; // the shift applied to the value read from Rm
+        bool setflags;
+        uint32_t carry;
+        switch (encoding)
+        {
+        case eEncodingT1:
+            Rd = Rn = Bits32(opcode, 2, 0);
+            Rm = Bits32(opcode, 5, 3);
+            setflags = !InITBlock();
+            shift_t = SRType_LSL;
+            shift_n = 0;
+            break;
+        case eEncodingT2:
+            Rd = Bits32(opcode, 11, 8);
+            Rn = Bits32(opcode, 19, 16);
+            Rm = Bits32(opcode, 3, 0);
+            setflags = BitIsSet(opcode, 20);
+            shift_n = DecodeImmShiftThumb(opcode, shift_t);
+            if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
+                return false;
+            break;
+        case eEncodingA1:
+            Rd = Bits32(opcode, 15, 12);
+            Rn = Bits32(opcode, 19, 16);
+            Rm = Bits32(opcode, 3, 0);
+            setflags = BitIsSet(opcode, 20);
+            shift_n = DecodeImmShiftARM(opcode, shift_t);
+
+            // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
+            if (Rd == 15 && setflags)
+                return EmulateSUBSPcLrEtc (opcode, encoding);
+            break;
+        default:
+            return false;
+        }
+
+        // Read the first operand.
+        uint32_t val1 = ReadCoreReg(Rn, &success);
+        if (!success)
+            return false;
+
+        // Read the second operand.
+        uint32_t val2 = ReadCoreReg(Rm, &success);
+        if (!success)
+            return false;
+
+        uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
+        if (!success)
+            return false;
+        uint32_t result = val1 & ~shifted;
+
+        EmulateInstruction::Context context;
+        context.type = EmulateInstruction::eContextImmediate;
+        context.SetNoArgs ();
+
+        if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
+            return false;
+    }
+    return true;
+}
+
+// LDR (immediate, ARM) calculates an address from a base register value and an immediate offset, loads a word 
+// from memory, and writes it to a register.  It can use offset, post-indexed, or pre-indexed addressing.
+bool
+EmulateInstructionARM::EmulateLDRImmediateARM (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    if ConditionPassed() then 
+        EncodingSpecificOperations(); 
+        offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 
+        address = if index then offset_addr else R[n]; 
+        data = MemU[address,4]; 
+        if wback then R[n] = offset_addr; 
+        if t == 15 then
+            if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE; 
+        elsif UnalignedSupport() || address<1:0> = '00' then
+            R[t] = data; 
+        else // Can only apply before ARMv7
+            R[t] = ROR(data, 8*UInt(address<1:0>));
+#endif
+                  
+    bool success = false;
+                
+    if (ConditionPassed(opcode))
+    {
+        const uint32_t addr_byte_size = GetAddressByteSize();
+                  
+        uint32_t t;
+        uint32_t n;
+        uint32_t imm32;
+        bool index;
+        bool add;
+        bool wback;
+                  
+        switch (encoding)
+        {
+            case eEncodingA1:
+                // if Rn == '1111' then SEE LDR (literal);
+                // if P == '0' && W == '1' then SEE LDRT; 
+                // if Rn == '1101' && P == '0' && U == '1' && W == '0' && imm12 == '000000000100' then SEE POP; 
+                // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 
+                t = Bits32 (opcode, 15, 12);
+                n = Bits32 (opcode, 19, 16);
+                imm32 = Bits32 (opcode, 11, 0);
+                  
+                // index = (P == '1');	add = (U == '1');	wback = (P == '0') || (W == '1');
+                index = BitIsSet (opcode, 24);
+                add = BitIsSet (opcode, 23);
+                wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
+                  
+                // if wback && n == t then UNPREDICTABLE;
+                if (wback && (n == t))
+                    return false;
+                  
+                break;
+                  
+            default:
+                return false;
+        }
+               
+        addr_t address;
+        addr_t offset_addr;
+        addr_t base_address = ReadCoreReg (n, &success);
+        if (!success)
+            return false;
+                  
+        // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 
+        if (add)
+            offset_addr = base_address + imm32;
+        else
+            offset_addr = base_address - imm32;
+                  
+        // address = if index then offset_addr else R[n]; 
+        if (index)
+            address = offset_addr;
+        else
+            address = base_address;
+                  
+        // data = MemU[address,4]; 
+                  
+        RegisterInfo base_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
+                 
+        EmulateInstruction::Context context;
+        context.type = eContextRegisterLoad;
+        context.SetRegisterPlusOffset (base_reg, address - base_address);
+                  
+        uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
+        if (!success)
+            return false;
+                  
+        // if wback then R[n] = offset_addr; 
+        if (wback)
+        {
+            context.type = eContextAdjustBaseRegister;
+            context.SetAddress (offset_addr);
+            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
+                return false;
+        }
+                  
+        // if t == 15 then
+        if (t == 15)
+        {
+            // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE; 
+            if (BitIsClear (address, 1) && BitIsClear (address, 0))
+            {
+                // LoadWritePC (data);
+                context.type = eContextRegisterLoad;
+                context.SetRegisterPlusOffset (base_reg, address - base_address);
+                LoadWritePC (context, data);
+            }
+            else
+                  return false;
+        }
+        // elsif UnalignedSupport() || address<1:0> = '00' then
+        else if (UnalignedSupport() || (BitIsClear (address, 1) && BitIsClear (address, 0)))
+        {
+            // R[t] = data; 
+            context.type = eContextRegisterLoad;
+            context.SetRegisterPlusOffset (base_reg, address - base_address);
+            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
+                return false;
+        }
+        // else // Can only apply before ARMv7
+        else
+        {
+            // R[t] = ROR(data, 8*UInt(address<1:0>));
+            data = ROR (data, Bits32 (address, 1, 0), &success);
+            if (!success)
+                return false;
+            context.type = eContextRegisterLoad;
+            context.SetImmediate (data);
+            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
+                return false;
+        }
+
+    }
+    return true;
+}
+                  
+// LDR (register) calculates an address from a base register value and an offset register value, loads a word 
+// from memory, and writes it to a resgister.  The offset register value can optionally be shifted.  
+bool
+EmulateInstructionARM::EmulateLDRRegister (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    if ConditionPassed() then 
+        EncodingSpecificOperations(); NullCheckIfThumbEE(n); 
+        offset = Shift(R[m], shift_t, shift_n, APSR.C); 
+        offset_addr = if add then (R[n] + offset) else (R[n] - offset); 
+        address = if index then offset_addr else R[n]; 
+        data = MemU[address,4]; 
+        if wback then R[n] = offset_addr; 
+        if t == 15 then
+            if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE; 
+        elsif UnalignedSupport() || address<1:0> = '00' then
+            R[t] = data; 
+        else // Can only apply before ARMv7
+            if CurrentInstrSet() == InstrSet_ARM then 
+                R[t] = ROR(data, 8*UInt(address<1:0>));
+            else 
+                R[t] = bits(32) UNKNOWN;
+#endif
+                  
+    bool success = false;
+                  
+    if (ConditionPassed(opcode))
+    {
+        const uint32_t addr_byte_size = GetAddressByteSize();
+                  
+        uint32_t t;
+        uint32_t n;
+        uint32_t m;
+        bool index;
+        bool add;
+        bool wback;
+        ARM_ShifterType shift_t;
+        uint32_t shift_n;
+                  
+        switch (encoding)
+        {
+            case eEncodingT1:
+                // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE"; 
+                // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 
+                t = Bits32 (opcode, 2, 0);
+                n = Bits32 (opcode, 5, 3);
+                m = Bits32 (opcode, 8, 6);
+                  
+                // index = TRUE; add = TRUE; wback = FALSE;
+                index = true;
+                add = true;
+                wback = false;
+                  
+                // (shift_t, shift_n) = (SRType_LSL, 0);
+                shift_t = SRType_LSL;
+                shift_n = 0;
+                  
+                break;
+                  
+            case eEncodingT2:
+                // if Rn == '1111' then SEE LDR (literal);
+                // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
+                t = Bits32 (opcode, 15, 12);
+                n = Bits32 (opcode, 19, 16);
+                m = Bits32 (opcode, 3, 0);
+                  
+                // index = TRUE; add = TRUE; wback = FALSE; 
+                index = true;
+                add = true;
+                wback = false;
+                  
+                // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); 
+                shift_t = SRType_LSL;
+                shift_n = Bits32 (opcode, 5, 4);
+                  
+                // if BadReg(m) then UNPREDICTABLE; 
+                if (BadReg (m))
+                    return false;
+                  
+                // if t == 15 && InITBlock() && !LastInITBlock() then UNPREDICTABLE;
+                if ((t == 15) && InITBlock() && !LastInITBlock())
+                    return false;
+                  
+                break;
+                  
+            case eEncodingA1:
+            {
+                // if P == '0' && W == '1' then SEE LDRT; 
+                // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
+                t = Bits32 (opcode, 15, 12);
+                n = Bits32 (opcode, 19, 16);
+                m = Bits32 (opcode, 3, 0);
+                  
+                // index = (P == '1');	add = (U == '1');	wback = (P == '0') || (W == '1'); 
+                index = BitIsSet (opcode, 24);
+                add = BitIsSet (opcode, 23);
+                wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
+                  
+                // (shift_t, shift_n) = DecodeImmShift(type, imm5); 
+                uint32_t type = Bits32 (opcode, 6, 5);
+                uint32_t imm5 = Bits32 (opcode, 11, 7);
+                shift_n = DecodeImmShift (type, imm5, shift_t);
+                  
+                // if m == 15 then UNPREDICTABLE; 
+                if (m == 15)
+                    return false;
+                  
+                // if wback && (n == 15 || n == t) then UNPREDICTABLE;
+                if (wback && ((n == 15) || (n == t)))
+                    return false;
+            }
+                break;
+                  
+                  
+            default:
+                return false;
+        }
+         
+        uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
+        if (!success)
+            return false;
+                  
+        uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
+        if (!success)
+            return false;
+            
+        addr_t offset_addr;
+        addr_t address;
+                  
+        // offset = Shift(R[m], shift_t, shift_n, APSR.C);   -- Note "The APSR is an application level alias for the CPSR".
+        addr_t offset = Shift (Rm, shift_t, shift_n, Bit32 (m_opcode_cpsr, APSR_C), &success);
+        if (!success)
+            return false;
+                  
+        // offset_addr = if add then (R[n] + offset) else (R[n] - offset); 
+        if (add)
+            offset_addr = Rn + offset;
+        else
+            offset_addr = Rn - offset;
+                  
+        // address = if index then offset_addr else R[n]; 
+            if (index)
+                address = offset_addr;
+            else
+                address = Rn;
+                  
+        // data = MemU[address,4]; 
+        RegisterInfo base_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
+                  
+        EmulateInstruction::Context context;
+        context.type = eContextRegisterLoad;
+        context.SetRegisterPlusOffset (base_reg, address - Rn);
+                  
+        uint64_t data = MemURead (context, address, addr_byte_size, 0, &success);
+        if (!success)
+            return false;
+                  
+        // if wback then R[n] = offset_addr; 
+        if (wback)
+        {
+            context.type = eContextAdjustBaseRegister;
+            context.SetAddress (offset_addr);
+            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
+                return false;
+        }
+            
+        // if t == 15 then
+        if (t == 15)
+        {
+            // if address<1:0> == '00' then LoadWritePC(data); else UNPREDICTABLE;
+            if (BitIsClear (address, 1) && BitIsClear (address, 0))
+            {
+                context.type = eContextRegisterLoad;
+                context.SetRegisterPlusOffset (base_reg, address - Rn);
+                LoadWritePC (context, data);
+            }
+            else
+                return false;
+        }
+        // elsif UnalignedSupport() || address<1:0> = '00' then
+        else if (UnalignedSupport () || (BitIsClear (address, 1) && BitIsClear (address, 0)))
+        {
+            // R[t] = data; 
+            context.type = eContextRegisterLoad;
+            context.SetRegisterPlusOffset (base_reg, address - Rn);
+            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
+                return false;
+        }
+        else // Can only apply before ARMv7
+        {
+            // if CurrentInstrSet() == InstrSet_ARM then 
+            if (CurrentInstrSet () == eModeARM)
+            {
+                // R[t] = ROR(data, 8*UInt(address<1:0>));
+                data = ROR (data, Bits32 (address, 1, 0), &success);
+                if (!success)
+                    return false;
+                context.type = eContextRegisterLoad;
+                context.SetImmediate (data);
+                if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
+                    return false;
+            }
+            else
+            {
+                // R[t] = bits(32) UNKNOWN;
+                WriteBits32Unknown (t);
+            }
+        }
+    }
+    return true;
+}
+
+// LDRB (immediate, Thumb)
+bool
+EmulateInstructionARM::EmulateLDRBImmediate (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    if ConditionPassed() then 
+        EncodingSpecificOperations(); NullCheckIfThumbEE(n); 
+        offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 
+        address = if index then offset_addr else R[n]; 
+        R[t] = ZeroExtend(MemU[address,1], 32); 
+        if wback then R[n] = offset_addr;
+#endif
+                  
+    bool success = false;
+                  
+    if (ConditionPassed(opcode))
+    {
+        uint32_t t;
+        uint32_t n;
+        uint32_t imm32;
+        bool index;
+        bool add;
+        bool wback;
+                  
+        // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 
+        switch (encoding)
+        {
+            case eEncodingT1:
+                // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5, 32); 
+                t = Bits32 (opcode, 2, 0);
+                n = Bits32 (opcode, 5, 3);
+                imm32 = Bits32 (opcode, 10, 6);
+                  
+                // index = TRUE; add = TRUE; wback = FALSE;
+                index = true;
+                add = true;
+                wback= false;
+                  
+                break;
+                  
+            case eEncodingT2:
+                // if Rt == '1111' then SEE PLD; 
+                // if Rn == '1111' then SEE LDRB (literal); 
+                // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 
+                t = Bits32 (opcode, 15, 12);
+                n = Bits32 (opcode, 19, 16);
+                imm32 = Bits32 (opcode, 11, 0);
+                  
+                // index = TRUE; add = TRUE; wback = FALSE; 
+                index = true;
+                add = true;
+                wback = false;
+                  
+                // if t == 13 then UNPREDICTABLE;
+                if (t == 13)
+                    return false;
+                  
+                break;
+                  
+            case eEncodingT3:
+                // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLD; 
+                // if Rn == '1111' then SEE LDRB (literal); 
+                // if P == '1' && U == '1' && W == '0' then SEE LDRBT; 
+                // if P == '0' && W == '0' then UNDEFINED;
+                if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
+                    return false;
+                  
+                  // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32);
+                t = Bits32 (opcode, 15, 12);
+                n = Bits32 (opcode, 19, 16);
+                imm32 = Bits32 (opcode, 7, 0);
+                  
+                // index = (P == '1'); add = (U == '1'); wback = (W == '1'); 
+                index = BitIsSet (opcode, 10);
+                add = BitIsSet (opcode, 9);
+                wback = BitIsSet (opcode, 8);
+                  
+                // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
+                if (BadReg (t) || (wback && (n == t)))
+                    return false;
+                  
+                break;
+                  
+            default:
+                return false;
+        }
+                  
+        uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
+        if (!success)
+            return false;
+                  
+        addr_t address;
+        addr_t offset_addr;
+                  
+        // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 
+        if (add)
+            offset_addr = Rn + imm32;
+        else
+            offset_addr = Rn - imm32;
+                  
+        // address = if index then offset_addr else R[n]; 
+        if (index)
+            address = offset_addr;
+        else
+            address = Rn;
+                  
+        // R[t] = ZeroExtend(MemU[address,1], 32); 
+        RegisterInfo base_reg;
+        RegisterInfo data_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
+                  
+        EmulateInstruction::Context context;
+        context.type = eContextRegisterLoad;
+        context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
+                  
+        uint64_t data = MemURead (context, address, 1, 0, &success);
+        if (!success)
+            return false;
+            
+        if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
+            return false;
+                  
+        // if wback then R[n] = offset_addr;
+        if (wback)
+        {
+            context.type = eContextAdjustBaseRegister;
+            context.SetAddress (offset_addr);
+            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
+                return false;
+        }
+    }
+    return true;
+}
+                
+// LDRB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory, 
+// zero-extends it to form a 32-bit word and writes it to a register.
+bool
+EmulateInstructionARM::EmulateLDRBLiteral (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    if ConditionPassed() then 
+        EncodingSpecificOperations(); NullCheckIfThumbEE(15); 
+        base = Align(PC,4); 
+        address = if add then (base + imm32) else (base - imm32); 
+        R[t] = ZeroExtend(MemU[address,1], 32);
+#endif
+                  
+    bool success = false;
+                  
+    if (ConditionPassed(opcode))
+    {
+        uint32_t t;
+        uint32_t imm32;
+        bool add;
+        switch (encoding)
+        {
+            case eEncodingT1:
+                // if Rt == '1111' then SEE PLD; 
+                // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1'); 
+                t = Bits32 (opcode, 15, 12);
+                imm32 = Bits32 (opcode, 11, 0);
+                add = BitIsSet (opcode, 23);
+                  
+                // if t == 13 then UNPREDICTABLE;
+                if (t == 13)
+                    return false;
+                  
+                break;
+                  
+            case eEncodingA1:
+                // t == UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1'); 
+                t = Bits32 (opcode, 15, 12);
+                imm32 = Bits32 (opcode, 11, 0);
+                add = BitIsSet (opcode, 23);
+                  
+                // if t == 15 then UNPREDICTABLE;
+                if (t == 15)
+                    return false;
+                break;
+                  
+            default:
+                return false;
+        }
+                  
+        // base = Align(PC,4); 
+        uint32_t pc_val = ReadCoreReg (PC_REG, &success);
+        if (!success)
+            return false;
+                  
+        uint32_t base = AlignPC (pc_val);
+                  
+        addr_t address;
+        // address = if add then (base + imm32) else (base - imm32); 
+        if (add)
+            address = base + imm32;
+        else
+            address = base - imm32;
+                  
+        // R[t] = ZeroExtend(MemU[address,1], 32);
+        EmulateInstruction::Context context;
+        context.type = eContextRelativeBranchImmediate;
+        context.SetImmediate (address - base);
+                  
+        uint64_t data = MemURead (context, address, 1, 0, &success);
+        if (!success)
+            return false;
+                  
+        if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
+            return false;
+    }
+    return true;
+}
+  
+// LDRB (register) calculates an address from a base register value and an offset rigister value, loads a byte from
+// memory, zero-extends it to form a 32-bit word, and writes it to a register.  The offset register value can 
+// optionally be shifted.
+bool
+EmulateInstructionARM::EmulateLDRBRegister (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    if ConditionPassed() then 
+        EncodingSpecificOperations(); NullCheckIfThumbEE(n); 
+        offset = Shift(R[m], shift_t, shift_n, APSR.C); 
+        offset_addr = if add then (R[n] + offset) else (R[n] - offset); 
+        address = if index then offset_addr else R[n]; 
+        R[t] = ZeroExtend(MemU[address,1],32); 
+        if wback then R[n] = offset_addr;
+#endif
+                  
+    bool success = false;
+                
+    if (ConditionPassed(opcode))
+    {
+        uint32_t t;
+        uint32_t n;
+        uint32_t m;
+        bool index;
+        bool add;
+        bool wback;
+        ARM_ShifterType shift_t;
+        uint32_t shift_n;
+
+        // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 
+        switch (encoding)
+        {
+            case eEncodingT1:
+                // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 
+                t = Bits32 (opcode, 2, 0);
+                n = Bits32 (opcode, 5, 3);
+                m = Bits32 (opcode, 8, 6);
+                  
+                // index = TRUE; add = TRUE; wback = FALSE; 
+                index = true;
+                add = true;
+                wback = false;
+                  
+                // (shift_t, shift_n) = (SRType_LSL, 0);
+                shift_t = SRType_LSL;
+                shift_n = 0;
+                break;
+                  
+            case eEncodingT2:
+                // if Rt == '1111' then SEE PLD; 
+                // if Rn == '1111' then SEE LDRB (literal); 
+                // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 
+                t = Bits32 (opcode, 15, 12);
+                n = Bits32 (opcode, 19, 16);
+                m = Bits32 (opcode, 3, 0);
+                  
+                // index = TRUE; add = TRUE; wback = FALSE; 
+                index = true;
+                add = true;
+                wback = false;
+                  
+                // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); 
+                shift_t = SRType_LSL;
+                shift_n = Bits32 (opcode, 5, 4);
+                  
+                // if t == 13 || BadReg(m) then UNPREDICTABLE;
+                if ((t == 13) || BadReg (m))
+                    return false;
+                break;
+                  
+            case eEncodingA1:
+            {
+                // if P == '0' && W == '1' then SEE LDRBT; 
+                // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 
+                t = Bits32 (opcode, 15, 12);
+                n = Bits32 (opcode, 19, 16);
+                m = Bits32 (opcode, 3, 0);
+                  
+                // index = (P == '1');	add = (U == '1');	wback = (P == '0') || (W == '1'); 
+                index = BitIsSet (opcode, 24);
+                add = BitIsSet (opcode, 23);
+                wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
+                  
+                // (shift_t, shift_n) = DecodeImmShift(type, imm5); 
+                uint32_t type = Bits32 (opcode, 6, 5);
+                uint32_t imm5 = Bits32 (opcode, 11, 7);
+                shift_n = DecodeImmShift (type, imm5, shift_t);
+                  
+                // if t == 15 || m == 15 then UNPREDICTABLE; 
+                if ((t == 15) || (m == 15))
+                    return false;
+                  
+                // if wback && (n == 15 || n == t) then UNPREDICTABLE;
+                if (wback && ((n == 15) || (n == t)))
+                    return false;
+            }
+                break;
+                  
+            default:
+                return false;
+        }
+        
+        addr_t offset_addr;
+        addr_t address;
+        
+        // offset = Shift(R[m], shift_t, shift_n, APSR.C); 
+        uint32_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
+        if (!success)
+            return false;
+                  
+        addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C, &success);
+        if (!success)
+            return false;
+                  
+        // offset_addr = if add then (R[n] + offset) else (R[n] - offset); 
+        uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
+        if (!success)
+            return false;
+                  
+        if (add)
+            offset_addr = Rn + offset;
+        else
+            offset_addr = Rn - offset;
+                  
+        // address = if index then offset_addr else R[n]; 
+        if (index)
+            address = offset_addr;
+        else
+            address = Rn;
+                  
+        // R[t] = ZeroExtend(MemU[address,1],32); 
+        RegisterInfo base_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
+        
+        EmulateInstruction::Context context;
+        context.type = eContextRegisterLoad;
+        context.SetRegisterPlusOffset (base_reg, address - Rn);
+                  
+        uint64_t data = MemURead (context, address, 1, 0, &success);
+        if (!success)
+            return false;
+                  
+        if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
+            return false;
+                  
+        // if wback then R[n] = offset_addr;
+        if (wback)
+        {
+            context.type = eContextAdjustBaseRegister;
+            context.SetAddress (offset_addr);
+            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
+                return false;
+        }
+    }
+    return true;
+}
+ 
+// LDRH (immediate, Thumb) calculates an address from a base register value and an immediate offset, loads a 
+// halfword from memory, zero-extends it to form a 32-bit word, and writes it to a register.  It can use offset, 
+// post-indexed, or pre-indexed addressing.
+bool
+EmulateInstructionARM::EmulateLDRHImmediate (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    if ConditionPassed() then 
+        EncodingSpecificOperations(); NullCheckIfThumbEE(n); 
+        offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 
+        address = if index then offset_addr else R[n]; 
+        data = MemU[address,2]; 
+        if wback then R[n] = offset_addr; 
+        if UnalignedSupport() || address<0> = '0' then
+            R[t] = ZeroExtend(data, 32); 
+        else // Can only apply before ARMv7
+            R[t] = bits(32) UNKNOWN;
+#endif
+                  
+                  
+    bool success = false;
+                  
+    if (ConditionPassed(opcode))
+    {
+        uint32_t t;
+        uint32_t n;
+        uint32_t imm32;
+        bool index;
+        bool add;
+        bool wback;
+                  
+        // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 
+        switch (encoding)
+        {
+            case eEncodingT1:
+                // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm5:'0', 32);
+                t = Bits32 (opcode, 2, 0);
+                n = Bits32 (opcode, 5, 3);
+                imm32 = Bits32 (opcode, 10, 6) << 1;
+                  
+                // index = TRUE; add = TRUE; wback = FALSE;
+                index = true;
+                add = true;
+                wback = false;
+                  
+                break;
+                  
+            case eEncodingT2:
+                // if Rt == '1111' then SEE "Unallocated memory hints"; 
+                // if Rn == '1111' then SEE LDRH (literal); 
+                // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 
+                t = Bits32 (opcode, 15, 12);
+                n = Bits32 (opcode, 19, 16);
+                imm32 = Bits32 (opcode, 11, 0);
+                  
+                // index = TRUE; add = TRUE; wback = FALSE; 
+                index = true;
+                add = true;
+                wback = false;
+                  
+                // if t == 13 then UNPREDICTABLE;
+                if (t == 13)
+                    return false;
+                break;
+                  
+            case eEncodingT3:
+                // if Rn == '1111' then SEE LDRH (literal); 
+                // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE "Unallocated memory hints"; 
+                // if P == '1' && U == '1' && W == '0' then SEE LDRHT; 
+                // if P == '0' && W == '0' then UNDEFINED; 
+                if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
+                    return false;
+                  
+                // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); 
+                t = Bits32 (opcode, 15, 12);
+                n = Bits32 (opcode, 19, 16);
+                imm32 = Bits32 (opcode, 7, 0);
+                  
+                // index = (P == '1'); add = (U == '1'); wback = (W == '1'); 
+                index = BitIsSet (opcode, 10);
+                add = BitIsSet (opcode, 9);
+                wback = BitIsSet (opcode, 8);
+                  
+                // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
+                if (BadReg (t) || (wback && (n == t)))
+                    return false;
+                break;
+                  
+            default:
+                return false;
+        }
+            
+        // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 
+        uint32_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
+        if (!success)
+            return false;
+                  
+        addr_t offset_addr;
+        addr_t address;
+        
+        if (add)
+            offset_addr = Rn + imm32;
+        else
+            offset_addr = Rn - imm32;
+                  
+        // address = if index then offset_addr else R[n]; 
+        if (index)
+            address = offset_addr;
+        else
+            address = Rn;
+                  
+        // data = MemU[address,2]; 
+        RegisterInfo base_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
+                  
+        EmulateInstruction::Context context;
+        context.type = eContextRegisterLoad;
+        context.SetRegisterPlusOffset (base_reg, address - Rn);
+                  
+        uint64_t data = MemURead (context, address, 2, 0, &success);
+        if (!success)
+            return false;
+                  
+        // if wback then R[n] = offset_addr;
+        if (wback)
+        {
+            context.type = eContextAdjustBaseRegister;
+            context.SetAddress (offset_addr);
+            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
+                return false;
+        }
+                  
+        // if UnalignedSupport() || address<0> = '0' then
+        if (UnalignedSupport () || BitIsClear (address, 0))
+        {
+            // R[t] = ZeroExtend(data, 32); 
+            context.type = eContextRegisterLoad;
+            context.SetRegisterPlusOffset (base_reg, address - Rn);
+            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
+                return false;
+        }
+        else // Can only apply before ARMv7
+        {
+            // R[t] = bits(32) UNKNOWN;
+            WriteBits32Unknown (t);
+        }
+    }
+    return true;
+}
+                  
+// LDRH (literal) caculates an address from the PC value and an immediate offset, loads a halfword from memory, 
+// zero-extends it to form a 32-bit word, and writes it to a register.            
+bool
+EmulateInstructionARM::EmulateLDRHLiteral (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    if ConditionPassed() then 
+        EncodingSpecificOperations(); NullCheckIfThumbEE(15); 
+        base = Align(PC,4); 
+        address = if add then (base + imm32) else (base - imm32); 
+        data = MemU[address,2]; 
+        if UnalignedSupport() || address<0> = '0' then
+            R[t] = ZeroExtend(data, 32); 
+        else // Can only apply before ARMv7
+            R[t] = bits(32) UNKNOWN;
+#endif
+                                    
+    bool success = false;
+            
+    if (ConditionPassed(opcode))
+    {
+        uint32_t t;
+        uint32_t imm32;
+        bool add;
+                  
+        // EncodingSpecificOperations(); NullCheckIfThumbEE(15); 
+        switch (encoding)
+        {
+            case eEncodingT1:
+                // if Rt == '1111' then SEE "Unallocated memory hints"; 
+                // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1'); 
+                t = Bits32 (opcode, 15, 12);
+                imm32 = Bits32 (opcode, 11, 0);
+                add = BitIsSet (opcode, 23);
+                  
+                // if t == 13 then UNPREDICTABLE;
+                if (t == 13)
+                    return false;
+                  
+                break;
+                  
+            case eEncodingA1:
+            {
+                uint32_t imm4H = Bits32 (opcode, 11, 8);
+                uint32_t imm4L = Bits32 (opcode, 3, 0);
+                  
+                // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1');
+                t = Bits32 (opcode, 15, 12);
+                imm32 = (imm4H << 4) | imm4L;
+                add = BitIsSet (opcode, 23);
+                  
+                // if t == 15 then UNPREDICTABLE;                  
+                if (t == 15)
+                    return false;
+                break;
+            }
+                  
+            default:
+                return false;
+        }
+                  
+        // base = Align(PC,4); 
+        uint64_t pc_value = ReadCoreReg (PC_REG, &success);
+        if (!success)
+            return false;
+                  
+        addr_t base = AlignPC (pc_value);
+        addr_t address;
+                  
+        // address = if add then (base + imm32) else (base - imm32); 
+        if (add)
+            address = base + imm32;
+        else
+            address = base - imm32;
+                  
+        // data = MemU[address,2]; 
+        RegisterInfo base_reg;
+        GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, base_reg);
+                  
+        EmulateInstruction::Context context;
+        context.type = eContextRegisterLoad;
+        context.SetRegisterPlusOffset (base_reg, address - base);
+                  
+        uint64_t data = MemURead (context, address, 2, 0, &success);
+        if (!success)
+            return false;
+                  
+        
+        // if UnalignedSupport() || address<0> = '0' then
+        if (UnalignedSupport () || BitIsClear (address, 0))
+        {
+            // R[t] = ZeroExtend(data, 32); 
+            context.type = eContextRegisterLoad;
+            context.SetRegisterPlusOffset (base_reg, address - base);
+            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
+                return false;
+                  
+        }
+        else // Can only apply before ARMv7
+        {
+            // R[t] = bits(32) UNKNOWN;
+            WriteBits32Unknown (t);
+        }
+    }
+    return true;
+}
+                  
+// LDRH (literal) calculates an address from a base register value and an offset register value, loads a halfword 
+// from memory, zero-extends it to form a 32-bit word, and writes it to a register.  The offset register value can 
+// be shifted left by 0, 1, 2, or 3 bits.
+bool
+EmulateInstructionARM::EmulateLDRHRegister (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    if ConditionPassed() then 
+        EncodingSpecificOperations(); NullCheckIfThumbEE(n); 
+        offset = Shift(R[m], shift_t, shift_n, APSR.C); 
+        offset_addr = if add then (R[n] + offset) else (R[n] - offset); 
+        address = if index then offset_addr else R[n]; 
+        data = MemU[address,2]; 
+        if wback then R[n] = offset_addr; 
+        if UnalignedSupport() || address<0> = '0' then
+            R[t] = ZeroExtend(data, 32); 
+        else // Can only apply before ARMv7
+            R[t] = bits(32) UNKNOWN;
+#endif
+                  
+    bool success = false;
+            
+    if (ConditionPassed(opcode))
+    {
+        uint32_t t;
+        uint32_t n;
+        uint32_t m;
+        bool index;
+        bool add;
+        bool wback;
+        ARM_ShifterType shift_t;
+        uint32_t shift_n;
+                  
+        // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 
+        switch (encoding)
+        {
+            case eEncodingT1:
+                // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE"; 
+                // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm);
+                t = Bits32 (opcode, 2, 0);
+                n = Bits32 (opcode, 5, 3);
+                m = Bits32 (opcode, 8, 6);
+                  
+                // index = TRUE; add = TRUE; wback = FALSE; 
+                index = true;
+                add = true;
+                wback = false;
+                  
+                // (shift_t, shift_n) = (SRType_LSL, 0);
+                shift_t = SRType_LSL;
+                shift_n = 0;
+                  
+                break;
+                  
+            case eEncodingT2:
+                // if Rn == '1111' then SEE LDRH (literal); 
+                // if Rt == '1111' then SEE "Unallocated memory hints"; 
+                // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 
+                t = Bits32 (opcode, 15, 12);
+                n = Bits32 (opcode, 19, 16);
+                m = Bits32 (opcode, 3, 0);
+                  
+                // index = TRUE; add = TRUE; wback = FALSE; 
+                index = true;
+                add = true;
+                wback = false;
+                  
+                // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); 
+                shift_t = SRType_LSL;
+                shift_n = Bits32 (opcode, 5, 4);
+                  
+                // if t == 13 || BadReg(m) then UNPREDICTABLE;
+                if ((t == 13) || BadReg (m))
+                    return false;
+                break;
+                  
+            case eEncodingA1:
+                // if P == '0' && W == '1' then SEE LDRHT; 
+                // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 
+                t = Bits32 (opcode, 15, 12);
+                n = Bits32 (opcode, 19, 16);
+                m = Bits32 (opcode, 3, 0);
+                  
+                // index = (P == '1');	add = (U == '1');	wback = (P == '0') || (W == '1'); 
+                index = BitIsSet (opcode, 24);
+                add = BitIsSet (opcode, 23);
+                wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
+                  
+                // (shift_t, shift_n) = (SRType_LSL, 0); 
+                shift_t = SRType_LSL;
+                shift_n = 0;
+                  
+                // if t == 15 || m == 15 then UNPREDICTABLE; 
+                if ((t == 15) || (m == 15))
+                    return false;
+                  
+                // if wback && (n == 15 || n == t) then UNPREDICTABLE;
+                if (wback && ((n == 15) || (n == t)))
+                    return false;
+                  
+                break;
+                  
+            default:
+                return false;
+        }
+                  
+        // offset = Shift(R[m], shift_t, shift_n, APSR.C); 
+                  
+        uint64_t Rm  = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
+        if (!success)
+            return false;
+                  
+        addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C, &success);
+        if (!success)
+            return false;
+                  
+        addr_t offset_addr;
+        addr_t address;
+                  
+        // offset_addr = if add then (R[n] + offset) else (R[n] - offset);
+        uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
+        if (!success)
+            return false;
+                  
+        if (add)
+            offset_addr = Rn + offset;
+        else
+            offset_addr = Rn - offset;
+                  
+        // address = if index then offset_addr else R[n]; 
+        if (index)
+            address = offset_addr;
+        else
+            address = Rn;
+                  
+        // data = MemU[address,2]; 
+        RegisterInfo base_reg;
+        RegisterInfo offset_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
+                  
+        EmulateInstruction::Context context;
+        context.type = eContextRegisterLoad;
+        context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
+        uint64_t data = MemURead (context, address, 2, 0, &success);
+        if (!success)
+            return false;
+                  
+        // if wback then R[n] = offset_addr; 
+        if (wback)
+        {
+            context.type = eContextAdjustBaseRegister;
+            context.SetAddress (offset_addr);
+            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
+                return false;
+        }
+                  
+        // if UnalignedSupport() || address<0> = '0' then
+        if (UnalignedSupport() || BitIsClear (address, 0))
+        {
+            // R[t] = ZeroExtend(data, 32);
+            context.type = eContextRegisterLoad;
+            context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
+            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
+                return false;
+        }
+        else // Can only apply before ARMv7
+        {
+            // R[t] = bits(32) UNKNOWN;
+            WriteBits32Unknown (t);
+        }
+    }              
+    return true;
+}
+                                                                            
+// LDRSB (immediate) calculates an address from a base register value and an immediate offset, loads a byte from 
+// memory, sign-extends it to form a 32-bit word, and writes it to a register.  It can use offset, post-indexed, 
+// or pre-indexed addressing.
+bool
+EmulateInstructionARM::EmulateLDRSBImmediate (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    if ConditionPassed() then 
+        EncodingSpecificOperations(); NullCheckIfThumbEE(n); 
+        offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 
+        address = if index then offset_addr else R[n]; 
+        R[t] = SignExtend(MemU[address,1], 32); 
+        if wback then R[n] = offset_addr;
+#endif
+                  
+    bool success = false;
+                  
+    if (ConditionPassed(opcode))
+    {
+        uint32_t t;
+        uint32_t n;
+        uint32_t imm32;
+        bool index;
+        bool add;
+        bool wback;
+                  
+        // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 
+        switch (encoding)
+        {
+            case eEncodingT1:
+                // if Rt == '1111' then SEE PLI; 
+                // if Rn == '1111' then SEE LDRSB (literal); 
+                // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 
+                t = Bits32 (opcode, 15, 12);
+                n = Bits32 (opcode, 19, 16);
+                imm32 = Bits32 (opcode, 11, 0);
+                  
+                // index = TRUE; add = TRUE; wback = FALSE; 
+                index = true;
+                add = true;
+                wback = false;
+                  
+                // if t == 13 then UNPREDICTABLE;
+                if (t == 13)
+                    return false;
+                  
+                break;
+                  
+            case eEncodingT2:
+                // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLI; 
+                // if Rn == '1111' then SEE LDRSB (literal); 
+                // if P == '1' && U == '1' && W == '0' then SEE LDRSBT; 
+                // if P == '0' && W == '0' then UNDEFINED;
+                if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
+                    return false;
+                  
+                // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); 
+                t = Bits32 (opcode, 15, 12);
+                n = Bits32 (opcode, 19, 16);
+                imm32 = Bits32 (opcode, 7, 0);
+                  
+                // index = (P == '1'); add = (U == '1'); wback = (W == '1'); 
+                index = BitIsSet (opcode, 10);
+                add = BitIsSet (opcode, 9);
+                wback = BitIsSet (opcode, 8);
+                  
+                // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
+                  if (((t == 13) || ((t == 15) 
+                                     && (BitIsClear (opcode, 10) || BitIsSet (opcode, 9) || BitIsSet (opcode, 8)))) 
+                      || (wback && (n == t)))
+                    return false;
+                  
+                break;
+                  
+            case eEncodingA1:
+            {
+                // if Rn == '1111' then SEE LDRSB (literal); 
+                // if P == '0' && W == '1' then SEE LDRSBT; 
+                // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32); 
+                t = Bits32 (opcode, 15, 12);
+                n = Bits32 (opcode, 19, 16);
+            
+                uint32_t imm4H = Bits32 (opcode, 11, 8);
+                uint32_t imm4L = Bits32 (opcode, 3, 0);
+                imm32 = (imm4H << 4) | imm4L;
+                  
+                // index = (P == '1');	add = (U == '1');	wback = (P == '0') || (W == '1'); 
+                index = BitIsSet (opcode, 24);
+                add = BitIsSet (opcode, 23);
+                wback = (BitIsClear (opcode, 24) || BitIsSet (opcode, 21));
+                  
+                // if t == 15 || (wback && n == t) then UNPREDICTABLE;
+                if ((t == 15) || (wback && (n == t)))
+                    return false;
+                  
+                break;
+            }
+                  
+            default:
+                return false;
+        }
+                  
+        uint64_t Rn = ReadCoreReg (n, &success);
+        if (!success)
+            return false;
+                  
+        addr_t offset_addr;
+        addr_t address;
+                  
+        // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 
+        if (add)
+            offset_addr = Rn + imm32;
+        else
+            offset_addr = Rn - imm32;
+                      
+        // address = if index then offset_addr else R[n]; 
+        if (index)
+            address = offset_addr;
+        else
+            address = Rn;
+        
+        // R[t] = SignExtend(MemU[address,1], 32);
+        RegisterInfo base_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
+                  
+        EmulateInstruction::Context context;
+        context.type = eContextRegisterLoad;
+        context.SetRegisterPlusOffset (base_reg, address - Rn);
+                  
+        uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
+        if (!success)
+            return false;
+                  
+        int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
+        if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
+            return false;
+                  
+        // if wback then R[n] = offset_addr;
+        if (wback)
+        {
+            context.type = eContextAdjustBaseRegister;
+            context.SetAddress (offset_addr);
+            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
+                return false;
+        }
+    }
+                        
+    return true;
+}
+                  
+// LDRSB (literal) calculates an address from the PC value and an immediate offset, loads a byte from memory, 
+// sign-extends it to form a 32-bit word, and writes tit to a register.
+bool
+EmulateInstructionARM::EmulateLDRSBLiteral (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    if ConditionPassed() then 
+        EncodingSpecificOperations(); NullCheckIfThumbEE(15); 
+        base = Align(PC,4); 
+        address = if add then (base + imm32) else (base - imm32); 
+        R[t] = SignExtend(MemU[address,1], 32);
+#endif
+                  
+    bool success = false;
+            
+    if (ConditionPassed(opcode))
+    {
+        uint32_t t;
+        uint32_t imm32;
+        bool add;
+                  
+        // EncodingSpecificOperations(); NullCheckIfThumbEE(15); 
+        switch (encoding)
+        {
+            case eEncodingT1:
+                // if Rt == '1111' then SEE PLI; 
+                // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1'); 
+                t = Bits32 (opcode, 15, 12);
+                imm32 = Bits32 (opcode, 11, 0);
+                add = BitIsSet (opcode, 23);
+                  
+                // if t == 13 then UNPREDICTABLE;
+                if (t == 13)
+                    return false;
+                  
+                break;
+                  
+            case eEncodingA1:
+            {
+                // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1'); 
+                t = Bits32 (opcode, 15, 12);
+                uint32_t imm4H = Bits32 (opcode, 11, 8);
+                uint32_t imm4L = Bits32 (opcode, 3, 0);
+                imm32 = (imm4H << 4) | imm4L;
+                add = BitIsSet (opcode, 23);
+                  
+                // if t == 15 then UNPREDICTABLE;
+                if (t == 15)
+                    return false;
+                  
+                break;
+            }
+                  
+            default:
+                return false;
+        }
+                  
+        // base = Align(PC,4); 
+        uint64_t pc_value = ReadCoreReg (PC_REG, &success);
+        if (!success)
+            return false;
+        uint64_t base = AlignPC (pc_value);
+
+        // address = if add then (base + imm32) else (base - imm32); 
+        addr_t address;
+        if (add)
+            address = base + imm32;
+        else
+            address = base - imm32;
+                  
+        // R[t] = SignExtend(MemU[address,1], 32);
+        RegisterInfo base_reg;
+        GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, base_reg);
+            
+        EmulateInstruction::Context context;
+        context.type = eContextRegisterLoad;
+        context.SetRegisterPlusOffset (base_reg, address - base);
+                  
+        uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
+        if (!success)
+            return false;
+                  
+        int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
+        if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
+            return false;
+    }
+    return true;
+}
+                  
+// LDRSB (register) calculates an address from a base register value and an offset register value, loadsa byte from 
+// memory, sign-extends it to form a 32-bit word, and writes it to a register.  The offset register value can be 
+// shifted left by 0, 1, 2, or 3 bits.
+bool
+EmulateInstructionARM::EmulateLDRSBRegister (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    if ConditionPassed() then 
+        EncodingSpecificOperations(); NullCheckIfThumbEE(n); 
+        offset = Shift(R[m], shift_t, shift_n, APSR.C); 
+        offset_addr = if add then (R[n] + offset) else (R[n] - offset); 
+        address = if index then offset_addr else R[n]; 
+        R[t] = SignExtend(MemU[address,1], 32); 
+        if wback then R[n] = offset_addr;
+#endif
+                  
+    bool success = false;
+            
+    if (ConditionPassed(opcode))
+    {
+        uint32_t t;
+        uint32_t n;
+        uint32_t m;
+        bool index;
+        bool add;
+        bool wback;
+        ARM_ShifterType shift_t;
+        uint32_t shift_n;
+                  
+        // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 
+        switch (encoding)
+        {
+            case eEncodingT1:
+                // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 
+                t = Bits32 (opcode, 2, 0);
+                n = Bits32 (opcode, 5, 3);
+                m = Bits32 (opcode, 8, 6);
+                  
+                // index = TRUE; add = TRUE; wback = FALSE; 
+                index = true;
+                add = true;
+                wback = false;
+                  
+                // (shift_t, shift_n) = (SRType_LSL, 0);
+                shift_t = SRType_LSL;
+                shift_n = 0;
+                  
+                break;
+                  
+            case eEncodingT2:
+                // if Rt == '1111' then SEE PLI; 
+                // if Rn == '1111' then SEE LDRSB (literal); 
+                // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 
+                t = Bits32 (opcode, 15, 12);
+                n = Bits32 (opcode, 19, 16);
+                m = Bits32 (opcode, 3, 0);
+                  
+                // index = TRUE; add = TRUE; wback = FALSE; 
+                index = true;
+                add = true;
+                wback = false;
+                  
+                // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); 
+                shift_t = SRType_LSL;
+                shift_n = Bits32 (opcode, 5, 4);
+                  
+                // if t == 13 || BadReg(m) then UNPREDICTABLE;
+                if ((t == 13) || BadReg (m))
+                    return false;
+                break;
+                  
+            case eEncodingA1:
+                // if P == '0' && W == '1' then SEE LDRSBT; 
+                // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 
+                t = Bits32 (opcode, 15, 12);
+                n = Bits32 (opcode, 19, 16);
+                m = Bits32 (opcode, 3, 0);
+                  
+                // index = (P == '1');	add = (U == '1');	wback = (P == '0') || (W == '1'); 
+                index = BitIsSet (opcode, 24);
+                add = BitIsSet (opcode, 23);
+                wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
+                  
+                // (shift_t, shift_n) = (SRType_LSL, 0); 
+                shift_t = SRType_LSL;
+                shift_n = 0;
+                  
+                // if t == 15 || m == 15 then UNPREDICTABLE; 
+                if ((t == 15) || (m == 15))
+                    return false;
+                  
+                // if wback && (n == 15 || n == t) then UNPREDICTABLE;
+                if (wback && ((n == 15) || (n == t)))
+                    return false;
+                break;
+                  
+            default:
+                return false;
+        }
+                  
+        uint64_t Rm =  ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
+        if (!success)
+            return false;
+                  
+        // offset = Shift(R[m], shift_t, shift_n, APSR.C); 
+        addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C, &success);
+        if (!success)
+            return false;
+            
+        addr_t offset_addr;
+        addr_t address;
+                  
+        // offset_addr = if add then (R[n] + offset) else (R[n] - offset); 
+        uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
+        if (!success)
+            return false;
+                  
+        if (add)
+            offset_addr = Rn + offset;
+        else
+            offset_addr = Rn - offset;
+                  
+        // address = if index then offset_addr else R[n]; 
+        if (index)
+            address = offset_addr;
+        else
+            address = Rn;
+                  
+        // R[t] = SignExtend(MemU[address,1], 32); 
+        RegisterInfo base_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
+        RegisterInfo offset_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
+                  
+        EmulateInstruction::Context context;
+        context.type = eContextRegisterLoad;
+        context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
+                  
+        uint64_t unsigned_data = MemURead (context, address, 1, 0, &success);
+        if (!success)
+            return false;
+                  
+        int64_t signed_data = llvm::SignExtend64<8>(unsigned_data);
+        if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
+            return false;
+                  
+        // if wback then R[n] = offset_addr;
+        if (wback)
+        {
+            context.type = eContextAdjustBaseRegister;
+            context.SetAddress (offset_addr);
+            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
+                return false;
+        }
+    }
+    return true;
+}
+                  
+// LDRSH (immediate) calculates an address from a base register value and an immediate offset, loads a halfword from 
+// memory, sign-extends it to form a 32-bit word, and writes it to a register.  It can use offset, post-indexed, or 
+// pre-indexed addressing.
+bool
+EmulateInstructionARM::EmulateLDRSHImmediate (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    if ConditionPassed() then 
+        EncodingSpecificOperations(); NullCheckIfThumbEE(n); 
+        offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 
+        address = if index then offset_addr else R[n]; 
+        data = MemU[address,2]; 
+        if wback then R[n] = offset_addr; 
+        if UnalignedSupport() || address<0> = '0' then
+            R[t] = SignExtend(data, 32); 
+        else // Can only apply before ARMv7
+            R[t] = bits(32) UNKNOWN;
+#endif
+
+    bool success = false;
+                  
+    if (ConditionPassed(opcode))
+    {
+        uint32_t t;
+        uint32_t n;
+        uint32_t imm32;
+        bool index;
+        bool add;
+        bool wback;
+                  
+        // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 
+        switch (encoding)
+        {
+            case eEncodingT1:
+                // if Rn == '1111' then SEE LDRSH (literal); 
+                // if Rt == '1111' then SEE "Unallocated memory hints"; 
+                // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); 
+                t = Bits32 (opcode, 15, 12);
+                n = Bits32 (opcode, 19, 16);
+                imm32 = Bits32 (opcode, 11, 0);
+                  
+                // index = TRUE; add = TRUE; wback = FALSE; 
+                index = true;
+                add = true;
+                wback = false;
+                  
+                // if t == 13 then UNPREDICTABLE;
+                if (t == 13)
+                    return false;
+                  
+                break;
+                  
+            case eEncodingT2:
+                // if Rn == '1111' then SEE LDRSH (literal); 
+                // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE "Unallocated memory hints"; 
+                // if P == '1' && U == '1' && W == '0' then SEE LDRSHT; 
+                // if P == '0' && W == '0' then UNDEFINED; 
+                  if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8))
+                  return false;
+                  
+                // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); 
+                t = Bits32 (opcode, 15, 12);
+                n = Bits32 (opcode, 19, 16);
+                imm32 = Bits32 (opcode, 7, 0);
+                  
+                // index = (P == '1'); add = (U == '1'); wback = (W == '1'); 
+                index = BitIsSet (opcode, 10);
+                add = BitIsSet (opcode, 9);
+                wback = BitIsSet (opcode, 8);
+                  
+                // if BadReg(t) || (wback && n == t) then UNPREDICTABLE;
+                if (BadReg (t) || (wback && (n == t)))
+                    return false;
+                  
+                break;
+                  
+            case eEncodingA1:
+            {
+                // if Rn == '1111' then SEE LDRSH (literal); 
+                // if P == '0' && W == '1' then SEE LDRSHT; 
+                // t == UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32); 
+                t = Bits32 (opcode, 15, 12);
+                n = Bits32 (opcode, 19, 16);
+                uint32_t imm4H = Bits32 (opcode, 11,8);
+                uint32_t imm4L = Bits32 (opcode, 3, 0);
+                imm32 = (imm4H << 4) | imm4L;
+                  
+                // index = (P == '1');	add = (U == '1');	wback = (P == '0') || (W == '1'); 
+                index = BitIsSet (opcode, 24);
+                add = BitIsSet (opcode, 23);
+                wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
+                  
+                // if t == 15 || (wback && n == t) then UNPREDICTABLE;
+                if ((t == 15) || (wback && (n == t)))
+                    return false;
+                  
+                break;
+            }      
+                  
+            default:
+                return false;
+        }
+                  
+        // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32); 
+        uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
+        if (!success)
+            return false;
+                  
+        addr_t offset_addr;
+        if (add)
+            offset_addr = Rn + imm32;
+        else
+            offset_addr = Rn - imm32;
+                  
+        // address = if index then offset_addr else R[n]; 
+        addr_t address;
+        if (index)
+            address = offset_addr;
+        else
+            address = Rn;
+                  
+        // data = MemU[address,2]; 
+        RegisterInfo base_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
+                  
+        EmulateInstruction::Context context;
+        context.type = eContextRegisterLoad;
+        context.SetRegisterPlusOffset (base_reg, address - Rn);
+                  
+        uint64_t data = MemURead (context, address, 2, 0, &success);
+        if (!success)
+            return false;
+                  
+        // if wback then R[n] = offset_addr; 
+        if (wback)
+        {
+            context.type = eContextAdjustBaseRegister;
+            context.SetAddress (offset_addr);
+            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
+                return false;
+        }
+                  
+        // if UnalignedSupport() || address<0> = '0' then
+        if (UnalignedSupport() || BitIsClear (address, 0))
+        {
+            // R[t] = SignExtend(data, 32); 
+            int64_t signed_data = llvm::SignExtend64<16>(data);
+            context.type = eContextRegisterLoad;
+            context.SetRegisterPlusOffset (base_reg, address - Rn);
+            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
+                return false;
+        }
+        else // Can only apply before ARMv7
+        {
+            // R[t] = bits(32) UNKNOWN;
+            WriteBits32Unknown (t);
+        }
+    }
+    return true;
+}
+                  
+// LDRSH (literal) calculates an address from the PC value and an immediate offset, loads a halfword from memory, 
+// sign-extends it to from a 32-bit word, and writes it to a register.
+bool
+EmulateInstructionARM::EmulateLDRSHLiteral (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    if ConditionPassed() then 
+        EncodingSpecificOperations(); NullCheckIfThumbEE(15); 
+        base = Align(PC,4); 
+        address = if add then (base + imm32) else (base - imm32); 
+        data = MemU[address,2]; 
+        if UnalignedSupport() || address<0> = '0' then
+            R[t] = SignExtend(data, 32);
+        else // Can only apply before ARMv7
+            R[t] = bits(32) UNKNOWN;
+#endif
+                  
+    bool success = false;
+                  
+    if (ConditionPassed(opcode))
+    {
+        uint32_t t;
+        uint32_t imm32;
+        bool add;
+                  
+        // EncodingSpecificOperations(); NullCheckIfThumbEE(15); 
+        switch (encoding)
+        {
+            case eEncodingT1:
+                // if Rt == '1111' then SEE "Unallocated memory hints"; 
+                // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1'); 
+                t = Bits32  (opcode, 15, 12);
+                imm32 = Bits32 (opcode, 11, 0);
+                add = BitIsSet (opcode, 23);
+                  
+                // if t == 13 then UNPREDICTABLE;
+                if (t == 13)
+                    return false;
+                  
+                break;
+                  
+            case eEncodingA1:
+            {
+                // t == UInt(Rt); imm32 = ZeroExtend(imm4H:imm4L, 32); add = (U == '1'); 
+                t = Bits32 (opcode, 15, 12);
+                uint32_t imm4H = Bits32 (opcode, 11, 8);
+                uint32_t imm4L = Bits32 (opcode, 3, 0);
+                imm32 = (imm4H << 4) | imm4L;
+                add = BitIsSet (opcode, 23);
+                  
+                // if t == 15 then UNPREDICTABLE;
+                if (t == 15)
+                    return false;
+                  
+                break;
+            }      
+            default:
+                return false;
+        }
+            
+        // base = Align(PC,4); 
+        uint64_t pc_value = ReadCoreReg (PC_REG, &success);
+        if (!success)
+            return false;
+                  
+        uint64_t base = AlignPC (pc_value);
+        
+        addr_t address;
+        // address = if add then (base + imm32) else (base - imm32); 
+        if (add)
+            address = base + imm32;
+        else
+            address = base - imm32;
+                  
+        // data = MemU[address,2]; 
+        RegisterInfo base_reg;
+        GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, base_reg);
+                  
+        EmulateInstruction::Context context;
+        context.type = eContextRegisterLoad;
+        context.SetRegisterPlusOffset (base_reg, imm32);
+                  
+        uint64_t data = MemURead (context, address, 2, 0, &success);
+        if (!success)
+            return false;
+                  
+        // if UnalignedSupport() || address<0> = '0' then
+        if (UnalignedSupport() || BitIsClear (address, 0))
+        {
+            // R[t] = SignExtend(data, 32);
+            int64_t signed_data = llvm::SignExtend64<16>(data);
+            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
+                return false;
+        }
+        else // Can only apply before ARMv7
+        {
+            // R[t] = bits(32) UNKNOWN;
+            WriteBits32Unknown (t);
+        }
+    }
+    return true;
+}
+                  
+// LDRSH (register) calculates an address from a base register value and an offset register value, loads a halfword
+// from memory, sign-extends it to form a 32-bit word, and writes it to a register.  The offset register value can be 
+// shifted left by 0, 1, 2, or 3 bits.
+bool
+EmulateInstructionARM::EmulateLDRSHRegister (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    if ConditionPassed() then 
+        EncodingSpecificOperations(); NullCheckIfThumbEE(n); 
+        offset = Shift(R[m], shift_t, shift_n, APSR.C); 
+        offset_addr = if add then (R[n] + offset) else (R[n] - offset); 
+        address = if index then offset_addr else R[n]; 
+        data = MemU[address,2]; 
+        if wback then R[n] = offset_addr; 
+        if UnalignedSupport() || address<0> = '0' then
+            R[t] = SignExtend(data, 32); 
+        else // Can only apply before ARMv7
+            R[t] = bits(32) UNKNOWN;
+#endif
+                  
+    bool success = false;
+                  
+    if (ConditionPassed(opcode))
+    {
+        uint32_t t;
+        uint32_t n;
+        uint32_t m;
+        bool index;
+        bool add;
+        bool wback;
+        ARM_ShifterType shift_t;
+        uint32_t shift_n;
+                  
+        // EncodingSpecificOperations(); NullCheckIfThumbEE(n); 
+        switch (encoding)
+        {
+            case eEncodingT1:
+                // if CurrentInstrSet() == InstrSet_ThumbEE then SEE "Modified operation in ThumbEE"; 
+                // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 
+                t = Bits32 (opcode, 2, 0);
+                n = Bits32 (opcode, 5, 3);
+                m = Bits32 (opcode, 8, 6);
+                  
+                // index = TRUE; add = TRUE; wback = FALSE; 
+                index = true;
+                add = true;
+                wback = false;
+                  
+                // (shift_t, shift_n) = (SRType_LSL, 0);
+                shift_t = SRType_LSL;
+                shift_n = 0;
+                  
+                break;
+                  
+            case eEncodingT2:
+                // if Rn == '1111' then SEE LDRSH (literal); 
+                // if Rt == '1111' then SEE "Unallocated memory hints"; 
+                // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 
+                t = Bits32 (opcode, 15, 12);
+                n = Bits32 (opcode, 19, 16);
+                m = Bits32 (opcode, 3, 0);
+                  
+                // index = TRUE; add = TRUE; wback = FALSE; 
+                index = true;
+                add = true;
+                wback = false;
+                  
+                // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); 
+                shift_t = SRType_LSL;
+                shift_n = Bits32 (opcode, 5, 4);
+                  
+                // if t == 13 || BadReg(m) then UNPREDICTABLE;
+                if ((t == 13) || BadReg (m))
+                    return false;
+                  
+                break;
+                  
+            case eEncodingA1:
+                // if P == '0' && W == '1' then SEE LDRSHT; 
+                // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); 
+                t = Bits32 (opcode, 15, 12);
+                n = Bits32 (opcode, 19, 16);
+                m = Bits32 (opcode, 3, 0);
+                  
+                // index = (P == '1');	add = (U == '1');	wback = (P == '0') || (W == '1'); 
+                index = BitIsSet (opcode, 24);
+                add = BitIsSet (opcode, 23);
+                wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
+                  
+                // (shift_t, shift_n) = (SRType_LSL, 0); 
+                shift_t = SRType_LSL;
+                shift_n = 0;
+                  
+                // if t == 15 || m == 15 then UNPREDICTABLE; 
+                if ((t == 15) || (m == 15))
+                    return false;
+                  
+                // if wback && (n == 15 || n == t) then UNPREDICTABLE;
+                if (wback && ((n == 15) || (n == t)))
+                    return false;
+                  
+                break;
+                  
+            default:
+                return false;
+        }
+                  
+        uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
+        if (!success)
+            return false;
+                  
+        uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
+        if (!success)
+            return false;
+                  
+        // offset = Shift(R[m], shift_t, shift_n, APSR.C); 
+        addr_t offset = Shift (Rm, shift_t, shift_n, APSR_C, &success);
+        if (!success)
+            return false;
+                  
+        addr_t offset_addr;
+        addr_t address;
+                  
+        // offset_addr = if add then (R[n] + offset) else (R[n] - offset); 
+        if (add)
+            offset_addr = Rn + offset;
+        else
+            offset_addr = Rn - offset;
+                  
+        // address = if index then offset_addr else R[n]; 
+        if (index)
+            address = offset_addr;
+        else
+            address = Rn;
+                  
+        // data = MemU[address,2]; 
+        RegisterInfo base_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
+                  
+        RegisterInfo offset_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
+                  
+        EmulateInstruction::Context context;
+        context.type = eContextRegisterLoad;
+        context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
+                  
+        uint64_t data = MemURead (context, address, 2, 0, &success);
+        if (!success)
+            return false;
+                  
+        // if wback then R[n] = offset_addr; 
+        if (wback)
+        {
+            context.type = eContextAdjustBaseRegister;
+            context.SetAddress (offset_addr);
+            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
+                return false;
+        }
+                  
+        // if UnalignedSupport() || address<0> = '0' then
+        if (UnalignedSupport() || BitIsClear (address, 0))
+        {
+            // R[t] = SignExtend(data, 32); 
+            context.type = eContextRegisterLoad;
+            context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
+            
+            int64_t signed_data = llvm::SignExtend64<16>(data);
+            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, (uint64_t) signed_data))
+                return false;
+        }
+        else // Can only apply before ARMv7
+        {
+            // R[t] = bits(32) UNKNOWN;
+            WriteBits32Unknown (t);
+        }
+    }
+    return true;
+}
+         
+// SXTB extracts an 8-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination 
+// register.  You can specifiy a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value.
+bool 
+EmulateInstructionARM::EmulateSXTB (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    if ConditionPassed() then 
+        EncodingSpecificOperations();
+        rotated = ROR(R[m], rotation); 
+        R[d] = SignExtend(rotated<7:0>, 32);
+#endif
+                  
+    bool success = false;
+                  
+    if (ConditionPassed(opcode))
+    {
+        uint32_t d;
+        uint32_t m;
+        uint32_t rotation;
+                  
+        // EncodingSpecificOperations();
+        switch (encoding)
+        {
+            case eEncodingT1:
+                // d = UInt(Rd); m = UInt(Rm); rotation = 0;
+                d = Bits32 (opcode, 2, 0);
+                m = Bits32 (opcode, 5, 3);
+                rotation = 0;
+                  
+                break;
+                  
+            case eEncodingT2:
+                // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 
+                d = Bits32 (opcode, 11, 8);
+                m = Bits32 (opcode, 3, 0);
+                rotation = Bits32 (opcode, 5, 4) << 3;
+                              
+                // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
+                if (BadReg (d) || BadReg (m))
+                    return false;
+                  
+                break;
+                  
+            case eEncodingA1:
+                // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 
+                d = Bits32 (opcode, 15, 12);
+                m = Bits32 (opcode, 3, 0);
+                rotation = Bits32 (opcode, 11, 10) << 3;
+                  
+                // if d == 15 || m == 15 then UNPREDICTABLE;
+                if ((d == 15) || (m == 15))
+                    return false;
+                  
+                break;
+                  
+            default:
+                return false;
+        }
+                  
+        uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
+        if (!success)
+            return false;
+                  
+        // rotated = ROR(R[m], rotation); 
+        uint64_t rotated = ROR (Rm, rotation, &success);
+        if (!success)
+            return false;
+                  
+        // R[d] = SignExtend(rotated<7:0>, 32);
+        int64_t data = llvm::SignExtend64<8>(rotated);
+                  
+        RegisterInfo source_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, source_reg);
+                  
+        EmulateInstruction::Context context;
+        context.type = eContextRegisterLoad;
+        context.SetRegister (source_reg);
+                  
+        if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data))
+            return false;
+    }
+    return true;
+}
+                  
+// SXTH extracts a 16-bit value from a register, sign-extends it to 32 bits, and writes the result to the destination
+// register.  You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value.
+bool
+EmulateInstructionARM::EmulateSXTH (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    if ConditionPassed() then 
+        EncodingSpecificOperations(); 
+        rotated = ROR(R[m], rotation); 
+        R[d] = SignExtend(rotated<15:0>, 32);
+#endif
+                  
+    bool success = false;
+                  
+    if (ConditionPassed(opcode))
+    {
+        uint32_t d;
+        uint32_t m;
+        uint32_t rotation;
+                  
+        // EncodingSpecificOperations(); 
+        switch (encoding)
+        {
+            case eEncodingT1:
+                // d = UInt(Rd); m = UInt(Rm); rotation = 0;
+                d = Bits32 (opcode, 2, 0);
+                m = Bits32 (opcode, 5, 3);
+                rotation = 0;
+                  
+                break;
+                  
+            case eEncodingT2:
+                // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 
+                d = Bits32 (opcode, 11, 8);
+                m = Bits32 (opcode, 3, 0);
+                rotation = Bits32 (opcode, 5, 4) << 3;
+                  
+                // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
+                if (BadReg (d) || BadReg (m))
+                    return false;
+                  
+                break;
+                  
+            case eEncodingA1:
+                // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 
+                d = Bits32 (opcode, 15, 12);
+                m = Bits32 (opcode, 3, 0);
+                rotation = Bits32 (opcode, 11, 10) << 3;
+                  
+                // if d == 15 || m == 15 then UNPREDICTABLE;
+                if ((d == 15) || (m == 15))
+                    return false;
+                  
+                break;
+                
+            default:
+                return false;
+        }
+                  
+        uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
+        if (!success)
+            return false;
+                  
+        // rotated = ROR(R[m], rotation); 
+        uint64_t rotated = ROR (Rm, rotation, &success);
+        if (!success)
+            return false;
+                  
+        // R[d] = SignExtend(rotated<15:0>, 32);
+        RegisterInfo source_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, source_reg);
+                  
+        EmulateInstruction::Context context;
+        context.type = eContextRegisterLoad;
+        context.SetRegister (source_reg);
+                  
+        int64_t data = llvm::SignExtend64<16> (rotated);
+        if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, (uint64_t) data))
+            return false;
+    }
+                  
+    return true;
+}
+                  
+// UXTB extracts an 8-bit value from a register, zero-extneds it to 32 bits, and writes the result to the destination
+// register.  You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 8-bit value.
+bool
+EmulateInstructionARM::EmulateUXTB (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    if ConditionPassed() then 
+        EncodingSpecificOperations(); 
+        rotated = ROR(R[m], rotation); 
+        R[d] = ZeroExtend(rotated<7:0>, 32);
+#endif
+                  
+    bool success = false;
+                  
+    if (ConditionPassed(opcode))
+    {
+        uint32_t d;
+        uint32_t m;
+        uint32_t rotation;
+                  
+        // EncodingSpecificOperations(); 
+        switch (encoding)
+        {
+            case eEncodingT1:
+                // d = UInt(Rd); m = UInt(Rm); rotation = 0;
+                d = Bits32 (opcode, 2, 0);
+                m = Bits32 (opcode, 5, 3);
+                rotation = 0;
+                  
+                break;
+                  
+            case eEncodingT2:
+                // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 
+                d = Bits32 (opcode, 11, 8);
+                m = Bits32 (opcode, 3, 0);
+                  rotation = Bits32 (opcode, 5, 4) << 3;
+                  
+                // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
+                if (BadReg (d) || BadReg (m))
+                  return false;
+                  
+                break;
+                  
+            case eEncodingA1:
+                // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 
+                d = Bits32 (opcode, 15, 12);
+                m = Bits32 (opcode, 3, 0);
+                rotation = Bits32 (opcode, 11, 10) << 3;
+                  
+                // if d == 15 || m == 15 then UNPREDICTABLE;
+                if ((d == 15) || (m == 15))
+                    return false;
+                  
+                break;
+                  
+            default:
+                return false;
+        }
+                  
+        uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
+        if (!success)
+            return false;
+                  
+        // rotated = ROR(R[m], rotation); 
+        uint64_t rotated = ROR (Rm, rotation, &success);
+        if (!success)
+            return false;
+                  
+        // R[d] = ZeroExtend(rotated<7:0>, 32);
+        RegisterInfo source_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, source_reg);
+                  
+        EmulateInstruction::Context context;
+        context.type = eContextRegisterLoad;
+        context.SetRegister (source_reg);
+                  
+        if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 7, 0)))
+            return false;
+    }
+    return true;
+}
+                  
+// UXTH extracts a 16-bit value from a register, zero-extends it to 32 bits, and writes the result to the destination 
+// register.  You can specify a rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value.
+bool 
+EmulateInstructionARM::EmulateUXTH (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    if ConditionPassed() then 
+        EncodingSpecificOperations(); 
+        rotated = ROR(R[m], rotation); 
+        R[d] = ZeroExtend(rotated<15:0>, 32);
+#endif
+                  
+    bool success = false;
+                  
+    if (ConditionPassed(opcode))
+    {
+        uint32_t d;
+        uint32_t m;
+        uint32_t rotation;
+                  
+        switch (encoding)
+        {
+            case eEncodingT1:
+                // d = UInt(Rd); m = UInt(Rm); rotation = 0;
+                d = Bits32 (opcode, 2, 0);
+                m = Bits32 (opcode, 5, 3);
+                rotation = 0;
+                  
+                break;
+                  
+            case eEncodingT2:
+                // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 
+                d = Bits32 (opcode, 11, 8);
+                m = Bits32 (opcode, 3, 0);
+                rotation = Bits32 (opcode, 5, 4) << 3;
+                  
+                // if BadReg(d) || BadReg(m) then UNPREDICTABLE;
+                if (BadReg (d) || BadReg (m))
+                  return false;
+                  
+                break;
+                  
+            case eEncodingA1:
+                // d = UInt(Rd); m = UInt(Rm); rotation = UInt(rotate:'000'); 
+                d = Bits32 (opcode, 15, 12);
+                m = Bits32 (opcode, 3, 0);
+                rotation = Bits32 (opcode, 11, 10) << 3;
+                  
+                // if d == 15 || m == 15 then UNPREDICTABLE;
+                if ((d == 15) || (m == 15))
+                    return false;
+                  
+                break;
+                  
+            default:
+                return false;
+        }
+                  
+        uint64_t Rm = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + m, 0, &success);
+        if (!success)
+            return false;
+                  
+        // rotated = ROR(R[m], rotation); 
+        uint64_t rotated = ROR (Rm, rotation, &success);
+        if (!success)
+            return false;
+                  
+        // R[d] = ZeroExtend(rotated<15:0>, 32);
+        RegisterInfo source_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, source_reg);
+                  
+        EmulateInstruction::Context context;
+        context.type = eContextRegisterLoad;
+        context.SetRegister (source_reg);
+                  
+        if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, Bits32 (rotated, 15, 0)))
+            return false;
+    }
+    return true;
+}
+                 
+// RFE (Return From Exception) loads the PC and the CPSR from the word at the specified address and the following 
+// word respectively.  
+bool
+EmulateInstructionARM::EmulateRFE (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    if ConditionPassed() then 
+        EncodingSpecificOperations(); 
+        if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
+            UNPREDICTABLE; 
+        else
+            address = if increment then R[n] else R[n]-8; 
+            if wordhigher then address = address+4; 
+            CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE); 
+            BranchWritePC(MemA[address,4]);
+            if wback then R[n] = if increment then R[n]+8 else R[n]-8;
+#endif
+                  
+    bool success = false;
+                  
+    if (ConditionPassed(opcode))
+    {
+        uint32_t n;
+        bool wback;
+        bool increment;
+        bool wordhigher;
+                  
+        // EncodingSpecificOperations(); 
+        switch (encoding)
+        {
+            case eEncodingT1:
+                // n = UInt(Rn); wback = (W == '1'); increment = FALSE; wordhigher = FALSE; 
+                n = Bits32 (opcode, 19, 16);
+                wback = BitIsSet (opcode, 21);
+                increment = false;
+                wordhigher = false;
+                  
+                // if n == 15 then UNPREDICTABLE; 
+                if (n == 15)
+                    return false;
+                  
+                // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
+                if (InITBlock() && !LastInITBlock())
+                    return false;
+                  
+                break;
+                  
+            case eEncodingT2:
+                // n = UInt(Rn); wback = (W == '1'); increment = TRUE; wordhigher = FALSE; 
+                n = Bits32 (opcode, 19, 16);
+                wback = BitIsSet (opcode, 21);
+                increment = true;
+                wordhigher = false;
+                  
+                // if n == 15 then UNPREDICTABLE; 
+                if (n == 15)
+                    return false;
+                  
+                // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
+                if (InITBlock() && !LastInITBlock())
+                    return false;
+                  
+                break;
+                  
+            case eEncodingA1:
+                // n = UInt(Rn); 
+                n = Bits32 (opcode, 19, 16);
+                  
+                // wback = (W == '1'); inc = (U == '1'); wordhigher = (P == U); 
+                wback = BitIsSet (opcode, 21);
+                increment = BitIsSet (opcode, 23);
+                wordhigher = (Bit32 (opcode, 24) == Bit32 (opcode, 23));
+                  
+                // if n == 15 then UNPREDICTABLE;
+                if (n == 15)
+                    return false;
+                  
+                break;
+                  
+            default:
+                return false;
+        }
+                                    
+        // if !CurrentModeIsPrivileged() || CurrentInstrSet() == InstrSet_ThumbEE then
+        if (!CurrentModeIsPrivileged ())
+            // UNPREDICTABLE; 
+            return false;
+        else
+        {
+            uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success);
+            if (!success)
+                return false;
+                  
+            addr_t address;
+            // address = if increment then R[n] else R[n]-8; 
+            if (increment)
+                address = Rn;
+            else
+                address = Rn - 8;
+                  
+            // if wordhigher then address = address+4; 
+            if (wordhigher)
+                address = address + 4;
+                  
+            // CPSRWriteByInstr(MemA[address+4,4], '1111', TRUE);
+            RegisterInfo base_reg;
+            GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
+                  
+            EmulateInstruction::Context context;
+            context.type = eContextReturnFromException;
+            context.SetRegisterPlusOffset (base_reg, address - Rn);
+                  
+            uint64_t data = MemARead (context, address + 4, 4, 0, &success);
+            if (!success)
+                return false;
+                  
+            CPSRWriteByInstr (data, 15, true);
+                  
+            // BranchWritePC(MemA[address,4]);
+            uint64_t data2 = MemARead (context, address, 4, 0, &success);
+            if (!success)
+                return false;
+                  
+            BranchWritePC (context, data2);
+                  
+            // if wback then R[n] = if increment then R[n]+8 else R[n]-8;
+            if (wback)
+            {
+                context.type = eContextAdjustBaseRegister;
+                if (increment)
+                {
+                    context.SetOffset (8);
+                    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + 8))
+                        return false;
+                }
+                else
+                {
+                    context.SetOffset (-8);
+                    if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn - 8))
+                        return false;
+                }
+            } // if wback
+        }
+    } // if ConditionPassed()
+    return true;
+}
+                  
+// Bitwise Exclusive OR (immediate) performs a bitwise exclusive OR of a register value and an immediate value,
+// and writes the result to the destination register.  It can optionally update the condition flags based on
+// the result.
+bool
+EmulateInstructionARM::EmulateEORImm (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if ConditionPassed() then
+        EncodingSpecificOperations();
+        result = R[n] EOR imm32;
+        if d == 15 then         // Can only occur for ARM encoding
+            ALUWritePC(result); // setflags is always FALSE here
+        else
+            R[d] = result;
+            if setflags then
+                APSR.N = result<31>;
+                APSR.Z = IsZeroBit(result);
+                APSR.C = carry;
+                // APSR.V unchanged
+#endif
+
+    bool success = false;
+
+    if (ConditionPassed(opcode))
+    {
+        uint32_t Rd, Rn;
+        uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
+        bool setflags;
+        uint32_t carry; // the carry bit after ARM/Thumb Expand operation
+        switch (encoding)
+        {
+        case eEncodingT1:
+            Rd = Bits32(opcode, 11, 8);
+            Rn = Bits32(opcode, 19, 16);
+            setflags = BitIsSet(opcode, 20);
+            imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
+            // if Rd == '1111' && S == '1' then SEE TEQ (immediate);
+            if (Rd == 15 && setflags)
+                return EmulateTEQImm (opcode, eEncodingT1);
+            if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn))
+                return false;
+            break;
+        case eEncodingA1:
+            Rd = Bits32(opcode, 15, 12);
+            Rn = Bits32(opcode, 19, 16);
+            setflags = BitIsSet(opcode, 20);
+            imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
+
+            // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
+            if (Rd == 15 && setflags)
+                return EmulateSUBSPcLrEtc (opcode, encoding);
+            break;
+        default:
+            return false;
+        }
+
+        // Read the first operand.
+        uint32_t val1 = ReadCoreReg(Rn, &success);
+        if (!success)
+            return false;
+
+        uint32_t result = val1 ^ imm32;
+
+        EmulateInstruction::Context context;
+        context.type = EmulateInstruction::eContextImmediate;
+        context.SetNoArgs ();
+
+        if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
+            return false;
+    }
+    return true;
+}
+
+// Bitwise Exclusive OR (register) performs a bitwise exclusive OR of a register value and an
+// optionally-shifted register value, and writes the result to the destination register.
+// It can optionally update the condition flags based on the result.
+bool
+EmulateInstructionARM::EmulateEORReg (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if ConditionPassed() then
+        EncodingSpecificOperations();
+        (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
+        result = R[n] EOR shifted;
+        if d == 15 then         // Can only occur for ARM encoding
+            ALUWritePC(result); // setflags is always FALSE here
+        else
+            R[d] = result;
+            if setflags then
+                APSR.N = result<31>;
+                APSR.Z = IsZeroBit(result);
+                APSR.C = carry;
+                // APSR.V unchanged
+#endif
+
+    bool success = false;
+
+    if (ConditionPassed(opcode))
+    {
+        uint32_t Rd, Rn, Rm;
+        ARM_ShifterType shift_t;
+        uint32_t shift_n; // the shift applied to the value read from Rm
+        bool setflags;
+        uint32_t carry;
+        switch (encoding)
+        {
+        case eEncodingT1:
+            Rd = Rn = Bits32(opcode, 2, 0);
+            Rm = Bits32(opcode, 5, 3);
+            setflags = !InITBlock();
+            shift_t = SRType_LSL;
+            shift_n = 0;
+            break;
+        case eEncodingT2:
+            Rd = Bits32(opcode, 11, 8);
+            Rn = Bits32(opcode, 19, 16);
+            Rm = Bits32(opcode, 3, 0);
+            setflags = BitIsSet(opcode, 20);
+            shift_n = DecodeImmShiftThumb(opcode, shift_t);
+            // if Rd == '1111' && S == '1' then SEE TEQ (register);
+            if (Rd == 15 && setflags)
+                return EmulateTEQReg (opcode, eEncodingT1);
+            if (Rd == 13 || (Rd == 15 && !setflags) || BadReg(Rn) || BadReg(Rm))
+                return false;
+            break;
+        case eEncodingA1:
+            Rd = Bits32(opcode, 15, 12);
+            Rn = Bits32(opcode, 19, 16);
+            Rm = Bits32(opcode, 3, 0);
+            setflags = BitIsSet(opcode, 20);
+            shift_n = DecodeImmShiftARM(opcode, shift_t);
+
+            // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
+            if (Rd == 15 && setflags)
+                return EmulateSUBSPcLrEtc (opcode, encoding);
+            break;
+        default:
+            return false;
+        }
+
+        // Read the first operand.
+        uint32_t val1 = ReadCoreReg(Rn, &success);
+        if (!success)
+            return false;
+
+        // Read the second operand.
+        uint32_t val2 = ReadCoreReg(Rm, &success);
+        if (!success)
+            return false;
+
+        uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
+        if (!success)
+            return false;
+        uint32_t result = val1 ^ shifted;
+
+        EmulateInstruction::Context context;
+        context.type = EmulateInstruction::eContextImmediate;
+        context.SetNoArgs ();
+
+        if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
+            return false;
+    }
+    return true;
+}
+
+// Bitwise OR (immediate) performs a bitwise (inclusive) OR of a register value and an immediate value, and
+// writes the result to the destination register.  It can optionally update the condition flags based
+// on the result.
+bool
+EmulateInstructionARM::EmulateORRImm (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if ConditionPassed() then
+        EncodingSpecificOperations();
+        result = R[n] OR imm32;
+        if d == 15 then         // Can only occur for ARM encoding
+            ALUWritePC(result); // setflags is always FALSE here
+        else
+            R[d] = result;
+            if setflags then
+                APSR.N = result<31>;
+                APSR.Z = IsZeroBit(result);
+                APSR.C = carry;
+                // APSR.V unchanged
+#endif
+
+    bool success = false;
+
+    if (ConditionPassed(opcode))
+    {
+        uint32_t Rd, Rn;
+        uint32_t imm32; // the immediate value to be ORed to the value obtained from Rn
+        bool setflags;
+        uint32_t carry; // the carry bit after ARM/Thumb Expand operation
+        switch (encoding)
+        {
+        case eEncodingT1:
+            Rd = Bits32(opcode, 11, 8);
+            Rn = Bits32(opcode, 19, 16);
+            setflags = BitIsSet(opcode, 20);
+            imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
+            // if Rn == '1111' then SEE MOV (immediate);
+            if (Rn == 15)
+                return EmulateMOVRdImm (opcode, eEncodingT2);
+            if (BadReg(Rd) || Rn == 13)
+                return false;
+            break;
+        case eEncodingA1:
+            Rd = Bits32(opcode, 15, 12);
+            Rn = Bits32(opcode, 19, 16);
+            setflags = BitIsSet(opcode, 20);
+            imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
+
+            if (Rd == 15 && setflags)
+                return EmulateSUBSPcLrEtc (opcode, encoding);
+            break;
+        default:
+            return false;
+        }
+
+        // Read the first operand.
+        uint32_t val1 = ReadCoreReg(Rn, &success);
+        if (!success)
+            return false;
+
+        uint32_t result = val1 | imm32;
+
+        EmulateInstruction::Context context;
+        context.type = EmulateInstruction::eContextImmediate;
+        context.SetNoArgs ();
+
+        if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
+            return false;
+    }
+    return true;
+}
+
+// Bitwise OR (register) performs a bitwise (inclusive) OR of a register value and an optionally-shifted register
+// value, and writes the result to the destination register.  It can optionally update the condition flags based
+// on the result.
+bool
+EmulateInstructionARM::EmulateORRReg (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if ConditionPassed() then
+        EncodingSpecificOperations();
+        (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
+        result = R[n] OR shifted;
+        if d == 15 then         // Can only occur for ARM encoding
+            ALUWritePC(result); // setflags is always FALSE here
+        else
+            R[d] = result;
+            if setflags then
+                APSR.N = result<31>;
+                APSR.Z = IsZeroBit(result);
+                APSR.C = carry;
+                // APSR.V unchanged
+#endif
+
+    bool success = false;
+
+    if (ConditionPassed(opcode))
+    {
+        uint32_t Rd, Rn, Rm;
+        ARM_ShifterType shift_t;
+        uint32_t shift_n; // the shift applied to the value read from Rm
+        bool setflags;
+        uint32_t carry;
+        switch (encoding)
+        {
+        case eEncodingT1:
+            Rd = Rn = Bits32(opcode, 2, 0);
+            Rm = Bits32(opcode, 5, 3);
+            setflags = !InITBlock();
+            shift_t = SRType_LSL;
+            shift_n = 0;
+            break;
+        case eEncodingT2:
+            Rd = Bits32(opcode, 11, 8);
+            Rn = Bits32(opcode, 19, 16);
+            Rm = Bits32(opcode, 3, 0);
+            setflags = BitIsSet(opcode, 20);
+            shift_n = DecodeImmShiftThumb(opcode, shift_t);
+            // if Rn == '1111' then SEE MOV (register);
+            if (Rn == 15)
+                return EmulateMOVRdRm (opcode, eEncodingT3);
+            if (BadReg(Rd) || Rn == 13 || BadReg(Rm))
+                return false;
+            break;
+        case eEncodingA1:
+            Rd = Bits32(opcode, 15, 12);
+            Rn = Bits32(opcode, 19, 16);
+            Rm = Bits32(opcode, 3, 0);
+            setflags = BitIsSet(opcode, 20);
+            shift_n = DecodeImmShiftARM(opcode, shift_t);
+
+            if (Rd == 15 && setflags)
+                return EmulateSUBSPcLrEtc (opcode, encoding);
+            break;
+        default:
+            return false;
+        }
+
+        // Read the first operand.
+        uint32_t val1 = ReadCoreReg(Rn, &success);
+        if (!success)
+            return false;
+
+        // Read the second operand.
+        uint32_t val2 = ReadCoreReg(Rm, &success);
+        if (!success)
+            return false;
+
+        uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
+        if (!success)
+            return false;
+        uint32_t result = val1 | shifted;
+
+        EmulateInstruction::Context context;
+        context.type = EmulateInstruction::eContextImmediate;
+        context.SetNoArgs ();
+
+        if (!WriteCoreRegOptionalFlags(context, result, Rd, setflags, carry))
+            return false;
+    }
+    return true;
+}
+
+// Reverse Subtract (immediate) subtracts a register value from an immediate value, and writes the result to
+// the destination register. It can optionally update the condition flags based on the result.
+bool
+EmulateInstructionARM::EmulateRSBImm (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if ConditionPassed() then
+        EncodingSpecificOperations();
+        (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, '1');
+        if d == 15 then         // Can only occur for ARM encoding
+            ALUWritePC(result); // setflags is always FALSE here
+        else
+            R[d] = result;
+            if setflags then
+                APSR.N = result<31>;
+                APSR.Z = IsZeroBit(result);
+                APSR.C = carry;
+                APSR.V = overflow;
+#endif
+
+    bool success = false;
+
+    uint32_t Rd; // the destination register
+    uint32_t Rn; // the first operand
+    bool setflags;
+    uint32_t imm32; // the immediate value to be added to the value obtained from Rn
+    switch (encoding) {
+    case eEncodingT1:
+        Rd = Bits32(opcode, 2, 0);
+        Rn = Bits32(opcode, 5, 3);
+        setflags = !InITBlock();
+        imm32 = 0;
+        break;
+    case eEncodingT2:
+        Rd = Bits32(opcode, 11, 8);
+        Rn = Bits32(opcode, 19, 16);
+        setflags = BitIsSet(opcode, 20);
+        imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
+        if (BadReg(Rd) || BadReg(Rn))
+            return false;
+        break;
+    case eEncodingA1:
+        Rd = Bits32(opcode, 15, 12);
+        Rn = Bits32(opcode, 19, 16);
+        setflags = BitIsSet(opcode, 20);
+        imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
+
+        // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
+        if (Rd == 15 && setflags)
+            return EmulateSUBSPcLrEtc (opcode, encoding);
+        break;
+    default:
+        return false;
+    }
+    // Read the register value from the operand register Rn.
+    uint32_t reg_val = ReadCoreReg(Rn, &success);
+    if (!success)
+        return false;
+                  
+    AddWithCarryResult res = AddWithCarry(~reg_val, imm32, 1);
+
+    EmulateInstruction::Context context;
+    context.type = EmulateInstruction::eContextImmediate;
+    context.SetNoArgs ();
+
+    if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
+        return false;
+
+    return true;
+}
+
+// Reverse Subtract (register) subtracts a register value from an optionally-shifted register value, and writes the
+// result to the destination register. It can optionally update the condition flags based on the result.
+bool
+EmulateInstructionARM::EmulateRSBReg (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if ConditionPassed() then
+        EncodingSpecificOperations();
+        shifted = Shift(R[m], shift_t, shift_n, APSR.C);
+        (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, '1');
+        if d == 15 then         // Can only occur for ARM encoding
+            ALUWritePC(result); // setflags is always FALSE here
+        else
+            R[d] = result;
+            if setflags then
+                APSR.N = result<31>;
+                APSR.Z = IsZeroBit(result);
+                APSR.C = carry;
+                APSR.V = overflow;
+#endif
+
+    bool success = false;
+
+    uint32_t Rd; // the destination register
+    uint32_t Rn; // the first operand
+    uint32_t Rm; // the second operand
+    bool setflags;
+    ARM_ShifterType shift_t;
+    uint32_t shift_n; // the shift applied to the value read from Rm
+    switch (encoding) {
+    case eEncodingT1:
+        Rd = Bits32(opcode, 11, 8);
+        Rn = Bits32(opcode, 19, 16);
+        Rm = Bits32(opcode, 3, 0);
+        setflags = BitIsSet(opcode, 20);
+        shift_n = DecodeImmShiftThumb(opcode, shift_t);
+        // if (BadReg(d) || BadReg(m)) then UNPREDICTABLE;
+        if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
+            return false;
+        break;
+    case eEncodingA1:
+        Rd = Bits32(opcode, 15, 12);
+        Rn = Bits32(opcode, 19, 16);
+        Rm = Bits32(opcode, 3, 0);
+        setflags = BitIsSet(opcode, 20);
+        shift_n = DecodeImmShiftARM(opcode, shift_t);
+
+        // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
+        if (Rd == 15 && setflags)
+            return EmulateSUBSPcLrEtc (opcode, encoding);
+        break;
+    default:
+        return false;
+    }
+    // Read the register value from register Rn.
+    uint32_t val1 = ReadCoreReg(Rn, &success);
+    if (!success)
+        return false;
+
+    // Read the register value from register Rm.
+    uint32_t val2 = ReadCoreReg(Rm, &success);
+    if (!success)
+        return false;
+                  
+    uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
+    if (!success)
+        return false;
+    AddWithCarryResult res = AddWithCarry(~val1, shifted, 1);
+
+    EmulateInstruction::Context context;
+    context.type = EmulateInstruction::eContextImmediate;
+    context.SetNoArgs();
+    if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
+        return false;
+
+    return true;
+}
+
+// Reverse Subtract with Carry (immediate) subtracts a register value and the value of NOT (Carry flag) from
+// an immediate value, and writes the result to the destination register. It can optionally update the condition
+// flags based on the result.
+bool
+EmulateInstructionARM::EmulateRSCImm (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if ConditionPassed() then
+        EncodingSpecificOperations();
+        (result, carry, overflow) = AddWithCarry(NOT(R[n]), imm32, APSR.C);
+        if d == 15 then
+            ALUWritePC(result); // setflags is always FALSE here
+        else
+            R[d] = result;
+            if setflags then
+                APSR.N = result<31>;
+                APSR.Z = IsZeroBit(result);
+                APSR.C = carry;
+                APSR.V = overflow;
+#endif
+
+    bool success = false;
+
+    uint32_t Rd; // the destination register
+    uint32_t Rn; // the first operand
+    bool setflags;
+    uint32_t imm32; // the immediate value to be added to the value obtained from Rn
+    switch (encoding) {
+    case eEncodingA1:
+        Rd = Bits32(opcode, 15, 12);
+        Rn = Bits32(opcode, 19, 16);
+        setflags = BitIsSet(opcode, 20);
+        imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
+
+        // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
+        if (Rd == 15 && setflags)
+            return EmulateSUBSPcLrEtc  (opcode, encoding);
+        break;
+    default:
+        return false;
+    }
+    // Read the register value from the operand register Rn.
+    uint32_t reg_val = ReadCoreReg(Rn, &success);
+    if (!success)
+        return false;
+                  
+    AddWithCarryResult res = AddWithCarry(~reg_val, imm32, APSR_C);
+
+    EmulateInstruction::Context context;
+    context.type = EmulateInstruction::eContextImmediate;
+    context.SetNoArgs ();
+
+    if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
+        return false;
+
+    return true;
+}
+
+// Reverse Subtract with Carry (register) subtracts a register value and the value of NOT (Carry flag) from an
+// optionally-shifted register value, and writes the result to the destination register. It can optionally update the
+// condition flags based on the result.
+bool
+EmulateInstructionARM::EmulateRSCReg (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if ConditionPassed() then
+        EncodingSpecificOperations();
+        shifted = Shift(R[m], shift_t, shift_n, APSR.C);
+        (result, carry, overflow) = AddWithCarry(NOT(R[n]), shifted, APSR.C);
+        if d == 15 then
+            ALUWritePC(result); // setflags is always FALSE here
+        else
+            R[d] = result;
+            if setflags then
+                APSR.N = result<31>;
+                APSR.Z = IsZeroBit(result);
+                APSR.C = carry;
+                APSR.V = overflow;
+#endif
+
+    bool success = false;
+
+    uint32_t Rd; // the destination register
+    uint32_t Rn; // the first operand
+    uint32_t Rm; // the second operand
+    bool setflags;
+    ARM_ShifterType shift_t;
+    uint32_t shift_n; // the shift applied to the value read from Rm
+    switch (encoding) {
+    case eEncodingA1:
+        Rd = Bits32(opcode, 15, 12);
+        Rn = Bits32(opcode, 19, 16);
+        Rm = Bits32(opcode, 3, 0);
+        setflags = BitIsSet(opcode, 20);
+        shift_n = DecodeImmShiftARM(opcode, shift_t);
+
+        // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
+        if (Rd == 15 && setflags)
+            return EmulateSUBSPcLrEtc (opcode, encoding);
+        break;
+    default:
+        return false;
+    }
+    // Read the register value from register Rn.
+    uint32_t val1 = ReadCoreReg(Rn, &success);
+    if (!success)
+        return false;
+
+    // Read the register value from register Rm.
+    uint32_t val2 = ReadCoreReg(Rm, &success);
+    if (!success)
+        return false;
+                  
+    uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
+    if (!success)
+        return false;
+    AddWithCarryResult res = AddWithCarry(~val1, shifted, APSR_C);
+
+    EmulateInstruction::Context context;
+    context.type = EmulateInstruction::eContextImmediate;
+    context.SetNoArgs();
+    if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
+        return false;
+
+    return true;
+}
+
+// Subtract with Carry (immediate) subtracts an immediate value and the value of
+// NOT (Carry flag) from a register value, and writes the result to the destination register.
+// It can optionally update the condition flags based on the result.
+bool
+EmulateInstructionARM::EmulateSBCImm (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if ConditionPassed() then
+        EncodingSpecificOperations();
+        (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), APSR.C);
+        if d == 15 then         // Can only occur for ARM encoding
+            ALUWritePC(result); // setflags is always FALSE here
+        else
+            R[d] = result;
+            if setflags then
+                APSR.N = result<31>;
+                APSR.Z = IsZeroBit(result);
+                APSR.C = carry;
+                APSR.V = overflow;
+#endif
+
+    bool success = false;
+
+    uint32_t Rd; // the destination register
+    uint32_t Rn; // the first operand
+    bool setflags;
+    uint32_t imm32; // the immediate value to be added to the value obtained from Rn
+    switch (encoding) {
+    case eEncodingT1:
+        Rd = Bits32(opcode, 11, 8);
+        Rn = Bits32(opcode, 19, 16);
+        setflags = BitIsSet(opcode, 20);
+        imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
+        if (BadReg(Rd) || BadReg(Rn))
+            return false;
+        break;
+    case eEncodingA1:
+        Rd = Bits32(opcode, 15, 12);
+        Rn = Bits32(opcode, 19, 16);
+        setflags = BitIsSet(opcode, 20);
+        imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
+
+        // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
+        if (Rd == 15 && setflags)
+            return EmulateSUBSPcLrEtc (opcode, encoding);
+        break;
+    default:
+        return false;
+    }
+    // Read the register value from the operand register Rn.
+    uint32_t reg_val = ReadCoreReg(Rn, &success);
+    if (!success)
+        return false;
+                  
+    AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, APSR_C);
+
+    EmulateInstruction::Context context;
+    context.type = EmulateInstruction::eContextImmediate;
+    context.SetNoArgs ();
+
+    if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
+        return false;
+
+    return true;
+}
+
+// Subtract with Carry (register) subtracts an optionally-shifted register value and the value of
+// NOT (Carry flag) from a register value, and writes the result to the destination register.
+// It can optionally update the condition flags based on the result.
+bool
+EmulateInstructionARM::EmulateSBCReg (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if ConditionPassed() then
+        EncodingSpecificOperations();
+        shifted = Shift(R[m], shift_t, shift_n, APSR.C);
+        (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), APSR.C);
+        if d == 15 then         // Can only occur for ARM encoding
+            ALUWritePC(result); // setflags is always FALSE here
+        else
+            R[d] = result;
+            if setflags then
+                APSR.N = result<31>;
+                APSR.Z = IsZeroBit(result);
+                APSR.C = carry;
+                APSR.V = overflow;
+#endif
+
+    bool success = false;
+
+    uint32_t Rd; // the destination register
+    uint32_t Rn; // the first operand
+    uint32_t Rm; // the second operand
+    bool setflags;
+    ARM_ShifterType shift_t;
+    uint32_t shift_n; // the shift applied to the value read from Rm
+    switch (encoding) {
+    case eEncodingT1:
+        Rd = Rn = Bits32(opcode, 2, 0);
+        Rm = Bits32(opcode, 5, 3);
+        setflags = !InITBlock();
+        shift_t = SRType_LSL;
+        shift_n = 0;
+        break;
+    case eEncodingT2:
+        Rd = Bits32(opcode, 11, 8);
+        Rn = Bits32(opcode, 19, 16);
+        Rm = Bits32(opcode, 3, 0);
+        setflags = BitIsSet(opcode, 20);
+        shift_n = DecodeImmShiftThumb(opcode, shift_t);
+        if (BadReg(Rd) || BadReg(Rn) || BadReg(Rm))
+            return false;
+        break;
+    case eEncodingA1:
+        Rd = Bits32(opcode, 15, 12);
+        Rn = Bits32(opcode, 19, 16);
+        Rm = Bits32(opcode, 3, 0);
+        setflags = BitIsSet(opcode, 20);
+        shift_n = DecodeImmShiftARM(opcode, shift_t);
+                
+        // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
+        if (Rd == 15 && setflags)
+            return EmulateSUBSPcLrEtc (opcode, encoding);
+        break;
+    default:
+        return false;
+    }
+    // Read the register value from register Rn.
+    uint32_t val1 = ReadCoreReg(Rn, &success);
+    if (!success)
+        return false;
+
+    // Read the register value from register Rm.
+    uint32_t val2 = ReadCoreReg(Rm, &success);
+    if (!success)
+        return false;
+                  
+    uint32_t shifted = Shift(val2, shift_t, shift_n, APSR_C, &success);
+    if (!success)
+        return false;
+    AddWithCarryResult res = AddWithCarry(val1, ~shifted, APSR_C);
+
+    EmulateInstruction::Context context;
+    context.type = EmulateInstruction::eContextImmediate;
+    context.SetNoArgs();
+    if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
+        return false;
+
+    return true;
+}
+
+// This instruction subtracts an immediate value from a register value, and writes the result
+// to the destination register.  It can optionally update the condition flags based on the result.
+bool
+EmulateInstructionARM::EmulateSUBImmThumb (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if ConditionPassed() then
+        EncodingSpecificOperations();
+        (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
+        R[d] = result;
+        if setflags then
+            APSR.N = result<31>;
+            APSR.Z = IsZeroBit(result);
+            APSR.C = carry;
+            APSR.V = overflow;
+#endif
+
+    bool success = false;
+
+    uint32_t Rd; // the destination register
+    uint32_t Rn; // the first operand
+    bool setflags;
+    uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
+    switch (encoding) {
+    case eEncodingT1:
+        Rd = Bits32(opcode, 2, 0);
+        Rn = Bits32(opcode, 5, 3);
+        setflags = !InITBlock();
+        imm32 = Bits32(opcode, 8, 6); // imm32 = ZeroExtend(imm3, 32)
+        break;
+    case eEncodingT2:
+        Rd = Rn = Bits32(opcode, 10, 8);
+        setflags = !InITBlock();
+        imm32 = Bits32(opcode, 7, 0); // imm32 = ZeroExtend(imm8, 32)
+        break;
+    case eEncodingT3:
+        Rd = Bits32(opcode, 11, 8);
+        Rn = Bits32(opcode, 19, 16);
+        setflags = BitIsSet(opcode, 20);
+        imm32 = ThumbExpandImm(opcode); // imm32 = ThumbExpandImm(i:imm3:imm8)
+
+        // if Rd == '1111' && S == '1' then SEE CMP (immediate);
+        if (Rd == 15 && setflags)
+            return EmulateCMPImm (opcode, eEncodingT2);
+
+        // if Rn == '1101' then SEE SUB (SP minus immediate);
+        if (Rn == 13)
+            return EmulateSUBSPImm (opcode, eEncodingT2);
+
+        // if d == 13 || (d == 15 && S == '0') || n == 15 then UNPREDICTABLE;
+        if (Rd == 13 || (Rd == 15 && !setflags) || Rn == 15)
+            return false;
+        break;
+    case eEncodingT4:
+        Rd = Bits32(opcode, 11, 8);
+        Rn = Bits32(opcode, 19, 16);
+        setflags = BitIsSet(opcode, 20);
+        imm32 = ThumbImm12(opcode); // imm32 = ZeroExtend(i:imm3:imm8, 32)
+
+        // if Rn == '1111' then SEE ADR;
+        if (Rn == 15)
+            return EmulateADR (opcode, eEncodingT2);
+
+        // if Rn == '1101' then SEE SUB (SP minus immediate);
+        if (Rn == 13)
+            return EmulateSUBSPImm (opcode, eEncodingT3);
+
+        if (BadReg(Rd))
+            return false;
+        break;
+    default:
+        return false;
+    }
+    // Read the register value from the operand register Rn.
+    uint32_t reg_val = ReadCoreReg(Rn, &success);
+    if (!success)
+        return false;
+                  
+    AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
+
+    EmulateInstruction::Context context;
+    context.type = EmulateInstruction::eContextImmediate;
+    context.SetNoArgs ();
+
+    if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
+        return false;
+
+    return true;
+}
+
+// This instruction subtracts an immediate value from a register value, and writes the result
+// to the destination register.  It can optionally update the condition flags based on the result.
+bool
+EmulateInstructionARM::EmulateSUBImmARM (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if ConditionPassed() then
+        EncodingSpecificOperations();
+        (result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
+        if d == 15 then
+            ALUWritePC(result); // setflags is always FALSE here
+        else
+            R[d] = result;
+            if setflags then
+                APSR.N = result<31>;
+                APSR.Z = IsZeroBit(result);
+                APSR.C = carry;
+                APSR.V = overflow;
+#endif
+
+    bool success = false;
+
+    uint32_t Rd; // the destination register
+    uint32_t Rn; // the first operand
+    bool setflags;
+    uint32_t imm32; // the immediate value to be subtracted from the value obtained from Rn
+    switch (encoding) {
+    case eEncodingA1:
+        Rd = Bits32(opcode, 15, 12);
+        Rn = Bits32(opcode, 19, 16);
+        setflags = BitIsSet(opcode, 20);
+        imm32 = ARMExpandImm(opcode); // imm32 = ARMExpandImm(imm12)
+
+        // if Rn == '1111' && S == '0' then SEE ADR;
+        if (Rn == 15 && !setflags)
+            return EmulateADR (opcode, eEncodingA2);
+
+        // if Rn == '1101' then SEE SUB (SP minus immediate);
+        if (Rn == 13)
+            return EmulateSUBSPImm (opcode, eEncodingA1);
+
+        // if Rd == '1111' && S == '1' then SEE SUBS PC, LR and related instructions;
+        if (Rd == 15 && setflags)
+            return EmulateSUBSPcLrEtc (opcode, encoding);
+        break;
+    default:
+        return false;
+    }
+    // Read the register value from the operand register Rn.
+    uint32_t reg_val = ReadCoreReg(Rn, &success);
+    if (!success)
+        return false;
+                  
+    AddWithCarryResult res = AddWithCarry(reg_val, ~imm32, 1);
+
+    EmulateInstruction::Context context;
+    context.type = EmulateInstruction::eContextImmediate;
+    context.SetNoArgs ();
+
+    if (!WriteCoreRegOptionalFlags(context, res.result, Rd, setflags, res.carry_out, res.overflow))
+        return false;
+
+    return true;
+}
+
+// Test Equivalence (immediate) performs a bitwise exclusive OR operation on a register value and an
+// immediate value.  It updates the condition flags based on the result, and discards the result.
+bool
+EmulateInstructionARM::EmulateTEQImm (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if ConditionPassed() then
+        EncodingSpecificOperations();
+        result = R[n] EOR imm32;
+        APSR.N = result<31>;
+        APSR.Z = IsZeroBit(result);
+        APSR.C = carry;
+        // APSR.V unchanged
+#endif
+
+    bool success = false;
+
+    if (ConditionPassed(opcode))
+    {
+        uint32_t Rn;
+        uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
+        uint32_t carry; // the carry bit after ARM/Thumb Expand operation
+        switch (encoding)
+        {
+        case eEncodingT1:
+            Rn = Bits32(opcode, 19, 16);
+            imm32 = ThumbExpandImm_C (opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
+            if (BadReg(Rn))
+                return false;
+            break;
+        case eEncodingA1:
+            Rn = Bits32(opcode, 19, 16);
+            imm32 = ARMExpandImm_C (opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
+            break;
+        default:
+            return false;
+        }
+
+        // Read the first operand.
+        uint32_t val1 = ReadCoreReg(Rn, &success);
+        if (!success)
+            return false;
+
+        uint32_t result = val1 ^ imm32;
+
+        EmulateInstruction::Context context;
+        context.type = EmulateInstruction::eContextImmediate;
+        context.SetNoArgs ();
+
+        if (!WriteFlags(context, result, carry))
+            return false;
+    }
+    return true;
+}
+
+// Test Equivalence (register) performs a bitwise exclusive OR operation on a register value and an
+// optionally-shifted register value.  It updates the condition flags based on the result, and discards
+// the result.
+bool
+EmulateInstructionARM::EmulateTEQReg (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if ConditionPassed() then
+        EncodingSpecificOperations();
+        (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
+        result = R[n] EOR shifted;
+        APSR.N = result<31>;
+        APSR.Z = IsZeroBit(result);
+        APSR.C = carry;
+        // APSR.V unchanged
+#endif
+
+    bool success = false;
+
+    if (ConditionPassed(opcode))
+    {
+        uint32_t Rn, Rm;
+        ARM_ShifterType shift_t;
+        uint32_t shift_n; // the shift applied to the value read from Rm
+        uint32_t carry;
+        switch (encoding)
+        {
+        case eEncodingT1:
+            Rn = Bits32(opcode, 19, 16);
+            Rm = Bits32(opcode, 3, 0);
+            shift_n = DecodeImmShiftThumb(opcode, shift_t);
+            if (BadReg(Rn) || BadReg(Rm))
+                return false;
+            break;
+        case eEncodingA1:
+            Rn = Bits32(opcode, 19, 16);
+            Rm = Bits32(opcode, 3, 0);
+            shift_n = DecodeImmShiftARM(opcode, shift_t);
+            break;
+        default:
+            return false;
+        }
+
+        // Read the first operand.
+        uint32_t val1 = ReadCoreReg(Rn, &success);
+        if (!success)
+            return false;
+
+        // Read the second operand.
+        uint32_t val2 = ReadCoreReg(Rm, &success);
+        if (!success)
+            return false;
+
+        uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
+        if (!success)
+            return false;
+        uint32_t result = val1 ^ shifted;
+
+        EmulateInstruction::Context context;
+        context.type = EmulateInstruction::eContextImmediate;
+        context.SetNoArgs ();
+
+        if (!WriteFlags(context, result, carry))
+            return false;
+    }
+    return true;
+}
+
+// Test (immediate) performs a bitwise AND operation on a register value and an immediate value.
+// It updates the condition flags based on the result, and discards the result.
+bool
+EmulateInstructionARM::EmulateTSTImm (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if ConditionPassed() then
+        EncodingSpecificOperations();
+        result = R[n] AND imm32;
+        APSR.N = result<31>;
+        APSR.Z = IsZeroBit(result);
+        APSR.C = carry;
+        // APSR.V unchanged
+#endif
+
+    bool success = false;
+
+    if (ConditionPassed(opcode))
+    {
+        uint32_t Rn;
+        uint32_t imm32; // the immediate value to be ANDed to the value obtained from Rn
+        uint32_t carry; // the carry bit after ARM/Thumb Expand operation
+        switch (encoding)
+        {
+        case eEncodingT1:
+            Rn = Bits32(opcode, 19, 16);
+            imm32 = ThumbExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ThumbExpandImm(i:imm3:imm8, APSR.C)
+            if (BadReg(Rn))
+                return false;
+            break;
+        case eEncodingA1:
+            Rn = Bits32(opcode, 19, 16);
+            imm32 = ARMExpandImm_C(opcode, APSR_C, carry); // (imm32, carry) = ARMExpandImm(imm12, APSR.C)
+            break;
+        default:
+            return false;
+        }
+
+        // Read the first operand.
+        uint32_t val1 = ReadCoreReg(Rn, &success);
+        if (!success)
+            return false;
+
+        uint32_t result = val1 & imm32;
+
+        EmulateInstruction::Context context;
+        context.type = EmulateInstruction::eContextImmediate;
+        context.SetNoArgs ();
+
+        if (!WriteFlags(context, result, carry))
+            return false;
+    }
+    return true;
+}
+
+// Test (register) performs a bitwise AND operation on a register value and an optionally-shifted register value.
+// It updates the condition flags based on the result, and discards the result.
+bool
+EmulateInstructionARM::EmulateTSTReg (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    // ARM pseudo code...
+    if ConditionPassed() then
+        EncodingSpecificOperations();
+        (shifted, carry) = Shift_C(R[m], shift_t, shift_n, APSR.C);
+        result = R[n] AND shifted;
+        APSR.N = result<31>;
+        APSR.Z = IsZeroBit(result);
+        APSR.C = carry;
+        // APSR.V unchanged
+#endif
+
+    bool success = false;
+
+    if (ConditionPassed(opcode))
+    {
+        uint32_t Rn, Rm;
+        ARM_ShifterType shift_t;
+        uint32_t shift_n; // the shift applied to the value read from Rm
+        uint32_t carry;
+        switch (encoding)
+        {
+        case eEncodingT1:
+            Rn = Bits32(opcode, 2, 0);
+            Rm = Bits32(opcode, 5, 3);
+            shift_t = SRType_LSL;
+            shift_n = 0;
+            break;
+        case eEncodingT2:
+            Rn = Bits32(opcode, 19, 16);
+            Rm = Bits32(opcode, 3, 0);
+            shift_n = DecodeImmShiftThumb(opcode, shift_t);
+            if (BadReg(Rn) || BadReg(Rm))
+                return false;
+            break;
+        case eEncodingA1:
+            Rn = Bits32(opcode, 19, 16);
+            Rm = Bits32(opcode, 3, 0);
+            shift_n = DecodeImmShiftARM(opcode, shift_t);
+            break;
+        default:
+            return false;
+        }
+
+        // Read the first operand.
+        uint32_t val1 = ReadCoreReg(Rn, &success);
+        if (!success)
+            return false;
+
+        // Read the second operand.
+        uint32_t val2 = ReadCoreReg(Rm, &success);
+        if (!success)
+            return false;
+
+        uint32_t shifted = Shift_C(val2, shift_t, shift_n, APSR_C, carry, &success);
+        if (!success)
+            return false;
+        uint32_t result = val1 & shifted;
+
+        EmulateInstruction::Context context;
+        context.type = EmulateInstruction::eContextImmediate;
+        context.SetNoArgs ();
+
+        if (!WriteFlags(context, result, carry))
+            return false;
+    }
+    return true;
+}
+                  
+// A8.6.216 SUB (SP minus register)
+bool
+EmulateInstructionARM::EmulateSUBSPReg (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    if ConditionPassed() then
+        EncodingSpecificOperations();
+        shifted = Shift(R[m], shift_t, shift_n, APSR.C);
+        (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), �1�);
+        if d == 15 then // Can only occur for ARM encoding
+            ALUWritePC(result); // setflags is always FALSE here
+        else
+            R[d] = result;
+            if setflags then
+                APSR.N = result<31>;
+                APSR.Z = IsZeroBit(result);
+                APSR.C = carry;
+                APSR.V = overflow;
+#endif
+                  
+    bool success = false;
+                  
+    if (ConditionPassed(opcode))
+    {
+        uint32_t d;
+        uint32_t m;
+        bool setflags;
+        ARM_ShifterType shift_t;
+        uint32_t shift_n;
+
+        switch (encoding)
+        {
+            case eEncodingT1:
+                // d = UInt(Rd); m = UInt(Rm); setflags = (S == �1�);
+                d = Bits32 (opcode, 11, 8);
+                m = Bits32 (opcode, 3, 0);
+                setflags = BitIsSet (opcode, 20);
+
+                // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);
+                shift_n = DecodeImmShiftThumb (opcode, shift_t);
+
+                // if d == 13 && (shift_t != SRType_LSL || shift_n > 3) then UNPREDICTABLE;
+                if ((d == 13) && ((shift_t != SRType_LSL) || (shift_n > 3)))
+                    return false;
+
+                // if d == 15 || BadReg(m) then UNPREDICTABLE;
+                if ((d == 15) || BadReg (m))
+                    return false;
+                break;
+
+            case eEncodingA1:
+                // d = UInt(Rd); m = UInt(Rm); setflags = (S == �1�);
+                d = Bits32 (opcode, 15, 12);
+                m = Bits32 (opcode, 3, 0);
+                setflags = BitIsSet (opcode, 20);
+                
+                // if Rd == �1111� && S == �1� then SEE SUBS PC, LR and related instructions;
+                if (d == 15 && setflags)
+                    EmulateSUBSPcLrEtc (opcode, encoding);
+
+                // (shift_t, shift_n) = DecodeImmShift(type, imm5);
+                shift_n = DecodeImmShiftARM (opcode, shift_t);
+                break;
+
+            default:
+                return false;
+        }
+
+        // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
+        uint32_t Rm = ReadCoreReg (m, &success);
+        if (!success)
+            return false;
+
+        uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C, &success);
+        if (!success)
+            return false;
+
+        // (result, carry, overflow) = AddWithCarry(SP, NOT(shifted), �1�);
+        uint32_t sp_val = ReadCoreReg (SP_REG, &success);
+        if (!success)
+            return false;
+
+        AddWithCarryResult res = AddWithCarry (sp_val, ~shifted, 1);
+
+        EmulateInstruction::Context context;
+        context.type = eContextArithmetic;
+        RegisterInfo sp_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg);
+        RegisterInfo dwarf_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, dwarf_reg);
+        context.SetRegisterRegisterOperands (sp_reg, dwarf_reg);
+
+        if (!WriteCoreRegOptionalFlags(context, res.result, dwarf_r0 + d, setflags, res.carry_out, res.overflow))
+            return false;
+    }
+    return true;
+}
+                  
+                 
+// A8.6.7 ADD (register-shifted register)
+bool
+EmulateInstructionARM::EmulateADDRegShift (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    if ConditionPassed() then
+        EncodingSpecificOperations();
+        shift_n = UInt(R[s]<7:0>);
+        shifted = Shift(R[m], shift_t, shift_n, APSR.C);
+        (result, carry, overflow) = AddWithCarry(R[n], shifted, �0�);
+        R[d] = result;
+        if setflags then
+            APSR.N = result<31>;
+            APSR.Z = IsZeroBit(result);
+            APSR.C = carry;
+            APSR.V = overflow;
+#endif
+    
+    bool success = false;
+    
+    if (ConditionPassed(opcode))
+    {
+        uint32_t d;
+        uint32_t n;
+        uint32_t m;
+        uint32_t s;
+        bool setflags;
+        ARM_ShifterType shift_t;
+                  
+        switch (encoding)
+        {
+            case eEncodingA1:
+                // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); s = UInt(Rs);
+                d = Bits32 (opcode, 15, 12);
+                n = Bits32 (opcode, 19, 16);
+                m = Bits32 (opcode, 3, 0);
+                s = Bits32 (opcode, 11, 8);
+                  
+                // setflags = (S == �1�); shift_t = DecodeRegShift(type);
+                setflags = BitIsSet (opcode, 20);
+                shift_t = DecodeRegShift (Bits32 (opcode, 6, 5));
+                  
+                // if d == 15 || n == 15 || m == 15 || s == 15 then UNPREDICTABLE;
+                if ((d == 15) || (m == 15) || (m == 15) || (s == 15))
+                    return false;
+                break;
+                  
+            default:
+                return false;
+        }
+                  
+        // shift_n = UInt(R[s]<7:0>);
+        uint32_t Rs = ReadCoreReg (s, &success);
+        if (!success)
+            return false;
+                  
+        uint32_t shift_n = Bits32 (Rs, 7, 0);
+                  
+        // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
+        uint32_t Rm = ReadCoreReg (m, &success);
+        if (!success)
+            return false;
+                  
+        uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C, &success);
+        if (!success)
+            return false;
+
+        // (result, carry, overflow) = AddWithCarry(R[n], shifted, �0�);
+        uint32_t Rn = ReadCoreReg (n, &success);
+        if (!success)
+            return false;
+                  
+        AddWithCarryResult res = AddWithCarry (Rn, shifted, 0);
+                  
+        // R[d] = result;
+        EmulateInstruction::Context context;
+        context.type = eContextArithmetic;
+        RegisterInfo reg_n;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, reg_n);
+        RegisterInfo reg_m;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, reg_m);
+            
+        context.SetRegisterRegisterOperands (reg_n, reg_m);
+        
+        if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, res.result))
+            return false;
+                  
+        // if setflags then
+            // APSR.N = result<31>;
+            // APSR.Z = IsZeroBit(result);
+            // APSR.C = carry;
+            // APSR.V = overflow;
+        if (setflags)
+            return WriteFlags (context, res.result, res.carry_out, res.overflow);
+    }
+    return true;
+}
+
+// A8.6.213 SUB (register)
+bool
+EmulateInstructionARM::EmulateSUBReg (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    if ConditionPassed() then
+        EncodingSpecificOperations();
+        shifted = Shift(R[m], shift_t, shift_n, APSR.C);
+        (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), �1�);
+        if d == 15 then // Can only occur for ARM encoding
+            ALUWritePC(result); // setflags is always FALSE here
+        else
+            R[d] = result;
+            if setflags then
+                APSR.N = result<31>;
+                APSR.Z = IsZeroBit(result);
+                APSR.C = carry;
+                APSR.V = overflow;
+#endif
+    
+    bool success = false;
+    
+    if (ConditionPassed(opcode))
+    {
+        uint32_t d;
+        uint32_t n;
+        uint32_t m;
+        bool setflags;
+        ARM_ShifterType shift_t;
+        uint32_t shift_n;
+                  
+        switch (encoding)
+        {
+            case eEncodingT1:
+                // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = !InITBlock();
+                d = Bits32 (opcode, 2, 0);
+                n = Bits32 (opcode, 5, 3);
+                m = Bits32 (opcode, 8, 6);
+                setflags = !InITBlock();
+                  
+                // (shift_t, shift_n) = (SRType_LSL, 0);
+                shift_t = SRType_LSL;
+                shift_n = 0;
+                  
+                break;
+                  
+            case eEncodingT2:
+                // if Rd == �1111� && S == �1� then SEE CMP (register);
+                // if Rn == �1101� then SEE SUB (SP minus register);
+                // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == �1�);
+                d = Bits32 (opcode, 11, 8);
+                n = Bits32 (opcode, 19, 16);
+                m = Bits32 (opcode, 3, 0);
+                setflags = BitIsSet (opcode, 20);
+                  
+                // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2);
+                shift_n = DecodeImmShiftThumb (opcode, shift_t);
+                  
+                // if d == 13 || (d == 15 && S == '0') || n == 15 || BadReg(m) then UNPREDICTABLE;
+                if ((d == 13) || ((d == 15) && BitIsClear (opcode, 20)) || (n == 15) || BadReg (m))
+                    return false;
+                  
+                break;
+                  
+            case eEncodingA1:
+                // if Rn == �1101� then SEE SUB (SP minus register);
+                // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == �1�);
+                d = Bits32 (opcode, 15, 12);
+                n = Bits32 (opcode, 19, 16);
+                m = Bits32 (opcode, 3, 0);
+                setflags = BitIsSet (opcode, 20);
+                
+                // if Rd == �1111� && S == �1� then SEE SUBS PC, LR and related instructions;
+                if ((d == 15) && setflags)
+                    EmulateSUBSPcLrEtc (opcode, encoding);
+                  
+                // (shift_t, shift_n) = DecodeImmShift(type, imm5);
+                shift_n = DecodeImmShiftARM (opcode, shift_t);
+                  
+                break;
+                  
+            default:
+                return false;
+        }
+                  
+        // shifted = Shift(R[m], shift_t, shift_n, APSR.C);
+        uint32_t Rm = ReadCoreReg (m, &success);
+        if (!success)
+            return false;
+                  
+        uint32_t shifted = Shift (Rm, shift_t, shift_n, APSR_C, &success);
+        if (!success)
+            return false;
+                  
+        // (result, carry, overflow) = AddWithCarry(R[n], NOT(shifted), �1�);
+        uint32_t Rn = ReadCoreReg (n, &success);
+        if (!success)
+            return false;
+                  
+        AddWithCarryResult res = AddWithCarry (Rn, ~shifted, 1);
+                  
+        // if d == 15 then // Can only occur for ARM encoding
+            // ALUWritePC(result); // setflags is always FALSE here
+        // else
+            // R[d] = result;
+            // if setflags then
+                // APSR.N = result<31>;
+                // APSR.Z = IsZeroBit(result);
+                // APSR.C = carry;
+                // APSR.V = overflow;
+                  
+        EmulateInstruction::Context context;
+        context.type = eContextArithmetic;
+        RegisterInfo reg_n;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, reg_n);
+        RegisterInfo reg_m;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, reg_m);
+        context.SetRegisterRegisterOperands (reg_n, reg_m);
+                  
+        if (!WriteCoreRegOptionalFlags (context, res.result, dwarf_r0 + d, setflags, res.carry_out, res.overflow))
+            return false;
+    }
+    return true;
+}
+                  
+// A8.6.202 STREX
+// Store Register Exclusive calculates an address from a base register value and an immediate offset, and stores a 
+// word from a register to memory if the executing processor has exclusive access to the memory addressed.
+bool
+EmulateInstructionARM::EmulateSTREX (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    if ConditionPassed() then
+        EncodingSpecificOperations(); NullCheckIfThumbEE(n);
+        address = R[n] + imm32;
+        if ExclusiveMonitorsPass(address,4) then
+            MemA[address,4] = R[t];
+            R[d] = 0;
+        else
+            R[d] = 1;
+#endif
+    
+    bool success = false;
+    
+    if (ConditionPassed(opcode))
+    {
+        uint32_t d;
+        uint32_t t;
+        uint32_t n;
+        uint32_t imm32;
+        const uint32_t addr_byte_size = GetAddressByteSize();
+                  
+        switch (encoding)
+        {
+            case eEncodingT1:
+                // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8:�00�, 32);
+                d = Bits32 (opcode, 11, 8);
+                t = Bits32 (opcode, 15, 12);
+                n = Bits32 (opcode, 19, 16);
+                imm32 = Bits32 (opcode, 7, 0) << 2;
+                  
+                // if BadReg(d) || BadReg(t) || n == 15 then UNPREDICTABLE;
+                if (BadReg (d) || BadReg (t) || (n == 15))
+                  return false;
+                  
+                // if d == n || d == t then UNPREDICTABLE;
+                if ((d == n) || (d == t))
+                  return false;
+                  
+                break;
+                  
+            case eEncodingA1:
+                // d = UInt(Rd); t = UInt(Rt); n = UInt(Rn); imm32 = Zeros(32); // Zero offset
+                d = Bits32 (opcode, 15, 12);
+                t = Bits32 (opcode, 3, 0);
+                n = Bits32 (opcode, 19, 16);
+                imm32 = 0;
+                  
+                // if d == 15 || t == 15 || n == 15 then UNPREDICTABLE;
+                if ((d == 15) || (t == 15) || (n == 15))
+                    return false;
+                  
+                // if d == n || d == t then UNPREDICTABLE;
+                if ((d == n) || (d == t))
+                    return false;
+                  
+                break;
+                  
+            default:
+                return false;
+        }
+                  
+        // address = R[n] + imm32;
+        uint32_t Rn = ReadCoreReg (n, &success);
+        if (!success)
+            return false;
+                  
+        addr_t address = Rn + imm32;
+                  
+        RegisterInfo base_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
+        RegisterInfo data_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
+        EmulateInstruction::Context context;
+        context.type = eContextRegisterStore;
+        context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, imm32);
+                  
+        // if ExclusiveMonitorsPass(address,4) then
+        // if (ExclusiveMonitorsPass (address, addr_byte_size)) -- For now, for the sake of emulation, we will say this
+        //                                                         always return true.
+        if (true)
+        {
+            // MemA[address,4] = R[t];
+            uint32_t Rt = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + t, 0, &success);
+            if (!success)
+                return false;
+                  
+            if (!MemAWrite (context, address, Rt, addr_byte_size))
+                return false;
+                  
+            // R[d] = 0;
+            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 0))
+                return false;
+        }
+        else
+        {
+            // R[d] = 1;
+            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, 1))
+                return false;
+        }
+    }
+    return true;
+}
+
+// A8.6.197 STRB (immediate, ARM)
+bool
+EmulateInstructionARM::EmulateSTRBImmARM (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    if ConditionPassed() then
+        EncodingSpecificOperations();
+        offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
+        address = if index then offset_addr else R[n];
+        MemU[address,1] = R[t]<7:0>;
+        if wback then R[n] = offset_addr;
+#endif
+    
+    bool success = false;
+    
+    if (ConditionPassed(opcode))
+    {
+        uint32_t t;
+        uint32_t n;
+        uint32_t imm32;
+        bool index;
+        bool add;
+        bool wback;
+                  
+        switch (encoding)
+        {
+            case eEncodingA1:
+                // if P == �0� && W == �1� then SEE STRBT;
+                // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
+                t = Bits32 (opcode, 15, 12);
+                n = Bits32 (opcode, 19, 16);
+                imm32 = Bits32 (opcode, 11, 0);
+                  
+                // index = (P == �1�); add = (U == �1�); wback = (P == �0�) || (W == �1�);
+                index = BitIsSet (opcode, 24);
+                add = BitIsSet (opcode, 23);
+                wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
+                  
+                // if t == 15 then UNPREDICTABLE;
+                if (t == 15)
+                    return false;
+                  
+                // if wback && (n == 15 || n == t) then UNPREDICTABLE;
+                if (wback && ((n == 15) || (n == t)))
+                    return false;
+                  
+                break;
+                  
+            default:
+                return false;
+        }
+                  
+        // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
+        uint32_t Rn = ReadCoreReg (n, &success);
+        if (!success)
+            return false;
+                  
+        addr_t offset_addr;
+        if (add)
+            offset_addr = Rn + imm32;
+        else
+            offset_addr = Rn - imm32;
+                  
+        // address = if index then offset_addr else R[n];
+        addr_t address;
+        if (index)
+            address = offset_addr;
+        else
+            address = Rn;
+                  
+        // MemU[address,1] = R[t]<7:0>;
+        uint32_t Rt = ReadCoreReg (t, &success);
+        if (!success)
+            return false;
+                  
+        RegisterInfo base_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
+        RegisterInfo data_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
+        EmulateInstruction::Context context;
+        context.type = eContextRegisterStore;
+        context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
+                  
+        if (!MemUWrite (context, address, Bits32 (Rt, 7, 0), 1))
+            return false;
+                  
+        // if wback then R[n] = offset_addr;
+        if (wback)
+        {
+            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
+                return false;
+        }
+    }
+    return true;
+}
+
+// A8.6.194 STR (immediate, ARM)
+bool
+EmulateInstructionARM::EmulateSTRImmARM (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    if ConditionPassed() then
+        EncodingSpecificOperations();
+        offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
+        address = if index then offset_addr else R[n];
+        MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
+        if wback then R[n] = offset_addr;
+#endif
+    
+    bool success = false;
+    
+    if (ConditionPassed(opcode))
+    {
+        uint32_t t;
+        uint32_t n;
+        uint32_t imm32;
+        bool index;
+        bool add;
+        bool wback;
+                  
+        const uint32_t addr_byte_size = GetAddressByteSize();
+                  
+        switch (encoding)
+        {
+            case eEncodingA1:
+                // if P == �0� && W == �1� then SEE STRT;
+                // if Rn == �1101� && P == �1� && U == �0� && W == �1� && imm12 == �000000000100� then SEE PUSH;
+                // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32);
+                t = Bits32 (opcode, 15, 12);
+                n = Bits32 (opcode, 19, 16);
+                imm32 = Bits32 (opcode, 11, 0);
+                  
+                // index = (P == �1�); add = (U == �1�); wback = (P == �0�) || (W == �1�);
+                index = BitIsSet (opcode, 24);
+                add = BitIsSet (opcode, 23);
+                wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
+                  
+                // if wback && (n == 15 || n == t) then UNPREDICTABLE;
+                if (wback && ((n == 15) || (n == t)))
+                    return false;
+                  
+                break;
+                  
+            default:
+                return false;
+        }
+                  
+        // offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
+        uint32_t Rn = ReadCoreReg (n, &success);
+        if (!success)
+            return false;
+                  
+        addr_t offset_addr;
+        if (add)
+            offset_addr = Rn + imm32;
+        else
+            offset_addr = Rn - imm32;
+                  
+        // address = if index then offset_addr else R[n];
+        addr_t address;
+        if (index)
+            address = offset_addr;
+        else
+            address = Rn;
+                  
+        RegisterInfo base_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
+        RegisterInfo data_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
+        EmulateInstruction::Context context;
+        context.type = eContextRegisterStore;
+        context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
+                  
+        // MemU[address,4] = if t == 15 then PCStoreValue() else R[t];
+        uint32_t Rt = ReadCoreReg (t, &success);
+        if (!success)
+            return false;
+                  
+        if (t == 15)
+        {
+            uint32_t pc_value = ReadCoreReg (PC_REG, &success);
+            if (!success)
+                return false;
+                  
+            if (!MemUWrite (context, address, pc_value, addr_byte_size))
+                return false;
+        }
+        else
+        {
+            if (!MemUWrite (context, address, Rt, addr_byte_size))
+                  return false;
+        }
+                  
+        // if wback then R[n] = offset_addr;
+        if (wback)
+        {
+            context.type = eContextAdjustBaseRegister;
+            context.SetImmediate (offset_addr);
+                  
+            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
+                return false;
+        }
+    }
+    return true;
+}
+
+// A8.6.66 LDRD (immediate)
+// Load Register Dual (immediate) calculates an address from a base register value and an immediate offset, loads two
+// words from memory, and writes them to two registers.  It can use offset, post-indexed, or pre-indexed addressing.
+bool
+EmulateInstructionARM::EmulateLDRDImmediate (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    if ConditionPassed() then
+        EncodingSpecificOperations(); NullCheckIfThumbEE(n);
+        offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
+        address = if index then offset_addr else R[n];
+        R[t] = MemA[address,4];
+        R[t2] = MemA[address+4,4];
+        if wback then R[n] = offset_addr;
+#endif
+                  
+    bool success = false;
+                  
+    if (ConditionPassed(opcode))
+    {
+        uint32_t t;
+        uint32_t t2;
+        uint32_t n;
+        uint32_t imm32;
+        bool index;
+        bool add;
+        bool wback;
+                  
+        switch (encoding)
+        {
+            case eEncodingT1:
+                //if P == �0� && W == �0� then SEE �Related encodings�;
+                //if Rn == �1111� then SEE LDRD (literal);
+                //t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:�00�, 32);
+                t = Bits32 (opcode, 15, 12);
+                t2 = Bits32 (opcode, 11, 8);
+                n = Bits32 (opcode, 19, 16);
+                imm32 = Bits32 (opcode, 7, 0) << 2;
+                  
+                //index = (P == �1�); add = (U == �1�); wback = (W == �1�);
+                index = BitIsSet (opcode, 24);
+                add = BitIsSet (opcode, 23);
+                wback = BitIsSet (opcode, 21);
+                  
+                //if wback && (n == t || n == t2) then UNPREDICTABLE;
+                if (wback && ((n == t) || (n == t2)))
+                    return false;
+                  
+                //if BadReg(t) || BadReg(t2) || t == t2 then UNPREDICTABLE;
+                if (BadReg (t) || BadReg (t2) || (t == t2))
+                    return false;
+                  
+                break;
+                  
+            case eEncodingA1:
+                //if Rn == �1111� then SEE LDRD (literal);
+                //if Rt<0> == �1� then UNPREDICTABLE;
+                //t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
+                t = Bits32 (opcode, 15, 12);
+                if (BitIsSet (t, 0))
+                    return false;
+                t2 = t + 1;
+                n = Bits32 (opcode, 19, 16);
+                imm32 = (Bits32 (opcode, 11, 8) << 4) | Bits32 (opcode, 3, 0);
+                  
+                //index = (P == �1�); add = (U == �1�); wback = (P == �0�) || (W == �1�);
+                index = BitIsSet (opcode, 24);
+                add = BitIsSet (opcode, 23);
+                wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
+                  
+                //if P == �0� && W == �1� then UNPREDICTABLE;
+                if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
+                    return false;
+                  
+                //if wback && (n == t || n == t2) then UNPREDICTABLE;
+                if (wback && ((n == t) || (n == t2)))
+                    return false;
+                  
+                //if t2 == 15 then UNPREDICTABLE;
+                if (t2 == 15)
+                    return false;
+                  
+                break;
+                  
+            default:
+                return false;
+        }
+                  
+        //offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
+        uint32_t Rn = ReadCoreReg (n, &success);
+        if (!success)
+            return false;
+                  
+        addr_t offset_addr;
+        if (add)
+                  offset_addr = Rn + imm32;
+        else
+            offset_addr = Rn - imm32;
+                  
+        //address = if index then offset_addr else R[n];
+        addr_t address;
+        if (index)
+            address = offset_addr;
+        else
+            address = Rn;
+                  
+        //R[t] = MemA[address,4];
+        RegisterInfo base_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
+                  
+        EmulateInstruction::Context context;
+        context.type = eContextRegisterLoad;
+        context.SetRegisterPlusOffset (base_reg, address - Rn);
+                  
+        const uint32_t addr_byte_size = GetAddressByteSize();
+        uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
+        if (!success)
+            return false;
+                  
+        if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
+            return false;
+                  
+        //R[t2] = MemA[address+4,4];
+                  
+        context.SetRegisterPlusOffset (base_reg, (address + 4) - Rn);
+        data = MemARead (context, address + 4, addr_byte_size, 0, &success);
+        if (!success)
+            return false;
+                  
+        if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t2, data))
+            return false;
+                  
+        //if wback then R[n] = offset_addr;
+        if (wback)
+        {
+            context.type = eContextAdjustBaseRegister;
+            context.SetAddress (offset_addr);
+            
+            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
+                return false;
+        }
+    }
+    return true;
+}
+                  
+// A8.6.68 LDRD (register)
+// Load Register Dual (register) calculates an address from a base register value and a register offset, loads two 
+// words from memory, and writes them to two registers.  It can use offset, post-indexed or pre-indexed addressing.
+bool
+EmulateInstructionARM::EmulateLDRDRegister (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    if ConditionPassed() then
+        EncodingSpecificOperations();
+        offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
+        address = if index then offset_addr else R[n];
+        R[t] = MemA[address,4];
+        R[t2] = MemA[address+4,4];
+        if wback then R[n] = offset_addr;
+#endif
+                  
+    bool success = false;
+                  
+    if (ConditionPassed(opcode))
+    {
+        uint32_t t;
+        uint32_t t2;
+        uint32_t n;
+        uint32_t m;
+        bool index;
+        bool add;
+        bool wback;
+                  
+        switch (encoding)
+        {
+            case eEncodingA1:
+                // if Rt<0> == �1� then UNPREDICTABLE;
+                // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);
+                t = Bits32 (opcode, 15, 12);
+                if (BitIsSet (t, 0))
+                    return false;
+                t2 = t + 1;
+                n = Bits32 (opcode, 19, 16);
+                m = Bits32 (opcode, 3, 0);
+                  
+                // index = (P == �1�); add = (U == �1�); wback = (P == �0�) || (W == �1�);
+                index = BitIsSet (opcode, 24);
+                add = BitIsSet (opcode, 23);
+                wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
+                  
+                // if P == �0� && W == �1� then UNPREDICTABLE;
+                  if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
+                  return false;
+                  
+                // if t2 == 15 || m == 15 || m == t || m == t2 then UNPREDICTABLE;
+                  if ((t2 == 15) || (m == 15) || (m == t) || (m == t2))
+                  return false;
+                  
+                // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
+                  if (wback && ((n == 15) || (n == t) || (n == t2)))
+                  return false;
+                  
+                // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE;
+                if ((ArchVersion() < 6) && wback && (m == n))
+                  return false;
+                break;
+                  
+            default:
+                return false;
+        }
+                  
+        uint32_t Rn = ReadCoreReg (n, &success);
+        if (!success)
+            return false;
+        RegisterInfo base_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
+                  
+        uint32_t Rm = ReadCoreReg (m, &success);
+        if (!success)
+            return false;
+        RegisterInfo offset_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
+                  
+        // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
+        addr_t offset_addr;
+        if (add)
+            offset_addr = Rn + Rm;
+        else
+            offset_addr = Rn - Rm;
+                  
+        // address = if index then offset_addr else R[n];
+        addr_t address;
+        if (index)
+            address = offset_addr;
+        else
+            address = Rn;
+                  
+        EmulateInstruction::Context context;
+        context.type = eContextRegisterLoad;
+        context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
+                  
+        // R[t] = MemA[address,4];
+        const uint32_t addr_byte_size = GetAddressByteSize();
+        uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
+        if (!success)
+            return false;
+                  
+        if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t, data))
+            return false;
+                  
+        // R[t2] = MemA[address+4,4];
+                  
+        data = MemARead (context, address + 4, addr_byte_size, 0, &success);
+        if (!success)
+            return false;
+                  
+        if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + t2, data))
+            return false;
+                  
+        // if wback then R[n] = offset_addr;
+        if (wback)
+        {
+            context.type = eContextAdjustBaseRegister;
+            context.SetAddress (offset_addr);
+                  
+            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
+                return false;
+        }
+    }
+    return true;
+}
+
+// A8.6.200 STRD (immediate)
+// Store Register Dual (immediate) calculates an address from a base register value and an immediate offset, and 
+// stores two words from two registers to memory.  It can use offset, post-indexed, or pre-indexed addressing.
+bool
+EmulateInstructionARM::EmulateSTRDImm (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    if ConditionPassed() then
+        EncodingSpecificOperations(); NullCheckIfThumbEE(n);
+        offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
+        address = if index then offset_addr else R[n];
+        MemA[address,4] = R[t];
+        MemA[address+4,4] = R[t2];
+        if wback then R[n] = offset_addr;
+#endif
+                  
+    bool success = false;
+                  
+    if (ConditionPassed(opcode))
+    {
+        uint32_t t;
+        uint32_t t2;
+        uint32_t n;
+        uint32_t imm32;
+        bool index;
+        bool add;
+        bool wback;
+                  
+        switch (encoding)
+        {
+            case eEncodingT1:
+                // if P == �0� && W == �0� then SEE �Related encodings�;
+                // t = UInt(Rt); t2 = UInt(Rt2); n = UInt(Rn); imm32 = ZeroExtend(imm8:�00�, 32);
+                t = Bits32 (opcode, 15, 12);
+                t2 = Bits32 (opcode, 11, 8);
+                n = Bits32 (opcode, 19, 16);
+                imm32 = Bits32 (opcode, 7, 0) << 2;
+                  
+                // index = (P == �1�); add = (U == �1�); wback = (W == �1�);
+                index = BitIsSet (opcode, 24);
+                add = BitIsSet (opcode, 23);
+                wback = BitIsSet (opcode, 21);
+                
+                // if wback && (n == t || n == t2) then UNPREDICTABLE;
+                if (wback && ((n == t) || (n == t2)))
+                    return false;
+                  
+                // if n == 15 || BadReg(t) || BadReg(t2) then UNPREDICTABLE;
+                if ((n == 15) || BadReg (t) || BadReg (t2))
+                    return false;
+                  
+                break;
+                  
+            case eEncodingA1:
+                // if Rt<0> == �1� then UNPREDICTABLE;
+                // t = UInt(Rt); t2 = t+1; n = UInt(Rn); imm32 = ZeroExtend(imm4H:imm4L, 32);
+                t = Bits32 (opcode, 15, 12);
+                if (BitIsSet (t, 0))
+                    return false;
+                  
+                t2 = t + 1;
+                n = Bits32 (opcode, 19, 16);
+                imm32 = (Bits32 (opcode, 11, 8) << 4) | Bits32 (opcode, 3, 0);
+                  
+                // index = (P == �1�); add = (U == �1�); wback = (P == �0�) || (W == �1�);
+                index = BitIsSet (opcode, 24);
+                add = BitIsSet (opcode, 23);
+                wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
+                  
+                // if P == �0� && W == �1� then UNPREDICTABLE;
+                if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
+                    return false;
+                  
+                // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
+                if (wback && ((n == 15) || (n == t) || (n == t2)))
+                    return false;
+                  
+                // if t2 == 15 then UNPREDICTABLE;
+                if (t2 == 15)
+                    return false;
+                  
+                break;
+                  
+            default:
+                return false;
+        }
+                  
+        RegisterInfo base_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
+        
+        uint32_t Rn = ReadCoreReg (n, &success);
+        if (!success)
+            return false;
+                  
+        //offset_addr = if add then (R[n] + imm32) else (R[n] - imm32);
+        addr_t offset_addr;
+        if (add)
+            offset_addr = Rn + imm32;
+        else 
+            offset_addr = Rn - imm32;
+                  
+        //address = if index then offset_addr else R[n];
+        addr_t address;
+        if (index)
+            address = offset_addr;
+        else
+            address = Rn;
+                  
+        //MemA[address,4] = R[t];
+        RegisterInfo data_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
+                  
+        uint32_t data = ReadCoreReg (t, &success);
+        if (!success)
+            return false;
+                  
+        EmulateInstruction::Context context;
+        context.type = eContextRegisterStore;
+        context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
+                  
+        const uint32_t addr_byte_size = GetAddressByteSize();
+                  
+        if (!MemAWrite (context, address, data, addr_byte_size))
+            return false;
+
+        //MemA[address+4,4] = R[t2];
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t2, data_reg);
+        context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
+                  
+        data = ReadCoreReg (t2, &success);
+        if (!success)
+            return false;
+                  
+        if (!MemAWrite (context, address + 4, data, addr_byte_size))
+            return false;
+                
+        //if wback then R[n] = offset_addr;
+        if (wback)
+        {
+            context.type = eContextAdjustBaseRegister;
+            context.SetAddress (offset_addr);
+                  
+            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
+                return false;
+        }
+    }
+    return true;
+}
+                  
+                  
+// A8.6.201 STRD (register)
+bool
+EmulateInstructionARM::EmulateSTRDReg (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    if ConditionPassed() then
+        EncodingSpecificOperations();
+        offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
+        address = if index then offset_addr else R[n];
+        MemA[address,4] = R[t];
+        MemA[address+4,4] = R[t2];
+        if wback then R[n] = offset_addr;
+#endif
+                  
+    bool success = false;
+                  
+    if (ConditionPassed(opcode))
+    {
+        uint32_t t;
+        uint32_t t2;
+        uint32_t n;
+        uint32_t m;
+        bool index;
+        bool add;
+        bool wback;
+                  
+        switch (encoding)
+        {
+            case eEncodingA1:
+                // if Rt<0> == �1� then UNPREDICTABLE;
+                // t = UInt(Rt); t2 = t+1; n = UInt(Rn); m = UInt(Rm);
+                t = Bits32 (opcode, 15, 12);
+                if (BitIsSet (t, 0))
+                   return false;
+                  
+                t2 = t+1;
+                n = Bits32 (opcode, 19, 16);
+                m = Bits32 (opcode, 3, 0);
+                  
+                // index = (P == �1�); add = (U == �1�); wback = (P == �0�) || (W == �1�);
+                index = BitIsSet (opcode, 24);
+                add = BitIsSet (opcode, 23);
+                wback = BitIsClear (opcode, 24) || BitIsSet (opcode, 21);
+                  
+                // if P == �0� && W == �1� then UNPREDICTABLE;
+                if (BitIsClear (opcode, 24) && BitIsSet (opcode, 21))
+                   return false;
+                  
+                // if t2 == 15 || m == 15 then UNPREDICTABLE;
+                if ((t2 == 15) || (m == 15))
+                   return false;
+                  
+                // if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE;
+                if (wback && ((n == 15) || (n == t) || (n == t2)))
+                   return false;
+                  
+                // if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE;
+                if ((ArchVersion() < 6) && wback && (m == n))
+                   return false;
+                   
+                break;
+                  
+            default:
+                return false;
+        }
+                  
+        RegisterInfo base_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
+        RegisterInfo offset_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + m, offset_reg);
+        RegisterInfo data_reg;
+                  
+        uint32_t Rn = ReadCoreReg (n, &success);
+        if (!success)
+            return false;
+                  
+        uint32_t Rm = ReadCoreReg (m, &success);
+        if (!success)
+            return false;
+                  
+        // offset_addr = if add then (R[n] + R[m]) else (R[n] - R[m]);
+        addr_t offset_addr;
+        if (add)
+            offset_addr = Rn + Rm;
+        else
+            offset_addr = Rn - Rm;
+                  
+        // address = if index then offset_addr else R[n];
+        addr_t address;
+        if (index)
+            address = offset_addr;
+        else
+            address = Rn;
+                          // MemA[address,4] = R[t];
+        uint32_t Rt = ReadCoreReg (t, &success);
+        if (!success)
+            return false;
+                  
+        EmulateInstruction::Context context;
+        context.type = eContextRegisterStore;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t, data_reg);
+        context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg);
+                  
+        const uint32_t addr_byte_size = GetAddressByteSize();
+        
+        if (!MemAWrite (context, address, Rt, addr_byte_size))
+            return false;
+                  
+        // MemA[address+4,4] = R[t2];
+        uint32_t Rt2 = ReadCoreReg (t2, &success);
+        if (!success)
+            return false;
+                  
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + t2, data_reg);
+                
+        context.SetRegisterToRegisterPlusIndirectOffset (base_reg, offset_reg, data_reg);
+            
+        if (!MemAWrite (context, address + 4, Rt2, addr_byte_size))
+            return false;
+                  
+        // if wback then R[n] = offset_addr;
+        if (wback)
+        {
+            context.type = eContextAdjustBaseRegister;
+            context.SetAddress (offset_addr);
+                  
+            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, offset_addr))
+                return false;
+                  
+        }
+    }
+    return true;
+}
+                  
+// A8.6.319 VLDM
+// Vector Load Multiple loads multiple extension registers from consecutive memory locations using an address from 
+// an ARM core register.
+bool
+EmulateInstructionARM::EmulateVLDM (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    if ConditionPassed() then
+        EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
+        address = if add then R[n] else R[n]-imm32;
+        if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
+        for r = 0 to regs-1
+            if single_regs then
+                S[d+r] = MemA[address,4]; address = address+4;
+            else
+                word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
+                // Combine the word-aligned words in the correct order for current endianness.
+                D[d+r] = if BigEndian() then word1:word2 else word2:word1;
+#endif
+                  
+    bool success = false;
+                  
+    if (ConditionPassed(opcode))
+    {
+        bool single_regs;
+        bool add;
+        bool wback;
+        uint32_t d;
+        uint32_t n;
+        uint32_t imm32;
+        uint32_t regs;
+                                           
+        switch (encoding)
+        {
+            case eEncodingT1:
+            case eEncodingA1:
+                // if P == �0� && U == �0� && W == �0� then SEE �Related encodings�;
+                // if P == �0� && U == �1� && W == �1� && Rn == �1101� then SEE VPOP;
+                // if P == �1� && W == �0� then SEE VLDR;
+                // if P == U && W == �1� then UNDEFINED;
+                if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
+                    return false;
+                                           
+                // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
+                // single_regs = FALSE; add = (U == �1�); wback = (W == �1�);
+                single_regs = false;
+                add = BitIsSet (opcode, 23);
+                wback = BitIsSet (opcode, 21);
+                                           
+                // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:�00�, 32);
+                d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
+                n = Bits32 (opcode, 19, 16);
+                imm32 = Bits32 (opcode, 7, 0) << 2;
+                                           
+                // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see �FLDMX�.
+                regs = Bits32 (opcode, 7, 0) / 2;
+                                           
+                // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
+                if (n == 15 && (wback || CurrentInstrSet() != eModeARM))
+                    return false;
+                                           
+                // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;
+                if ((regs == 0) || (regs > 16) || ((d + regs) > 32))
+                    return false;
+                                           
+                break;
+                  
+            case eEncodingT2:
+            case eEncodingA2:
+                // if P == �0� && U == �0� && W == �0� then SEE �Related encodings�;
+                // if P == �0� && U == �1� && W == �1� && Rn == �1101� then SEE VPOP;
+                // if P == �1� && W == �0� then SEE VLDR;
+                // if P == U && W == �1� then UNDEFINED;
+                if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
+                    return false;
+                                           
+                // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
+                // single_regs = TRUE; add = (U == �1�); wback = (W == �1�); d = UInt(Vd:D); n = UInt(Rn);
+                single_regs = true;
+                add = BitIsSet (opcode, 23);
+                wback = BitIsSet (opcode, 21);
+                d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
+                n = Bits32 (opcode, 19, 16);
+                                           
+                // imm32 = ZeroExtend(imm8:�00�, 32); regs = UInt(imm8);
+                imm32 = Bits32 (opcode, 7, 0) << 2;
+                regs = Bits32 (opcode, 7, 0);
+                                           
+                // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
+                if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))
+                    return false;
+                                           
+                // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE;
+                if ((regs == 0) || ((d + regs) > 32))
+                    return false;
+                break;
+                  
+            default:
+                return false;
+        }
+                                           
+        RegisterInfo base_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
+                                           
+        uint32_t Rn = ReadCoreReg (n, &success);
+        if (!success)
+            return false;
+                                           
+        // address = if add then R[n] else R[n]-imm32;
+        addr_t address;
+        if (add)
+            address = Rn;
+        else
+            address = Rn - imm32;
+                                           
+        // if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
+        EmulateInstruction::Context context;
+                                           
+        if (wback)
+        {
+            uint32_t value;
+            if (add)
+                value = Rn + imm32;
+            else
+                value = Rn - imm32;
+                                           
+            context.type = eContextAdjustBaseRegister;
+            context.SetImmediateSigned (value - Rn);
+            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
+                return false;
+                                           
+        }
+                                           
+        const uint32_t addr_byte_size = GetAddressByteSize();
+        uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
+
+        context.type = eContextRegisterLoad;
+                                           
+        // for r = 0 to regs-1
+        for (uint32_t r = 0; r < regs; ++r)
+        {
+            if (single_regs)
+            {
+                // S[d+r] = MemA[address,4]; address = address+4;
+                context.SetRegisterPlusOffset (base_reg, address - Rn);
+                                           
+                uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
+                if (!success)
+                    return false;
+                                
+                if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d + r, data))
+                    return false;
+                                           
+                address = address + 4;
+            }
+            else
+            {
+                // word1 = MemA[address,4]; word2 = MemA[address+4,4]; address = address+8;
+                context.SetRegisterPlusOffset (base_reg, address - Rn);
+                uint32_t word1 = MemARead (context, address, addr_byte_size, 0, &success);
+                if (!success)
+                    return false;
+                                    
+                context.SetRegisterPlusOffset (base_reg, (address + 4) - Rn);
+                uint32_t word2 = MemARead (context, address + 4, addr_byte_size, 0, &success);
+                if (!success)
+                    return false;
+                                           
+                address = address + 8;
+                // // Combine the word-aligned words in the correct order for current endianness.
+                // D[d+r] = if BigEndian() then word1:word2 else word2:word1;
+                uint64_t data;
+                if (GetByteOrder() == eByteOrderBig)
+                {
+                    data = word1;
+                    data = (data << 32) | word2;
+                }
+                else
+                {
+                    data = word2;
+                    data = (data << 32) | word1;
+                }
+                                           
+                if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d + r, data))
+                    return false;
+            }
+        }
+    }
+    return true;
+}
+
+// A8.6.399 VSTM
+// Vector Store Multiple stores multiple extension registers to consecutive memory locations using an address from an
+// ARM core register.
+bool                                      
+EmulateInstructionARM::EmulateVSTM (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    if ConditionPassed() then
+        EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
+        address = if add then R[n] else R[n]-imm32;
+        if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
+        for r = 0 to regs-1
+            if single_regs then
+                MemA[address,4] = S[d+r]; address = address+4;
+            else
+                // Store as two word-aligned words in the correct order for current endianness.
+                MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
+                MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
+                address = address+8;
+#endif
+                                           
+    bool success = false;
+                                        
+    if (ConditionPassed (opcode))
+    {
+        bool single_regs;
+        bool add;
+        bool wback;
+        uint32_t d;
+        uint32_t n;
+        uint32_t imm32;
+        uint32_t regs;
+        
+        switch (encoding)
+        {
+            case eEncodingT1:
+            case eEncodingA1:
+                // if P == �0� && U == �0� && W == �0� then SEE �Related encodings�;
+                // if P == �1� && U == �0� && W == �1� && Rn == �1101� then SEE VPUSH;
+                // if P == �1� && W == �0� then SEE VSTR;
+                // if P == U && W == �1� then UNDEFINED;
+                if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
+                    return false;
+                    
+                // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
+                // single_regs = FALSE; add = (U == �1�); wback = (W == �1�);
+                single_regs = false;
+                add = BitIsSet (opcode, 23);
+                wback = BitIsSet (opcode, 21);
+                
+                // d = UInt(D:Vd); n = UInt(Rn); imm32 = ZeroExtend(imm8:�00�, 32);
+                d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
+                n = Bits32 (opcode, 19, 16);
+                imm32 = Bits32 (opcode, 7, 0) << 2;
+                
+                // regs = UInt(imm8) DIV 2; // If UInt(imm8) is odd, see �FSTMX�.
+                regs = Bits32 (opcode, 7, 0) / 2;
+                
+                // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
+                if ((n == 15) && (wback || (CurrentInstrSet() != eModeARM)))
+                    return false;
+                    
+                // if regs == 0 || regs > 16 || (d+regs) > 32 then UNPREDICTABLE;           
+                if ((regs == 0) || (regs > 16) || ((d + regs) > 32))
+                    return false;
+                    
+                break;
+                                           
+            case eEncodingT2:
+            case eEncodingA2:
+                // if P == �0� && U == �0� && W == �0� then SEE �Related encodings�;
+                // if P == �1� && U == �0� && W == �1� && Rn == �1101� then SEE VPUSH;
+                // if P == �1� && W == �0� then SEE VSTR;
+                // if P == U && W == �1� then UNDEFINED;
+                if ((Bit32 (opcode, 24) == Bit32 (opcode, 23)) && BitIsSet (opcode, 21))
+                    return false;
+                    
+                // // Remaining combinations are PUW = 010 (IA without !), 011 (IA with !), 101 (DB with !)
+                // single_regs = TRUE; add = (U == �1�); wback = (W == �1�); d = UInt(Vd:D); n = UInt(Rn);
+                single_regs = true;
+                add = BitIsSet (opcode, 23);
+                wback = BitIsSet (opcode, 21);
+                d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
+                n = Bits32 (opcode, 19, 16);
+                
+                // imm32 = ZeroExtend(imm8:�00�, 32); regs = UInt(imm8);
+                imm32 = Bits32 (opcode, 7, 0) << 2;
+                regs = Bits32 (opcode, 7, 0);
+                
+                // if n == 15 && (wback || CurrentInstrSet() != InstrSet_ARM) then UNPREDICTABLE;
+                if ((n == 15) && (wback || (CurrentInstrSet () != eModeARM)))
+                    return false;
+                    
+                // if regs == 0 || (d+regs) > 32 then UNPREDICTABLE;                     
+                if ((regs == 0) || ((d + regs) > 32))
+                    return false;
+                    
+                break;
+                                           
+            default:
+                return false;
+        }
+        
+        RegisterInfo base_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
+        
+        uint32_t Rn = ReadCoreReg (n, &success);
+        if (!success)
+            return false;
+            
+        // address = if add then R[n] else R[n]-imm32;
+        addr_t address;
+        if (add)
+            address = Rn;
+        else
+            address = Rn - imm32;
+            
+        EmulateInstruction::Context context;
+        // if wback then R[n] = if add then R[n]+imm32 else R[n]-imm32;
+        if (wback)
+        {
+            uint32_t value;
+            if (add)
+                value = Rn + imm32;
+            else
+                value = Rn - imm32;
+                
+            context.type = eContextAdjustBaseRegister;
+            context.SetRegisterPlusOffset (base_reg, value - Rn);
+            
+            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
+                return false;
+        }
+        
+        const uint32_t addr_byte_size = GetAddressByteSize();
+        uint32_t start_reg = single_regs ? dwarf_s0 : dwarf_d0;
+
+        context.type = eContextRegisterStore;
+        // for r = 0 to regs-1
+        for (uint32_t r = 0; r < regs; ++r)
+        {
+            
+            if (single_regs)
+            {
+                // MemA[address,4] = S[d+r]; address = address+4;
+                uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d + r, 0, &success);
+                if (!success)
+                    return false;
+            
+                RegisterInfo data_reg;
+                GetRegisterInfo (eRegisterKindDWARF, start_reg + d + r, data_reg);
+                context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
+                if (!MemAWrite (context, address, data, addr_byte_size))
+                    return false;
+                    
+                address = address + 4;
+            }
+            else
+            {
+                // // Store as two word-aligned words in the correct order for current endianness.
+                // MemA[address,4] = if BigEndian() then D[d+r]<63:32> else D[d+r]<31:0>;
+                // MemA[address+4,4] = if BigEndian() then D[d+r]<31:0> else D[d+r]<63:32>;
+                uint64_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d + r, 0, &success);
+                if (!success)
+                    return false;
+                    
+                RegisterInfo data_reg;
+                GetRegisterInfo (eRegisterKindDWARF, start_reg + d + r, data_reg);
+                
+                if (GetByteOrder() == eByteOrderBig)
+                {
+                    context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
+                    if (!MemAWrite (context, address, Bits64 (data, 63, 32), addr_byte_size))
+                        return false;
+                        
+                    context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
+                    if (!MemAWrite (context, address+ 4, Bits64 (data, 31, 0), addr_byte_size))
+                        return false;
+                }
+                else
+                {
+                    context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
+                    if (!MemAWrite (context, address, Bits64 (data, 31, 0), addr_byte_size))
+                        return false;
+                        
+                    context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
+                    if (!MemAWrite (context, address + 4, Bits64 (data, 63, 32), addr_byte_size))
+                        return false;
+                }    
+                // address = address+8;
+                address = address + 8;
+            }
+        }
+    }
+    return true;
+}
+                                
+// A8.6.320
+// This instruciton loads a single extension register fronm memory, using an address from an ARM core register, with
+// an optional offset.
+bool
+EmulateInstructionARM::EmulateVLDR (const uint32_t opcode, ARMEncoding encoding)
+{
+#if 0
+    if ConditionPassed() then
+        EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
+        base = if n == 15 then Align(PC,4) else R[n];
+        address = if add then (base + imm32) else (base - imm32);
+        if single_reg then
+            S[d] = MemA[address,4];
+        else
+            word1 = MemA[address,4]; word2 = MemA[address+4,4];
+            // Combine the word-aligned words in the correct order for current endianness.
+            D[d] = if BigEndian() then word1:word2 else word2:word1;
+#endif 
+    
+    bool success = false;
+    
+    if (ConditionPassed (opcode))
+    {
+        bool single_reg;
+        bool add;
+        uint32_t imm32;
+        uint32_t d;
+        uint32_t n;
+        
+        switch (encoding)
+        {
+            case eEncodingT1:
+            case eEncodingA1:
+                // single_reg = FALSE; add = (U == �1�); imm32 = ZeroExtend(imm8:�00�, 32);
+                single_reg = false;
+                add = BitIsSet (opcode, 23);
+                imm32 = Bits32 (opcode, 7, 0) << 2;
+                
+                // d = UInt(D:Vd); n = UInt(Rn);
+                d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
+                n = Bits32 (opcode, 19, 16);
+                
+                break;
+                
+            case eEncodingT2:
+            case eEncodingA2:
+                // single_reg = TRUE; add = (U == �1�); imm32 = ZeroExtend(imm8:�00�, 32);
+                single_reg = true;
+                add = BitIsSet (opcode, 23);
+                imm32 = Bits32 (opcode, 7, 0) << 2;
+                
+                // d = UInt(Vd:D); n = UInt(Rn);
+                d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
+                n = Bits32 (opcode, 19, 16);
+                
+                break;
+                
+            default:
+                return false;
+        }
+        RegisterInfo base_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
+        
+        uint32_t Rn = ReadCoreReg (n, &success);
+        if (!success)
+            return false;
+        
+        // base = if n == 15 then Align(PC,4) else R[n];
+        uint32_t base;
+        if (n == 15)
+            base = AlignPC (Rn);
+        else
+            base = Rn;
+            
+        // address = if add then (base + imm32) else (base - imm32);
+        addr_t address;
+        if (add)
+            address = base + imm32;
+        else
+            address = base - imm32;
+            
+        const uint32_t addr_byte_size = GetAddressByteSize();
+        uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0;
+
+        EmulateInstruction::Context context;
+        context.type = eContextRegisterLoad;
+        context.SetRegisterPlusOffset (base_reg, address - base);
+                                           
+        if (single_reg)
+        {
+            // S[d] = MemA[address,4];
+            uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
+            if (!success)
+                return false;
+                
+            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d, data))
+                return false;
+        }
+        else
+        {
+            // word1 = MemA[address,4]; word2 = MemA[address+4,4];
+            uint32_t word1 = MemARead (context, address, addr_byte_size, 0, &success);
+            if (!success)
+                return false;
+                
+            context.SetRegisterPlusOffset (base_reg, (address + 4) - base);
+            uint32_t word2 = MemARead (context, address + 4, addr_byte_size, 0, &success);
+            if (!success)
+                return false;
+            // // Combine the word-aligned words in the correct order for current endianness.
+            // D[d] = if BigEndian() then word1:word2 else word2:word1;
+            uint64_t data64;
+            if (GetByteOrder() == eByteOrderBig)
+            {
+                data64 = word1;
+                data64 = (data64 << 32) | word2;
+            }
+            else
+            {
+                data64 = word2;
+                data64 = (data64 << 32) | word1;
+            }
+            
+            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, start_reg + d, data64))
+                return false;
+        }
+    }
+    return true;
+}
+
+// A8.6.400 VSTR
+// This instruction stores a signle extension register to memory, using an address from an ARM core register, with an
+// optional offset.
+bool
+EmulateInstructionARM::EmulateVSTR (const uint32_t opcode, ARMEncoding encoding)
+{
+#if 0
+    if ConditionPassed() then
+        EncodingSpecificOperations(); CheckVFPEnabled(TRUE); NullCheckIfThumbEE(n);
+        address = if add then (R[n] + imm32) else (R[n] - imm32);
+        if single_reg then
+            MemA[address,4] = S[d];
+        else
+            // Store as two word-aligned words in the correct order for current endianness.
+            MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>;
+            MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>;
+#endif
+
+    bool success = false;
+    
+    if (ConditionPassed (opcode))
+    {
+        bool single_reg;
+        bool add;
+        uint32_t imm32;
+        uint32_t d;
+        uint32_t n;
+        
+        switch (encoding)
+        {
+            case eEncodingT1:
+            case eEncodingA1:
+                // single_reg = FALSE; add = (U == �1�); imm32 = ZeroExtend(imm8:�00�, 32);
+                single_reg = false;
+                add = BitIsSet (opcode, 23);
+                imm32 = Bits32 (opcode, 7, 0) << 2;
+                
+                // d = UInt(D:Vd); n = UInt(Rn);
+                d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
+                n = Bits32 (opcode, 19, 16);
+                
+                // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE;            
+                if ((n == 15) && (CurrentInstrSet() != eModeARM))
+                    return false;
+                    
+                break;
+                
+            case eEncodingT2:
+            case eEncodingA2:
+                // single_reg = TRUE; add = (U == �1�); imm32 = ZeroExtend(imm8:�00�, 32);
+                single_reg = true;
+                add = BitIsSet (opcode, 23);
+                imm32 = Bits32 (opcode, 7, 0) << 2;
+                
+                // d = UInt(Vd:D); n = UInt(Rn);
+                d = (Bits32 (opcode, 15, 12) << 1) | Bit32 (opcode, 22);
+                n = Bits32 (opcode, 19, 16);
+                
+                // if n == 15 && CurrentInstrSet() != InstrSet_ARM then UNPREDICTABLE;            
+                if ((n == 15) && (CurrentInstrSet() != eModeARM))
+                    return false;
+                    
+                break;
+                
+            default:
+                return false;
+        }
+        
+        RegisterInfo base_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
+        
+        uint32_t Rn = ReadCoreReg (n, &success);
+        if (!success)
+            return false;
+         
+        // address = if add then (R[n] + imm32) else (R[n] - imm32);
+        addr_t address;
+        if (add)
+            address = Rn + imm32;
+        else
+            address = Rn - imm32;
+            
+        const uint32_t addr_byte_size = GetAddressByteSize();
+        uint32_t start_reg = single_reg ? dwarf_s0 : dwarf_d0;
+
+        RegisterInfo data_reg;
+        GetRegisterInfo (eRegisterKindDWARF, start_reg + d, data_reg);
+        EmulateInstruction::Context context;
+        context.type = eContextRegisterStore;
+        context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
+                    
+        if (single_reg)
+        {
+            // MemA[address,4] = S[d];
+            uint32_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d, 0, &success);
+            if (!success)
+                return false;
+                
+            if (!MemAWrite (context, address, data, addr_byte_size))
+                return false;
+        }
+        else
+        {
+            // // Store as two word-aligned words in the correct order for current endianness.
+            // MemA[address,4] = if BigEndian() then D[d]<63:32> else D[d]<31:0>;
+            // MemA[address+4,4] = if BigEndian() then D[d]<31:0> else D[d]<63:32>;
+            uint64_t data = ReadRegisterUnsigned (eRegisterKindDWARF, start_reg + d, 0, &success);
+            if (!success)
+                return false;
+                
+            if (GetByteOrder() == eByteOrderBig)
+            {
+                if (!MemAWrite (context, address, Bits64 (data, 63, 32), addr_byte_size))
+                    return false;
+                    
+                context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
+                if (!MemAWrite (context, address + 4, Bits64 (data, 31, 0), addr_byte_size))
+                    return false;
+            }
+            else
+            {
+                if (!MemAWrite (context, address, Bits64 (data, 31, 0), addr_byte_size))
+                    return false;
+                    
+                context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, (address + 4) - Rn);
+                if (!MemAWrite (context, address + 4, Bits64 (data, 63, 32), addr_byte_size))
+                    return false;
+            }
+        }
+    }
+    return true;
+}
+
+// A8.6.307 VLDI1 (multiple single elements)
+// This instruction loads elements from memory into one, two, three or four registers, without de-interleaving.  Every
+// element of each register is loaded.
+bool
+EmulateInstructionARM::EmulateVLD1Multiple (const uint32_t opcode, ARMEncoding encoding)
+{
+#if 0
+    if ConditionPassed() then
+        EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
+        address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
+        if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
+        for r = 0 to regs-1
+            for e = 0 to elements-1
+                Elem[D[d+r],e,esize] = MemU[address,ebytes];
+                address = address + ebytes;
+#endif
+
+    bool success = false;
+    
+    if (ConditionPassed (opcode))
+    {
+        uint32_t regs;
+        uint32_t alignment;
+        uint32_t ebytes;
+        uint32_t esize;
+        uint32_t elements;
+        uint32_t d;
+        uint32_t n;
+        uint32_t m;
+        bool wback;
+        bool register_index;
+        
+        switch (encoding)
+        {
+            case eEncodingT1:
+            case eEncodingA1:
+            {
+                // case type of
+                    // when �0111�
+                        // regs = 1; if align<1> == �1� then UNDEFINED;
+                    // when �1010�
+                        // regs = 2; if align == �11� then UNDEFINED;
+                    // when �0110�
+                        // regs = 3; if align<1> == �1� then UNDEFINED;
+                    // when �0010�
+                        // regs = 4;
+                    // otherwise
+                        // SEE �Related encodings�;
+                uint32_t type = Bits32 (opcode, 11, 8);
+                uint32_t align = Bits32 (opcode, 5, 4);
+                if (type == 7) // '0111'
+                {
+                    regs = 1;
+                    if (BitIsSet (align, 1))
+                        return false;
+                }
+                else if (type == 10) // '1010'
+                {
+                    regs = 2;
+                    if (align == 3)
+                        return false;
+                    
+                }
+                else if (type == 6) // '0110'
+                {
+                    regs = 3;
+                    if (BitIsSet (align, 1))
+                        return false;
+                }
+                else if (type == 2) // '0010'
+                {
+                    regs = 4;
+                }
+                else
+                    return false;
+                
+                // alignment = if align == �00� then 1 else 4 << UInt(align);
+                if (align == 0)
+                    alignment = 1;
+                else
+                    alignment = 4 << align;
+                    
+                // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes;
+                ebytes = 1 << Bits32 (opcode, 7, 6);
+                esize = 8 * ebytes;
+                elements = 8 / ebytes;
+                
+                // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
+                d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
+                n = Bits32 (opcode, 19, 15);
+                m = Bits32 (opcode, 3, 0);
+                
+                // wback = (m != 15); register_index = (m != 15 && m != 13);
+                wback = (m != 15);
+                register_index = ((m != 15) && (m != 13));
+                
+                // if d+regs > 32 then UNPREDICTABLE;            
+                if ((d + regs) > 32)
+                    return false;
+            }
+                break;
+                
+            default:
+                return false;
+        }
+        
+        RegisterInfo base_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
+        
+        uint32_t Rn = ReadCoreReg (n, &success);
+        if (!success)
+            return false;
+            
+        // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
+        addr_t address = Rn;
+        if ((address % alignment) != 0)
+            return false;
+            
+        EmulateInstruction::Context context;
+        // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
+        if (wback)
+        {
+            uint32_t Rm = ReadCoreReg (m, &success);
+            if (!success)
+                return false;
+                
+            uint32_t offset;
+            if (register_index)
+                offset = Rm;
+            else
+                offset = 8 * regs;
+                
+            uint32_t value = Rn + offset;
+            context.type = eContextAdjustBaseRegister;
+            context.SetRegisterPlusOffset (base_reg, offset);
+            
+            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
+                return false;
+            
+        }
+        
+        // for r = 0 to regs-1
+        for (uint32_t r = 0; r < regs; ++r)
+        {
+            // for e = 0 to elements-1
+            uint64_t assembled_data = 0;
+            for (uint32_t e = 0; e < elements; ++e)
+            {
+                // Elem[D[d+r],e,esize] = MemU[address,ebytes];
+                context.type = eContextRegisterLoad;
+                context.SetRegisterPlusOffset (base_reg, address - Rn);
+                uint64_t data = MemURead (context, address, ebytes, 0, &success);
+                if (!success)
+                    return false;
+                    
+                assembled_data = (data << (e * esize)) | assembled_data; // New data goes to the left of existing data
+                
+                // address = address + ebytes;
+                address = address + ebytes;
+            }
+            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_d0 + d + r, assembled_data))
+                return false;
+        }
+    }
+    return true;
+}
+
+// A8.6.308 VLD1 (single element to one lane)
+//
+bool
+EmulateInstructionARM::EmulateVLD1Single (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    if ConditionPassed() then
+        EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
+        address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
+        if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
+        Elem[D[d],index,esize] = MemU[address,ebytes];
+#endif
+
+    bool success = false;
+    
+    if (ConditionPassed (opcode))
+    {
+        uint32_t ebytes;
+        uint32_t esize;
+        uint32_t index;
+        uint32_t alignment;
+        uint32_t d;
+        uint32_t n;
+        uint32_t m;
+        bool wback;
+        bool register_index;
+        
+        switch (encoding)
+        {
+            case eEncodingT1:
+            case eEncodingA1:
+            {
+                uint32_t size = Bits32 (opcode, 11, 10);
+                uint32_t index_align = Bits32 (opcode, 7, 4);
+                // if size == �11� then SEE VLD1 (single element to all lanes);
+                if (size == 3)
+                   return EmulateVLD1SingleAll (opcode, encoding);
+                // case size of
+                if (size == 0) // when '00'
+                {
+                    // if index_align<0> != �0� then UNDEFINED;
+                    if (BitIsClear (index_align, 0))
+                        return false;
+                        
+                    // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1;
+                    ebytes = 1;
+                    esize = 8;
+                    index = Bits32 (index_align, 3, 1);
+                    alignment = 1;
+                }
+                else if (size == 1) // when �01�
+                {
+                    // if index_align<1> != �0� then UNDEFINED;
+                    if (BitIsClear (index_align, 1))
+                        return false;
+                        
+                    // ebytes = 2; esize = 16; index = UInt(index_align<3:2>);
+                    ebytes = 2;
+                    esize = 16;
+                    index = Bits32 (index_align, 3, 2);
+                    
+                    // alignment = if index_align<0> == �0� then 1 else 2;
+                    if (BitIsClear (index_align, 0))
+                        alignment = 1;
+                    else
+                        alignment = 2;
+                }
+                else if (size == 2) // when �10�
+                {
+                    // if index_align<2> != �0� then UNDEFINED;
+                    if (BitIsClear (index_align, 2))
+                        return false;
+                        
+                    // if index_align<1:0> != �00� && index_align<1:0> != �11� then UNDEFINED;
+                    if ((Bits32 (index_align, 1, 0) != 0) && (Bits32 (index_align, 1, 0) != 3))
+                        return false;
+                        
+                    // ebytes = 4; esize = 32; index = UInt(index_align<3>);
+                    ebytes = 4;
+                    esize = 32;
+                    index = Bit32 (index_align, 3);
+                    
+                    // alignment = if index_align<1:0> == �00� then 1 else 4;
+                    if (Bits32 (index_align, 1, 0) == 0)
+                        alignment = 1;
+                    else
+                        alignment = 4;
+                }
+                else
+                {
+                    return false;
+                }
+                // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
+                d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
+                n = Bits32 (opcode, 19, 16);
+                m = Bits32 (opcode, 3, 0);
+                
+                // wback = (m != 15); register_index = (m != 15 && m != 13); if n == 15 then UNPREDICTABLE;
+                wback = (m != 15);
+                register_index = ((m != 15) && (m != 13));
+                
+                if (n == 15)
+                    return false;
+                
+            }
+                break;
+                
+            default:
+                return false;
+        }
+        
+        RegisterInfo base_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
+        
+        uint32_t Rn = ReadCoreReg (n, &success);
+        if (!success)
+            return false;
+            
+        // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
+        addr_t address = Rn;
+        if ((address % alignment) != 0)
+            return false;
+            
+        EmulateInstruction::Context context;
+        // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
+        if (wback)
+        {
+            uint32_t Rm = ReadCoreReg (m, &success);
+            if (!success)
+                return false;
+                
+            uint32_t offset;
+            if (register_index)
+                offset = Rm;
+            else
+                offset = ebytes;
+                
+            uint32_t value = Rn + offset;
+            
+            context.type = eContextAdjustBaseRegister;
+            context.SetRegisterPlusOffset (base_reg, offset);
+            
+            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, value))
+                return false;
+        }
+        
+        // Elem[D[d],index,esize] = MemU[address,ebytes];
+        uint32_t element = MemURead (context, address, esize, 0, &success);
+        if (!success)
+            return false;
+            
+        element = element << (index * esize);
+        
+        uint64_t reg_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_d0 + d, 0, &success);
+        if (!success)
+            return false;
+            
+        uint64_t all_ones = -1;
+        uint64_t mask = all_ones << ((index+1) * esize);  // mask is all 1's to left of where 'element' goes, & all 0's
+                                                          // at element & to the right of element.
+        if (index > 0)
+            mask = mask | Bits64 (all_ones, (index * esize) - 1, 0); // add 1's to the right of where 'element' goes.
+                                                                     // now mask should be 0's where element goes & 1's 
+                                                                     // everywhere else.
+
+        uint64_t masked_reg = reg_data & mask;  // Take original reg value & zero out 'element' bits
+        reg_data = masked_reg & element;        // Put 'element' into those bits in reg_data.
+        
+        context.type = eContextRegisterLoad;
+        if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, reg_data))
+            return false;
+    }
+    return true;
+}
+
+// A8.6.391 VST1 (multiple single elements)
+// Vector Store (multiple single elements) stores elements to memory from one, two, three, or four regsiters, without
+// interleaving.  Every element of each register is stored.
+bool
+EmulateInstructionARM::EmulateVST1Multiple (const uint32_t opcode, ARMEncoding encoding)
+{
+#if 0
+    if ConditionPassed() then
+        EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
+        address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
+        if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
+        for r = 0 to regs-1
+            for e = 0 to elements-1
+                MemU[address,ebytes] = Elem[D[d+r],e,esize];
+                address = address + ebytes;
+#endif
+    
+    bool success = false;
+    
+    if (ConditionPassed (opcode))
+    {
+        uint32_t regs;
+        uint32_t alignment;
+        uint32_t ebytes;
+        uint32_t esize;
+        uint32_t elements;
+        uint32_t d;
+        uint32_t n;
+        uint32_t m;
+        bool wback;
+        bool register_index;
+            
+        switch (encoding)
+        {
+            case eEncodingT1:
+            case eEncodingA1:
+            {
+                uint32_t type = Bits32 (opcode, 11, 8);
+                uint32_t align = Bits32 (opcode, 5, 4);
+                
+                // case type of
+                if (type == 7)    // when �0111�
+                {
+                    // regs = 1; if align<1> == �1� then UNDEFINED;
+                    regs = 1;
+                    if (BitIsSet (align, 1))
+                        return false;
+                }
+                else if (type == 10) // when �1010�
+                {
+                    // regs = 2; if align == �11� then UNDEFINED;
+                    regs = 2;
+                    if (align == 3)
+                        return false;
+                }
+                else if (type == 6) // when �0110�
+                {
+                    // regs = 3; if align<1> == �1� then UNDEFINED;
+                    regs = 3;
+                    if (BitIsSet (align, 1))
+                        return false;
+                }
+                else if (type == 2) // when �0010�
+                    // regs = 4;
+                    regs = 4;
+                else // otherwise
+                    // SEE �Related encodings�;
+                    return false;
+                    
+                // alignment = if align == �00� then 1 else 4 << UInt(align);
+                if (align == 0)
+                    alignment = 1;
+                else
+                    alignment = 4 << align;
+                    
+                // ebytes = 1 << UInt(size); esize = 8 * ebytes; elements = 8 DIV ebytes;
+                ebytes = 1 << Bits32 (opcode,7, 6);
+                esize = 8 * ebytes;
+                elements = 8 / ebytes;
+                
+                // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
+                d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
+                n = Bits32 (opcode, 19, 16);
+                m = Bits32 (opcode, 3, 0);
+                
+                // wback = (m != 15); register_index = (m != 15 && m != 13);
+                wback = (m != 15);
+                register_index = ((m != 15) && (m != 13));
+                
+                // if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE;            
+                if ((d + regs) > 32)
+                    return false;
+                    
+                if (n == 15)
+                    return false;
+                    
+            }
+                break;
+                
+            default:
+                return false;
+        }
+        
+        RegisterInfo base_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
+        
+        uint32_t Rn = ReadCoreReg (n, &success);
+        if (!success)
+            return false;
+        
+        // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
+        addr_t address = Rn;
+        if ((address % alignment) != 0)
+            return false;
+        
+        EmulateInstruction::Context context;
+        // if wback then R[n] = R[n] + (if register_index then R[m] else 8*regs);
+        if (wback)
+        {
+            uint32_t Rm = ReadCoreReg (m, &success);
+            if (!success)
+                return false;
+                
+            uint32_t offset;
+            if (register_index)
+                offset = Rm;
+            else
+                offset = 8 * regs;
+                
+            context.type = eContextAdjustBaseRegister;
+            context.SetRegisterPlusOffset (base_reg, offset);
+            
+            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset))
+                return false;
+        }
+        
+        RegisterInfo data_reg;
+        context.type = eContextRegisterStore;
+        // for r = 0 to regs-1
+        for (uint32_t r = 0; r < regs; ++r)
+        {
+            GetRegisterInfo (eRegisterKindDWARF, dwarf_d0 + d + r, data_reg);
+            uint64_t register_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_d0 + d + r, 0, &success);
+            if (!success)
+                return false;
+
+             // for e = 0 to elements-1
+            for (uint32_t e = 0; e < elements; ++e)
+            {
+                // MemU[address,ebytes] = Elem[D[d+r],e,esize];
+                uint64_t word = Bits64 (register_data, ((e + 1) * esize) - 1, e * esize);
+                
+                context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
+                if (!MemUWrite (context, address, word, ebytes))
+                    return false;
+                    
+                // address = address + ebytes;
+                address = address + ebytes;
+            }
+        }
+    }
+    return true;
+}
+
+// A8.6.392 VST1 (single element from one lane)
+// This instruction stores one element to memory from one element of a register.  
+bool
+EmulateInstructionARM::EmulateVST1Single (const uint32_t opcode, ARMEncoding encoding)
+{
+#if 0
+    if ConditionPassed() then
+        EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
+        address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
+        if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
+        MemU[address,ebytes] = Elem[D[d],index,esize];
+#endif
+
+    bool success = false;
+    
+    if (ConditionPassed (opcode))
+    {
+        uint32_t ebytes;
+        uint32_t esize;
+        uint32_t index;
+        uint32_t alignment;
+        uint32_t d;
+        uint32_t n;
+        uint32_t m;
+        bool wback;
+        bool register_index;
+        
+        switch (encoding)
+        {
+            case eEncodingT1:
+            case eEncodingA1:
+            {
+                uint32_t size = Bits32 (opcode, 11, 10);
+                uint32_t index_align = Bits32 (opcode, 7, 4);
+                
+                // if size == �11� then UNDEFINED;
+                if (size == 3)
+                    return false;
+                    
+                // case size of
+                if (size == 0) // when �00�
+                {
+                    // if index_align<0> != �0� then UNDEFINED;
+                    if (BitIsClear (index_align, 0))
+                        return false;
+                    // ebytes = 1; esize = 8; index = UInt(index_align<3:1>); alignment = 1;
+                    ebytes = 1;
+                    esize = 8;
+                    index = Bits32 (index_align, 3, 1);
+                    alignment = 1;
+                }
+                else if (size == 1) // when �01�
+                {
+                    // if index_align<1> != �0� then UNDEFINED;
+                    if (BitIsClear (index_align, 1))
+                        return false;
+                            
+                    // ebytes = 2; esize = 16; index = UInt(index_align<3:2>);
+                    ebytes = 2;
+                    esize = 16;
+                    index = Bits32 (index_align, 3, 2);
+                    
+                    // alignment = if index_align<0> == �0� then 1 else 2;
+                    if (BitIsClear (index_align, 0))
+                        alignment = 1;
+                    else
+                        alignment = 2;
+                }
+                else if (size == 2) // when �10�
+                {
+                    // if index_align<2> != �0� then UNDEFINED;
+                    if (BitIsClear (index_align, 2))
+                        return false;
+                        
+                    // if index_align<1:0> != �00� && index_align<1:0> != �11� then UNDEFINED;
+                    if ((Bits32 (index_align, 1, 0) != 0) && (Bits32 (index_align, 1, 0) != 3))
+                        return false;
+                        
+                    // ebytes = 4; esize = 32; index = UInt(index_align<3>);
+                    ebytes = 4;
+                    esize = 32;
+                    index = Bit32 (index_align, 3);
+                    
+                    // alignment = if index_align<1:0> == �00� then 1 else 4;
+                    if (Bits32 (index_align, 1, 0) == 0)
+                        alignment = 1;
+                    else
+                        alignment = 4;
+                }
+                else
+                {
+                    return false;
+                }
+                // d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
+                d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
+                n = Bits32 (opcode, 19, 16);
+                m = Bits32 (opcode, 3, 0);
+                
+                // wback = (m != 15); register_index = (m != 15 && m != 13);  if n == 15 then UNPREDICTABLE;          
+                wback = (m != 15);
+                register_index = ((m != 15) && (m != 13));
+                
+                if (n == 15)
+                    return false;
+            }
+                break;
+                
+            default:
+                return false;
+        }
+        
+        RegisterInfo base_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
+        
+        uint32_t Rn = ReadCoreReg (n, &success);
+        if (!success)
+            return false;
+            
+        // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
+        addr_t address = Rn;
+        if ((address % alignment) != 0)
+            return false;
+            
+        EmulateInstruction::Context context;
+        // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
+        if (wback)
+        {
+            uint32_t Rm = ReadCoreReg (m, &success);
+            if (!success)
+                return false;
+                
+            uint32_t offset;
+            if (register_index)
+                offset = Rm;
+            else
+                offset = ebytes;
+                
+            context.type = eContextAdjustBaseRegister;
+            context.SetRegisterPlusOffset (base_reg, offset);
+            
+            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset))
+                return false;
+        }
+        
+        // MemU[address,ebytes] = Elem[D[d],index,esize];
+        uint64_t register_data = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_d0 + d, 0, &success);
+        if (!success)
+            return false;
+            
+        uint64_t word = Bits64 (register_data, ((index + 1) * esize) - 1,  index * esize);
+        
+        RegisterInfo data_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_d0 + d, data_reg);
+        context.type = eContextRegisterStore;
+        context.SetRegisterToRegisterPlusOffset (data_reg, base_reg, address - Rn);
+        
+        if (!MemUWrite (context, address, word, ebytes))
+            return false;
+    }
+    return true;
+}
+
+// A8.6.309 VLD1 (single element to all lanes)
+// This instruction loads one element from memory into every element of one or two vectors.
+bool
+EmulateInstructionARM::EmulateVLD1SingleAll (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    if ConditionPassed() then
+        EncodingSpecificOperations(); CheckAdvSIMDEnabled(); NullCheckIfThumbEE(n);
+        address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
+        if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
+        replicated_element = Replicate(MemU[address,ebytes], elements);
+        for r = 0 to regs-1
+            D[d+r] = replicated_element;
+#endif
+
+    bool success = false;
+    
+    if (ConditionPassed (opcode))
+    {
+        uint32_t ebytes;
+        uint32_t elements;
+        uint32_t regs;
+        uint32_t alignment;
+        uint32_t d;
+        uint32_t n;
+        uint32_t m;
+        bool wback;
+        bool register_index;
+            
+        switch (encoding)
+        {
+            case eEncodingT1:
+            case eEncodingA1:
+            {
+                //if size == �11� || (size == �00� && a == �1�) then UNDEFINED;
+                uint32_t size = Bits32 (opcode, 7, 6);
+                if ((size == 3) || ((size == 0) && BitIsSet (opcode, 4)))
+                    return false;
+                    
+                //ebytes = 1 << UInt(size); elements = 8 DIV ebytes; regs = if T == �0� then 1 else 2;
+                ebytes = 1 << size;
+                elements = 8 / ebytes;
+                if (BitIsClear (opcode, 5))
+                    regs = 1;
+                else
+                    regs = 2;
+                    
+                //alignment = if a == �0� then 1 else ebytes;
+                if (BitIsClear (opcode, 4))
+                    alignment = 1;
+                else
+                    alignment = ebytes;
+                    
+                //d = UInt(D:Vd); n = UInt(Rn); m = UInt(Rm);
+                d = (Bit32 (opcode, 22) << 4) | Bits32 (opcode, 15, 12);
+                n = Bits32 (opcode, 19, 16);
+                m = Bits32 (opcode, 3, 0);
+                
+                //wback = (m != 15); register_index = (m != 15 && m != 13);
+                wback = (m != 15);
+                register_index = ((m != 15) && (m != 13));
+                
+                //if d+regs > 32 then UNPREDICTABLE; if n == 15 then UNPREDICTABLE;            
+                if ((d + regs) > 32)
+                    return false;
+                    
+                if (n == 15)
+                    return false;
+            }
+            break;
+                
+            default:
+                return false;
+        }
+        
+        RegisterInfo base_reg;
+        GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, base_reg);
+        
+        uint32_t Rn = ReadCoreReg (n, &success);
+        if (!success)
+            return false;
+            
+        // address = R[n]; if (address MOD alignment) != 0 then GenerateAlignmentException();
+        addr_t address = Rn;
+        if ((address % alignment) != 0)
+            return false;
+        
+        EmulateInstruction::Context context;
+        // if wback then R[n] = R[n] + (if register_index then R[m] else ebytes);
+        if (wback)
+        {
+            uint32_t Rm = ReadCoreReg (m, &success);
+            if (!success)
+                return false;
+                
+            uint32_t offset;
+            if (register_index)
+                offset = Rm;
+            else
+                offset = ebytes;
+                
+            context.type = eContextAdjustBaseRegister;
+            context.SetRegisterPlusOffset (base_reg, offset);
+            
+            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + n, Rn + offset))
+                return false;
+        }
+        
+        // replicated_element = Replicate(MemU[address,ebytes], elements);
+        
+        context.type = eContextRegisterLoad;
+        uint64_t word = MemURead (context, address, ebytes, 0, &success);
+        if (!success)
+            return false;
+        
+        uint64_t replicated_element = 0;
+        uint32_t esize = ebytes * 8;
+        for (uint32_t e = 0; e < elements; ++e)
+            replicated_element = (replicated_element << esize) | Bits64 (word, esize - 1, 0);
+
+        // for r = 0 to regs-1
+        for (uint32_t r = 0; r < regs; ++r)
+        {
+            // D[d+r] = replicated_element;
+            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_d0 + d + r, replicated_element))
+                return false;
+        }
+    }
+    return true;
+}
+
+// B6.2.13 SUBS PC, LR and related instructions
+//The SUBS PC, LR, #<const? instruction provides an exception return without the use of the stack.  It subtracts the
+// immediate constant from the LR, branches to the resulting address, and also copies the SPSR to the CPSR.
+bool
+EmulateInstructionARM::EmulateSUBSPcLrEtc (const uint32_t opcode, const ARMEncoding encoding)
+{
+#if 0
+    if ConditionPassed() then
+        EncodingSpecificOperations();
+        if CurrentInstrSet() == InstrSet_ThumbEE then
+            UNPREDICTABLE;
+        operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C) else imm32;
+        case opcode of
+            when �0000� result = R[n] AND operand2; // AND
+            when �0001� result = R[n] EOR operand2; // EOR
+            when �0010� (result, -, -) = AddWithCarry(R[n], NOT(operand2), �1�); // SUB
+            when �0011� (result, -, -) = AddWithCarry(NOT(R[n]), operand2, �1�); // RSB
+            when �0100� (result, -, -) = AddWithCarry(R[n], operand2, �0�); // ADD
+            when �0101� (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC
+            when �0110� (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC
+            when �0111� (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC
+            when �1100� result = R[n] OR operand2; // ORR
+            when �1101� result = operand2; // MOV
+            when �1110� result = R[n] AND NOT(operand2); // BIC
+            when �1111� result = NOT(operand2); // MVN
+        CPSRWriteByInstr(SPSR[], �1111�, TRUE);
+        BranchWritePC(result);
+#endif
+
+    bool success = false;
+
+    if (ConditionPassed (opcode))
+    {
+        uint32_t n;
+        uint32_t m;
+        uint32_t imm32;
+        bool register_form;
+        ARM_ShifterType shift_t;
+        uint32_t shift_n;
+        uint32_t code;
+
+        switch (encoding)
+        {
+            case eEncodingT1:
+                // if CurrentInstrSet() == InstrSet_ThumbEE then UNPREDICTABLE
+                // n = 14; imm32 = ZeroExtend(imm8, 32); register_form = FALSE; opcode = �0010�; // = SUB
+                n = 14;
+                imm32 = Bits32 (opcode, 7, 0);
+                register_form = false;
+                code = 2;
+                
+                // if InITBlock() && !LastInITBlock() then UNPREDICTABLE;
+                if (InITBlock() && !LastInITBlock())
+                    return false;
+                    
+                break;
+
+            case eEncodingA1:
+                // n = UInt(Rn); imm32 = ARMExpandImm(imm12); register_form = FALSE;
+                n = Bits32 (opcode, 19, 16);
+                imm32 = ARMExpandImm (opcode);
+                register_form = false;
+                code = Bits32 (opcode, 24, 21);
+                
+                break;
+
+            case eEncodingA2:
+                // n = UInt(Rn); m = UInt(Rm); register_form = TRUE;
+                n = Bits32 (opcode, 19, 16);
+                m = Bits32 (opcode, 3, 0);
+                register_form = true;
+                
+                // (shift_t, shift_n) = DecodeImmShift(type, imm5);
+                shift_n = DecodeImmShiftARM (opcode, shift_t);
+                
+                break;
+
+            default:
+                return false;
+        }
+
+        // operand2 = if register_form then Shift(R[m], shift_t, shift_n, APSR.C) else imm32;
+        uint32_t operand2;
+        if (register_form)
+        {
+            uint32_t Rm = ReadCoreReg (m, &success);
+            if (!success)
+                return false;
+                
+            operand2 = Shift (Rm, shift_t, shift_n, APSR_C, &success);
+            if (!success)
+                return false;
+        }
+        else
+        {
+            operand2 = imm32;
+        }
+        
+        uint32_t Rn = ReadCoreReg (n, &success);
+        if (!success)
+            return false;
+        
+        AddWithCarryResult result;
+        
+        // case opcode of
+        switch (code)
+        {
+            case 0: // when �0000� 
+                // result = R[n] AND operand2; // AND
+                result.result = Rn & operand2;
+                break;
+
+            case 1: // when �0001� 
+                // result = R[n] EOR operand2; // EOR
+                result.result = Rn ^ operand2;
+                break;
+                
+            case 2: // when �0010� 
+                // (result, -, -) = AddWithCarry(R[n], NOT(operand2), �1�); // SUB
+                result = AddWithCarry (Rn, ~(operand2), 1);
+                break;
+                
+            case 3: // when �0011� 
+                // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, �1�); // RSB
+                result = AddWithCarry (~(Rn), operand2, 1);
+                break;
+                
+            case 4: // when �0100� 
+                // (result, -, -) = AddWithCarry(R[n], operand2, �0�); // ADD
+                result = AddWithCarry (Rn, operand2, 0);
+                break;
+                
+            case 5: // when �0101� 
+                // (result, -, -) = AddWithCarry(R[n], operand2, APSR.c); // ADC
+                result = AddWithCarry (Rn, operand2, APSR_C);
+                break;
+                
+            case 6: // when �0110� 
+                // (result, -, -) = AddWithCarry(R[n], NOT(operand2), APSR.C); // SBC
+                result = AddWithCarry (Rn, ~(operand2), APSR_C);
+                break;
+                
+            case 7: // when �0111� 
+                // (result, -, -) = AddWithCarry(NOT(R[n]), operand2, APSR.C); // RSC
+                result = AddWithCarry (~(Rn), operand2, APSR_C);
+                break;
+                
+            case 10: // when �1100� 
+                // result = R[n] OR operand2; // ORR
+                result.result = Rn | operand2;
+                break;
+                
+            case 11: // when �1101� 
+                // result = operand2; // MOV
+                result.result = operand2;
+                break;
+                
+            case 12: // when �1110� 
+                // result = R[n] AND NOT(operand2); // BIC
+                result.result = Rn & ~(operand2);
+                break;
+                
+            case 15: // when �1111� 
+                // result = NOT(operand2); // MVN
+                result.result = ~(operand2);
+                break;
+                
+            default:
+                return false;
+        }
+        // CPSRWriteByInstr(SPSR[], �1111�, TRUE);
+        
+        // For now, in emulation mode, we don't have access to the SPSR, so we will use the CPSR instead, and hope for
+        // the best.
+        uint32_t spsr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_cpsr, 0, &success);
+        if (!success)
+            return false;
+        
+        CPSRWriteByInstr (spsr, 15, true);
+        
+        // BranchWritePC(result);
+        EmulateInstruction::Context context;
+        context.type = eContextAdjustPC;
+        context.SetImmediate (result.result);
+        
+        BranchWritePC (context, result.result);
+    }
+    return true;
+}
+    
+EmulateInstructionARM::ARMOpcode*
+EmulateInstructionARM::GetARMOpcodeForInstruction (const uint32_t opcode, uint32_t arm_isa)
+{
+    static ARMOpcode 
+    g_arm_opcodes[] = 
+    {
+        //----------------------------------------------------------------------
+        // Prologue instructions
+        //----------------------------------------------------------------------
+
+        // push register(s)
+        { 0x0fff0000, 0x092d0000, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
+        { 0x0fff0fff, 0x052d0004, ARMvAll,       eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push <register>" },
+
+        // set r7 to point to a stack offset
+        { 0x0ffff000, 0x028d7000, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #<const>" },
+        { 0x0ffff000, 0x024c7000, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBR7IPImm, "sub r7, ip, #<const>"},
+        // copy the stack pointer to ip
+        { 0x0fffffff, 0x01a0c00d, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdSP, "mov ip, sp" },
+        { 0x0ffff000, 0x028dc000, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRdSPImm, "add ip, sp, #<const>" },
+        { 0x0ffff000, 0x024dc000, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBIPSPImm, "sub ip, sp, #<const>"},
+
+        // adjust the stack pointer
+        { 0x0ffff000, 0x024dd000, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #<const>"},
+        { 0x0fef0010, 0x004d0000, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPReg, "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}" }, 
+
+        // push one register
+        // if Rn == '1101' && imm12 == '000000000100' then SEE PUSH;
+        { 0x0e5f0000, 0x040d0000, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRtSP, "str Rt, [sp, #-imm12]!" },
+
+        // vector push consecutive extension register(s)
+        { 0x0fbf0f00, 0x0d2d0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
+        { 0x0fbf0f00, 0x0d2d0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
+
+        //----------------------------------------------------------------------
+        // Epilogue instructions
+        //----------------------------------------------------------------------
+
+        { 0x0fff0000, 0x08bd0000, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
+        { 0x0fff0fff, 0x049d0004, ARMvAll,       eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop <register>"},
+        { 0x0fbf0f00, 0x0cbd0b00, ARMV6T2_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
+        { 0x0fbf0f00, 0x0cbd0a00, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
+
+        //----------------------------------------------------------------------
+        // Supervisor Call (previously Software Interrupt)
+        //----------------------------------------------------------------------
+        { 0x0f000000, 0x0f000000, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSVC, "svc #imm24"},
+
+        //----------------------------------------------------------------------
+        // Branch instructions
+        //----------------------------------------------------------------------
+        { 0x0f000000, 0x0a000000, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateB, "b #imm24"},
+        // To resolve ambiguity, "blx <label>" should come before "bl <label>".
+        { 0xfe000000, 0xfa000000, ARMV5_ABOVE,   eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
+        { 0x0f000000, 0x0b000000, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
+        { 0x0ffffff0, 0x012fff30, ARMV5_ABOVE,   eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
+        // for example, "bx lr"
+        { 0x0ffffff0, 0x012fff10, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
+        // bxj
+        { 0x0ffffff0, 0x012fff20, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
+
+        //----------------------------------------------------------------------
+        // Data-processing instructions
+        //----------------------------------------------------------------------
+        // adc (immediate)
+        { 0x0fe00000, 0x02a00000, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #const"},
+        // adc (register)
+        { 0x0fe00010, 0x00a00000, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
+        // add (immediate)
+        { 0x0fe00000, 0x02800000, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmARM, "add{s}<c> <Rd>, <Rn>, #const"},
+        // add (register)
+        { 0x0fe00010, 0x00800000, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDReg, "add{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
+        // add (register-shifted register)
+        { 0x0fe00090, 0x00800010, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDRegShift, "add{s}<c> <Rd>, <Rn>, <Rm>, <type> <RS>"},
+        // adr
+        { 0x0fff0000, 0x028f0000, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
+        { 0x0fff0000, 0x024f0000, ARMvAll,       eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
+        // and (immediate)
+        { 0x0fe00000, 0x02000000, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #const"},
+        // and (register)
+        { 0x0fe00010, 0x00000000, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
+        // bic (immediate)
+        { 0x0fe00000, 0x03c00000, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #const"},
+        // bic (register)
+        { 0x0fe00010, 0x01c00000, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
+        // eor (immediate)
+        { 0x0fe00000, 0x02200000, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #const"},
+        // eor (register)
+        { 0x0fe00010, 0x00200000, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
+        // orr (immediate)
+        { 0x0fe00000, 0x03800000, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #const"},
+        // orr (register)
+        { 0x0fe00010, 0x01800000, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
+        // rsb (immediate)
+        { 0x0fe00000, 0x02600000, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c> <Rd>, <Rn>, #<const>"},
+        // rsb (register)
+        { 0x0fe00010, 0x00600000, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
+        // rsc (immediate)
+        { 0x0fe00000, 0x02e00000, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSCImm, "rsc{s}<c> <Rd>, <Rn>, #<const>"},
+        // rsc (register)
+        { 0x0fe00010, 0x00e00000, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSCReg, "rsc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
+        // sbc (immediate)
+        { 0x0fe00000, 0x02c00000, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
+        // sbc (register)
+        { 0x0fe00010, 0x00c00000, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c> <Rd>, <Rn>, <Rm> {,<shift>}"},
+        // sub (immediate, ARM)
+        { 0x0fe00000, 0x02400000, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmARM, "sub{s}<c> <Rd>, <Rn>, #<const>"},
+        // sub (sp minus immediate)
+        { 0x0fef0000, 0x024d0000, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}<c> <Rd>, sp, #<const>"},
+        // sub (register)
+        { 0x0fe00010, 0x00400000, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBReg, "sub{s}<c> <Rd>, <Rn>, <Rm>{,<shift>}"},
+        // teq (immediate)
+        { 0x0ff0f000, 0x03300000, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #const"},
+        // teq (register)
+        { 0x0ff0f010, 0x01300000, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
+        // tst (immediate)
+        { 0x0ff0f000, 0x03100000, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #const"},
+        // tst (register)
+        { 0x0ff0f010, 0x01100000, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rn>, <Rm> {,<shift>}"},
+
+        // mov (immediate)
+        { 0x0fef0000, 0x03a00000, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c> <Rd>, #<const>"},
+        { 0x0ff00000, 0x03000000, ARMV6T2_ABOVE, eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>, #<imm16>" },
+        // mov (register)
+        { 0x0fef0ff0, 0x01a00000, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c> <Rd>, <Rm>"},
+        // mvn (immediate)
+        { 0x0fef0000, 0x03e00000, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s}<c> <Rd>, #<const>"},
+        // mvn (register)
+        { 0x0fef0010, 0x01e00000, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c> <Rd>, <Rm> {,<shift>}"},
+        // cmn (immediate)
+        { 0x0ff0f000, 0x03700000, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
+        // cmn (register)
+        { 0x0ff0f010, 0x01700000, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
+        // cmp (immediate)
+        { 0x0ff0f000, 0x03500000, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #<const>"},
+        // cmp (register)
+        { 0x0ff0f010, 0x01500000, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm> {,<shift>}"},
+        // asr (immediate)
+        { 0x0fef0070, 0x01a00040, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c> <Rd>, <Rm>, #imm"},
+        // asr (register)
+        { 0x0fef00f0, 0x01a00050, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c> <Rd>, <Rn>, <Rm>"},
+        // lsl (immediate)
+        { 0x0fef0070, 0x01a00000, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c> <Rd>, <Rm>, #imm"},
+        // lsl (register)
+        { 0x0fef00f0, 0x01a00010, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c> <Rd>, <Rn>, <Rm>"},
+        // lsr (immediate)
+        { 0x0fef0070, 0x01a00020, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c> <Rd>, <Rm>, #imm"},
+        // lsr (register)
+        { 0x0fef00f0, 0x01a00050, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c> <Rd>, <Rn>, <Rm>"},
+        // rrx is a special case encoding of ror (immediate)
+        { 0x0fef0ff0, 0x01a00060, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c> <Rd>, <Rm>"},
+        // ror (immediate)
+        { 0x0fef0070, 0x01a00060, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c> <Rd>, <Rm>, #imm"},
+        // ror (register)
+        { 0x0fef00f0, 0x01a00070, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c> <Rd>, <Rn>, <Rm>"},
+        // mul
+        { 0x0fe000f0, 0x00000090, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMUL, "mul{s}<c> <Rd>,<R>,<Rm>" },
+
+        // subs pc, lr and related instructions
+        { 0x0e10f000, 0x0210f000, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPcLrEtc, "<opc>S<c> PC,#<const> | <Rn>,#<const>" }, 
+        { 0x0e10f010, 0x0010f000, ARMvAll,       eEncodingA2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPcLrEtc, "<opc>S<c> PC,<Rn>,<Rm{,<shift>}" },
+
+        //----------------------------------------------------------------------
+        // Load instructions
+        //----------------------------------------------------------------------
+        { 0x0fd00000, 0x08900000, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
+        { 0x0fd00000, 0x08100000, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDA, "ldmda<c> <Rn>{!} <registers>" },
+        { 0x0fd00000, 0x09100000, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
+        { 0x0fd00000, 0x09900000, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMIB, "ldmib<c> <Rn<{!} <registers>" },
+        { 0x0e500000, 0x04100000, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRImmediateARM, "ldr<c> <Rt> [<Rn> {#+/-<imm12>}]" },
+        { 0x0e500010, 0x06100000, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt> [<Rn> +/-<Rm> {<shift>}] {!}" },
+        { 0x0e5f0000, 0x045f0000, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>, [...]"},
+        { 0xfe500010, 0x06500000, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>, [<Rn>,+/-<Rm>{, <shift>}]{!}" },
+        { 0x0e5f00f0, 0x005f00b0, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
+        { 0x0e5000f0, 0x001000b0, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>,[<Rn>,+/-<Rm>]{!}"  }, 
+        { 0x0e5000f0, 0x005000d0, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>, [<Rn>{,#+/-<imm8>}]" },
+        { 0x0e5f00f0, 0x005f00d0, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt> <label>" },
+        { 0x0e5000f0, 0x001000d0, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
+        { 0x0e5000f0, 0x005000f0, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>{,#+/-<imm8>}]"},
+        { 0x0e5f00f0, 0x005f00f0, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
+        { 0x0e5000f0, 0x001000f0, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,+/-<Rm>]{!}" },
+        { 0x0e5000f0, 0x004000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDImmediate, "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm8>]!"},
+        { 0x0e500ff0, 0x000000d0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDRegister, "ldrd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"},
+        { 0x0e100f00, 0x0c100b00, ARMvAll,       eEncodingA1, VFPv2_ABOVE,  eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
+        { 0x0e100f00, 0x0c100a00, ARMvAll,       eEncodingA2, VFPv2v3,      eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
+        { 0x0f300f00, 0x0d100b00, ARMvAll,       eEncodingA1, VFPv2_ABOVE,  eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
+        { 0x0f300f00, 0x0d100a00, ARMvAll,       eEncodingA2, VFPv2v3,      eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, [<Rn>{,#+/-<imm>}]"},
+        { 0xffb00000, 0xf4200000, ARMvAll,       eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Multiple, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
+        { 0xffb00300, 0xf4a00000, ARMvAll,       eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Single, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
+        { 0xffb00f00, 0xf4a00c00, ARMvAll,       eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1SingleAll, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
+                  
+        //----------------------------------------------------------------------
+        // Store instructions
+        //----------------------------------------------------------------------
+        { 0x0fd00000, 0x08800000, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
+        { 0x0fd00000, 0x08000000, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDA, "stmda<c> <Rn>{!} <registers>" },
+        { 0x0fd00000, 0x09000000, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
+        { 0x0fd00000, 0x09800000, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMIB, "stmib<c> <Rn>{!} <registers>" },
+        { 0x0e500010, 0x06000000, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> [<Rn> +/-<Rm> {<shift>}]{!}" },
+        { 0x0e5000f0, 0x000000b0, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,+/-<Rm>[{!}" },
+        { 0x0ff00ff0, 0x01800f90, ARMV6_ABOVE,   eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTREX, "strex<c> <Rd>, <Rt>, [<Rn>]"},
+        { 0x0e500000, 0x04400000, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBImmARM, "strb<c> <Rt>,[<Rn>,#+/-<imm12>]!"},
+        { 0x0e500000, 0x04000000, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRImmARM, "str<c> <Rt>,[<Rn>,#+/-<imm12>]!"},
+        { 0x0e5000f0, 0x004000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDImm, "strd<c> <Rt>, <Rt2>, [<Rn> #+/-<imm8>]!"},
+        { 0x0e500ff0, 0x000000f0, ARMV5TE_ABOVE, eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDReg, "strd<c> <Rt>, <Rt2>, [<Rn>, +/-<Rm>]{!}"},
+        { 0x0e100f00, 0x0c000b00, ARMvAll,       eEncodingA1, VFPv2_ABOVE,  eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"},
+        { 0x0e100f00, 0x0c000a00, ARMvAll,       eEncodingA2, VFPv2v3,      eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!} <list>"},
+        { 0x0f300f00, 0x0d000b00, ARMvAll,       eEncodingA1, VFPv2_ABOVE,  eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd> [<Rn>{,#+/-<imm>}]"},
+        { 0x0f300f00, 0x0d000a00, ARMvAll,       eEncodingA2, VFPv2v3,      eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd> [<Rn>{,#+/-<imm>}]"},
+        { 0xffb00000, 0xf4000000, ARMvAll,       eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Multiple, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
+        { 0xffb00300, 0xf4800000, ARMvAll,       eEncodingA1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Single, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
+                  
+        //----------------------------------------------------------------------
+        // Other instructions
+        //----------------------------------------------------------------------
+        { 0x0fff00f0, 0x06af00f0, ARMV6_ABOVE,  eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>{,<rotation>}" },
+        { 0x0fff00f0, 0x06bf0070, ARMV6_ABOVE,  eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>{,<rotation>}" },
+        { 0x0fff00f0, 0x06ef0070, ARMV6_ABOVE,  eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>{,<rotation>}" },
+        { 0x0fff00f0, 0x06ff0070, ARMV6_ABOVE,  eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>{,<rotation>}" },
+        { 0xfe500000, 0xf8100000, ARMV6_ABOVE,  eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{<amode>} <Rn>{!}" }
+                  
+    };
+    static const size_t k_num_arm_opcodes = sizeof(g_arm_opcodes)/sizeof(ARMOpcode);
+                  
+    for (size_t i=0; i<k_num_arm_opcodes; ++i)
+    {
+        if ((g_arm_opcodes[i].mask & opcode) == g_arm_opcodes[i].value &&
+            (g_arm_opcodes[i].variants & arm_isa) != 0)
+            return &g_arm_opcodes[i];
+    }
+    return NULL;
+}
+
+    
+EmulateInstructionARM::ARMOpcode*
+EmulateInstructionARM::GetThumbOpcodeForInstruction (const uint32_t opcode, uint32_t arm_isa)
+{
+
+    static ARMOpcode 
+    g_thumb_opcodes[] =
+    {
+        //----------------------------------------------------------------------
+        // Prologue instructions
+        //----------------------------------------------------------------------
+
+        // push register(s)
+        { 0xfffffe00, 0x0000b400, ARMvAll,       eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulatePUSH, "push <registers>" },
+        { 0xffff0000, 0xe92d0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <registers>" },
+        { 0xffff0fff, 0xf84d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulatePUSH, "push.w <register>" },
+
+        // set r7 to point to a stack offset
+        { 0xffffff00, 0x0000af00, ARMvAll,       eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDRdSPImm, "add r7, sp, #imm" },
+        // copy the stack pointer to r7
+        { 0xffffffff, 0x0000466f, ARMvAll,       eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdSP, "mov r7, sp" },
+        // move from high register to low register (comes after "mov r7, sp" to resolve ambiguity)
+        { 0xffffffc0, 0x00004640, ARMvAll,       eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVLowHigh, "mov r0-r7, r8-r15" },
+
+        // PC-relative load into register (see also EmulateADDSPRm)
+        { 0xfffff800, 0x00004800, ARMvAll,       eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr <Rt>, [PC, #imm]"},
+
+        // adjust the stack pointer
+        { 0xffffff87, 0x00004485, ARMvAll,       eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPRm, "add sp, <Rm>"},
+        { 0xffffff80, 0x0000b080, ARMvAll,       eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBSPImm, "sub sp, sp, #imm"},
+        { 0xfbef8f00, 0xf1ad0d00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub.w sp, sp, #<const>"},
+        { 0xfbff8f00, 0xf2ad0d00, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw sp, sp, #imm12"},
+        { 0xffef8000, 0xebad0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPReg, "sub{s}<c> <Rd>, sp, <Rm>{,<shift>}" },
+
+        // vector push consecutive extension register(s)
+        { 0xffbf0f00, 0xed2d0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.64 <list>"},
+        { 0xffbf0f00, 0xed2d0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPUSH, "vpush.32 <list>"},
+
+        //----------------------------------------------------------------------
+        // Epilogue instructions
+        //----------------------------------------------------------------------
+
+        { 0xfffff800, 0x0000a800, ARMV4T_ABOVE,  eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add<c> <Rd>, sp, #imm"},
+        { 0xffffff80, 0x0000b000, ARMvAll,       eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDSPImm, "add sp, #imm"},
+        { 0xfffffe00, 0x0000bc00, ARMvAll,       eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulatePOP, "pop <registers>"},
+        { 0xffff0000, 0xe8bd0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <registers>" },
+        { 0xffff0fff, 0xf85d0d04, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulatePOP, "pop.w <register>" },
+        { 0xffbf0f00, 0xecbd0b00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.64 <list>"},
+        { 0xffbf0f00, 0xecbd0a00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateVPOP, "vpop.32 <list>"},
+
+        //----------------------------------------------------------------------
+        // Supervisor Call (previously Software Interrupt)
+        //----------------------------------------------------------------------
+        { 0xffffff00, 0x0000df00, ARMvAll,       eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSVC, "svc #imm8"},
+
+        //----------------------------------------------------------------------
+        // If Then makes up to four following instructions conditional.
+        //----------------------------------------------------------------------
+        // The next 5 opcode _must_ come before the if then instruction
+        { 0xffffffff, 0x0000bf00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateNop, "nop"},
+        { 0xffffffff, 0x0000bf10, ARMV7_ABOVE,   eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateNop, "nop YIELD (yield hint)"},
+        { 0xffffffff, 0x0000bf20, ARMV7_ABOVE,   eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateNop, "nop WFE (wait for event hint)"},
+        { 0xffffffff, 0x0000bf30, ARMV7_ABOVE,   eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateNop, "nop WFI (wait for interrupt hint)"},
+        { 0xffffffff, 0x0000bf40, ARMV7_ABOVE,   eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateNop, "nop SEV (send event hint)"},
+        { 0xffffff00, 0x0000bf00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateIT, "it{<x>{<y>{<z>}}} <firstcond>"},
+
+        //----------------------------------------------------------------------
+        // Branch instructions
+        //----------------------------------------------------------------------
+        // To resolve ambiguity, "b<c> #imm8" should come after "svc #imm8".
+        { 0xfffff000, 0x0000d000, ARMvAll,       eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm8 (outside IT)"},
+        { 0xfffff800, 0x0000e000, ARMvAll,       eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateB, "b<c> #imm11 (outside or last in IT)"},
+        { 0xf800d000, 0xf0008000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside IT)"},
+        { 0xf800d000, 0xf0009000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateB, "b<c>.w #imm8 (outside or last in IT)"},
+        // J1 == J2 == 1
+        { 0xf800d000, 0xf000d000, ARMV4T_ABOVE,  eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "bl <label>"},
+        // J1 == J2 == 1
+        { 0xf800d001, 0xf000c000, ARMV5_ABOVE,   eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateBLXImmediate, "blx <label>"},
+        { 0xffffff87, 0x00004780, ARMV5_ABOVE,   eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateBLXRm, "blx <Rm>"},
+        // for example, "bx lr"
+        { 0xffffff87, 0x00004700, ARMvAll,       eEncodingA1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXRm, "bx <Rm>"},
+        // bxj
+        { 0xfff0ffff, 0xf3c08f00, ARMV5J_ABOVE,  eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBXJRm, "bxj <Rm>"},
+        // compare and branch
+        { 0xfffff500, 0x0000b100, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCB, "cb{n}z <Rn>, <label>"},
+        // table branch byte
+        { 0xfff0fff0, 0xe8d0f000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTB, "tbb<c> <Rn>, <Rm>"},
+        // table branch halfword
+        { 0xfff0fff0, 0xe8d0f010, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTB, "tbh<c> <Rn>, <Rm>, lsl #1"},
+
+        //----------------------------------------------------------------------
+        // Data-processing instructions
+        //----------------------------------------------------------------------
+        // adc (immediate)
+        { 0xfbe08000, 0xf1400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCImm, "adc{s}<c> <Rd>, <Rn>, #<const>"},
+        // adc (register)
+        { 0xffffffc0, 0x00004140, ARMvAll,       eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADCReg, "adcs|adc<c> <Rdn>, <Rm>"},
+        { 0xffe08000, 0xeb400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateADCReg, "adc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
+        // add (register)
+        { 0xfffffe00, 0x00001800, ARMvAll,       eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDReg, "adds|add<c> <Rd>, <Rn>, <Rm>"},
+        // Make sure "add sp, <Rm>" comes before this instruction, so there's no ambiguity decoding the two.
+        { 0xffffff00, 0x00004400, ARMvAll,       eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDReg, "add<c> <Rdn>, <Rm>"},
+        // adr
+        { 0xfffff800, 0x0000a000, ARMvAll,       eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
+        { 0xfbff8000, 0xf2af0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "sub<c> <Rd>, PC, #<const>"},
+        { 0xfbff8000, 0xf20f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateADR, "add<c> <Rd>, PC, #<const>"},
+        // and (immediate)
+        { 0xfbe08000, 0xf0000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDImm, "and{s}<c> <Rd>, <Rn>, #<const>"},
+        // and (register)
+        { 0xffffffc0, 0x00004000, ARMvAll,       eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateANDReg, "ands|and<c> <Rdn>, <Rm>"},
+        { 0xffe08000, 0xea000000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateANDReg, "and{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
+        // bic (immediate)
+        { 0xfbe08000, 0xf0200000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICImm, "bic{s}<c> <Rd>, <Rn>, #<const>"},
+        // bic (register)
+        { 0xffffffc0, 0x00004380, ARMvAll,       eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateBICReg, "bics|bic<c> <Rdn>, <Rm>"},
+        { 0xffe08000, 0xea200000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateBICReg, "bic{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
+        // eor (immediate)
+        { 0xfbe08000, 0xf0800000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORImm, "eor{s}<c> <Rd>, <Rn>, #<const>"},
+        // eor (register)
+        { 0xffffffc0, 0x00004040, ARMvAll,       eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateEORReg, "eors|eor<c> <Rdn>, <Rm>"},
+        { 0xffe08000, 0xea800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateEORReg, "eor{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
+        // orr (immediate)
+        { 0xfbe08000, 0xf0400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRImm, "orr{s}<c> <Rd>, <Rn>, #<const>"},
+        // orr (register)
+        { 0xffffffc0, 0x00004300, ARMvAll,       eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateORRReg, "orrs|orr<c> <Rdn>, <Rm>"},
+        { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateORRReg, "orr{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
+        // rsb (immediate)
+        { 0xffffffc0, 0x00004240, ARMvAll,       eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateRSBImm, "rsbs|rsb<c> <Rd>, <Rn>, #0"},
+        { 0xfbe08000, 0xf1c00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBImm, "rsb{s}<c>.w <Rd>, <Rn>, #<const>"},
+        // rsb (register)
+        { 0xffe08000, 0xea400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRSBReg, "rsb{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
+        // sbc (immediate)
+        { 0xfbe08000, 0xf1600000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCImm, "sbc{s}<c> <Rd>, <Rn>, #<const>"},
+        // sbc (register)
+        { 0xffffffc0, 0x00004180, ARMvAll,       eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSBCReg, "sbcs|sbc<c> <Rdn>, <Rm>"},
+        { 0xffe08000, 0xeb600000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSBCReg, "sbc{s}<c>.w <Rd>, <Rn>, <Rm> {,<shift>}"},
+        // add (immediate, Thumb)
+        { 0xfffffe00, 0x00001c00, ARMV4T_ABOVE,  eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rd>,<Rn>,#<imm3>" },
+        { 0xfffff800, 0x00003000, ARMV4T_ABOVE,  eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateADDImmThumb, "adds|add<c> <Rdn>,#<imm8>" },
+        { 0xfbe08000, 0xf1000000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "add{s}<c>.w <Rd>,<Rn>,#<const>" },
+        { 0xfbf08000, 0xf2000000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateADDImmThumb, "addw<c> <Rd>,<Rn>,#<imm12>" },
+        // sub (immediate, Thumb)
+        { 0xfffffe00, 0x00001e00, ARMvAll,       eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rd>, <Rn> #imm3"},
+        { 0xfffff800, 0x00003800, ARMvAll,       eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBImmThumb, "subs|sub<c> <Rdn>, #imm8"},
+        { 0xfbe08000, 0xf1a00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "sub{s}<c>.w <Rd>, <Rn>, #<const>"},
+        { 0xfbf08000, 0xf2a00000, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBImmThumb, "subw<c> <Rd>, <Rn>, #imm12"},
+        // sub (sp minus immediate)
+        { 0xfbef8000, 0xf1ad0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "sub{s}.w <Rd>, sp, #<const>"},
+        { 0xfbff8000, 0xf2ad0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPImm, "subw<c> <Rd>, sp, #imm12"},
+        // sub (register)
+        { 0xfffffe00, 0x00001a00, ARMV4T_ABOVE,  eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSUBReg, "subs|sub<c> <Rd>, <Rn>, <Rm>"},
+        { 0xffe08000, 0xeba00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBReg, "sub{s}<c>.w <Rd>, <Rn>, <Rm>{,<shift>}"},
+        // teq (immediate)
+        { 0xfbf08f00, 0xf0900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQImm, "teq<c> <Rn>, #<const>"},
+        // teq (register)
+        { 0xfff08f00, 0xea900f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTEQReg, "teq<c> <Rn>, <Rm> {,<shift>}"},
+        // tst (immediate)
+        { 0xfbf08f00, 0xf0100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTImm, "tst<c> <Rn>, #<const>"},
+        // tst (register)
+        { 0xffffffc0, 0x00004200, ARMvAll,       eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateTSTReg, "tst<c> <Rdn>, <Rm>"},
+        { 0xfff08f00, 0xea100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateTSTReg, "tst<c>.w <Rn>, <Rm> {,<shift>}"},
+
+
+        // move from high register to high register
+        { 0xffffff00, 0x00004600, ARMvAll,       eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "mov<c> <Rd>, <Rm>"},
+        // move from low register to low register
+        { 0xffffffc0, 0x00000000, ARMvAll,       eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdRm, "movs <Rd>, <Rm>"},
+        // mov{s}<c>.w <Rd>, <Rm>
+        { 0xffeff0f0, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdRm, "mov{s}<c>.w <Rd>, <Rm>"},
+        // move immediate
+        { 0xfffff800, 0x00002000, ARMvAll,       eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMOVRdImm, "movs|mov<c> <Rd>, #imm8"},
+        { 0xfbef8000, 0xf04f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "mov{s}<c>.w <Rd>, #<const>"},
+        { 0xfbf08000, 0xf2400000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateMOVRdImm, "movw<c> <Rd>,#<imm16>"},
+        // mvn (immediate)
+        { 0xfbef8000, 0xf06f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNImm, "mvn{s} <Rd>, #<const>"},
+        // mvn (register)
+        { 0xffffffc0, 0x000043c0, ARMvAll,       eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMVNReg, "mvns|mvn<c> <Rd>, <Rm>"},
+        { 0xffef8000, 0xea6f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMVNReg, "mvn{s}<c>.w <Rd>, <Rm> {,<shift>}"},
+        // cmn (immediate)
+        { 0xfbf08f00, 0xf1100f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNImm, "cmn<c> <Rn>, #<const>"},
+        // cmn (register)
+        { 0xffffffc0, 0x000042c0, ARMvAll,       eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm>"},
+        { 0xfff08f00, 0xeb100f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMNReg, "cmn<c> <Rn>, <Rm> {,<shift>}"},
+        // cmp (immediate)
+        { 0xfffff800, 0x00002800, ARMvAll,       eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPImm, "cmp<c> <Rn>, #imm8"},
+        { 0xfbf08f00, 0xf1b00f00, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateCMPImm, "cmp<c>.w <Rn>, #<const>"},
+        // cmp (register) (Rn and Rm both from r0-r7)
+        { 0xffffffc0, 0x00004280, ARMvAll,       eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
+        // cmp (register) (Rn and Rm not both from r0-r7)
+        { 0xffffff00, 0x00004500, ARMvAll,       eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp<c> <Rn>, <Rm>"},
+        // asr (immediate)
+        { 0xfffff800, 0x00001000, ARMvAll,       eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr<c> <Rd>, <Rm>, #imm"},
+        { 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}<c>.w <Rd>, <Rm>, #imm"},
+        // asr (register)
+        { 0xffffffc0, 0x00004100, ARMvAll,       eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateASRReg, "asrs|asr<c> <Rdn>, <Rm>"},
+        { 0xffe0f0f0, 0xfa40f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRReg, "asr{s}<c>.w <Rd>, <Rn>, <Rm>"},
+        // lsl (immediate)
+        { 0xfffff800, 0x00000000, ARMvAll,       eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSLImm, "lsls|lsl<c> <Rd>, <Rm>, #imm"},
+        { 0xffef8030, 0xea4f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLImm, "lsl{s}<c>.w <Rd>, <Rm>, #imm"},
+        // lsl (register)
+        { 0xffffffc0, 0x00004080, ARMvAll,       eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSLReg, "lsls|lsl<c> <Rdn>, <Rm>"},
+        { 0xffe0f0f0, 0xfa00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSLReg, "lsl{s}<c>.w <Rd>, <Rn>, <Rm>"},
+        // lsr (immediate)
+        { 0xfffff800, 0x00000800, ARMvAll,       eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSRImm, "lsrs|lsr<c> <Rd>, <Rm>, #imm"},
+        { 0xffef8030, 0xea4f0010, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRImm, "lsr{s}<c>.w <Rd>, <Rm>, #imm"},
+        // lsr (register)
+        { 0xffffffc0, 0x000040c0, ARMvAll,       eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLSRReg, "lsrs|lsr<c> <Rdn>, <Rm>"},
+        { 0xffe0f0f0, 0xfa20f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLSRReg, "lsr{s}<c>.w <Rd>, <Rn>, <Rm>"},
+        // rrx is a special case encoding of ror (immediate)
+        { 0xffeff0f0, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRRX, "rrx{s}<c>.w <Rd>, <Rm>"},
+        // ror (immediate)
+        { 0xffef8030, 0xea4f0030, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORImm, "ror{s}<c>.w <Rd>, <Rm>, #imm"},
+        // ror (register)
+        { 0xffffffc0, 0x000041c0, ARMvAll,       eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateRORReg, "rors|ror<c> <Rdn>, <Rm>"},
+        { 0xffe0f0f0, 0xfa60f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRORReg, "ror{s}<c>.w <Rd>, <Rn>, <Rm>"},
+        // mul
+        { 0xffffffc0, 0x00004340, ARMV4T_ABOVE,  eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateMUL, "muls <Rdm>,<Rn>,<Rdm>" },
+        // mul
+        { 0xfff0f0f0, 0xfb00f000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateMUL, "mul<c> <Rd>,<Rn>,<Rm>" },
+
+        // subs pc, lr and related instructions
+        { 0xffffff00, 0xf3de8f00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSUBSPcLrEtc, "SUBS<c> PC, LR, #<imm8>" },
+
+        //----------------------------------------------------------------------
+        // RFE instructions  *** IMPORTANT *** THESE MUST BE LISTED **BEFORE** THE LDM.. Instructions in this table; 
+        // otherwise the wrong instructions will be selected.
+        //----------------------------------------------------------------------
+ 
+        { 0xffd0ffff, 0xe810c000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfedb<c> <Rn>{!}" },
+        { 0xffd0ffff, 0xe990c000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateRFE, "rfe{ia}<c> <Rn>{!}" },
+
+        //----------------------------------------------------------------------
+        // Load instructions
+        //----------------------------------------------------------------------
+        { 0xfffff800, 0x0000c800, ARMV4T_ABOVE,  eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDM, "ldm<c> <Rn>{!} <registers>" },
+        { 0xffd02000, 0xe8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDM, "ldm<c>.w <Rn>{!} <registers>" },
+        { 0xffd00000, 0xe9100000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDMDB, "ldmdb<c> <Rn>{!} <registers>" },
+        { 0xfffff800, 0x00006800, ARMV4T_ABOVE,  eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#imm}]"},
+        { 0xfffff800, 0x00009800, ARMV4T_ABOVE,  eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [SP{,#imm}]"},
+        { 0xfff00000, 0xf8d00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c>.w <Rt>, [<Rn>{,#imm12}]"},
+        { 0xfff00800, 0xf8500800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtRnImm, "ldr<c> <Rt>, [<Rn>{,#+/-<imm8>}]{!}"},
+                  // Thumb2 PC-relative load into register
+        { 0xff7f0000, 0xf85f0000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRtPCRelative, "ldr<c>.w <Rt>, [PC, +/-#imm}]"},
+        { 0xfffffe00, 0x00005800, ARMV4T_ABOVE,  eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c> <Rt>, [<Rn>, <Rm>]" }, 
+        { 0xfff00fc0, 0xf8500000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRRegister, "ldr<c>.w <Rt>, [<Rn>,<Rm>{,LSL #<imm2>}]" },
+        { 0xfffff800, 0x00007800, ARMV4T_ABOVE,  eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>{,#<imm5>}]" },
+        { 0xfff00000, 0xf8900000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
+        { 0xfff00800, 0xf8100800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBImmediate, "ldrb<c> <Rt>,[<Rn>, #+/-<imm8>]{!}" },
+        { 0xff7f0000, 0xf81f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBLiteral, "ldrb<c> <Rt>,[...]" },
+        { 0xfffffe00, 0x00005c00, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c> <Rt>,[<Rn>,<Rm>]" },
+        { 0xfff00fc0, 0xf8100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRBRegister, "ldrb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]" },
+        { 0xfffff800, 0x00008800, ARMV4T_ABOVE,  eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>, [<Rn>{,#<imm>}]"  },
+        { 0xfff00000, 0xf8b00000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c>.w <Rt>,[<Rn>{,#<imm12>}]" },
+        { 0xfff00800, 0xf8300800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHImmediate, "ldrh<c> <Rt>,[<Rn>,#+/-<imm8>]{!}"  },
+        { 0xff7f0000, 0xf83f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHLiteral, "ldrh<c> <Rt>, <label>" },
+        { 0xfffffe00, 0x00005a00, ARMV4T_ABOVE,  eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c> <Rt>, [<Rn>,<Rm>]" },
+        { 0xfff00fc0, 0xf8300000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRHRegister, "ldrh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
+        { 0xfff00000, 0xf9900000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#<imm12>]" },
+        { 0xfff00800, 0xf9100800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBImmediate, "ldrsb<c> <Rt>,[<Rn>,#+/-<imm8>]" },
+        { 0xff7f0000, 0xf91f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBLiteral, "ldrsb<c> <Rt>, <label>" },
+        { 0xfffffe00, 0x00005600, ARMV4T_ABOVE,  eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c> <Rt>,[<Rn>,<Rm>]" },
+        { 0xfff00fc0, 0xf9100000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSBRegister, "ldrsb<c>.w <Rt>,[<Rn>,<Rm>{,LSL #imm2>}]"  },
+        { 0xfff00000, 0xf9b00000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#<imm12>]" },
+        { 0xfff00800, 0xf9300800, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHImmediate, "ldrsh<c> <Rt>,[<Rn>,#+/-<imm8>]" },
+        { 0xff7f0000, 0xf93f0000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHLiteral, "ldrsh<c> <Rt>,<label>" },
+        { 0xfffffe00, 0x00005e00, ARMV4T_ABOVE,  eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c> <Rt>,[<Rn>,<Rm>]" },
+        { 0xfff00fc0, 0xf9300000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRSHRegister, "ldrsh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
+        { 0xfe500000, 0xe8500000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateLDRDImmediate, "ldrd<c> <Rt>, <Rt2>, [<Rn>,#+/-<imm>]!"},
+        { 0xfe100f00, 0xec100b00, ARMvAll,       eEncodingT1, VFPv2_ABOVE,  eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>"},
+        { 0xfe100f00, 0xec100a00, ARMvAll,       eEncodingT2, VFPv2v3,      eSize32, &EmulateInstructionARM::EmulateVLDM, "vldm{mode}<c> <Rn>{!}, <list>" },
+        { 0xffe00f00, 0xed100b00, ARMvAll,       eEncodingT1, VFPv2_ABOVE,  eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
+        { 0xff300f00, 0xed100a00, ARMvAll,       eEncodingT2, VFPv2v3,      eSize32, &EmulateInstructionARM::EmulateVLDR, "vldr<c> <Sd>, {<Rn>{,#+/-<imm>}]"},
+        { 0xffb00000, 0xf9200000, ARMvAll,       eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Multiple, "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"},
+        { 0xffb00300, 0xf9a00000, ARMvAll,       eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1Single, "vld1<c>.<size> <list>, [<Rn>{@<align>}],<Rm>"},
+        { 0xffb00f00, 0xf9a00c00, ARMvAll,       eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVLD1SingleAll, "vld1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
+                  
+        //----------------------------------------------------------------------
+        // Store instructions
+        //----------------------------------------------------------------------
+        { 0xfffff800, 0x0000c000, ARMV4T_ABOVE,  eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTM, "stm<c> <Rn>{!} <registers>" },
+        { 0xffd00000, 0xe8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTM, "stm<c>.w <Rn>{!} <registers>" },
+        { 0xffd00000, 0xe9000000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTMDB, "stmdb<c> <Rn>{!} <registers>" },
+        { 0xfffff800, 0x00006000, ARMV4T_ABOVE,  eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>{,#<imm>}]" },
+        { 0xfffff800, 0x00009000, ARMV4T_ABOVE,  eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [SP,#<imm>]" },
+        { 0xfff00000, 0xf8c00000, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c>.w <Rt>, [<Rn>,#<imm12>]" },
+        { 0xfff00800, 0xf8400800, ARMV6T2_ABOVE, eEncodingT4, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRThumb, "str<c> <Rt>, [<Rn>,#+/-<imm8>]" },
+        { 0xfffffe00, 0x00005000, ARMV4T_ABOVE,  eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRRegister, "str<c> <Rt> ,{<Rn>, <Rm>]" },
+        { 0xfff00fc0, 0xf8400000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRRegister, "str<c>.w <Rt>, [<Rn>, <Rm> {lsl #imm2>}]" },
+        { 0xfffff800, 0x00007000, ARMV4T_ABOVE,  eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt>, [<Rn>, #<imm5>]" },
+        { 0xfff00000, 0xf8800000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c>.w <Rt>, [<Rn>, #<imm12>]" },
+        { 0xfff00800, 0xf8000800, ARMV6T2_ABOVE, eEncodingT3, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRBThumb, "strb<c> <Rt> ,[<Rn>, #+/-<imm8>]{!}" },
+        { 0xfffffe00, 0x00005200, ARMV4T_ABOVE,  eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c> <Rt>,[<Rn>,<Rm>]" },
+        { 0xfff00fc0, 0xf8200000, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRHRegister, "strh<c>.w <Rt>,[<Rn>,<Rm>{,LSL #<imm2>}]" },
+        { 0xfff00000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTREX, "strex<c> <Rd>, <Rt>, [<Rn{,#<imm>}]" },
+        { 0xfe500000, 0xe8400000, ARMV6T2_ABOVE, eEncodingT1, No_VFP, eSize32, &EmulateInstructionARM::EmulateSTRDImm, "strd<c> <Rt>, <Rt2>, [<Rn>, #+/-<imm>]!"},
+        { 0xfe100f00, 0xec000b00, ARMvAll,       eEncodingT1, VFPv2_ABOVE,  eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"},
+        { 0xfea00f00, 0xec000a00, ARMvAll,       eEncodingT2, VFPv2v3,      eSize32, &EmulateInstructionARM::EmulateVSTM, "vstm{mode}<c> <Rn>{!}, <list>"},
+        { 0xff300f00, 0xed000b00, ARMvAll,       eEncodingT1, VFPv2_ABOVE,  eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Dd>, [<Rn>{,#+/-<imm>}]"},
+        { 0xff300f00, 0xed000a00, ARMvAll,       eEncodingT2, VFPv2v3,      eSize32, &EmulateInstructionARM::EmulateVSTR, "vstr<c> <Sd>, [<Rn>{,#+/-<imm>}]"},
+        { 0xffb00000, 0xf9000000, ARMvAll,       eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Multiple, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"},
+        { 0xffb00300, 0xf9800000, ARMvAll,       eEncodingT1, AdvancedSIMD, eSize32, &EmulateInstructionARM::EmulateVST1Single, "vst1<c>.<size> <list>, [<Rn>{@<align>}], <Rm>"}, 
+                  
+        //----------------------------------------------------------------------
+        // Other instructions
+        //----------------------------------------------------------------------
+        { 0xffffffc0, 0x0000b240, ARMV6_ABOVE,   eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSXTB, "sxtb<c> <Rd>,<Rm>" },
+        { 0xfffff080, 0xfa4ff080, ARMV6_ABOVE,   eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTB, "sxtb<c>.w <Rd>,<Rm>{,<rotation>}" },
+        { 0xffffffc0, 0x0000b200, ARMV6_ABOVE,   eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateSXTH, "sxth<c> <Rd>,<Rm>" },
+        { 0xfffff080, 0xfa0ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateSXTH, "sxth<c>.w <Rd>,<Rm>{,<rotation>}" },
+        { 0xffffffc0, 0x0000b2c0, ARMV6_ABOVE,   eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateUXTB, "uxtb<c> <Rd>,<Rm>" },
+        { 0xfffff080, 0xfa5ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTB, "uxtb<c>.w <Rd>,<Rm>{,<rotation>}" },
+        { 0xffffffc0, 0x0000b280, ARMV6_ABOVE,   eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateUXTH, "uxth<c> <Rd>,<Rm>" },
+        { 0xfffff080, 0xfa1ff080, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateUXTH, "uxth<c>.w <Rd>,<Rm>{,<rotation>}" },
+    };
+
+    const size_t k_num_thumb_opcodes = sizeof(g_thumb_opcodes)/sizeof(ARMOpcode);
+    for (size_t i=0; i<k_num_thumb_opcodes; ++i)
+    {
+        if ((g_thumb_opcodes[i].mask & opcode) == g_thumb_opcodes[i].value &&
+            (g_thumb_opcodes[i].variants & arm_isa) != 0)
+            return &g_thumb_opcodes[i];
+    }
+    return NULL;
+}
+
+bool
+EmulateInstructionARM::SetArchitecture (const ArchSpec &arch)
+{
+    m_arch = arch;
+    m_arm_isa = 0;
+    const char *arch_cstr = arch.GetArchitectureName ();
+    if (arch_cstr)
+    {
+        if      (0 == ::strcasecmp(arch_cstr, "armv4t"))    m_arm_isa = ARMv4T;
+        else if (0 == ::strcasecmp(arch_cstr, "armv5tej"))  m_arm_isa = ARMv5TEJ;
+        else if (0 == ::strcasecmp(arch_cstr, "armv5te"))   m_arm_isa = ARMv5TE;
+        else if (0 == ::strcasecmp(arch_cstr, "armv5t"))    m_arm_isa = ARMv5T;
+        else if (0 == ::strcasecmp(arch_cstr, "armv6k"))    m_arm_isa = ARMv6K;
+        else if (0 == ::strcasecmp(arch_cstr, "armv6t2"))   m_arm_isa = ARMv6T2;
+        else if (0 == ::strcasecmp(arch_cstr, "armv7s"))    m_arm_isa = ARMv7S;
+        else if (0 == ::strcasecmp(arch_cstr, "arm"))       m_arm_isa = ARMvAll;
+        else if (0 == ::strcasecmp(arch_cstr, "thumb"))     m_arm_isa = ARMvAll;
+        else if (0 == ::strncasecmp(arch_cstr,"armv4", 5))  m_arm_isa = ARMv4;
+        else if (0 == ::strncasecmp(arch_cstr,"armv6", 5))  m_arm_isa = ARMv6;
+        else if (0 == ::strncasecmp(arch_cstr,"armv7", 5))  m_arm_isa = ARMv7;
+        else if (0 == ::strncasecmp(arch_cstr,"armv8", 5))  m_arm_isa = ARMv8;
+    }
+    return m_arm_isa != 0;
+}
+
+bool
+EmulateInstructionARM::SetInstruction (const Opcode &insn_opcode, const Address &inst_addr, Target *target)
+{
+    if (EmulateInstruction::SetInstruction (insn_opcode, inst_addr, target))
+    {
+        if (m_arch.GetTriple().getArch() == llvm::Triple::thumb)
+            m_opcode_mode = eModeThumb;
+        else
+        {
+            AddressClass addr_class = inst_addr.GetAddressClass();
+
+            if ((addr_class == eAddressClassCode) || (addr_class == eAddressClassUnknown))
+                m_opcode_mode = eModeARM;
+            else if (addr_class == eAddressClassCodeAlternateISA)
+                m_opcode_mode = eModeThumb;
+            else
+                return false;
+        }
+        if (m_opcode_mode == eModeThumb)
+            m_opcode_cpsr = CPSR_MODE_USR | MASK_CPSR_T;
+        else
+            m_opcode_cpsr = CPSR_MODE_USR;
+        return true;
+    }
+    return false;
+}
+
+bool 
+EmulateInstructionARM::ReadInstruction ()
+{
+    bool success = false;
+    m_opcode_cpsr = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, 0, &success);
+    if (success)
+    {
+        addr_t pc = ReadRegisterUnsigned (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_ADDRESS, &success);
+        if (success)
+        {
+            Context read_inst_context;
+            read_inst_context.type = eContextReadOpcode;
+            read_inst_context.SetNoArgs ();
+                  
+            if (m_opcode_cpsr & MASK_CPSR_T)
+            {
+                m_opcode_mode = eModeThumb;
+                uint32_t thumb_opcode = MemARead(read_inst_context, pc, 2, 0, &success);
+                
+                if (success)
+                {
+                    if ((thumb_opcode & 0xe000) != 0xe000 || ((thumb_opcode & 0x1800u) == 0))
+                    {
+                        m_opcode.SetOpcode16 (thumb_opcode);
+                    }
+                    else
+                    {
+                        m_opcode.SetOpcode32 ((thumb_opcode << 16) | MemARead(read_inst_context, pc + 2, 2, 0, &success));
+                    }
+                }
+            }
+            else
+            {
+                m_opcode_mode = eModeARM;
+                m_opcode.SetOpcode32 (MemARead(read_inst_context, pc, 4, 0, &success));
+            }
+        }
+    }
+    if (!success)
+    {
+        m_opcode_mode = eModeInvalid;
+        m_addr = LLDB_INVALID_ADDRESS;
+    }
+    return success;
+}
+
+uint32_t
+EmulateInstructionARM::ArchVersion ()
+{
+    return m_arm_isa;
+}
+
+bool
+EmulateInstructionARM::ConditionPassed (const uint32_t opcode, bool *is_conditional)
+{
+   // If we are ignoring conditions, then always return true.
+   // this allows us to iterate over disassembly code and still
+   // emulate an instruction even if we don't have all the right
+   // bits set in the CPSR register...
+    if (m_ignore_conditions)
+        return true;
+    
+    if (is_conditional)
+        *is_conditional = true;
+
+    const uint32_t cond = CurrentCond (opcode);
+    
+    if (cond == UINT32_MAX)
+        return false;
+    
+    bool result = false;
+    switch (UnsignedBits(cond, 3, 1))
+    {
+    case 0: 
+		if (m_opcode_cpsr == 0)
+			result = true;
+        else
+            result = (m_opcode_cpsr & MASK_CPSR_Z) != 0; 
+		break;
+    case 1:
+        if (m_opcode_cpsr == 0)
+            result = true;
+        else
+            result = (m_opcode_cpsr & MASK_CPSR_C) != 0; 
+		break;
+    case 2:
+        if (m_opcode_cpsr == 0)
+            result = true;
+        else
+            result = (m_opcode_cpsr & MASK_CPSR_N) != 0; 
+		break;
+    case 3:
+        if (m_opcode_cpsr == 0)
+            result = true;
+        else
+            result = (m_opcode_cpsr & MASK_CPSR_V) != 0; 
+		break;
+    case 4:
+        if (m_opcode_cpsr == 0)
+            result = true;
+        else
+            result = ((m_opcode_cpsr & MASK_CPSR_C) != 0) && ((m_opcode_cpsr & MASK_CPSR_Z) == 0); 
+		break;
+    case 5: 
+        if (m_opcode_cpsr == 0)
+            result = true;
+        else
+		{
+            bool n = (m_opcode_cpsr & MASK_CPSR_N);
+            bool v = (m_opcode_cpsr & MASK_CPSR_V);
+            result = n == v;
+        }
+        break;
+    case 6: 
+        if (m_opcode_cpsr == 0)
+            result = true;
+        else
+		{
+            bool n = (m_opcode_cpsr & MASK_CPSR_N);
+            bool v = (m_opcode_cpsr & MASK_CPSR_V);
+            result = n == v && ((m_opcode_cpsr & MASK_CPSR_Z) == 0);
+        }
+        break;
+    case 7: 
+        // Always execute (cond == 0b1110, or the special 0b1111 which gives
+        // opcodes different meanings, but always means execution happpens.
+        if (is_conditional)
+            *is_conditional = false;
+        result = true; 
+        break;
+    }
+
+    if (cond & 1)
+        result = !result;
+    return result;
+}
+
+uint32_t
+EmulateInstructionARM::CurrentCond (const uint32_t opcode)
+{
+    switch (m_opcode_mode)
+    {
+    case eModeInvalid:
+        break;
+
+    case eModeARM:
+        return UnsignedBits(opcode, 31, 28);
+    
+    case eModeThumb:
+        // For T1 and T3 encodings of the Branch instruction, it returns the 4-bit
+        // 'cond' field of the encoding.
+        {
+            const uint32_t byte_size = m_opcode.GetByteSize();
+            if (byte_size == 2)
+            {
+                if (Bits32(opcode, 15, 12) == 0x0d && Bits32(opcode, 11, 7) != 0x0f)
+                    return Bits32(opcode, 11, 7);
+            }
+            else if (byte_size == 4)
+            {
+                if (Bits32(opcode, 31, 27) == 0x1e &&
+                    Bits32(opcode, 15, 14) == 0x02 &&
+                    Bits32(opcode, 12, 12) == 0x00 &&
+                    Bits32(opcode, 25, 22) <= 0x0d)
+                {
+                    return Bits32(opcode, 25, 22);
+                }
+            }
+            else
+                // We have an invalid thumb instruction, let's bail out.
+                break;
+            
+            return m_it_session.GetCond();
+        }
+    }
+    return UINT32_MAX;  // Return invalid value
+}
+
+bool
+EmulateInstructionARM::InITBlock()
+{
+    return CurrentInstrSet() == eModeThumb && m_it_session.InITBlock();
+}
+
+bool
+EmulateInstructionARM::LastInITBlock()
+{
+    return CurrentInstrSet() == eModeThumb && m_it_session.LastInITBlock();
+}
+
+bool 
+EmulateInstructionARM::BadMode (uint32_t mode)
+{
+                  
+    switch (mode)
+    {
+        case 16: return false; // '10000'
+        case 17: return false; // '10001'
+        case 18: return false; // '10010'
+        case 19: return false; // '10011'
+        case 22: return false; // '10110'
+        case 23: return false; // '10111'
+        case 27: return false; // '11011'
+        case 31: return false; // '11111'
+        default: return true;
+    }
+    return true;
+}
+                
+bool
+EmulateInstructionARM::CurrentModeIsPrivileged ()
+{
+    uint32_t mode = Bits32 (m_opcode_cpsr, 4, 0);
+                  
+    if (BadMode (mode))
+        return false;
+                  
+    if (mode == 16)
+        return false;
+                
+    return true;
+}
+
+void
+EmulateInstructionARM::CPSRWriteByInstr (uint32_t value, uint32_t bytemask, bool affect_execstate)
+{
+    bool privileged = CurrentModeIsPrivileged();
+
+    uint32_t tmp_cpsr = Bits32 (m_opcode_cpsr, 23, 20) << 20;
+                  
+    if (BitIsSet (bytemask, 3))
+    {
+        tmp_cpsr = tmp_cpsr | (Bits32 (value, 31, 27) << 27);
+        if (affect_execstate)
+            tmp_cpsr = tmp_cpsr | (Bits32 (value, 26, 24) << 24);
+    }
+                  
+    if (BitIsSet (bytemask, 2))
+    {
+        tmp_cpsr = tmp_cpsr | (Bits32 (value, 19, 16) << 16);
+    }
+                  
+    if (BitIsSet (bytemask, 1))
+    {
+        if (affect_execstate)
+            tmp_cpsr = tmp_cpsr | (Bits32 (value, 15, 10) << 10);
+        tmp_cpsr = tmp_cpsr | (Bit32 (value, 9) << 9);
+        if (privileged)
+            tmp_cpsr = tmp_cpsr | (Bit32 (value, 8) << 8);
+    }
+                
+    if (BitIsSet (bytemask, 0))
+    {
+        if (privileged)
+            tmp_cpsr = tmp_cpsr | (Bits32 (value, 7, 6) << 6);
+        if (affect_execstate)
+            tmp_cpsr = tmp_cpsr | (Bit32 (value, 5) << 5);
+        if (privileged)
+            tmp_cpsr = tmp_cpsr | Bits32 (value, 4, 0);
+    }
+                  
+    m_opcode_cpsr = tmp_cpsr;
+}
+
+                  
+bool
+EmulateInstructionARM::BranchWritePC (const Context &context, uint32_t addr)
+{
+    addr_t target;
+
+    // Check the current instruction set.
+    if (CurrentInstrSet() == eModeARM)
+        target = addr & 0xfffffffc;
+    else
+        target = addr & 0xfffffffe;
+
+    if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
+        return false;
+
+    return true;
+}
+
+// As a side effect, BXWritePC sets context.arg2 to eModeARM or eModeThumb by inspecting addr.
+bool
+EmulateInstructionARM::BXWritePC (Context &context, uint32_t addr)
+{
+    addr_t target;
+    // If the CPSR is changed due to switching between ARM and Thumb ISETSTATE,
+    // we want to record it and issue a WriteRegister callback so the clients
+    // can track the mode changes accordingly.
+    bool cpsr_changed = false;
+
+    if (BitIsSet(addr, 0))
+    {
+        if (CurrentInstrSet() != eModeThumb)
+        {
+            SelectInstrSet(eModeThumb);
+            cpsr_changed = true;
+        }
+        target = addr & 0xfffffffe;
+        context.SetISA (eModeThumb);
+    }
+    else if (BitIsClear(addr, 1))
+    {
+        if (CurrentInstrSet() != eModeARM)
+        {
+            SelectInstrSet(eModeARM);
+            cpsr_changed = true;
+        }
+        target = addr & 0xfffffffc;
+        context.SetISA (eModeARM);
+    }
+    else
+        return false; // address<1:0> == '10' => UNPREDICTABLE
+
+    if (cpsr_changed)
+    {
+        if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
+            return false;
+    }
+    if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, target))
+        return false;
+
+    return true;
+}
+
+// Dispatches to either BXWritePC or BranchWritePC based on architecture versions.
+bool
+EmulateInstructionARM::LoadWritePC (Context &context, uint32_t addr)
+{
+    if (ArchVersion() >= ARMv5T)
+        return BXWritePC(context, addr);
+    else
+        return BranchWritePC((const Context)context, addr);
+}
+
+// Dispatches to either BXWritePC or BranchWritePC based on architecture versions and current instruction set.
+bool
+EmulateInstructionARM::ALUWritePC (Context &context, uint32_t addr)
+{
+    if (ArchVersion() >= ARMv7 && CurrentInstrSet() == eModeARM)
+        return BXWritePC(context, addr);
+    else
+        return BranchWritePC((const Context)context, addr);
+}
+
+EmulateInstructionARM::Mode
+EmulateInstructionARM::CurrentInstrSet ()
+{
+    return m_opcode_mode;
+}
+
+// Set the 'T' bit of our CPSR.  The m_opcode_mode gets updated when the next
+// ReadInstruction() is performed.  This function has a side effect of updating
+// the m_new_inst_cpsr member variable if necessary.
+bool
+EmulateInstructionARM::SelectInstrSet (Mode arm_or_thumb)
+{
+    m_new_inst_cpsr = m_opcode_cpsr;
+    switch (arm_or_thumb)
+    {
+    default:
+        return false;
+    case eModeARM:
+        // Clear the T bit.
+        m_new_inst_cpsr &= ~MASK_CPSR_T;
+        break;
+    case eModeThumb:
+        // Set the T bit.
+        m_new_inst_cpsr |= MASK_CPSR_T;
+        break;
+    }
+    return true;
+}
+
+// This function returns TRUE if the processor currently provides support for
+// unaligned memory accesses, or FALSE otherwise. This is always TRUE in ARMv7,
+// controllable by the SCTLR.U bit in ARMv6, and always FALSE before ARMv6.
+bool
+EmulateInstructionARM::UnalignedSupport()
+{
+    return (ArchVersion() >= ARMv7);
+}
+
+// The main addition and subtraction instructions can produce status information
+// about both unsigned carry and signed overflow conditions.  This status
+// information can be used to synthesize multi-word additions and subtractions.
+EmulateInstructionARM::AddWithCarryResult
+EmulateInstructionARM::AddWithCarry (uint32_t x, uint32_t y, uint8_t carry_in)
+{
+    uint32_t result;
+    uint8_t carry_out;
+    uint8_t overflow;
+
+    uint64_t unsigned_sum = x + y + carry_in;
+    int64_t signed_sum = (int32_t)x + (int32_t)y + (int32_t)carry_in;
+    
+    result = UnsignedBits(unsigned_sum, 31, 0);
+//    carry_out = (result == unsigned_sum ? 0 : 1);
+    overflow = ((int32_t)result == signed_sum ? 0 : 1);
+
+    if (carry_in)
+        carry_out = ((int32_t) x >= (int32_t) (~y)) ? 1 : 0;
+    else
+        carry_out = ((int32_t) x > (int32_t) y) ? 1 : 0;
+    
+    AddWithCarryResult res = { result, carry_out, overflow };
+    return res;
+}
+
+uint32_t
+EmulateInstructionARM::ReadCoreReg(uint32_t num, bool *success)
+{
+    uint32_t reg_kind, reg_num;
+    switch (num)
+    {
+    case SP_REG:
+        reg_kind = eRegisterKindGeneric;
+        reg_num  = LLDB_REGNUM_GENERIC_SP;
+        break;
+    case LR_REG:
+        reg_kind = eRegisterKindGeneric;
+        reg_num  = LLDB_REGNUM_GENERIC_RA;
+        break;
+    case PC_REG:
+        reg_kind = eRegisterKindGeneric;
+        reg_num  = LLDB_REGNUM_GENERIC_PC;
+        break;
+    default:
+        if (num < SP_REG)
+        {
+            reg_kind = eRegisterKindDWARF;
+            reg_num  = dwarf_r0 + num;
+        }
+        else
+        {
+            //assert(0 && "Invalid register number");
+            *success = false;
+            return UINT32_MAX;
+        }
+        break;
+    }
+
+    // Read our register.
+    uint32_t val = ReadRegisterUnsigned (reg_kind, reg_num, 0, success);
+
+    // When executing an ARM instruction , PC reads as the address of the current
+    // instruction plus 8.
+    // When executing a Thumb instruction , PC reads as the address of the current
+    // instruction plus 4.
+    if (num == 15)
+    {
+        if (CurrentInstrSet() == eModeARM)
+            val += 8;
+        else
+            val += 4;
+    }
+
+    return val;
+}
+
+// Write the result to the ARM core register Rd, and optionally update the
+// condition flags based on the result.
+//
+// This helper method tries to encapsulate the following pseudocode from the
+// ARM Architecture Reference Manual:
+//
+// if d == 15 then         // Can only occur for encoding A1
+//     ALUWritePC(result); // setflags is always FALSE here
+// else
+//     R[d] = result;
+//     if setflags then
+//         APSR.N = result<31>;
+//         APSR.Z = IsZeroBit(result);
+//         APSR.C = carry;
+//         // APSR.V unchanged
+//
+// In the above case, the API client does not pass in the overflow arg, which
+// defaults to ~0u.
+bool
+EmulateInstructionARM::WriteCoreRegOptionalFlags (Context &context,
+                                                  const uint32_t result,
+                                                  const uint32_t Rd,
+                                                  bool setflags,
+                                                  const uint32_t carry,
+                                                  const uint32_t overflow)
+{
+    if (Rd == 15)
+    {
+        if (!ALUWritePC (context, result))
+            return false;
+    }
+    else
+    {
+        uint32_t reg_kind, reg_num;
+        switch (Rd)
+        {
+        case SP_REG:
+            reg_kind = eRegisterKindGeneric;
+            reg_num  = LLDB_REGNUM_GENERIC_SP;
+            break;
+        case LR_REG:
+            reg_kind = eRegisterKindGeneric;
+            reg_num  = LLDB_REGNUM_GENERIC_RA;
+            break;
+        default:
+            reg_kind = eRegisterKindDWARF;
+            reg_num  = dwarf_r0 + Rd;
+        }
+        if (!WriteRegisterUnsigned (context, reg_kind, reg_num, result))
+            return false;
+        if (setflags)
+            return WriteFlags (context, result, carry, overflow);
+    }
+    return true;
+}
+
+// This helper method tries to encapsulate the following pseudocode from the
+// ARM Architecture Reference Manual:
+//
+// APSR.N = result<31>;
+// APSR.Z = IsZeroBit(result);
+// APSR.C = carry;
+// APSR.V = overflow
+//
+// Default arguments can be specified for carry and overflow parameters, which means
+// not to update the respective flags.
+bool
+EmulateInstructionARM::WriteFlags (Context &context,
+                                   const uint32_t result,
+                                   const uint32_t carry,
+                                   const uint32_t overflow)
+{
+    m_new_inst_cpsr = m_opcode_cpsr;
+    SetBit32(m_new_inst_cpsr, CPSR_N_POS, Bit32(result, CPSR_N_POS));
+    SetBit32(m_new_inst_cpsr, CPSR_Z_POS, result == 0 ? 1 : 0);
+    if (carry != ~0u)
+        SetBit32(m_new_inst_cpsr, CPSR_C_POS, carry);
+    if (overflow != ~0u)
+        SetBit32(m_new_inst_cpsr, CPSR_V_POS, overflow);
+    if (m_new_inst_cpsr != m_opcode_cpsr)
+    {
+        if (!WriteRegisterUnsigned (context, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, m_new_inst_cpsr))
+            return false;
+    }
+    return true;
+}
+
+bool
+EmulateInstructionARM::EvaluateInstruction (uint32_t evaluate_options)
+{
+    // Advance the ITSTATE bits to their values for the next instruction.
+    if (m_opcode_mode == eModeThumb && m_it_session.InITBlock())
+        m_it_session.ITAdvance();
+
+    ARMOpcode *opcode_data = NULL;
+   
+    if (m_opcode_mode == eModeThumb)
+        opcode_data = GetThumbOpcodeForInstruction (m_opcode.GetOpcode32(), m_arm_isa);
+    else if (m_opcode_mode == eModeARM)
+        opcode_data = GetARMOpcodeForInstruction (m_opcode.GetOpcode32(), m_arm_isa);
+        
+    if (opcode_data == NULL)
+        return false;
+    
+    const bool auto_advance_pc = evaluate_options & eEmulateInstructionOptionAutoAdvancePC;
+    m_ignore_conditions = evaluate_options & eEmulateInstructionOptionIgnoreConditions;
+                 
+    bool success = false;
+    if (m_opcode_cpsr == 0 || m_ignore_conditions == false)
+    {
+        m_opcode_cpsr = ReadRegisterUnsigned (eRegisterKindDWARF, 
+                                                dwarf_cpsr, 
+                                                0,
+                                                &success);
+    }
+
+    // Only return false if we are unable to read the CPSR if we care about conditions
+    if (success == false && m_ignore_conditions == false)
+        return false;
+    
+    uint32_t orig_pc_value = 0;
+    if (auto_advance_pc)
+    {
+        orig_pc_value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc, 0, &success);
+        if (!success)
+            return false;
+    }
+    
+    // Call the Emulate... function.
+    success = (this->*opcode_data->callback) (m_opcode.GetOpcode32(), opcode_data->encoding);  
+    if (!success)
+        return false;
+        
+    if (auto_advance_pc)
+    {
+        uint32_t after_pc_value = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc, 0, &success);
+        if (!success)
+            return false;
+            
+        if (auto_advance_pc && (after_pc_value == orig_pc_value))
+        {
+            if (opcode_data->size == eSize32)
+                after_pc_value += 4;
+            else if (opcode_data->size == eSize16)
+                after_pc_value += 2;
+                
+            EmulateInstruction::Context context;
+            context.type = eContextAdvancePC;
+            context.SetNoArgs();
+            if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc, after_pc_value))
+                return false;
+                
+        }
+    }
+    return true;
+}
+
+bool
+EmulateInstructionARM::TestEmulation (Stream *out_stream, ArchSpec &arch, OptionValueDictionary *test_data)
+{
+    if (!test_data)
+    {
+        out_stream->Printf ("TestEmulation: Missing test data.\n");
+        return false;
+    }
+    
+    static ConstString opcode_key ("opcode");
+    static ConstString before_key ("before_state");
+    static ConstString after_key ("after_state");
+        
+    OptionValueSP value_sp = test_data->GetValueForKey (opcode_key);
+        
+    uint32_t test_opcode;
+    if ((value_sp.get() == NULL) || (value_sp->GetType() != OptionValue::eTypeUInt64))
+    {
+        out_stream->Printf ("TestEmulation: Error reading opcode from test file.\n");
+        return false;
+    }
+    test_opcode = value_sp->GetUInt64Value ();
+
+    if (arch.GetTriple().getArch() == llvm::Triple::arm)
+    {
+        m_opcode_mode = eModeARM;
+        m_opcode.SetOpcode32 (test_opcode);
+    }
+    else if (arch.GetTriple().getArch() == llvm::Triple::thumb)
+    {
+        m_opcode_mode = eModeThumb;
+        if (test_opcode < 0x10000)
+            m_opcode.SetOpcode16 (test_opcode);
+        else
+            m_opcode.SetOpcode32 (test_opcode);
+
+    }
+    else
+    {
+        out_stream->Printf ("TestEmulation:  Invalid arch.\n");
+        return false;
+    }
+
+    EmulationStateARM before_state;
+    EmulationStateARM after_state;
+    
+    value_sp = test_data->GetValueForKey (before_key);
+    if ((value_sp.get() == NULL) || (value_sp->GetType() != OptionValue::eTypeDictionary))
+    {
+        out_stream->Printf ("TestEmulation:  Failed to find 'before' state.\n");
+        return false;
+    }
+    
+    OptionValueDictionary *state_dictionary = value_sp->GetAsDictionary ();
+    if (!before_state.LoadStateFromDictionary (state_dictionary))
+    {
+        out_stream->Printf ("TestEmulation:  Failed loading 'before' state.\n");
+        return false;
+    }
+
+    value_sp = test_data->GetValueForKey (after_key);
+    if ((value_sp.get() == NULL) || (value_sp->GetType() != OptionValue::eTypeDictionary))
+    {
+        out_stream->Printf ("TestEmulation:  Failed to find 'after' state.\n");
+        return false;
+    }
+
+    state_dictionary = value_sp->GetAsDictionary ();
+    if (!after_state.LoadStateFromDictionary (state_dictionary))
+    {
+        out_stream->Printf ("TestEmulation: Failed loading 'after' state.\n");
+        return false;
+    }
+
+    SetBaton ((void *) &before_state);
+    SetCallbacks (&EmulationStateARM::ReadPseudoMemory,
+                  &EmulationStateARM::WritePseudoMemory,
+                  &EmulationStateARM::ReadPseudoRegister,
+                  &EmulationStateARM::WritePseudoRegister);
+                  
+    bool success = EvaluateInstruction (eEmulateInstructionOptionAutoAdvancePC);
+    if (!success)
+    {
+        out_stream->Printf ("TestEmulation:  EvaluateInstruction() failed.\n");
+        return false;
+    }
+        
+    success = before_state.CompareState (after_state);
+    if (!success)
+        out_stream->Printf ("TestEmulation:  'before' and 'after' states do not match.\n");
+        
+    return success;
+}
+//
+//                                           
+//const char *
+//EmulateInstructionARM::GetRegisterName (uint32_t reg_kind, uint32_t reg_num)
+//{
+//    if (reg_kind == eRegisterKindGeneric)
+//    {
+//        switch (reg_num)
+//        {
+//        case LLDB_REGNUM_GENERIC_PC:    return "pc";
+//        case LLDB_REGNUM_GENERIC_SP:    return "sp";
+//        case LLDB_REGNUM_GENERIC_FP:    return "fp";
+//        case LLDB_REGNUM_GENERIC_RA:    return "lr";
+//        case LLDB_REGNUM_GENERIC_FLAGS: return "cpsr";
+//        default: return NULL;
+//        }
+//    }
+//    else if (reg_kind == eRegisterKindDWARF)
+//    {
+//        return GetARMDWARFRegisterName (reg_num);
+//    }
+//    return NULL;
+//}
+//
+bool
+EmulateInstructionARM::CreateFunctionEntryUnwind (UnwindPlan &unwind_plan)
+{
+    unwind_plan.Clear();
+    unwind_plan.SetRegisterKind (eRegisterKindDWARF);
+
+    UnwindPlan::RowSP row(new UnwindPlan::Row);
+
+    // Our previous Call Frame Address is the stack pointer
+    row->SetCFARegister (dwarf_sp);
+    
+    // Our previous PC is in the LR
+    row->SetRegisterLocationToRegister(dwarf_pc, dwarf_lr, true);
+    unwind_plan.AppendRow (row);
+
+    // All other registers are the same.
+    
+    unwind_plan.SetSourceName ("EmulateInstructionARM");
+    unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
+    unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolYes);
+    return true;
+}
diff --git a/source/Plugins/Instruction/ARM/EmulateInstructionARM.h b/source/Plugins/Instruction/ARM/EmulateInstructionARM.h
new file mode 100644
index 000000000000..b926dc0deb4a
--- /dev/null
+++ b/source/Plugins/Instruction/ARM/EmulateInstructionARM.h
@@ -0,0 +1,990 @@
+//===-- lldb_EmulateInstructionARM.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_EmulateInstructionARM_h_
+#define lldb_EmulateInstructionARM_h_
+
+#include "lldb/Core/EmulateInstruction.h"
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/Error.h"
+#include "Plugins/Process/Utility/ARMDefines.h"
+
+namespace lldb_private {
+
+// ITSession - Keep track of the IT Block progression.
+class ITSession
+{
+public:
+    ITSession() : ITCounter(0), ITState(0) {}
+    ~ITSession() {}
+
+    // InitIT - Initializes ITCounter/ITState.
+    bool InitIT(uint32_t bits7_0);
+
+    // ITAdvance - Updates ITCounter/ITState as IT Block progresses.
+    void ITAdvance();
+
+    // InITBlock - Returns true if we're inside an IT Block.
+    bool InITBlock();
+
+    // LastInITBlock - Returns true if we're the last instruction inside an IT Block.
+    bool LastInITBlock();
+
+    // GetCond - Gets condition bits for the current thumb instruction.
+    uint32_t GetCond();
+
+private:
+    uint32_t ITCounter; // Possible values: 0, 1, 2, 3, 4.
+    uint32_t ITState;   // A2.5.2 Consists of IT[7:5] and IT[4:0] initially.
+};
+
+class EmulateInstructionARM : public EmulateInstruction
+{
+public: 
+    typedef enum
+    {
+        eEncodingA1,
+        eEncodingA2,
+        eEncodingA3,
+        eEncodingA4,
+        eEncodingA5,
+        eEncodingT1,
+        eEncodingT2,
+        eEncodingT3,
+        eEncodingT4,
+        eEncodingT5
+    } ARMEncoding;
+    
+
+    static void
+    Initialize ();
+    
+    static void
+    Terminate ();
+
+    static lldb_private::ConstString
+    GetPluginNameStatic ();
+    
+    static const char *
+    GetPluginDescriptionStatic ();
+    
+    static lldb_private::EmulateInstruction *
+    CreateInstance (const lldb_private::ArchSpec &arch, 
+                    InstructionType inst_type);
+    
+    static bool
+    SupportsEmulatingIntructionsOfTypeStatic (InstructionType inst_type)
+    {
+        switch (inst_type)
+        {
+            case eInstructionTypeAny:
+            case eInstructionTypePrologueEpilogue:
+            case eInstructionTypePCModifying:
+                return true;
+                
+            case eInstructionTypeAll:
+                return false;
+        }
+        return false;
+    }
+
+    virtual lldb_private::ConstString
+    GetPluginName()
+    {
+        return GetPluginNameStatic();
+    }
+
+    virtual uint32_t
+    GetPluginVersion()
+    {
+        return 1;
+    }
+
+    bool
+    SetTargetTriple (const ArchSpec &arch);
+    
+    enum Mode
+    {
+        eModeInvalid = -1,
+        eModeARM,
+        eModeThumb
+    };
+    
+    EmulateInstructionARM (const ArchSpec &arch) :
+        EmulateInstruction (arch),
+        m_arm_isa (0),
+        m_opcode_mode (eModeInvalid),
+        m_opcode_cpsr (0),
+        m_it_session (),
+        m_ignore_conditions (false)
+    {
+        SetArchitecture (arch);
+    }
+
+//    EmulateInstructionARM (const ArchSpec &arch,
+//                           bool ignore_conditions,
+//                           void *baton,
+//                           ReadMemory read_mem_callback,
+//                           WriteMemory write_mem_callback,
+//                           ReadRegister read_reg_callback,
+//                           WriteRegister write_reg_callback) :
+//        EmulateInstruction (arch,
+//                            ignore_conditions,
+//                            baton,
+//                            read_mem_callback,
+//                            write_mem_callback,
+//                            read_reg_callback,
+//                            write_reg_callback),
+//        m_arm_isa (0),
+//        m_opcode_mode (eModeInvalid),
+//        m_opcode_cpsr (0),
+//        m_it_session ()
+//    {
+//    }
+    
+    virtual bool
+    SupportsEmulatingIntructionsOfType (InstructionType inst_type)
+    {
+        return SupportsEmulatingIntructionsOfTypeStatic (inst_type);
+    }
+
+    virtual bool
+    SetArchitecture (const ArchSpec &arch);
+
+    virtual bool 
+    ReadInstruction ();
+    
+    virtual bool
+    SetInstruction (const Opcode &insn_opcode, const Address &inst_addr, Target *target);
+
+    virtual bool
+    EvaluateInstruction (uint32_t evaluate_options);
+    
+    virtual bool
+    TestEmulation (Stream *out_stream, ArchSpec &arch, OptionValueDictionary *test_data);
+
+    virtual bool
+    GetRegisterInfo (uint32_t reg_kind, uint32_t reg_num, RegisterInfo &reg_info);
+    
+
+    virtual bool
+    CreateFunctionEntryUnwind (UnwindPlan &unwind_plan);
+
+    uint32_t
+    ArchVersion();
+
+    bool
+    ConditionPassed (const uint32_t opcode, 
+                     bool *is_conditional = NULL);  // Filled in with true if the opcode is a conditional opcode
+                                                    // Filled in with false if the opcode is always executed
+
+    uint32_t
+    CurrentCond (const uint32_t opcode);
+
+    // InITBlock - Returns true if we're in Thumb mode and inside an IT Block.
+    bool InITBlock();
+
+    // LastInITBlock - Returns true if we're in Thumb mode and the last instruction inside an IT Block.
+    bool LastInITBlock();
+
+    bool 
+    BadMode (uint32_t mode);
+    
+    bool
+    CurrentModeIsPrivileged ();
+    
+    void
+    CPSRWriteByInstr (uint32_t value, uint32_t bytemask, bool affect_execstate);
+    
+    bool
+    BranchWritePC(const Context &context, uint32_t addr);
+
+    bool
+    BXWritePC(Context &context, uint32_t addr);
+
+    bool
+    LoadWritePC(Context &context, uint32_t addr);
+
+    bool
+    ALUWritePC(Context &context, uint32_t addr);
+
+    Mode
+    CurrentInstrSet();
+
+    bool
+    SelectInstrSet(Mode arm_or_thumb);
+
+    bool
+    WriteBits32Unknown (int n);
+
+    bool
+    WriteBits32UnknownToMemory (lldb::addr_t address);
+    
+    bool
+    UnalignedSupport();
+
+    typedef struct
+    {
+        uint32_t result;
+        uint8_t carry_out;
+        uint8_t overflow;
+    } AddWithCarryResult;
+
+    AddWithCarryResult
+    AddWithCarry(uint32_t x, uint32_t y, uint8_t carry_in);
+
+    // Helper method to read the content of an ARM core register.
+    uint32_t
+    ReadCoreReg (uint32_t regnum, bool *success);
+
+    // See A8.6.96 MOV (immediate) Operation.
+    // Default arguments are specified for carry and overflow parameters, which means
+    // not to update the respective flags even if setflags is true.
+    bool
+    WriteCoreRegOptionalFlags (Context &context,
+                               const uint32_t result,
+                               const uint32_t Rd,
+                               bool setflags,
+                               const uint32_t carry = ~0u,
+                               const uint32_t overflow = ~0u);
+
+    bool
+    WriteCoreReg (Context &context,
+                  const uint32_t result,
+                  const uint32_t Rd)
+    {
+        // Don't set the flags.
+        return WriteCoreRegOptionalFlags(context, result, Rd, false);
+    }
+
+    // See A8.6.35 CMP (immediate) Operation.
+    // Default arguments are specified for carry and overflow parameters, which means
+    // not to update the respective flags.
+    bool
+    WriteFlags (Context &context,
+                const uint32_t result,
+                const uint32_t carry = ~0u,
+                const uint32_t overflow = ~0u);
+
+    inline uint64_t
+    MemARead (EmulateInstruction::Context &context, 
+              lldb::addr_t address, 
+              uint32_t size, 
+              uint64_t fail_value, 
+              bool *success_ptr)
+    {
+        // This is a stub function corresponding to "MemA[]" in the ARM manual pseudocode, for 
+        // aligned reads from memory.  Since we are not trying to write a full hardware simulator, and since
+        // we are running in User mode (rather than Kernel mode) and therefore won't have access to many of the
+        // system registers we would need in order to fully implement this function, we will just call
+        // ReadMemoryUnsigned from here.  In the future, if we decide we do need to do more faithful emulation of
+        // the hardware, we can update this function appropriately.
+        
+        return ReadMemoryUnsigned (context, address, size, fail_value, success_ptr);
+    }
+    
+    inline bool
+    MemAWrite (EmulateInstruction::Context &context,
+               lldb::addr_t address,
+               uint64_t data_val,
+               uint32_t size)
+    
+    {
+        // This is a stub function corresponding to "MemA[]" in the ARM manual pseudocode, for 
+        // aligned writes to memory.  Since we are not trying to write a full hardware simulator, and since
+        // we are running in User mode (rather than Kernel mode) and therefore won't have access to many of the
+        // system registers we would need in order to fully implement this function, we will just call
+        // WriteMemoryUnsigned from here.  In the future, if we decide we do need to do more faithful emulation of
+        // the hardware, we can update this function appropriately.
+        
+        return WriteMemoryUnsigned (context, address, data_val, size);
+    }
+    
+    
+    inline uint64_t
+    MemURead (EmulateInstruction::Context &context,
+              lldb::addr_t address,
+              uint32_t size,
+              uint64_t fail_value,
+              bool *success_ptr)
+    {
+        // This is a stub function corresponding to "MemU[]" in the ARM manual pseudocode, for 
+        // unaligned reads from memory.  Since we are not trying to write a full hardware simulator, and since
+        // we are running in User mode (rather than Kernel mode) and therefore won't have access to many of the
+        // system registers we would need in order to fully implement this function, we will just call
+        // ReadMemoryUnsigned from here.  In the future, if we decide we do need to do more faithful emulation of
+        // the hardware, we can update this function appropriately.
+        
+        return ReadMemoryUnsigned (context, address, size, fail_value, success_ptr);
+    }
+    
+    inline bool
+    MemUWrite (EmulateInstruction::Context &context, 
+               lldb::addr_t address,
+               uint64_t data_val,
+               uint32_t size)
+    
+    {
+        // This is a stub function corresponding to "MemU[]" in the ARM manual pseudocode, for 
+        // unaligned writes to memory.  Since we are not trying to write a full hardware simulator, and since
+        // we are running in User mode (rather than Kernel mode) and therefore won't have access to many of the
+        // system registers we would need in order to fully implement this function, we will just call
+        // WriteMemoryUnsigned from here.  In the future, if we decide we do need to do more faithful emulation of
+        // the hardware, we can update this function appropriately.
+        
+        return WriteMemoryUnsigned (context, address, data_val, size);
+    }
+
+protected:
+
+    // Typedef for the callback function used during the emulation.
+    // Pass along (ARMEncoding)encoding as the callback data.
+    typedef enum
+    {
+        eSize16,
+        eSize32
+    } ARMInstrSize;
+
+    typedef struct
+    {
+        uint32_t mask;
+        uint32_t value;
+        uint32_t variants;
+        EmulateInstructionARM::ARMEncoding encoding;
+        uint32_t vfp_variants;
+        ARMInstrSize size;
+        bool (EmulateInstructionARM::*callback) (const uint32_t opcode, const EmulateInstructionARM::ARMEncoding encoding);
+        const char *name;
+    }  ARMOpcode;
+    
+    uint32_t
+    GetFramePointerRegisterNumber () const;
+
+    uint32_t
+    GetFramePointerDWARFRegisterNumber () const;
+
+    static ARMOpcode*
+    GetARMOpcodeForInstruction (const uint32_t opcode, uint32_t isa_mask);
+
+    static ARMOpcode*
+    GetThumbOpcodeForInstruction (const uint32_t opcode, uint32_t isa_mask);
+
+    // A8.6.123 PUSH
+    bool
+    EmulatePUSH (const uint32_t opcode, const ARMEncoding encoding);
+    
+    // A8.6.122 POP
+    bool
+    EmulatePOP (const uint32_t opcode, const ARMEncoding encoding);
+    
+    // A8.6.8 ADD (SP plus immediate)
+    bool
+    EmulateADDRdSPImm (const uint32_t opcode, const ARMEncoding encoding);
+
+    // A8.6.97 MOV (register) -- Rd == r7|ip and Rm == sp
+    bool
+    EmulateMOVRdSP (const uint32_t opcode, const ARMEncoding encoding);
+
+    // A8.6.97 MOV (register) -- move from r8-r15 to r0-r7
+    bool
+    EmulateMOVLowHigh (const uint32_t opcode, const ARMEncoding encoding);
+
+    // A8.6.59 LDR (literal)
+    bool
+    EmulateLDRRtPCRelative (const uint32_t opcode, const ARMEncoding encoding);
+
+    // A8.6.8 ADD (SP plus immediate)
+    bool
+    EmulateADDSPImm (const uint32_t opcode, const ARMEncoding encoding);
+
+    // A8.6.9 ADD (SP plus register)
+    bool
+    EmulateADDSPRm (const uint32_t opcode, const ARMEncoding encoding);
+
+    // A8.6.23 BL, BLX (immediate)
+    bool
+    EmulateBLXImmediate (const uint32_t opcode, const ARMEncoding encoding);
+
+    // A8.6.24 BLX (register)
+    bool
+    EmulateBLXRm (const uint32_t opcode, const ARMEncoding encoding);
+
+    // A8.6.25 BX
+    bool
+    EmulateBXRm (const uint32_t opcode, const ARMEncoding encoding);
+
+    // A8.6.26 BXJ
+    bool
+    EmulateBXJRm (const uint32_t opcode, const ARMEncoding encoding);
+
+    // A8.6.212 SUB (immediate, ARM) -- Rd == r7 and Rm == ip
+    bool
+    EmulateSUBR7IPImm (const uint32_t opcode, const ARMEncoding encoding);
+
+    // A8.6.215 SUB (SP minus immediate) -- Rd == ip
+    bool
+    EmulateSUBIPSPImm (const uint32_t opcode, const ARMEncoding encoding);
+
+    // A8.6.215 SUB (SP minus immediate)
+    bool
+    EmulateSUBSPImm (const uint32_t opcode, const ARMEncoding encoding);
+    
+    // A8.6.216 SUB (SP minus register)
+    bool
+    EmulateSUBSPReg (const uint32_t opcode, const ARMEncoding encoding);
+
+    // A8.6.194 STR (immediate, ARM) -- Rn == sp
+    bool
+    EmulateSTRRtSP (const uint32_t opcode, const ARMEncoding encoding);
+
+    // A8.6.355 VPUSH
+    bool
+    EmulateVPUSH (const uint32_t opcode, const ARMEncoding encoding);
+
+    // A8.6.354 VPOP
+    bool
+    EmulateVPOP (const uint32_t opcode, const ARMEncoding encoding);
+
+    // A8.6.218 SVC (previously SWI)
+    bool
+    EmulateSVC (const uint32_t opcode, const ARMEncoding encoding);
+
+    // A8.6.50 IT
+    bool
+    EmulateIT (const uint32_t opcode, const ARMEncoding encoding);
+
+    // NOP
+    bool
+    EmulateNop (const uint32_t opcode, const ARMEncoding encoding);
+
+    // A8.6.16 B
+    bool
+    EmulateB (const uint32_t opcode, const ARMEncoding encoding);
+    
+    // A8.6.27 CBNZ, CBZ
+    bool
+    EmulateCB (const uint32_t opcode, const ARMEncoding encoding);
+
+    // A8.6.226 TBB, TBH
+    bool
+    EmulateTB (const uint32_t opcode, const ARMEncoding encoding);
+
+    // A8.6.4 ADD (immediate, Thumb)
+    bool
+    EmulateADDImmThumb (const uint32_t opcode, const ARMEncoding encoding);
+
+    // A8.6.5 ADD (immediate, ARM)
+    bool
+    EmulateADDImmARM (const uint32_t opcode, const ARMEncoding encoding);
+    
+    // A8.6.6 ADD (register)
+    bool
+    EmulateADDReg (const uint32_t opcode, const ARMEncoding encoding);
+    
+    // A8.6.7 ADD (register-shifted register)
+    bool
+    EmulateADDRegShift (const uint32_t opcode, const ARMEncoding encoding);
+
+    // A8.6.97 MOV (register)
+    bool
+    EmulateMOVRdRm (const uint32_t opcode, const ARMEncoding encoding);
+
+    // A8.6.96 MOV (immediate)
+    bool
+    EmulateMOVRdImm (const uint32_t opcode, const ARMEncoding encoding);
+
+    // A8.6.35 CMP (immediate)
+    bool
+    EmulateCMPImm (const uint32_t opcode, const ARMEncoding encoding);
+
+    // A8.6.36 CMP (register)
+    bool
+    EmulateCMPReg (const uint32_t opcode, const ARMEncoding encoding);
+
+    // A8.6.14 ASR (immediate)
+    bool
+    EmulateASRImm (const uint32_t opcode, const ARMEncoding encoding);
+
+    // A8.6.15 ASR (register)
+    bool
+    EmulateASRReg (const uint32_t opcode, const ARMEncoding encoding);
+
+    // A8.6.88 LSL (immediate)
+    bool
+    EmulateLSLImm (const uint32_t opcode, const ARMEncoding encoding);
+
+    // A8.6.89 LSL (register)
+    bool
+    EmulateLSLReg (const uint32_t opcode, const ARMEncoding encoding);
+
+    // A8.6.90 LSR (immediate)
+    bool
+    EmulateLSRImm (const uint32_t opcode, const ARMEncoding encoding);
+
+    // A8.6.91 LSR (register)
+    bool
+    EmulateLSRReg (const uint32_t opcode, const ARMEncoding encoding);
+
+    // A8.6.139 ROR (immediate)
+    bool
+    EmulateRORImm (const uint32_t opcode, const ARMEncoding encoding);
+
+    // A8.6.140 ROR (register)
+    bool
+    EmulateRORReg (const uint32_t opcode, const ARMEncoding encoding);
+
+    // A8.6.141 RRX
+    bool
+    EmulateRRX (const uint32_t opcode, const ARMEncoding encoding);
+
+    // Helper method for ASR, LSL, LSR, ROR (immediate), and RRX
+    bool
+    EmulateShiftImm (const uint32_t opcode, const ARMEncoding encoding, ARM_ShifterType shift_type);
+
+    // Helper method for ASR, LSL, LSR, and ROR (register)
+    bool
+    EmulateShiftReg (const uint32_t opcode, const ARMEncoding encoding, ARM_ShifterType shift_type);
+
+    // LOAD FUNCTIONS
+    
+    // A8.6.53 LDM/LDMIA/LDMFD
+    bool
+    EmulateLDM (const uint32_t opcode, const ARMEncoding encoding);
+    
+    // A8.6.54 LDMDA/LDMFA
+    bool
+    EmulateLDMDA (const uint32_t opcode, const ARMEncoding encoding);
+    
+    // A8.6.55 LDMDB/LDMEA
+    bool 
+    EmulateLDMDB (const uint32_t opcode, const ARMEncoding encoding);
+    
+    // A8.6.56 LDMIB/LDMED
+    bool
+    EmulateLDMIB (const uint32_t opcode, const ARMEncoding encoding);
+
+    // A8.6.57 LDR (immediate, Thumb) -- Encoding T1
+    bool
+    EmulateLDRRtRnImm (const uint32_t opcode, const ARMEncoding encoding);
+
+    // A8.6.58 LDR (immediate, ARM) - Encoding A1
+    bool
+    EmulateLDRImmediateARM (const uint32_t opcode, const ARMEncoding encoding);
+    
+    // A8.6.59 LDR (literal)
+    bool
+    EmulateLDRLiteral (const uint32_t, const ARMEncoding encoding);
+    
+    // A8.6.60 LDR (register) - Encoding T1, T2, A1
+    bool
+    EmulateLDRRegister (const uint32_t opcode, const ARMEncoding encoding);
+    
+    // A8.6.61 LDRB (immediate, Thumb) - Encoding T1, T2, T3
+    bool
+    EmulateLDRBImmediate (const uint32_t opcode, const ARMEncoding encoding);
+    
+    // A8.6.62 LDRB (immediate, ARM)
+    bool
+    EmulateLDRBImmediateARM (const uint32_t opcode, const ARMEncoding encoding);
+                             
+    // A8.6.63 LDRB (literal) - Encoding T1, A1
+    bool
+    EmulateLDRBLiteral (const uint32_t opcode, const ARMEncoding encoding);
+                             
+    // A8.6.64 LDRB (register) - Encoding T1, T2, A1
+    bool
+    EmulateLDRBRegister (const uint32_t opcode, const ARMEncoding encoding);
+                             
+    // A8.6.65 LDRBT
+    bool
+    EmulateLDRBT (const uint32_t opcode, const ARMEncoding encoding);
+        
+    // A8.6.66 LDRD (immediate)
+    bool
+    EmulateLDRDImmediate (const uint32_t opcode, const ARMEncoding encoding);
+                             
+    // A8.6.67
+    bool
+    EmulateLDRDLiteral (const uint32_t opcode, const ARMEncoding encoding);
+                             
+    // A8.6.68 LDRD (register)
+    bool
+    EmulateLDRDRegister (const uint32_t opcode, const ARMEncoding encoding);
+                             
+    // A8.6.69 LDREX
+    bool
+    EmulateLDREX (const uint32_t opcode, const ARMEncoding encoding);
+                             
+    // A8.6.70 LDREXB
+    bool
+    EmulateLDREXB (const uint32_t opcode, const ARMEncoding encoding);
+                             
+    // A8.6.71 LDREXD
+    bool
+    EmulateLDREXD (const uint32_t opcode, const ARMEncoding encoding);
+                             
+    // A8.6.72 LDREXH
+    bool
+    EmulateLDREXH (const uint32_t opcode, const ARMEncoding encoding);
+                                                 
+    // A8.6.73 LDRH (immediate, Thumb) - Encoding T1, T2, T3
+    bool
+    EmulateLDRHImmediate (const uint32_t opcode, const ARMEncoding encoding);
+                             
+    // A8.6.74 LDRS (immediate, ARM)
+    bool
+    EmulateLDRHImmediateARM (const uint32_t opcode, const ARMEncoding encoding);
+                             
+    // A8.6.75 LDRH (literal) - Encoding T1, A1
+    bool
+    EmulateLDRHLiteral (const uint32_t opcode, const ARMEncoding encoding);
+                             
+    // A8.6.76 LDRH (register) - Encoding T1, T2, A1
+    bool
+    EmulateLDRHRegister (const uint32_t opcode, const ARMEncoding encoding);
+                             
+    // A8.6.77 LDRHT
+    bool
+    EmulateLDRHT (const uint32_t opcode, const ARMEncoding encoding);
+                             
+    // A8.6.78 LDRSB (immediate) - Encoding T1, T2, A1
+    bool
+    EmulateLDRSBImmediate (const uint32_t opcode, const ARMEncoding encoding);
+                             
+    // A8.6.79 LDRSB (literal) - Encoding T1, A1
+    bool
+    EmulateLDRSBLiteral (const uint32_t opcode, const ARMEncoding encoding);
+                             
+    // A8.6.80 LDRSB (register) - Encoding T1, T2, A1
+    bool
+    EmulateLDRSBRegister (const uint32_t opcode, const ARMEncoding encoding);
+                             
+    // A8.6.81 LDRSBT
+    bool
+    EmulateLDRSBT (const uint32_t opcode, const ARMEncoding encoding);
+                             
+    // A8.6.82 LDRSH (immediate) - Encoding T1, T2, A1
+    bool
+    EmulateLDRSHImmediate (const uint32_t opcode, const ARMEncoding encoding);
+                             
+    // A8.6.83 LDRSH (literal) - Encoding T1, A1
+    bool
+    EmulateLDRSHLiteral (const uint32_t opcode, const ARMEncoding encoding);
+
+    // A8.6.84 LDRSH (register) - Encoding T1, T2, A1
+    bool
+    EmulateLDRSHRegister (const uint32_t opcode, const ARMEncoding encoding);
+                             
+    // A8.6.85 LDRSHT
+    bool
+    EmulateLDRSHT (const uint32_t opcode, const ARMEncoding encoding);
+                             
+    // A8.6.86
+    bool
+    EmulateLDRT (const uint32_t opcode, const ARMEncoding encoding);
+                             
+
+    // STORE FUNCTIONS
+                             
+    // A8.6.189 STM/STMIA/STMEA
+    bool
+    EmulateSTM (const uint32_t opcode, const ARMEncoding encoding);
+    
+    // A8.6.190 STMDA/STMED
+    bool
+    EmulateSTMDA (const uint32_t opcode, const ARMEncoding encoding);
+    
+    // A8.6.191 STMDB/STMFD
+    bool
+    EmulateSTMDB (const uint32_t opcode, const ARMEncoding encoding);
+    
+    // A8.6.192 STMIB/STMFA
+    bool
+    EmulateSTMIB (const uint32_t opcode, const ARMEncoding encoding);
+    
+    // A8.6.193 STR (immediate, Thumb)
+    bool
+    EmulateSTRThumb(const uint32_t opcode, const ARMEncoding encoding);
+                             
+    // A8.6.194 STR (immediate, ARM)
+    bool
+    EmulateSTRImmARM (const uint32_t opcode, const ARMEncoding encoding);
+    
+    // A8.6.195 STR (register)
+    bool
+    EmulateSTRRegister (const uint32_t opcode, const ARMEncoding encoding);
+    
+    // A8.6.196 STRB (immediate, Thumb)
+    bool
+    EmulateSTRBThumb (const uint32_t opcode, const ARMEncoding encoding);
+                             
+    // A8.6.197 STRB (immediate, ARM)
+    bool
+    EmulateSTRBImmARM (const uint32_t opcode, const ARMEncoding encoding);
+            
+    // A8.6.198 STRB (register)
+    bool
+    EmulateSTRBReg (const uint32_t opcode, const ARMEncoding encoding);
+                             
+    // A8.6.199 STRBT
+    bool
+    EmulateSTRBT (const uint32_t opcode, const ARMEncoding encoding);
+                            
+    // A8.6.200 STRD (immediate)
+    bool
+    EmulateSTRDImm (const uint32_t opcode, const ARMEncoding encoding);
+                             
+    // A8.6.201 STRD (register)
+    bool
+    EmulateSTRDReg (const uint32_t opcode, const ARMEncoding encoding);
+                             
+    // A8.6.202 STREX
+    bool
+    EmulateSTREX (const uint32_t opcode, const ARMEncoding encoding);
+                    
+    // A8.6.203 STREXB
+    bool
+    EmulateSTREXB (const uint32_t opcode, const ARMEncoding encoding);
+                             
+    // A8.6.204 STREXD
+    bool
+    EmulateSTREXD (const uint32_t opcode, const ARMEncoding encoding);
+                            
+    // A8.6.205 STREXH
+    bool
+    EmulateSTREXH (const uint32_t opcode, const ARMEncoding encoding);
+                             
+    // A8.6.206 STRH (immediate, Thumb)
+    bool
+    EmulateSTRHImmThumb (const uint32_t opcode, const ARMEncoding encoding);
+                             
+    // A8.6.207 STRH (immediate, ARM)
+    bool
+    EmulateSTRHImmARM (const uint32_t opcode, const ARMEncoding encoding);
+                             
+    // A8.6.208 STRH (register)
+    bool
+    EmulateSTRHRegister (const uint32_t opcode, const ARMEncoding encoding);
+                             
+    // A8.6.209 STRHT
+    bool
+    EmulateSTRHT (const uint32_t opcode, const ARMEncoding encoding);
+                             
+    // A8.6.210 STRT
+    bool
+    EmulateSTRT (const uint32_t opcode, const ARMEncoding encoding);
+    
+    // A8.6.1 ADC (immediate)
+    bool
+    EmulateADCImm (const uint32_t opcode, const ARMEncoding encoding);
+    
+    // A8.6.2 ADC (Register)
+    bool
+    EmulateADCReg (const uint32_t opcode, const ARMEncoding encoding);
+    
+    // A8.6.10 ADR
+    bool
+    EmulateADR (const uint32_t opcode, const ARMEncoding encoding);
+    
+    // A8.6.11 AND (immediate)
+    bool
+    EmulateANDImm (const uint32_t opcode, const ARMEncoding encoding);
+    
+    // A8.6.12 AND (register)
+    bool
+    EmulateANDReg (const uint32_t opcode, const ARMEncoding encoding);
+    
+    // A8.6.19 BIC (immediate)
+    bool
+    EmulateBICImm (const uint32_t opcode, const ARMEncoding encoding);
+    
+    // A8.6.20 BIC (register)
+    bool
+    EmulateBICReg (const uint32_t opcode, const ARMEncoding encoding);
+    
+    // A8.6.26 BXJ
+    bool
+    EmulateBXJ (const uint32_t opcode, const ARMEncoding encoding);
+    
+    // A8.6.32 CMN (immediate)
+    bool
+    EmulateCMNImm (const uint32_t opcode, const ARMEncoding encoding);
+    
+    // A8.6.33 CMN (register)
+    bool
+    EmulateCMNReg (const uint32_t opcode, const ARMEncoding encoding);
+    
+    // A8.6.44 EOR (immediate)
+    bool
+    EmulateEORImm (const uint32_t opcode, const ARMEncoding encoding);
+    
+    // A8.6.45 EOR (register)
+    bool
+    EmulateEORReg (const uint32_t opcode, const ARMEncoding encoding);
+    
+    // A8.6.105 MUL
+    bool
+    EmulateMUL (const uint32_t opcode, const ARMEncoding encoding);
+    
+    // A8.6.106 MVN (immediate)
+    bool
+    EmulateMVNImm (const uint32_t opcode, const ARMEncoding encoding);
+    
+    // A8.6.107 MVN (register)
+    bool
+    EmulateMVNReg (const uint32_t opcode, const ARMEncoding encoding);
+    
+    // A8.6.113 ORR (immediate)
+    bool
+    EmulateORRImm (const uint32_t opcode, const ARMEncoding encoding);
+
+    // A8.6.114 ORR (register)
+    bool
+    EmulateORRReg (const uint32_t opcode, const ARMEncoding encoding);
+
+    // A8.6.117 PLD (immediate, literal) - Encoding T1, T2, T3, A1
+    bool
+    EmulatePLDImmediate (const uint32_t opcode, const ARMEncoding encoding);
+    
+    // A8.6.119 PLI (immediate,literal) - Encoding T3, A1
+    bool
+    EmulatePLIImmediate (const uint32_t opcode, const ARMEncoding encoding);
+    
+    // A8.6.120 PLI (register) - Encoding T1, A1
+    bool
+    EmulatePLIRegister (const uint32_t opcode, const ARMEncoding encoding);
+    
+    // A8.6.141 RSB (immediate)
+    bool
+    EmulateRSBImm (const uint32_t opcode, const ARMEncoding encoding);
+    
+    // A8.6.142 RSB (register)
+    bool
+    EmulateRSBReg (const uint32_t opcode, const ARMEncoding encoding);
+    
+    // A8.6.144 RSC (immediate)
+    bool
+    EmulateRSCImm (const uint32_t opcode, const ARMEncoding encoding);
+    
+    // A8.6.145 RSC (register)
+    bool
+    EmulateRSCReg (const uint32_t opcode, const ARMEncoding encoding);
+    
+    // A8.6.150 SBC (immediate)
+    bool
+    EmulateSBCImm (const uint32_t opcode, const ARMEncoding encoding);
+    
+    // A8.6.151 SBC (register)
+    bool
+    EmulateSBCReg (const uint32_t opcode, const ARMEncoding encoding);
+    
+    // A8.6.211 SUB (immediate, Thumb)
+    bool
+    EmulateSUBImmThumb (const uint32_t opcode, const ARMEncoding encoding);
+    
+    // A8.6.212 SUB (immediate, ARM)
+    bool
+    EmulateSUBImmARM (const uint32_t opcode, const ARMEncoding encoding);
+                             
+    // A8.6.213 SUB (register)
+    bool
+    EmulateSUBReg (const uint32_t opcode, const ARMEncoding encoding);
+                             
+    // A8.6.214 SUB (register-shifted register)
+    bool
+    EmulateSUBRegShift (const uint32_t opcode, const ARMEncoding encoding);
+    
+    // A8.6.222 SXTB  - Encoding T1
+    bool
+    EmulateSXTB (const uint32_t opcode, const ARMEncoding encoding);
+    
+    // A8.6.224 SXTH  - EncodingT1
+    bool
+    EmulateSXTH (const uint32_t opcode, const ARMEncoding encoding);
+    
+    // A8.6.227 TEQ (immediate) - Encoding A1
+    bool
+    EmulateTEQImm (const uint32_t opcode, const ARMEncoding encoding);
+    
+    // A8.6.228 TEQ (register)  - Encoding A1
+    bool
+    EmulateTEQReg (const uint32_t opcode, const ARMEncoding encoding);
+    
+    // A8.6.230 TST (immediate) - Encoding A1
+    bool
+    EmulateTSTImm (const uint32_t opcode, const ARMEncoding encoding);
+    
+    // A8.6.231 TST (register)  - Encoding T1, A1
+    bool
+    EmulateTSTReg (const uint32_t opcode, const ARMEncoding encoding);
+    
+    // A8.6.262 UXTB  - Encoding T1
+    bool
+    EmulateUXTB (const uint32_t opcode, const ARMEncoding encoding);
+    
+    // A8.6.264 UXTH  - Encoding T1
+    bool
+    EmulateUXTH (const uint32_t opcode, const ARMEncoding encoding);
+    
+    // B6.1.8  RFE
+    bool
+    EmulateRFE (const uint32_t opcode, const ARMEncoding encoding);
+    
+    // A8.6.319 VLDM
+    bool
+    EmulateVLDM (const uint32_t opcode, const ARMEncoding encoding);
+    
+    // A8.6.399 VSTM
+    bool
+    EmulateVSTM (const uint32_t opcode, const ARMEncoding encoding);
+    
+    // A8.6.307 VLD1 (multiple single elements)
+    bool
+    EmulateVLD1Multiple (const uint32_t opcode, const ARMEncoding encoding);
+    
+    // A8.6.308 VLD1 (single element to one lane)
+    bool
+    EmulateVLD1Single (const uint32_t opcode, const ARMEncoding encoding);
+    
+    // A8.6.309 VLD1 (single element to all lanes)
+    bool
+    EmulateVLD1SingleAll (const uint32_t opcode, const ARMEncoding encoding);
+    
+    // A8.6.391 VST1 (multiple single elements)
+    bool
+    EmulateVST1Multiple (const uint32_t opcode, const ARMEncoding encoding);
+    
+    // A8.6.392 VST1 (single element from one lane)
+    bool
+    EmulateVST1Single (const uint32_t opcode, const ARMEncoding encoding);
+    
+    // A8.6.317 VLDR
+    bool
+    EmulateVLDR (const uint32_t opcode, const ARMEncoding encoding);
+    
+    
+    // A8.6.400 VSTR
+    bool
+    EmulateVSTR (const uint32_t opcode, const ARMEncoding encoding);
+    
+    // B6.2.13 SUBS PC, LR and related instructions
+    bool
+    EmulateSUBSPcLrEtc (const uint32_t opcode, const ARMEncoding encoding);
+    
+    uint32_t m_arm_isa;
+    Mode m_opcode_mode;
+    uint32_t m_opcode_cpsr;
+    uint32_t m_new_inst_cpsr; // This can get updated by the opcode.
+    ITSession m_it_session;
+    bool m_ignore_conditions;
+};
+
+}   // namespace lldb_private
+
+#endif  // lldb_EmulateInstructionARM_h_
diff --git a/source/Plugins/Instruction/ARM/EmulationStateARM.cpp b/source/Plugins/Instruction/ARM/EmulationStateARM.cpp
new file mode 100644
index 000000000000..bad4118971e0
--- /dev/null
+++ b/source/Plugins/Instruction/ARM/EmulationStateARM.cpp
@@ -0,0 +1,406 @@
+//===-- EmulationStateARM.cpp -----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "EmulationStateARM.h"
+
+#include "lldb/Core/RegisterValue.h"
+#include "lldb/Core/Scalar.h"
+#include "lldb/Interpreter/OptionValueArray.h"
+#include "lldb/Interpreter/OptionValueDictionary.h"
+#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/RegisterContext.h"
+
+#include "Utility/ARM_DWARF_Registers.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+EmulationStateARM::EmulationStateARM () :
+    m_gpr (),
+    m_vfp_regs (),
+    m_memory ()
+{
+    ClearPseudoRegisters();
+}
+
+EmulationStateARM::~EmulationStateARM ()
+{
+}
+
+bool
+EmulationStateARM::LoadPseudoRegistersFromFrame (StackFrame &frame)
+{
+    RegisterContext *reg_ctx = frame.GetRegisterContext().get();
+    bool success = true;
+    uint32_t reg_num;
+    
+    for (int i = dwarf_r0; i < dwarf_r0 + 17; ++i)
+    {
+        reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindDWARF, i);
+        const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex (reg_num);
+        RegisterValue reg_value;
+        if (reg_ctx->ReadRegister (reg_info, reg_value))
+        {
+            m_gpr[i - dwarf_r0] = reg_value.GetAsUInt32();
+        }
+        else
+            success = false;
+    }
+    
+    for (int i = dwarf_d0; i < dwarf_d0 + 32; ++i)
+    {
+        reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindDWARF, i);
+        RegisterValue reg_value;
+        const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex (reg_num);
+
+        if (reg_ctx->ReadRegister (reg_info, reg_value))
+        {
+            uint32_t idx = i - dwarf_d0;
+            if (i < 16)
+                m_vfp_regs.sd_regs[idx].d_reg = reg_value.GetAsUInt64();
+            else
+                m_vfp_regs.d_regs[idx - 16] = reg_value.GetAsUInt64();
+        }
+        else
+            success = false;
+    }
+    
+    return success;
+}
+    
+bool
+EmulationStateARM::StorePseudoRegisterValue (uint32_t reg_num, uint64_t value)
+{
+    if ((dwarf_r0 <= reg_num) && (reg_num <= dwarf_cpsr))
+        m_gpr[reg_num  - dwarf_r0] = (uint32_t) value;
+    else if ((dwarf_s0 <= reg_num) && (reg_num <= dwarf_s31))
+    {
+        uint32_t idx = reg_num - dwarf_s0;
+        m_vfp_regs.sd_regs[idx / 2].s_reg[idx % 2] = (uint32_t) value;
+    }
+    else if ((dwarf_d0 <= reg_num) && (reg_num <= dwarf_d31))
+    {
+        if ((reg_num - dwarf_d0) < 16)
+        {
+            m_vfp_regs.sd_regs[reg_num - dwarf_d0].d_reg = value;
+        }
+        else
+            m_vfp_regs.d_regs[reg_num - dwarf_d16] = value;
+    }
+    else
+        return false;
+        
+    return true;
+}
+    
+uint64_t
+EmulationStateARM::ReadPseudoRegisterValue (uint32_t reg_num, bool &success)
+{
+    uint64_t value = 0;
+    success = true;
+    
+    if ((dwarf_r0 <= reg_num) && (reg_num <= dwarf_cpsr))
+        value = m_gpr[reg_num  - dwarf_r0];
+    else if ((dwarf_s0 <= reg_num) && (reg_num <= dwarf_s31))
+    {
+        uint32_t idx = reg_num - dwarf_s0;
+        value = m_vfp_regs.sd_regs[idx / 2].s_reg[idx % 2];
+    }
+    else if ((dwarf_d0 <= reg_num) && (reg_num <= dwarf_d31))
+    {
+        if ((reg_num - dwarf_d0) < 16)
+            value = m_vfp_regs.sd_regs[reg_num - dwarf_d0].d_reg;
+        else
+            value = m_vfp_regs.d_regs[reg_num - dwarf_d16];
+    }
+    else
+        success = false;
+        
+    return value;
+}
+    
+void
+EmulationStateARM::ClearPseudoRegisters ()
+{
+    for (int i = 0; i < 17; ++i)
+        m_gpr[i] = 0;
+    
+    for (int i = 0; i < 16; ++i)
+        m_vfp_regs.sd_regs[i].d_reg = 0;
+    
+    for (int i = 0; i < 16; ++i)
+        m_vfp_regs.d_regs[i] = 0;
+}
+
+void
+EmulationStateARM::ClearPseudoMemory ()
+{
+    m_memory.clear();
+}
+    
+bool
+EmulationStateARM::StoreToPseudoAddress (lldb::addr_t p_address, uint64_t value, uint32_t size)
+{
+    if (size > 8)
+        return false;
+    
+    if (size <= 4)
+        m_memory[p_address] = value;
+    else if (size == 8)
+    {
+        m_memory[p_address] = (value << 32) >> 32;
+        m_memory[p_address + 4] = value << 32;
+    }
+    return true;
+}
+    
+uint32_t
+EmulationStateARM::ReadFromPseudoAddress (lldb::addr_t p_address, uint32_t size, bool &success)
+{
+    std::map<lldb::addr_t,uint32_t>::iterator pos;
+    uint32_t ret_val = 0;
+    
+    success = true;
+    pos = m_memory.find(p_address);
+    if (pos != m_memory.end())
+        ret_val = pos->second;
+    else
+        success = false;
+        
+    return ret_val;
+}
+
+size_t
+EmulationStateARM::ReadPseudoMemory (EmulateInstruction *instruction,
+                                     void *baton,
+                                     const EmulateInstruction::Context &context,
+                                     lldb::addr_t addr,
+                                     void *dst,
+                                     size_t length)
+{
+    if (!baton)
+        return 0;
+        
+    bool success = true;
+    EmulationStateARM *pseudo_state = (EmulationStateARM *) baton;
+    if (length <= 4)
+    {
+        uint32_t value = pseudo_state->ReadFromPseudoAddress (addr, length, success);
+        if (!success)
+            return 0;
+            
+        *((uint32_t *) dst) = value;
+    }
+    else if (length == 8)
+    {
+        uint32_t value1 = pseudo_state->ReadFromPseudoAddress (addr, 4, success);
+        if (!success)
+            return 0;
+            
+        uint32_t value2 = pseudo_state->ReadFromPseudoAddress (addr + 4, 4, success);
+        if (!success)
+            return 0;
+            
+        uint64_t value64 = value2;
+        value64 = (value64 << 32) | value1;
+        *((uint64_t *) dst) = value64;
+    }
+    else
+        success = false;
+    
+    if (success)
+        return length;
+    
+    return 0;
+}
+    
+size_t
+EmulationStateARM::WritePseudoMemory (EmulateInstruction *instruction,
+                                      void *baton,
+                                      const EmulateInstruction::Context &context,
+                                      lldb::addr_t addr,
+                                      const void *dst,
+                                      size_t length)
+{
+    if (!baton)
+        return 0;
+        
+    bool success;
+    EmulationStateARM *pseudo_state = (EmulationStateARM *) baton;
+    uint64_t value = *((uint64_t *) dst);
+    success = pseudo_state->StoreToPseudoAddress (addr, value, length);
+    if (success)
+        return length;
+        
+    return 0;
+}
+    
+bool
+EmulationStateARM::ReadPseudoRegister (EmulateInstruction *instruction,
+                                       void *baton,
+                                       const lldb_private::RegisterInfo *reg_info,
+                                       lldb_private::RegisterValue &reg_value)
+{
+    if (!baton || !reg_info)
+        return false;
+        
+    bool success = true;
+    EmulationStateARM *pseudo_state = (EmulationStateARM *) baton;
+    const uint32_t dwarf_reg_num = reg_info->kinds[eRegisterKindDWARF];
+    assert (dwarf_reg_num != LLDB_INVALID_REGNUM);
+    uint64_t reg_uval = pseudo_state->ReadPseudoRegisterValue (dwarf_reg_num, success);
+    
+    if (success)
+        success = reg_value.SetUInt(reg_uval, reg_info->byte_size);
+    return success;
+    
+}
+    
+bool
+EmulationStateARM::WritePseudoRegister (EmulateInstruction *instruction,
+                                        void *baton,
+                                        const EmulateInstruction::Context &context,
+                                        const lldb_private::RegisterInfo *reg_info,
+                                        const lldb_private::RegisterValue &reg_value)
+{
+    if (!baton || !reg_info)
+        return false;
+
+    EmulationStateARM *pseudo_state = (EmulationStateARM *) baton;
+    const uint32_t dwarf_reg_num = reg_info->kinds[eRegisterKindDWARF];
+    assert (dwarf_reg_num != LLDB_INVALID_REGNUM);
+    return pseudo_state->StorePseudoRegisterValue (dwarf_reg_num, reg_value.GetAsUInt64());
+}
+                         
+bool
+EmulationStateARM::CompareState (EmulationStateARM &other_state)
+{
+    bool match = true;
+   
+    for (int i = 0; match && i < 17; ++i)
+    {
+        if (m_gpr[i] != other_state.m_gpr[i])
+            match = false;
+    }
+    
+    for (int i = 0; match && i < 16; ++i)
+    {
+        if (m_vfp_regs.sd_regs[i].s_reg[0] != other_state.m_vfp_regs.sd_regs[i].s_reg[0])
+            match = false;
+
+        if (m_vfp_regs.sd_regs[i].s_reg[1] != other_state.m_vfp_regs.sd_regs[i].s_reg[1])
+            match = false;
+    }
+    
+    for (int i = 0; match && i < 32; ++i)
+    {
+        if (i < 16)
+        {
+            if (m_vfp_regs.sd_regs[i].d_reg != other_state.m_vfp_regs.sd_regs[i].d_reg)
+                match = false;
+        }
+        else
+        {
+            if (m_vfp_regs.d_regs[i - 16] != other_state.m_vfp_regs.d_regs[i - 16])
+                match = false;
+        }
+    }
+    
+    return match;
+}
+
+bool
+EmulationStateARM::LoadStateFromDictionary (OptionValueDictionary *test_data)
+{
+    static ConstString memory_key ("memory");
+    static ConstString registers_key ("registers");
+    
+    if (!test_data)
+        return false;
+    
+    OptionValueSP value_sp = test_data->GetValueForKey (memory_key);
+    
+    // Load memory, if present.
+    
+    if (value_sp.get() != NULL)
+    {
+        static ConstString address_key ("address");
+        static ConstString data_key ("data");
+        uint64_t start_address = 0;
+        
+        OptionValueDictionary *mem_dict = value_sp->GetAsDictionary();
+        value_sp = mem_dict->GetValueForKey (address_key);
+        if (value_sp.get() == NULL)
+            return false;
+        else
+            start_address = value_sp->GetUInt64Value ();
+        
+        value_sp = mem_dict->GetValueForKey (data_key);
+        OptionValueArray *mem_array = value_sp->GetAsArray();
+        if (!mem_array)
+            return false;
+
+        uint32_t num_elts = mem_array->GetSize();
+        uint32_t address = (uint32_t) start_address;
+        
+        for (uint32_t i = 0; i < num_elts; ++i)
+        {
+            value_sp = mem_array->GetValueAtIndex (i);
+            if (value_sp.get() == NULL)
+                return false;
+            uint64_t value = value_sp->GetUInt64Value();
+            StoreToPseudoAddress (address, value, 4);
+            address = address + 4;
+        }
+    }
+    
+    value_sp = test_data->GetValueForKey (registers_key);
+    if (value_sp.get() == NULL)
+        return false;
+
+        
+    // Load General Registers
+   
+    OptionValueDictionary *reg_dict = value_sp->GetAsDictionary ();
+   
+    StreamString sstr;
+    for (int i = 0; i < 16; ++i)
+    {
+        sstr.Clear();
+        sstr.Printf ("r%d", i);
+        ConstString reg_name (sstr.GetData());
+        value_sp = reg_dict->GetValueForKey (reg_name);
+        if (value_sp.get() == NULL)
+            return false;
+        uint64_t reg_value = value_sp->GetUInt64Value();
+        StorePseudoRegisterValue (dwarf_r0 + i, reg_value);
+    }
+    
+    static ConstString cpsr_name ("cpsr");
+    value_sp = reg_dict->GetValueForKey (cpsr_name);
+    if (value_sp.get() == NULL)
+        return false;
+    StorePseudoRegisterValue (dwarf_cpsr, value_sp->GetUInt64Value());
+    
+    // Load s/d Registers
+    for (int i = 0; i < 32; ++i)
+    {
+        sstr.Clear();
+        sstr.Printf ("s%d", i);
+        ConstString reg_name (sstr.GetData());
+        value_sp = reg_dict->GetValueForKey (reg_name);
+        if (value_sp.get() == NULL)
+            return false;
+        uint64_t reg_value = value_sp->GetUInt64Value();
+        StorePseudoRegisterValue (dwarf_s0 + i, reg_value);
+    }
+
+    return true;
+}
+
diff --git a/source/Plugins/Instruction/ARM/EmulationStateARM.h b/source/Plugins/Instruction/ARM/EmulationStateARM.h
new file mode 100644
index 000000000000..8d84abc75614
--- /dev/null
+++ b/source/Plugins/Instruction/ARM/EmulationStateARM.h
@@ -0,0 +1,100 @@
+//===-- lldb_EmulationStateARM.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_EmulationStateARM_h_
+#define lldb_EmulationStateARM_h_
+
+#include <map>
+
+#include "lldb/Core/EmulateInstruction.h"
+#include "lldb/Core/Opcode.h"
+
+class EmulationStateARM {
+public: 
+    
+    EmulationStateARM ();
+    
+    virtual
+    ~EmulationStateARM ();
+    
+    bool
+    StorePseudoRegisterValue (uint32_t reg_num, uint64_t value);
+    
+    uint64_t
+    ReadPseudoRegisterValue (uint32_t reg_num, bool &success);
+    
+    bool
+    StoreToPseudoAddress (lldb::addr_t p_address, uint64_t value, uint32_t size);
+    
+    uint32_t
+    ReadFromPseudoAddress (lldb::addr_t p_address, uint32_t size, bool &success);
+    
+    void
+    ClearPseudoRegisters ();
+    
+    void
+    ClearPseudoMemory ();
+    
+    bool
+    LoadPseudoRegistersFromFrame (lldb_private::StackFrame &frame);
+    
+    bool
+    LoadStateFromDictionary (lldb_private::OptionValueDictionary *test_data);
+
+    bool
+    CompareState (EmulationStateARM &other_state);
+
+    static size_t
+    ReadPseudoMemory (lldb_private::EmulateInstruction *instruction,
+                      void *baton,
+                      const lldb_private::EmulateInstruction::Context &context,
+                      lldb::addr_t addr,
+                      void *dst,
+                      size_t length);
+    
+    static size_t
+    WritePseudoMemory (lldb_private::EmulateInstruction *instruction,
+                       void *baton,
+                       const lldb_private::EmulateInstruction::Context &context,
+                       lldb::addr_t addr,
+                       const void *dst,
+                       size_t length);
+    
+    static bool
+    ReadPseudoRegister (lldb_private::EmulateInstruction *instruction,
+                        void *baton,
+                        const lldb_private::RegisterInfo *reg_info,
+                        lldb_private::RegisterValue &reg_value);
+    
+    static bool
+    WritePseudoRegister (lldb_private::EmulateInstruction *instruction,
+                         void *baton,
+                         const lldb_private::EmulateInstruction::Context &context,
+                         const lldb_private::RegisterInfo *reg_info,
+                         const lldb_private::RegisterValue &reg_value);
+private:
+    uint32_t m_gpr[17];
+    struct sd_regs
+    {
+        union 
+        {
+            uint32_t s_reg[2];
+            uint64_t d_reg;
+        } sd_regs[16];  // sregs 0 - 31 & dregs 0 - 15
+        
+        uint64_t d_regs[16]; // dregs 16-31
+ 
+    } m_vfp_regs;
+    
+    std::map<lldb::addr_t, uint32_t> m_memory; // Eventually will want to change uint32_t to a data buffer heap type.
+    
+    DISALLOW_COPY_AND_ASSIGN (EmulationStateARM);
+};
+
+#endif  // lldb_EmulationStateARM_h_
diff --git a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
new file mode 100644
index 000000000000..247d7b0e7fe4
--- /dev/null
+++ b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
@@ -0,0 +1,461 @@
+//===-- ItaniumABILanguageRuntime.cpp --------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ItaniumABILanguageRuntime.h"
+
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Scalar.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/Core/ValueObjectMemory.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/Symbol.h"
+#include "lldb/Symbol/TypeList.h"
+#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 <vector>
+
+using namespace lldb;
+using namespace lldb_private;
+
+static const char *vtable_demangled_prefix = "vtable for ";
+
+bool
+ItaniumABILanguageRuntime::CouldHaveDynamicValue (ValueObject &in_value)
+{
+    const bool check_cxx = true;
+    const bool check_objc = false;
+    return in_value.GetClangType().IsPossibleDynamicType (NULL, check_cxx, check_objc);
+}
+
+bool
+ItaniumABILanguageRuntime::GetDynamicTypeAndAddress (ValueObject &in_value, 
+                                                     lldb::DynamicValueType use_dynamic, 
+                                                     TypeAndOrName &class_type_or_name, 
+                                                     Address &dynamic_address)
+{
+    // For Itanium, if the type has a vtable pointer in the object, it will be at offset 0
+    // in the object.  That will point to the "address point" within the vtable (not the beginning of the
+    // vtable.)  We can then look up the symbol containing this "address point" and that symbol's name 
+    // demangled will contain the full class name.
+    // The second pointer above the "address point" is the "offset_to_top".  We'll use that to get the
+    // start of the value object which holds the dynamic type.
+    //
+    
+    class_type_or_name.Clear();
+    
+    // Only a pointer or reference type can have a different dynamic and static type:
+    if (CouldHaveDynamicValue (in_value))
+    {
+        // First job, pull out the address at 0 offset from the object.
+        AddressType address_type;
+        lldb::addr_t original_ptr = in_value.GetPointerValue(&address_type);
+        if (original_ptr == LLDB_INVALID_ADDRESS)
+            return false;
+        
+        ExecutionContext exe_ctx (in_value.GetExecutionContextRef());
+
+        Target *target = exe_ctx.GetTargetPtr();
+        Process *process = exe_ctx.GetProcessPtr();
+
+        char memory_buffer[16];
+        DataExtractor data(memory_buffer, sizeof(memory_buffer), 
+                           process->GetByteOrder(), 
+                           process->GetAddressByteSize());
+        size_t address_byte_size = process->GetAddressByteSize();
+        Error error;
+        size_t bytes_read = process->ReadMemory (original_ptr, 
+                                                 memory_buffer, 
+                                                 address_byte_size, 
+                                                 error);
+        if (!error.Success() || (bytes_read != address_byte_size))
+        {
+            return false;
+        }
+        
+        lldb::offset_t offset = 0;
+        lldb::addr_t vtable_address_point = data.GetAddress (&offset);
+            
+        if (offset == 0)
+            return false;
+        
+        // Now find the symbol that contains this address:
+        
+        SymbolContext sc;
+        Address address_point_address;
+        if (target && !target->GetSectionLoadList().IsEmpty())
+        {
+            if (target->GetSectionLoadList().ResolveLoadAddress (vtable_address_point, address_point_address))
+            {
+                target->GetImages().ResolveSymbolContextForAddress (address_point_address, eSymbolContextSymbol, sc);
+                Symbol *symbol = sc.symbol;
+                if (symbol != NULL)
+                {
+                    const char *name = symbol->GetMangled().GetDemangledName().AsCString();
+                    if (strstr(name, vtable_demangled_prefix) == name)
+                    {
+                        Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
+                        if (log)
+                            log->Printf ("0x%16.16" PRIx64 ": static-type = '%s' has vtable symbol '%s'\n",
+                                         original_ptr,
+                                         in_value.GetTypeName().GetCString(),
+                                         name);
+                        // We are a C++ class, that's good.  Get the class name and look it up:
+                        const char *class_name = name + strlen(vtable_demangled_prefix);
+                        class_type_or_name.SetName (class_name);
+                        const bool exact_match = true;
+                        TypeList class_types;
+                        
+                        uint32_t num_matches = 0;
+                        // First look in the module that the vtable symbol came from
+                        // and look for a single exact match.
+                        if (sc.module_sp)
+                        {
+                            num_matches = sc.module_sp->FindTypes (sc,
+                                                                   ConstString(class_name),
+                                                                   exact_match,
+                                                                   1,
+                                                                   class_types);
+                        }
+                        
+                        // If we didn't find a symbol, then move on to the entire
+                        // module list in the target and get as many unique matches
+                        // as possible
+                        if (num_matches == 0)
+                        {
+                            num_matches = target->GetImages().FindTypes (sc,
+                                                                         ConstString(class_name),
+                                                                         exact_match,
+                                                                         UINT32_MAX,
+                                                                         class_types);
+                        }
+                        
+                        lldb::TypeSP type_sp;
+                        if (num_matches == 0)
+                        {
+                            if (log)
+                                log->Printf("0x%16.16" PRIx64 ": is not dynamic\n", original_ptr);
+                            return false;
+                        }
+                        if (num_matches == 1)
+                        {
+                            type_sp = class_types.GetTypeAtIndex(0);
+                            if (log)
+                                log->Printf ("0x%16.16" PRIx64 ": static-type = '%s' has dynamic type: uid={0x%" PRIx64 "}, type-name='%s'\n",
+                                             original_ptr,
+                                             in_value.GetTypeName().AsCString(),
+                                             type_sp->GetID(),
+                                             type_sp->GetName().GetCString());
+
+                            class_type_or_name.SetTypeSP(class_types.GetTypeAtIndex(0));
+                        }
+                        else if (num_matches > 1)
+                        {
+                            size_t i;
+                            if (log)
+                            {
+                                for (i = 0; i < num_matches; i++)
+                                {
+                                    type_sp = class_types.GetTypeAtIndex(i);
+                                    if (type_sp)
+                                    {
+                                        if (log)
+                                            log->Printf ("0x%16.16" PRIx64 ": static-type = '%s' has multiple matching dynamic types: uid={0x%" PRIx64 "}, type-name='%s'\n",
+                                                         original_ptr,
+                                                         in_value.GetTypeName().AsCString(),
+                                                         type_sp->GetID(),
+                                                         type_sp->GetName().GetCString());
+                                    }
+                                }
+                            }
+
+                            for (i = 0; i < num_matches; i++)
+                            {
+                                type_sp = class_types.GetTypeAtIndex(i);
+                                if (type_sp)
+                                {
+                                    if (type_sp->GetClangFullType().IsCXXClassType())
+                                    {
+                                        if (log)
+                                            log->Printf ("0x%16.16" PRIx64 ": static-type = '%s' has multiple matching dynamic types, picking this one: uid={0x%" PRIx64 "}, type-name='%s'\n",
+                                                         original_ptr,
+                                                         in_value.GetTypeName().AsCString(),
+                                                         type_sp->GetID(),
+                                                         type_sp->GetName().GetCString());
+                                        class_type_or_name.SetTypeSP(type_sp);
+                                        break;
+                                    }
+                                }
+                            }
+                            
+                            if (i == num_matches)
+                            {
+                                if (log)
+                                    log->Printf ("0x%16.16" PRIx64 ": static-type = '%s' has multiple matching dynamic types, didn't find a C++ match\n",
+                                                 original_ptr,
+                                                 in_value.GetTypeName().AsCString());
+                                return false;
+                            }
+                        }
+
+                        // There can only be one type with a given name,
+                        // so we've just found duplicate definitions, and this
+                        // one will do as well as any other.
+                        // We don't consider something to have a dynamic type if
+                        // it is the same as the static type.  So compare against
+                        // the value we were handed.
+                        if (type_sp)
+                        {
+                            if (ClangASTContext::AreTypesSame (in_value.GetClangType(),
+                                                               type_sp->GetClangFullType()))
+                            {
+                                // The dynamic type we found was the same type,
+                                // so we don't have a dynamic type here...
+                                return false;
+                            }
+
+                            // The offset_to_top is two pointers above the address.
+                            Address offset_to_top_address = address_point_address;
+                            int64_t slide = -2 * ((int64_t) target->GetArchitecture().GetAddressByteSize());
+                            offset_to_top_address.Slide (slide);
+                            
+                            Error error;
+                            lldb::addr_t offset_to_top_location = offset_to_top_address.GetLoadAddress(target);
+                            
+                            size_t bytes_read = process->ReadMemory (offset_to_top_location, 
+                                                                     memory_buffer, 
+                                                                     address_byte_size, 
+                                                                     error);
+                                                                     
+                            if (!error.Success() || (bytes_read != address_byte_size))
+                            {
+                                return false;
+                            }
+                            
+                            offset = 0;
+                            int64_t offset_to_top = data.GetMaxS64(&offset, process->GetAddressByteSize());
+                            
+                            // So the dynamic type is a value that starts at offset_to_top
+                            // above the original address.
+                            lldb::addr_t dynamic_addr = original_ptr + offset_to_top;
+                            if (!target->GetSectionLoadList().ResolveLoadAddress (dynamic_addr, dynamic_address))
+                            {
+                                dynamic_address.SetRawAddress(dynamic_addr);
+                            }
+                            return true;
+                        }
+                    }
+                }
+            }
+        }
+    }
+    
+    return class_type_or_name.IsEmpty() == false;
+}
+
+bool
+ItaniumABILanguageRuntime::IsVTableName (const char *name)
+{
+    if (name == NULL)
+        return false;
+        
+    // Can we maybe ask Clang about this?
+    if (strstr (name, "_vptr$") == name)
+        return true;
+    else
+        return false;
+}
+
+//------------------------------------------------------------------
+// Static Functions
+//------------------------------------------------------------------
+LanguageRuntime *
+ItaniumABILanguageRuntime::CreateInstance (Process *process, lldb::LanguageType language)
+{
+    // FIXME: We have to check the process and make sure we actually know that this process supports
+    // the Itanium ABI.
+    if (language == eLanguageTypeC_plus_plus)
+        return new ItaniumABILanguageRuntime (process);
+    else
+        return NULL;
+}
+
+void
+ItaniumABILanguageRuntime::Initialize()
+{
+    PluginManager::RegisterPlugin (GetPluginNameStatic(),
+                                   "Itanium ABI for the C++ language",
+                                   CreateInstance);    
+}
+
+void
+ItaniumABILanguageRuntime::Terminate()
+{
+    PluginManager::UnregisterPlugin (CreateInstance);
+}
+
+lldb_private::ConstString
+ItaniumABILanguageRuntime::GetPluginNameStatic()
+{
+    static ConstString g_name("itanium");
+    return g_name;
+}
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+lldb_private::ConstString
+ItaniumABILanguageRuntime::GetPluginName()
+{
+    return GetPluginNameStatic();
+}
+
+uint32_t
+ItaniumABILanguageRuntime::GetPluginVersion()
+{
+    return 1;
+}
+
+BreakpointResolverSP
+ItaniumABILanguageRuntime::CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bool throw_bp)
+{
+    return CreateExceptionResolver (bkpt, catch_bp, throw_bp, false);
+}
+
+BreakpointResolverSP
+ItaniumABILanguageRuntime::CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bool throw_bp, bool for_expressions)
+{
+    // One complication here is that most users DON'T want to stop at __cxa_allocate_expression, but until we can do
+    // anything better with predicting unwinding the expression parser does.  So we have two forms of the exception
+    // breakpoints, one for expressions that leaves out __cxa_allocate_exception, and one that includes it.
+    // The SetExceptionBreakpoints does the latter, the CreateExceptionBreakpoint in the runtime the former.
+    static const char *g_catch_name = "__cxa_begin_catch";
+    static const char *g_throw_name1 = "__cxa_throw";
+    static const char *g_throw_name2 = "__cxa_rethrow";
+    static const char *g_exception_throw_name = "__cxa_allocate_exception";
+    std::vector<const char *> exception_names;
+    exception_names.reserve(4);
+    if (catch_bp)
+        exception_names.push_back(g_catch_name);
+
+    if (throw_bp)
+    {
+        exception_names.push_back(g_throw_name1);
+        exception_names.push_back(g_throw_name2);
+    }
+
+    if (for_expressions)
+        exception_names.push_back(g_exception_throw_name);
+    
+    BreakpointResolverSP resolver_sp (new BreakpointResolverName (bkpt,
+                                                                  exception_names.data(),
+                                                                  exception_names.size(),
+                                                                  eFunctionNameTypeBase,
+                                                                  eLazyBoolNo));
+
+    return resolver_sp;
+}
+
+
+
+lldb::SearchFilterSP
+ItaniumABILanguageRuntime::CreateExceptionSearchFilter ()
+{
+    Target &target = m_process->GetTarget();
+
+    if (target.GetArchitecture().GetTriple().getVendor() == llvm::Triple::Apple)
+    {
+        // Limit the number of modules that are searched for these breakpoints for
+        // Apple binaries.
+        FileSpecList filter_modules;
+        filter_modules.Append(FileSpec("libc++abi.dylib", false));
+        filter_modules.Append(FileSpec("libSystem.B.dylib", false));
+        return target.GetSearchFilterForModuleList(&filter_modules);
+    }
+    else
+    {
+        return LanguageRuntime::CreateExceptionSearchFilter();
+    }
+}
+
+lldb::BreakpointSP
+ItaniumABILanguageRuntime::CreateExceptionBreakpoint (bool catch_bp,
+                                                      bool throw_bp,
+                                                      bool for_expressions,
+                                                      bool is_internal)
+{
+    Target &target = m_process->GetTarget();
+    FileSpecList filter_modules;
+    BreakpointResolverSP exception_resolver_sp = CreateExceptionResolver (NULL, catch_bp, throw_bp, for_expressions);
+    SearchFilterSP filter_sp (CreateExceptionSearchFilter ());
+    return target.CreateBreakpoint (filter_sp, exception_resolver_sp, is_internal);
+}
+
+void
+ItaniumABILanguageRuntime::SetExceptionBreakpoints ()
+{
+    if (!m_process)
+        return;
+    
+    const bool catch_bp = false;
+    const bool throw_bp = true;
+    const bool is_internal = true;
+    const bool for_expressions = true;
+    
+    // For the exception breakpoints set by the Expression parser, we'll be a little more aggressive and
+    // stop at exception allocation as well.
+    
+    if (m_cxx_exception_bp_sp)
+    {
+        m_cxx_exception_bp_sp->SetEnabled (true);
+    }
+    else
+    {
+        m_cxx_exception_bp_sp = CreateExceptionBreakpoint (catch_bp, throw_bp, for_expressions, is_internal);
+        if (m_cxx_exception_bp_sp)
+            m_cxx_exception_bp_sp->SetBreakpointKind("c++ exception");
+    }
+    
+}
+
+void
+ItaniumABILanguageRuntime::ClearExceptionBreakpoints ()
+{
+    if (!m_process)
+        return;
+    
+    if (m_cxx_exception_bp_sp)
+    {
+        m_cxx_exception_bp_sp->SetEnabled (false);
+    }    
+}
+
+bool
+ItaniumABILanguageRuntime::ExceptionBreakpointsExplainStop (lldb::StopInfoSP stop_reason)
+{
+    if (!m_process)
+        return false;
+    
+    if (!stop_reason || 
+        stop_reason->GetStopReason() != eStopReasonBreakpoint)
+        return false;
+    
+    uint64_t break_site_id = stop_reason->GetValue();
+    return m_process->GetBreakpointSiteList().BreakpointSiteContainsBreakpoint(break_site_id,
+                                                                               m_cxx_exception_bp_sp->GetID());
+    
+}
diff --git a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h
new file mode 100644
index 000000000000..6b2c437de252
--- /dev/null
+++ b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h
@@ -0,0 +1,101 @@
+//===-- ItaniumABILanguageRuntime.h ----------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ItaniumABILanguageRuntime_h_
+#define liblldb_ItaniumABILanguageRuntime_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Breakpoint/BreakpointResolver.h"
+#include "lldb/Target/LanguageRuntime.h"
+#include "lldb/Target/CPPLanguageRuntime.h"
+#include "lldb/Core/Value.h"
+
+namespace lldb_private {
+    
+    class ItaniumABILanguageRuntime :
+    public lldb_private::CPPLanguageRuntime
+    {
+    public:
+        ~ItaniumABILanguageRuntime() { }
+        
+        virtual bool
+        IsVTableName (const char *name);
+        
+        virtual bool
+        GetDynamicTypeAndAddress (ValueObject &in_value, 
+                                  lldb::DynamicValueType use_dynamic, 
+                                  TypeAndOrName &class_type_or_name, 
+                                  Address &address);
+        
+        virtual bool
+        CouldHaveDynamicValue (ValueObject &in_value);
+        
+        //------------------------------------------------------------------
+        // Static Functions
+        //------------------------------------------------------------------
+        static void
+        Initialize();
+        
+        static void
+        Terminate();
+        
+        static lldb_private::LanguageRuntime *
+        CreateInstance (Process *process, lldb::LanguageType language);
+        
+        static lldb_private::ConstString
+        GetPluginNameStatic();
+
+        //------------------------------------------------------------------
+        // PluginInterface protocol
+        //------------------------------------------------------------------
+        virtual lldb_private::ConstString
+        GetPluginName();
+        
+        virtual uint32_t
+        GetPluginVersion();
+        
+        virtual void
+        SetExceptionBreakpoints ();
+        
+        virtual void
+        ClearExceptionBreakpoints ();
+        
+        virtual bool
+        ExceptionBreakpointsExplainStop (lldb::StopInfoSP stop_reason);
+
+        virtual lldb::BreakpointResolverSP
+        CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bool throw_bp);
+        
+        virtual lldb::SearchFilterSP
+        CreateExceptionSearchFilter ();
+
+    protected:
+
+        lldb::BreakpointResolverSP
+        CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bool throw_bp, bool for_expressions);
+
+        lldb::BreakpointSP
+        CreateExceptionBreakpoint(bool catch_bp,
+                                  bool throw_bp,
+                                  bool for_expressions,
+                                  bool is_internal);
+        
+    private:
+        ItaniumABILanguageRuntime(Process *process) : lldb_private::CPPLanguageRuntime(process) { } // Call CreateInstance instead.
+        
+        lldb::BreakpointSP                              m_cxx_exception_bp_sp;
+    };
+    
+} // namespace lldb_private
+
+#endif  // liblldb_ItaniumABILanguageRuntime_h_
diff --git a/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp b/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp
new file mode 100644
index 000000000000..1ec5f3d733a0
--- /dev/null
+++ b/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp
@@ -0,0 +1,585 @@
+//===-- ObjectContainerBSDArchive.cpp ---------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ObjectContainerBSDArchive.h"
+
+#include <ar.h>
+
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/DataBuffer.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/Timer.h"
+#include "lldb/Host/Mutex.h"
+#include "lldb/Symbol/ObjectFile.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+
+ObjectContainerBSDArchive::Object::Object() :
+    ar_name(),
+    ar_date(0),
+    ar_uid(0),
+    ar_gid(0),
+    ar_mode(0),
+    ar_size(0),
+    ar_file_offset(0),
+    ar_file_size(0)
+{
+}
+
+void
+ObjectContainerBSDArchive::Object::Clear()
+{
+    ar_name.Clear();
+    ar_date = 0;
+    ar_uid  = 0;
+    ar_gid  = 0;
+    ar_mode = 0;
+    ar_size = 0;
+    ar_file_offset = 0;
+    ar_file_size = 0;
+}
+
+lldb::offset_t
+ObjectContainerBSDArchive::Object::Extract (const DataExtractor& data, lldb::offset_t offset)
+{
+    size_t ar_name_len = 0;
+    std::string str;
+    char *err;
+    str.assign ((const char *)data.GetData(&offset, 16),    16);
+    if (str.find("#1/") == 0)
+    {
+        // If the name is longer than 16 bytes, or contains an embedded space
+        // then it will use this format where the length of the name is
+        // here and the name characters are after this header.
+        ar_name_len = strtoul(str.c_str() + 3, &err, 10);
+    }
+    else
+    {
+        // Strip off any spaces (if the object file name contains spaces it
+        // will use the extended format above).
+        str.erase (str.find(' '));
+        ar_name.SetCString(str.c_str());
+    }
+
+    str.assign ((const char *)data.GetData(&offset, 12),    12);
+    ar_date = strtoul(str.c_str(), &err, 10);
+
+    str.assign ((const char *)data.GetData(&offset, 6), 6);
+    ar_uid  = strtoul(str.c_str(), &err, 10);
+
+    str.assign ((const char *)data.GetData(&offset, 6), 6);
+    ar_gid  = strtoul(str.c_str(), &err, 10);
+
+    str.assign ((const char *)data.GetData(&offset, 8), 8);
+    ar_mode = strtoul(str.c_str(), &err, 8);
+
+    str.assign ((const char *)data.GetData(&offset, 10),    10);
+    ar_size = strtoul(str.c_str(), &err, 10);
+
+    str.assign ((const char *)data.GetData(&offset, 2), 2);
+    if (str == ARFMAG)
+    {
+        if (ar_name_len > 0)
+        {
+            str.assign ((const char *)data.GetData(&offset, ar_name_len), ar_name_len);
+            ar_name.SetCString (str.c_str());
+        }
+        ar_file_offset = offset;
+        ar_file_size = ar_size - ar_name_len;
+        return offset;
+    }
+    return LLDB_INVALID_OFFSET;
+}
+
+ObjectContainerBSDArchive::Archive::Archive
+(
+    const lldb_private::ArchSpec &arch,
+    const lldb_private::TimeValue &time,
+    lldb::offset_t file_offset,
+    lldb_private::DataExtractor &data
+) :
+    m_arch (arch),
+    m_time (time),
+    m_file_offset (file_offset),
+    m_objects(),
+    m_data (data)
+{
+}
+
+ObjectContainerBSDArchive::Archive::~Archive ()
+{
+}
+
+size_t
+ObjectContainerBSDArchive::Archive::ParseObjects ()
+{
+    DataExtractor &data = m_data;
+    std::string str;
+    lldb::offset_t offset = 0;
+    str.assign((const char *)data.GetData(&offset, SARMAG), SARMAG);
+    if (str == ARMAG)
+    {
+        Object obj;
+        do
+        {
+            offset = obj.Extract (data, offset);
+            if (offset == LLDB_INVALID_OFFSET)
+                break;
+            size_t obj_idx = m_objects.size();
+            m_objects.push_back(obj);
+            // Insert all of the C strings out of order for now...
+            m_object_name_to_index_map.Append (obj.ar_name.GetCString(), obj_idx);
+            offset += obj.ar_file_size;
+            obj.Clear();
+        } while (data.ValidOffset(offset));
+
+        // Now sort all of the object name pointers
+        m_object_name_to_index_map.Sort ();
+    }
+    return m_objects.size();
+}
+
+ObjectContainerBSDArchive::Object *
+ObjectContainerBSDArchive::Archive::FindObject (const ConstString &object_name, const TimeValue &object_mod_time)
+{
+    const ObjectNameToIndexMap::Entry *match = m_object_name_to_index_map.FindFirstValueForName (object_name.GetCString());
+    if (match)
+    {
+        if (object_mod_time.IsValid())
+        {
+            const uint64_t object_date = object_mod_time.GetAsSecondsSinceJan1_1970();
+            if (m_objects[match->value].ar_date == object_date)
+                return &m_objects[match->value];
+            const ObjectNameToIndexMap::Entry *next_match = m_object_name_to_index_map.FindNextValueForName (match);
+            while (next_match)
+            {
+                if (m_objects[next_match->value].ar_date == object_date)
+                    return &m_objects[next_match->value];
+                next_match = m_object_name_to_index_map.FindNextValueForName (next_match);
+            }
+        }
+        else
+        {
+            return &m_objects[match->value];
+        }
+    }
+    return NULL;
+}
+
+
+ObjectContainerBSDArchive::Archive::shared_ptr
+ObjectContainerBSDArchive::Archive::FindCachedArchive (const FileSpec &file, const ArchSpec &arch, const TimeValue &time, lldb::offset_t file_offset)
+{
+    Mutex::Locker locker(Archive::GetArchiveCacheMutex ());
+    shared_ptr archive_sp;
+    Archive::Map &archive_map = Archive::GetArchiveCache ();
+    Archive::Map::iterator pos = archive_map.find (file);
+    // Don't cache a value for "archive_map.end()" below since we might
+    // delete an archive entry...
+    while (pos != archive_map.end() && pos->first == file)
+    {
+        bool match = true;
+        if (arch.IsValid() && pos->second->GetArchitecture().IsCompatibleMatch(arch) == false)
+            match = false;
+        else if (file_offset != LLDB_INVALID_OFFSET && pos->second->GetFileOffset() != file_offset)
+            match = false;
+        if (match)
+        {
+            if (pos->second->GetModificationTime() == time)
+            {
+                return pos->second;
+            }
+            else
+            {
+                // We have a file at the same path with the same architecture
+                // whose modification time doesn't match. It doesn't make sense
+                // for us to continue to use this BSD archive since we cache only
+                // the object info which consists of file time info and also the
+                // file offset and file size of any contianed objects. Since
+                // this information is now out of date, we won't get the correct
+                // information if we go and extract the file data, so we should 
+                // remove the old and outdated entry.
+                archive_map.erase (pos);
+                pos = archive_map.find (file);
+                continue; // Continue to next iteration so we don't increment pos below...
+            }
+        }
+        ++pos;
+    }
+    return archive_sp;
+}
+
+ObjectContainerBSDArchive::Archive::shared_ptr
+ObjectContainerBSDArchive::Archive::ParseAndCacheArchiveForFile
+(
+    const FileSpec &file,
+    const ArchSpec &arch,
+    const TimeValue &time,
+    lldb::offset_t file_offset,
+    DataExtractor &data
+)
+{
+    shared_ptr archive_sp(new Archive (arch, time, file_offset, data));
+    if (archive_sp)
+    {
+        const size_t num_objects = archive_sp->ParseObjects ();
+        if (num_objects > 0)
+        {
+            Mutex::Locker locker(Archive::GetArchiveCacheMutex ());
+            Archive::GetArchiveCache().insert(std::make_pair(file, archive_sp));
+        }
+        else
+        {
+            archive_sp.reset();
+        }
+    }
+    return archive_sp;
+}
+
+ObjectContainerBSDArchive::Archive::Map &
+ObjectContainerBSDArchive::Archive::GetArchiveCache ()
+{
+    static Archive::Map g_archive_map;
+    return g_archive_map;
+}
+
+Mutex &
+ObjectContainerBSDArchive::Archive::GetArchiveCacheMutex ()
+{
+    static Mutex g_archive_map_mutex (Mutex::eMutexTypeRecursive);
+    return g_archive_map_mutex;
+}
+
+
+void
+ObjectContainerBSDArchive::Initialize()
+{
+    PluginManager::RegisterPlugin (GetPluginNameStatic(),
+                                   GetPluginDescriptionStatic(),
+                                   CreateInstance,
+                                   GetModuleSpecifications);
+}
+
+void
+ObjectContainerBSDArchive::Terminate()
+{
+    PluginManager::UnregisterPlugin (CreateInstance);
+}
+
+
+lldb_private::ConstString
+ObjectContainerBSDArchive::GetPluginNameStatic()
+{
+    static ConstString g_name("bsd-archive");
+    return g_name;
+}
+
+const char *
+ObjectContainerBSDArchive::GetPluginDescriptionStatic()
+{
+    return "BSD Archive object container reader.";
+}
+
+
+ObjectContainer *
+ObjectContainerBSDArchive::CreateInstance
+(
+    const lldb::ModuleSP &module_sp,
+    DataBufferSP& data_sp,
+    lldb::offset_t data_offset,
+    const FileSpec *file,
+    lldb::offset_t file_offset,
+    lldb::offset_t length)
+{
+    ConstString object_name (module_sp->GetObjectName());
+    if (object_name)
+    {
+        if (data_sp)
+        {
+            // We have data, which means this is the first 512 bytes of the file
+            // Check to see if the magic bytes match and if they do, read the entire
+            // table of contents for the archive and cache it
+            DataExtractor data;
+            data.SetData (data_sp, data_offset, length);
+            if (file && data_sp && ObjectContainerBSDArchive::MagicBytesMatch(data))
+            {
+                Timer scoped_timer (__PRETTY_FUNCTION__,
+                                    "ObjectContainerBSDArchive::CreateInstance (module = %s, file = %p, file_offset = 0x%8.8" PRIx64 ", file_size = 0x%8.8" PRIx64 ")",
+                                    module_sp->GetFileSpec().GetPath().c_str(),
+                                    file, (uint64_t) file_offset, (uint64_t) length);
+
+                // Map the entire .a file to be sure that we don't lose any data if the file
+                // gets updated by a new build while this .a file is being used for debugging
+                DataBufferSP archive_data_sp (file->MemoryMapFileContents(file_offset, length));
+                lldb::offset_t archive_data_offset = 0;
+
+                Archive::shared_ptr archive_sp (Archive::FindCachedArchive (*file,
+                                                                            module_sp->GetArchitecture(),
+                                                                            module_sp->GetModificationTime(),
+                                                                            file_offset));
+                std::unique_ptr<ObjectContainerBSDArchive> container_ap(new ObjectContainerBSDArchive (module_sp,
+                                                                                                       archive_data_sp,
+                                                                                                       archive_data_offset,
+                                                                                                       file,
+                                                                                                       file_offset,
+                                                                                                       length));
+
+                if (container_ap.get())
+                {
+                    if (archive_sp)
+                    {
+                        // We already have this archive in our cache, use it
+                        container_ap->SetArchive (archive_sp);
+                        return container_ap.release();
+                    }
+                    else if (container_ap->ParseHeader())
+                        return container_ap.release();
+                }
+            }
+        }
+        else
+        {
+            // No data, just check for a cached archive
+            Archive::shared_ptr archive_sp (Archive::FindCachedArchive (*file,
+                                                                        module_sp->GetArchitecture(),
+                                                                        module_sp->GetModificationTime(),
+                                                                        file_offset));
+            if (archive_sp)
+            {
+                std::unique_ptr<ObjectContainerBSDArchive> container_ap(new ObjectContainerBSDArchive (module_sp, data_sp, data_offset, file, file_offset, length));
+                
+                if (container_ap.get())
+                {
+                    // We already have this archive in our cache, use it
+                    container_ap->SetArchive (archive_sp);
+                    return container_ap.release();
+                }
+            }
+        }
+    }
+    return NULL;
+}
+
+
+
+bool
+ObjectContainerBSDArchive::MagicBytesMatch (const DataExtractor &data)
+{
+    uint32_t offset = 0;
+    const char* armag = (const char* )data.PeekData (offset, sizeof(ar_hdr));
+    if (armag && ::strncmp(armag, ARMAG, SARMAG) == 0)
+    {
+        armag += offsetof(struct ar_hdr, ar_fmag) + SARMAG;
+        if (strncmp(armag, ARFMAG, 2) == 0)
+            return true;
+    }
+    return false;
+}
+
+ObjectContainerBSDArchive::ObjectContainerBSDArchive
+(
+    const lldb::ModuleSP &module_sp,
+    DataBufferSP& data_sp,
+    lldb::offset_t data_offset,
+    const lldb_private::FileSpec *file,
+    lldb::offset_t file_offset,
+    lldb::offset_t size
+) :
+    ObjectContainer (module_sp, file, file_offset, size, data_sp, data_offset),
+    m_archive_sp ()
+{
+}
+void
+ObjectContainerBSDArchive::SetArchive (Archive::shared_ptr &archive_sp)
+{
+    m_archive_sp = archive_sp;
+}
+
+
+
+ObjectContainerBSDArchive::~ObjectContainerBSDArchive()
+{
+}
+
+bool
+ObjectContainerBSDArchive::ParseHeader ()
+{
+    if (m_archive_sp.get() == NULL)
+    {
+        if (m_data.GetByteSize() > 0)
+        {
+            ModuleSP module_sp (GetModule());
+            if (module_sp)
+            {
+                m_archive_sp = Archive::ParseAndCacheArchiveForFile (m_file,
+                                                                     module_sp->GetArchitecture(),
+                                                                     module_sp->GetModificationTime(),
+                                                                     m_offset,
+                                                                     m_data);
+            }
+            // Clear the m_data that contains the entire archive
+            // data and let our m_archive_sp hold onto the data.
+            m_data.Clear();
+        }
+    }
+    return m_archive_sp.get() != NULL;
+}
+
+void
+ObjectContainerBSDArchive::Dump (Stream *s) const
+{
+    s->Printf("%p: ", this);
+    s->Indent();
+    const size_t num_archs = GetNumArchitectures();
+    const size_t num_objects = GetNumObjects();
+    s->Printf("ObjectContainerBSDArchive, num_archs = %lu, num_objects = %lu", num_archs, num_objects);
+    uint32_t i;
+    ArchSpec arch;
+    s->IndentMore();
+    for (i=0; i<num_archs; i++)
+    {
+        s->Indent();
+        GetArchitectureAtIndex(i, arch);
+        s->Printf("arch[%u] = %s\n", i, arch.GetArchitectureName());
+    }
+    for (i=0; i<num_objects; i++)
+    {
+        s->Indent();
+        s->Printf("object[%u] = %s\n", i, GetObjectNameAtIndex (i));
+    }
+    s->IndentLess();
+    s->EOL();
+}
+
+ObjectFileSP
+ObjectContainerBSDArchive::GetObjectFile (const FileSpec *file)
+{
+    ModuleSP module_sp (GetModule());
+    if (module_sp)
+    {
+        if (module_sp->GetObjectName() && m_archive_sp)
+        {
+            Object *object = m_archive_sp->FindObject (module_sp->GetObjectName(),
+                                                       module_sp->GetObjectModificationTime());
+            if (object)
+            {
+                lldb::offset_t data_offset = object->ar_file_offset;
+                return ObjectFile::FindPlugin (module_sp,
+                                               file, 
+                                               m_offset + object->ar_file_offset,
+                                               object->ar_file_size,
+                                               m_archive_sp->GetData().GetSharedDataBuffer(),
+                                               data_offset);
+            }
+        }
+    }
+    return ObjectFileSP();
+}
+
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+lldb_private::ConstString
+ObjectContainerBSDArchive::GetPluginName()
+{
+    return GetPluginNameStatic();
+}
+
+uint32_t
+ObjectContainerBSDArchive::GetPluginVersion()
+{
+    return 1;
+}
+
+
+size_t
+ObjectContainerBSDArchive::GetModuleSpecifications (const lldb_private::FileSpec& file,
+                                                    lldb::DataBufferSP& data_sp,
+                                                    lldb::offset_t data_offset,
+                                                    lldb::offset_t file_offset,
+                                                    lldb::offset_t file_size,
+                                                    lldb_private::ModuleSpecList &specs)
+{
+
+    // We have data, which means this is the first 512 bytes of the file
+    // Check to see if the magic bytes match and if they do, read the entire
+    // table of contents for the archive and cache it
+    DataExtractor data;
+    data.SetData (data_sp, data_offset, data_sp->GetByteSize());
+    if (file && data_sp && ObjectContainerBSDArchive::MagicBytesMatch(data))
+    {
+        const size_t initial_count = specs.GetSize();
+        TimeValue file_mod_time = file.GetModificationTime();
+        Archive::shared_ptr archive_sp (Archive::FindCachedArchive (file, ArchSpec(), file_mod_time, file_offset));
+        bool set_archive_arch = false;
+        if (!archive_sp)
+        {
+            set_archive_arch = true;
+            DataBufferSP data_sp (file.MemoryMapFileContents(file_offset, file_size));
+            data.SetData (data_sp, 0, data_sp->GetByteSize());
+            archive_sp = Archive::ParseAndCacheArchiveForFile(file, ArchSpec(), file_mod_time, file_offset, data);
+        }
+        
+        if (archive_sp)
+        {
+            const size_t num_objects = archive_sp->GetNumObjects();
+            for (size_t idx = 0; idx < num_objects; ++idx)
+            {
+                const Object *object = archive_sp->GetObjectAtIndex (idx);
+                if (object)
+                {
+                    const lldb::offset_t object_file_offset = file_offset + object->ar_file_offset;
+                    if (object->ar_file_offset < file_size && file_size > object_file_offset)
+                    {
+                        if (ObjectFile::GetModuleSpecifications(file,
+                                                                object_file_offset,
+                                                                file_size - object_file_offset,
+                                                                specs))
+                        {
+                            ModuleSpec &spec = specs.GetModuleSpecRefAtIndex (specs.GetSize() - 1);
+                            TimeValue object_mod_time;
+                            object_mod_time.OffsetWithSeconds(object->ar_date);
+                            spec.GetObjectName () = object->ar_name;
+                            spec.SetObjectOffset(object_file_offset);
+                            spec.GetObjectModificationTime () = object_mod_time;
+                        }
+                    }
+                }
+            }
+        }
+        const size_t end_count = specs.GetSize();
+        size_t num_specs_added = end_count - initial_count;
+        if (set_archive_arch && num_specs_added > 0)
+        {
+            // The archive was created but we didn't have an architecture
+            // so we need to set it
+            for (size_t i=initial_count; i<end_count; ++ i)
+            {
+                ModuleSpec module_spec;
+                if (specs.GetModuleSpecAtIndex(i, module_spec))
+                {
+                    if (module_spec.GetArchitecture().IsValid())
+                    {
+                        archive_sp->SetArchitecture (module_spec.GetArchitecture());
+                        break;
+                    }
+                }
+            }
+        }
+        return num_specs_added;
+    }
+    return 0;
+}
diff --git a/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h b/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h
new file mode 100644
index 000000000000..8093c580ff97
--- /dev/null
+++ b/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h
@@ -0,0 +1,229 @@
+//===-- ObjectContainerBSDArchive.h -----------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ObjectContainerBSDArchive_h_
+#define liblldb_ObjectContainerBSDArchive_h_
+
+#include "lldb/Symbol/ObjectContainer.h"
+
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/ConstString.h"
+#include "lldb/Host/FileSpec.h"
+#include "lldb/Core/UniqueCStringMap.h"
+#include "lldb/Host/TimeValue.h"
+
+class ObjectContainerBSDArchive :
+    public lldb_private::ObjectContainer
+{
+public:
+
+    //------------------------------------------------------------------
+    // Static Functions
+    //------------------------------------------------------------------
+    static void
+    Initialize();
+
+    static void
+    Terminate();
+
+    static lldb_private::ConstString
+    GetPluginNameStatic();
+
+    static const char *
+    GetPluginDescriptionStatic();
+
+    static lldb_private::ObjectContainer *
+    CreateInstance (const lldb::ModuleSP &module_sp,
+                    lldb::DataBufferSP& data_sp,
+                    lldb::offset_t data_offset,
+                    const lldb_private::FileSpec *file,
+                    lldb::offset_t offset,
+                    lldb::offset_t length);
+
+    static size_t
+    GetModuleSpecifications (const lldb_private::FileSpec& file,
+                             lldb::DataBufferSP& data_sp,
+                             lldb::offset_t data_offset,
+                             lldb::offset_t file_offset,
+                             lldb::offset_t length,
+                             lldb_private::ModuleSpecList &specs);
+
+    static bool
+    MagicBytesMatch (const lldb_private::DataExtractor &data);
+
+    //------------------------------------------------------------------
+    // Member Functions
+    //------------------------------------------------------------------
+    ObjectContainerBSDArchive (const lldb::ModuleSP &module_sp,
+                               lldb::DataBufferSP& data_sp,
+                               lldb::offset_t data_offset,
+                               const lldb_private::FileSpec *file,
+                               lldb::offset_t offset,
+                               lldb::offset_t length);
+
+    virtual
+    ~ObjectContainerBSDArchive();
+
+    virtual bool
+    ParseHeader ();
+
+    virtual size_t
+    GetNumObjects () const
+    {
+        if (m_archive_sp)
+            return m_archive_sp->GetNumObjects();
+        return 0;
+    }
+    virtual void
+    Dump (lldb_private::Stream *s) const;
+
+    virtual lldb::ObjectFileSP
+    GetObjectFile (const lldb_private::FileSpec *file);
+
+    //------------------------------------------------------------------
+    // PluginInterface protocol
+    //------------------------------------------------------------------
+    virtual lldb_private::ConstString
+    GetPluginName();
+
+    virtual uint32_t
+    GetPluginVersion();
+
+protected:
+
+    struct Object
+    {
+        Object();
+
+        void
+        Clear();
+
+        lldb::offset_t
+        Extract (const lldb_private::DataExtractor& data, lldb::offset_t offset);
+
+        lldb_private::ConstString       ar_name;        // name
+        uint32_t        ar_date;        // modification time
+        uint16_t        ar_uid;         // user id
+        uint16_t        ar_gid;         // group id
+        uint16_t        ar_mode;        // octal file permissions
+        uint32_t        ar_size;        // size in bytes
+        lldb::offset_t  ar_file_offset; // file offset in bytes from the beginning of the file of the object data
+        lldb::offset_t  ar_file_size;   // length of the object data
+
+        typedef std::vector<Object>         collection;
+        typedef collection::iterator        iterator;
+        typedef collection::const_iterator  const_iterator;
+    };
+
+    class Archive
+    {
+    public:
+        typedef std::shared_ptr<Archive> shared_ptr;
+        typedef std::multimap<lldb_private::FileSpec, shared_ptr> Map;
+
+        static Map &
+        GetArchiveCache ();
+
+        static lldb_private::Mutex &
+        GetArchiveCacheMutex ();
+
+        static Archive::shared_ptr
+        FindCachedArchive (const lldb_private::FileSpec &file,
+                           const lldb_private::ArchSpec &arch,
+                           const lldb_private::TimeValue &mod_time,
+                           lldb::offset_t file_offset);
+
+        static Archive::shared_ptr
+        ParseAndCacheArchiveForFile (const lldb_private::FileSpec &file,
+                                     const lldb_private::ArchSpec &arch,
+                                     const lldb_private::TimeValue &mod_time,
+                                     lldb::offset_t file_offset,
+                                     lldb_private::DataExtractor &data);
+
+        Archive (const lldb_private::ArchSpec &arch,
+                 const lldb_private::TimeValue &mod_time,
+                 lldb::offset_t file_offset,
+                 lldb_private::DataExtractor &data);
+
+        ~Archive ();
+
+        size_t
+        GetNumObjects () const
+        {
+            return m_objects.size();
+        }
+
+        const Object *
+        GetObjectAtIndex (size_t idx)
+        {
+            if (idx < m_objects.size())
+                return &m_objects[idx];
+            return NULL;
+        }
+
+        size_t
+        ParseObjects ();
+
+        Object *
+        FindObject (const lldb_private::ConstString &object_name,
+                    const lldb_private::TimeValue &object_mod_time);
+
+        lldb::offset_t
+        GetFileOffset () const
+        {
+            return m_file_offset;
+        }
+
+        const lldb_private::TimeValue &
+        GetModificationTime()
+        {
+            return m_time;
+        }
+
+        const lldb_private::ArchSpec &
+        GetArchitecture () const
+        {
+            return m_arch;
+        }
+
+        void
+        SetArchitecture (const lldb_private::ArchSpec &arch)
+        {
+            m_arch = arch;
+        }
+
+        bool
+        HasNoExternalReferences() const;
+
+        lldb_private::DataExtractor &
+        GetData ()
+        {
+            return m_data;
+        }
+
+    protected:
+        typedef lldb_private::UniqueCStringMap<uint32_t> ObjectNameToIndexMap;
+        //----------------------------------------------------------------------
+        // Member Variables
+        //----------------------------------------------------------------------
+        lldb_private::ArchSpec m_arch;
+        lldb_private::TimeValue m_time;
+        lldb::offset_t m_file_offset;
+        Object::collection m_objects;
+        ObjectNameToIndexMap m_object_name_to_index_map;
+        lldb_private::DataExtractor m_data; ///< The data for this object container so we don't lose data if the .a files gets modified
+    };
+
+    void
+    SetArchive (Archive::shared_ptr &archive_sp);
+
+    Archive::shared_ptr m_archive_sp;
+};
+
+#endif  // liblldb_ObjectContainerBSDArchive_h_
diff --git a/source/Plugins/ObjectFile/ELF/ELFHeader.cpp b/source/Plugins/ObjectFile/ELF/ELFHeader.cpp
new file mode 100644
index 000000000000..a63a01d7ed7a
--- /dev/null
+++ b/source/Plugins/ObjectFile/ELF/ELFHeader.cpp
@@ -0,0 +1,465 @@
+//===-- ELFHeader.cpp ----------------------------------------- -*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <cstring>
+
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Section.h"
+#include "lldb/Core/Stream.h"
+
+#include "ELFHeader.h"
+
+using namespace elf;
+using namespace lldb;
+using namespace llvm::ELF;
+
+//------------------------------------------------------------------------------
+// Static utility functions.
+//
+// GetMaxU64 and GetMaxS64 wrap the similarly named methods from DataExtractor
+// with error handling code and provide for parsing a sequence of values.
+static bool
+GetMaxU64(const lldb_private::DataExtractor &data,
+          lldb::offset_t *offset,
+          uint64_t *value,
+          uint32_t byte_size)
+{
+    const lldb::offset_t saved_offset = *offset;
+    *value = data.GetMaxU64(offset, byte_size);
+    return *offset != saved_offset;
+}
+
+static bool
+GetMaxU64(const lldb_private::DataExtractor &data, 
+          lldb::offset_t *offset,
+          uint64_t *value,
+          uint32_t byte_size,
+          uint32_t count) 
+{
+    lldb::offset_t saved_offset = *offset;
+
+    for (uint32_t i = 0; i < count; ++i, ++value)
+    {
+        if (GetMaxU64(data, offset, value, byte_size) == false) 
+        {
+            *offset = saved_offset;
+            return false;
+        }
+    }
+    return true;
+}
+
+static bool
+GetMaxS64(const lldb_private::DataExtractor &data, 
+          lldb::offset_t *offset,
+          int64_t *value,
+          uint32_t byte_size)
+{
+    const lldb::offset_t saved_offset = *offset;
+    *value = data.GetMaxS64(offset, byte_size);
+    return *offset != saved_offset;
+}
+
+static bool
+GetMaxS64(const lldb_private::DataExtractor &data, 
+          lldb::offset_t *offset,
+          int64_t *value,
+          uint32_t byte_size,
+          uint32_t count) 
+{
+    lldb::offset_t saved_offset = *offset;
+
+    for (uint32_t i = 0; i < count; ++i, ++value)
+    {
+        if (GetMaxS64(data, offset, value, byte_size) == false) 
+        {
+            *offset = saved_offset;
+            return false;
+        }
+    }
+    return true;
+}
+
+//------------------------------------------------------------------------------
+// ELFHeader
+
+ELFHeader::ELFHeader()
+{
+    memset(this, 0, sizeof(ELFHeader)); 
+}
+
+ByteOrder
+ELFHeader::GetByteOrder() const 
+{
+    if (e_ident[EI_DATA] == ELFDATA2MSB)
+        return eByteOrderBig;
+    if (e_ident[EI_DATA] == ELFDATA2LSB)
+        return eByteOrderLittle;
+    return eByteOrderInvalid;
+}
+
+bool
+ELFHeader::Parse(lldb_private::DataExtractor &data, lldb::offset_t *offset) 
+{
+    // Read e_ident.  This provides byte order and address size info.
+    if (data.GetU8(offset, &e_ident, EI_NIDENT) == NULL)
+        return false;
+
+    const unsigned byte_size = Is32Bit() ? 4 : 8;
+    data.SetByteOrder(GetByteOrder());
+    data.SetAddressByteSize(byte_size);
+
+    // Read e_type and e_machine.
+    if (data.GetU16(offset, &e_type, 2) == NULL)
+        return false;
+
+    // Read e_version.
+    if (data.GetU32(offset, &e_version, 1) == NULL)
+        return false;
+
+    // Read e_entry, e_phoff and e_shoff.
+    if (GetMaxU64(data, offset, &e_entry, byte_size, 3) == false)
+        return false;
+
+    // Read e_flags.
+    if (data.GetU32(offset, &e_flags, 1) == NULL)
+        return false;
+
+    // Read e_ehsize, e_phentsize, e_phnum, e_shentsize, e_shnum and
+    // e_shstrndx.
+    if (data.GetU16(offset, &e_ehsize, 6) == NULL)
+        return false;
+
+    return true;
+}
+
+bool
+ELFHeader::MagicBytesMatch(const uint8_t *magic)
+{
+    return memcmp(magic, ElfMagic, strlen(ElfMagic)) == 0;
+}
+
+unsigned
+ELFHeader::AddressSizeInBytes(const uint8_t *magic)
+{
+    unsigned address_size = 0;
+
+    switch (magic[EI_CLASS]) 
+    {
+    case ELFCLASS32:
+        address_size = 4;
+        break;
+            
+    case ELFCLASS64:
+        address_size = 8;
+        break;
+    }
+    return address_size;
+}
+
+unsigned
+ELFHeader::GetRelocationJumpSlotType() const
+{
+    unsigned slot = 0;
+
+    switch (e_machine)
+    {
+    default:
+        assert(false && "architecture not supported");
+        break;
+    case EM_386:
+    case EM_486:
+        slot = R_386_JUMP_SLOT;
+        break;
+    case EM_X86_64:
+        slot = R_X86_64_JUMP_SLOT;
+        break;
+    case EM_ARM:
+        slot = R_ARM_JUMP_SLOT;
+        break;
+    }
+
+    return slot;
+}
+
+//------------------------------------------------------------------------------
+// ELFSectionHeader
+
+ELFSectionHeader::ELFSectionHeader() 
+{
+    memset(this, 0, sizeof(ELFSectionHeader));
+}
+
+bool
+ELFSectionHeader::Parse(const lldb_private::DataExtractor &data,
+                        lldb::offset_t *offset)
+{
+    const unsigned byte_size = data.GetAddressByteSize();
+
+    // Read sh_name and sh_type.
+    if (data.GetU32(offset, &sh_name, 2) == NULL)
+        return false;
+
+    // Read sh_flags.
+    if (GetMaxU64(data, offset, &sh_flags, byte_size) == false)
+        return false;
+
+    // Read sh_addr, sh_off and sh_size.
+    if (GetMaxU64(data, offset, &sh_addr, byte_size, 3) == false)
+        return false;
+
+    // Read sh_link and sh_info.
+    if (data.GetU32(offset, &sh_link, 2) == NULL)
+        return false;
+
+    // Read sh_addralign and sh_entsize.
+    if (GetMaxU64(data, offset, &sh_addralign, byte_size, 2) == false)
+        return false;
+
+    return true;
+}
+
+//------------------------------------------------------------------------------
+// ELFSymbol
+
+ELFSymbol::ELFSymbol() 
+{
+    memset(this, 0, sizeof(ELFSymbol));
+}
+
+#define ENUM_TO_CSTR(e) case e: return #e
+
+const char *
+ELFSymbol::bindingToCString(unsigned char binding)
+{
+    switch (binding)
+    {
+    ENUM_TO_CSTR(STB_LOCAL);
+    ENUM_TO_CSTR(STB_GLOBAL);
+    ENUM_TO_CSTR(STB_WEAK);
+    ENUM_TO_CSTR(STB_LOOS);
+    ENUM_TO_CSTR(STB_HIOS);
+    ENUM_TO_CSTR(STB_LOPROC);
+    ENUM_TO_CSTR(STB_HIPROC);
+    }
+    return "";
+}
+
+const char *
+ELFSymbol::typeToCString(unsigned char type)
+{
+    switch (type)
+    {
+    ENUM_TO_CSTR(STT_NOTYPE);
+    ENUM_TO_CSTR(STT_OBJECT);
+    ENUM_TO_CSTR(STT_FUNC);
+    ENUM_TO_CSTR(STT_SECTION);
+    ENUM_TO_CSTR(STT_FILE);
+    ENUM_TO_CSTR(STT_COMMON);
+    ENUM_TO_CSTR(STT_TLS);
+    ENUM_TO_CSTR(STT_LOOS);
+    ENUM_TO_CSTR(STT_HIOS);
+    ENUM_TO_CSTR(STT_GNU_IFUNC);
+    ENUM_TO_CSTR(STT_LOPROC);
+    ENUM_TO_CSTR(STT_HIPROC);
+    }
+    return "";
+}
+
+const char *
+ELFSymbol::sectionIndexToCString (elf_half shndx,
+                                  const lldb_private::SectionList *section_list)
+{
+    switch (shndx)
+    {
+    ENUM_TO_CSTR(SHN_UNDEF);
+    ENUM_TO_CSTR(SHN_LOPROC);
+    ENUM_TO_CSTR(SHN_HIPROC);
+    ENUM_TO_CSTR(SHN_LOOS);
+    ENUM_TO_CSTR(SHN_HIOS);
+    ENUM_TO_CSTR(SHN_ABS);
+    ENUM_TO_CSTR(SHN_COMMON);
+    ENUM_TO_CSTR(SHN_XINDEX);
+    default:
+        {
+            const lldb_private::Section *section = section_list->GetSectionAtIndex(shndx).get();
+            if (section)
+                return section->GetName().AsCString("");
+        }
+        break;
+    }
+    return "";
+}
+
+void
+ELFSymbol::Dump (lldb_private::Stream *s,
+                 uint32_t idx,
+                 const lldb_private::DataExtractor *strtab_data,
+                 const lldb_private::SectionList *section_list)
+{
+    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,
+              st_name,
+              st_info,
+              bindingToCString (getBinding()),
+              typeToCString (getType()),
+              st_other,
+              st_shndx,
+              sectionIndexToCString (st_shndx, section_list),
+              strtab_data ? strtab_data->PeekCStr(st_name) : "");
+}
+
+bool
+ELFSymbol::Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset)
+{
+    const unsigned byte_size = data.GetAddressByteSize();
+    const bool parsing_32 = byte_size == 4;
+
+    // Read st_name.
+    if (data.GetU32(offset, &st_name, 1) == NULL)
+        return false;
+
+    if (parsing_32) 
+    {
+        // Read st_value and st_size.
+        if (GetMaxU64(data, offset, &st_value, byte_size, 2) == false)
+            return false;
+
+        // Read st_info and st_other.
+        if (data.GetU8(offset, &st_info, 2) == NULL)
+            return false;
+            
+        // Read st_shndx.
+        if (data.GetU16(offset, &st_shndx, 1) == NULL)
+            return false;
+    }
+    else 
+    {
+        // Read st_info and st_other.
+        if (data.GetU8(offset, &st_info, 2) == NULL)
+            return false;
+            
+        // Read st_shndx.
+        if (data.GetU16(offset, &st_shndx, 1) == NULL)
+            return false;
+
+        // Read st_value and st_size.
+        if (data.GetU64(offset, &st_value, 2) == NULL)
+            return false;
+    }
+    return true;
+}
+
+//------------------------------------------------------------------------------
+// ELFProgramHeader
+
+ELFProgramHeader::ELFProgramHeader() 
+{
+    memset(this, 0, sizeof(ELFProgramHeader));
+}
+
+bool
+ELFProgramHeader::Parse(const lldb_private::DataExtractor &data, 
+                        lldb::offset_t *offset)
+{
+    const uint32_t byte_size = data.GetAddressByteSize();
+    const bool parsing_32 = byte_size == 4;
+
+    // Read p_type;
+    if (data.GetU32(offset, &p_type, 1) == NULL)
+        return false;
+
+    if (parsing_32) {
+        // Read p_offset, p_vaddr, p_paddr, p_filesz and p_memsz.
+        if (GetMaxU64(data, offset, &p_offset, byte_size, 5) == false)
+            return false;
+
+        // Read p_flags.
+        if (data.GetU32(offset, &p_flags, 1) == NULL)
+            return false;
+
+        // Read p_align.
+        if (GetMaxU64(data, offset, &p_align, byte_size) == false)
+            return false;
+    }
+    else {
+        // Read p_flags.
+        if (data.GetU32(offset, &p_flags, 1) == NULL)
+            return false;
+
+        // Read p_offset, p_vaddr, p_paddr, p_filesz, p_memsz and p_align.
+        if (GetMaxU64(data, offset, &p_offset, byte_size, 6) == false)
+            return false;
+    }
+
+    return true;
+}
+
+//------------------------------------------------------------------------------
+// ELFDynamic
+
+ELFDynamic::ELFDynamic() 
+{ 
+    memset(this, 0, sizeof(ELFDynamic)); 
+}
+
+bool
+ELFDynamic::Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset)
+{
+    const unsigned byte_size = data.GetAddressByteSize();
+    return GetMaxS64(data, offset, &d_tag, byte_size, 2);
+}
+
+//------------------------------------------------------------------------------
+// ELFRel
+
+ELFRel::ELFRel()
+{
+    memset(this, 0, sizeof(ELFRel));
+}
+
+bool
+ELFRel::Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset)
+{
+    const unsigned byte_size = data.GetAddressByteSize();
+
+    // Read r_offset and r_info.
+    if (GetMaxU64(data, offset, &r_offset, byte_size, 2) == false)
+        return false;
+
+    return true;
+}
+
+//------------------------------------------------------------------------------
+// ELFRela
+
+ELFRela::ELFRela()
+{
+    memset(this, 0, sizeof(ELFRela));
+}
+
+bool
+ELFRela::Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset)
+{
+    const unsigned byte_size = data.GetAddressByteSize();
+
+    // Read r_offset and r_info.
+    if (GetMaxU64(data, offset, &r_offset, byte_size, 2) == false)
+        return false;
+
+    // Read r_addend;
+    if (GetMaxS64(data, offset, &r_addend, byte_size) == false)
+        return false;
+
+    return true;
+}
+
+
diff --git a/source/Plugins/ObjectFile/ELF/ELFHeader.h b/source/Plugins/ObjectFile/ELF/ELFHeader.h
new file mode 100644
index 000000000000..aa2c16b6168c
--- /dev/null
+++ b/source/Plugins/ObjectFile/ELF/ELFHeader.h
@@ -0,0 +1,433 @@
+//===-- ELFHeader.h ------------------------------------------- -*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+/// @file
+/// @brief Generic structures and typedefs for ELF files.
+///
+/// This file provides definitions for the various entities comprising an ELF
+/// file.  The structures are generic in the sense that they do not correspond
+/// to the exact binary layout of an ELF, but can be used to hold the
+/// information present in both 32 and 64 bit variants of the format.  Each
+/// entity provides a \c Parse method which is capable of transparently reading
+/// both 32 and 64 bit instances of the object.
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ELFHeader_h_
+#define liblldb_ELFHeader_h_
+
+#include "llvm/Support/ELF.h"
+
+#include "lldb/lldb-enumerations.h"
+
+namespace lldb_private
+{
+class DataExtractor;
+} // End namespace lldb_private.
+
+namespace elf 
+{
+
+//------------------------------------------------------------------------------
+/// @name ELF type definitions.
+///
+/// Types used to represent the various components of ELF structures.  All types
+/// are signed or unsigned integral types wide enough to hold values from both
+/// 32 and 64 bit ELF variants.
+//@{
+typedef uint64_t elf_addr;
+typedef uint64_t elf_off;
+typedef uint16_t elf_half;
+typedef uint32_t elf_word;
+typedef int32_t  elf_sword;
+typedef uint64_t elf_size;
+typedef uint64_t elf_xword;
+typedef int64_t  elf_sxword;
+//@}
+
+//------------------------------------------------------------------------------
+/// @class ELFHeader
+/// @brief Generic representation of an ELF file header.
+///
+/// This object is used to identify the general attributes on an ELF file and to
+/// locate additional sections within the file.
+struct ELFHeader 
+{
+    unsigned char e_ident[llvm::ELF::EI_NIDENT]; ///< ELF file identification.
+    elf_addr      e_entry;            ///< Virtual address program entry point.
+    elf_off       e_phoff;            ///< File offset of program header table.
+    elf_off       e_shoff;            ///< File offset of section header table.
+    elf_word      e_flags;            ///< Processor specific flags.
+    elf_word      e_version;          ///< Version of object file (always 1).
+    elf_half      e_type;             ///< Object file type.
+    elf_half      e_machine;          ///< Target architecture.
+    elf_half      e_ehsize;           ///< Byte size of the ELF header.
+    elf_half      e_phentsize;        ///< Size of a program header table entry.
+    elf_half      e_phnum;            ///< Number of program header entries.
+    elf_half      e_shentsize;        ///< Size of a section header table entry.
+    elf_half      e_shnum;            ///< Number of section header entries.
+    elf_half      e_shstrndx;         ///< String table section index.
+
+    ELFHeader();
+
+    //--------------------------------------------------------------------------
+    /// Returns true if this is a 32 bit ELF file header.
+    ///
+    /// @return
+    ///    True if this is a 32 bit ELF file header.
+    bool Is32Bit() const { 
+        return e_ident[llvm::ELF::EI_CLASS] == llvm::ELF::ELFCLASS32; 
+    }
+
+    //--------------------------------------------------------------------------
+    /// Returns true if this is a 64 bit ELF file header.
+    ///
+    /// @return
+    ///   True if this is a 64 bit ELF file header.
+    bool Is64Bit() const { 
+        return e_ident[llvm::ELF::EI_CLASS] == llvm::ELF::ELFCLASS64; 
+    }
+
+    //--------------------------------------------------------------------------
+    /// The byte order of this ELF file header.
+    ///
+    /// @return
+    ///    The byte order of this ELF file as described by the header.
+    lldb::ByteOrder
+    GetByteOrder() const;
+
+    //--------------------------------------------------------------------------
+    /// The jump slot relocation type of this ELF.
+    unsigned
+    GetRelocationJumpSlotType() const;
+
+    //--------------------------------------------------------------------------
+    /// 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.
+    ///
+    /// @param[in,out] data
+    ///    The DataExtractor to read from.  Updated with the address size and
+    ///    byte order attributes appropriate to this header.
+    ///
+    /// @param[in,out] offset
+    ///    Pointer to an offset in the data.  On return the offset will be
+    ///    advanced by the number of bytes read.
+    ///
+    /// @return
+    ///    True if the ELFHeader was successfully read and false
+    ///    otherwise.
+    bool
+    Parse(lldb_private::DataExtractor &data, lldb::offset_t *offset);
+
+    //--------------------------------------------------------------------------
+    /// Examines at most EI_NIDENT bytes starting from the given pointer and
+    /// determines if the magic ELF identification exists.
+    ///
+    /// @return
+    ///    True if the given sequence of bytes identifies an ELF file.
+    static bool
+    MagicBytesMatch(const uint8_t *magic);
+
+    //--------------------------------------------------------------------------
+    /// Examines at most EI_NIDENT bytes starting from the given address and
+    /// determines the address size of the underlying ELF file.  This function
+    /// should only be called on an pointer for which MagicBytesMatch returns
+    /// true.
+    ///
+    /// @return
+    ///    The number of bytes forming an address in the ELF file (either 4 or
+    ///    8), else zero if the address size could not be determined.
+    static unsigned
+    AddressSizeInBytes(const uint8_t *magic);
+};
+
+//------------------------------------------------------------------------------
+/// @class ELFSectionHeader
+/// @brief Generic representation of an ELF section header.
+struct ELFSectionHeader 
+{
+    elf_word  sh_name;          ///< Section name string index.
+    elf_word  sh_type;          ///< Section type.
+    elf_xword sh_flags;         ///< Section attributes. 
+    elf_addr  sh_addr;          ///< Virtual address of the section in memory.
+    elf_off   sh_offset;        ///< Start of section from beginning of file.
+    elf_xword sh_size;          ///< Number of bytes occupied in the file.
+    elf_word  sh_link;          ///< Index of associated section.
+    elf_word  sh_info;          ///< Extra section info (overloaded).
+    elf_xword sh_addralign;     ///< Power of two alignment constraint.
+    elf_xword sh_entsize;       ///< Byte size of each section entry.
+
+    ELFSectionHeader();
+
+    //--------------------------------------------------------------------------
+    /// Parse an ELFSectionHeader entry from the given DataExtracter starting at
+    /// position \p offset.
+    ///
+    /// @param[in] data
+    ///    The DataExtractor to read from.  The address size of the extractor
+    ///    determines if a 32 or 64 bit object should be read.
+    ///
+    /// @param[in,out] offset
+    ///    Pointer to an offset in the data.  On return the offset will be
+    ///    advanced by the number of bytes read.
+    ///
+    /// @return
+    ///    True if the ELFSectionHeader was successfully read and false
+    ///    otherwise.
+    bool
+    Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset);
+};
+
+//------------------------------------------------------------------------------
+/// @class ELFProgramHeader
+/// @brief Generic representation of an ELF program header.
+struct ELFProgramHeader
+{
+    elf_word  p_type;           ///< Type of program segment.
+    elf_word  p_flags;          ///< Segment attributes.
+    elf_off   p_offset;         ///< Start of segment from beginning of file.
+    elf_addr  p_vaddr;          ///< Virtual address of segment in memory.
+    elf_addr  p_paddr;          ///< Physical address (for non-VM systems). 
+    elf_xword p_filesz;         ///< Byte size of the segment in file.
+    elf_xword p_memsz;          ///< Byte size of the segment in memory.
+    elf_xword p_align;          ///< Segment alignment constraint.
+
+    ELFProgramHeader();
+
+    /// Parse an ELFProgramHeader entry from the given DataExtractor starting at
+    /// position \p offset.  The address size of the DataExtractor determines if
+    /// a 32 or 64 bit object is to be parsed.
+    ///
+    /// @param[in] data
+    ///    The DataExtractor to read from.  The address size of the extractor
+    ///    determines if a 32 or 64 bit object should be read.
+    ///
+    /// @param[in,out] offset
+    ///    Pointer to an offset in the data.  On return the offset will be
+    ///    advanced by the number of bytes read.
+    ///
+    /// @return
+    ///    True if the ELFProgramHeader was successfully read and false
+    ///    otherwise.
+    bool
+    Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset);
+};
+
+//------------------------------------------------------------------------------
+/// @class ELFSymbol
+/// @brief Represents a symbol within an ELF symbol table.
+struct ELFSymbol
+{
+    elf_addr      st_value;     ///< Absolute or relocatable address.
+    elf_xword     st_size;      ///< Size of the symbol or zero.
+    elf_word      st_name;      ///< Symbol name string index.
+    unsigned char st_info;      ///< Symbol type and binding attributes.
+    unsigned char st_other;     ///< Reserved for future use.
+    elf_half      st_shndx;     ///< Section to which this symbol applies.
+
+    ELFSymbol();
+
+    /// Returns the binding attribute of the st_info member.
+    unsigned char getBinding() const { return st_info >> 4; }
+
+    /// Returns the type attribute of the st_info member.
+    unsigned char getType() const { return st_info & 0x0F; }
+
+    /// Sets the binding and type of the st_info member.
+    void setBindingAndType(unsigned char binding, unsigned char type) {
+        st_info = (binding << 4) + (type & 0x0F);
+    }
+
+    static const char *
+    bindingToCString(unsigned char binding);
+
+    static const char *
+    typeToCString(unsigned char type);
+
+    static const char *
+    sectionIndexToCString(elf_half shndx,
+                          const lldb_private::SectionList *section_list);
+
+    /// Parse an ELFSymbol entry from the given DataExtractor starting at
+    /// position \p offset.  The address size of the DataExtractor determines if
+    /// a 32 or 64 bit object is to be parsed.
+    ///
+    /// @param[in] data
+    ///    The DataExtractor to read from.  The address size of the extractor
+    ///    determines if a 32 or 64 bit object should be read.
+    ///
+    /// @param[in,out] offset
+    ///    Pointer to an offset in the data.  On return the offset will be
+    ///    advanced by the number of bytes read.
+    ///
+    /// @return
+    ///    True if the ELFSymbol was successfully read and false otherwise.
+    bool
+    Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset);
+    
+    void
+    Dump (lldb_private::Stream *s,
+          uint32_t idx,
+          const lldb_private::DataExtractor *strtab_data,
+          const lldb_private::SectionList *section_list);
+};
+
+//------------------------------------------------------------------------------
+/// @class ELFDynamic
+/// @brief Represents an entry in an ELF dynamic table.
+struct ELFDynamic
+{
+    elf_sxword d_tag;           ///< Type of dynamic table entry.
+    union
+    {
+        elf_xword d_val;        ///< Integer value of the table entry.
+        elf_addr  d_ptr;        ///< Pointer value of the table entry.
+    };
+
+    ELFDynamic();
+
+    /// Parse an ELFDynamic entry from the given DataExtractor starting at
+    /// position \p offset.  The address size of the DataExtractor determines if
+    /// a 32 or 64 bit object is to be parsed.
+    ///
+    /// @param[in] data
+    ///    The DataExtractor to read from.  The address size of the extractor
+    ///    determines if a 32 or 64 bit object should be read.
+    ///
+    /// @param[in,out] offset
+    ///    Pointer to an offset in the data.  On return the offset will be
+    ///    advanced by the number of bytes read.
+    ///
+    /// @return
+    ///    True if the ELFDynamic entry was successfully read and false
+    ///    otherwise.
+    bool
+    Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset);
+};
+
+//------------------------------------------------------------------------------
+/// @class ELFRel
+/// @brief Represents a relocation entry with an implicit addend.
+struct ELFRel
+{
+    elf_addr  r_offset;         ///< Address of reference.
+    elf_xword r_info;           ///< symbol index and type of relocation.
+
+    ELFRel();
+
+    /// Parse an ELFRel entry from the given DataExtractor starting at position
+    /// \p offset.  The address size of the DataExtractor determines if a 32 or
+    /// 64 bit object is to be parsed.
+    ///
+    /// @param[in] data
+    ///    The DataExtractor to read from.  The address size of the extractor
+    ///    determines if a 32 or 64 bit object should be read.
+    ///
+    /// @param[in,out] offset
+    ///    Pointer to an offset in the data.  On return the offset will be
+    ///    advanced by the number of bytes read.
+    ///
+    /// @return
+    ///    True if the ELFRel entry was successfully read and false otherwise.
+    bool
+    Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset);
+
+    /// Returns the type when the given entry represents a 32-bit relocation.
+    static unsigned
+    RelocType32(const ELFRel &rel)
+    {
+        return rel.r_info & 0x0ff;
+    }
+
+    /// Returns the type when the given entry represents a 64-bit relocation.
+    static unsigned
+    RelocType64(const ELFRel &rel)
+    {
+        return rel.r_info & 0xffffffff;
+    }
+
+    /// Returns the symbol index when the given entry represents a 32-bit
+    /// reloction.
+    static unsigned
+    RelocSymbol32(const ELFRel &rel)
+    {
+        return rel.r_info >> 8;
+    }
+
+    /// Returns the symbol index when the given entry represents a 64-bit
+    /// reloction.
+    static unsigned
+    RelocSymbol64(const ELFRel &rel)
+    {
+        return rel.r_info >> 32;
+    }
+};
+
+//------------------------------------------------------------------------------
+/// @class ELFRela
+/// @brief Represents a relocation entry with an explicit addend.
+struct ELFRela
+{
+    elf_addr   r_offset;        ///< Address of reference.
+    elf_xword  r_info;          ///< Symbol index and type of relocation.
+    elf_sxword r_addend;        ///< Constant part of expression.
+
+    ELFRela();
+
+    /// Parse an ELFRela entry from the given DataExtractor starting at position
+    /// \p offset.  The address size of the DataExtractor determines if a 32 or
+    /// 64 bit object is to be parsed.
+    ///
+    /// @param[in] data
+    ///    The DataExtractor to read from.  The address size of the extractor
+    ///    determines if a 32 or 64 bit object should be read.
+    ///
+    /// @param[in,out] offset
+    ///    Pointer to an offset in the data.  On return the offset will be
+    ///    advanced by the number of bytes read.
+    ///
+    /// @return
+    ///    True if the ELFRela entry was successfully read and false otherwise.
+    bool
+    Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset);
+
+    /// Returns the type when the given entry represents a 32-bit relocation.
+    static unsigned
+    RelocType32(const ELFRela &rela)
+    {
+        return rela.r_info & 0x0ff;
+    }
+
+    /// Returns the type when the given entry represents a 64-bit relocation.
+    static unsigned
+    RelocType64(const ELFRela &rela)
+    {
+        return rela.r_info & 0xffffffff;
+    }
+
+    /// Returns the symbol index when the given entry represents a 32-bit
+    /// reloction.
+    static unsigned
+    RelocSymbol32(const ELFRela &rela)
+    {
+        return rela.r_info >> 8;
+    }
+
+    /// Returns the symbol index when the given entry represents a 64-bit
+    /// reloction.
+    static unsigned
+    RelocSymbol64(const ELFRela &rela)
+    {
+        return rela.r_info >> 32;
+    }
+};
+
+} // End namespace elf.
+
+#endif // #ifndef liblldb_ELFHeader_h_
diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
new file mode 100644
index 000000000000..2e9f6903280c
--- /dev/null
+++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -0,0 +1,1893 @@
+//===-- ObjectFileELF.cpp ------------------------------------- -*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ObjectFileELF.h"
+
+#include <cassert>
+#include <algorithm>
+
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/DataBuffer.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/FileSpecList.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Section.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Host/Host.h"
+
+#include "llvm/ADT/PointerUnion.h"
+
+#define CASE_AND_STREAM(s, def, width)                  \
+    case def: s->Printf("%-*s", width, #def); break;
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace elf;
+using namespace llvm::ELF;
+
+namespace {
+//===----------------------------------------------------------------------===//
+/// @class ELFRelocation
+/// @brief Generic wrapper for ELFRel and ELFRela.
+///
+/// This helper class allows us to parse both ELFRel and ELFRela relocation
+/// entries in a generic manner.
+class ELFRelocation
+{
+public:
+
+    /// Constructs an ELFRelocation entry with a personality as given by @p
+    /// type.
+    ///
+    /// @param type Either DT_REL or DT_RELA.  Any other value is invalid.
+    ELFRelocation(unsigned type);
+ 
+    ~ELFRelocation();
+
+    bool
+    Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset);
+
+    static unsigned
+    RelocType32(const ELFRelocation &rel);
+
+    static unsigned
+    RelocType64(const ELFRelocation &rel);
+
+    static unsigned
+    RelocSymbol32(const ELFRelocation &rel);
+
+    static unsigned
+    RelocSymbol64(const ELFRelocation &rel);
+
+private:
+    typedef llvm::PointerUnion<ELFRel*, ELFRela*> RelocUnion;
+
+    RelocUnion reloc;
+};
+
+ELFRelocation::ELFRelocation(unsigned type)
+{ 
+    if (type == DT_REL)
+        reloc = new ELFRel();
+    else if (type == DT_RELA)
+        reloc = new ELFRela();
+    else {
+        assert(false && "unexpected relocation type");
+        reloc = static_cast<ELFRel*>(NULL);
+    }
+}
+
+ELFRelocation::~ELFRelocation()
+{
+    if (reloc.is<ELFRel*>())
+        delete reloc.get<ELFRel*>();
+    else
+        delete reloc.get<ELFRela*>();            
+}
+
+bool
+ELFRelocation::Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset)
+{
+    if (reloc.is<ELFRel*>())
+        return reloc.get<ELFRel*>()->Parse(data, offset);
+    else
+        return reloc.get<ELFRela*>()->Parse(data, offset);
+}
+
+unsigned
+ELFRelocation::RelocType32(const ELFRelocation &rel)
+{
+    if (rel.reloc.is<ELFRel*>())
+        return ELFRel::RelocType32(*rel.reloc.get<ELFRel*>());
+    else
+        return ELFRela::RelocType32(*rel.reloc.get<ELFRela*>());
+}
+
+unsigned
+ELFRelocation::RelocType64(const ELFRelocation &rel)
+{
+    if (rel.reloc.is<ELFRel*>())
+        return ELFRel::RelocType64(*rel.reloc.get<ELFRel*>());
+    else
+        return ELFRela::RelocType64(*rel.reloc.get<ELFRela*>());
+}
+
+unsigned
+ELFRelocation::RelocSymbol32(const ELFRelocation &rel)
+{
+    if (rel.reloc.is<ELFRel*>())
+        return ELFRel::RelocSymbol32(*rel.reloc.get<ELFRel*>());
+    else
+        return ELFRela::RelocSymbol32(*rel.reloc.get<ELFRela*>());
+}
+
+unsigned
+ELFRelocation::RelocSymbol64(const ELFRelocation &rel)
+{
+    if (rel.reloc.is<ELFRel*>())
+        return ELFRel::RelocSymbol64(*rel.reloc.get<ELFRel*>());
+    else
+        return ELFRela::RelocSymbol64(*rel.reloc.get<ELFRela*>());
+}
+
+} // end anonymous namespace
+
+//------------------------------------------------------------------
+// Static methods.
+//------------------------------------------------------------------
+void
+ObjectFileELF::Initialize()
+{
+    PluginManager::RegisterPlugin(GetPluginNameStatic(),
+                                  GetPluginDescriptionStatic(),
+                                  CreateInstance,
+                                  CreateMemoryInstance,
+                                  GetModuleSpecifications);
+}
+
+void
+ObjectFileELF::Terminate()
+{
+    PluginManager::UnregisterPlugin(CreateInstance);
+}
+
+lldb_private::ConstString
+ObjectFileELF::GetPluginNameStatic()
+{
+    static ConstString g_name("elf");
+    return g_name;
+}
+
+const char *
+ObjectFileELF::GetPluginDescriptionStatic()
+{
+    return "ELF object file reader.";
+}
+
+ObjectFile *
+ObjectFileELF::CreateInstance (const lldb::ModuleSP &module_sp,
+                               DataBufferSP &data_sp,
+                               lldb::offset_t data_offset,
+                               const lldb_private::FileSpec* file,
+                               lldb::offset_t file_offset,
+                               lldb::offset_t length)
+{
+    if (!data_sp)
+    {
+        data_sp = file->MemoryMapFileContents(file_offset, length);
+        data_offset = 0;
+    }
+
+    if (data_sp && data_sp->GetByteSize() > (llvm::ELF::EI_NIDENT + data_offset))
+    {
+        const uint8_t *magic = data_sp->GetBytes() + data_offset;
+        if (ELFHeader::MagicBytesMatch(magic))
+        {
+            // Update the data to contain the entire file if it doesn't already
+            if (data_sp->GetByteSize() < length) {
+                data_sp = file->MemoryMapFileContents(file_offset, length);
+                data_offset = 0;
+                magic = data_sp->GetBytes();
+            }
+            unsigned address_size = ELFHeader::AddressSizeInBytes(magic);
+            if (address_size == 4 || address_size == 8)
+            {
+                std::unique_ptr<ObjectFileELF> objfile_ap(new ObjectFileELF(module_sp, data_sp, data_offset, file, file_offset, length));
+                ArchSpec spec;
+                if (objfile_ap->GetArchitecture(spec) &&
+                    objfile_ap->SetModulesArchitecture(spec))
+                    return objfile_ap.release();
+            }
+        }
+    }
+    return NULL;
+}
+
+
+ObjectFile*
+ObjectFileELF::CreateMemoryInstance (const lldb::ModuleSP &module_sp, 
+                                     DataBufferSP& data_sp, 
+                                     const lldb::ProcessSP &process_sp, 
+                                     lldb::addr_t header_addr)
+{
+    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;
+}
+
+/*
+ * crc function from http://svnweb.freebsd.org/base/head/sys/libkern/crc32.c
+ *
+ *   COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or
+ *   code or tables extracted from it, as desired without restriction.
+ */
+static uint32_t
+calc_gnu_debuglink_crc32(const void *buf, size_t size)
+{
+    static const uint32_t g_crc32_tab[] =
+    {
+        0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
+        0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+        0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
+        0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+        0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
+        0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+        0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
+        0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+        0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
+        0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+        0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
+        0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+        0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
+        0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+        0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
+        0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+        0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
+        0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+        0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
+        0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+        0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
+        0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+        0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
+        0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+        0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
+        0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+        0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
+        0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+        0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
+        0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+        0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
+        0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+        0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
+        0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+        0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
+        0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+        0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
+        0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+        0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
+        0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+        0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
+        0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+        0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
+    };    
+    const uint8_t *p = (const uint8_t *)buf;
+    uint32_t crc;
+
+    crc = ~0U;
+    while (size--)
+        crc = g_crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
+    return crc ^ ~0U;
+}
+
+size_t
+ObjectFileELF::GetModuleSpecifications (const lldb_private::FileSpec& file,
+                                        lldb::DataBufferSP& data_sp,
+                                        lldb::offset_t data_offset,
+                                        lldb::offset_t file_offset,
+                                        lldb::offset_t length,
+                                        lldb_private::ModuleSpecList &specs)
+{
+    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, this info isn't guaranteed to exist or be correct. Details:
+                    //  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());
+
+                    // Try to get the UUID from the section list. Usually that's at the end, so
+                    // map the file in if we don't have it already.
+                    size_t section_header_end = header.e_shoff + header.e_shnum * header.e_shentsize;
+                    if (section_header_end > data_sp->GetByteSize())
+                    {
+                        data_sp = file.MemoryMapFileContents (file_offset, section_header_end);
+                        data.SetData(data_sp);
+                    }
+
+                    uint32_t gnu_debuglink_crc = 0;
+                    std::string gnu_debuglink_file;
+                    SectionHeaderColl section_headers;
+                    lldb_private::UUID &uuid = spec.GetUUID();
+                    GetSectionHeaderInfo(section_headers, data, header, uuid, gnu_debuglink_file, gnu_debuglink_crc);
+
+                    if (!uuid.IsValid())
+                    {
+                        if (!gnu_debuglink_crc)
+                        {
+                            // Need to map entire file into memory to calculate the crc.
+                            data_sp = file.MemoryMapFileContents (file_offset, SIZE_MAX);
+                            data.SetData(data_sp);
+                            gnu_debuglink_crc = calc_gnu_debuglink_crc32 (data.GetDataStart(), data.GetByteSize());
+                        }
+                        if (gnu_debuglink_crc)
+                        {
+                            // Use 4 bytes of crc from the .gnu_debuglink section.
+                            uint32_t uuidt[4] = { gnu_debuglink_crc, 0, 0, 0 };
+                            uuid.SetBytes (uuidt, sizeof(uuidt));
+                        }
+                    }
+
+                    specs.Append(spec);
+                }
+            }
+        }
+    }
+
+    return specs.GetSize() - initial_count;
+}
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+lldb_private::ConstString
+ObjectFileELF::GetPluginName()
+{
+    return GetPluginNameStatic();
+}
+
+uint32_t
+ObjectFileELF::GetPluginVersion()
+{
+    return m_plugin_version;
+}
+//------------------------------------------------------------------
+// ObjectFile protocol
+//------------------------------------------------------------------
+
+ObjectFileELF::ObjectFileELF (const lldb::ModuleSP &module_sp, 
+                              DataBufferSP& data_sp,
+                              lldb::offset_t data_offset,
+                              const FileSpec* file, 
+                              lldb::offset_t file_offset,
+                              lldb::offset_t length) : 
+    ObjectFile(module_sp, file, file_offset, length, data_sp, data_offset),
+    m_header(),
+    m_program_headers(),
+    m_section_headers(),
+    m_filespec_ap()
+{
+    if (file)
+        m_file = *file;
+    ::memset(&m_header, 0, sizeof(m_header));
+    m_gnu_debuglink_crc = 0;
+    m_gnu_debuglink_file.clear();
+}
+
+ObjectFileELF::~ObjectFileELF()
+{
+}
+
+bool
+ObjectFileELF::IsExecutable() const
+{
+    return m_header.e_entry != 0;
+}
+
+ByteOrder
+ObjectFileELF::GetByteOrder() const
+{
+    if (m_header.e_ident[EI_DATA] == ELFDATA2MSB)
+        return eByteOrderBig;
+    if (m_header.e_ident[EI_DATA] == ELFDATA2LSB)
+        return eByteOrderLittle;
+    return eByteOrderInvalid;
+}
+
+uint32_t
+ObjectFileELF::GetAddressByteSize() const
+{
+    return m_data.GetAddressByteSize();
+}
+
+size_t
+ObjectFileELF::SectionIndex(const SectionHeaderCollIter &I)
+{
+    return std::distance(m_section_headers.begin(), I) + 1u;
+}
+
+size_t
+ObjectFileELF::SectionIndex(const SectionHeaderCollConstIter &I) const
+{
+    return std::distance(m_section_headers.begin(), I) + 1u;
+}
+
+bool
+ObjectFileELF::ParseHeader()
+{
+    lldb::offset_t offset = 0;
+    return m_header.Parse(m_data, &offset);
+}
+
+bool
+ObjectFileELF::GetUUID(lldb_private::UUID* uuid)
+{
+    // Need to parse the section list to get the UUIDs, so make sure that's been done.
+    if (!ParseSectionHeaders())
+        return false;
+
+    if (m_uuid.IsValid())
+    {
+        // We have the full build id uuid.
+        *uuid = m_uuid;
+        return true;
+    }
+    else 
+    {
+        if (!m_gnu_debuglink_crc)
+            m_gnu_debuglink_crc = calc_gnu_debuglink_crc32 (m_data.GetDataStart(), m_data.GetByteSize());
+        if (m_gnu_debuglink_crc)
+        {
+            // Use 4 bytes of crc from the .gnu_debuglink section.
+            uint32_t uuidt[4] = { m_gnu_debuglink_crc, 0, 0, 0 };
+            uuid->SetBytes (uuidt, sizeof(uuidt));
+            return true;
+        }
+    }
+
+    return false;
+}
+
+lldb_private::FileSpecList
+ObjectFileELF::GetDebugSymbolFilePaths()
+{
+    FileSpecList file_spec_list;
+
+    if (!m_gnu_debuglink_file.empty())
+    {
+        FileSpec file_spec (m_gnu_debuglink_file.c_str(), false);
+        file_spec_list.Append (file_spec);
+    }
+    return file_spec_list;
+}
+
+uint32_t
+ObjectFileELF::GetDependentModules(FileSpecList &files)
+{
+    size_t num_modules = ParseDependentModules();
+    uint32_t num_specs = 0;
+
+    for (unsigned i = 0; i < num_modules; ++i)
+    {
+        if (files.AppendIfUnique(m_filespec_ap->GetFileSpecAtIndex(i)))
+            num_specs++;
+    }
+
+    return num_specs;
+}
+
+Address
+ObjectFileELF::GetImageInfoAddress()
+{
+    if (!ParseDynamicSymbols())
+        return Address();
+
+    SectionList *section_list = GetSectionList();
+    if (!section_list)
+        return Address();
+
+    // Find the SHT_DYNAMIC (.dynamic) section.
+    SectionSP dynsym_section_sp (section_list->FindSectionByType (eSectionTypeELFDynamicLinkInfo, true));
+    if (!dynsym_section_sp)
+        return Address();
+    assert (dynsym_section_sp->GetObjectFile() == this);
+
+    user_id_t dynsym_id = dynsym_section_sp->GetID();
+    const ELFSectionHeaderInfo *dynsym_hdr = GetSectionHeaderByIndex(dynsym_id);
+    if (!dynsym_hdr)
+        return Address();
+
+    for (size_t i = 0; i < m_dynamic_symbols.size(); ++i)
+    {
+        ELFDynamic &symbol = m_dynamic_symbols[i];
+
+        if (symbol.d_tag == DT_DEBUG)
+        {
+            // Compute the offset as the number of previous entries plus the
+            // size of d_tag.
+            addr_t offset = i * dynsym_hdr->sh_entsize + GetAddressByteSize();
+            return Address(dynsym_section_sp, offset);
+        }
+    }
+
+    return Address();
+}
+
+lldb_private::Address
+ObjectFileELF::GetEntryPointAddress () 
+{
+    if (m_entry_point_address.IsValid())
+        return m_entry_point_address;
+
+    if (!ParseHeader() || !IsExecutable())
+        return m_entry_point_address;
+
+    SectionList *section_list = GetSectionList();
+    addr_t offset = m_header.e_entry;
+
+    if (!section_list) 
+        m_entry_point_address.SetOffset(offset);
+    else
+        m_entry_point_address.ResolveAddressUsingFileSections(offset, section_list);
+    return m_entry_point_address;
+}
+
+//----------------------------------------------------------------------
+// ParseDependentModules
+//----------------------------------------------------------------------
+size_t
+ObjectFileELF::ParseDependentModules()
+{
+    if (m_filespec_ap.get())
+        return m_filespec_ap->GetSize();
+
+    m_filespec_ap.reset(new FileSpecList());
+
+    if (!ParseSectionHeaders())
+        return 0;
+
+    SectionList *section_list = GetSectionList();
+    if (!section_list)
+        return 0;
+
+    // Find the SHT_DYNAMIC section.
+    Section *dynsym = section_list->FindSectionByType (eSectionTypeELFDynamicLinkInfo, true).get();
+    if (!dynsym)
+        return 0;
+    assert (dynsym->GetObjectFile() == this);
+
+    const ELFSectionHeaderInfo *header = GetSectionHeaderByIndex (dynsym->GetID());
+    if (!header)
+        return 0;
+    // sh_link: section header index of string table used by entries in the section.
+    Section *dynstr = section_list->FindSectionByID (header->sh_link + 1).get();
+    if (!dynstr)
+        return 0;
+
+    DataExtractor dynsym_data;
+    DataExtractor dynstr_data;
+    if (ReadSectionData(dynsym, dynsym_data) &&
+        ReadSectionData(dynstr, dynstr_data))
+    {
+        ELFDynamic symbol;
+        const lldb::offset_t section_size = dynsym_data.GetByteSize();
+        lldb::offset_t offset = 0;
+
+        // The only type of entries we are concerned with are tagged DT_NEEDED,
+        // yielding the name of a required library.
+        while (offset < section_size)
+        {
+            if (!symbol.Parse(dynsym_data, &offset))
+                break;
+
+            if (symbol.d_tag != DT_NEEDED)
+                continue;
+
+            uint32_t str_index = static_cast<uint32_t>(symbol.d_val);
+            const char *lib_name = dynstr_data.PeekCStr(str_index);
+            m_filespec_ap->Append(FileSpec(lib_name, true));
+        }
+    }
+
+    return m_filespec_ap->GetSize();
+}
+
+//----------------------------------------------------------------------
+// ParseProgramHeaders
+//----------------------------------------------------------------------
+size_t
+ObjectFileELF::ParseProgramHeaders()
+{
+    // We have already parsed the program headers
+    if (!m_program_headers.empty())
+        return m_program_headers.size();
+
+    // If there are no program headers to read we are done.
+    if (m_header.e_phnum == 0)
+        return 0;
+
+    m_program_headers.resize(m_header.e_phnum);
+    if (m_program_headers.size() != m_header.e_phnum)
+        return 0;
+
+    const size_t ph_size = m_header.e_phnum * m_header.e_phentsize;
+    const elf_off ph_offset = m_header.e_phoff;
+    DataExtractor data;
+    if (GetData (ph_offset, ph_size, data) != ph_size)
+        return 0;
+
+    uint32_t idx;
+    lldb::offset_t offset;
+    for (idx = 0, offset = 0; idx < m_header.e_phnum; ++idx)
+    {
+        if (m_program_headers[idx].Parse(data, &offset) == false)
+            break;
+    }
+
+    if (idx < m_program_headers.size())
+        m_program_headers.resize(idx);
+
+    return m_program_headers.size();
+}
+
+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, &notehdr, 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;
+}
+
+//----------------------------------------------------------------------
+// GetSectionHeaderInfo
+//----------------------------------------------------------------------
+size_t
+ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl &section_headers,
+                                    lldb_private::DataExtractor &object_data,
+                                    const elf::ELFHeader &header,
+                                    lldb_private::UUID &uuid,
+                                    std::string &gnu_debuglink_file,
+                                    uint32_t &gnu_debuglink_crc)
+{
+    // We have already parsed the section headers
+    if (!section_headers.empty())
+        return section_headers.size();
+
+    // If there are no section headers we are done.
+    if (header.e_shnum == 0)
+        return 0;
+
+    section_headers.resize(header.e_shnum);
+    if (section_headers.size() != header.e_shnum)
+        return 0;
+
+    const size_t sh_size = header.e_shnum * header.e_shentsize;
+    const elf_off sh_offset = header.e_shoff;
+    DataExtractor sh_data;
+    if (sh_data.SetData (object_data, sh_offset, sh_size) != sh_size)
+        return 0;
+
+    uint32_t idx;
+    lldb::offset_t offset;
+    for (idx = 0, offset = 0; idx < header.e_shnum; ++idx)
+    {
+        if (section_headers[idx].Parse(sh_data, &offset) == false)
+            break;
+    }
+    if (idx < section_headers.size())
+        section_headers.resize(idx);
+
+    const unsigned strtab_idx = header.e_shstrndx;
+    if (strtab_idx && strtab_idx < section_headers.size())
+    {
+        const ELFSectionHeaderInfo &sheader = section_headers[strtab_idx];
+        const size_t byte_size = sheader.sh_size;
+        const Elf64_Off offset = sheader.sh_offset;
+        lldb_private::DataExtractor shstr_data;
+
+        if (shstr_data.SetData (object_data, offset, byte_size) == byte_size)
+        {
+            for (SectionHeaderCollIter I = section_headers.begin();
+                 I != section_headers.end(); ++I)
+            {
+                static ConstString g_sect_name_gnu_debuglink (".gnu_debuglink");
+                const ELFSectionHeaderInfo &header = *I;
+                const uint64_t section_size = header.sh_type == SHT_NOBITS ? 0 : header.sh_size;
+                ConstString name(shstr_data.PeekCStr(I->sh_name));
+
+                I->section_name = name;
+
+                if (name == g_sect_name_gnu_debuglink)
+                {
+                    DataExtractor data;
+                    if (section_size && (data.SetData (object_data, header.sh_offset, section_size) == section_size))
+                    {
+                        lldb::offset_t gnu_debuglink_offset = 0;
+                        gnu_debuglink_file = data.GetCStr (&gnu_debuglink_offset);
+                        gnu_debuglink_offset = llvm::RoundUpToAlignment (gnu_debuglink_offset, 4);
+                        data.GetU32 (&gnu_debuglink_offset, &gnu_debuglink_crc, 1);
+                    }
+                }
+
+                if (header.sh_type == SHT_NOTE && !uuid.IsValid())
+                {
+                    DataExtractor data;
+                    if (section_size && (data.SetData (object_data, header.sh_offset, section_size) == section_size))
+                    {
+                        ParseNoteGNUBuildID (data, uuid);
+                    }
+                }
+            }
+
+            return section_headers.size();
+        }
+    }
+
+    section_headers.clear();
+    return 0;
+}
+
+size_t
+ObjectFileELF::GetProgramHeaderCount()
+{
+    return ParseProgramHeaders();
+}
+
+const elf::ELFProgramHeader *
+ObjectFileELF::GetProgramHeaderByIndex(lldb::user_id_t id)
+{
+    if (!id || !ParseProgramHeaders())
+        return NULL;
+
+    if (--id < m_program_headers.size())
+        return &m_program_headers[id];
+
+    return NULL;
+}
+
+DataExtractor 
+ObjectFileELF::GetSegmentDataByIndex(lldb::user_id_t id)
+{
+    const elf::ELFProgramHeader *segment_header = GetProgramHeaderByIndex(id);
+    if (segment_header == NULL)
+        return DataExtractor();
+    return DataExtractor(m_data, segment_header->p_offset, segment_header->p_filesz);
+}
+
+//----------------------------------------------------------------------
+// ParseSectionHeaders
+//----------------------------------------------------------------------
+size_t
+ObjectFileELF::ParseSectionHeaders()
+{
+    return GetSectionHeaderInfo(m_section_headers, m_data, m_header, m_uuid, m_gnu_debuglink_file, m_gnu_debuglink_crc);
+}
+
+const ObjectFileELF::ELFSectionHeaderInfo *
+ObjectFileELF::GetSectionHeaderByIndex(lldb::user_id_t id)
+{
+    if (!id || !ParseSectionHeaders())
+        return NULL;
+
+    if (--id < m_section_headers.size())
+        return &m_section_headers[id];
+
+    return NULL;
+}
+
+void
+ObjectFileELF::CreateSections(SectionList &unified_section_list)
+{
+    if (!m_sections_ap.get() && ParseSectionHeaders())
+    {
+        m_sections_ap.reset(new SectionList());
+
+        for (SectionHeaderCollIter I = m_section_headers.begin();
+             I != m_section_headers.end(); ++I)
+        {
+            const ELFSectionHeaderInfo &header = *I;
+
+            ConstString& name = I->section_name;
+            const uint64_t file_size = header.sh_type == SHT_NOBITS ? 0 : header.sh_size;
+            const uint64_t vm_size = header.sh_flags & SHF_ALLOC ? header.sh_size : 0;
+
+            static ConstString g_sect_name_text (".text");
+            static ConstString g_sect_name_data (".data");
+            static ConstString g_sect_name_bss (".bss");
+            static ConstString g_sect_name_tdata (".tdata");
+            static ConstString g_sect_name_tbss (".tbss");
+            static ConstString g_sect_name_dwarf_debug_abbrev (".debug_abbrev");
+            static ConstString g_sect_name_dwarf_debug_aranges (".debug_aranges");
+            static ConstString g_sect_name_dwarf_debug_frame (".debug_frame");
+            static ConstString g_sect_name_dwarf_debug_info (".debug_info");
+            static ConstString g_sect_name_dwarf_debug_line (".debug_line");
+            static ConstString g_sect_name_dwarf_debug_loc (".debug_loc");
+            static ConstString g_sect_name_dwarf_debug_macinfo (".debug_macinfo");
+            static ConstString g_sect_name_dwarf_debug_pubnames (".debug_pubnames");
+            static ConstString g_sect_name_dwarf_debug_pubtypes (".debug_pubtypes");
+            static ConstString g_sect_name_dwarf_debug_ranges (".debug_ranges");
+            static ConstString g_sect_name_dwarf_debug_str (".debug_str");
+            static ConstString g_sect_name_eh_frame (".eh_frame");
+
+            SectionType sect_type = eSectionTypeOther;
+
+            bool is_thread_specific = false;
+
+            if      (name == g_sect_name_text)                  sect_type = eSectionTypeCode;
+            else if (name == g_sect_name_data)                  sect_type = eSectionTypeData;
+            else if (name == g_sect_name_bss)                   sect_type = eSectionTypeZeroFill;
+            else if (name == g_sect_name_tdata)
+            {
+                sect_type = eSectionTypeData;
+                is_thread_specific = true;   
+            }
+            else if (name == g_sect_name_tbss)
+            {
+                sect_type = eSectionTypeZeroFill;   
+                is_thread_specific = true;   
+            }
+            // .debug_abbrev – Abbreviations used in the .debug_info section
+            // .debug_aranges – Lookup table for mapping addresses to compilation units
+            // .debug_frame – Call frame information
+            // .debug_info – The core DWARF information section
+            // .debug_line – Line number information
+            // .debug_loc – Location lists used in DW_AT_location attributes
+            // .debug_macinfo – Macro information
+            // .debug_pubnames – Lookup table for mapping object and function names to compilation units
+            // .debug_pubtypes – Lookup table for mapping type names to compilation units
+            // .debug_ranges – Address ranges used in DW_AT_ranges attributes
+            // .debug_str – String table used in .debug_info
+            // MISSING? .gnu_debugdata - "mini debuginfo / MiniDebugInfo" section, http://sourceware.org/gdb/onlinedocs/gdb/MiniDebugInfo.html
+            // MISSING? .debug-index - http://src.chromium.org/viewvc/chrome/trunk/src/build/gdb-add-index?pathrev=144644
+            // MISSING? .debug_types - Type descriptions from DWARF 4? See http://gcc.gnu.org/wiki/DwarfSeparateTypeInfo
+            else if (name == g_sect_name_dwarf_debug_abbrev)    sect_type = eSectionTypeDWARFDebugAbbrev;
+            else if (name == g_sect_name_dwarf_debug_aranges)   sect_type = eSectionTypeDWARFDebugAranges;
+            else if (name == g_sect_name_dwarf_debug_frame)     sect_type = eSectionTypeDWARFDebugFrame;
+            else if (name == g_sect_name_dwarf_debug_info)      sect_type = eSectionTypeDWARFDebugInfo;
+            else if (name == g_sect_name_dwarf_debug_line)      sect_type = eSectionTypeDWARFDebugLine;
+            else if (name == g_sect_name_dwarf_debug_loc)       sect_type = eSectionTypeDWARFDebugLoc;
+            else if (name == g_sect_name_dwarf_debug_macinfo)   sect_type = eSectionTypeDWARFDebugMacInfo;
+            else if (name == g_sect_name_dwarf_debug_pubnames)  sect_type = eSectionTypeDWARFDebugPubNames;
+            else if (name == g_sect_name_dwarf_debug_pubtypes)  sect_type = eSectionTypeDWARFDebugPubTypes;
+            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;
+
+            switch (header.sh_type)
+            {
+                case SHT_SYMTAB:
+                    assert (sect_type == eSectionTypeOther);
+                    sect_type = eSectionTypeELFSymbolTable;
+                    break;
+                case SHT_DYNSYM:
+                    assert (sect_type == eSectionTypeOther);
+                    sect_type = eSectionTypeELFDynamicSymbols;
+                    break;
+                case SHT_RELA:
+                case SHT_REL:
+                    assert (sect_type == eSectionTypeOther);
+                    sect_type = eSectionTypeELFRelocationEntries;
+                    break;
+                case SHT_DYNAMIC:
+                    assert (sect_type == eSectionTypeOther);
+                    sect_type = eSectionTypeELFDynamicLinkInfo;
+                    break;
+            }
+
+            SectionSP section_sp (new Section(GetModule(),        // Module to which this section belongs.
+                                              this,               // ObjectFile to which this section belongs and should read section data from.
+                                              SectionIndex(I),    // Section ID.
+                                              name,               // Section name.
+                                              sect_type,          // Section type.
+                                              header.sh_addr,     // VM address.
+                                              vm_size,            // VM size in bytes of this section.
+                                              header.sh_offset,   // Offset of this section in the file.
+                                              file_size,          // Size of the section as found in the file.
+                                              header.sh_flags));  // Flags for this section.
+
+            if (is_thread_specific)
+                section_sp->SetIsThreadSpecific (is_thread_specific);
+            m_sections_ap->AddSection(section_sp);
+        }
+    }
+
+    if (m_sections_ap.get())
+    {
+        if (GetType() == eTypeDebugInfo)
+        {
+            static const SectionType g_sections[] =
+            {
+                eSectionTypeDWARFDebugAranges,
+                eSectionTypeDWARFDebugInfo,
+                eSectionTypeDWARFDebugAbbrev,
+                eSectionTypeDWARFDebugFrame,
+                eSectionTypeDWARFDebugLine,
+                eSectionTypeDWARFDebugStr,
+                eSectionTypeDWARFDebugLoc,
+                eSectionTypeDWARFDebugMacInfo,
+                eSectionTypeDWARFDebugPubNames,
+                eSectionTypeDWARFDebugPubTypes,
+                eSectionTypeDWARFDebugRanges,
+                eSectionTypeELFSymbolTable,
+            };
+            SectionList *elf_section_list = m_sections_ap.get();
+            for (size_t idx = 0; idx < sizeof(g_sections) / sizeof(g_sections[0]); ++idx)
+            {
+                SectionType section_type = g_sections[idx];
+                SectionSP section_sp (elf_section_list->FindSectionByType (section_type, true));
+                if (section_sp)
+                {
+                    SectionSP module_section_sp (unified_section_list.FindSectionByType (section_type, true));
+                    if (module_section_sp)
+                        unified_section_list.ReplaceSection (module_section_sp->GetID(), section_sp);
+                    else
+                        unified_section_list.AddSection (section_sp);
+                }
+            }
+        }
+        else
+        {
+            unified_section_list = *m_sections_ap;
+        }
+    }
+}
+
+// private
+unsigned
+ObjectFileELF::ParseSymbols (Symtab *symtab,
+                             user_id_t start_id,
+                             SectionList *section_list,
+                             const size_t num_symbols,
+                             const DataExtractor &symtab_data,
+                             const DataExtractor &strtab_data)
+{
+    ELFSymbol symbol;
+    lldb::offset_t offset = 0;
+
+    static ConstString text_section_name(".text");
+    static ConstString init_section_name(".init");
+    static ConstString fini_section_name(".fini");
+    static ConstString ctors_section_name(".ctors");
+    static ConstString dtors_section_name(".dtors");
+
+    static ConstString data_section_name(".data");
+    static ConstString rodata_section_name(".rodata");
+    static ConstString rodata1_section_name(".rodata1");
+    static ConstString data2_section_name(".data1");
+    static ConstString bss_section_name(".bss");
+
+    //StreamFile strm(stdout, false);
+    unsigned i;
+    for (i = 0; i < num_symbols; ++i)
+    {
+        if (symbol.Parse(symtab_data, &offset) == false)
+            break;
+        
+        const char *symbol_name = strtab_data.PeekCStr(symbol.st_name);
+
+        // No need to add symbols that have no names
+        if (symbol_name == NULL || symbol_name[0] == '\0')
+            continue;
+
+        //symbol.Dump (&strm, i, &strtab_data, section_list);
+
+        SectionSP symbol_section_sp;
+        SymbolType symbol_type = eSymbolTypeInvalid;
+        Elf64_Half symbol_idx = symbol.st_shndx;
+
+        switch (symbol_idx)
+        {
+        case SHN_ABS:
+            symbol_type = eSymbolTypeAbsolute;
+            break;
+        case SHN_UNDEF:
+            symbol_type = eSymbolTypeUndefined;
+            break;
+        default:
+            symbol_section_sp = section_list->GetSectionAtIndex(symbol_idx);
+            break;
+        }
+
+        // If a symbol is undefined do not process it further even if it has a STT type
+        if (symbol_type != eSymbolTypeUndefined)
+        {
+            switch (symbol.getType())
+            {
+            default:
+            case STT_NOTYPE:
+                // The symbol's type is not specified.
+                break;
+
+            case STT_OBJECT:
+                // The symbol is associated with a data object, such as a variable,
+                // an array, etc.
+                symbol_type = eSymbolTypeData;
+                break;
+
+            case STT_FUNC:
+                // The symbol is associated with a function or other executable code.
+                symbol_type = eSymbolTypeCode;
+                break;
+
+            case STT_SECTION:
+                // The symbol is associated with a section. Symbol table entries of
+                // this type exist primarily for relocation and normally have
+                // STB_LOCAL binding.
+                break;
+
+            case STT_FILE:
+                // Conventionally, the symbol's name gives the name of the source
+                // file associated with the object file. A file symbol has STB_LOCAL
+                // binding, its section index is SHN_ABS, and it precedes the other
+                // STB_LOCAL symbols for the file, if it is present.
+                symbol_type = eSymbolTypeSourceFile;
+                break;
+
+            case STT_GNU_IFUNC:
+                // The symbol is associated with an indirect function. The actual
+                // function will be resolved if it is referenced.
+                symbol_type = eSymbolTypeResolver;
+                break;
+            }
+        }
+
+        if (symbol_type == eSymbolTypeInvalid)
+        {
+            if (symbol_section_sp)
+            {
+                const ConstString &sect_name = symbol_section_sp->GetName();
+                if (sect_name == text_section_name ||
+                    sect_name == init_section_name ||
+                    sect_name == fini_section_name ||
+                    sect_name == ctors_section_name ||
+                    sect_name == dtors_section_name)
+                {
+                    symbol_type = eSymbolTypeCode;
+                }
+                else if (sect_name == data_section_name ||
+                         sect_name == data2_section_name ||
+                         sect_name == rodata_section_name ||
+                         sect_name == rodata1_section_name ||
+                         sect_name == bss_section_name)
+                {
+                    symbol_type = eSymbolTypeData;
+                }
+            }
+        }
+
+        // If the symbol section we've found has no data (SHT_NOBITS), then check the module section
+        // list. This can happen if we're parsing the debug file and it has no .text section, for example.
+        if (symbol_section_sp && (symbol_section_sp->GetFileSize() == 0))
+        {
+            ModuleSP module_sp(GetModule());
+            if (module_sp)
+            {
+                SectionList *module_section_list = module_sp->GetSectionList();
+                if (module_section_list && module_section_list != section_list)
+                {
+                    const ConstString &sect_name = symbol_section_sp->GetName();
+                    lldb::SectionSP section_sp (module_section_list->FindSectionByName (sect_name));
+                    if (section_sp && section_sp->GetFileSize())
+                    {
+                        symbol_section_sp = section_sp;
+                    }
+                }
+            }
+        }
+
+        uint64_t symbol_value = symbol.st_value;
+        if (symbol_section_sp)
+            symbol_value -= symbol_section_sp->GetFileAddress();
+        bool is_global = symbol.getBinding() == STB_GLOBAL;
+        uint32_t flags = symbol.st_other << 8 | symbol.st_info;
+        bool is_mangled = symbol_name ? (symbol_name[0] == '_' && symbol_name[1] == 'Z') : false;
+        Symbol dc_symbol(
+            i + start_id,       // ID is the original symbol table index.
+            symbol_name,        // Symbol name.
+            is_mangled,         // Is the symbol name mangled?
+            symbol_type,        // Type of this symbol
+            is_global,          // Is this globally visible?
+            false,              // Is this symbol debug info?
+            false,              // Is this symbol a trampoline?
+            false,              // Is this symbol artificial?
+            symbol_section_sp,  // Section in which this symbol is defined or null.
+            symbol_value,       // Offset in section or symbol value.
+            symbol.st_size,     // Size in bytes of this symbol.
+            true,               // Size is valid
+            flags);             // Symbol flags.
+        symtab->AddSymbol(dc_symbol);
+    }
+
+    return i;
+}
+
+unsigned
+ObjectFileELF::ParseSymbolTable(Symtab *symbol_table, user_id_t start_id, lldb_private::Section *symtab)
+{
+    if (symtab->GetObjectFile() != this)
+    {
+        // If the symbol table section is owned by a different object file, have it do the
+        // parsing.
+        ObjectFileELF *obj_file_elf = static_cast<ObjectFileELF *>(symtab->GetObjectFile());
+        return obj_file_elf->ParseSymbolTable (symbol_table, start_id, symtab);
+    }
+
+    // Get section list for this object file.
+    SectionList *section_list = m_sections_ap.get();
+    if (!section_list)
+        return 0;
+
+    user_id_t symtab_id = symtab->GetID();
+    const ELFSectionHeaderInfo *symtab_hdr = GetSectionHeaderByIndex(symtab_id);
+    assert(symtab_hdr->sh_type == SHT_SYMTAB || 
+           symtab_hdr->sh_type == SHT_DYNSYM);
+
+    // sh_link: section header index of associated string table.
+    // Section ID's are ones based.
+    user_id_t strtab_id = symtab_hdr->sh_link + 1;
+    Section *strtab = section_list->FindSectionByID(strtab_id).get();
+
+    unsigned num_symbols = 0;
+    if (symtab && strtab)
+    {
+        assert (symtab->GetObjectFile() == this);
+        assert (strtab->GetObjectFile() == this);
+
+        DataExtractor symtab_data;
+        DataExtractor strtab_data;
+        if (ReadSectionData(symtab, symtab_data) &&
+            ReadSectionData(strtab, strtab_data))
+        {
+            size_t num_symbols = symtab_data.GetByteSize() / symtab_hdr->sh_entsize;
+
+            num_symbols = ParseSymbols(symbol_table, start_id, 
+                                       section_list, num_symbols,
+                                       symtab_data, strtab_data);
+        }
+    }
+
+    return num_symbols;
+}
+
+size_t
+ObjectFileELF::ParseDynamicSymbols()
+{
+    if (m_dynamic_symbols.size())
+        return m_dynamic_symbols.size();
+
+    SectionList *section_list = GetSectionList();
+    if (!section_list)
+        return 0;
+
+    // Find the SHT_DYNAMIC section.
+    Section *dynsym = section_list->FindSectionByType (eSectionTypeELFDynamicLinkInfo, true).get();
+    if (!dynsym)
+        return 0;
+    assert (dynsym->GetObjectFile() == this);
+
+    ELFDynamic symbol;
+    DataExtractor dynsym_data;
+    if (ReadSectionData(dynsym, dynsym_data))
+    {
+        const lldb::offset_t section_size = dynsym_data.GetByteSize();
+        lldb::offset_t cursor = 0;
+
+        while (cursor < section_size)
+        {
+            if (!symbol.Parse(dynsym_data, &cursor))
+                break;
+
+            m_dynamic_symbols.push_back(symbol);
+        }
+    }
+
+    return m_dynamic_symbols.size();
+}
+
+const ELFDynamic *
+ObjectFileELF::FindDynamicSymbol(unsigned tag)
+{
+    if (!ParseDynamicSymbols())
+        return NULL;
+
+    DynamicSymbolCollIter I = m_dynamic_symbols.begin();
+    DynamicSymbolCollIter E = m_dynamic_symbols.end();
+    for ( ; I != E; ++I)
+    {
+        ELFDynamic *symbol = &*I;
+
+        if (symbol->d_tag == tag)
+            return symbol;
+    }
+
+    return NULL;
+}
+
+unsigned
+ObjectFileELF::PLTRelocationType()
+{
+    const ELFDynamic *symbol = FindDynamicSymbol(DT_PLTREL);
+
+    if (symbol)
+        return symbol->d_val;
+
+    return 0;
+}
+
+static unsigned
+ParsePLTRelocations(Symtab *symbol_table,
+                    user_id_t start_id,
+                    unsigned rel_type,
+                    const ELFHeader *hdr,
+                    const ELFSectionHeader *rel_hdr,
+                    const ELFSectionHeader *plt_hdr,
+                    const ELFSectionHeader *sym_hdr,
+                    const lldb::SectionSP &plt_section_sp,
+                    DataExtractor &rel_data,
+                    DataExtractor &symtab_data,
+                    DataExtractor &strtab_data)
+{
+    ELFRelocation rel(rel_type);
+    ELFSymbol symbol;
+    lldb::offset_t offset = 0;
+    const elf_xword plt_entsize = plt_hdr->sh_entsize;
+    const elf_xword num_relocations = rel_hdr->sh_size / rel_hdr->sh_entsize;
+
+    typedef unsigned (*reloc_info_fn)(const ELFRelocation &rel);
+    reloc_info_fn reloc_type;
+    reloc_info_fn reloc_symbol;
+
+    if (hdr->Is32Bit())
+    {
+        reloc_type = ELFRelocation::RelocType32;
+        reloc_symbol = ELFRelocation::RelocSymbol32;
+    }
+    else
+    {
+        reloc_type = ELFRelocation::RelocType64;
+        reloc_symbol = ELFRelocation::RelocSymbol64;
+    }
+
+    unsigned slot_type = hdr->GetRelocationJumpSlotType();
+    unsigned i;
+    for (i = 0; i < num_relocations; ++i)
+    {
+        if (rel.Parse(rel_data, &offset) == false)
+            break;
+
+        if (reloc_type(rel) != slot_type)
+            continue;
+
+        lldb::offset_t symbol_offset = reloc_symbol(rel) * sym_hdr->sh_entsize;
+        uint64_t plt_index = (i + 1) * plt_entsize;
+
+        if (!symbol.Parse(symtab_data, &symbol_offset))
+            break;
+
+        const char *symbol_name = strtab_data.PeekCStr(symbol.st_name);
+        bool is_mangled = symbol_name ? (symbol_name[0] == '_' && symbol_name[1] == 'Z') : false;
+
+        Symbol jump_symbol(
+            i + start_id,    // Symbol table index
+            symbol_name,     // symbol name.
+            is_mangled,      // is the symbol name mangled?
+            eSymbolTypeTrampoline, // Type of this symbol
+            false,           // Is this globally visible?
+            false,           // Is this symbol debug info?
+            true,            // Is this symbol a trampoline?
+            true,            // Is this symbol artificial?
+            plt_section_sp,  // Section in which this symbol is defined or null.
+            plt_index,       // Offset in section or symbol value.
+            plt_entsize,     // Size in bytes of this symbol.
+            true,            // Size is valid
+            0);              // Symbol flags.
+
+        symbol_table->AddSymbol(jump_symbol);
+    }
+
+    return i;
+}
+
+unsigned
+ObjectFileELF::ParseTrampolineSymbols(Symtab *symbol_table,
+                                      user_id_t start_id,
+                                      const ELFSectionHeaderInfo *rel_hdr,
+                                      user_id_t rel_id)
+{
+    assert(rel_hdr->sh_type == SHT_RELA || rel_hdr->sh_type == SHT_REL);
+
+    // The link field points to the associated symbol table. The info field
+    // points to the section holding the plt.
+    user_id_t symtab_id = rel_hdr->sh_link;
+    user_id_t plt_id = rel_hdr->sh_info;
+
+    if (!symtab_id || !plt_id)
+        return 0;
+
+    // Section ID's are ones based;
+    symtab_id++;
+    plt_id++;
+
+    const ELFSectionHeaderInfo *plt_hdr = GetSectionHeaderByIndex(plt_id);
+    if (!plt_hdr)
+        return 0;
+
+    const ELFSectionHeaderInfo *sym_hdr = GetSectionHeaderByIndex(symtab_id);
+    if (!sym_hdr)
+        return 0;
+
+    SectionList *section_list = m_sections_ap.get();
+    if (!section_list)
+        return 0;
+
+    Section *rel_section = section_list->FindSectionByID(rel_id).get();
+    if (!rel_section)
+        return 0;
+
+    SectionSP plt_section_sp (section_list->FindSectionByID(plt_id));
+    if (!plt_section_sp)
+        return 0;
+
+    Section *symtab = section_list->FindSectionByID(symtab_id).get();
+    if (!symtab)
+        return 0;
+
+    // sh_link points to associated string table.
+    Section *strtab = section_list->FindSectionByID(sym_hdr->sh_link + 1).get();
+    if (!strtab)
+        return 0;
+
+    DataExtractor rel_data;
+    if (!ReadSectionData(rel_section, rel_data))
+        return 0;
+
+    DataExtractor symtab_data;
+    if (!ReadSectionData(symtab, symtab_data))
+        return 0;
+
+    DataExtractor strtab_data;
+    if (!ReadSectionData(strtab, strtab_data))
+        return 0;
+
+    unsigned rel_type = PLTRelocationType();
+    if (!rel_type)
+        return 0;
+
+    return ParsePLTRelocations (symbol_table, 
+                                start_id, 
+                                rel_type,
+                                &m_header, 
+                                rel_hdr, 
+                                plt_hdr, 
+                                sym_hdr,
+                                plt_section_sp, 
+                                rel_data, 
+                                symtab_data, 
+                                strtab_data);
+}
+
+Symtab *
+ObjectFileELF::GetSymtab()
+{
+    ModuleSP module_sp(GetModule());
+    if (!module_sp)
+        return NULL;
+
+    // We always want to use the main object file so we (hopefully) only have one cached copy
+    // of our symtab, dynamic sections, etc.
+    ObjectFile *module_obj_file = module_sp->GetObjectFile();
+    if (module_obj_file && module_obj_file != this)
+        return module_obj_file->GetSymtab();
+
+    if (m_symtab_ap.get() == NULL)
+    {
+        SectionList *section_list = GetSectionList();
+        if (!section_list)
+            return NULL;
+
+        uint64_t symbol_id = 0;
+        lldb_private::Mutex::Locker locker(module_sp->GetMutex());
+
+        m_symtab_ap.reset(new Symtab(this));
+
+        // Sharable objects and dynamic executables usually have 2 distinct symbol
+        // tables, one named ".symtab", and the other ".dynsym". The dynsym is a smaller
+        // version of the symtab that only contains global symbols. The information found
+        // in the dynsym is therefore also found in the symtab, while the reverse is not
+        // necessarily true.
+        Section *symtab = section_list->FindSectionByType (eSectionTypeELFSymbolTable, true).get();
+        if (!symtab)
+        {
+            // The symtab section is non-allocable and can be stripped, so if it doesn't exist
+            // then use the dynsym section which should always be there.
+            symtab = section_list->FindSectionByType (eSectionTypeELFDynamicSymbols, true).get();
+        }
+        if (symtab)
+            symbol_id += ParseSymbolTable (m_symtab_ap.get(), symbol_id, symtab);
+
+        // Synthesize trampoline symbols to help navigate the PLT.
+        const ELFDynamic *symbol = FindDynamicSymbol(DT_JMPREL);
+        if (symbol)
+        {
+            addr_t addr = symbol->d_ptr;
+            Section *reloc_section = section_list->FindSectionContainingFileAddress(addr).get();
+            if (reloc_section) 
+            {
+                user_id_t reloc_id = reloc_section->GetID();
+                const ELFSectionHeaderInfo *reloc_header = GetSectionHeaderByIndex(reloc_id);
+                assert(reloc_header);
+
+                ParseTrampolineSymbols (m_symtab_ap.get(), symbol_id, reloc_header, reloc_id);
+            }
+        }
+    }
+    return m_symtab_ap.get();
+}
+
+bool
+ObjectFileELF::IsStripped ()
+{
+    // TODO: determine this for ELF
+    return false;
+}
+
+//===----------------------------------------------------------------------===//
+// Dump
+//
+// Dump the specifics of the runtime file container (such as any headers
+// segments, sections, etc).
+//----------------------------------------------------------------------
+void
+ObjectFileELF::Dump(Stream *s)
+{
+    DumpELFHeader(s, m_header);
+    s->EOL();
+    DumpELFProgramHeaders(s);
+    s->EOL();
+    DumpELFSectionHeaders(s);
+    s->EOL();
+    SectionList *section_list = GetSectionList();
+    if (section_list)
+        section_list->Dump(s, NULL, true, UINT32_MAX);
+    Symtab *symtab = GetSymtab();
+    if (symtab)
+        symtab->Dump(s, NULL, eSortOrderNone);
+    s->EOL();
+    DumpDependentModules(s);
+    s->EOL();
+}
+
+//----------------------------------------------------------------------
+// DumpELFHeader
+//
+// Dump the ELF header to the specified output stream
+//----------------------------------------------------------------------
+void
+ObjectFileELF::DumpELFHeader(Stream *s, const ELFHeader &header)
+{
+    s->PutCString("ELF Header\n");
+    s->Printf("e_ident[EI_MAG0   ] = 0x%2.2x\n", header.e_ident[EI_MAG0]);
+    s->Printf("e_ident[EI_MAG1   ] = 0x%2.2x '%c'\n",
+              header.e_ident[EI_MAG1], header.e_ident[EI_MAG1]);
+    s->Printf("e_ident[EI_MAG2   ] = 0x%2.2x '%c'\n",
+              header.e_ident[EI_MAG2], header.e_ident[EI_MAG2]);
+    s->Printf("e_ident[EI_MAG3   ] = 0x%2.2x '%c'\n",
+              header.e_ident[EI_MAG3], header.e_ident[EI_MAG3]);
+
+    s->Printf("e_ident[EI_CLASS  ] = 0x%2.2x\n", header.e_ident[EI_CLASS]);
+    s->Printf("e_ident[EI_DATA   ] = 0x%2.2x ", header.e_ident[EI_DATA]);
+    DumpELFHeader_e_ident_EI_DATA(s, header.e_ident[EI_DATA]);
+    s->Printf ("\ne_ident[EI_VERSION] = 0x%2.2x\n", header.e_ident[EI_VERSION]);
+    s->Printf ("e_ident[EI_PAD    ] = 0x%2.2x\n", header.e_ident[EI_PAD]);
+
+    s->Printf("e_type      = 0x%4.4x ", header.e_type);
+    DumpELFHeader_e_type(s, header.e_type);
+    s->Printf("\ne_machine   = 0x%4.4x\n", header.e_machine);
+    s->Printf("e_version   = 0x%8.8x\n", header.e_version);
+    s->Printf("e_entry     = 0x%8.8" PRIx64 "\n", header.e_entry);
+    s->Printf("e_phoff     = 0x%8.8" PRIx64 "\n", header.e_phoff);
+    s->Printf("e_shoff     = 0x%8.8" PRIx64 "\n", header.e_shoff);
+    s->Printf("e_flags     = 0x%8.8x\n", header.e_flags);
+    s->Printf("e_ehsize    = 0x%4.4x\n", header.e_ehsize);
+    s->Printf("e_phentsize = 0x%4.4x\n", header.e_phentsize);
+    s->Printf("e_phnum     = 0x%4.4x\n", header.e_phnum);
+    s->Printf("e_shentsize = 0x%4.4x\n", header.e_shentsize);
+    s->Printf("e_shnum     = 0x%4.4x\n", header.e_shnum);
+    s->Printf("e_shstrndx  = 0x%4.4x\n", header.e_shstrndx);
+}
+
+//----------------------------------------------------------------------
+// DumpELFHeader_e_type
+//
+// Dump an token value for the ELF header member e_type
+//----------------------------------------------------------------------
+void
+ObjectFileELF::DumpELFHeader_e_type(Stream *s, elf_half e_type)
+{
+    switch (e_type)
+    {
+    case ET_NONE:   *s << "ET_NONE"; break;
+    case ET_REL:    *s << "ET_REL"; break;
+    case ET_EXEC:   *s << "ET_EXEC"; break;
+    case ET_DYN:    *s << "ET_DYN"; break;
+    case ET_CORE:   *s << "ET_CORE"; break;
+    default:
+        break;
+    }
+}
+
+//----------------------------------------------------------------------
+// DumpELFHeader_e_ident_EI_DATA
+//
+// Dump an token value for the ELF header member e_ident[EI_DATA]
+//----------------------------------------------------------------------
+void
+ObjectFileELF::DumpELFHeader_e_ident_EI_DATA(Stream *s, unsigned char ei_data)
+{
+    switch (ei_data)
+    {
+    case ELFDATANONE:   *s << "ELFDATANONE"; break;
+    case ELFDATA2LSB:   *s << "ELFDATA2LSB - Little Endian"; break;
+    case ELFDATA2MSB:   *s << "ELFDATA2MSB - Big Endian"; break;
+    default:
+        break;
+    }
+}
+
+
+//----------------------------------------------------------------------
+// DumpELFProgramHeader
+//
+// Dump a single ELF program header to the specified output stream
+//----------------------------------------------------------------------
+void
+ObjectFileELF::DumpELFProgramHeader(Stream *s, const ELFProgramHeader &ph)
+{
+    DumpELFProgramHeader_p_type(s, ph.p_type);
+    s->Printf(" %8.8" PRIx64 " %8.8" PRIx64 " %8.8" PRIx64, ph.p_offset, ph.p_vaddr, ph.p_paddr);
+    s->Printf(" %8.8" PRIx64 " %8.8" PRIx64 " %8.8x (", ph.p_filesz, ph.p_memsz, ph.p_flags);
+
+    DumpELFProgramHeader_p_flags(s, ph.p_flags);
+    s->Printf(") %8.8" PRIx64, ph.p_align);
+}
+
+//----------------------------------------------------------------------
+// DumpELFProgramHeader_p_type
+//
+// Dump an token value for the ELF program header member p_type which
+// describes the type of the program header
+// ----------------------------------------------------------------------
+void
+ObjectFileELF::DumpELFProgramHeader_p_type(Stream *s, elf_word p_type)
+{
+    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_TLS         , kStrWidth);
+    CASE_AND_STREAM(s, PT_GNU_EH_FRAME, kStrWidth);
+    default:
+        s->Printf("0x%8.8x%*s", p_type, kStrWidth - 10, "");
+        break;
+    }
+}
+
+
+//----------------------------------------------------------------------
+// DumpELFProgramHeader_p_flags
+//
+// Dump an token value for the ELF program header member p_flags
+//----------------------------------------------------------------------
+void
+ObjectFileELF::DumpELFProgramHeader_p_flags(Stream *s, elf_word p_flags)
+{
+    *s  << ((p_flags & PF_X) ? "PF_X" : "    ")
+        << (((p_flags & PF_X) && (p_flags & PF_W)) ? '+' : ' ')
+        << ((p_flags & PF_W) ? "PF_W" : "    ")
+        << (((p_flags & PF_W) && (p_flags & PF_R)) ? '+' : ' ')
+        << ((p_flags & PF_R) ? "PF_R" : "    ");
+}
+
+//----------------------------------------------------------------------
+// DumpELFProgramHeaders
+//
+// Dump all of the ELF program header to the specified output stream
+//----------------------------------------------------------------------
+void
+ObjectFileELF::DumpELFProgramHeaders(Stream *s)
+{
+    if (ParseProgramHeaders())
+    {
+        s->PutCString("Program Headers\n");
+        s->PutCString("IDX  p_type          p_offset p_vaddr  p_paddr  "
+                      "p_filesz p_memsz  p_flags                   p_align\n");
+        s->PutCString("==== --------------- -------- -------- -------- "
+                      "-------- -------- ------------------------- --------\n");
+
+        uint32_t idx = 0;
+        for (ProgramHeaderCollConstIter I = m_program_headers.begin();
+             I != m_program_headers.end(); ++I, ++idx)
+        {
+            s->Printf("[%2u] ", idx);
+            ObjectFileELF::DumpELFProgramHeader(s, *I);
+            s->EOL();
+        }
+    }
+}
+
+//----------------------------------------------------------------------
+// DumpELFSectionHeader
+//
+// Dump a single ELF section header to the specified output stream
+//----------------------------------------------------------------------
+void
+ObjectFileELF::DumpELFSectionHeader(Stream *s, const ELFSectionHeaderInfo &sh)
+{
+    s->Printf("%8.8x ", sh.sh_name);
+    DumpELFSectionHeader_sh_type(s, sh.sh_type);
+    s->Printf(" %8.8" PRIx64 " (", sh.sh_flags);
+    DumpELFSectionHeader_sh_flags(s, sh.sh_flags);
+    s->Printf(") %8.8" PRIx64 " %8.8" PRIx64 " %8.8" PRIx64, sh.sh_addr, sh.sh_offset, sh.sh_size);
+    s->Printf(" %8.8x %8.8x", sh.sh_link, sh.sh_info);
+    s->Printf(" %8.8" PRIx64 " %8.8" PRIx64, sh.sh_addralign, sh.sh_entsize);
+}
+
+//----------------------------------------------------------------------
+// DumpELFSectionHeader_sh_type
+//
+// Dump an token value for the ELF section header member sh_type which
+// describes the type of the section
+//----------------------------------------------------------------------
+void
+ObjectFileELF::DumpELFSectionHeader_sh_type(Stream *s, elf_word sh_type)
+{
+    const int kStrWidth = 12;
+    switch (sh_type)
+    {
+    CASE_AND_STREAM(s, SHT_NULL     , kStrWidth);
+    CASE_AND_STREAM(s, SHT_PROGBITS , kStrWidth);
+    CASE_AND_STREAM(s, SHT_SYMTAB   , kStrWidth);
+    CASE_AND_STREAM(s, SHT_STRTAB   , kStrWidth);
+    CASE_AND_STREAM(s, SHT_RELA     , kStrWidth);
+    CASE_AND_STREAM(s, SHT_HASH     , kStrWidth);
+    CASE_AND_STREAM(s, SHT_DYNAMIC  , kStrWidth);
+    CASE_AND_STREAM(s, SHT_NOTE     , kStrWidth);
+    CASE_AND_STREAM(s, SHT_NOBITS   , kStrWidth);
+    CASE_AND_STREAM(s, SHT_REL      , kStrWidth);
+    CASE_AND_STREAM(s, SHT_SHLIB    , kStrWidth);
+    CASE_AND_STREAM(s, SHT_DYNSYM   , kStrWidth);
+    CASE_AND_STREAM(s, SHT_LOPROC   , kStrWidth);
+    CASE_AND_STREAM(s, SHT_HIPROC   , kStrWidth);
+    CASE_AND_STREAM(s, SHT_LOUSER   , kStrWidth);
+    CASE_AND_STREAM(s, SHT_HIUSER   , kStrWidth);
+    default:
+        s->Printf("0x%8.8x%*s", sh_type, kStrWidth - 10, "");
+        break;
+    }
+}
+
+//----------------------------------------------------------------------
+// DumpELFSectionHeader_sh_flags
+//
+// Dump an token value for the ELF section header member sh_flags
+//----------------------------------------------------------------------
+void
+ObjectFileELF::DumpELFSectionHeader_sh_flags(Stream *s, elf_xword sh_flags)
+{
+    *s  << ((sh_flags & SHF_WRITE) ? "WRITE" : "     ")
+        << (((sh_flags & SHF_WRITE) && (sh_flags & SHF_ALLOC)) ? '+' : ' ')
+        << ((sh_flags & SHF_ALLOC) ? "ALLOC" : "     ")
+        << (((sh_flags & SHF_ALLOC) && (sh_flags & SHF_EXECINSTR)) ? '+' : ' ')
+        << ((sh_flags & SHF_EXECINSTR) ? "EXECINSTR" : "         ");
+}
+
+//----------------------------------------------------------------------
+// DumpELFSectionHeaders
+//
+// Dump all of the ELF section header to the specified output stream
+//----------------------------------------------------------------------
+void
+ObjectFileELF::DumpELFSectionHeaders(Stream *s)
+{
+    if (!ParseSectionHeaders())
+        return;
+
+    s->PutCString("Section Headers\n");
+    s->PutCString("IDX  name     type         flags                            "
+                  "addr     offset   size     link     info     addralgn "
+                  "entsize  Name\n");
+    s->PutCString("==== -------- ------------ -------------------------------- "
+                  "-------- -------- -------- -------- -------- -------- "
+                  "-------- ====================\n");
+
+    uint32_t idx = 0;
+    for (SectionHeaderCollConstIter I = m_section_headers.begin();
+         I != m_section_headers.end(); ++I, ++idx)
+    {
+        s->Printf("[%2u] ", idx);
+        ObjectFileELF::DumpELFSectionHeader(s, *I);
+        const char* section_name = I->section_name.AsCString("");
+        if (section_name)
+            *s << ' ' << section_name << "\n";
+    }
+}
+
+void
+ObjectFileELF::DumpDependentModules(lldb_private::Stream *s)
+{
+    size_t num_modules = ParseDependentModules();
+
+    if (num_modules > 0)
+    {
+        s->PutCString("Dependent Modules:\n");
+        for (unsigned i = 0; i < num_modules; ++i)
+        {
+            const FileSpec &spec = m_filespec_ap->GetFileSpecAtIndex(i);
+            s->Printf("   %s\n", spec.GetFilename().GetCString());
+        }
+    }
+}
+
+bool
+ObjectFileELF::GetArchitecture (ArchSpec &arch)
+{
+    if (!ParseHeader())
+        return false;
+
+    arch.SetArchitecture (eArchTypeELF, m_header.e_machine, LLDB_INVALID_CPUTYPE);
+    arch.GetTriple().setOSName (Host::GetOSString().GetCString());
+    arch.GetTriple().setVendorName(Host::GetVendorString().GetCString());
+    return true;
+}
+
+ObjectFile::Type
+ObjectFileELF::CalculateType()
+{
+    switch (m_header.e_type)
+    {
+        case llvm::ELF::ET_NONE:
+            // 0 - No file type
+            return eTypeUnknown;
+
+        case llvm::ELF::ET_REL:
+            // 1 - Relocatable file
+            return eTypeObjectFile;
+
+        case llvm::ELF::ET_EXEC:
+            // 2 - Executable file
+            return eTypeExecutable;
+
+        case llvm::ELF::ET_DYN:
+            // 3 - Shared object file
+            return eTypeSharedLibrary;
+
+        case ET_CORE:
+            // 4 - Core file
+            return eTypeCoreFile;
+
+        default:
+            break;
+    }
+    return eTypeUnknown;
+}
+
+ObjectFile::Strata
+ObjectFileELF::CalculateStrata()
+{
+    switch (m_header.e_type)
+    {
+        case llvm::ELF::ET_NONE:    
+            // 0 - No file type
+            return eStrataUnknown;
+
+        case llvm::ELF::ET_REL:
+            // 1 - Relocatable file
+            return eStrataUnknown;
+
+        case llvm::ELF::ET_EXEC:
+            // 2 - Executable file
+            // TODO: is there any way to detect that an executable is a kernel
+            // related executable by inspecting the program headers, section 
+            // headers, symbols, or any other flag bits???
+            return eStrataUser;
+
+        case llvm::ELF::ET_DYN:
+            // 3 - Shared object file
+            // TODO: is there any way to detect that an shared library is a kernel
+            // related executable by inspecting the program headers, section 
+            // headers, symbols, or any other flag bits???
+            return eStrataUnknown;
+
+        case ET_CORE:
+            // 4 - Core file
+            // TODO: is there any way to detect that an core file is a kernel
+            // related executable by inspecting the program headers, section 
+            // headers, symbols, or any other flag bits???
+            return eStrataUnknown;
+
+        default:
+            break;
+    }
+    return eStrataUnknown;
+}
+
diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.h b/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
new file mode 100644
index 000000000000..2365101f4275
--- /dev/null
+++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
@@ -0,0 +1,333 @@
+//===-- ObjectFileELF.h --------------------------------------- -*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ObjectFileELF_h_
+#define liblldb_ObjectFileELF_h_
+
+#include <stdint.h>
+#include <vector>
+
+#include "lldb/lldb-private.h"
+#include "lldb/Host/FileSpec.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Core/UUID.h"
+
+#include "ELFHeader.h"
+
+//------------------------------------------------------------------------------
+/// @class ObjectFileELF
+/// @brief Generic ELF object file reader.
+///
+/// This class provides a generic ELF (32/64 bit) reader plugin implementing the
+/// ObjectFile protocol.
+class ObjectFileELF :
+    public lldb_private::ObjectFile
+{
+public:
+    //------------------------------------------------------------------
+    // Static Functions
+    //------------------------------------------------------------------
+    static void
+    Initialize();
+
+    static void
+    Terminate();
+
+    static lldb_private::ConstString
+    GetPluginNameStatic();
+
+    static const char *
+    GetPluginDescriptionStatic();
+
+    static lldb_private::ObjectFile *
+    CreateInstance(const lldb::ModuleSP &module_sp,
+                   lldb::DataBufferSP& data_sp,
+                   lldb::offset_t data_offset,
+                   const lldb_private::FileSpec* file,
+                   lldb::offset_t file_offset,
+                   lldb::offset_t length);
+
+    static lldb_private::ObjectFile *
+    CreateMemoryInstance (const lldb::ModuleSP &module_sp, 
+                          lldb::DataBufferSP& data_sp, 
+                          const lldb::ProcessSP &process_sp, 
+                          lldb::addr_t header_addr);
+
+    static size_t
+    GetModuleSpecifications (const lldb_private::FileSpec& file,
+                             lldb::DataBufferSP& data_sp,
+                             lldb::offset_t data_offset,
+                             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
+    //------------------------------------------------------------------
+    virtual lldb_private::ConstString
+    GetPluginName();
+
+    virtual uint32_t
+    GetPluginVersion();
+
+    //------------------------------------------------------------------
+    // ObjectFile Protocol.
+    //------------------------------------------------------------------
+    virtual
+    ~ObjectFileELF();
+
+    virtual bool
+    ParseHeader();
+
+    virtual lldb::ByteOrder
+    GetByteOrder() const;
+
+    virtual bool
+    IsExecutable () const;
+
+    virtual uint32_t
+    GetAddressByteSize() const;
+
+    virtual lldb_private::Symtab *
+    GetSymtab();
+
+    virtual bool
+    IsStripped ();
+
+    virtual void
+    CreateSections (lldb_private::SectionList &unified_section_list);
+
+    virtual void
+    Dump(lldb_private::Stream *s);
+
+    virtual bool
+    GetArchitecture (lldb_private::ArchSpec &arch);
+
+    virtual bool
+    GetUUID(lldb_private::UUID* uuid);
+
+    virtual lldb_private::FileSpecList
+    GetDebugSymbolFilePaths();
+
+    virtual uint32_t
+    GetDependentModules(lldb_private::FileSpecList& files);
+
+    virtual lldb_private::Address
+    GetImageInfoAddress();
+    
+    virtual lldb_private::Address
+    GetEntryPointAddress ();
+    
+    virtual ObjectFile::Type
+    CalculateType();
+    
+    virtual ObjectFile::Strata
+    CalculateStrata();
+
+    // Returns number of program headers found in the ELF file.
+    size_t
+    GetProgramHeaderCount();
+
+    // Returns the program header with the given index.
+    const elf::ELFProgramHeader *
+    GetProgramHeaderByIndex(lldb::user_id_t id);
+
+    // Returns segment data for the given index.
+    lldb_private::DataExtractor
+    GetSegmentDataByIndex(lldb::user_id_t id);
+
+private:
+    ObjectFileELF(const lldb::ModuleSP &module_sp,
+                  lldb::DataBufferSP& data_sp,
+                  lldb::offset_t data_offset,
+                  const lldb_private::FileSpec* file,
+                  lldb::offset_t offset,
+                  lldb::offset_t length);
+
+    typedef std::vector<elf::ELFProgramHeader>  ProgramHeaderColl;
+    typedef ProgramHeaderColl::iterator         ProgramHeaderCollIter;
+    typedef ProgramHeaderColl::const_iterator   ProgramHeaderCollConstIter;
+
+    struct ELFSectionHeaderInfo : public elf::ELFSectionHeader
+    {
+        lldb_private::ConstString section_name;
+    };
+    typedef std::vector<ELFSectionHeaderInfo>   SectionHeaderColl;
+    typedef SectionHeaderColl::iterator         SectionHeaderCollIter;
+    typedef SectionHeaderColl::const_iterator   SectionHeaderCollConstIter;
+
+    typedef std::vector<elf::ELFDynamic>        DynamicSymbolColl;
+    typedef DynamicSymbolColl::iterator         DynamicSymbolCollIter;
+    typedef DynamicSymbolColl::const_iterator   DynamicSymbolCollConstIter;
+
+    /// Version of this reader common to all plugins based on this class.
+    static const uint32_t m_plugin_version = 1;
+
+    /// ELF file header.
+    elf::ELFHeader m_header;
+
+    /// ELF build ID.
+    lldb_private::UUID m_uuid;
+
+    /// ELF .gnu_debuglink file and crc data if available.
+    std::string m_gnu_debuglink_file;
+    uint32_t m_gnu_debuglink_crc;
+
+    /// Collection of program headers.
+    ProgramHeaderColl m_program_headers;
+
+    /// Collection of section headers.
+    SectionHeaderColl m_section_headers;
+
+    /// Collection of symbols from the dynamic table.
+    DynamicSymbolColl m_dynamic_symbols;
+
+    /// List of file specifications corresponding to the modules (shared
+    /// libraries) on which this object file depends.
+    mutable std::unique_ptr<lldb_private::FileSpecList> m_filespec_ap;
+
+    /// Cached value of the entry point for this module.
+    lldb_private::Address  m_entry_point_address;
+
+    /// Returns a 1 based index of the given section header.
+    size_t
+    SectionIndex(const SectionHeaderCollIter &I);
+
+    /// Returns a 1 based index of the given section header.
+    size_t
+    SectionIndex(const SectionHeaderCollConstIter &I) const;
+
+    /// Parses all section headers present in this object file and populates
+    /// m_program_headers.  This method will compute the header list only once.
+    /// Returns the number of headers parsed.
+    size_t
+    ParseProgramHeaders();
+
+    /// Parses all section headers present in this object file and populates
+    /// m_section_headers.  This method will compute the header list only once.
+    /// Returns the number of headers parsed.
+    size_t
+    ParseSectionHeaders();
+
+    /// Parses the elf section headers and returns the uuid, debug link name, crc.
+    static size_t
+    GetSectionHeaderInfo(SectionHeaderColl &section_headers,
+                         lldb_private::DataExtractor &data,
+                         const elf::ELFHeader &header,
+                         lldb_private::UUID &uuid,
+                         std::string &gnu_debuglink_file,
+                         uint32_t &gnu_debuglink_crc);
+
+    /// Scans the dynamic section and locates all dependent modules (shared
+    /// libraries) populating m_filespec_ap.  This method will compute the
+    /// dependent module list only once.  Returns the number of dependent
+    /// modules parsed.
+    size_t
+    ParseDependentModules();
+
+    /// Parses the dynamic symbol table and populates m_dynamic_symbols.  The
+    /// vector retains the order as found in the object file.  Returns the
+    /// number of dynamic symbols parsed.
+    size_t
+    ParseDynamicSymbols();
+
+    /// Populates m_symtab_ap will all non-dynamic linker symbols.  This method
+    /// will parse the symbols only once.  Returns the number of symbols parsed.
+    unsigned
+    ParseSymbolTable(lldb_private::Symtab *symbol_table,
+                     lldb::user_id_t start_id,
+                     lldb_private::Section *symtab);
+
+    /// Helper routine for ParseSymbolTable().
+    unsigned
+    ParseSymbols(lldb_private::Symtab *symbol_table, 
+                 lldb::user_id_t start_id,
+                 lldb_private::SectionList *section_list,
+                 const size_t num_symbols,
+                 const lldb_private::DataExtractor &symtab_data,
+                 const lldb_private::DataExtractor &strtab_data);
+
+    /// Scans the relocation entries and adds a set of artificial symbols to the
+    /// given symbol table for each PLT slot.  Returns the number of symbols
+    /// added.
+    unsigned
+    ParseTrampolineSymbols(lldb_private::Symtab *symbol_table, 
+                           lldb::user_id_t start_id,
+                           const ELFSectionHeaderInfo *rela_hdr,
+                           lldb::user_id_t section_id);
+
+    /// Returns the section header with the given id or NULL.
+    const ELFSectionHeaderInfo *
+    GetSectionHeaderByIndex(lldb::user_id_t id);
+
+    /// @name  ELF header dump routines
+    //@{
+    static void
+    DumpELFHeader(lldb_private::Stream *s, const elf::ELFHeader& header);
+
+    static void
+    DumpELFHeader_e_ident_EI_DATA(lldb_private::Stream *s,
+                                  unsigned char ei_data);
+
+    static void
+    DumpELFHeader_e_type(lldb_private::Stream *s, elf::elf_half e_type);
+    //@}
+
+    /// @name ELF program header dump routines
+    //@{
+    void
+    DumpELFProgramHeaders(lldb_private::Stream *s);
+
+    static void
+    DumpELFProgramHeader(lldb_private::Stream *s, 
+                         const elf::ELFProgramHeader &ph);
+
+    static void
+    DumpELFProgramHeader_p_type(lldb_private::Stream *s, elf::elf_word p_type);
+
+    static void
+    DumpELFProgramHeader_p_flags(lldb_private::Stream *s, 
+                                 elf::elf_word p_flags);
+    //@}
+
+    /// @name ELF section header dump routines
+    //@{
+    void
+    DumpELFSectionHeaders(lldb_private::Stream *s);
+
+    static void
+    DumpELFSectionHeader(lldb_private::Stream *s, 
+                         const ELFSectionHeaderInfo& sh);
+
+    static void
+    DumpELFSectionHeader_sh_type(lldb_private::Stream *s, 
+                                 elf::elf_word sh_type);
+
+    static void
+    DumpELFSectionHeader_sh_flags(lldb_private::Stream *s, 
+                                  elf::elf_xword sh_flags);
+    //@}
+
+    /// ELF dependent module dump routine.
+    void
+    DumpDependentModules(lldb_private::Stream *s);
+
+    const elf::ELFDynamic *
+    FindDynamicSymbol(unsigned tag);
+        
+    unsigned
+    PLTRelocationType();
+};
+
+#endif // #ifndef liblldb_ObjectFileELF_h_
diff --git a/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp b/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp
new file mode 100644
index 000000000000..4cfe38e5840f
--- /dev/null
+++ b/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp
@@ -0,0 +1,417 @@
+//===-- OperatingSystemPython.cpp --------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/lldb-python.h"
+
+#ifndef LLDB_DISABLE_PYTHON
+
+#include "OperatingSystemPython.h"
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/Debugger.h"
+#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"
+#include "lldb/Symbol/ClangNamespaceDecl.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/VariableList.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/StopInfo.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/ThreadList.h"
+#include "lldb/Target/Thread.h"
+#include "Plugins/Process/Utility/DynamicRegisterInfo.h"
+#include "Plugins/Process/Utility/RegisterContextDummy.h"
+#include "Plugins/Process/Utility/RegisterContextMemory.h"
+#include "Plugins/Process/Utility/ThreadMemory.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+void
+OperatingSystemPython::Initialize()
+{
+    PluginManager::RegisterPlugin (GetPluginNameStatic(),
+                                   GetPluginDescriptionStatic(),
+                                   CreateInstance);
+}
+
+void
+OperatingSystemPython::Terminate()
+{
+    PluginManager::UnregisterPlugin (CreateInstance);
+}
+
+OperatingSystem *
+OperatingSystemPython::CreateInstance (Process *process, bool force)
+{
+    // Python OperatingSystem plug-ins must be requested by name, so force must be true
+    FileSpec python_os_plugin_spec (process->GetPythonOSPluginPath());
+    if (python_os_plugin_spec && python_os_plugin_spec.Exists())
+    {
+        std::unique_ptr<OperatingSystemPython> os_ap (new OperatingSystemPython (process, python_os_plugin_spec));
+        if (os_ap.get() && os_ap->IsValid())
+            return os_ap.release();
+    }
+    return NULL;
+}
+
+
+ConstString
+OperatingSystemPython::GetPluginNameStatic()
+{
+    static ConstString g_name("python");
+    return g_name;
+}
+
+const char *
+OperatingSystemPython::GetPluginDescriptionStatic()
+{
+    return "Operating system plug-in that gathers OS information from a python class that implements the necessary OperatingSystem functionality.";
+}
+
+
+OperatingSystemPython::OperatingSystemPython (lldb_private::Process *process, const FileSpec &python_module_path) :
+    OperatingSystem (process),
+    m_thread_list_valobj_sp (),
+    m_register_info_ap (),
+    m_interpreter (NULL),
+    m_python_object_sp ()
+{
+    if (!process)
+        return;
+    TargetSP target_sp = process->CalculateTarget();
+    if (!target_sp)
+        return;
+    m_interpreter = target_sp->GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
+    if (m_interpreter)
+    {
+        
+        std::string os_plugin_class_name (python_module_path.GetFilename().AsCString(""));
+        if (!os_plugin_class_name.empty())
+        {
+            const bool init_session = false;
+            const bool allow_reload = true;
+            char python_module_path_cstr[PATH_MAX];
+            python_module_path.GetPath(python_module_path_cstr, sizeof(python_module_path_cstr));
+            Error error;
+            if (m_interpreter->LoadScriptingModule (python_module_path_cstr, allow_reload, init_session, error))
+            {
+                // Strip the ".py" extension if there is one
+                size_t py_extension_pos = os_plugin_class_name.rfind(".py");
+                if (py_extension_pos != std::string::npos)
+                    os_plugin_class_name.erase (py_extension_pos);
+                // Add ".OperatingSystemPlugIn" to the module name to get a string like "modulename.OperatingSystemPlugIn"
+                os_plugin_class_name += ".OperatingSystemPlugIn";
+                ScriptInterpreterObjectSP object_sp = m_interpreter->OSPlugin_CreatePluginObject(os_plugin_class_name.c_str(), process->CalculateProcess());
+                if (object_sp && object_sp->GetObject())
+                    m_python_object_sp = object_sp;
+            }
+        }
+    }
+}
+
+OperatingSystemPython::~OperatingSystemPython ()
+{
+}
+
+DynamicRegisterInfo *
+OperatingSystemPython::GetDynamicRegisterInfo ()
+{
+    if (m_register_info_ap.get() == NULL)
+    {
+        if (!m_interpreter || !m_python_object_sp)
+            return NULL;
+        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());
+        
+        PythonDictionary dictionary(m_interpreter->OSPlugin_RegisterInfo(m_python_object_sp));
+        if (!dictionary)
+            return NULL;
+        
+        m_register_info_ap.reset (new DynamicRegisterInfo (dictionary));
+        assert (m_register_info_ap->GetNumRegisters() > 0);
+        assert (m_register_info_ap->GetNumRegisterSets() > 0);
+    }
+    return m_register_info_ap.get();
+}
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+ConstString
+OperatingSystemPython::GetPluginName()
+{
+    return GetPluginNameStatic();
+}
+
+uint32_t
+OperatingSystemPython::GetPluginVersion()
+{
+    return 1;
+}
+
+bool
+OperatingSystemPython::UpdateThreadList (ThreadList &old_thread_list,
+                                         ThreadList &core_thread_list,
+                                         ThreadList &new_thread_list)
+{
+    if (!m_interpreter || !m_python_object_sp)
+        return false;
+    
+    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.
+    // So get & hold that.  This is a recursive lock so we can grant it to any Python code called on the stack below us.
+    Target &target = m_process->GetTarget();
+    Mutex::Locker api_locker (target.GetAPIMutex());
+    
+    if (log)
+        log->Printf ("OperatingSystemPython::UpdateThreadList() fetching thread data from python for pid %" PRIu64, m_process->GetID());
+
+    // The threads that are in "new_thread_list" upon entry are the threads from the
+    // lldb_private::Process subclass, no memory threads will be in this list.
+    
+    auto lock = m_interpreter->AcquireInterpreterLock(); // to make sure threads_list stays alive
+    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)
+        {
+            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);
+                }
+            }
+        }
+    }
+    
+    // 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 = core_thread_list;
+
+    return new_thread_list.GetSize(false) > 0;
+}
+
+ThreadSP
+OperatingSystemPython::CreateThreadFromThreadInfo (PythonDictionary &thread_dict,
+                                                   ThreadList &core_thread_list,
+                                                   ThreadList &old_thread_list,
+                                                   bool *did_create_ptr)
+{
+    ThreadSP thread_sp;
+    if (thread_dict)
+    {
+        PythonString tid_pystr("tid");
+        const tid_t tid = thread_dict.GetItemForKeyAsInteger (tid_pystr, LLDB_INVALID_THREAD_ID);
+        if (tid != LLDB_INVALID_THREAD_ID)
+        {
+            PythonString core_pystr("core");
+            PythonString name_pystr("name");
+            PythonString queue_pystr("queue");
+            //PythonString state_pystr("state");
+            //PythonString stop_reason_pystr("stop_reason");
+            PythonString reg_data_addr_pystr ("register_data_addr");
+            
+            const uint32_t core_number = thread_dict.GetItemForKeyAsInteger (core_pystr, UINT32_MAX);
+            const addr_t reg_data_addr = thread_dict.GetItemForKeyAsInteger (reg_data_addr_pystr, LLDB_INVALID_ADDRESS);
+            const char *name = thread_dict.GetItemForKeyAsString (name_pystr);
+            const char *queue = thread_dict.GetItemForKeyAsString (queue_pystr);
+            //const char *state = thread_dict.GetItemForKeyAsString (state_pystr);
+            //const char *stop_reason = thread_dict.GetItemForKeyAsString (stop_reason_pystr);
+            
+            // See if a thread already exists for "tid"
+            thread_sp = old_thread_list.FindThreadByID (tid, false);
+            if (thread_sp)
+            {
+                // A thread already does exist for "tid", make sure it was an operating system
+                // plug-in generated thread.
+                if (!IsOperatingSystemPluginThread(thread_sp))
+                {
+                    // We have thread ID overlap between the protocol threads and the
+                    // operating system threads, clear the thread so we create an
+                    // operating system thread for this.
+                    thread_sp.reset();
+                }
+            }
+    
+            if (!thread_sp)
+            {
+                if (did_create_ptr)
+                    *did_create_ptr = true;
+                thread_sp.reset (new ThreadMemory (*m_process,
+                                                   tid,
+                                                   name,
+                                                   queue,
+                                                   reg_data_addr));
+                
+            }
+            
+            if (core_number < core_thread_list.GetSize(false))
+            {
+                ThreadSP core_thread_sp (core_thread_list.GetThreadAtIndex(core_number, false));
+                if (core_thread_sp)
+                {
+                    ThreadSP backing_core_thread_sp (core_thread_sp->GetBackingThread());
+                    if (backing_core_thread_sp)
+                    {
+                        thread_sp->SetBackingThread(backing_core_thread_sp);
+                    }
+                    else
+                    {
+                        thread_sp->SetBackingThread(core_thread_sp);
+                    }
+                }
+            }
+        }
+    }
+    return thread_sp;
+}
+
+
+
+void
+OperatingSystemPython::ThreadWasSelected (Thread *thread)
+{
+}
+
+RegisterContextSP
+OperatingSystemPython::CreateRegisterContextForThread (Thread *thread, addr_t reg_data_addr)
+{
+    RegisterContextSP reg_ctx_sp;
+    if (!m_interpreter || !m_python_object_sp || !thread)
+        return reg_ctx_sp;
+
+    if (!IsOperatingSystemPluginThread(thread->shared_from_this()))
+        return reg_ctx_sp;
+    
+    // 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.
+    // So get & hold that.  This is a recursive lock so we can grant it to any Python code called on the stack below us.
+    Target &target = m_process->GetTarget();
+    Mutex::Locker api_locker (target.GetAPIMutex());
+
+    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
+
+    auto lock = m_interpreter->AcquireInterpreterLock(); // to make sure python objects stays alive
+    if (reg_data_addr != LLDB_INVALID_ADDRESS)
+    {
+        // The registers data is in contiguous memory, just create the register
+        // context using the address provided
+        if (log)
+            log->Printf ("OperatingSystemPython::CreateRegisterContextForThread (tid = 0x%" PRIx64 ", 0x%" PRIx64 ", reg_data_addr = 0x%" PRIx64 ") creating memory register context",
+                         thread->GetID(),
+                         thread->GetProtocolID(),
+                         reg_data_addr);
+        reg_ctx_sp.reset (new RegisterContextMemory (*thread, 0, *GetDynamicRegisterInfo (), reg_data_addr));
+    }
+    else
+    {
+        // No register data address is provided, query the python plug-in to let
+        // it make up the data as it sees fit
+        if (log)
+            log->Printf ("OperatingSystemPython::CreateRegisterContextForThread (tid = 0x%" PRIx64 ", 0x%" PRIx64 ") fetching register data from python",
+                         thread->GetID(),
+                         thread->GetProtocolID());
+
+        PythonString reg_context_data(m_interpreter->OSPlugin_RegisterContextData (m_python_object_sp, thread->GetID()));
+        if (reg_context_data)
+        {
+            DataBufferSP data_sp (new DataBufferHeap (reg_context_data.GetString(),
+                                                      reg_context_data.GetSize()));
+            if (data_sp->GetByteSize())
+            {
+                RegisterContextMemory *reg_ctx_memory = new RegisterContextMemory (*thread, 0, *GetDynamicRegisterInfo (), LLDB_INVALID_ADDRESS);
+                if (reg_ctx_memory)
+                {
+                    reg_ctx_sp.reset(reg_ctx_memory);
+                    reg_ctx_memory->SetAllRegisterData (data_sp);
+                }
+            }
+        }
+    }
+    // if we still have no register data, fallback on a dummy context to avoid crashing
+    if (!reg_ctx_sp)
+    {
+        if (log)
+            log->Printf ("OperatingSystemPython::CreateRegisterContextForThread (tid = 0x%" PRIx64 ") forcing a dummy register context", thread->GetID());
+        reg_ctx_sp.reset(new RegisterContextDummy(*thread,0,target.GetArchitecture().GetAddressByteSize()));
+    }
+    return reg_ctx_sp;
+}
+
+StopInfoSP
+OperatingSystemPython::CreateThreadStopReason (lldb_private::Thread *thread)
+{
+    // We should have gotten the thread stop info from the dictionary of data for
+    // the thread in the initial call to get_thread_info(), this should have been
+    // cached so we can return it here
+    StopInfoSP stop_info_sp; //(StopInfo::CreateStopReasonWithSignal (*thread, SIGSTOP));
+    return stop_info_sp;
+}
+
+lldb::ThreadSP
+OperatingSystemPython::CreateThread (lldb::tid_t tid, addr_t context)
+{
+    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
+    
+    if (log)
+        log->Printf ("OperatingSystemPython::CreateThread (tid = 0x%" PRIx64 ", context = 0x%" PRIx64 ") fetching register data from python", tid, context);
+    
+    if (m_interpreter && m_python_object_sp)
+    {
+        // 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.
+        // So get & hold that.  This is a recursive lock so we can grant it to any Python code called on the stack below us.
+        Target &target = m_process->GetTarget();
+        Mutex::Locker api_locker (target.GetAPIMutex());
+        
+        auto lock = m_interpreter->AcquireInterpreterLock(); // to make sure thread_info_dict stays alive
+        PythonDictionary thread_info_dict (m_interpreter->OSPlugin_CreateThread(m_python_object_sp, tid, context));
+        if (thread_info_dict)
+        {
+            ThreadList core_threads(m_process);
+            ThreadList &thread_list = m_process->GetThreadList();
+            bool did_create = false;
+            ThreadSP thread_sp (CreateThreadFromThreadInfo (thread_info_dict, core_threads, thread_list, &did_create));
+            if (did_create)
+                thread_list.AddThread(thread_sp);
+            return thread_sp;
+        }
+    }
+    return ThreadSP();
+}
+
+
+
+#endif // #ifndef LLDB_DISABLE_PYTHON
diff --git a/source/Plugins/OperatingSystem/Python/OperatingSystemPython.h b/source/Plugins/OperatingSystem/Python/OperatingSystemPython.h
new file mode 100644
index 000000000000..077039e50d56
--- /dev/null
+++ b/source/Plugins/OperatingSystem/Python/OperatingSystemPython.h
@@ -0,0 +1,109 @@
+//===-- OperatingSystemPython.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_DISABLE_PYTHON
+
+#ifndef liblldb_OperatingSystemPython_h_
+#define liblldb_OperatingSystemPython_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+#include "lldb/Interpreter/ScriptInterpreter.h"
+#include "lldb/Target/OperatingSystem.h"
+
+class DynamicRegisterInfo;
+
+class OperatingSystemPython : public lldb_private::OperatingSystem
+{
+public:
+    //------------------------------------------------------------------
+    // Static Functions
+    //------------------------------------------------------------------
+    static lldb_private::OperatingSystem *
+    CreateInstance (lldb_private::Process *process, bool force);
+    
+    static void
+    Initialize();
+    
+    static void
+    Terminate();
+    
+    static lldb_private::ConstString
+    GetPluginNameStatic();
+    
+    static const char *
+    GetPluginDescriptionStatic();
+    
+    //------------------------------------------------------------------
+    // Class Methods
+    //------------------------------------------------------------------
+    OperatingSystemPython (lldb_private::Process *process,
+                           const lldb_private::FileSpec &python_module_path);
+    
+    virtual
+    ~OperatingSystemPython ();
+    
+    //------------------------------------------------------------------
+    // lldb_private::PluginInterface Methods
+    //------------------------------------------------------------------
+    virtual lldb_private::ConstString
+    GetPluginName();
+    
+    virtual uint32_t
+    GetPluginVersion();
+    
+    //------------------------------------------------------------------
+    // lldb_private::OperatingSystem Methods
+    //------------------------------------------------------------------
+    virtual bool
+    UpdateThreadList (lldb_private::ThreadList &old_thread_list,
+                      lldb_private::ThreadList &real_thread_list,
+                      lldb_private::ThreadList &new_thread_list);
+    
+    virtual void
+    ThreadWasSelected (lldb_private::Thread *thread);
+
+    virtual lldb::RegisterContextSP
+    CreateRegisterContextForThread (lldb_private::Thread *thread,
+                                    lldb::addr_t reg_data_addr);
+
+    virtual lldb::StopInfoSP
+    CreateThreadStopReason (lldb_private::Thread *thread);
+
+    //------------------------------------------------------------------
+    // Method for lazy creation of threads on demand
+    //------------------------------------------------------------------
+    virtual lldb::ThreadSP
+    CreateThread (lldb::tid_t tid, lldb::addr_t context);
+
+protected:
+    
+    bool IsValid() const
+    {
+        return m_python_object_sp && m_python_object_sp->GetObject() != NULL;
+    }
+    
+    lldb::ThreadSP
+    CreateThreadFromThreadInfo (lldb_private::PythonDictionary &thread_dict,
+                                lldb_private::ThreadList &core_thread_list,
+                                lldb_private::ThreadList &old_thread_list,
+                                bool *did_create_ptr);
+
+    DynamicRegisterInfo *
+    GetDynamicRegisterInfo ();
+
+    lldb::ValueObjectSP m_thread_list_valobj_sp;
+    std::unique_ptr<DynamicRegisterInfo> m_register_info_ap;
+    lldb_private::ScriptInterpreter *m_interpreter;
+    lldb::ScriptInterpreterObjectSP m_python_object_sp;
+    
+};
+
+#endif // #ifndef liblldb_OperatingSystemPython_h_
+#endif // #ifndef LLDB_DISABLE_PYTHON
diff --git a/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp b/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp
new file mode 100644
index 000000000000..dc0917255d9b
--- /dev/null
+++ b/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp
@@ -0,0 +1,648 @@
+//===-- PlatformFreeBSD.cpp ---------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/lldb-python.h"
+
+#include "PlatformFreeBSD.h"
+
+// C Includes
+#include <stdio.h>
+#include <sys/utsname.h>
+
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Host/Host.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+Platform *
+PlatformFreeBSD::CreateInstance (bool force, const lldb_private::ArchSpec *arch)
+{
+    // The only time we create an instance is when we are creating a remote
+    // freebsd platform
+    const bool is_host = false;
+
+    bool create = force;
+    if (create == false && arch && arch->IsValid())
+    {
+        const llvm::Triple &triple = arch->GetTriple();
+        switch (triple.getVendor())
+        {
+            case llvm::Triple::PC:
+                create = true;
+                break;
+                
+#if defined(__FreeBSD__) || defined(__OpenBSD__)
+            // Only accept "unknown" for the vendor if the host is BSD and
+            // it "unknown" wasn't specified (it was just returned becasue it
+            // was NOT specified)
+            case llvm::Triple::UnknownArch:
+                create = !arch->TripleVendorWasSpecified();
+                break;
+#endif
+            default:
+                break;
+        }
+        
+        if (create)
+        {
+            switch (triple.getOS())
+            {
+                case llvm::Triple::FreeBSD:
+                case llvm::Triple::KFreeBSD:
+                    break;
+                    
+#if defined(__FreeBSD__) || defined(__OpenBSD__)
+                // Only accept "unknown" for the OS if the host is BSD and
+                // it "unknown" wasn't specified (it was just returned becasue it
+                // was NOT specified)
+                case llvm::Triple::UnknownOS:
+                    create = arch->TripleOSWasSpecified();
+                    break;
+#endif
+                default:
+                    create = false;
+                    break;
+            }
+        }
+    }
+    if (create)
+        return new PlatformFreeBSD (is_host);
+    return NULL;
+
+}
+
+lldb_private::ConstString
+PlatformFreeBSD::GetPluginNameStatic (bool is_host)
+{
+    if (is_host)
+    {
+        static ConstString g_host_name(Platform::GetHostPlatformName ());
+        return g_host_name;
+    }
+    else
+    {
+        static ConstString g_remote_name("remote-freebsd");
+        return g_remote_name;
+    }
+}
+
+const char *
+PlatformFreeBSD::GetDescriptionStatic (bool is_host)
+{
+    if (is_host)
+        return "Local FreeBSD user platform plug-in.";
+    else
+        return "Remote FreeBSD user platform plug-in.";
+}
+
+static uint32_t g_initialize_count = 0;
+
+void
+PlatformFreeBSD::Initialize ()
+{
+    if (g_initialize_count++ == 0)
+    {
+#if defined (__FreeBSD__)
+    	// Force a host flag to true for the default platform object.
+        PlatformSP default_platform_sp (new PlatformFreeBSD(true));
+        default_platform_sp->SetSystemArchitecture (Host::GetArchitecture());
+        Platform::SetDefaultPlatform (default_platform_sp);
+#endif
+        PluginManager::RegisterPlugin(PlatformFreeBSD::GetPluginNameStatic(false),
+                                      PlatformFreeBSD::GetDescriptionStatic(false),
+                                      PlatformFreeBSD::CreateInstance);
+    }
+}
+
+void
+PlatformFreeBSD::Terminate ()
+{
+    if (g_initialize_count > 0 && --g_initialize_count == 0)
+    	PluginManager::UnregisterPlugin (PlatformFreeBSD::CreateInstance);
+}
+
+//------------------------------------------------------------------
+/// Default Constructor
+//------------------------------------------------------------------
+PlatformFreeBSD::PlatformFreeBSD (bool is_host) :
+Platform(is_host)
+{
+}
+
+//------------------------------------------------------------------
+/// Destructor.
+///
+/// The destructor is virtual since this class is designed to be
+/// inherited from by the plug-in instance.
+//------------------------------------------------------------------
+PlatformFreeBSD::~PlatformFreeBSD()
+{
+}
+
+
+Error
+PlatformFreeBSD::ResolveExecutable (const FileSpec &exe_file,
+                                    const ArchSpec &exe_arch,
+                                    lldb::ModuleSP &exe_module_sp,
+                                    const FileSpecList *module_search_paths_ptr)
+{
+    Error error;
+    // Nothing special to do here, just use the actual file and architecture
+
+    char exe_path[PATH_MAX];
+    FileSpec resolved_exe_file (exe_file);
+
+    if (IsHost())
+    {
+        // If we have "ls" as the exe_file, resolve the executable location based on
+        // the current path variables
+        if (!resolved_exe_file.Exists())
+        {
+            exe_file.GetPath(exe_path, sizeof(exe_path));
+            resolved_exe_file.SetFile(exe_path, true);
+        }
+
+        if (!resolved_exe_file.Exists())
+            resolved_exe_file.ResolveExecutableLocation ();
+
+        if (resolved_exe_file.Exists())
+            error.Clear();
+        else
+        {
+            exe_file.GetPath(exe_path, sizeof(exe_path));
+            error.SetErrorStringWithFormat("unable to find executable for '%s'", exe_path);
+        }
+    }
+    else
+    {
+        if (m_remote_platform_sp)
+        {
+            error = m_remote_platform_sp->ResolveExecutable (exe_file,
+                                                             exe_arch,
+                                                             exe_module_sp,
+                                                             module_search_paths_ptr);
+        }
+        else
+        {
+            // We may connect to a process and use the provided executable (Don't use local $PATH).
+            
+            // Resolve any executable within a bundle on MacOSX
+            Host::ResolveExecutableInBundle (resolved_exe_file);
+            
+            if (resolved_exe_file.Exists()) {
+                error.Clear();
+            }
+            else
+            {
+                exe_file.GetPath(exe_path, sizeof(exe_path));
+                error.SetErrorStringWithFormat("the platform is not currently connected, and '%s' doesn't exist in the system root.", exe_path);
+            }
+        }
+    }
+
+
+    if (error.Success())
+    {
+        ModuleSpec module_spec (resolved_exe_file, exe_arch);
+        if (module_spec.GetArchitecture().IsValid())
+        {
+            error = ModuleList::GetSharedModule (module_spec,
+                                                 exe_module_sp,
+                                                 module_search_paths_ptr,
+                                                 NULL,
+                                                 NULL);
+
+            if (!exe_module_sp || exe_module_sp->GetObjectFile() == NULL)
+            {
+                exe_module_sp.reset();
+                error.SetErrorStringWithFormat ("'%s' doesn't contain the architecture %s",
+                                                exe_file.GetPath().c_str(),
+                                                exe_arch.GetArchitectureName());
+            }
+        }
+        else
+        {
+            // No valid architecture was specified, ask the platform for
+            // the architectures that we should be using (in the correct order)
+            // and see if we can find a match that way
+            StreamString arch_names;
+            ArchSpec platform_arch;
+            for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, platform_arch); ++idx)
+            {
+                error = ModuleList::GetSharedModule (module_spec,
+                                                     exe_module_sp,
+                                                     module_search_paths_ptr,
+                                                     NULL,
+                                                     NULL);
+                // Did we find an executable using one of the
+                if (error.Success())
+                {
+                    if (exe_module_sp && exe_module_sp->GetObjectFile())
+                        break;
+                    else
+                        error.SetErrorToGenericError();
+                }
+
+                if (idx > 0)
+                    arch_names.PutCString (", ");
+                arch_names.PutCString (platform_arch.GetArchitectureName());
+            }
+
+            if (error.Fail() || !exe_module_sp)
+            {
+                error.SetErrorStringWithFormat ("'%s' doesn't contain any '%s' platform architectures: %s",
+                                                exe_file.GetPath().c_str(),
+                                                GetPluginName().GetCString(),
+                                                arch_names.GetString().c_str());
+            }
+        }
+    }
+    else
+    {
+        error.SetErrorStringWithFormat ("'%s' does not exist",
+                                        exe_file.GetPath().c_str());
+    }
+
+    return error;
+}
+
+size_t
+PlatformFreeBSD::GetSoftwareBreakpointTrapOpcode (Target &target, BreakpointSite *bp_site)
+{
+    ArchSpec arch = target.GetArchitecture();
+    const uint8_t *trap_opcode = NULL;
+    size_t trap_opcode_size = 0;
+
+    switch (arch.GetCore())
+    {
+    default:
+        assert(false && "Unhandled architecture in PlatformFreeBSD::GetSoftwareBreakpointTrapOpcode()");
+        break;
+
+    case ArchSpec::eCore_x86_32_i386:
+    case ArchSpec::eCore_x86_64_x86_64:
+        {
+            static const uint8_t g_i386_opcode[] = { 0xCC };
+            trap_opcode = g_i386_opcode;
+            trap_opcode_size = sizeof(g_i386_opcode);
+        }
+        break;
+    }
+
+    if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size))
+        return trap_opcode_size;
+
+    return 0;
+}
+
+bool
+PlatformFreeBSD::GetRemoteOSVersion ()
+{
+    if (m_remote_platform_sp)
+        return m_remote_platform_sp->GetOSVersion (m_major_os_version,
+                                                   m_minor_os_version,
+                                                   m_update_os_version);
+    return false;
+}
+
+bool
+PlatformFreeBSD::GetRemoteOSBuildString (std::string &s)
+{
+    if (m_remote_platform_sp)
+        return m_remote_platform_sp->GetRemoteOSBuildString (s);
+    s.clear();
+    return false;
+}
+
+bool
+PlatformFreeBSD::GetRemoteOSKernelDescription (std::string &s)
+{
+    if (m_remote_platform_sp)
+        return m_remote_platform_sp->GetRemoteOSKernelDescription (s);
+    s.clear();
+    return false;
+}
+
+// Remote Platform subclasses need to override this function
+ArchSpec
+PlatformFreeBSD::GetRemoteSystemArchitecture ()
+{
+    if (m_remote_platform_sp)
+        return m_remote_platform_sp->GetRemoteSystemArchitecture ();
+    return ArchSpec();
+}
+
+
+const char *
+PlatformFreeBSD::GetHostname ()
+{
+    if (IsHost())
+        return Platform::GetHostname();
+
+    if (m_remote_platform_sp)
+        return m_remote_platform_sp->GetHostname ();
+    return NULL;
+}
+
+bool
+PlatformFreeBSD::IsConnected () const
+{
+    if (IsHost())
+        return true;
+    else if (m_remote_platform_sp)
+        return m_remote_platform_sp->IsConnected();
+    return false;
+}
+
+Error
+PlatformFreeBSD::ConnectRemote (Args& args)
+{
+    Error error;
+    if (IsHost())
+    {
+        error.SetErrorStringWithFormat ("can't connect to the host platform '%s', always connected", GetPluginName().GetCString());
+    }
+    else
+    {
+        if (!m_remote_platform_sp)
+            m_remote_platform_sp = Platform::Create ("remote-gdb-server", error);
+
+        if (m_remote_platform_sp)
+        {
+            if (error.Success())
+            {
+                if (m_remote_platform_sp)
+                {
+                    error = m_remote_platform_sp->ConnectRemote (args);
+                }
+                else
+                {
+                    error.SetErrorString ("\"platform connect\" takes a single argument: <connect-url>");
+                }
+            }
+        }
+        else
+            error.SetErrorString ("failed to create a 'remote-gdb-server' platform");
+
+        if (error.Fail())
+            m_remote_platform_sp.reset();
+    }
+
+    return error;
+}
+
+Error
+PlatformFreeBSD::DisconnectRemote ()
+{
+    Error error;
+
+    if (IsHost())
+    {
+        error.SetErrorStringWithFormat ("can't disconnect from the host platform '%s', always connected", GetPluginName().GetCString());
+    }
+    else
+    {
+        if (m_remote_platform_sp)
+            error = m_remote_platform_sp->DisconnectRemote ();
+        else
+            error.SetErrorString ("the platform is not currently connected");
+    }
+    return error;
+}
+
+bool
+PlatformFreeBSD::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
+{
+    bool success = false;
+    if (IsHost())
+    {
+        success = Platform::GetProcessInfo (pid, process_info);
+    }
+    else if (m_remote_platform_sp) 
+    {
+        success = m_remote_platform_sp->GetProcessInfo (pid, process_info);
+    }
+    return success;
+}
+
+
+
+uint32_t
+PlatformFreeBSD::FindProcesses (const ProcessInstanceInfoMatch &match_info,
+                               ProcessInstanceInfoList &process_infos)
+{
+    uint32_t match_count = 0;
+    if (IsHost())
+    {
+        // Let the base class figure out the host details
+        match_count = Platform::FindProcesses (match_info, process_infos);
+    }
+    else
+    {
+        // If we are remote, we can only return results if we are connected
+        if (m_remote_platform_sp)
+            match_count = m_remote_platform_sp->FindProcesses (match_info, process_infos);
+    }
+    return match_count;
+}
+
+Error
+PlatformFreeBSD::LaunchProcess (ProcessLaunchInfo &launch_info)
+{
+    Error error;
+    if (IsHost())
+    {
+        error = Platform::LaunchProcess (launch_info);
+    }
+    else
+    {
+        if (m_remote_platform_sp)
+            error = m_remote_platform_sp->LaunchProcess (launch_info);
+        else
+            error.SetErrorString ("the platform is not currently connected");
+    }
+    return error;
+}
+
+lldb::ProcessSP
+PlatformFreeBSD::Attach(ProcessAttachInfo &attach_info,
+                        Debugger &debugger,
+                        Target *target,
+                        Listener &listener,
+                        Error &error)
+{
+    lldb::ProcessSP process_sp;
+    if (IsHost())
+    {
+        if (target == NULL)
+        {
+            TargetSP new_target_sp;
+            ArchSpec emptyArchSpec;
+
+            error = debugger.GetTargetList().CreateTarget (debugger,
+                                                           NULL,
+                                                           emptyArchSpec,
+                                                           false,
+                                                           m_remote_platform_sp,
+                                                           new_target_sp);
+            target = new_target_sp.get();
+        }
+        else
+            error.Clear();
+
+        if (target && error.Success())
+        {
+            debugger.GetTargetList().SetSelectedTarget(target);
+            // The freebsd always currently uses the GDB remote debugger plug-in
+            // so even when debugging locally we are debugging remotely!
+            // Just like the darwin plugin.
+            process_sp = target->CreateProcess (listener, "gdb-remote", NULL);
+
+            if (process_sp)
+                error = process_sp->Attach (attach_info);
+        }
+    }
+    else
+    {
+        if (m_remote_platform_sp)
+            process_sp = m_remote_platform_sp->Attach (attach_info, debugger, target, listener, error);
+        else
+            error.SetErrorString ("the platform is not currently connected");
+    }
+    return process_sp;
+}
+
+const char *
+PlatformFreeBSD::GetUserName (uint32_t uid)
+{
+    // Check the cache in Platform in case we have already looked this uid up
+    const char *user_name = Platform::GetUserName(uid);
+    if (user_name)
+        return user_name;
+
+    if (IsRemote() && m_remote_platform_sp)
+        return m_remote_platform_sp->GetUserName(uid);
+    return NULL;
+}
+
+const char *
+PlatformFreeBSD::GetGroupName (uint32_t gid)
+{
+    const char *group_name = Platform::GetGroupName(gid);
+    if (group_name)
+        return group_name;
+
+    if (IsRemote() && m_remote_platform_sp)
+        return m_remote_platform_sp->GetGroupName(gid);
+    return NULL;
+}
+
+
+// From PlatformMacOSX only
+Error
+PlatformFreeBSD::GetFile (const FileSpec &platform_file,
+                          const UUID *uuid_ptr,
+                          FileSpec &local_file)
+{
+    if (IsRemote())
+    {
+        if (m_remote_platform_sp)
+            return m_remote_platform_sp->GetFile (platform_file, uuid_ptr, local_file);
+    }
+
+    // Default to the local case
+    local_file = platform_file;
+    return Error();
+}
+
+Error
+PlatformFreeBSD::GetSharedModule (const ModuleSpec &module_spec,
+                                  ModuleSP &module_sp,
+                                  const FileSpecList *module_search_paths_ptr,
+                                  ModuleSP *old_module_sp_ptr,
+                                  bool *did_create_ptr)
+{
+    Error error;
+    module_sp.reset();
+
+    if (IsRemote())
+    {
+        // If we have a remote platform always, let it try and locate
+        // the shared module first.
+        if (m_remote_platform_sp)
+        {
+            error = m_remote_platform_sp->GetSharedModule (module_spec,
+                                                           module_sp,
+                                                           module_search_paths_ptr,
+                                                           old_module_sp_ptr,
+                                                           did_create_ptr);
+        }
+    }
+
+    if (!module_sp)
+    {
+        // Fall back to the local platform and find the file locally
+        error = Platform::GetSharedModule (module_spec,
+                                           module_sp,
+                                           module_search_paths_ptr,
+                                           old_module_sp_ptr,
+                                           did_create_ptr);
+    }
+    if (module_sp)
+        module_sp->SetPlatformFileSpec(module_spec.GetFileSpec());
+    return error;
+}
+
+
+bool
+PlatformFreeBSD::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch)
+{
+    // From macosx;s plugin code. For FreeBSD we may want to support more archs.
+    if (idx == 0)
+    {
+        arch = Host::GetArchitecture (Host::eSystemDefaultArchitecture);
+        return arch.IsValid();
+    }
+    else if (idx == 1)
+    {
+        ArchSpec platform_arch (Host::GetArchitecture (Host::eSystemDefaultArchitecture));
+        ArchSpec platform_arch64 (Host::GetArchitecture (Host::eSystemDefaultArchitecture64));
+        if (platform_arch.IsExactMatch(platform_arch64))
+        {
+            // This freebsd platform supports both 32 and 64 bit. Since we already
+            // returned the 64 bit arch for idx == 0, return the 32 bit arch
+            // for idx == 1
+            arch = Host::GetArchitecture (Host::eSystemDefaultArchitecture32);
+            return arch.IsValid();
+        }
+    }
+    return false;
+}
+
+void
+PlatformFreeBSD::GetStatus (Stream &strm)
+{
+    struct utsname un;
+
+    if (uname(&un)) {
+        strm << "FreeBSD";
+        return;
+    }
+
+    strm << "Host: " << un.sysname << ' ' << un.release << ' ' << un.version << '\n';
+    Platform::GetStatus(strm);
+}
diff --git a/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h b/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h
new file mode 100644
index 000000000000..4aa158eb6e87
--- /dev/null
+++ b/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h
@@ -0,0 +1,162 @@
+//===-- PlatformFreeBSD.h -----------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_PlatformFreeBSD_h_
+#define liblldb_PlatformFreeBSD_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Target/Platform.h"
+
+class PlatformFreeBSD : public lldb_private::Platform
+{
+public:
+    // Mostly taken from PlatformDarwin and PlatformMacOSX
+
+    //------------------------------------------------------------
+    // Class functions
+    //------------------------------------------------------------
+    static lldb_private::Platform*
+    CreateInstance (bool force, const lldb_private::ArchSpec *arch);
+
+    static void
+    Initialize ();
+
+    static void
+    Terminate ();
+
+    static lldb_private::ConstString
+    GetPluginNameStatic (bool is_host);
+
+    static const char *
+    GetDescriptionStatic (bool is_host);
+
+    //------------------------------------------------------------
+    // Class Methods
+    //------------------------------------------------------------
+    PlatformFreeBSD (bool is_host);
+
+    virtual
+    ~PlatformFreeBSD();
+
+    //------------------------------------------------------------
+    // lldb_private::PluginInterface functions
+    //------------------------------------------------------------
+    virtual lldb_private::ConstString
+    GetPluginName()
+    {
+        return GetPluginNameStatic (IsHost());
+    }
+
+    virtual uint32_t
+    GetPluginVersion()
+    {
+        return 1;
+    }
+
+    virtual const char *
+    GetDescription ()
+    {
+        return GetDescriptionStatic(IsHost());
+    }
+
+    //------------------------------------------------------------
+    // lldb_private::Platform functions
+    //------------------------------------------------------------
+    virtual lldb_private::Error
+    ResolveExecutable (const lldb_private::FileSpec &exe_file,
+                       const lldb_private::ArchSpec &arch,
+                       lldb::ModuleSP &module_sp,
+                       const lldb_private::FileSpecList *module_search_paths_ptr);
+
+    virtual size_t
+    GetSoftwareBreakpointTrapOpcode (lldb_private::Target &target,
+                                     lldb_private::BreakpointSite *bp_site);
+
+    virtual bool
+    GetRemoteOSVersion ();
+
+    virtual bool
+    GetRemoteOSBuildString (std::string &s);
+
+    virtual bool
+    GetRemoteOSKernelDescription (std::string &s);
+
+    // Remote Platform subclasses need to override this function
+    virtual lldb_private::ArchSpec
+    GetRemoteSystemArchitecture ();
+
+    virtual bool
+    IsConnected () const;
+
+    virtual lldb_private::Error
+    ConnectRemote (lldb_private::Args& args);
+
+    virtual lldb_private::Error
+    DisconnectRemote ();
+
+    virtual const char *
+    GetHostname ();
+
+    virtual const char *
+    GetUserName (uint32_t uid);
+
+    virtual const char *
+    GetGroupName (uint32_t gid);
+
+    virtual bool
+    GetProcessInfo (lldb::pid_t pid,
+                    lldb_private::ProcessInstanceInfo &proc_info);
+
+    virtual uint32_t
+    FindProcesses (const lldb_private::ProcessInstanceInfoMatch &match_info,
+                   lldb_private::ProcessInstanceInfoList &process_infos);
+
+    virtual lldb_private::Error
+    LaunchProcess (lldb_private::ProcessLaunchInfo &launch_info);
+
+    virtual lldb::ProcessSP
+    Attach(lldb_private::ProcessAttachInfo &attach_info,
+           lldb_private::Debugger &debugger,
+           lldb_private::Target *target,
+           lldb_private::Listener &listener,
+           lldb_private::Error &error);
+
+    // FreeBSD processes can not be launched by spawning and attaching.
+    virtual bool
+    CanDebugProcess () { return false; }
+
+    // Only on PlatformMacOSX:
+    virtual lldb_private::Error
+    GetFile (const lldb_private::FileSpec &platform_file,
+             const lldb_private::UUID* uuid, lldb_private::FileSpec &local_file);
+
+    lldb_private::Error
+    GetSharedModule (const lldb_private::ModuleSpec &module_spec,
+                     lldb::ModuleSP &module_sp,
+                     const lldb_private::FileSpecList *module_search_paths_ptr,
+                     lldb::ModuleSP *old_module_sp_ptr,
+                     bool *did_create_ptr);
+
+    virtual bool
+    GetSupportedArchitectureAtIndex (uint32_t idx, lldb_private::ArchSpec &arch);
+
+    virtual void
+    GetStatus (lldb_private::Stream &strm);
+
+protected:
+    lldb::PlatformSP m_remote_platform_sp; // Allow multiple ways to connect to a remote freebsd OS
+
+private:
+    DISALLOW_COPY_AND_ASSIGN (PlatformFreeBSD);
+};
+
+#endif  // liblldb_PlatformFreeBSD_h_
diff --git a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
new file mode 100644
index 000000000000..684d1921e920
--- /dev/null
+++ b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
@@ -0,0 +1,418 @@
+//===-- PlatformRemoteGDBServer.cpp -----------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/lldb-python.h"
+
+#include "PlatformRemoteGDBServer.h"
+
+// C Includes
+#include <sys/sysctl.h>
+
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Core/ConnectionFileDescriptor.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleList.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Host/FileSpec.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+static bool g_initialized = false;
+
+void
+PlatformRemoteGDBServer::Initialize ()
+{
+    if (g_initialized == false)
+    {
+        g_initialized = true;
+        PluginManager::RegisterPlugin (PlatformRemoteGDBServer::GetPluginNameStatic(),
+                                       PlatformRemoteGDBServer::GetDescriptionStatic(),
+                                       PlatformRemoteGDBServer::CreateInstance);
+    }
+}
+
+void
+PlatformRemoteGDBServer::Terminate ()
+{
+    if (g_initialized)
+    {
+        g_initialized = false;
+        PluginManager::UnregisterPlugin (PlatformRemoteGDBServer::CreateInstance);
+    }
+}
+
+Platform* 
+PlatformRemoteGDBServer::CreateInstance (bool force, const lldb_private::ArchSpec *arch)
+{
+    bool create = force;
+    if (!create)
+    {
+        create = !arch->TripleVendorWasSpecified() && !arch->TripleOSWasSpecified();
+    }
+    if (create)
+        return new PlatformRemoteGDBServer ();
+    return NULL;
+}
+
+
+lldb_private::ConstString
+PlatformRemoteGDBServer::GetPluginNameStatic()
+{
+    static ConstString g_name("remote-gdb-server");
+    return g_name;
+}
+
+const char *
+PlatformRemoteGDBServer::GetDescriptionStatic()
+{
+    return "A platform that uses the GDB remote protocol as the communication transport.";
+}
+
+const char *
+PlatformRemoteGDBServer::GetDescription ()
+{
+    if (m_platform_description.empty())
+    {
+        if (IsConnected())
+        {
+            // Send the get description packet
+        }
+    }
+    
+    if (!m_platform_description.empty())
+        return m_platform_description.c_str();
+    return GetDescriptionStatic();
+}
+
+Error
+PlatformRemoteGDBServer::ResolveExecutable (const FileSpec &exe_file,
+                                            const ArchSpec &exe_arch,
+                                            lldb::ModuleSP &exe_module_sp,
+                                            const FileSpecList *module_search_paths_ptr)
+{
+    Error error;
+    error.SetErrorString ("PlatformRemoteGDBServer::ResolveExecutable() is unimplemented");
+    return error;
+}
+
+Error
+PlatformRemoteGDBServer::GetFile (const FileSpec &platform_file, 
+                                  const UUID *uuid_ptr,
+                                  FileSpec &local_file)
+{
+    // Default to the local case
+    local_file = platform_file;
+    return Error();
+}
+
+//------------------------------------------------------------------
+/// Default Constructor
+//------------------------------------------------------------------
+PlatformRemoteGDBServer::PlatformRemoteGDBServer () :
+    Platform(false), // This is a remote platform
+    m_gdb_client(true)
+{
+}
+
+//------------------------------------------------------------------
+/// Destructor.
+///
+/// The destructor is virtual since this class is designed to be
+/// inherited from by the plug-in instance.
+//------------------------------------------------------------------
+PlatformRemoteGDBServer::~PlatformRemoteGDBServer()
+{
+}
+
+bool
+PlatformRemoteGDBServer::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch)
+{
+    return false;
+}
+
+size_t
+PlatformRemoteGDBServer::GetSoftwareBreakpointTrapOpcode (Target &target, BreakpointSite *bp_site)
+{
+    // This isn't needed if the z/Z packets are supported in the GDB remote
+    // server. But we might need a packet to detect this.
+    return 0;
+}
+
+bool
+PlatformRemoteGDBServer::GetRemoteOSVersion ()
+{
+    uint32_t major, minor, update;
+    if (m_gdb_client.GetOSVersion (major, minor, update))
+    {
+        m_major_os_version = major;
+        m_minor_os_version = minor;
+        m_update_os_version = update;
+        return true;
+    }
+    return false;
+}
+
+bool
+PlatformRemoteGDBServer::GetRemoteOSBuildString (std::string &s)
+{
+    return m_gdb_client.GetOSBuildString (s);
+}
+
+bool
+PlatformRemoteGDBServer::GetRemoteOSKernelDescription (std::string &s)
+{
+    return m_gdb_client.GetOSKernelDescription (s);
+}
+
+// Remote Platform subclasses need to override this function
+ArchSpec
+PlatformRemoteGDBServer::GetRemoteSystemArchitecture ()
+{
+    return m_gdb_client.GetSystemArchitecture();
+}
+
+bool
+PlatformRemoteGDBServer::IsConnected () const
+{
+    return m_gdb_client.IsConnected();
+}        
+
+Error
+PlatformRemoteGDBServer::ConnectRemote (Args& args)
+{
+    Error error;
+    if (IsConnected())
+    {
+        error.SetErrorStringWithFormat ("the platform is already connected to '%s', execute 'platform disconnect' to close the current connection", 
+                                        GetHostname());
+    }
+    else
+    {
+        if (args.GetArgumentCount() == 1)
+        {
+            const char *url = args.GetArgumentAtIndex(0);
+            m_gdb_client.SetConnection (new ConnectionFileDescriptor());
+            const ConnectionStatus status = m_gdb_client.Connect(url, &error);
+            if (status == eConnectionStatusSuccess)
+            {
+                if (m_gdb_client.HandshakeWithServer(&error))
+                {
+                    m_gdb_client.QueryNoAckModeSupported();
+                    m_gdb_client.GetHostInfo();
+#if 0
+                    m_gdb_client.TestPacketSpeed(10000);
+#endif
+                }
+                else
+                {
+                    m_gdb_client.Disconnect();
+                }
+            }
+        }
+        else
+        {
+            error.SetErrorString ("\"platform connect\" takes a single argument: <connect-url>");
+        }
+    }
+
+    return error;
+}
+
+Error
+PlatformRemoteGDBServer::DisconnectRemote ()
+{
+    Error error;
+    m_gdb_client.Disconnect(&error);
+    return error;
+}
+
+const char *
+PlatformRemoteGDBServer::GetHostname ()
+{
+    m_gdb_client.GetHostname (m_name);
+    if (m_name.empty())
+        return NULL;
+    return m_name.c_str();
+}
+
+const char *
+PlatformRemoteGDBServer::GetUserName (uint32_t uid)
+{
+    // Try and get a cache user name first
+    const char *cached_user_name = Platform::GetUserName(uid);
+    if (cached_user_name)
+        return cached_user_name;
+    std::string name;
+    if (m_gdb_client.GetUserName(uid, name))
+        return SetCachedUserName(uid, name.c_str(), name.size());
+
+    SetUserNameNotFound(uid); // Negative cache so we don't keep sending packets
+    return NULL;
+}
+
+const char *
+PlatformRemoteGDBServer::GetGroupName (uint32_t gid)
+{
+    const char *cached_group_name = Platform::GetGroupName(gid);
+    if (cached_group_name)
+        return cached_group_name;
+    std::string name;
+    if (m_gdb_client.GetGroupName(gid, name))
+        return SetCachedGroupName(gid, name.c_str(), name.size());
+
+    SetGroupNameNotFound(gid); // Negative cache so we don't keep sending packets
+    return NULL;
+}
+
+uint32_t
+PlatformRemoteGDBServer::FindProcesses (const ProcessInstanceInfoMatch &match_info,
+                                        ProcessInstanceInfoList &process_infos)
+{
+    return m_gdb_client.FindProcesses (match_info, process_infos);
+}
+
+bool
+PlatformRemoteGDBServer::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
+{
+    return m_gdb_client.GetProcessInfo (pid, process_info);
+}
+
+
+Error
+PlatformRemoteGDBServer::LaunchProcess (ProcessLaunchInfo &launch_info)
+{
+    Error error;
+    lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
+    
+    m_gdb_client.SetSTDIN ("/dev/null");
+    m_gdb_client.SetSTDOUT ("/dev/null");
+    m_gdb_client.SetSTDERR ("/dev/null");
+    m_gdb_client.SetDisableASLR (launch_info.GetFlags().Test (eLaunchFlagDisableASLR));
+    
+    const char *working_dir = launch_info.GetWorkingDirectory();
+    if (working_dir && working_dir[0])
+    {
+        m_gdb_client.SetWorkingDir (working_dir);
+    }
+    
+    // Send the environment and the program + arguments after we connect
+    const char **argv = launch_info.GetArguments().GetConstArgumentVector();
+    const char **envp = launch_info.GetEnvironmentEntries().GetConstArgumentVector();
+
+    if (envp)
+    {
+        const char *env_entry;
+        for (int i=0; (env_entry = envp[i]); ++i)
+        {
+            if (m_gdb_client.SendEnvironmentPacket(env_entry) != 0)
+                break;
+        }
+    }
+    const uint32_t old_packet_timeout = m_gdb_client.SetPacketTimeout (5);
+    int arg_packet_err = m_gdb_client.SendArgumentsPacket (argv);
+    m_gdb_client.SetPacketTimeout (old_packet_timeout);
+    if (arg_packet_err == 0)
+    {
+        std::string error_str;
+        if (m_gdb_client.GetLaunchSuccess (error_str))
+        {
+            pid = m_gdb_client.GetCurrentProcessID ();
+            if (pid != LLDB_INVALID_PROCESS_ID)
+                launch_info.SetProcessID (pid);
+        }
+        else
+        {
+            error.SetErrorString (error_str.c_str());
+        }
+    }
+    else
+    {
+        error.SetErrorStringWithFormat("'A' packet returned an error: %i", arg_packet_err);
+    }
+    return error;
+}
+
+lldb::ProcessSP
+PlatformRemoteGDBServer::Attach (lldb_private::ProcessAttachInfo &attach_info,
+                                 Debugger &debugger,
+                                 Target *target,       // Can be NULL, if NULL create a new target, else use existing one
+                                 Listener &listener, 
+                                 Error &error)
+{
+    lldb::ProcessSP process_sp;
+    if (IsRemote())
+    {
+        if (IsConnected())
+        {
+            uint16_t port = m_gdb_client.LaunchGDBserverAndGetPort();
+            
+            if (port == 0)
+            {
+                error.SetErrorStringWithFormat ("unable to launch a GDB server on '%s'", GetHostname ());
+            }
+            else
+            {
+                if (target == NULL)
+                {
+                    TargetSP new_target_sp;
+                    
+                    error = debugger.GetTargetList().CreateTarget (debugger,
+                                                                   NULL,
+                                                                   NULL, 
+                                                                   false,
+                                                                   NULL,
+                                                                   new_target_sp);
+                    target = new_target_sp.get();
+                }
+                else
+                    error.Clear();
+                
+                if (target && error.Success())
+                {
+                    debugger.GetTargetList().SetSelectedTarget(target);
+                    
+                    // The darwin always currently uses the GDB remote debugger plug-in
+                    // so even when debugging locally we are debugging remotely!
+                    process_sp = target->CreateProcess (listener, "gdb-remote", NULL);
+                    
+                    if (process_sp)
+                    {
+                        char connect_url[256];
+                        const int connect_url_len = ::snprintf (connect_url, 
+                                                                sizeof(connect_url), 
+                                                                "connect://%s:%u", 
+                                                                GetHostname (), 
+                                                                port);
+                        assert (connect_url_len < (int)sizeof(connect_url));
+                        error = process_sp->ConnectRemote (NULL, connect_url);
+                        if (error.Success())
+                            error = process_sp->Attach(attach_info);
+                    }
+                }
+            }
+        }
+        else
+        {
+            error.SetErrorString("not connected to remote gdb server");
+        }
+    }
+    return process_sp;
+}
+
+
diff --git a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h
new file mode 100644
index 000000000000..22b3dd49be54
--- /dev/null
+++ b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h
@@ -0,0 +1,147 @@
+//===-- PlatformRemoteGDBServer.h ----------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_PlatformRemoteGDBServer_h_
+#define liblldb_PlatformRemoteGDBServer_h_
+
+// C Includes
+// C++ Includes
+#include <string>
+
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Target/Platform.h"
+#include "../../Process/gdb-remote/GDBRemoteCommunicationClient.h"
+
+class PlatformRemoteGDBServer : public lldb_private::Platform
+{
+public:
+
+    static void
+    Initialize ();
+
+    static void
+    Terminate ();
+    
+    static lldb_private::Platform* 
+    CreateInstance (bool force, const lldb_private::ArchSpec *arch);
+
+    static lldb_private::ConstString
+    GetPluginNameStatic();
+
+    static const char *
+    GetDescriptionStatic();
+
+
+    PlatformRemoteGDBServer ();
+
+    virtual
+    ~PlatformRemoteGDBServer();
+
+    //------------------------------------------------------------
+    // lldb_private::PluginInterface functions
+    //------------------------------------------------------------
+    virtual lldb_private::ConstString
+    GetPluginName()
+    {
+        return GetPluginNameStatic();
+    }
+    
+    virtual uint32_t
+    GetPluginVersion()
+    {
+        return 1;
+    }
+    
+
+    //------------------------------------------------------------
+    // lldb_private::Platform functions
+    //------------------------------------------------------------
+    virtual lldb_private::Error
+    ResolveExecutable (const lldb_private::FileSpec &exe_file,
+                       const lldb_private::ArchSpec &arch,
+                       lldb::ModuleSP &module_sp,
+                       const lldb_private::FileSpecList *module_search_paths_ptr);
+
+    virtual const char *
+    GetDescription ();
+
+    virtual lldb_private::Error
+    GetFile (const lldb_private::FileSpec &platform_file, 
+             const lldb_private::UUID *uuid_ptr,
+             lldb_private::FileSpec &local_file);
+
+    virtual bool
+    GetProcessInfo (lldb::pid_t pid, 
+                    lldb_private::ProcessInstanceInfo &proc_info);
+    
+    virtual uint32_t
+    FindProcesses (const lldb_private::ProcessInstanceInfoMatch &match_info,
+                   lldb_private::ProcessInstanceInfoList &process_infos);
+
+    virtual lldb_private::Error
+    LaunchProcess (lldb_private::ProcessLaunchInfo &launch_info);
+    
+    virtual lldb::ProcessSP
+    Attach (lldb_private::ProcessAttachInfo &attach_info,
+            lldb_private::Debugger &debugger,
+            lldb_private::Target *target,       // Can be NULL, if NULL create a new target, else use existing one
+            lldb_private::Listener &listener,
+            lldb_private::Error &error);
+
+    virtual bool
+    GetSupportedArchitectureAtIndex (uint32_t idx, lldb_private::ArchSpec &arch);
+
+    virtual size_t
+    GetSoftwareBreakpointTrapOpcode (lldb_private::Target &target, 
+                                     lldb_private::BreakpointSite *bp_site);
+
+    virtual bool
+    GetRemoteOSVersion ();
+
+    virtual bool
+    GetRemoteOSBuildString (std::string &s);
+    
+    virtual bool
+    GetRemoteOSKernelDescription (std::string &s);
+
+    // Remote Platform subclasses need to override this function
+    virtual lldb_private::ArchSpec
+    GetRemoteSystemArchitecture ();
+
+    // Remote subclasses should override this and return a valid instance
+    // name if connected.
+    virtual const char *
+    GetHostname ();
+
+    virtual const char *
+    GetUserName (uint32_t uid);
+    
+    virtual const char *
+    GetGroupName (uint32_t gid);
+
+    virtual bool
+    IsConnected () const;
+
+    virtual lldb_private::Error
+    ConnectRemote (lldb_private::Args& args);
+
+    virtual lldb_private::Error
+    DisconnectRemote ();
+
+protected:
+    GDBRemoteCommunicationClient m_gdb_client;
+    std::string m_platform_description; // After we connect we can get a more complete description of what we are connected to
+
+private:
+    DISALLOW_COPY_AND_ASSIGN (PlatformRemoteGDBServer);
+
+};
+
+#endif  // liblldb_PlatformRemoteGDBServer_h_
diff --git a/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp b/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp
new file mode 100644
index 000000000000..ea26d972b860
--- /dev/null
+++ b/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp
@@ -0,0 +1,132 @@
+//===-- ProcessFreeBSD.cpp ----------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+#include <errno.h>
+
+// C++ Includes
+// Other libraries and framework includes
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/State.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Target/DynamicLoader.h"
+#include "lldb/Target/Target.h"
+
+#include "ProcessFreeBSD.h"
+#include "ProcessPOSIXLog.h"
+#include "Plugins/Process/Utility/InferiorCallPOSIX.h"
+#include "ProcessMonitor.h"
+#include "POSIXThread.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//------------------------------------------------------------------------------
+// Static functions.
+
+lldb::ProcessSP
+ProcessFreeBSD::CreateInstance(Target& target,
+                               Listener &listener,
+                               const FileSpec *crash_file_path)
+{
+    lldb::ProcessSP process_sp;
+    if (crash_file_path == NULL)
+        process_sp.reset(new ProcessFreeBSD (target, listener));
+    return process_sp;
+}
+
+void
+ProcessFreeBSD::Initialize()
+{
+    static bool g_initialized = false;
+
+    if (!g_initialized)
+    {
+        PluginManager::RegisterPlugin(GetPluginNameStatic(),
+                                      GetPluginDescriptionStatic(),
+                                      CreateInstance);
+        Log::Callbacks log_callbacks = {
+            ProcessPOSIXLog::DisableLog,
+            ProcessPOSIXLog::EnableLog,
+            ProcessPOSIXLog::ListLogCategories
+        };
+
+        Log::RegisterLogChannel (ProcessFreeBSD::GetPluginNameStatic(), log_callbacks);
+        ProcessPOSIXLog::RegisterPluginName(GetPluginNameStatic());
+        g_initialized = true;
+    }
+}
+
+lldb_private::ConstString
+ProcessFreeBSD::GetPluginNameStatic()
+{
+    static ConstString g_name("freebsd");
+    return g_name;
+}
+
+const char *
+ProcessFreeBSD::GetPluginDescriptionStatic()
+{
+    return "Process plugin for FreeBSD";
+}
+
+//------------------------------------------------------------------------------
+// ProcessInterface protocol.
+
+lldb_private::ConstString
+ProcessFreeBSD::GetPluginName()
+{
+    return GetPluginNameStatic();
+}
+
+uint32_t
+ProcessFreeBSD::GetPluginVersion()
+{
+    return 1;
+}
+
+void
+ProcessFreeBSD::GetPluginCommandHelp(const char *command, Stream *strm)
+{
+}
+
+Error
+ProcessFreeBSD::ExecutePluginCommand(Args &command, Stream *strm)
+{
+    return Error(1, eErrorTypeGeneric);
+}
+
+Log *
+ProcessFreeBSD::EnablePluginLogging(Stream *strm, Args &command)
+{
+    return NULL;
+}
+
+//------------------------------------------------------------------------------
+// Constructors and destructors.
+
+ProcessFreeBSD::ProcessFreeBSD(Target& target, Listener &listener)
+    : ProcessPOSIX(target, listener)
+{
+}
+
+void
+ProcessFreeBSD::Terminate()
+{
+}
+
+bool
+ProcessFreeBSD::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list)
+{
+    // XXX haxx
+    new_thread_list = old_thread_list;
+  
+    return false;
+}
diff --git a/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h b/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h
new file mode 100644
index 000000000000..5f79b74cad30
--- /dev/null
+++ b/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h
@@ -0,0 +1,82 @@
+//===-- ProcessFreeBSD.h ------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ProcessFreeBSD_H_
+#define liblldb_ProcessFreeBSD_H_
+
+// C Includes
+
+// C++ Includes
+#include <queue>
+
+// Other libraries and framework includes
+#include "lldb/Target/Process.h"
+#include "lldb/Target/ThreadList.h"
+#include "ProcessMessage.h"
+#include "ProcessPOSIX.h"
+
+class ProcessMonitor;
+
+class ProcessFreeBSD :
+    public ProcessPOSIX
+{
+
+public:
+    //------------------------------------------------------------------
+    // Static functions.
+    //------------------------------------------------------------------
+    static lldb::ProcessSP
+    CreateInstance(lldb_private::Target& target,
+                   lldb_private::Listener &listener,
+                   const lldb_private::FileSpec *crash_file_path);
+
+    static void
+    Initialize();
+
+    static void
+    Terminate();
+
+    static lldb_private::ConstString
+    GetPluginNameStatic();
+
+    static const char *
+    GetPluginDescriptionStatic();
+
+    //------------------------------------------------------------------
+    // Constructors and destructors
+    //------------------------------------------------------------------
+    ProcessFreeBSD(lldb_private::Target& target,
+                   lldb_private::Listener &listener);
+
+    virtual bool
+    UpdateThreadList(lldb_private::ThreadList &old_thread_list, lldb_private::ThreadList &new_thread_list);
+
+    //------------------------------------------------------------------
+    // PluginInterface protocol
+    //------------------------------------------------------------------
+    virtual lldb_private::ConstString
+    GetPluginName();
+
+    virtual uint32_t
+    GetPluginVersion();
+
+    virtual void
+    GetPluginCommandHelp(const char *command, lldb_private::Stream *strm);
+
+    virtual lldb_private::Error
+    ExecutePluginCommand(lldb_private::Args &command,
+                         lldb_private::Stream *strm);
+
+    virtual lldb_private::Log *
+    EnablePluginLogging(lldb_private::Stream *strm,
+                        lldb_private::Args &command);
+
+};
+
+#endif  // liblldb_MacOSXProcess_H_
diff --git a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
new file mode 100644
index 000000000000..9fd51d2d640a
--- /dev/null
+++ b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
@@ -0,0 +1,1677 @@
+//===-- ProcessMonitor.cpp ------------------------------------ -*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+#include <errno.h>
+#include <poll.h>
+#include <string.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sys/ptrace.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+// C++ Includes
+// Other libraries and framework includes
+#include "lldb/Core/Error.h"
+#include "lldb/Core/RegisterValue.h"
+#include "lldb/Core/Scalar.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Utility/PseudoTerminal.h"
+
+
+#include "POSIXThread.h"
+#include "ProcessFreeBSD.h"
+#include "ProcessPOSIXLog.h"
+#include "ProcessMonitor.h"
+
+extern "C" {
+      extern char ** environ;
+ }
+
+using namespace lldb;
+using namespace lldb_private;
+
+// We disable the tracing of ptrace calls for integration builds to
+// avoid the additional indirection and checks.
+#ifndef LLDB_CONFIGURATION_BUILDANDINTEGRATION
+// Wrapper for ptrace to catch errors and log calls.
+
+const char *
+Get_PT_IO_OP(int op)
+{
+    switch (op) {
+        case PIOD_READ_D:  return "READ_D";
+        case PIOD_WRITE_D: return "WRITE_D";
+        case PIOD_READ_I:  return "READ_I";
+        case PIOD_WRITE_I: return "WRITE_I";
+        default:           return "Unknown op";
+    }
+}
+
+// Wrapper for ptrace to catch errors and log calls.
+// Note that ptrace sets errno on error because -1 is reserved as a valid result.
+extern long
+PtraceWrapper(int req, lldb::pid_t pid, void *addr, int data,
+              const char* reqName, const char* file, int line)
+{
+    long int result;
+
+    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PTRACE));
+
+    if (log) {
+        log->Printf("ptrace(%s, %lu, %p, %x) called from file %s line %d",
+                    reqName, pid, addr, data, file, line);
+        if (req == PT_IO) {
+            struct ptrace_io_desc *pi = (struct ptrace_io_desc *) addr;
+            
+            log->Printf("PT_IO: op=%s offs=%zx size=%ld",
+                     Get_PT_IO_OP(pi->piod_op), (size_t)pi->piod_offs, pi->piod_len);
+        }
+    }
+
+    //PtraceDisplayBytes(req, data);
+
+    errno = 0;
+    result = ptrace(req, pid, (caddr_t) addr, data);
+
+    //PtraceDisplayBytes(req, data);
+
+    if (log && errno != 0)
+    {
+        const char* str;
+        switch (errno)
+        {
+        case ESRCH:  str = "ESRCH"; break;
+        case EINVAL: str = "EINVAL"; break;
+        case EBUSY:  str = "EBUSY"; break;
+        case EPERM:  str = "EPERM"; break;
+        default:     str = "<unknown>";
+        }
+        log->Printf("ptrace() failed; errno=%d (%s)", errno, str);
+    }
+
+#ifdef __amd64__
+    if (log) {
+        if (req == PT_GETREGS) {
+            struct reg *r = (struct reg *) addr;
+
+            log->Printf("PT_GETREGS: ip=0x%lx", r->r_rip);
+            log->Printf("PT_GETREGS: sp=0x%lx", r->r_rsp);
+            log->Printf("PT_GETREGS: bp=0x%lx", r->r_rbp);
+            log->Printf("PT_GETREGS: ax=0x%lx", r->r_rax);
+        }
+    }
+#endif
+     
+    return result;
+}
+
+// Wrapper for ptrace when logging is not required.
+// Sets errno to 0 prior to calling ptrace.
+extern long
+PtraceWrapper(int req, lldb::pid_t pid, void *addr, int data)
+{
+    long result = 0;
+    errno = 0;
+    result = ptrace(req, pid, (caddr_t)addr, data);
+    return result;
+}
+
+#define PTRACE(req, pid, addr, data) \
+    PtraceWrapper((req), (pid), (addr), (data), #req, __FILE__, __LINE__)
+#else
+    PtraceWrapper((req), (pid), (addr), (data))
+#endif
+
+//------------------------------------------------------------------------------
+// Static implementations of ProcessMonitor::ReadMemory and
+// ProcessMonitor::WriteMemory.  This enables mutual recursion between these
+// functions without needed to go thru the thread funnel.
+
+static size_t
+DoReadMemory(lldb::pid_t pid, lldb::addr_t vm_addr, void *buf, size_t size, 
+             Error &error)
+{
+    struct ptrace_io_desc pi_desc;
+
+    pi_desc.piod_op = PIOD_READ_D;
+    pi_desc.piod_offs = (void *)vm_addr;
+    pi_desc.piod_addr = buf;
+    pi_desc.piod_len = size;
+
+    if (PTRACE(PT_IO, pid, (caddr_t)&pi_desc, 0) < 0)
+        error.SetErrorToErrno();
+    return pi_desc.piod_len;
+}
+
+static size_t
+DoWriteMemory(lldb::pid_t pid, lldb::addr_t vm_addr, const void *buf, 
+              size_t size, Error &error)
+{
+    struct ptrace_io_desc pi_desc;
+
+    pi_desc.piod_op = PIOD_WRITE_D;
+    pi_desc.piod_offs = (void *)vm_addr;
+    pi_desc.piod_addr = (void *)buf;
+    pi_desc.piod_len = size;
+
+    if (PTRACE(PT_IO, pid, (caddr_t)&pi_desc, 0) < 0)
+        error.SetErrorToErrno();
+    return pi_desc.piod_len;
+}
+
+// Simple helper function to ensure flags are enabled on the given file
+// descriptor.
+static bool
+EnsureFDFlags(int fd, int flags, Error &error)
+{
+    int status;
+
+    if ((status = fcntl(fd, F_GETFL)) == -1)
+    {
+        error.SetErrorToErrno();
+        return false;
+    }
+
+    if (fcntl(fd, F_SETFL, status | flags) == -1)
+    {
+        error.SetErrorToErrno();
+        return false;
+    }
+
+    return true;
+}
+
+//------------------------------------------------------------------------------
+/// @class Operation
+/// @brief Represents a ProcessMonitor operation.
+///
+/// Under FreeBSD, it is not possible to ptrace() from any other thread but the
+/// one that spawned or attached to the process from the start.  Therefore, when
+/// a ProcessMonitor is asked to deliver or change the state of an inferior
+/// process the operation must be "funneled" to a specific thread to perform the
+/// task.  The Operation class provides an abstract base for all services the
+/// ProcessMonitor must perform via the single virtual function Execute, thus
+/// encapsulating the code that needs to run in the privileged context.
+class Operation
+{
+public:
+    virtual ~Operation() {}
+    virtual void Execute(ProcessMonitor *monitor) = 0;
+};
+
+//------------------------------------------------------------------------------
+/// @class ReadOperation
+/// @brief Implements ProcessMonitor::ReadMemory.
+class ReadOperation : public Operation
+{
+public:
+    ReadOperation(lldb::addr_t addr, void *buff, size_t size,
+                  Error &error, size_t &result)
+        : m_addr(addr), m_buff(buff), m_size(size),
+          m_error(error), m_result(result)
+        { }
+
+    void Execute(ProcessMonitor *monitor);
+
+private:
+    lldb::addr_t m_addr;
+    void *m_buff;
+    size_t m_size;
+    Error &m_error;
+    size_t &m_result;
+};
+
+void
+ReadOperation::Execute(ProcessMonitor *monitor)
+{
+    lldb::pid_t pid = monitor->GetPID();
+
+    m_result = DoReadMemory(pid, m_addr, m_buff, m_size, m_error);
+}
+
+//------------------------------------------------------------------------------
+/// @class WriteOperation
+/// @brief Implements ProcessMonitor::WriteMemory.
+class WriteOperation : public Operation
+{
+public:
+    WriteOperation(lldb::addr_t addr, const void *buff, size_t size,
+                   Error &error, size_t &result)
+        : m_addr(addr), m_buff(buff), m_size(size),
+          m_error(error), m_result(result)
+        { }
+
+    void Execute(ProcessMonitor *monitor);
+
+private:
+    lldb::addr_t m_addr;
+    const void *m_buff;
+    size_t m_size;
+    Error &m_error;
+    size_t &m_result;
+};
+
+void
+WriteOperation::Execute(ProcessMonitor *monitor)
+{
+    lldb::pid_t pid = monitor->GetPID();
+
+    m_result = DoWriteMemory(pid, m_addr, m_buff, m_size, m_error);
+}
+
+//------------------------------------------------------------------------------
+/// @class ReadRegOperation
+/// @brief Implements ProcessMonitor::ReadRegisterValue.
+class ReadRegOperation : public Operation
+{
+public:
+    ReadRegOperation(lldb::tid_t tid, unsigned offset, unsigned size,
+                     RegisterValue &value, bool &result)
+        : m_tid(tid), m_offset(offset), m_size(size),
+          m_value(value), m_result(result)
+        { }
+
+    void Execute(ProcessMonitor *monitor);
+
+private:
+    lldb::tid_t m_tid;
+    unsigned m_offset;
+    unsigned m_size;
+    RegisterValue &m_value;
+    bool &m_result;
+};
+
+void
+ReadRegOperation::Execute(ProcessMonitor *monitor)
+{
+    struct reg regs;
+    int rc;
+
+    if ((rc = PTRACE(PT_GETREGS, m_tid, (caddr_t)&regs, 0)) < 0) {
+        m_result = false;
+    } else {
+        if (m_size == sizeof(uintptr_t))
+            m_value = *(uintptr_t *)(((caddr_t)&regs) + m_offset);
+        else 
+            memcpy(&m_value, (((caddr_t)&regs) + m_offset), m_size);
+        m_result = true;
+    }
+}
+
+//------------------------------------------------------------------------------
+/// @class WriteRegOperation
+/// @brief Implements ProcessMonitor::WriteRegisterValue.
+class WriteRegOperation : public Operation
+{
+public:
+    WriteRegOperation(lldb::tid_t tid, unsigned offset,
+                      const RegisterValue &value, bool &result)
+        : m_tid(tid), m_offset(offset),
+          m_value(value), m_result(result)
+        { }
+
+    void Execute(ProcessMonitor *monitor);
+
+private:
+    lldb::tid_t m_tid;
+    unsigned m_offset;
+    const RegisterValue &m_value;
+    bool &m_result;
+};
+
+void
+WriteRegOperation::Execute(ProcessMonitor *monitor)
+{
+    struct reg regs;
+
+    if (PTRACE(PT_GETREGS, m_tid, (caddr_t)&regs, 0) < 0) {
+        m_result = false;
+        return;
+    }
+    *(uintptr_t *)(((caddr_t)&regs) + m_offset) = (uintptr_t)m_value.GetAsUInt64();
+    if (PTRACE(PT_SETREGS, m_tid, (caddr_t)&regs, 0) < 0)
+        m_result = false;
+    else
+        m_result = true;
+}
+
+//------------------------------------------------------------------------------
+/// @class ReadGPROperation
+/// @brief Implements ProcessMonitor::ReadGPR.
+class ReadGPROperation : public Operation
+{
+public:
+    ReadGPROperation(lldb::tid_t tid, void *buf, bool &result)
+        : m_tid(tid), m_buf(buf), m_result(result)
+        { }
+
+    void Execute(ProcessMonitor *monitor);
+
+private:
+    lldb::tid_t m_tid;
+    void *m_buf;
+    bool &m_result;
+};
+
+void
+ReadGPROperation::Execute(ProcessMonitor *monitor)
+{
+    int rc;
+
+    errno = 0;
+    rc = PTRACE(PT_GETREGS, m_tid, (caddr_t)m_buf, 0);
+    if (errno != 0)
+        m_result = false;
+    else
+        m_result = true;
+}
+
+//------------------------------------------------------------------------------
+/// @class ReadFPROperation
+/// @brief Implements ProcessMonitor::ReadFPR.
+class ReadFPROperation : public Operation
+{
+public:
+    ReadFPROperation(lldb::tid_t tid, void *buf, bool &result)
+        : m_tid(tid), m_buf(buf), m_result(result)
+        { }
+
+    void Execute(ProcessMonitor *monitor);
+
+private:
+    lldb::tid_t m_tid;
+    void *m_buf;
+    bool &m_result;
+};
+
+void
+ReadFPROperation::Execute(ProcessMonitor *monitor)
+{
+    if (PTRACE(PT_GETFPREGS, m_tid, (caddr_t)m_buf, 0) < 0)
+        m_result = false;
+    else
+        m_result = true;
+}
+
+//------------------------------------------------------------------------------
+/// @class WriteGPROperation
+/// @brief Implements ProcessMonitor::WriteGPR.
+class WriteGPROperation : public Operation
+{
+public:
+    WriteGPROperation(lldb::tid_t tid, void *buf, bool &result)
+        : m_tid(tid), m_buf(buf), m_result(result)
+        { }
+
+    void Execute(ProcessMonitor *monitor);
+
+private:
+    lldb::tid_t m_tid;
+    void *m_buf;
+    bool &m_result;
+};
+
+void
+WriteGPROperation::Execute(ProcessMonitor *monitor)
+{
+    if (PTRACE(PT_SETREGS, m_tid, (caddr_t)m_buf, 0) < 0)
+        m_result = false;
+    else
+        m_result = true;
+}
+
+//------------------------------------------------------------------------------
+/// @class WriteFPROperation
+/// @brief Implements ProcessMonitor::WriteFPR.
+class WriteFPROperation : public Operation
+{
+public:
+    WriteFPROperation(lldb::tid_t tid, void *buf, bool &result)
+        : m_tid(tid), m_buf(buf), m_result(result)
+        { }
+
+    void Execute(ProcessMonitor *monitor);
+
+private:
+    lldb::tid_t m_tid;
+    void *m_buf;
+    bool &m_result;
+};
+
+void
+WriteFPROperation::Execute(ProcessMonitor *monitor)
+{
+    if (PTRACE(PT_SETFPREGS, m_tid, (caddr_t)m_buf, 0) < 0)
+        m_result = false;
+    else
+        m_result = true;
+}
+
+//------------------------------------------------------------------------------
+/// @class ResumeOperation
+/// @brief Implements ProcessMonitor::Resume.
+class ResumeOperation : public Operation
+{
+public:
+    ResumeOperation(lldb::tid_t tid, uint32_t signo, bool &result) :
+        m_tid(tid), m_signo(signo), m_result(result) { }
+
+    void Execute(ProcessMonitor *monitor);
+
+private:
+    lldb::tid_t m_tid;
+    uint32_t m_signo;
+    bool &m_result;
+};
+
+void
+ResumeOperation::Execute(ProcessMonitor *monitor)
+{
+    int data = 0;
+
+    if (m_signo != LLDB_INVALID_SIGNAL_NUMBER)
+        data = m_signo;
+
+    if (PTRACE(PT_CONTINUE, m_tid, (caddr_t)1, data))
+    {
+        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;
+}
+
+//------------------------------------------------------------------------------
+/// @class SingleStepOperation
+/// @brief Implements ProcessMonitor::SingleStep.
+class SingleStepOperation : public Operation
+{
+public:
+    SingleStepOperation(lldb::tid_t tid, uint32_t signo, bool &result)
+        : m_tid(tid), m_signo(signo), m_result(result) { }
+
+    void Execute(ProcessMonitor *monitor);
+
+private:
+    lldb::tid_t m_tid;
+    uint32_t m_signo;
+    bool &m_result;
+};
+
+void
+SingleStepOperation::Execute(ProcessMonitor *monitor)
+{
+    int data = 0;
+
+    if (m_signo != LLDB_INVALID_SIGNAL_NUMBER)
+        data = m_signo;
+
+    if (PTRACE(PT_STEP, m_tid, NULL, data))
+        m_result = false;
+    else
+        m_result = true;
+}
+
+//------------------------------------------------------------------------------
+/// @class LwpInfoOperation
+/// @brief Implements ProcessMonitor::GetLwpInfo.
+class LwpInfoOperation : public Operation
+{
+public:
+    LwpInfoOperation(lldb::tid_t tid, void *info, bool &result, int &ptrace_err)
+        : m_tid(tid), m_info(info), m_result(result), m_err(ptrace_err) { }
+
+    void Execute(ProcessMonitor *monitor);
+
+private:
+    lldb::tid_t m_tid;
+    void *m_info;
+    bool &m_result;
+    int &m_err;
+};
+
+void
+LwpInfoOperation::Execute(ProcessMonitor *monitor)
+{
+    struct ptrace_lwpinfo plwp;
+
+    if (PTRACE(PT_LWPINFO, m_tid, (caddr_t)&plwp, sizeof(plwp))) {
+        m_result = false;
+        m_err = errno;
+    } else {
+        memcpy(m_info, &plwp, sizeof(plwp));
+        m_result = true;
+    }
+}
+
+//------------------------------------------------------------------------------
+/// @class EventMessageOperation
+/// @brief Implements ProcessMonitor::GetEventMessage.
+class EventMessageOperation : public Operation
+{
+public:
+    EventMessageOperation(lldb::tid_t tid, unsigned long *message, bool &result)
+        : m_tid(tid), m_message(message), m_result(result) { }
+
+    void Execute(ProcessMonitor *monitor);
+
+private:
+    lldb::tid_t m_tid;
+    unsigned long *m_message;
+    bool &m_result;
+};
+
+void
+EventMessageOperation::Execute(ProcessMonitor *monitor)
+{
+    struct ptrace_lwpinfo plwp;
+
+    if (PTRACE(PT_LWPINFO, m_tid, (caddr_t)&plwp, sizeof(plwp)))
+        m_result = false;
+    else {
+        if (plwp.pl_flags & PL_FLAG_FORKED) {
+            m_message = (unsigned long *)plwp.pl_child_pid;
+            m_result = true;
+        } else
+            m_result = false;
+    }
+}
+
+//------------------------------------------------------------------------------
+/// @class KillOperation
+/// @brief Implements ProcessMonitor::BringProcessIntoLimbo.
+class KillOperation : public Operation
+{
+public:
+    KillOperation(bool &result) : m_result(result) { }
+
+    void Execute(ProcessMonitor *monitor);
+
+private:
+    bool &m_result;
+};
+
+void
+KillOperation::Execute(ProcessMonitor *monitor)
+{
+    lldb::pid_t pid = monitor->GetPID();
+
+    if (PTRACE(PT_KILL, pid, NULL, 0))
+        m_result = false;
+    else
+        m_result = true;
+}
+
+//------------------------------------------------------------------------------
+/// @class DetachOperation
+/// @brief Implements ProcessMonitor::BringProcessIntoLimbo.
+class DetachOperation : public Operation
+{
+public:
+    DetachOperation(Error &result) : m_error(result) { }
+
+    void Execute(ProcessMonitor *monitor);
+
+private:
+    Error &m_error;
+};
+
+void
+DetachOperation::Execute(ProcessMonitor *monitor)
+{
+    lldb::pid_t pid = monitor->GetPID();
+
+    if (PTRACE(PT_DETACH, pid, NULL, 0) < 0)
+        m_error.SetErrorToErrno();
+  
+}
+
+ProcessMonitor::OperationArgs::OperationArgs(ProcessMonitor *monitor)
+    : m_monitor(monitor)
+{
+    sem_init(&m_semaphore, 0, 0);
+}
+
+ProcessMonitor::OperationArgs::~OperationArgs()
+{
+    sem_destroy(&m_semaphore);
+}
+
+ProcessMonitor::LaunchArgs::LaunchArgs(ProcessMonitor *monitor,
+                                       lldb_private::Module *module,
+                                       char const **argv,
+                                       char const **envp,
+                                       const char *stdin_path,
+                                       const char *stdout_path,
+                                       const char *stderr_path,
+                                       const char *working_dir)
+    : OperationArgs(monitor),
+      m_module(module),
+      m_argv(argv),
+      m_envp(envp),
+      m_stdin_path(stdin_path),
+      m_stdout_path(stdout_path),
+      m_stderr_path(stderr_path),
+      m_working_dir(working_dir) { }
+
+ProcessMonitor::LaunchArgs::~LaunchArgs()
+{ }
+
+ProcessMonitor::AttachArgs::AttachArgs(ProcessMonitor *monitor,
+                                       lldb::pid_t pid)
+    : OperationArgs(monitor), m_pid(pid) { }
+
+ProcessMonitor::AttachArgs::~AttachArgs()
+{ }
+
+//------------------------------------------------------------------------------
+/// The basic design of the ProcessMonitor is built around two threads.
+///
+/// One thread (@see SignalThread) simply blocks on a call to waitpid() looking
+/// for changes in the debugee state.  When a change is detected a
+/// ProcessMessage is sent to the associated ProcessFreeBSD instance.  This thread
+/// "drives" state changes in the debugger.
+///
+/// The second thread (@see OperationThread) is responsible for two things 1)
+/// launching or attaching to the inferior process, and then 2) servicing
+/// operations such as register reads/writes, stepping, etc.  See the comments
+/// on the Operation class for more info as to why this is needed.
+ProcessMonitor::ProcessMonitor(ProcessPOSIX *process,
+                               Module *module,
+                               const char *argv[],
+                               const char *envp[],
+                               const char *stdin_path,
+                               const char *stdout_path,
+                               const char *stderr_path,
+                               const char *working_dir,
+                               lldb_private::Error &error)
+    : m_process(static_cast<ProcessFreeBSD *>(process)),
+      m_operation_thread(LLDB_INVALID_HOST_THREAD),
+      m_monitor_thread(LLDB_INVALID_HOST_THREAD),
+      m_pid(LLDB_INVALID_PROCESS_ID),
+      m_server_mutex(Mutex::eMutexTypeRecursive),
+      m_terminal_fd(-1),
+      m_client_fd(-1),
+      m_server_fd(-1)
+{
+    std::unique_ptr<LaunchArgs> args;
+
+    args.reset(new LaunchArgs(this, module, argv, envp,
+                              stdin_path, stdout_path, stderr_path, working_dir));
+    
+
+    // Server/client descriptors.
+    if (!EnableIPC())
+    {
+        error.SetErrorToGenericError();
+        error.SetErrorString("Monitor failed to initialize.");
+    }
+
+    StartLaunchOpThread(args.get(), error);
+    if (!error.Success())
+        return;
+
+WAIT_AGAIN:
+    // Wait for the operation thread to initialize.
+    if (sem_wait(&args->m_semaphore))
+    {
+        if (errno == EINTR)
+            goto WAIT_AGAIN;
+        else
+        {
+            error.SetErrorToErrno();
+            return;
+        }
+    }
+
+    // Check that the launch was a success.
+    if (!args->m_error.Success())
+    {
+        StopOpThread();
+        error = args->m_error;
+        return;
+    }
+
+    // Finally, start monitoring the child process for change in state.
+    m_monitor_thread = Host::StartMonitoringChildProcess(
+        ProcessMonitor::MonitorCallback, this, GetPID(), true);
+    if (!IS_VALID_LLDB_HOST_THREAD(m_monitor_thread))
+    {
+        error.SetErrorToGenericError();
+        error.SetErrorString("Process launch failed.");
+        return;
+    }
+}
+
+ProcessMonitor::ProcessMonitor(ProcessPOSIX *process,
+                               lldb::pid_t pid,
+                               lldb_private::Error &error)
+    : m_process(static_cast<ProcessFreeBSD *>(process)),
+      m_operation_thread(LLDB_INVALID_HOST_THREAD),
+      m_monitor_thread(LLDB_INVALID_HOST_THREAD),
+      m_pid(pid),
+      m_server_mutex(Mutex::eMutexTypeRecursive),
+      m_terminal_fd(-1),
+      m_client_fd(-1),
+      m_server_fd(-1)
+{
+    std::unique_ptr<AttachArgs> args;
+
+    args.reset(new AttachArgs(this, pid));
+
+    // Server/client descriptors.
+    if (!EnableIPC())
+    {
+        error.SetErrorToGenericError();
+        error.SetErrorString("Monitor failed to initialize.");
+    }
+
+    StartAttachOpThread(args.get(), error);
+    if (!error.Success())
+        return;
+
+WAIT_AGAIN:
+    // Wait for the operation thread to initialize.
+    if (sem_wait(&args->m_semaphore))
+    {
+        if (errno == EINTR)
+            goto WAIT_AGAIN;
+        else
+        {
+            error.SetErrorToErrno();
+            return;
+        }
+    }
+
+    // Check that the attach was a success.
+    if (!args->m_error.Success())
+    {
+        StopOpThread();
+        error = args->m_error;
+        return;
+    }
+
+    // Finally, start monitoring the child process for change in state.
+    m_monitor_thread = Host::StartMonitoringChildProcess(
+        ProcessMonitor::MonitorCallback, this, GetPID(), true);
+    if (!IS_VALID_LLDB_HOST_THREAD(m_monitor_thread))
+    {
+        error.SetErrorToGenericError();
+        error.SetErrorString("Process attach failed.");
+        return;
+    }
+}
+
+ProcessMonitor::~ProcessMonitor()
+{
+    StopMonitor();
+}
+
+//------------------------------------------------------------------------------
+// Thread setup and tear down.
+void
+ProcessMonitor::StartLaunchOpThread(LaunchArgs *args, Error &error)
+{
+    static const char *g_thread_name = "lldb.process.freebsd.operation";
+
+    if (IS_VALID_LLDB_HOST_THREAD(m_operation_thread))
+        return;
+
+    m_operation_thread =
+        Host::ThreadCreate(g_thread_name, LaunchOpThread, args, &error);
+}
+
+void *
+ProcessMonitor::LaunchOpThread(void *arg)
+{
+    LaunchArgs *args = static_cast<LaunchArgs*>(arg);
+
+    if (!Launch(args)) {
+        sem_post(&args->m_semaphore);
+        return NULL;
+    }
+
+    ServeOperation(args);
+    return NULL;
+}
+
+bool
+ProcessMonitor::Launch(LaunchArgs *args)
+{
+    ProcessMonitor *monitor = args->m_monitor;
+    ProcessFreeBSD &process = monitor->GetProcess();
+    lldb::ProcessSP processSP = process.shared_from_this();
+    const char **argv = args->m_argv;
+    const char **envp = args->m_envp;
+    const char *stdin_path = args->m_stdin_path;
+    const char *stdout_path = args->m_stdout_path;
+    const char *stderr_path = args->m_stderr_path;
+    const char *working_dir = args->m_working_dir;
+
+    lldb_utility::PseudoTerminal terminal;
+    const size_t err_len = 1024;
+    char err_str[err_len];
+    lldb::pid_t pid;
+
+    lldb::ThreadSP inferior;
+    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
+
+    // Propagate the environment if one is not supplied.
+    if (envp == NULL || envp[0] == NULL)
+        envp = const_cast<const char **>(environ);
+
+    // Pseudo terminal setup.
+    if (!terminal.OpenFirstAvailableMaster(O_RDWR | O_NOCTTY, err_str, err_len))
+    {
+        args->m_error.SetErrorToGenericError();
+        args->m_error.SetErrorString("Could not open controlling TTY.");
+        goto FINISH;
+    }
+
+    if ((pid = terminal.Fork(err_str, err_len)) == -1)
+    {
+        args->m_error.SetErrorToGenericError();
+        args->m_error.SetErrorString("Process fork failed.");
+        goto FINISH;
+    }
+
+    // Recognized child exit status codes.
+    enum {
+        ePtraceFailed = 1,
+        eDupStdinFailed,
+        eDupStdoutFailed,
+        eDupStderrFailed,
+        eChdirFailed,
+        eExecFailed
+    };
+
+    // Child process.
+    if (pid == 0)
+    {
+        // Trace this process.
+        if (PTRACE(PT_TRACE_ME, 0, NULL, 0) < 0)
+            exit(ePtraceFailed);
+
+        // Do not inherit setgid powers.
+        setgid(getgid());
+
+        // Let us have our own process group.
+        setpgid(0, 0);
+
+        // Dup file descriptors if needed.
+        //
+        // FIXME: If two or more of the paths are the same we needlessly open
+        // the same file multiple times.
+        if (stdin_path != NULL && stdin_path[0])
+            if (!DupDescriptor(stdin_path, STDIN_FILENO, O_RDONLY))
+                exit(eDupStdinFailed);
+
+        if (stdout_path != NULL && stdout_path[0])
+            if (!DupDescriptor(stdout_path, STDOUT_FILENO, O_WRONLY | O_CREAT))
+                exit(eDupStdoutFailed);
+
+        if (stderr_path != NULL && stderr_path[0])
+            if (!DupDescriptor(stderr_path, STDERR_FILENO, O_WRONLY | O_CREAT))
+                exit(eDupStderrFailed);
+
+        // Change working directory
+        if (working_dir != NULL && working_dir[0])
+          if (0 != ::chdir(working_dir))
+              exit(eChdirFailed);
+
+        // Execute.  We should never return.
+        execve(argv[0],
+               const_cast<char *const *>(argv),
+               const_cast<char *const *>(envp));
+        exit(eExecFailed);
+    }
+
+    // Wait for the child process to to trap on its call to execve.
+    ::pid_t wpid;
+    int status;
+    if ((wpid = waitpid(pid, &status, 0)) < 0)
+    {
+        args->m_error.SetErrorToErrno();
+        goto FINISH;
+    }
+    else if (WIFEXITED(status))
+    {
+        // open, dup or execve likely failed for some reason.
+        args->m_error.SetErrorToGenericError();
+        switch (WEXITSTATUS(status))
+        {
+            case ePtraceFailed:
+                args->m_error.SetErrorString("Child ptrace failed.");
+                break;
+            case eDupStdinFailed:
+                args->m_error.SetErrorString("Child open stdin failed.");
+                break;
+            case eDupStdoutFailed:
+                args->m_error.SetErrorString("Child open stdout failed.");
+                break;
+            case eDupStderrFailed:
+                args->m_error.SetErrorString("Child open stderr failed.");
+                break;
+            case eChdirFailed:
+                args->m_error.SetErrorString("Child failed to set working directory.");
+                break;
+            case eExecFailed:
+                args->m_error.SetErrorString("Child exec failed.");
+                break;
+            default:
+                args->m_error.SetErrorString("Child returned unknown exit status.");
+                break;
+        }
+        goto FINISH;
+    }
+    assert(WIFSTOPPED(status) && wpid == pid &&
+           "Could not sync with inferior process.");
+
+#ifdef notyet
+    // Have the child raise an event on exit.  This is used to keep the child in
+    // limbo until it is destroyed.
+    if (PTRACE(PTRACE_SETOPTIONS, pid, NULL, PTRACE_O_TRACEEXIT) < 0)
+    {
+        args->m_error.SetErrorToErrno();
+        goto FINISH;
+    }
+#endif
+    // Release the master terminal descriptor and pass it off to the
+    // ProcessMonitor instance.  Similarly stash the inferior pid.
+    monitor->m_terminal_fd = terminal.ReleaseMasterFileDescriptor();
+    monitor->m_pid = pid;
+
+    // Set the terminal fd to be in non blocking mode (it simplifies the
+    // implementation of ProcessFreeBSD::GetSTDOUT to have a non-blocking
+    // descriptor to read from).
+    if (!EnsureFDFlags(monitor->m_terminal_fd, O_NONBLOCK, args->m_error))
+        goto FINISH;
+
+    // Update the process thread list with this new thread.
+    inferior.reset(process.CreateNewPOSIXThread(*processSP, pid));
+    if (log)
+        log->Printf ("ProcessMonitor::%s() adding pid = %" PRIu64, __FUNCTION__, pid);
+    process.GetThreadList().AddThread(inferior);
+
+    // Let our process instance know the thread has stopped.
+    process.SendMessage(ProcessMessage::Trace(pid));
+
+FINISH:
+    return args->m_error.Success();
+}
+
+bool
+ProcessMonitor::EnableIPC()
+{
+    int fd[2];
+
+    if (socketpair(AF_UNIX, SOCK_STREAM, 0, fd))
+        return false;
+
+    m_client_fd = fd[0];
+    m_server_fd = fd[1];
+    return true;
+}
+
+void
+ProcessMonitor::StartAttachOpThread(AttachArgs *args, lldb_private::Error &error)
+{
+    static const char *g_thread_name = "lldb.process.freebsd.operation";
+
+    if (IS_VALID_LLDB_HOST_THREAD(m_operation_thread))
+        return;
+
+    m_operation_thread =
+        Host::ThreadCreate(g_thread_name, AttachOpThread, args, &error);
+}
+
+void *
+ProcessMonitor::AttachOpThread(void *arg)
+{
+    AttachArgs *args = static_cast<AttachArgs*>(arg);
+
+    if (!Attach(args))
+        return NULL;
+
+    ServeOperation(args);
+    return NULL;
+}
+
+bool
+ProcessMonitor::Attach(AttachArgs *args)
+{
+    lldb::pid_t pid = args->m_pid;
+
+    ProcessMonitor *monitor = args->m_monitor;
+    ProcessFreeBSD &process = monitor->GetProcess();
+    lldb::ProcessSP processSP = process.shared_from_this();
+    ThreadList &tl = process.GetThreadList();
+    lldb::ThreadSP inferior;
+
+    if (pid <= 1)
+    {
+        args->m_error.SetErrorToGenericError();
+        args->m_error.SetErrorString("Attaching to process 1 is not allowed.");
+        goto FINISH;
+    }
+
+    // Attach to the requested process.
+    if (PTRACE(PT_ATTACH, pid, NULL, 0) < 0)
+    {
+        args->m_error.SetErrorToErrno();
+        goto FINISH;
+    }
+
+    int status;
+    if ((status = waitpid(pid, NULL, 0)) < 0)
+    {
+        args->m_error.SetErrorToErrno();
+        goto FINISH;
+    }
+
+    // Update the process thread list with the attached thread.
+    inferior.reset(process.CreateNewPOSIXThread(*processSP, pid));
+    tl.AddThread(inferior);
+
+    // Let our process instance know the thread has stopped.
+    process.SendMessage(ProcessMessage::Trace(pid));
+
+ FINISH:
+    return args->m_error.Success();
+}
+
+bool
+ProcessMonitor::MonitorCallback(void *callback_baton,
+                                lldb::pid_t pid,
+                                bool exited,
+                                int signal,
+                                int status)
+{
+    ProcessMessage message;
+    ProcessMonitor *monitor = static_cast<ProcessMonitor*>(callback_baton);
+    ProcessFreeBSD *process = monitor->m_process;
+    assert(process);
+    bool stop_monitoring;
+    struct ptrace_lwpinfo plwp;
+    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->GetLwpInfo(pid, &plwp, ptrace_err))
+        stop_monitoring = true; // pid is gone.  Bail.
+    else {
+        switch (plwp.pl_siginfo.si_signo)
+        {
+        case SIGTRAP:
+            message = MonitorSIGTRAP(monitor, &plwp.pl_siginfo, pid);
+            break;
+            
+        default:
+            message = MonitorSignal(monitor, &plwp.pl_siginfo, pid);
+            break;
+        }
+
+        process->SendMessage(message);
+        stop_monitoring = message.GetKind() == ProcessMessage::eExitMessage;
+    }
+
+    return stop_monitoring;
+}
+
+ProcessMessage
+ProcessMonitor::MonitorSIGTRAP(ProcessMonitor *monitor,
+                               const siginfo_t *info, lldb::pid_t pid)
+{
+    ProcessMessage message;
+
+    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
+
+    assert(monitor);
+    assert(info && info->si_signo == SIGTRAP && "Unexpected child signal!");
+
+    switch (info->si_code)
+    {
+    default:
+        assert(false && "Unexpected SIGTRAP code!");
+        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.
+        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;
+    }
+
+    return message;
+}
+
+ProcessMessage
+ProcessMonitor::MonitorSignal(ProcessMonitor *monitor,
+                              const siginfo_t *info, lldb::pid_t pid)
+{
+    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 FreeBSD.
+    //
+    // IOW, user generated signals never generate what we consider to be a
+    // "crash".
+    //
+    // Similarly, ACK signals generated by this monitor.
+    if (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),
+                            "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);
+        return ProcessMessage::Crash(pid, reason, signo, fault_addr);
+    }
+
+    if (signo == SIGILL) {
+        lldb::addr_t fault_addr = reinterpret_cast<lldb::addr_t>(info->si_addr);
+        ProcessMessage::CrashReason reason = GetCrashReasonForSIGILL(info);
+        return ProcessMessage::Crash(pid, reason, signo, fault_addr);
+    }
+
+    if (signo == SIGFPE) {
+        lldb::addr_t fault_addr = reinterpret_cast<lldb::addr_t>(info->si_addr);
+        ProcessMessage::CrashReason reason = GetCrashReasonForSIGFPE(info);
+        return ProcessMessage::Crash(pid, reason, signo, fault_addr);
+    }
+
+    if (signo == SIGBUS) {
+        lldb::addr_t fault_addr = reinterpret_cast<lldb::addr_t>(info->si_addr);
+        ProcessMessage::CrashReason reason = GetCrashReasonForSIGBUS(info);
+        return ProcessMessage::Crash(pid, reason, signo, fault_addr);
+    }
+
+    // Everything else is "normal" and does not require any special action on
+    // our part.
+    return ProcessMessage::Signal(pid, signo);
+}
+
+ProcessMessage::CrashReason
+ProcessMonitor::GetCrashReasonForSIGSEGV(const siginfo_t *info)
+{
+    ProcessMessage::CrashReason reason;
+    assert(info->si_signo == SIGSEGV);
+
+    reason = ProcessMessage::eInvalidCrashReason;
+
+    switch (info->si_code) 
+    {
+    default:
+        assert(false && "unexpected si_code for SIGSEGV");
+        break;
+    case SEGV_MAPERR:
+        reason = ProcessMessage::eInvalidAddress;
+        break;
+    case SEGV_ACCERR:
+        reason = ProcessMessage::ePrivilegedAddress;
+        break;
+    }
+        
+    return reason;
+}
+
+ProcessMessage::CrashReason
+ProcessMonitor::GetCrashReasonForSIGILL(const siginfo_t *info)
+{
+    ProcessMessage::CrashReason reason;
+    assert(info->si_signo == SIGILL);
+
+    reason = ProcessMessage::eInvalidCrashReason;
+
+    switch (info->si_code)
+    {
+    default:
+        assert(false && "unexpected si_code for SIGILL");
+        break;
+    case ILL_ILLOPC:
+        reason = ProcessMessage::eIllegalOpcode;
+        break;
+    case ILL_ILLOPN:
+        reason = ProcessMessage::eIllegalOperand;
+        break;
+    case ILL_ILLADR:
+        reason = ProcessMessage::eIllegalAddressingMode;
+        break;
+    case ILL_ILLTRP:
+        reason = ProcessMessage::eIllegalTrap;
+        break;
+    case ILL_PRVOPC:
+        reason = ProcessMessage::ePrivilegedOpcode;
+        break;
+    case ILL_PRVREG:
+        reason = ProcessMessage::ePrivilegedRegister;
+        break;
+    case ILL_COPROC:
+        reason = ProcessMessage::eCoprocessorError;
+        break;
+    case ILL_BADSTK:
+        reason = ProcessMessage::eInternalStackError;
+        break;
+    }
+
+    return reason;
+}
+
+ProcessMessage::CrashReason
+ProcessMonitor::GetCrashReasonForSIGFPE(const siginfo_t *info)
+{
+    ProcessMessage::CrashReason reason;
+    assert(info->si_signo == SIGFPE);
+
+    reason = ProcessMessage::eInvalidCrashReason;
+
+    switch (info->si_code)
+    {
+    default:
+        assert(false && "unexpected si_code for SIGFPE");
+        break;
+    case FPE_INTDIV:
+        reason = ProcessMessage::eIntegerDivideByZero;
+        break;
+    case FPE_INTOVF:
+        reason = ProcessMessage::eIntegerOverflow;
+        break;
+    case FPE_FLTDIV:
+        reason = ProcessMessage::eFloatDivideByZero;
+        break;
+    case FPE_FLTOVF:
+        reason = ProcessMessage::eFloatOverflow;
+        break;
+    case FPE_FLTUND:
+        reason = ProcessMessage::eFloatUnderflow;
+        break;
+    case FPE_FLTRES:
+        reason = ProcessMessage::eFloatInexactResult;
+        break;
+    case FPE_FLTINV:
+        reason = ProcessMessage::eFloatInvalidOperation;
+        break;
+    case FPE_FLTSUB:
+        reason = ProcessMessage::eFloatSubscriptRange;
+        break;
+    }
+
+    return reason;
+}
+
+ProcessMessage::CrashReason
+ProcessMonitor::GetCrashReasonForSIGBUS(const siginfo_t *info)
+{
+    ProcessMessage::CrashReason reason;
+    assert(info->si_signo == SIGBUS);
+
+    reason = ProcessMessage::eInvalidCrashReason;
+
+    switch (info->si_code)
+    {
+    default:
+        assert(false && "unexpected si_code for SIGBUS");
+        break;
+    case BUS_ADRALN:
+        reason = ProcessMessage::eIllegalAlignment;
+        break;
+    case BUS_ADRERR:
+        reason = ProcessMessage::eIllegalAddress;
+        break;
+    case BUS_OBJERR:
+        reason = ProcessMessage::eHardwareError;
+        break;
+    }
+
+    return reason;
+}
+
+void
+ProcessMonitor::ServeOperation(OperationArgs *args)
+{
+    int status;
+    pollfd fdset;
+
+    ProcessMonitor *monitor = args->m_monitor;
+
+    fdset.fd = monitor->m_server_fd;
+    fdset.events = POLLIN | POLLPRI;
+    fdset.revents = 0;
+
+    // We are finised with the arguments and are ready to go.  Sync with the
+    // parent thread and start serving operations on the inferior.
+    sem_post(&args->m_semaphore);
+
+    for (;;)
+    {
+        if ((status = poll(&fdset, 1, -1)) < 0)
+        {
+            switch (errno)
+            {
+            default:
+                assert(false && "Unexpected poll() failure!");
+                continue;
+
+            case EINTR: continue; // Just poll again.
+            case EBADF: return;   // Connection terminated.
+            }
+        }
+
+        assert(status == 1 && "Too many descriptors!");
+
+        if (fdset.revents & POLLIN)
+        {
+            Operation *op = NULL;
+
+        READ_AGAIN:
+            if ((status = read(fdset.fd, &op, sizeof(op))) < 0)
+            {
+                // There is only one acceptable failure.
+                assert(errno == EINTR);
+                goto READ_AGAIN;
+            }
+            if (status == 0)
+                continue; // Poll again. The connection probably terminated.
+            assert(status == sizeof(op));
+            op->Execute(monitor);
+            write(fdset.fd, &op, sizeof(op));
+        }
+    }
+}
+
+void
+ProcessMonitor::DoOperation(Operation *op)
+{
+    int status;
+    Operation *ack = NULL;
+    Mutex::Locker lock(m_server_mutex);
+
+    // FIXME: Do proper error checking here.
+    write(m_client_fd, &op, sizeof(op));
+
+READ_AGAIN:
+    if ((status = read(m_client_fd, &ack, sizeof(ack))) < 0)
+    {
+        // If interrupted by a signal handler try again.  Otherwise the monitor
+        // thread probably died and we have a stale file descriptor -- abort the
+        // operation.
+        if (errno == EINTR)
+            goto READ_AGAIN;
+        return;
+    }
+
+    assert(status == sizeof(ack));
+    assert(ack == op && "Invalid monitor thread response!");
+}
+
+size_t
+ProcessMonitor::ReadMemory(lldb::addr_t vm_addr, void *buf, size_t size,
+                           Error &error)
+{
+    size_t result;
+    ReadOperation op(vm_addr, buf, size, error, result);
+    DoOperation(&op);
+    return result;
+}
+
+size_t
+ProcessMonitor::WriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size,
+                            lldb_private::Error &error)
+{
+    size_t result;
+    WriteOperation op(vm_addr, buf, size, error, result);
+    DoOperation(&op);
+    return result;
+}
+
+bool
+ProcessMonitor::ReadRegisterValue(lldb::tid_t tid, unsigned offset, const char* reg_name,
+                                  unsigned size, RegisterValue &value)
+{
+    bool result;
+    ReadRegOperation op(tid, offset, size, value, result);
+    DoOperation(&op);
+    return result;
+}
+
+bool
+ProcessMonitor::WriteRegisterValue(lldb::tid_t tid, unsigned offset,
+                                   const char* reg_name, const RegisterValue &value)
+{
+    bool result;
+    WriteRegOperation op(tid, offset, value, result);
+    DoOperation(&op);
+    return result;
+}
+
+bool
+ProcessMonitor::ReadGPR(lldb::tid_t tid, void *buf, size_t buf_size)
+{
+    bool result;
+    ReadGPROperation op(tid, buf, result);
+    DoOperation(&op);
+    return result;
+}
+
+bool
+ProcessMonitor::ReadFPR(lldb::tid_t tid, void *buf, size_t buf_size)
+{
+    bool result;
+    ReadFPROperation op(tid, buf, result);
+    DoOperation(&op);
+    return result;
+}
+
+bool
+ProcessMonitor::ReadRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset)
+{
+    return false;
+}
+
+bool
+ProcessMonitor::WriteGPR(lldb::tid_t tid, void *buf, size_t buf_size)
+{
+    bool result;
+    WriteGPROperation op(tid, buf, result);
+    DoOperation(&op);
+    return result;
+}
+
+bool
+ProcessMonitor::WriteFPR(lldb::tid_t tid, void *buf, size_t buf_size)
+{
+    bool result;
+    WriteFPROperation op(tid, buf, result);
+    DoOperation(&op);
+    return result;
+}
+
+bool
+ProcessMonitor::WriteRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset)
+{
+    return false;
+}
+
+bool
+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;
+}
+
+bool
+ProcessMonitor::SingleStep(lldb::tid_t tid, uint32_t signo)
+{
+    bool result;
+    SingleStepOperation op(tid, signo, result);
+    DoOperation(&op);
+    return result;
+}
+
+bool
+ProcessMonitor::BringProcessIntoLimbo()
+{
+    bool result;
+    KillOperation op(result);
+    DoOperation(&op);
+    return result;
+}
+
+bool
+ProcessMonitor::GetLwpInfo(lldb::tid_t tid, void *lwpinfo, int &ptrace_err)
+{
+    bool result;
+    LwpInfoOperation op(tid, lwpinfo, result, ptrace_err);
+    DoOperation(&op);
+    return result;
+}
+
+bool
+ProcessMonitor::GetEventMessage(lldb::tid_t tid, unsigned long *message)
+{
+    bool result;
+    EventMessageOperation op(tid, message, result);
+    DoOperation(&op);
+    return result;
+}
+
+lldb_private::Error
+ProcessMonitor::Detach(lldb::tid_t tid)
+{
+    lldb_private::Error error;
+    if (tid != LLDB_INVALID_THREAD_ID)
+    {
+        DetachOperation op(error);
+        DoOperation(&op);
+    }
+    return error;
+}    
+
+bool
+ProcessMonitor::DupDescriptor(const char *path, int fd, int flags)
+{
+    int target_fd = open(path, flags, 0666);
+
+    if (target_fd == -1)
+        return false;
+
+    return (dup2(target_fd, fd) == -1) ? false : true;
+}
+
+void
+ProcessMonitor::StopMonitoringChildProcess()
+{
+    lldb::thread_result_t thread_result;
+
+    if (IS_VALID_LLDB_HOST_THREAD(m_monitor_thread))
+    {
+        Host::ThreadCancel(m_monitor_thread, NULL);
+        Host::ThreadJoin(m_monitor_thread, &thread_result, NULL);
+        m_monitor_thread = LLDB_INVALID_HOST_THREAD;
+    }
+}
+
+void
+ProcessMonitor::StopMonitor()
+{
+    StopMonitoringChildProcess();
+    StopOpThread();
+    CloseFD(m_terminal_fd);
+    CloseFD(m_client_fd);
+    CloseFD(m_server_fd);
+}
+
+void
+ProcessMonitor::StopOpThread()
+{
+    lldb::thread_result_t result;
+
+    if (!IS_VALID_LLDB_HOST_THREAD(m_operation_thread))
+        return;
+
+    Host::ThreadCancel(m_operation_thread, NULL);
+    Host::ThreadJoin(m_operation_thread, &result, NULL);
+    m_operation_thread = LLDB_INVALID_HOST_THREAD;
+}
+
+void
+ProcessMonitor::CloseFD(int &fd)
+{
+    if (fd != -1)
+    {
+        close(fd);
+        fd = -1;
+    }
+}
diff --git a/source/Plugins/Process/FreeBSD/ProcessMonitor.h b/source/Plugins/Process/FreeBSD/ProcessMonitor.h
new file mode 100644
index 000000000000..ce66c03f2f8c
--- /dev/null
+++ b/source/Plugins/Process/FreeBSD/ProcessMonitor.h
@@ -0,0 +1,322 @@
+//===-- ProcessMonitor.h -------------------------------------- -*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ProcessMonitor_H_
+#define liblldb_ProcessMonitor_H_
+
+// C Includes
+#include <semaphore.h>
+#include <signal.h>
+
+// C++ Includes
+// Other libraries and framework includes
+#include "lldb/lldb-types.h"
+#include "lldb/Host/Mutex.h"
+
+namespace lldb_private
+{
+class Error;
+class Module;
+class Scalar;
+} // End lldb_private namespace.
+
+class ProcessFreeBSD;
+class Operation;
+
+/// @class ProcessMonitor
+/// @brief Manages communication with the inferior (debugee) process.
+///
+/// Upon construction, this class prepares and launches an inferior process for
+/// debugging.
+///
+/// Changes in the inferior process state are propagated to the associated
+/// ProcessFreeBSD instance by calling ProcessFreeBSD::SendMessage with the
+/// appropriate ProcessMessage events.
+///
+/// A purposely minimal set of operations are provided to interrogate and change
+/// the inferior process state.
+class ProcessMonitor
+{
+public:
+
+    /// Launches an inferior process ready for debugging.  Forms the
+    /// implementation of Process::DoLaunch.
+    ProcessMonitor(ProcessPOSIX *process,
+                   lldb_private::Module *module,
+                   char const *argv[],
+                   char const *envp[],
+                   const char *stdin_path,
+                   const char *stdout_path,
+                   const char *stderr_path,
+                   const char *working_dir,
+                   lldb_private::Error &error);
+
+    ProcessMonitor(ProcessPOSIX *process,
+                   lldb::pid_t pid,
+                   lldb_private::Error &error);
+
+    ~ProcessMonitor();
+
+    /// Provides the process number of debugee.
+    lldb::pid_t
+    GetPID() const { return m_pid; }
+
+    /// Returns the process associated with this ProcessMonitor.
+    ProcessFreeBSD &
+    GetProcess() { return *m_process; }
+
+    /// Returns a file descriptor to the controlling terminal of the inferior
+    /// process.
+    ///
+    /// Reads from this file descriptor yield both the standard output and
+    /// standard error of this debugee.  Even if stderr and stdout were
+    /// redirected on launch it may still happen that data is available on this
+    /// descriptor (if the inferior process opens /dev/tty, for example).
+    ///
+    /// If this monitor was attached to an existing process this method returns
+    /// -1.
+    int
+    GetTerminalFD() const { return m_terminal_fd; }
+
+    /// Reads @p size bytes from address @vm_adder in the inferior process
+    /// address space.
+    ///
+    /// This method is provided to implement Process::DoReadMemory.
+    size_t
+    ReadMemory(lldb::addr_t vm_addr, void *buf, size_t size,
+               lldb_private::Error &error);
+
+    /// Writes @p size bytes from address @p vm_adder in the inferior process
+    /// address space.
+    ///
+    /// This method is provided to implement Process::DoWriteMemory.
+    size_t
+    WriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size,
+                lldb_private::Error &error);
+
+    /// Reads the contents from the register identified by the given (architecture
+    /// dependent) offset.
+    ///
+    /// This method is provided for use by RegisterContextFreeBSD derivatives.
+    /// FIXME: The FreeBSD implementation of this function should use tid in order
+    ///        to enable support for debugging threaded programs.
+    bool
+    ReadRegisterValue(lldb::tid_t tid, unsigned offset, const char *reg_name,
+                      unsigned size, lldb_private::RegisterValue &value);
+
+    /// Writes the given value to the register identified by the given
+    /// (architecture dependent) offset.
+    ///
+    /// This method is provided for use by RegisterContextFreeBSD derivatives.
+    /// FIXME: The FreeBSD implementation of this function should use tid in order
+    ///        to enable support for debugging threaded programs.
+    bool
+    WriteRegisterValue(lldb::tid_t tid, unsigned offset, const char *reg_name,
+                       const lldb_private::RegisterValue &value);
+
+    /// Reads all general purpose registers into the specified buffer.
+    /// FIXME: The FreeBSD implementation of this function should use tid in order
+    ///        to enable support for debugging threaded programs.
+    bool
+    ReadGPR(lldb::tid_t tid, void *buf, size_t buf_size);
+
+    /// Reads all floating point registers into the specified buffer.
+    /// FIXME: The FreeBSD implementation of this function should use tid in order
+    ///        to enable support for debugging threaded programs.
+    bool
+    ReadFPR(lldb::tid_t tid, void *buf, size_t buf_size);
+
+    /// Reads the specified register set into the specified buffer.
+    ///
+    /// This method is provided for use by RegisterContextFreeBSD derivatives.
+    /// FIXME: The FreeBSD implementation of this function should use tid in order
+    ///        to enable support for debugging threaded programs.
+    bool
+    ReadRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset);
+
+    /// Writes all general purpose registers into the specified buffer.
+    /// FIXME: The FreeBSD implementation of this function should use tid in order
+    ///        to enable support for debugging threaded programs.
+    bool
+    WriteGPR(lldb::tid_t tid, void *buf, size_t buf_size);
+
+    /// Writes all floating point registers into the specified buffer.
+    /// FIXME: The FreeBSD implementation of this function should use tid in order
+    ///        to enable support for debugging threaded programs.
+    bool
+    WriteFPR(lldb::tid_t tid, void *buf, size_t buf_size);
+
+    /// Writes the specified register set into the specified buffer.
+    ///
+    /// This method is provided for use by RegisterContextFreeBSD derivatives.
+    /// FIXME: The FreeBSD implementation of this function should use tid in order
+    ///        to enable support for debugging threaded programs.
+    bool
+    WriteRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset);
+
+    /// Writes a ptrace_lwpinfo structure corresponding to the given thread ID
+    /// to the memory region pointed to by @p lwpinfo.
+    bool
+    GetLwpInfo(lldb::tid_t tid, void *lwpinfo, int &error_no);
+
+    /// Writes the raw event message code (vis-a-vis PTRACE_GETEVENTMSG)
+    /// corresponding to the given thread IDto the memory pointed to by @p
+    /// message.
+    bool
+    GetEventMessage(lldb::tid_t tid, unsigned long *message);
+
+    /// Resumes the given thread.  If @p signo is anything but
+    /// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the thread.
+    bool
+    Resume(lldb::tid_t tid, uint32_t signo);
+
+    /// Single steps the given thread.  If @p signo is anything but
+    /// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the thread.
+    bool
+    SingleStep(lldb::tid_t tid, uint32_t signo);
+
+    /// Sends the inferior process a PTRACE_KILL signal.  The inferior will
+    /// still exists and can be interrogated.  Once resumed it will exit as
+    /// though it received a SIGKILL.
+    bool
+    BringProcessIntoLimbo();
+
+    lldb_private::Error
+    Detach(lldb::tid_t tid);
+
+    void
+    StopMonitor();
+
+private:
+    ProcessFreeBSD *m_process;
+
+    lldb::thread_t m_operation_thread;
+    lldb::thread_t m_monitor_thread;
+    lldb::pid_t m_pid;
+
+
+    lldb_private::Mutex m_server_mutex;
+    int m_terminal_fd;
+    int m_client_fd;
+    int m_server_fd;
+
+    struct OperationArgs
+    {
+        OperationArgs(ProcessMonitor *monitor);
+
+        ~OperationArgs();
+
+        ProcessMonitor *m_monitor;      // The monitor performing the attach.
+        sem_t m_semaphore;              // Posted to once operation complete.
+        lldb_private::Error m_error;    // Set if process operation failed.
+    };
+
+    /// @class LauchArgs
+    ///
+    /// @brief Simple structure to pass data to the thread responsible for
+    /// launching a child process.
+    struct LaunchArgs : OperationArgs
+    {
+        LaunchArgs(ProcessMonitor *monitor,
+                   lldb_private::Module *module,
+                   char const **argv,
+                   char const **envp,
+                   const char *stdin_path,
+                   const char *stdout_path,
+                   const char *stderr_path,
+                   const char *working_dir);
+
+        ~LaunchArgs();
+
+        lldb_private::Module *m_module; // The executable image to launch.
+        char const **m_argv;            // Process arguments.
+        char const **m_envp;            // Process environment.
+        const char *m_stdin_path;       // Redirect stdin or NULL.
+        const char *m_stdout_path;      // Redirect stdout or NULL.
+        const char *m_stderr_path;      // Redirect stderr or NULL.
+        const char *m_working_dir;      // Working directory or NULL.
+    };
+
+    void
+    StartLaunchOpThread(LaunchArgs *args, lldb_private::Error &error);
+
+    static void *
+    LaunchOpThread(void *arg);
+
+    static bool
+    Launch(LaunchArgs *args);
+
+    bool
+    EnableIPC();
+
+    struct AttachArgs : OperationArgs
+    {
+        AttachArgs(ProcessMonitor *monitor,
+                   lldb::pid_t pid);
+
+        ~AttachArgs();
+
+        lldb::pid_t m_pid;              // pid of the process to be attached.
+    };
+
+    void
+    StartAttachOpThread(AttachArgs *args, lldb_private::Error &error);
+
+    static void *
+    AttachOpThread(void *args);
+
+    static bool
+    Attach(AttachArgs *args);
+
+    static void
+    ServeOperation(OperationArgs *args);
+
+    static bool
+    DupDescriptor(const char *path, int fd, int flags);
+
+    static bool
+    MonitorCallback(void *callback_baton,
+                    lldb::pid_t pid, bool exited, int signal, int status);
+
+    static ProcessMessage
+    MonitorSIGTRAP(ProcessMonitor *monitor,
+                   const siginfo_t *info, lldb::pid_t pid);
+
+    static ProcessMessage
+    MonitorSignal(ProcessMonitor *monitor, 
+                  const siginfo_t *info, lldb::pid_t pid);
+
+    static ProcessMessage::CrashReason
+    GetCrashReasonForSIGSEGV(const siginfo_t *info);
+
+    static ProcessMessage::CrashReason
+    GetCrashReasonForSIGILL(const siginfo_t *info);
+
+    static ProcessMessage::CrashReason
+    GetCrashReasonForSIGFPE(const siginfo_t *info);
+
+    static ProcessMessage::CrashReason
+    GetCrashReasonForSIGBUS(const siginfo_t *info);
+
+    void
+    DoOperation(Operation *op);
+
+    /// Stops the child monitor thread.
+    void
+    StopMonitoringChildProcess();
+
+    /// Stops the operation thread used to attach/launch a process.
+    void
+    StopOpThread();
+
+    void
+    CloseFD(int &fd);
+};
+
+#endif // #ifndef liblldb_ProcessMonitor_H_
diff --git a/source/Plugins/Process/POSIX/POSIXStopInfo.cpp b/source/Plugins/Process/POSIX/POSIXStopInfo.cpp
new file mode 100644
index 000000000000..6e2c140682ba
--- /dev/null
+++ b/source/Plugins/Process/POSIX/POSIXStopInfo.cpp
@@ -0,0 +1,89 @@
+//===-- POSIXStopInfo.cpp ---------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "POSIXStopInfo.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+//===----------------------------------------------------------------------===//
+// POSIXLimboStopInfo
+
+POSIXLimboStopInfo::~POSIXLimboStopInfo() { }
+
+lldb::StopReason
+POSIXLimboStopInfo::GetStopReason() const
+{
+    return lldb::eStopReasonThreadExiting;
+}
+
+const char *
+POSIXLimboStopInfo::GetDescription()
+{
+    return "thread exiting";
+}
+
+bool
+POSIXLimboStopInfo::ShouldStop(Event *event_ptr)
+{
+    return false;
+}
+
+bool
+POSIXLimboStopInfo::ShouldNotify(Event *event_ptr)
+{
+    return false;
+}
+
+//===----------------------------------------------------------------------===//
+// POSIXCrashStopInfo
+
+POSIXCrashStopInfo::~POSIXCrashStopInfo() { }
+
+lldb::StopReason
+POSIXCrashStopInfo::GetStopReason() const
+{
+    return lldb::eStopReasonException;
+}
+
+const char *
+POSIXCrashStopInfo::GetDescription()
+{
+    return ProcessMessage::GetCrashReasonString(m_crash_reason, m_fault_addr);
+}
+
+//===----------------------------------------------------------------------===//
+// POSIXNewThreadStopInfo
+
+POSIXNewThreadStopInfo::~POSIXNewThreadStopInfo() { }
+
+lldb::StopReason
+POSIXNewThreadStopInfo::GetStopReason() const
+{
+    return lldb::eStopReasonNone;
+}
+
+const char *
+POSIXNewThreadStopInfo::GetDescription()
+{
+    return "thread spawned";
+}
+
+bool
+POSIXNewThreadStopInfo::ShouldStop(Event *event_ptr)
+{
+    return false;
+}
+
+bool
+POSIXNewThreadStopInfo::ShouldNotify(Event *event_ptr)
+{
+    return false;
+}
diff --git a/source/Plugins/Process/POSIX/POSIXStopInfo.h b/source/Plugins/Process/POSIX/POSIXStopInfo.h
new file mode 100644
index 000000000000..cbf309e53506
--- /dev/null
+++ b/source/Plugins/Process/POSIX/POSIXStopInfo.h
@@ -0,0 +1,120 @@
+//===-- POSIXStopInfo.h -----------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_POSIXStopInfo_H_
+#define liblldb_POSIXStopInfo_H_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Target/StopInfo.h"
+
+#include "POSIXThread.h"
+#include "ProcessMessage.h"
+
+//===----------------------------------------------------------------------===//
+/// @class POSIXStopInfo
+/// @brief Simple base class for all POSIX-specific StopInfo objects.
+///
+class POSIXStopInfo
+    : public lldb_private::StopInfo
+{
+public:
+    POSIXStopInfo(lldb_private::Thread &thread, uint32_t status)
+        : StopInfo(thread, status)
+        { }
+};
+
+//===----------------------------------------------------------------------===//
+/// @class POSIXLimboStopInfo
+/// @brief Represents the stop state of a process ready to exit.
+///
+class POSIXLimboStopInfo
+    : public POSIXStopInfo
+{
+public:
+    POSIXLimboStopInfo(POSIXThread &thread)
+        : POSIXStopInfo(thread, 0)
+        { }
+
+    ~POSIXLimboStopInfo();
+
+    lldb::StopReason
+    GetStopReason() const;
+
+    const char *
+    GetDescription();
+
+    bool
+    ShouldStop(lldb_private::Event *event_ptr);
+
+    bool
+    ShouldNotify(lldb_private::Event *event_ptr);
+};
+
+
+//===----------------------------------------------------------------------===//
+/// @class POSIXCrashStopInfo
+/// @brief Represents the stop state of process that is ready to crash.
+///
+class POSIXCrashStopInfo
+    : public POSIXStopInfo
+{
+public:
+    POSIXCrashStopInfo(POSIXThread &thread, uint32_t status,
+                       ProcessMessage::CrashReason reason,
+                       lldb::addr_t fault_addr)
+        : POSIXStopInfo(thread, status),
+          m_crash_reason(reason),
+          m_fault_addr(fault_addr)
+        { }
+
+    ~POSIXCrashStopInfo();
+
+    lldb::StopReason
+    GetStopReason() const;
+
+    const char *
+    GetDescription();
+
+private:
+    ProcessMessage::CrashReason m_crash_reason;
+    lldb::addr_t m_fault_addr;
+};    
+
+//===----------------------------------------------------------------------===//
+/// @class POSIXNewThreadStopInfo
+/// @brief Represents the stop state of process when a new thread is spawned.
+///
+
+class POSIXNewThreadStopInfo
+    : public POSIXStopInfo
+{
+public:
+    POSIXNewThreadStopInfo (POSIXThread &thread)
+        : POSIXStopInfo (thread, 0)
+        { }
+
+    ~POSIXNewThreadStopInfo();
+
+    lldb::StopReason
+    GetStopReason() const;
+
+    const char *
+    GetDescription();
+
+    bool
+    ShouldStop(lldb_private::Event *event_ptr);
+
+    bool
+    ShouldNotify(lldb_private::Event *event_ptr);
+};
+
+#endif
diff --git a/source/Plugins/Process/POSIX/POSIXThread.cpp b/source/Plugins/Process/POSIX/POSIXThread.cpp
new file mode 100644
index 000000000000..93c296679df2
--- /dev/null
+++ b/source/Plugins/Process/POSIX/POSIXThread.cpp
@@ -0,0 +1,578 @@
+//===-- POSIXThread.cpp -----------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/lldb-python.h"
+
+// C Includes
+#include <errno.h>
+
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Breakpoint/Watchpoint.h"
+#include "lldb/Breakpoint/BreakpointLocation.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"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/ThreadSpec.h"
+#include "POSIXStopInfo.h"
+#include "POSIXThread.h"
+#include "ProcessPOSIX.h"
+#include "ProcessPOSIXLog.h"
+#include "ProcessMonitor.h"
+#include "RegisterContext_i386.h"
+#include "RegisterContext_x86_64.h"
+#include "RegisterContextPOSIX.h"
+#include "RegisterContextLinux_x86_64.h"
+#include "RegisterContextFreeBSD_x86_64.h"
+
+#include "UnwindLLDB.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+POSIXThread::POSIXThread(Process &process, lldb::tid_t tid)
+    : Thread(process, tid),
+      m_frame_ap (),
+      m_breakpoint (),
+      m_thread_name_valid (false),
+      m_thread_name ()
+{
+    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()
+{
+    DestroyThread();
+}
+
+ProcessMonitor &
+POSIXThread::GetMonitor()
+{
+    ProcessSP base = GetProcess();
+    ProcessPOSIX &process = static_cast<ProcessPOSIX&>(*base);
+    return process.GetMonitor();
+}
+
+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->Printf ("POSIXThread::%s (tid = %" PRIi64 ") setting thread resume state to running", __FUNCTION__, GetID());
+}
+
+const char *
+POSIXThread::GetInfo()
+{
+    return NULL;
+}
+
+void
+POSIXThread::SetName (const char *name)
+{
+    m_thread_name_valid = (name && name[0]);
+    if (m_thread_name_valid)
+        m_thread_name.assign (name);
+    else
+        m_thread_name.clear();
+}
+
+const char *
+POSIXThread::GetName ()
+{
+    if (!m_thread_name_valid)
+    {
+        SetName(Host::GetThreadName(GetProcess()->GetID(), GetID()).c_str());
+        m_thread_name_valid = true;
+    }
+
+    if (m_thread_name.empty())
+        return NULL;
+    return m_thread_name.c_str();
+}
+
+lldb::RegisterContextSP
+POSIXThread::GetRegisterContext()
+{
+    if (!m_reg_context_sp)
+    {
+        ArchSpec arch = Host::GetArchitecture();
+
+        switch (arch.GetCore())
+        {
+        default:
+            assert(false && "CPU type not supported!");
+            break;
+
+        case ArchSpec::eCore_x86_32_i386:
+        case ArchSpec::eCore_x86_32_i486:
+        case ArchSpec::eCore_x86_32_i486sx:
+            m_reg_context_sp.reset(new RegisterContext_i386(*this, 0));
+            break;
+
+        case ArchSpec::eCore_x86_64_x86_64:
+            switch (arch.GetTriple().getOS())
+            {
+                case llvm::Triple::FreeBSD:
+                    m_reg_context_sp.reset(new RegisterContextFreeBSD_x86_64(*this, 0));
+                    break;
+                case llvm::Triple::Linux:
+                    m_reg_context_sp.reset(new RegisterContextLinux_x86_64(*this, 0));
+                    break;
+                default:
+                    assert(false && "OS not supported");
+                    break;
+            }
+            break;
+        }
+    }
+    return m_reg_context_sp;
+}
+
+lldb::RegisterContextSP
+POSIXThread::CreateRegisterContextForFrame(lldb_private::StackFrame *frame)
+{
+    lldb::RegisterContextSP reg_ctx_sp;
+    uint32_t concrete_frame_idx = 0;
+
+    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
+    if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
+        log->Printf ("POSIXThread::%s ()", __FUNCTION__);
+
+    if (frame)
+        concrete_frame_idx = frame->GetConcreteFrameIndex();
+
+    if (concrete_frame_idx == 0)
+        reg_ctx_sp = GetRegisterContext();
+    else
+    {
+        assert(GetUnwinder());
+        reg_ctx_sp = GetUnwinder()->CreateRegisterContextForFrame(frame);
+    }
+
+    return reg_ctx_sp;
+}
+
+bool
+POSIXThread::CalculateStopInfo()
+{
+    SetStopInfo (m_stop_info_sp);
+    return true;
+}
+
+Unwind *
+POSIXThread::GetUnwinder()
+{
+    if (m_unwinder_ap.get() == NULL)
+        m_unwinder_ap.reset(new UnwindLLDB(*this));
+
+    return m_unwinder_ap.get();
+}
+
+void
+POSIXThread::WillResume(lldb::StateType resume_state)
+{
+    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()
+{
+    lldb::StateType resume_state = GetResumeState();
+    ProcessMonitor &monitor = GetMonitor();
+    bool status;
+
+    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
+    if (log)
+        log->Printf ("POSIXThread::%s (), resume_state = %s", __FUNCTION__,
+                         StateAsCString(resume_state));
+
+    switch (resume_state)
+    {
+    default:
+        assert(false && "Unexpected state for resume!");
+        status = false;
+        break;
+
+    case lldb::eStateRunning:
+        SetState(resume_state);
+        status = monitor.Resume(GetID(), GetResumeSignal());
+        break;
+
+    case lldb::eStateStepping:
+        SetState(resume_state);
+        status = monitor.SingleStep(GetID(), GetResumeSignal());
+        break;
+    case lldb::eStateStopped:
+    case lldb::eStateSuspended:
+        status = true;
+        break;
+    }
+
+    return status;
+}
+
+void
+POSIXThread::Notify(const ProcessMessage &message)
+{
+    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
+    if (log)
+        log->Printf ("POSIXThread::%s () message kind = '%s' for tid %" PRIu64,
+                     __FUNCTION__, message.PrintKind(), GetID());
+
+    switch (message.GetKind())
+    {
+    default:
+        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;
+
+    case ProcessMessage::eSignalDeliveredMessage:
+        SignalDeliveredNotify(message);
+        break;
+
+    case ProcessMessage::eTraceMessage:
+        TraceNotify(message);
+        break;
+
+    case ProcessMessage::eBreakpointMessage:
+        BreakNotify(message);
+        break;
+
+    case ProcessMessage::eWatchpointMessage:
+        WatchNotify(message);
+        break;
+
+    case ProcessMessage::eCrashMessage:
+        CrashNotify(message);
+        break;
+
+    case ProcessMessage::eNewThreadMessage:
+        ThreadNotify(message);
+        break;
+    }
+}
+
+bool
+POSIXThread::EnableHardwareWatchpoint(Watchpoint *wp)
+{
+    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 = 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 wp_set;
+}
+
+bool
+POSIXThread::DisableHardwareWatchpoint(Watchpoint *wp)
+{
+    bool result = false;
+    if (wp)
+    {
+        lldb::RegisterContextSP reg_ctx_sp = GetRegisterContext();
+        if (reg_ctx_sp.get())
+            result = reg_ctx_sp->ClearHardwareWatchpoint(wp->GetHardwareIndex());
+    }
+    return result;
+}
+
+uint32_t
+POSIXThread::NumSupportedHardwareWatchpoints()
+{
+    lldb::RegisterContextSP reg_ctx_sp = GetRegisterContext();
+    if (reg_ctx_sp.get())
+        return reg_ctx_sp->NumSupportedHardwareWatchpoints();
+    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)
+{
+    bool status;
+    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
+
+    assert(GetRegisterContext());
+    status = GetRegisterContextPOSIX()->UpdateAfterBreakpoint();
+    assert(status && "Breakpoint update failed!");
+
+    // With our register state restored, resolve the breakpoint object
+    // corresponding to our current PC.
+    assert(GetRegisterContext());
+    lldb::addr_t pc = GetRegisterContext()->GetPC();
+    if (log)
+        log->Printf ("POSIXThread::%s () PC=0x%8.8" PRIx64, __FUNCTION__, pc);
+    lldb::BreakpointSiteSP bp_site(GetProcess()->GetBreakpointSiteList().FindByAddress(pc));
+
+    // If the breakpoint is for this thread, then we'll report the hit, but if it is for another thread,
+    // we can just report no reason.  We don't need to worry about stepping over the breakpoint here, that
+    // will be taken care of when the thread resumes and notices that there's a breakpoint under the pc.
+    if (bp_site && bp_site->ValidForThisThread(this))
+    {
+        lldb::break_id_t bp_id = bp_site->GetID();
+        if (GetProcess()->GetThreadList().SetSelectedThreadByID(GetID()))
+            SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id));
+        else
+            assert(false && "Invalid thread ID during BreakNotify.");
+    }
+    else
+    {
+        const ThreadSpec *spec = bp_site ? 
+            bp_site->GetOwnerAtIndex(0)->GetOptionsNoCreate()->GetThreadSpecNoCreate() : 0;
+
+        if (spec && spec->TIDMatches(*this))
+            assert(false && "BreakpointSite is invalid for the current ThreadSpec.");
+        else
+        {
+            if (!m_stop_info_sp) {
+                StopInfoSP invalid_stop_info_sp;
+                SetStopInfo (invalid_stop_info_sp);
+            }
+        }
+    }
+}
+
+void
+POSIXThread::WatchNotify(const ProcessMessage &message)
+{
+    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
+
+    lldb::addr_t halt_addr = message.GetHWAddress();
+    if (log)
+        log->Printf ("POSIXThread::%s () Hardware Watchpoint Address = 0x%8.8"
+                     PRIx64, __FUNCTION__, halt_addr);
+
+    RegisterContextPOSIX* reg_ctx = GetRegisterContextPOSIX();
+    if (reg_ctx)
+    {
+        uint32_t num_hw_wps = reg_ctx->NumSupportedHardwareWatchpoints();
+        uint32_t wp_idx;
+        for (wp_idx = 0; wp_idx < num_hw_wps; wp_idx++)
+        {
+            if (reg_ctx->IsWatchpointHit(wp_idx))
+            {
+                // Clear the watchpoint hit here
+                reg_ctx->ClearWatchpointHits();
+                break;
+            }
+        }
+
+        if (wp_idx == num_hw_wps)
+            return;
+
+        Target &target = GetProcess()->GetTarget();
+        lldb::addr_t wp_monitor_addr = reg_ctx->GetWatchpointAddress(wp_idx);
+        const WatchpointList &wp_list = target.GetWatchpointList();
+        lldb::WatchpointSP wp_sp = wp_list.FindByAddress(wp_monitor_addr);
+
+        assert(wp_sp.get() && "No watchpoint found");
+        SetStopInfo (StopInfo::CreateStopReasonWithWatchpointID(*this,
+                                                                wp_sp->GetID()));
+    }
+}
+
+void
+POSIXThread::TraceNotify(const ProcessMessage &message)
+{
+    SetStopInfo (StopInfo::CreateStopReasonToTrace(*this));
+}
+
+void
+POSIXThread::LimboNotify(const ProcessMessage &message)
+{
+    SetStopInfo (lldb::StopInfoSP(new POSIXLimboStopInfo(*this)));
+}
+
+void
+POSIXThread::SignalNotify(const ProcessMessage &message)
+{
+    int signo = message.GetSignal();
+
+    SetStopInfo (StopInfo::CreateStopReasonWithSignal(*this, signo));
+    SetResumeSignal(signo);
+}
+
+void
+POSIXThread::SignalDeliveredNotify(const ProcessMessage &message)
+{
+    int signo = message.GetSignal();
+
+    SetStopInfo (StopInfo::CreateStopReasonWithSignal(*this, signo));
+    SetResumeSignal(signo);
+}
+
+void
+POSIXThread::CrashNotify(const ProcessMessage &message)
+{
+    // FIXME: Update stop reason as per bugzilla 14598
+    int signo = message.GetSignal();
+
+    assert(message.GetKind() == ProcessMessage::eCrashMessage);
+
+    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
+    if (log)
+        log->Printf ("POSIXThread::%s () signo = %i, reason = '%s'",
+                     __FUNCTION__, signo, message.PrintCrashReason());
+
+    SetStopInfo (lldb::StopInfoSP(new POSIXCrashStopInfo(*this, signo,
+                                                         message.GetCrashReason(),
+                                                         message.GetFaultAddress())));
+    SetResumeSignal(signo);
+}
+
+void
+POSIXThread::ThreadNotify(const ProcessMessage &message)
+{
+    SetStopInfo (lldb::StopInfoSP(new POSIXNewThreadStopInfo(*this)));
+}
+
+unsigned
+POSIXThread::GetRegisterIndexFromOffset(unsigned offset)
+{
+    unsigned reg = LLDB_INVALID_REGNUM;
+    ArchSpec arch = Host::GetArchitecture();
+
+    switch (arch.GetCore())
+    {
+    default:
+        llvm_unreachable("CPU type not supported!");
+        break;
+
+    case ArchSpec::eCore_x86_32_i386:
+    case ArchSpec::eCore_x86_32_i486:
+    case ArchSpec::eCore_x86_32_i486sx:
+    case ArchSpec::eCore_x86_64_x86_64:
+        {
+            RegisterContextSP base = GetRegisterContext();
+            if (base) {
+                RegisterContextPOSIX &context = static_cast<RegisterContextPOSIX &>(*base);
+                reg = context.GetRegisterIndexFromOffset(offset);
+            }
+        }
+        break;
+    }
+    return reg;
+}
+
+const char *
+POSIXThread::GetRegisterName(unsigned reg)
+{
+    const char * name = nullptr;
+    ArchSpec arch = Host::GetArchitecture();
+
+    switch (arch.GetCore())
+    {
+    default:
+        assert(false && "CPU type not supported!");
+        break;
+
+    case ArchSpec::eCore_x86_32_i386:
+    case ArchSpec::eCore_x86_32_i486:
+    case ArchSpec::eCore_x86_32_i486sx:
+    case ArchSpec::eCore_x86_64_x86_64:
+        name = GetRegisterContext()->GetRegisterName(reg);
+        break;
+    }
+    return name;
+}
+
+const char *
+POSIXThread::GetRegisterNameFromOffset(unsigned offset)
+{
+    return GetRegisterName(GetRegisterIndexFromOffset(offset));
+}
+
diff --git a/source/Plugins/Process/POSIX/POSIXThread.h b/source/Plugins/Process/POSIX/POSIXThread.h
new file mode 100644
index 000000000000..d051d23860df
--- /dev/null
+++ b/source/Plugins/Process/POSIX/POSIXThread.h
@@ -0,0 +1,133 @@
+//===-- POSIXThread.h -------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_POSIXThread_H_
+#define liblldb_POSIXThread_H_
+
+// C Includes
+// C++ Includes
+#include <memory>
+#include <string>
+
+// Other libraries and framework includes
+#include "lldb/Target/Thread.h"
+#include "RegisterContextPOSIX.h"
+
+class ProcessMessage;
+class ProcessMonitor;
+class RegisterContextPOSIX;
+
+//------------------------------------------------------------------------------
+// @class POSIXThread
+// @brief Abstraction of a POSIX thread.
+class POSIXThread
+    : public lldb_private::Thread
+{
+public:
+    POSIXThread(lldb_private::Process &process, lldb::tid_t tid);
+
+    virtual ~POSIXThread();
+
+    void
+    RefreshStateAfterStop();
+
+    virtual void
+    WillResume(lldb::StateType resume_state);
+
+    // This notifies the thread when a private stop occurs.
+    virtual void
+    DidStop ();
+
+    const char *
+    GetInfo();
+
+    void
+    SetName (const char *name);
+
+    const char *
+    GetName ();
+
+    virtual lldb::RegisterContextSP
+    GetRegisterContext();
+
+    virtual lldb::RegisterContextSP
+    CreateRegisterContextForFrame (lldb_private::StackFrame *frame);
+
+    //--------------------------------------------------------------------------
+    // These functions provide a mapping from the register offset
+    // back to the register index or name for use in debugging or log
+    // output.
+
+    unsigned
+    GetRegisterIndexFromOffset(unsigned offset);
+
+    const char *
+    GetRegisterName(unsigned reg);
+
+    const char *
+    GetRegisterNameFromOffset(unsigned offset);
+
+    //--------------------------------------------------------------------------
+    // These methods form a specialized interface to POSIX threads.
+    //
+    bool Resume();
+
+    void Notify(const ProcessMessage &message);
+
+    //--------------------------------------------------------------------------
+    // These methods provide an interface to watchpoints
+    //
+    bool EnableHardwareWatchpoint(lldb_private::Watchpoint *wp);
+
+    bool DisableHardwareWatchpoint(lldb_private::Watchpoint *wp);
+
+    uint32_t NumSupportedHardwareWatchpoints();
+
+    uint32_t FindVacantWatchpointIndex();
+
+protected:
+    RegisterContextPOSIX *
+    GetRegisterContextPOSIX ()
+    {
+        if (!m_reg_context_sp)
+            m_reg_context_sp = GetRegisterContext();
+#if 0
+        return dynamic_cast<RegisterContextPOSIX*>(m_reg_context_sp.get());
+#endif
+        return (RegisterContextPOSIX *)m_reg_context_sp.get();
+    }
+    
+    std::unique_ptr<lldb_private::StackFrame> m_frame_ap;
+
+    lldb::BreakpointSiteSP m_breakpoint;
+
+    bool m_thread_name_valid;
+    std::string m_thread_name;
+
+    ProcessMonitor &
+    GetMonitor();
+
+    virtual bool
+    CalculateStopInfo();
+
+    void BreakNotify(const ProcessMessage &message);
+    void WatchNotify(const ProcessMessage &message);
+    virtual void TraceNotify(const ProcessMessage &message);
+    void LimboNotify(const ProcessMessage &message);
+    void SignalNotify(const ProcessMessage &message);
+    void SignalDeliveredNotify(const ProcessMessage &message);
+    void CrashNotify(const ProcessMessage &message);
+    void ThreadNotify(const ProcessMessage &message);
+    void ExitNotify(const ProcessMessage &message);
+
+    lldb_private::Unwind *
+    GetUnwinder();
+};
+
+#endif // #ifndef liblldb_POSIXThread_H_
diff --git a/source/Plugins/Process/POSIX/ProcessMessage.cpp b/source/Plugins/Process/POSIX/ProcessMessage.cpp
new file mode 100644
index 000000000000..60a29e07cea8
--- /dev/null
+++ b/source/Plugins/Process/POSIX/ProcessMessage.cpp
@@ -0,0 +1,258 @@
+//===-- ProcessMessage.cpp --------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ProcessMessage.h"
+
+#include <sstream>
+
+using namespace lldb_private;
+
+namespace {
+
+inline void AppendFaultAddr(std::string& str, lldb::addr_t addr)
+{
+    std::stringstream ss;
+    ss << " (fault address: 0x" << std::hex << addr << ")";
+    str += ss.str();
+}
+
+}
+
+const char *
+ProcessMessage::GetCrashReasonString(CrashReason reason, lldb::addr_t fault_addr)
+{
+    static std::string str;
+
+    switch (reason)
+    {
+    default:
+        assert(false && "invalid CrashReason");
+        break;
+
+    case eInvalidAddress:
+        str = "invalid address";
+        AppendFaultAddr(str, fault_addr);
+        break;
+    case ePrivilegedAddress:
+        str = "address access protected";
+        AppendFaultAddr(str, fault_addr);
+        break;
+    case eIllegalOpcode:
+        str = "illegal instruction";
+        break;
+    case eIllegalOperand:
+        str = "illegal instruction operand";
+        break;
+    case eIllegalAddressingMode:
+        str = "illegal addressing mode";
+        break;
+    case eIllegalTrap:
+        str = "illegal trap";
+        break;
+    case ePrivilegedOpcode:
+        str = "privileged instruction";
+        break;
+    case ePrivilegedRegister:
+        str = "privileged register";
+        break;
+    case eCoprocessorError:
+        str = "coprocessor error";
+        break;
+    case eInternalStackError:
+        str = "internal stack error";
+        break;
+    case eIllegalAlignment:
+        str = "illegal alignment";
+        break;
+    case eIllegalAddress:
+        str = "illegal address";
+        break;
+    case eHardwareError:
+        str = "hardware error";
+        break;
+    case eIntegerDivideByZero:
+        str = "integer divide by zero";
+        break;
+    case eIntegerOverflow:
+        str = "integer overflow";
+        break;
+    case eFloatDivideByZero:
+        str = "floating point divide by zero";
+        break;
+    case eFloatOverflow:
+        str = "floating point overflow";
+        break;
+    case eFloatUnderflow:
+        str = "floating point underflow";
+        break;
+    case eFloatInexactResult:
+        str = "inexact floating point result";
+        break;
+    case eFloatInvalidOperation:
+        str = "invalid floating point operation";
+        break;
+    case eFloatSubscriptRange:
+        str = "invalid floating point subscript range";
+        break;
+    }
+
+    return str.c_str();
+}
+
+const char *
+ProcessMessage::PrintCrashReason(CrashReason reason)
+{
+#ifdef LLDB_CONFIGURATION_BUILDANDINTEGRATION
+    // Just return the code in asci for integration builds.
+    chcar str[8];
+    sprintf(str, "%d", reason);
+#else
+    const char *str = NULL;
+
+    switch (reason)
+    {
+        case eInvalidCrashReason:
+            str = "eInvalidCrashReason";
+            break;
+
+        // SIGSEGV crash reasons.
+        case eInvalidAddress:
+            str = "eInvalidAddress";
+            break;
+        case ePrivilegedAddress:
+            str = "ePrivilegedAddress";
+            break;
+
+        // SIGILL crash reasons.
+        case eIllegalOpcode:
+            str = "eIllegalOpcode";
+            break;
+        case eIllegalOperand:
+            str = "eIllegalOperand";
+            break;
+        case eIllegalAddressingMode:
+            str = "eIllegalAddressingMode";
+            break;
+        case eIllegalTrap:
+            str = "eIllegalTrap";
+            break;
+        case ePrivilegedOpcode:
+            str = "ePrivilegedOpcode";
+            break;
+        case ePrivilegedRegister:
+            str = "ePrivilegedRegister";
+            break;
+        case eCoprocessorError:
+            str = "eCoprocessorError";
+            break;
+        case eInternalStackError:
+            str = "eInternalStackError";
+            break;
+
+        // SIGBUS crash reasons:
+        case eIllegalAlignment:
+            str = "eIllegalAlignment";
+            break;
+        case eIllegalAddress:
+            str = "eIllegalAddress";
+            break;
+        case eHardwareError:
+            str = "eHardwareError";
+            break;
+
+        // SIGFPE crash reasons:
+        case eIntegerDivideByZero:
+            str = "eIntegerDivideByZero";
+            break;
+        case eIntegerOverflow:
+            str = "eIntegerOverflow";
+            break;
+        case eFloatDivideByZero:
+            str = "eFloatDivideByZero";
+            break;
+        case eFloatOverflow:
+            str = "eFloatOverflow";
+            break;
+        case eFloatUnderflow:
+            str = "eFloatUnderflow";
+            break;
+        case eFloatInexactResult:
+            str = "eFloatInexactResult";
+            break;
+        case eFloatInvalidOperation:
+            str = "eFloatInvalidOperation";
+            break;
+        case eFloatSubscriptRange:
+            str = "eFloatSubscriptRange";
+            break;
+    }
+#endif
+
+    return str;
+}
+
+const char *
+ProcessMessage::PrintCrashReason() const
+{
+    return PrintCrashReason(m_crash_reason);
+}
+
+const char *
+ProcessMessage::PrintKind(Kind kind)
+{
+#ifdef LLDB_CONFIGURATION_BUILDANDINTEGRATION
+    // Just return the code in asci for integration builds.
+    chcar str[8];
+    sprintf(str, "%d", reason);
+#else
+    const char *str = NULL;
+
+    switch (kind)
+    {
+    case eInvalidMessage:
+        str = "eInvalidMessage";
+        break;
+    case eExitMessage:
+        str = "eExitMessage";
+        break;
+    case eLimboMessage:
+        str = "eLimboMessage";
+        break;
+    case eSignalMessage:
+        str = "eSignalMessage";
+        break;
+    case eSignalDeliveredMessage:
+        str = "eSignalDeliveredMessage";
+        break;
+    case eTraceMessage:
+        str = "eTraceMessage";
+        break;
+    case eBreakpointMessage:
+        str = "eBreakpointMessage";
+        break;
+    case eWatchpointMessage:
+        str = "eWatchpointMessage";
+        break;
+    case eCrashMessage:
+        str = "eCrashMessage";
+        break;
+    case eNewThreadMessage:
+        str = "eNewThreadMessage";
+        break;
+    }
+#endif
+
+    return str;
+}
+
+const char *
+ProcessMessage::PrintKind() const
+{
+    return PrintKind(m_kind);
+}
diff --git a/source/Plugins/Process/POSIX/ProcessMessage.h b/source/Plugins/Process/POSIX/ProcessMessage.h
new file mode 100644
index 000000000000..c6c460c13445
--- /dev/null
+++ b/source/Plugins/Process/POSIX/ProcessMessage.h
@@ -0,0 +1,207 @@
+//===-- ProcessMessage.h ----------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ProcessMessage_H_
+#define liblldb_ProcessMessage_H_
+
+#include <cassert>
+
+#include "lldb/lldb-defines.h"
+#include "lldb/lldb-types.h"
+
+class ProcessMessage
+{
+public:
+
+    /// The type of signal this message can correspond to.
+    enum Kind
+    {
+        eInvalidMessage,
+        eExitMessage,
+        eLimboMessage,
+        eSignalMessage,
+        eSignalDeliveredMessage,
+        eTraceMessage,
+        eBreakpointMessage,
+        eWatchpointMessage,
+        eCrashMessage,
+        eNewThreadMessage
+    };
+
+    enum CrashReason
+    {
+        eInvalidCrashReason,
+
+        // SIGSEGV crash reasons.
+        eInvalidAddress,
+        ePrivilegedAddress,
+
+        // SIGILL crash reasons.
+        eIllegalOpcode,
+        eIllegalOperand,
+        eIllegalAddressingMode,
+        eIllegalTrap,
+        ePrivilegedOpcode,
+        ePrivilegedRegister,
+        eCoprocessorError,
+        eInternalStackError,
+
+        // SIGBUS crash reasons,
+        eIllegalAlignment,
+        eIllegalAddress,
+        eHardwareError,
+
+        // SIGFPE crash reasons,
+        eIntegerDivideByZero,
+        eIntegerOverflow,
+        eFloatDivideByZero,
+        eFloatOverflow,
+        eFloatUnderflow,
+        eFloatInexactResult,
+        eFloatInvalidOperation,
+        eFloatSubscriptRange
+    };
+
+    ProcessMessage()
+        : m_tid(LLDB_INVALID_PROCESS_ID),
+          m_kind(eInvalidMessage),
+          m_crash_reason(eInvalidCrashReason),
+          m_status(0),
+          m_addr(0) { }
+
+    Kind GetKind() const { return m_kind; }
+
+    lldb::tid_t GetTID() const { return m_tid; }
+
+    /// Indicates that the thread @p tid is about to exit with status @p status.
+    static ProcessMessage Limbo(lldb::tid_t tid, int status) {
+        return ProcessMessage(tid, eLimboMessage, status);
+    }
+
+    /// Indicates that the thread @p tid had the signal @p signum delivered.
+    static ProcessMessage Signal(lldb::tid_t tid, int signum) {
+        return ProcessMessage(tid, eSignalMessage, signum);
+    }
+
+    /// Indicates that a signal @p signum generated by the debugging process was
+    /// delivered to the thread @p tid.
+    static ProcessMessage SignalDelivered(lldb::tid_t tid, int signum) {
+        return ProcessMessage(tid, eSignalDeliveredMessage, signum);
+    }
+
+    /// Indicates that the thread @p tid encountered a trace point.
+    static ProcessMessage Trace(lldb::tid_t tid) {
+        return ProcessMessage(tid, eTraceMessage);
+    }
+
+    /// Indicates that the thread @p tid encountered a break point.
+    static ProcessMessage Break(lldb::tid_t tid) {
+        return ProcessMessage(tid, eBreakpointMessage);
+    }
+
+    static ProcessMessage Watch(lldb::tid_t tid, lldb::addr_t wp_addr) {
+        return ProcessMessage(tid, eWatchpointMessage, 0, wp_addr);
+    }
+
+    /// Indicates that the thread @p tid crashed.
+    static ProcessMessage Crash(lldb::pid_t pid, CrashReason reason,
+                                int signo, lldb::addr_t fault_addr) {
+        ProcessMessage message(pid, eCrashMessage, signo, fault_addr);
+        message.m_crash_reason = reason;
+        return message;
+    }
+
+    /// 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;
+    }
+
+    int GetSignal() const {
+        assert(GetKind() == eSignalMessage || GetKind() == eCrashMessage ||
+               GetKind() == eSignalDeliveredMessage);
+        return m_status;
+    }
+
+    int GetStopStatus() const {
+        assert(GetKind() == eSignalMessage);
+        return m_status;
+    }
+
+    CrashReason GetCrashReason() const {
+        assert(GetKind() == eCrashMessage);
+        return m_crash_reason;
+    }
+
+    lldb::addr_t GetFaultAddress() const {
+        assert(GetKind() == eCrashMessage);
+        return m_addr;
+    }
+
+    lldb::addr_t GetHWAddress() const {
+        assert(GetKind() == eWatchpointMessage || GetKind() == eTraceMessage);
+        return m_addr;
+    }
+
+    lldb::tid_t GetChildTID() const {
+        assert(GetKind() == eNewThreadMessage);
+        return m_child_tid;
+    }
+
+    static const char *
+    GetCrashReasonString(CrashReason reason, lldb::addr_t fault_addr);
+
+    const char *
+    PrintCrashReason() const;
+
+    static const char *
+    PrintCrashReason(CrashReason reason);
+
+    const char *
+    PrintKind() const;
+
+    static const char *
+    PrintKind(Kind);
+
+private:
+    ProcessMessage(lldb::tid_t tid, Kind kind, 
+                   int status = 0, lldb::addr_t addr = 0)
+        : m_tid(tid),
+          m_kind(kind),
+          m_crash_reason(eInvalidCrashReason),
+          m_status(status),
+          m_addr(addr),
+          m_child_tid(0) { }
+
+    ProcessMessage(lldb::tid_t tid, Kind kind, lldb::tid_t child_tid)
+        : m_tid(tid),
+          m_kind(kind),
+          m_crash_reason(eInvalidCrashReason),
+          m_status(0),
+          m_addr(0),
+          m_child_tid(child_tid) { }
+
+    lldb::tid_t m_tid;
+    Kind        m_kind         : 8;
+    CrashReason m_crash_reason : 8;
+    int m_status;
+    lldb::addr_t m_addr;
+    lldb::tid_t m_child_tid;
+};
+
+#endif // #ifndef liblldb_ProcessMessage_H_
diff --git a/source/Plugins/Process/POSIX/ProcessPOSIX.cpp b/source/Plugins/Process/POSIX/ProcessPOSIX.cpp
new file mode 100644
index 000000000000..f04631ddf914
--- /dev/null
+++ b/source/Plugins/Process/POSIX/ProcessPOSIX.cpp
@@ -0,0 +1,911 @@
+//===-- ProcessPOSIX.cpp ----------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/lldb-python.h"
+
+// C Includes
+#include <errno.h>
+
+// C++ Includes
+// Other libraries and framework includes
+#include "lldb/Breakpoint/Watchpoint.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/State.h"
+#include "lldb/Host/FileSpec.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Target/DynamicLoader.h"
+#include "lldb/Target/Platform.h"
+#include "lldb/Target/Target.h"
+
+#include "ProcessPOSIX.h"
+#include "ProcessPOSIXLog.h"
+#include "Plugins/Process/Utility/InferiorCallPOSIX.h"
+#include "ProcessMonitor.h"
+#include "POSIXThread.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//------------------------------------------------------------------------------
+// Static functions.
+#if 0
+Process*
+ProcessPOSIX::CreateInstance(Target& target, Listener &listener)
+{
+    return new ProcessPOSIX(target, listener);
+}
+
+
+void
+ProcessPOSIX::Initialize()
+{
+    static bool g_initialized = false;
+
+    if (!g_initialized)
+    {
+        g_initialized = true;
+        PluginManager::RegisterPlugin(GetPluginNameStatic(),
+                                      GetPluginDescriptionStatic(),
+                                      CreateInstance);
+
+        Log::Callbacks log_callbacks = {
+            ProcessPOSIXLog::DisableLog,
+            ProcessPOSIXLog::EnableLog,
+            ProcessPOSIXLog::ListLogCategories
+        };
+        
+        Log::RegisterLogChannel (ProcessPOSIX::GetPluginNameStatic(), log_callbacks);
+    }
+}
+#endif
+
+//------------------------------------------------------------------------------
+// Constructors and destructors.
+
+ProcessPOSIX::ProcessPOSIX(Target& target, Listener &listener)
+    : Process(target, listener),
+      m_byte_order(lldb::endian::InlHostByteOrder()),
+      m_monitor(NULL),
+      m_module(NULL),
+      m_message_mutex (Mutex::eMutexTypeRecursive),
+      m_exit_now(false),
+      m_seen_initial_stop()
+{
+    // FIXME: Putting this code in the ctor and saving the byte order in a
+    // member variable is a hack to avoid const qual issues in GetByteOrder.
+	lldb::ModuleSP module = GetTarget().GetExecutableModule();
+	if (module && module->GetObjectFile())
+		m_byte_order = module->GetObjectFile()->GetByteOrder();
+}
+
+ProcessPOSIX::~ProcessPOSIX()
+{
+    delete m_monitor;
+}
+
+//------------------------------------------------------------------------------
+// Process protocol.
+void
+ProcessPOSIX::Finalize()
+{
+  Process::Finalize();
+
+  if (m_monitor)
+    m_monitor->StopMonitor();
+}
+
+bool
+ProcessPOSIX::CanDebug(Target &target, bool plugin_specified_by_name)
+{
+    // For now we are just making sure the file exists for a given module
+    ModuleSP exe_module_sp(target.GetExecutableModule());
+    if (exe_module_sp.get())
+        return exe_module_sp->GetFileSpec().Exists();
+    // If there is no executable module, we return true since we might be preparing to attach.
+    return true;
+}
+
+Error
+ProcessPOSIX::DoAttachToProcessWithID(lldb::pid_t pid)
+{
+    Error error;
+    assert(m_monitor == NULL);
+
+    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
+    if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
+        log->Printf ("ProcessPOSIX::%s(pid = %" PRIi64 ")", __FUNCTION__, GetID());
+
+    m_monitor = new ProcessMonitor(this, pid, error);
+
+    if (!error.Success())
+        return error;
+
+    PlatformSP platform_sp (m_target.GetPlatform ());
+    assert (platform_sp.get());
+    if (!platform_sp)
+        return error;  // FIXME: Detatch?
+
+    // Find out what we can about this process
+    ProcessInstanceInfo process_info;
+    platform_sp->GetProcessInfo (pid, process_info);
+
+    // Resolve the executable module
+    ModuleSP exe_module_sp;
+    FileSpecList executable_search_paths (Target::GetDefaultExecutableSearchPaths());
+    error = platform_sp->ResolveExecutable(process_info.GetExecutableFile(),
+                                           m_target.GetArchitecture(),
+                                           exe_module_sp,
+                                           executable_search_paths.GetSize() ? &executable_search_paths : NULL);
+    if (!error.Success())
+        return error;
+
+    // Fix the target architecture if necessary
+    const ArchSpec &module_arch = exe_module_sp->GetArchitecture();
+    if (module_arch.IsValid() && !m_target.GetArchitecture().IsExactMatch(module_arch))
+        m_target.SetArchitecture(module_arch);
+
+    // Initialize the target module list
+    m_target.SetExecutableModule (exe_module_sp, true);
+
+    SetSTDIOFileDescriptor(m_monitor->GetTerminalFD());
+
+    SetID(pid);
+
+    return error;
+}
+
+Error
+ProcessPOSIX::DoAttachToProcessWithID (lldb::pid_t pid,  const ProcessAttachInfo &attach_info)
+{
+    return DoAttachToProcessWithID(pid);
+}
+
+Error
+ProcessPOSIX::WillLaunch(Module* module)
+{
+    Error error;
+    return error;
+}
+
+const char *
+ProcessPOSIX::GetFilePath(
+    const lldb_private::ProcessLaunchInfo::FileAction *file_action,
+    const char *default_path)
+{
+    const char *pts_name = "/dev/pts/";
+    const char *path = NULL;
+
+    if (file_action)
+    {
+        if (file_action->GetAction () == ProcessLaunchInfo::FileAction::eFileActionOpen)
+            path = file_action->GetPath();
+            // By default the stdio paths passed in will be pseudo-terminal
+            // (/dev/pts). If so, convert to using a different default path
+            // instead to redirect I/O to the debugger console. This should
+            //  also handle user overrides to /dev/null or a different file.
+            if (::strncmp(path, pts_name, ::strlen(pts_name)) == 0)
+                path = default_path;
+    }
+
+    return path;
+}
+
+Error
+ProcessPOSIX::DoLaunch (Module *module,
+                       const ProcessLaunchInfo &launch_info)
+{
+    Error error;
+    assert(m_monitor == NULL);
+
+    const char* working_dir = launch_info.GetWorkingDirectory();
+    if (working_dir) {
+      FileSpec WorkingDir(working_dir, true);
+      if (!WorkingDir || WorkingDir.GetFileType() != FileSpec::eFileTypeDirectory)
+      {
+          error.SetErrorStringWithFormat("No such file or directory: %s", working_dir);
+          return error;
+      }
+    }
+
+    SetPrivateState(eStateLaunching);
+
+    const lldb_private::ProcessLaunchInfo::FileAction *file_action;
+
+    // Default of NULL will mean to use existing open file descriptors
+    const char *stdin_path = NULL;
+    const char *stdout_path = NULL;
+    const char *stderr_path = NULL;
+
+    file_action = launch_info.GetFileActionForFD (STDIN_FILENO);
+    stdin_path = GetFilePath(file_action, stdin_path);
+
+    file_action = launch_info.GetFileActionForFD (STDOUT_FILENO);
+    stdout_path = GetFilePath(file_action, stdout_path);
+
+    file_action = launch_info.GetFileActionForFD (STDERR_FILENO);
+    stderr_path = GetFilePath(file_action, stderr_path);
+
+    m_monitor = new ProcessMonitor (this, 
+                                    module,
+                                    launch_info.GetArguments().GetConstArgumentVector(), 
+                                    launch_info.GetEnvironmentEntries().GetConstArgumentVector(),
+                                    stdin_path, 
+                                    stdout_path, 
+                                    stderr_path,
+                                    working_dir,
+                                    error);
+
+    m_module = module;
+
+    if (!error.Success())
+        return error;
+
+    SetSTDIOFileDescriptor(m_monitor->GetTerminalFD());
+
+    SetID(m_monitor->GetPID());
+    return error;
+}
+
+void
+ProcessPOSIX::DidLaunch()
+{
+}
+
+Error
+ProcessPOSIX::DoResume()
+{
+    StateType state = GetPrivateState();
+
+    assert(state == eStateStopped);
+
+    SetPrivateState(eStateRunning);
+
+    bool did_resume = false;
+
+    Mutex::Locker 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());
+        did_resume = thread->Resume() || did_resume;
+    }
+    assert(did_resume && "Process resume failed!");
+
+    return Error();
+}
+
+addr_t
+ProcessPOSIX::GetImageInfoAddress()
+{
+    Target *target = &GetTarget();
+    ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile();
+    Address addr = obj_file->GetImageInfoAddress();
+
+    if (addr.IsValid()) 
+        return addr.GetLoadAddress(target);
+    else
+        return LLDB_INVALID_ADDRESS;
+}
+
+Error
+ProcessPOSIX::DoHalt(bool &caused_stop)
+{
+    Error error;
+
+    if (IsStopped())
+    {
+        caused_stop = false;
+    }
+    else if (kill(GetID(), SIGSTOP))
+    {
+        caused_stop = false;
+        error.SetErrorToErrno();
+    }
+    else
+    {
+        caused_stop = true;
+    }
+    return error;
+}
+
+Error
+ProcessPOSIX::DoDetach(bool keep_stopped)
+{
+    Error error;
+    if (keep_stopped)
+    {
+        // FIXME: If you want to implement keep_stopped,
+        // this would be the place to do it.
+        error.SetErrorString("Detaching with keep_stopped true is not currently supported on this platform.");
+        return error;
+    }
+
+    Mutex::Locker 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());
+        error = m_monitor->Detach(thread->GetID());
+    }
+
+    if (error.Success())
+        SetPrivateState(eStateDetached);
+
+    return error;
+}
+
+Error
+ProcessPOSIX::DoSignal(int signal)
+{
+    Error error;
+
+    if (kill(GetID(), signal))
+        error.SetErrorToErrno();
+
+    return error;
+}
+
+Error
+ProcessPOSIX::DoDestroy()
+{
+    Error error;
+
+    if (!HasExited())
+    {
+        // Drive the exit event to completion (do not keep the inferior in
+        // limbo).
+        m_exit_now = true;
+
+        if ((m_monitor == NULL || kill(m_monitor->GetPID(), SIGKILL)) && error.Success())
+        {
+            error.SetErrorToErrno();
+            return error;
+        }
+
+        SetPrivateState(eStateExited);
+    }
+
+    return error;
+}
+
+void
+ProcessPOSIX::SendMessage(const ProcessMessage &message)
+{
+    Mutex::Locker lock(m_message_mutex);
+
+    Mutex::Locker thread_lock(m_thread_list.GetMutex());
+
+    POSIXThread *thread = static_cast<POSIXThread*>(
+        m_thread_list.FindThreadByID(message.GetTID(), false).get());
+
+    switch (message.GetKind())
+    {
+    case ProcessMessage::eInvalidMessage:
+        return;
+
+    case ProcessMessage::eLimboMessage:
+        assert(thread);
+        thread->SetState(eStateStopped);
+        if (message.GetTID() == GetID())
+        {
+            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:
+        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);
+        }
+        else if (!IsAThreadRunning())
+            SetPrivateState(eStateStopped);
+        break;
+
+    case ProcessMessage::eSignalMessage:
+    case ProcessMessage::eSignalDeliveredMessage:
+        if (message.GetSignal() == SIGSTOP &&
+            AddThreadForInitialStopIfNeeded(message.GetTID()))
+            return;
+        // Intentional fall-through
+
+    case ProcessMessage::eBreakpointMessage:
+    case ProcessMessage::eTraceMessage:
+    case ProcessMessage::eWatchpointMessage:
+    case ProcessMessage::eNewThreadMessage:
+    case ProcessMessage::eCrashMessage:
+        assert(thread);
+        thread->SetState(eStateStopped);
+        StopAllThreads(message.GetTID());
+        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?
+}
+
+bool
+ProcessPOSIX::AddThreadForInitialStopIfNeeded(lldb::tid_t stop_tid)
+{
+    bool added_to_set = false;
+    ThreadStopSet::iterator it = m_seen_initial_stop.find(stop_tid);
+    if (it == m_seen_initial_stop.end())
+    {
+        m_seen_initial_stop.insert(stop_tid);
+        added_to_set = true;
+    }
+    return added_to_set;
+}
+
+POSIXThread *
+ProcessPOSIX::CreateNewPOSIXThread(lldb_private::Process &process, lldb::tid_t tid)
+{
+    return new POSIXThread(process, tid);
+}
+
+void
+ProcessPOSIX::RefreshStateAfterStop()
+{
+    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
+    if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
+        log->Printf ("ProcessPOSIX::%s(), message_queue size = %d", __FUNCTION__, (int)m_message_queue.size());
+
+    Mutex::Locker lock(m_message_mutex);
+
+    // 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.
+        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)
+        {
+            if (log)
+                log->Printf ("ProcessPOSIX::%s() adding thread, tid = %" PRIi64, __FUNCTION__, message.GetChildTID());
+            lldb::tid_t child_tid = message.GetChildTID();
+            ThreadSP thread_sp;
+            thread_sp.reset(CreateNewPOSIXThread(*this, child_tid));
+
+            Mutex::Locker lock(m_thread_list.GetMutex());
+
+            m_thread_list.AddThread(thread_sp);
+        }
+
+        m_thread_list.RefreshStateAfterStop();
+
+        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);
+
+            Mutex::Locker lock(m_thread_list.GetMutex());
+
+            ThreadSP thread_sp = m_thread_list.RemoveThreadByID(tid, false);
+            thread_sp.reset();
+            m_seen_initial_stop.erase(tid);
+        }
+
+        m_message_queue.pop();
+    }
+}
+
+bool
+ProcessPOSIX::IsAlive()
+{
+    StateType state = GetPrivateState();
+    return state != eStateDetached
+        && state != eStateExited
+        && state != eStateInvalid
+        && state != eStateUnloaded;
+}
+
+size_t
+ProcessPOSIX::DoReadMemory(addr_t vm_addr,
+                           void *buf, size_t size, Error &error)
+{
+    assert(m_monitor);
+    return m_monitor->ReadMemory(vm_addr, buf, size, error);
+}
+
+size_t
+ProcessPOSIX::DoWriteMemory(addr_t vm_addr, const void *buf, size_t size,
+                            Error &error)
+{
+    assert(m_monitor);
+    return m_monitor->WriteMemory(vm_addr, buf, size, error);
+}
+
+addr_t
+ProcessPOSIX::DoAllocateMemory(size_t size, uint32_t permissions,
+                               Error &error)
+{
+    addr_t allocated_addr = LLDB_INVALID_ADDRESS;
+
+    unsigned prot = 0;
+    if (permissions & lldb::ePermissionsReadable)
+        prot |= eMmapProtRead;
+    if (permissions & lldb::ePermissionsWritable)
+        prot |= eMmapProtWrite;
+    if (permissions & lldb::ePermissionsExecutable)
+        prot |= eMmapProtExec;
+
+    if (InferiorCallMmap(this, allocated_addr, 0, size, prot,
+                         eMmapFlagsAnon | eMmapFlagsPrivate, -1, 0)) {
+        m_addr_to_mmap_size[allocated_addr] = size;
+        error.Clear();
+    } else {
+        allocated_addr = LLDB_INVALID_ADDRESS;
+        error.SetErrorStringWithFormat("unable to allocate %zu bytes of memory with permissions %s", size, GetPermissionsAsCString (permissions));
+    }
+
+    return allocated_addr;
+}
+
+Error
+ProcessPOSIX::DoDeallocateMemory(lldb::addr_t addr)
+{
+    Error error;
+    MMapMap::iterator pos = m_addr_to_mmap_size.find(addr);
+    if (pos != m_addr_to_mmap_size.end() &&
+        InferiorCallMunmap(this, addr, pos->second))
+        m_addr_to_mmap_size.erase (pos);
+    else
+        error.SetErrorStringWithFormat("unable to deallocate memory at 0x%" PRIx64, addr);
+
+    return error;
+}
+
+addr_t
+ProcessPOSIX::ResolveIndirectFunction(const Address *address, Error &error)
+{
+    addr_t function_addr = LLDB_INVALID_ADDRESS;
+    if (address == NULL) {
+        error.SetErrorStringWithFormat("unable to determine direct function call for NULL address");
+    } else if (!InferiorCall(this, address, function_addr)) {
+        function_addr = LLDB_INVALID_ADDRESS;
+        error.SetErrorStringWithFormat("unable to determine direct function call for indirect function %s",
+                                       address->CalculateSymbolContextSymbol()->GetName().AsCString());
+    }
+    return function_addr;
+}
+
+size_t
+ProcessPOSIX::GetSoftwareBreakpointTrapOpcode(BreakpointSite* bp_site)
+{
+    static const uint8_t g_i386_opcode[] = { 0xCC };
+
+    ArchSpec arch = GetTarget().GetArchitecture();
+    const uint8_t *opcode = NULL;
+    size_t opcode_size = 0;
+
+    switch (arch.GetCore())
+    {
+    default:
+        assert(false && "CPU type not supported!");
+        break;
+
+    case ArchSpec::eCore_x86_32_i386:
+    case ArchSpec::eCore_x86_64_x86_64:
+        opcode = g_i386_opcode;
+        opcode_size = sizeof(g_i386_opcode);
+        break;
+    }
+
+    bp_site->SetTrapOpcode(opcode, opcode_size);
+    return opcode_size;
+}
+
+Error
+ProcessPOSIX::EnableBreakpointSite(BreakpointSite *bp_site)
+{
+    return EnableSoftwareBreakpoint(bp_site);
+}
+
+Error
+ProcessPOSIX::DisableBreakpointSite(BreakpointSite *bp_site)
+{
+    return DisableSoftwareBreakpoint(bp_site);
+}
+
+Error
+ProcessPOSIX::EnableWatchpoint(Watchpoint *wp, bool notify)
+{
+    Error error;
+    if (wp)
+    {
+        user_id_t watchID = wp->GetID();
+        addr_t addr = wp->GetLoadAddress();
+        Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
+        if (log)
+            log->Printf ("ProcessPOSIX::EnableWatchpoint(watchID = %" PRIu64 ")",
+                         watchID);
+        if (wp->IsEnabled())
+        {
+            if (log)
+                log->Printf("ProcessPOSIX::EnableWatchpoint(watchID = %" PRIu64
+                            ") addr = 0x%8.8" PRIx64 ": watchpoint already enabled.",
+                            watchID, (uint64_t)addr);
+            return error;
+        }
+
+        // Try to find a vacant watchpoint slot in the inferiors' main thread
+        uint32_t wp_hw_index = LLDB_INVALID_INDEX32;
+        Mutex::Locker lock(m_thread_list.GetMutex());
+        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)
+        {
+            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
+            {
+                // 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.");
+    return error;
+}
+
+Error
+ProcessPOSIX::DisableWatchpoint(Watchpoint *wp, bool notify)
+{
+    Error error;
+    if (wp)
+    {
+        user_id_t watchID = wp->GetID();
+        addr_t addr = wp->GetLoadAddress();
+        Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_WATCHPOINTS));
+        if (log)
+            log->Printf("ProcessPOSIX::DisableWatchpoint(watchID = %" PRIu64 ")",
+                        watchID);
+        if (!wp->IsEnabled())
+        {
+            if (log)
+                log->Printf("ProcessPOSIX::DisableWatchpoint(watchID = %" PRIu64
+                            ") addr = 0x%8.8" PRIx64 ": watchpoint already disabled.",
+                            watchID, (uint64_t)addr);
+            // This is needed (for now) to keep watchpoints disabled correctly
+            wp->SetEnabled(false, notify);
+            return error;
+        }
+
+        if (wp->IsHardware())
+        {
+            bool wp_disabled = true;
+            Mutex::Locker 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());
+                if (thread)
+                    wp_disabled &= thread->DisableHardwareWatchpoint(wp);
+                else
+                    wp_disabled = false;
+            }
+            if (wp_disabled)
+            {
+                wp->SetHardwareIndex(LLDB_INVALID_INDEX32);
+                wp->SetEnabled(false, notify);
+                return error;
+            }
+            else
+                error.SetErrorString("Disabling hardware watchpoint failed");
+        }
+    }
+    else
+        error.SetErrorString("Watchpoint argument was NULL.");
+    return error;
+}
+
+Error
+ProcessPOSIX::GetWatchpointSupportInfo(uint32_t &num)
+{
+    Error error;
+    Mutex::Locker lock(m_thread_list.GetMutex());
+    POSIXThread *thread = static_cast<POSIXThread*>(
+                          m_thread_list.GetThreadAtIndex(0, false).get());
+    if (thread)
+        num = thread->NumSupportedHardwareWatchpoints();
+    else
+        error.SetErrorString("Process does not exist.");
+    return error;
+}
+
+Error
+ProcessPOSIX::GetWatchpointSupportInfo(uint32_t &num, bool &after)
+{
+    Error error = GetWatchpointSupportInfo(num);
+    // Watchpoints trigger and halt the inferior after
+    // the corresponding instruction has been executed.
+    after = true;
+    return error;
+}
+
+uint32_t
+ProcessPOSIX::UpdateThreadListIfNeeded()
+{
+    Mutex::Locker lock(m_thread_list.GetMutex());
+    // Do not allow recursive updates.
+    return m_thread_list.GetSize(false);
+}
+
+bool
+ProcessPOSIX::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list)
+{
+    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
+    if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
+        log->Printf ("ProcessPOSIX::%s() (pid = %" PRIi64 ")", __FUNCTION__, GetID());
+
+    // Update the process thread list with this new thread.
+    // FIXME: We should be using tid, not pid.
+    assert(m_monitor);
+    ThreadSP thread_sp (old_thread_list.FindThreadByID (GetID(), false));
+    if (!thread_sp) {
+        thread_sp.reset(CreateNewPOSIXThread(*this, GetID()));
+    }
+
+    if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
+        log->Printf ("ProcessPOSIX::%s() updated pid = %" PRIi64, __FUNCTION__, GetID());
+    new_thread_list.AddThread(thread_sp);
+
+    return new_thread_list.GetSize(false) > 0;
+}
+
+ByteOrder
+ProcessPOSIX::GetByteOrder() const
+{
+    // FIXME: We should be able to extract this value directly.  See comment in
+    // ProcessPOSIX().
+    return m_byte_order;
+}
+
+size_t
+ProcessPOSIX::PutSTDIN(const char *buf, size_t len, Error &error)
+{
+    ssize_t status;
+    if ((status = write(m_monitor->GetTerminalFD(), buf, len)) < 0) 
+    {
+        error.SetErrorToErrno();
+        return 0;
+    }
+    return status;
+}
+
+UnixSignals &
+ProcessPOSIX::GetUnixSignals()
+{
+    return m_signals;
+}
+
+//------------------------------------------------------------------------------
+// Utility functions.
+
+bool
+ProcessPOSIX::HasExited()
+{
+    switch (GetPrivateState())
+    {
+    default:
+        break;
+
+    case eStateDetached:
+    case eStateExited:
+        return true;
+    }
+
+    return false;
+}
+
+bool
+ProcessPOSIX::IsStopped()
+{
+    switch (GetPrivateState())
+    {
+    default:
+        break;
+
+    case eStateStopped:
+    case eStateCrashed:
+    case eStateSuspended:
+        return true;
+    }
+
+    return false;
+}
+
+bool
+ProcessPOSIX::IsAThreadRunning()
+{
+    bool is_running = false;
+    Mutex::Locker 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());
+        StateType thread_state = thread->GetState();
+        if (thread_state == eStateRunning || thread_state == eStateStepping)
+        {
+            is_running = true;
+            break;
+        }
+    }
+    return is_running;
+}
diff --git a/source/Plugins/Process/POSIX/ProcessPOSIX.h b/source/Plugins/Process/POSIX/ProcessPOSIX.h
new file mode 100644
index 000000000000..48b19bac47e7
--- /dev/null
+++ b/source/Plugins/Process/POSIX/ProcessPOSIX.h
@@ -0,0 +1,211 @@
+//===-- ProcessPOSIX.h ------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ProcessPOSIX_H_
+#define liblldb_ProcessPOSIX_H_
+
+// C Includes
+
+// C++ Includes
+#include <queue>
+#include <set>
+
+// Other libraries and framework includes
+#include "lldb/Target/Process.h"
+#include "lldb/Target/UnixSignals.h"
+#include "ProcessMessage.h"
+
+class ProcessMonitor;
+class POSIXThread;
+
+class ProcessPOSIX :
+    public lldb_private::Process
+{
+public:
+
+    //------------------------------------------------------------------
+    // Constructors and destructors
+    //------------------------------------------------------------------
+    ProcessPOSIX(lldb_private::Target& target,
+                 lldb_private::Listener &listener);
+
+    virtual
+    ~ProcessPOSIX();
+
+    //------------------------------------------------------------------
+    // Process protocol.
+    //------------------------------------------------------------------
+    virtual void
+    Finalize();
+
+    virtual bool
+    CanDebug(lldb_private::Target &target, bool plugin_specified_by_name);
+
+    virtual lldb_private::Error
+    WillLaunch(lldb_private::Module *module);
+
+    virtual lldb_private::Error
+    DoAttachToProcessWithID(lldb::pid_t pid);
+
+    virtual lldb_private::Error
+    DoAttachToProcessWithID (lldb::pid_t pid, const lldb_private::ProcessAttachInfo &attach_info);
+
+    virtual lldb_private::Error
+    DoLaunch (lldb_private::Module *exe_module, 
+              const lldb_private::ProcessLaunchInfo &launch_info);
+
+    virtual void
+    DidLaunch();
+
+    virtual lldb_private::Error
+    DoResume();
+
+    virtual lldb_private::Error
+    DoHalt(bool &caused_stop);
+
+    virtual lldb_private::Error
+    DoDetach(bool keep_stopped);
+
+    virtual lldb_private::Error
+    DoSignal(int signal);
+
+    virtual lldb_private::Error
+    DoDestroy();
+
+    virtual void
+    RefreshStateAfterStop();
+
+    virtual bool
+    IsAlive();
+
+    virtual size_t
+    DoReadMemory(lldb::addr_t vm_addr,
+                 void *buf,
+                 size_t size,
+                 lldb_private::Error &error);
+
+    virtual size_t
+    DoWriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size,
+                  lldb_private::Error &error);
+
+    virtual lldb::addr_t
+    DoAllocateMemory(size_t size, uint32_t permissions,
+                     lldb_private::Error &error);
+
+    virtual lldb_private::Error
+    DoDeallocateMemory(lldb::addr_t ptr);
+
+    virtual lldb::addr_t
+    ResolveIndirectFunction(const lldb_private::Address *address, lldb_private::Error &error);
+
+    virtual size_t
+    GetSoftwareBreakpointTrapOpcode(lldb_private::BreakpointSite* bp_site);
+
+    virtual lldb_private::Error
+    EnableBreakpointSite(lldb_private::BreakpointSite *bp_site);
+
+    virtual lldb_private::Error
+    DisableBreakpointSite(lldb_private::BreakpointSite *bp_site);
+
+    virtual lldb_private::Error
+    EnableWatchpoint(lldb_private::Watchpoint *wp, bool notify = true);
+
+    virtual lldb_private::Error
+    DisableWatchpoint(lldb_private::Watchpoint *wp, bool notify = true);
+
+    virtual lldb_private::Error
+    GetWatchpointSupportInfo(uint32_t &num);
+
+    virtual lldb_private::Error
+    GetWatchpointSupportInfo(uint32_t &num, bool &after);
+
+    virtual uint32_t
+    UpdateThreadListIfNeeded();
+
+    virtual bool
+    UpdateThreadList(lldb_private::ThreadList &old_thread_list, 
+                     lldb_private::ThreadList &new_thread_list) = 0;
+
+    virtual lldb::ByteOrder
+    GetByteOrder() const;
+
+    virtual lldb::addr_t
+    GetImageInfoAddress();
+
+    virtual size_t
+    PutSTDIN(const char *buf, size_t len, lldb_private::Error &error);
+
+    //--------------------------------------------------------------------------
+    // ProcessPOSIX internal API.
+
+    /// Registers the given message with this process.
+    void SendMessage(const ProcessMessage &message);
+
+    ProcessMonitor &
+    GetMonitor() { assert(m_monitor); return *m_monitor; }
+
+    lldb_private::UnixSignals &
+    GetUnixSignals();
+
+    const char *
+    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);
+
+    /// Adds the thread to the list of threads for which we have received the initial stopping signal.
+    /// The \p stop_tid paramter indicates the thread which the stop happened for.
+    bool
+    AddThreadForInitialStopIfNeeded(lldb::tid_t stop_tid);
+
+    virtual POSIXThread *
+    CreateNewPOSIXThread(lldb_private::Process &process, lldb::tid_t tid);
+
+protected:
+    /// Target byte order.
+    lldb::ByteOrder m_byte_order;
+
+    /// Process monitor;
+    ProcessMonitor *m_monitor;
+
+    /// The module we are executing.
+    lldb_private::Module *m_module;
+
+    /// Message queue notifying this instance of inferior process state changes.
+    lldb_private::Mutex m_message_mutex;
+    std::queue<ProcessMessage> m_message_queue;
+
+    /// Drive any exit events to completion.
+    bool m_exit_now;
+
+    /// OS-specific signal set.
+    lldb_private::UnixSignals m_signals;
+
+    /// Returns true if the process has exited.
+    bool HasExited();
+
+    /// Returns true if the process is stopped.
+    bool IsStopped();
+
+    /// Returns true if at least one running is currently running
+    bool IsAThreadRunning();
+
+    typedef std::map<lldb::addr_t, lldb::addr_t> MMapMap;
+    MMapMap m_addr_to_mmap_size;
+
+    typedef std::set<lldb::tid_t> ThreadStopSet;
+    /// Every thread begins with a stop signal. This keeps track
+    /// of the threads for which we have received the stop signal.
+    ThreadStopSet m_seen_initial_stop;
+};
+
+#endif  // liblldb_MacOSXProcess_H_
diff --git a/source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp b/source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp
new file mode 100644
index 000000000000..624ca87b883a
--- /dev/null
+++ b/source/Plugins/Process/POSIX/ProcessPOSIXLog.cpp
@@ -0,0 +1,193 @@
+//===-- ProcessPOSIXLog.cpp ---------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ProcessPOSIXLog.h"
+
+#include "lldb/Interpreter/Args.h"
+#include "lldb/Core/StreamFile.h"
+
+#include "ProcessPOSIX.h"
+#include "ProcessPOSIXLog.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+// We want to avoid global constructors where code needs to be run so here we
+// control access to our static g_log_sp by hiding it in a singleton function
+// that will construct the static g_log_sp the first time this function is 
+// called.
+static bool g_log_enabled = false;
+static Log * g_log = NULL;
+static Log *
+GetLog ()
+{
+    if (!g_log_enabled)
+        return NULL;
+    return g_log;
+}
+
+
+Log *
+ProcessPOSIXLog::GetLogIfAllCategoriesSet (uint32_t mask)
+{
+    Log *log(GetLog ());
+    if (log && mask)
+    {
+        uint32_t log_mask = log->GetMask().Get();
+        if ((log_mask & mask) != mask)
+            return NULL;
+    }
+    return log;
+}
+
+static uint32_t
+GetFlagBits (const char *arg)
+{
+    if      (::strcasecmp (arg, "all")        == 0 ) return POSIX_LOG_ALL;
+    else if (::strcasecmp (arg, "async")      == 0 ) return POSIX_LOG_ASYNC;
+    else if (::strncasecmp (arg, "break", 5)  == 0 ) return POSIX_LOG_BREAKPOINTS;
+    else if (::strncasecmp (arg, "comm", 4)   == 0 ) return POSIX_LOG_COMM;
+    else if (::strcasecmp (arg, "default")    == 0 ) return POSIX_LOG_DEFAULT;
+    else if (::strcasecmp (arg, "packets")    == 0 ) return POSIX_LOG_PACKETS;
+    else if (::strcasecmp (arg, "memory")     == 0 ) return POSIX_LOG_MEMORY;
+    else if (::strcasecmp (arg, "data-short") == 0 ) return POSIX_LOG_MEMORY_DATA_SHORT;
+    else if (::strcasecmp (arg, "data-long")  == 0 ) return POSIX_LOG_MEMORY_DATA_LONG;
+    else if (::strcasecmp (arg, "process")    == 0 ) return POSIX_LOG_PROCESS;
+    else if (::strcasecmp (arg, "ptrace")     == 0 ) return POSIX_LOG_PTRACE;
+    else if (::strcasecmp (arg, "registers")  == 0 ) return POSIX_LOG_REGISTERS;
+    else if (::strcasecmp (arg, "step")       == 0 ) return POSIX_LOG_STEP;
+    else if (::strcasecmp (arg, "thread")     == 0 ) return POSIX_LOG_THREAD;
+    else if (::strcasecmp (arg, "verbose")    == 0 ) return POSIX_LOG_VERBOSE;
+    else if (::strncasecmp (arg, "watch", 5)  == 0 ) return POSIX_LOG_WATCHPOINTS;
+    return 0;
+}
+
+void
+ProcessPOSIXLog::DisableLog (const char **args, Stream *feedback_strm)
+{
+    Log *log (GetLog ());
+    if (log)
+    {
+        uint32_t flag_bits = 0;
+        
+        flag_bits = log->GetMask().Get();
+        for (; args[0]; args++)
+        {
+            const char *arg = args[0];
+            uint32_t bits = GetFlagBits(arg);
+
+            if (bits)
+            {
+                flag_bits &= ~bits;
+            }
+            else
+            {
+                feedback_strm->Printf("error: unrecognized log category '%s'\n", arg);
+                ListLogCategories (feedback_strm);
+            }
+        }
+        
+        log->GetMask().Reset (flag_bits);
+        if (flag_bits == 0)
+            g_log_enabled = false;
+    }
+    
+    return;
+}
+
+Log *
+ProcessPOSIXLog::EnableLog (StreamSP &log_stream_sp, uint32_t log_options, const char **args, Stream *feedback_strm)
+{
+    // Try see if there already is a log - that way we can reuse its settings.
+    // We could reuse the log in toto, but we don't know that the stream is the same.
+    uint32_t flag_bits = 0;
+    if (g_log)
+        flag_bits = g_log->GetMask().Get();
+
+    // Now make a new log with this stream if one was provided
+    if (log_stream_sp)
+    {
+        if (g_log)
+            g_log->SetStream(log_stream_sp);
+        else
+            g_log = new Log(log_stream_sp);
+    }
+
+    if (g_log)
+    {
+        bool got_unknown_category = false;
+        for (; args[0]; args++)
+        {
+            const char *arg = args[0];
+            uint32_t bits = GetFlagBits(arg);
+
+            if (bits)
+            {
+                flag_bits |= bits;
+            }
+            else
+            {
+                feedback_strm->Printf("error: unrecognized log category '%s'\n", arg);
+                if (got_unknown_category == false)
+                {
+                    got_unknown_category = true;
+                    ListLogCategories (feedback_strm);
+                }
+            }
+        }
+        if (flag_bits == 0)
+            flag_bits = POSIX_LOG_DEFAULT;
+        g_log->GetMask().Reset(flag_bits);
+        g_log->GetOptions().Reset(log_options);
+        g_log_enabled = true;
+    }
+    return g_log;
+}
+
+void
+ProcessPOSIXLog::ListLogCategories (Stream *strm)
+{
+    strm->Printf ("Logging categories for '%s':\n"
+                  "  all - turn on all available logging categories\n"
+                  "  async - log asynchronous activity\n"
+                  "  break - log breakpoints\n"
+                  "  communication - log communication activity\n"
+                  "  default - enable the default set of logging categories for liblldb\n"
+                  "  packets - log gdb remote packets\n"
+                  "  memory - log memory reads and writes\n"
+                  "  data-short - log memory bytes for memory reads and writes for short transactions only\n"
+                  "  data-long - log memory bytes for memory reads and writes for all transactions\n"
+                  "  process - log process events and activities\n"
+#ifndef LLDB_CONFIGURATION_BUILDANDINTEGRATION
+                  "  ptrace - log all calls to ptrace\n"
+#endif
+                  "  registers - log register read/writes\n"
+                  "  thread - log thread events and activities\n"
+                  "  step - log step related activities\n"
+                  "  verbose - enable verbose logging\n"
+                  "  watch - log watchpoint related activities\n", ProcessPOSIXLog::m_pluginname);
+}
+
+
+void
+ProcessPOSIXLog::LogIf (uint32_t mask, const char *format, ...)
+{
+    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (mask));
+    if (log)
+    {
+        va_list args;
+        va_start (args, format);
+        log->VAPrintf (format, args);
+        va_end (args);
+    }
+}
+
+int ProcessPOSIXLog::m_nestinglevel;
+const char *ProcessPOSIXLog::m_pluginname = "";
diff --git a/source/Plugins/Process/POSIX/ProcessPOSIXLog.h b/source/Plugins/Process/POSIX/ProcessPOSIXLog.h
new file mode 100644
index 000000000000..a1e2e3747d21
--- /dev/null
+++ b/source/Plugins/Process/POSIX/ProcessPOSIXLog.h
@@ -0,0 +1,111 @@
+//===-- ProcessPOSIXLog.h -----------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ProcessPOSIXLog_h_
+#define liblldb_ProcessPOSIXLog_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+
+// Project includes
+#include "lldb/Core/Log.h"
+
+#define POSIX_LOG_VERBOSE                  (1u << 0)
+#define POSIX_LOG_PROCESS                  (1u << 1)
+#define POSIX_LOG_THREAD                   (1u << 2)
+#define POSIX_LOG_PACKETS                  (1u << 3)
+#define POSIX_LOG_MEMORY                   (1u << 4)    // Log memory reads/writes calls
+#define POSIX_LOG_MEMORY_DATA_SHORT        (1u << 5)    // Log short memory reads/writes bytes
+#define POSIX_LOG_MEMORY_DATA_LONG         (1u << 6)    // Log all memory reads/writes bytes
+#define POSIX_LOG_BREAKPOINTS              (1u << 7)
+#define POSIX_LOG_WATCHPOINTS              (1u << 8)
+#define POSIX_LOG_STEP                     (1u << 9)
+#define POSIX_LOG_COMM                     (1u << 10)
+#define POSIX_LOG_ASYNC                    (1u << 11)
+#define POSIX_LOG_PTRACE                   (1u << 12)
+#define POSIX_LOG_REGISTERS                (1u << 13)
+#define POSIX_LOG_ALL                      (UINT32_MAX)
+#define POSIX_LOG_DEFAULT                  POSIX_LOG_PACKETS
+
+// The size which determines "short memory reads/writes".
+#define POSIX_LOG_MEMORY_SHORT_BYTES       (4 * sizeof(ptrdiff_t))
+
+class ProcessPOSIXLog
+{
+    static int m_nestinglevel;
+    static const char *m_pluginname;
+
+public:
+    static void
+    RegisterPluginName(const char *pluginName)
+    {
+        m_pluginname = pluginName;
+    }
+
+    static void
+    RegisterPluginName(lldb_private::ConstString pluginName)
+        {
+            m_pluginname = pluginName.GetCString();
+        }
+
+    static lldb_private::Log *
+    GetLogIfAllCategoriesSet(uint32_t mask = 0);
+
+    static void
+    DisableLog (const char **args, lldb_private::Stream *feedback_strm);
+
+    static lldb_private::Log *
+    EnableLog (lldb::StreamSP &log_stream_sp, uint32_t log_options,
+               const char **args, lldb_private::Stream *feedback_strm);
+
+    static void
+    ListLogCategories (lldb_private::Stream *strm);
+
+    static void
+    LogIf (uint32_t mask, const char *format, ...);
+
+    // The following functions can be used to enable the client to limit
+    // logging to only the top level function calls.  This is useful for
+    // recursive functions.  FIXME: not thread safe!
+    //     Example:
+    //     void NestingFunc() {
+    //         LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_ALL));
+    //         if (log)
+    //         {
+    //             ProcessPOSIXLog::IncNestLevel();
+    //             if (ProcessPOSIXLog::AtTopNestLevel())
+    //                 log->Print(msg);
+    //         }
+    //         NestingFunc();
+    //         if (log)
+    //             ProcessPOSIXLog::DecNestLevel();
+    //     }
+
+    static bool
+    AtTopNestLevel()
+    {
+        return m_nestinglevel == 1;
+    }
+
+    static void
+    IncNestLevel()
+    {
+        ++m_nestinglevel;
+    }
+
+    static void
+    DecNestLevel()
+    {
+        --m_nestinglevel;
+        assert(m_nestinglevel >= 0);
+    }
+};
+
+#endif  // liblldb_ProcessPOSIXLog_h_
diff --git a/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.cpp b/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.cpp
new file mode 100644
index 000000000000..0fb9dc1cb3dc
--- /dev/null
+++ b/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.cpp
@@ -0,0 +1,136 @@
+//===-- RegisterContextFreeBSD_x86_64.h ------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+
+#include "RegisterContextFreeBSD_x86_64.h"
+#include <vector>
+
+using namespace lldb_private;
+
+// Computes the offset of the given GPR in the user data area.
+#define GPR_OFFSET(regname)                                                 \
+    (offsetof(GPR, regname))
+
+// Update the FreeBSD specific information (offset and size).
+#define UPDATE_GPR_INFO(reg)                                                \
+do {                                                                        \
+    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 {                                                                        \
+    GetRegisterContext()[gpr_##i386_reg].byte_offset = GPR_OFFSET(reg);         \
+} while(false);
+
+typedef struct _GPR
+{
+    uint64_t r15;
+    uint64_t r14;
+    uint64_t r13;
+    uint64_t r12;
+    uint64_t r11;
+    uint64_t r10;
+    uint64_t r9;
+    uint64_t r8;
+    uint64_t rdi;
+    uint64_t rsi;
+    uint64_t rbp;
+    uint64_t rbx;
+    uint64_t rdx;
+    uint64_t rcx;
+    uint64_t rax;
+    uint32_t trapno;
+    uint16_t fs;
+    uint16_t gs;
+    uint32_t err;
+    uint16_t es;
+    uint16_t ds;
+    uint64_t rip;
+    uint64_t cs;
+    uint64_t rflags;
+    uint64_t rsp;
+    uint64_t ss;
+} GPR;
+
+// 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)
+{
+}
+
+size_t
+RegisterContextFreeBSD_x86_64::GetGPRSize()
+{
+    return sizeof(GPR);
+}
+
+const RegisterInfo *
+RegisterContextFreeBSD_x86_64::GetRegisterInfo()
+{
+    // Allocate RegisterInfo only once
+    if (GetRegisterContext().empty())
+    {
+        // Copy the register information from base class
+        const RegisterInfo *base_info = RegisterContext_x86_64::GetRegisterInfo();
+        if (base_info)
+        {
+            GetRegisterContext().insert(GetRegisterContext().end(), &base_info[0], &base_info[k_num_registers]);
+            // Update the FreeBSD specific register information (offset and size).
+            UpdateRegisterInfo();
+        }
+    }
+    return &GetRegisterContext()[0];
+}
+
+void
+RegisterContextFreeBSD_x86_64::UpdateRegisterInfo()
+{
+    UPDATE_GPR_INFO(rax);
+    UPDATE_GPR_INFO(rbx);
+    UPDATE_GPR_INFO(rcx);
+    UPDATE_GPR_INFO(rdx);
+    UPDATE_GPR_INFO(rdi);
+    UPDATE_GPR_INFO(rsi);
+    UPDATE_GPR_INFO(rbp);
+    UPDATE_GPR_INFO(rsp);
+    UPDATE_GPR_INFO(r8);
+    UPDATE_GPR_INFO(r9);
+    UPDATE_GPR_INFO(r10);
+    UPDATE_GPR_INFO(r11);
+    UPDATE_GPR_INFO(r12);
+    UPDATE_GPR_INFO(r13);
+    UPDATE_GPR_INFO(r14);
+    UPDATE_GPR_INFO(r15);
+    UPDATE_GPR_INFO(rip);
+    UPDATE_GPR_INFO(rflags);
+    UPDATE_GPR_INFO(cs);
+    UPDATE_GPR_INFO(fs);
+    UPDATE_GPR_INFO(gs);
+    UPDATE_GPR_INFO(ss);
+    UPDATE_GPR_INFO(ds);
+    UPDATE_GPR_INFO(es);
+
+    UPDATE_I386_GPR_INFO(eax, rax);
+    UPDATE_I386_GPR_INFO(ebx, rbx);
+    UPDATE_I386_GPR_INFO(ecx, rcx);
+    UPDATE_I386_GPR_INFO(edx, rdx);
+    UPDATE_I386_GPR_INFO(edi, rdi);
+    UPDATE_I386_GPR_INFO(esi, rsi);
+    UPDATE_I386_GPR_INFO(ebp, rbp);
+    UPDATE_I386_GPR_INFO(esp, rsp);
+    UPDATE_I386_GPR_INFO(eip, rip);
+    UPDATE_I386_GPR_INFO(eflags, rflags);
+}
+
diff --git a/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.h b/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.h
new file mode 100644
index 000000000000..ffff40a9c65b
--- /dev/null
+++ b/source/Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.h
@@ -0,0 +1,32 @@
+//===-- RegisterContextFreeBSD_x86_64.h ---------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_RegisterContextFreeBSD_x86_64_H_
+#define liblldb_RegisterContextFreeBSD_x86_64_H_
+
+#include "Plugins/Process/POSIX/RegisterContext_x86_64.h"
+
+class RegisterContextFreeBSD_x86_64:
+    public RegisterContext_x86_64
+{
+public:
+    RegisterContextFreeBSD_x86_64(lldb_private::Thread &thread, uint32_t concrete_frame_idx);
+
+    size_t
+    GetGPRSize();
+
+protected:
+    virtual const lldb_private::RegisterInfo *
+    GetRegisterInfo();
+
+    virtual void
+    UpdateRegisterInfo();
+};
+
+#endif
diff --git a/source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.cpp b/source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.cpp
new file mode 100644
index 000000000000..c1aea2a41a1f
--- /dev/null
+++ b/source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.cpp
@@ -0,0 +1,180 @@
+//===-- RegisterContextLinux_x86_64.h --------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+
+#include "llvm/Support/Compiler.h"
+#include "RegisterContextLinux_x86_64.h"
+#include <vector>
+
+using namespace lldb_private;
+
+// Computes the offset of the given GPR in the user data area.
+#define GPR_OFFSET(regname)                                                 \
+    (offsetof(GPR, regname))
+
+// Update the Linux specific information (offset and size).
+#define UPDATE_GPR_INFO(reg)                                                \
+do {                                                                        \
+    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 {                                                                        \
+    GetRegisterContext()[gpr_##i386_reg].byte_offset = GPR_OFFSET(reg);         \
+} while(false);
+
+#define DR_OFFSET(reg_index)                                                \
+    (LLVM_EXTENSION offsetof(UserArea, u_debugreg[reg_index]))
+
+#define UPDATE_DR_INFO(reg_index)                                                \
+do {                                                                             \
+    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
+{
+    uint64_t r15;
+    uint64_t r14;
+    uint64_t r13;
+    uint64_t r12;
+    uint64_t rbp;
+    uint64_t rbx;
+    uint64_t r11;
+    uint64_t r10;
+    uint64_t r9;
+    uint64_t r8;
+    uint64_t rax;
+    uint64_t rcx;
+    uint64_t rdx;
+    uint64_t rsi;
+    uint64_t rdi;
+    uint64_t orig_ax;
+    uint64_t rip;
+    uint64_t cs;
+    uint64_t rflags;
+    uint64_t rsp;
+    uint64_t ss;
+    uint64_t fs_base;
+    uint64_t gs_base;
+    uint64_t ds;
+    uint64_t es;
+    uint64_t fs;
+    uint64_t gs;
+} GPR;
+
+typedef RegisterContext_x86_64::FXSAVE FXSAVE;
+
+struct UserArea
+{
+    GPR      gpr;           // General purpose registers.
+    int32_t  fpvalid;       // True if FPU is being used.
+    int32_t  pad0;
+    FXSAVE   i387;          // General purpose floating point registers (see FPR for extended register sets).
+    uint64_t tsize;         // Text segment size.
+    uint64_t dsize;         // Data segment size.
+    uint64_t ssize;         // Stack segment size.
+    uint64_t start_code;    // VM address of text.
+    uint64_t start_stack;   // VM address of stack bottom (top in rsp).
+    int64_t  signal;        // Signal causing core dump.
+    int32_t  reserved;      // Unused.
+    int32_t  pad1;
+    uint64_t ar0;           // Location of GPR's.
+    FXSAVE*  fpstate;       // Location of FPR's.
+    uint64_t magic;         // Identifier for core dumps.
+    char     u_comm[32];    // Command causing core dump.
+    uint64_t u_debugreg[8]; // Debug registers (DR0 - DR7).
+    uint64_t error_code;    // CPU error code.
+    uint64_t fault_address; // Control register CR3.
+};
+
+// 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)
+{
+}
+
+size_t
+RegisterContextLinux_x86_64::GetGPRSize()
+{
+    return sizeof(GPR);
+}
+
+const RegisterInfo *
+RegisterContextLinux_x86_64::GetRegisterInfo()
+{
+    // Allocate RegisterInfo only once
+    if (GetRegisterContext().empty())
+    {
+        // Copy the register information from base class
+        const RegisterInfo *base_info = RegisterContext_x86_64::GetRegisterInfo();
+        if (base_info)
+        {
+            GetRegisterContext().insert(GetRegisterContext().end(), &base_info[0], &base_info[k_num_registers]);
+            // Update the Linux specific register information (offset and size).
+            UpdateRegisterInfo();
+        }
+    }
+    return &GetRegisterContext()[0];
+}
+
+void
+RegisterContextLinux_x86_64::UpdateRegisterInfo()
+{
+    UPDATE_GPR_INFO(rax);
+    UPDATE_GPR_INFO(rbx);
+    UPDATE_GPR_INFO(rcx);
+    UPDATE_GPR_INFO(rdx);
+    UPDATE_GPR_INFO(rdi);
+    UPDATE_GPR_INFO(rsi);
+    UPDATE_GPR_INFO(rbp);
+    UPDATE_GPR_INFO(rsp);
+    UPDATE_GPR_INFO(r8);
+    UPDATE_GPR_INFO(r9);
+    UPDATE_GPR_INFO(r10);
+    UPDATE_GPR_INFO(r11);
+    UPDATE_GPR_INFO(r12);
+    UPDATE_GPR_INFO(r13);
+    UPDATE_GPR_INFO(r14);
+    UPDATE_GPR_INFO(r15);
+    UPDATE_GPR_INFO(rip);
+    UPDATE_GPR_INFO(rflags);
+    UPDATE_GPR_INFO(cs);
+    UPDATE_GPR_INFO(fs);
+    UPDATE_GPR_INFO(gs);
+    UPDATE_GPR_INFO(ss);
+    UPDATE_GPR_INFO(ds);
+    UPDATE_GPR_INFO(es);
+
+    UPDATE_I386_GPR_INFO(eax, rax);
+    UPDATE_I386_GPR_INFO(ebx, rbx);
+    UPDATE_I386_GPR_INFO(ecx, rcx);
+    UPDATE_I386_GPR_INFO(edx, rdx);
+    UPDATE_I386_GPR_INFO(edi, rdi);
+    UPDATE_I386_GPR_INFO(esi, rsi);
+    UPDATE_I386_GPR_INFO(ebp, rbp);
+    UPDATE_I386_GPR_INFO(esp, rsp);
+    UPDATE_I386_GPR_INFO(eip, rip);
+    UPDATE_I386_GPR_INFO(eflags, rflags);
+
+    UPDATE_DR_INFO(0);
+    UPDATE_DR_INFO(1);
+    UPDATE_DR_INFO(2);
+    UPDATE_DR_INFO(3);
+    UPDATE_DR_INFO(4);
+    UPDATE_DR_INFO(5);
+    UPDATE_DR_INFO(6);
+    UPDATE_DR_INFO(7);
+}
+
diff --git a/source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.h b/source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.h
new file mode 100644
index 000000000000..1509ef55b8dc
--- /dev/null
+++ b/source/Plugins/Process/POSIX/RegisterContextLinux_x86_64.h
@@ -0,0 +1,32 @@
+//===-- RegisterContextLinux_x86_64.h ---------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_RegisterContextLinux_x86_64_H_
+#define liblldb_RegisterContextLinux_x86_64_H_
+
+#include "Plugins/Process/POSIX/RegisterContext_x86_64.h"
+
+class RegisterContextLinux_x86_64:
+    public RegisterContext_x86_64
+{
+public:
+    RegisterContextLinux_x86_64(lldb_private::Thread &thread, uint32_t concrete_frame_idx);
+
+    size_t
+    GetGPRSize();
+
+protected:
+    virtual const lldb_private::RegisterInfo *
+    GetRegisterInfo();
+
+    virtual void
+    UpdateRegisterInfo();
+};
+
+#endif
diff --git a/source/Plugins/Process/POSIX/RegisterContextPOSIX.h b/source/Plugins/Process/POSIX/RegisterContextPOSIX.h
new file mode 100644
index 000000000000..63ae01e83a90
--- /dev/null
+++ b/source/Plugins/Process/POSIX/RegisterContextPOSIX.h
@@ -0,0 +1,70 @@
+//===-- RegisterContextPOSIX.h --------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_RegisterContextPOSIX_H_
+#define liblldb_RegisterContextPOSIX_H_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+#include "lldb/Target/RegisterContext.h"
+
+//------------------------------------------------------------------------------
+/// @class RegisterContextPOSIX
+///
+/// @brief Extends RegisterClass with a few virtual operations useful on POSIX.
+class RegisterContextPOSIX
+    : public lldb_private::RegisterContext
+{
+public:
+    RegisterContextPOSIX(lldb_private::Thread &thread,
+                         uint32_t 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
+    /// implementation simply returns true for architectures which do not
+    /// require any update.
+    ///
+    /// @return
+    ///    True if the operation succeeded and false otherwise.
+    virtual bool UpdateAfterBreakpoint() { return true; }
+
+    /// Determines the index in lldb's register file given a kernel byte offset.
+    virtual unsigned
+    GetRegisterIndexFromOffset(unsigned offset) { return LLDB_INVALID_REGNUM; }
+
+    // Checks to see if a watchpoint specified by hw_index caused the inferior
+    // to stop.
+    virtual bool
+    IsWatchpointHit (uint32_t hw_index) { return false; }
+
+    // Resets any watchpoints that have been hit.
+    virtual bool
+    ClearWatchpointHits () { return false; }
+
+    // Returns the watchpoint address associated with a watchpoint hardware
+    // index.
+    virtual lldb::addr_t
+    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_
diff --git a/source/Plugins/Process/POSIX/RegisterContext_i386.cpp b/source/Plugins/Process/POSIX/RegisterContext_i386.cpp
new file mode 100644
index 000000000000..49676bd3fc73
--- /dev/null
+++ b/source/Plugins/Process/POSIX/RegisterContext_i386.cpp
@@ -0,0 +1,551 @@
+//===-- RegisterContextPOSIX_i386.cpp ---------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Host/Endian.h"
+#include "llvm/Support/Compiler.h"
+
+#include "ProcessPOSIX.h"
+#include "ProcessPOSIXLog.h"
+#include "ProcessMonitor.h"
+#include "RegisterContext_i386.h"
+#include "RegisterContext_x86.h"
+
+using namespace lldb_private;
+using namespace lldb;
+
+enum
+{
+    k_first_gpr,
+    gpr_eax = k_first_gpr,
+    gpr_ebx,
+    gpr_ecx,
+    gpr_edx,
+    gpr_edi,
+    gpr_esi,
+    gpr_ebp,
+    gpr_esp,
+    gpr_ss,
+    gpr_eflags,
+#ifdef __FreeBSD__
+    gpr_orig_ax,
+#endif
+    gpr_eip,
+    gpr_cs,
+    gpr_ds,
+    gpr_es,
+    gpr_fs,
+    gpr_gs,
+    k_last_gpr = gpr_gs,
+
+    k_first_fpr,
+    fpu_fcw = k_first_fpr,
+    fpu_fsw,
+    fpu_ftw,
+    fpu_fop,
+    fpu_ip,
+    fpu_cs,
+    fpu_foo,
+    fpu_fos,
+    fpu_mxcsr,
+    fpu_stmm0,
+    fpu_stmm1,
+    fpu_stmm2,
+    fpu_stmm3,
+    fpu_stmm4,
+    fpu_stmm5,
+    fpu_stmm6,
+    fpu_stmm7,
+    fpu_xmm0,
+    fpu_xmm1,
+    fpu_xmm2,
+    fpu_xmm3,
+    fpu_xmm4,
+    fpu_xmm5,
+    fpu_xmm6,
+    fpu_xmm7,
+    k_last_fpr = fpu_xmm7,
+
+    k_num_registers,
+    k_num_gpr_registers = k_last_gpr - k_first_gpr + 1,
+    k_num_fpu_registers = k_last_fpr - k_first_fpr + 1
+};
+
+// Number of register sets provided by this context.
+enum
+{
+    k_num_register_sets = 2
+};
+
+static const
+uint32_t g_gpr_regnums[k_num_gpr_registers] =
+{
+    gpr_eax,
+    gpr_ebx,
+    gpr_ecx,
+    gpr_edx,
+    gpr_edi,
+    gpr_esi,
+    gpr_ebp,
+    gpr_esp,
+    gpr_ss,
+    gpr_eflags,
+#ifdef __FreeBSD__
+    gpr_orig_ax,
+#endif
+    gpr_eip,
+    gpr_cs,
+    gpr_ds,
+    gpr_es,
+    gpr_fs,
+    gpr_gs,
+};
+
+static const uint32_t
+g_fpu_regnums[k_num_fpu_registers] =
+{
+    fpu_fcw,
+    fpu_fsw,
+    fpu_ftw,
+    fpu_fop,
+    fpu_ip,
+    fpu_cs,
+    fpu_foo,
+    fpu_fos,
+    fpu_mxcsr,
+    fpu_stmm0,
+    fpu_stmm1,
+    fpu_stmm2,
+    fpu_stmm3,
+    fpu_stmm4,
+    fpu_stmm5,
+    fpu_stmm6,
+    fpu_stmm7,
+    fpu_xmm0,
+    fpu_xmm1,
+    fpu_xmm2,
+    fpu_xmm3,
+    fpu_xmm4,
+    fpu_xmm5,
+    fpu_xmm6,
+    fpu_xmm7,
+};
+
+static const RegisterSet
+g_reg_sets[k_num_register_sets] =
+{
+    { "General Purpose Registers", "gpr", k_num_gpr_registers, g_gpr_regnums },
+    { "Floating Point Registers",  "fpu", k_num_fpu_registers, g_fpu_regnums }
+};
+
+// Computes the offset of the given GPR in the user data area.
+#define GPR_OFFSET(regname) \
+    (offsetof(RegisterContext_i386::UserArea, regs) + \
+     offsetof(RegisterContext_i386::GPR, regname))
+
+// Computes the offset of the given FPR in the user data area.
+#define FPR_OFFSET(regname) \
+    (offsetof(RegisterContext_i386::UserArea, i387) + \
+     offsetof(RegisterContext_i386::FPU, regname))
+
+// Number of bytes needed to represent a GPR.
+#define GPR_SIZE(reg) sizeof(((RegisterContext_i386::GPR*)NULL)->reg)
+
+// Number of bytes needed to represent a FPR.
+#define FPR_SIZE(reg) sizeof(((RegisterContext_i386::FPU*)NULL)->reg)
+
+// Number of bytes needed to represent the i'th FP register.
+#define FP_SIZE sizeof(((RegisterContext_i386::MMSReg*)NULL)->bytes)
+
+// Number of bytes needed to represent an XMM register.
+#define XMM_SIZE sizeof(RegisterContext_i386::XMMReg)
+
+#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4)        \
+    { #reg, alt, GPR_SIZE(reg), GPR_OFFSET(reg), eEncodingUint, \
+      eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg }, NULL, NULL }
+
+#define DEFINE_FPR(reg, kind1, kind2, kind3, kind4)              \
+    { #reg, NULL, FPR_SIZE(reg), FPR_OFFSET(reg), eEncodingUint, \
+      eFormatHex, { kind1, kind2, kind3, kind4, fpu_##reg }, NULL, NULL }
+
+#define DEFINE_FP(reg, i)                                          \
+    { #reg#i, NULL, FP_SIZE, LLVM_EXTENSION FPR_OFFSET(reg[i]),    \
+      eEncodingVector, eFormatVectorOfUInt8,                       \
+      { dwarf_##reg##i, dwarf_##reg##i,                            \
+        LLDB_INVALID_REGNUM, gdb_##reg##i, fpu_##reg##i }, NULL, NULL }
+
+#define DEFINE_XMM(reg, i)                                         \
+    { #reg#i, NULL, XMM_SIZE, LLVM_EXTENSION FPR_OFFSET(reg[i]),   \
+       eEncodingVector, eFormatVectorOfUInt8,                      \
+      { dwarf_##reg##i, dwarf_##reg##i,                            \
+        LLDB_INVALID_REGNUM, gdb_##reg##i, fpu_##reg##i }, NULL, NULL }
+
+static RegisterInfo
+g_register_infos[k_num_registers] =
+{
+    // General purpose registers.
+    DEFINE_GPR(eax,    NULL,    gcc_eax,    dwarf_eax,    LLDB_INVALID_REGNUM,    gdb_eax),
+    DEFINE_GPR(ebx,    NULL,    gcc_ebx,    dwarf_ebx,    LLDB_INVALID_REGNUM,    gdb_ebx),
+    DEFINE_GPR(ecx,    NULL,    gcc_ecx,    dwarf_ecx,    LLDB_INVALID_REGNUM,    gdb_ecx),
+    DEFINE_GPR(edx,    NULL,    gcc_edx,    dwarf_edx,    LLDB_INVALID_REGNUM,    gdb_edx),
+    DEFINE_GPR(edi,    NULL,    gcc_edi,    dwarf_edi,    LLDB_INVALID_REGNUM,    gdb_edi),
+    DEFINE_GPR(esi,    NULL,    gcc_esi,    dwarf_esi,    LLDB_INVALID_REGNUM,    gdb_esi),
+    DEFINE_GPR(ebp,    "fp",    gcc_ebp,    dwarf_ebp,    LLDB_INVALID_REGNUM,    gdb_ebp),
+    DEFINE_GPR(esp,    "sp",    gcc_esp,    dwarf_esp,    LLDB_INVALID_REGNUM,    gdb_esp),
+    DEFINE_GPR(ss,     NULL,    LLDB_INVALID_REGNUM,     LLDB_INVALID_REGNUM,     LLDB_INVALID_REGNUM,    gdb_ss),
+    DEFINE_GPR(eflags, "flags", gcc_eflags, dwarf_eflags, LLDB_INVALID_REGNUM,    gdb_eflags),
+    DEFINE_GPR(eip,    "pc",    gcc_eip,    dwarf_eip,    LLDB_INVALID_REGNUM,    gdb_eip),
+    DEFINE_GPR(cs,     NULL,    LLDB_INVALID_REGNUM,     LLDB_INVALID_REGNUM,     LLDB_INVALID_REGNUM,    gdb_cs),
+    DEFINE_GPR(ds,     NULL,    LLDB_INVALID_REGNUM,     LLDB_INVALID_REGNUM,     LLDB_INVALID_REGNUM,    gdb_ds),
+    DEFINE_GPR(es,     NULL,    LLDB_INVALID_REGNUM,     LLDB_INVALID_REGNUM,     LLDB_INVALID_REGNUM,    gdb_es),
+    DEFINE_GPR(fs,     NULL,    LLDB_INVALID_REGNUM,     LLDB_INVALID_REGNUM,     LLDB_INVALID_REGNUM,    gdb_fs),
+    DEFINE_GPR(gs,     NULL,    LLDB_INVALID_REGNUM,     LLDB_INVALID_REGNUM,     LLDB_INVALID_REGNUM,    gdb_gs),
+
+    // Floating point registers.
+    DEFINE_FPR(fcw,       LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fcw),
+    DEFINE_FPR(fsw,       LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fsw),
+    DEFINE_FPR(ftw,       LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ftw),
+    DEFINE_FPR(fop,       LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fop),
+    DEFINE_FPR(ip,        LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_ip),
+    DEFINE_FPR(cs,        LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_cs),
+    DEFINE_FPR(foo,       LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_dp),
+    DEFINE_FPR(fos,       LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ds),
+    DEFINE_FPR(mxcsr,     LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_mxcsr),
+
+    DEFINE_FP(stmm, 0),
+    DEFINE_FP(stmm, 1),
+    DEFINE_FP(stmm, 2),
+    DEFINE_FP(stmm, 3),
+    DEFINE_FP(stmm, 4),
+    DEFINE_FP(stmm, 5),
+    DEFINE_FP(stmm, 6),
+    DEFINE_FP(stmm, 7),
+
+    // XMM registers
+    DEFINE_XMM(xmm, 0),
+    DEFINE_XMM(xmm, 1),
+    DEFINE_XMM(xmm, 2),
+    DEFINE_XMM(xmm, 3),
+    DEFINE_XMM(xmm, 4),
+    DEFINE_XMM(xmm, 5),
+    DEFINE_XMM(xmm, 6),
+    DEFINE_XMM(xmm, 7),
+
+};
+
+#ifndef NDEBUG
+static size_t k_num_register_infos = (sizeof(g_register_infos)/sizeof(RegisterInfo));
+#endif
+
+static unsigned GetRegOffset(unsigned reg)
+{
+    assert(reg < k_num_registers && "Invalid register number.");
+    return g_register_infos[reg].byte_offset;
+}
+
+static unsigned GetRegSize(unsigned reg)
+{
+    assert(reg < k_num_registers && "Invalid register number.");
+    return g_register_infos[reg].byte_size;
+}
+
+RegisterContext_i386::RegisterContext_i386(Thread &thread,
+                                                     uint32_t concrete_frame_idx)
+    : RegisterContextPOSIX(thread, concrete_frame_idx)
+{
+}
+
+RegisterContext_i386::~RegisterContext_i386()
+{
+}
+
+ProcessMonitor &
+RegisterContext_i386::GetMonitor()
+{
+    ProcessSP base = CalculateProcess();
+    ProcessPOSIX *process = static_cast<ProcessPOSIX*>(base.get());
+    return process->GetMonitor();
+}
+
+void
+RegisterContext_i386::Invalidate()
+{
+}
+
+void
+RegisterContext_i386::InvalidateAllRegisters()
+{
+}
+
+size_t
+RegisterContext_i386::GetRegisterCount()
+{
+    assert(k_num_register_infos == k_num_registers);
+    return k_num_registers;
+}
+
+const RegisterInfo *
+RegisterContext_i386::GetRegisterInfoAtIndex(size_t reg)
+{
+    assert(k_num_register_infos == k_num_registers);
+    if (reg < k_num_registers)
+        return &g_register_infos[reg];
+    else
+        return NULL;
+}
+
+size_t
+RegisterContext_i386::GetRegisterSetCount()
+{
+    return k_num_register_sets;
+}
+
+const RegisterSet *
+RegisterContext_i386::GetRegisterSet(size_t set)
+{
+    if (set < k_num_register_sets)
+        return &g_reg_sets[set];
+    else
+        return NULL;
+}
+
+unsigned
+RegisterContext_i386::GetRegisterIndexFromOffset(unsigned offset)
+{
+    unsigned reg;
+    for (reg = 0; reg < k_num_registers; reg++)
+    {
+        if (g_register_infos[reg].byte_offset == offset)
+            break;
+    }
+    assert(reg < k_num_registers && "Invalid register offset.");
+    return reg;
+}
+
+const char *
+RegisterContext_i386::GetRegisterName(unsigned reg)
+{
+    assert(reg < k_num_registers && "Invalid register offset.");
+    return g_register_infos[reg].name;
+}
+
+bool
+RegisterContext_i386::ReadRegister(const RegisterInfo *reg_info,
+                                        RegisterValue &value)
+{
+    const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
+    ProcessMonitor &monitor = GetMonitor();
+    return monitor.ReadRegisterValue(m_thread.GetID(), GetRegOffset(reg),
+                                     GetRegisterName(reg), GetRegSize(reg), value);
+}
+
+bool
+RegisterContext_i386::ReadAllRegisterValues(DataBufferSP &data_sp)
+{
+    return false;
+}
+
+bool RegisterContext_i386::WriteRegister(const RegisterInfo *reg_info,
+                                         const RegisterValue &value)
+{
+    const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
+    ProcessMonitor &monitor = GetMonitor();
+    return monitor.WriteRegisterValue(m_thread.GetID(), GetRegOffset(reg),
+                                      GetRegisterName(reg), value);
+}
+
+bool
+RegisterContext_i386::WriteAllRegisterValues(const DataBufferSP &data)
+{
+    return false;
+}
+
+bool
+RegisterContext_i386::UpdateAfterBreakpoint()
+{
+    // PC points one byte past the int3 responsible for the breakpoint.
+    lldb::addr_t pc;
+
+    if ((pc = GetPC()) == LLDB_INVALID_ADDRESS)
+        return false;
+
+    SetPC(pc - 1);
+    return true;
+}
+
+uint32_t
+RegisterContext_i386::ConvertRegisterKindToRegisterNumber(uint32_t kind,
+                                                               uint32_t num)
+{
+    if (kind == eRegisterKindGeneric)
+    {
+        switch (num)
+        {
+        case LLDB_REGNUM_GENERIC_PC:    return gpr_eip;
+        case LLDB_REGNUM_GENERIC_SP:    return gpr_esp;
+        case LLDB_REGNUM_GENERIC_FP:    return gpr_ebp;
+        case LLDB_REGNUM_GENERIC_FLAGS: return gpr_eflags;
+        case LLDB_REGNUM_GENERIC_RA:
+        default:
+            return LLDB_INVALID_REGNUM;
+        }
+    }
+
+    if (kind == eRegisterKindGCC || kind == eRegisterKindDWARF)
+    {
+        switch (num)
+        {
+        case dwarf_eax:  return gpr_eax;
+        case dwarf_edx:  return gpr_edx;
+        case dwarf_ecx:  return gpr_ecx;
+        case dwarf_ebx:  return gpr_ebx;
+        case dwarf_esi:  return gpr_esi;
+        case dwarf_edi:  return gpr_edi;
+        case dwarf_ebp:  return gpr_ebp;
+        case dwarf_esp:  return gpr_esp;
+        case dwarf_eip:  return gpr_eip;
+        case dwarf_xmm0: return fpu_xmm0;
+        case dwarf_xmm1: return fpu_xmm1;
+        case dwarf_xmm2: return fpu_xmm2;
+        case dwarf_xmm3: return fpu_xmm3;
+        case dwarf_xmm4: return fpu_xmm4;
+        case dwarf_xmm5: return fpu_xmm5;
+        case dwarf_xmm6: return fpu_xmm6;
+        case dwarf_xmm7: return fpu_xmm7;
+        case dwarf_stmm0: return fpu_stmm0;
+        case dwarf_stmm1: return fpu_stmm1;
+        case dwarf_stmm2: return fpu_stmm2;
+        case dwarf_stmm3: return fpu_stmm3;
+        case dwarf_stmm4: return fpu_stmm4;
+        case dwarf_stmm5: return fpu_stmm5;
+        case dwarf_stmm6: return fpu_stmm6;
+        case dwarf_stmm7: return fpu_stmm7;
+        default:
+            return LLDB_INVALID_REGNUM;
+        }
+    }
+
+    if (kind == eRegisterKindGDB)
+    {
+        switch (num)
+        {
+        case gdb_eax     : return gpr_eax;
+        case gdb_ebx     : return gpr_ebx;
+        case gdb_ecx     : return gpr_ecx;
+        case gdb_edx     : return gpr_edx;
+        case gdb_esi     : return gpr_esi;
+        case gdb_edi     : return gpr_edi;
+        case gdb_ebp     : return gpr_ebp;
+        case gdb_esp     : return gpr_esp;
+        case gdb_eip     : return gpr_eip;
+        case gdb_eflags  : return gpr_eflags;
+        case gdb_cs      : return gpr_cs;
+        case gdb_ss      : return gpr_ss;
+        case gdb_ds      : return gpr_ds;
+        case gdb_es      : return gpr_es;
+        case gdb_fs      : return gpr_fs;
+        case gdb_gs      : return gpr_gs;
+        case gdb_stmm0   : return fpu_stmm0;
+        case gdb_stmm1   : return fpu_stmm1;
+        case gdb_stmm2   : return fpu_stmm2;
+        case gdb_stmm3   : return fpu_stmm3;
+        case gdb_stmm4   : return fpu_stmm4;
+        case gdb_stmm5   : return fpu_stmm5;
+        case gdb_stmm6   : return fpu_stmm6;
+        case gdb_stmm7   : return fpu_stmm7;
+        case gdb_fcw     : return fpu_fcw;
+        case gdb_fsw     : return fpu_fsw;
+        case gdb_ftw     : return fpu_ftw;
+        case gdb_fpu_cs  : return fpu_cs;
+        case gdb_ip      : return fpu_ip;
+        case gdb_fpu_ds  : return fpu_fos;
+        case gdb_dp      : return fpu_foo;
+        case gdb_fop     : return fpu_fop;
+        case gdb_xmm0    : return fpu_xmm0;
+        case gdb_xmm1    : return fpu_xmm1;
+        case gdb_xmm2    : return fpu_xmm2;
+        case gdb_xmm3    : return fpu_xmm3;
+        case gdb_xmm4    : return fpu_xmm4;
+        case gdb_xmm5    : return fpu_xmm5;
+        case gdb_xmm6    : return fpu_xmm6;
+        case gdb_xmm7    : return fpu_xmm7;
+        case gdb_mxcsr   : return fpu_mxcsr;
+        default:
+            return LLDB_INVALID_REGNUM;
+        }
+    }
+    else if (kind == eRegisterKindLLDB)
+    {
+        return num;
+    }
+
+    return LLDB_INVALID_REGNUM;
+}
+
+bool
+RegisterContext_i386::HardwareSingleStep(bool enable)
+{
+    enum { TRACE_BIT = 0x100 };
+    uint64_t eflags;
+
+    if ((eflags = ReadRegisterAsUnsigned(gpr_eflags, -1UL)) == -1UL)
+        return false;
+
+    if (enable)
+    {
+        if (eflags & TRACE_BIT)
+            return true;
+
+        eflags |= TRACE_BIT;
+    }
+    else
+    {
+        if (!(eflags & TRACE_BIT))
+            return false;
+
+        eflags &= ~TRACE_BIT;
+    }
+
+    return WriteRegisterFromUnsigned(gpr_eflags, eflags);
+}
+
+void
+RegisterContext_i386::LogGPR(const char *title)
+{
+    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_REGISTERS));
+    if (log)
+    {
+        if (title)
+            log->Printf ("%s", title);
+        for (uint32_t i=0; i<k_num_gpr_registers; i++)
+        {
+            uint32_t reg = gpr_eax + i;
+            log->Printf("%12s = 0x%8.8" PRIx64, g_register_infos[reg].name, ((uint64_t*)&user.regs)[reg]);
+        }
+    }
+}
+
+bool
+RegisterContext_i386::ReadGPR()
+{
+    bool result;
+
+    ProcessMonitor &monitor = GetMonitor();
+    result = monitor.ReadGPR(m_thread.GetID(), &user.regs, sizeof(user.regs));
+    LogGPR("RegisterContext_i386::ReadGPR()");
+    return result;
+}
+
+bool
+RegisterContext_i386::ReadFPR()
+{
+    ProcessMonitor &monitor = GetMonitor();
+    return monitor.ReadFPR(m_thread.GetID(), &user.i387, sizeof(user.i387));
+}
diff --git a/source/Plugins/Process/POSIX/RegisterContext_i386.h b/source/Plugins/Process/POSIX/RegisterContext_i386.h
new file mode 100644
index 000000000000..96066c47b815
--- /dev/null
+++ b/source/Plugins/Process/POSIX/RegisterContext_i386.h
@@ -0,0 +1,169 @@
+//===-- RegisterContext_i386.h ------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_RegisterContext_i386_h_
+#define liblldb_RegisterContext_i386_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Log.h"
+#include "RegisterContextPOSIX.h"
+
+class RegisterContext_i386 : public RegisterContextPOSIX
+{
+public:
+    RegisterContext_i386(lldb_private::Thread &thread,
+                              uint32_t concreate_frame_idx);
+
+    ~RegisterContext_i386();
+
+    void
+    Invalidate();
+
+    void
+    InvalidateAllRegisters();
+
+    size_t
+    GetRegisterCount();
+
+    const lldb_private::RegisterInfo *
+    GetRegisterInfoAtIndex(size_t reg);
+
+    size_t
+    GetRegisterSetCount();
+
+    const lldb_private::RegisterSet *
+    GetRegisterSet(size_t set);
+
+    unsigned
+    GetRegisterIndexFromOffset(unsigned offset);
+
+    const char *
+    GetRegisterName(unsigned reg);
+
+    bool
+    ReadRegisterValue(uint32_t reg, lldb_private::Scalar &value);
+
+    bool
+    ReadRegisterBytes(uint32_t reg, lldb_private::DataExtractor &data);
+
+    virtual bool
+    ReadRegister(const lldb_private::RegisterInfo *reg_info,
+                 lldb_private::RegisterValue &value);
+
+    bool
+    ReadAllRegisterValues(lldb::DataBufferSP &data_sp);
+
+    bool
+    WriteRegisterValue(uint32_t reg, const lldb_private::Scalar &value);
+
+    bool
+    WriteRegisterBytes(uint32_t reg, lldb_private::DataExtractor &data,
+                       uint32_t data_offset = 0);
+
+    virtual bool
+    WriteRegister(const lldb_private::RegisterInfo *reg_info,
+                  const lldb_private::RegisterValue &value);
+
+    bool
+    WriteAllRegisterValues(const lldb::DataBufferSP &data_sp);
+
+    uint32_t
+    ConvertRegisterKindToRegisterNumber(uint32_t kind, uint32_t num);
+
+    bool
+    HardwareSingleStep(bool enable);
+
+    bool
+    UpdateAfterBreakpoint();
+
+    struct GPR
+    {
+        uint32_t ebx;
+        uint32_t ecx;
+        uint32_t edx;
+        uint32_t esi;
+        uint32_t edi;
+        uint32_t ebp;
+        uint32_t eax;
+        uint32_t ds;
+        uint32_t es;
+        uint32_t fs;
+        uint32_t gs;
+        uint32_t orig_ax;
+        uint32_t eip;
+        uint32_t cs;
+        uint32_t eflags;
+        uint32_t esp;
+        uint32_t ss;
+    };
+
+    struct MMSReg
+    {
+        uint8_t bytes[8];
+    };
+
+    struct XMMReg
+    {
+        uint8_t bytes[16];
+    };
+
+    struct FPU
+    {
+        uint16_t    fcw;
+        uint16_t    fsw;
+        uint16_t    ftw;
+        uint16_t    fop;
+        uint32_t    ip;
+        uint32_t    cs;
+        uint32_t    foo;
+        uint32_t    fos;
+        uint32_t    mxcsr;
+        uint32_t    reserved;
+        MMSReg      stmm[8];
+        XMMReg      xmm[8];
+        uint32_t    pad[56];
+    };
+
+    // A user area like this no longer exists on FreeBSD
+    // making this a Linux artifact. Nonetheless, it is safe
+    // leaving it here while the code is being cleaned up and generalized.
+
+    struct UserArea
+    {
+        GPR      regs;          // General purpose registers.
+        int32_t  fpvalid;       // True if FPU is being used.
+        FPU      i387;          // FPU registers.
+        uint32_t tsize;         // Text segment size.
+        uint32_t dsize;         // Data segment size.
+        uint32_t ssize;         // Stack segment size.
+        uint32_t start_code;    // VM address of text.
+        uint32_t start_stack;   // VM address of stack bottom (top in rsp).
+        int32_t  signal;        // Signal causing core dump.
+        int32_t  reserved;      // Unused.
+        uint32_t ar0;           // Location of GPR's.
+        FPU*     fpstate;       // Location of FPR's.
+        uint32_t magic;         // Identifier for core dumps.
+        char     u_comm[32];    // Command causing core dump.
+        uint32_t u_debugreg[8]; // Debug registers (DR0 - DR7).
+    };
+private:
+    UserArea user;
+
+    ProcessMonitor &GetMonitor();
+
+    void LogGPR(const char *title);
+
+    bool ReadGPR();
+    bool ReadFPR();
+};
+
+#endif // #ifndef liblldb_RegisterContext_i386_h_
diff --git a/source/Plugins/Process/POSIX/RegisterContext_x86.h b/source/Plugins/Process/POSIX/RegisterContext_x86.h
new file mode 100644
index 000000000000..61a25c407758
--- /dev/null
+++ b/source/Plugins/Process/POSIX/RegisterContext_x86.h
@@ -0,0 +1,110 @@
+//===-- RegisterContext_x86.h ---------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_RegisterContext_x86_H_
+#define liblldb_RegisterContext_x86_H_
+
+enum
+{
+    gcc_eax = 0,
+    gcc_ecx,
+    gcc_edx,
+    gcc_ebx,
+    gcc_ebp,
+    gcc_esp,
+    gcc_esi,
+    gcc_edi,
+    gcc_eip,
+    gcc_eflags
+};
+
+enum
+{
+    dwarf_eax = 0,
+    dwarf_ecx,
+    dwarf_edx,
+    dwarf_ebx,
+    dwarf_esp,
+    dwarf_ebp,
+    dwarf_esi,
+    dwarf_edi,
+    dwarf_eip,
+    dwarf_eflags,
+    dwarf_stmm0 = 11,
+    dwarf_stmm1,
+    dwarf_stmm2,
+    dwarf_stmm3,
+    dwarf_stmm4,
+    dwarf_stmm5,
+    dwarf_stmm6,
+    dwarf_stmm7,
+    dwarf_xmm0 = 21,
+    dwarf_xmm1,
+    dwarf_xmm2,
+    dwarf_xmm3,
+    dwarf_xmm4,
+    dwarf_xmm5,
+    dwarf_xmm6,
+    dwarf_xmm7
+};
+
+enum
+{
+    gdb_eax        =  0,
+    gdb_ecx        =  1,
+    gdb_edx        =  2,
+    gdb_ebx        =  3,
+    gdb_esp        =  4,
+    gdb_ebp        =  5,
+    gdb_esi        =  6,
+    gdb_edi        =  7,
+    gdb_eip        =  8,
+    gdb_eflags     =  9,
+    gdb_cs         = 10,
+    gdb_ss         = 11,
+    gdb_ds         = 12,
+    gdb_es         = 13,
+    gdb_fs         = 14,
+    gdb_gs         = 15,
+    gdb_stmm0      = 16,
+    gdb_stmm1      = 17,
+    gdb_stmm2      = 18,
+    gdb_stmm3      = 19,
+    gdb_stmm4      = 20,
+    gdb_stmm5      = 21,
+    gdb_stmm6      = 22,
+    gdb_stmm7      = 23,
+    gdb_fcw        = 24,
+    gdb_fsw        = 25,
+    gdb_ftw        = 26,
+    gdb_fpu_cs     = 27,
+    gdb_ip         = 28,
+    gdb_fpu_ds     = 29,
+    gdb_dp         = 30,
+    gdb_fop        = 31,
+    gdb_xmm0       = 32,
+    gdb_xmm1       = 33,
+    gdb_xmm2       = 34,
+    gdb_xmm3       = 35,
+    gdb_xmm4       = 36,
+    gdb_xmm5       = 37,
+    gdb_xmm6       = 38,
+    gdb_xmm7       = 39,
+    gdb_mxcsr      = 40,
+    gdb_mm0        = 41,
+    gdb_mm1        = 42,
+    gdb_mm2        = 43,
+    gdb_mm3        = 44,
+    gdb_mm4        = 45,
+    gdb_mm5        = 46,
+    gdb_mm6        = 47,
+    gdb_mm7        = 48
+};
+
+#endif
diff --git a/source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp b/source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp
new file mode 100644
index 000000000000..617b18484e5a
--- /dev/null
+++ b/source/Plugins/Process/POSIX/RegisterContext_x86_64.cpp
@@ -0,0 +1,1563 @@
+//===-- RegisterContext_x86_64.cpp -------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <cstring>
+#include <errno.h>
+#include <stdint.h>
+
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/RegisterValue.h"
+#include "lldb/Core/Scalar.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Host/Endian.h"
+#include "llvm/Support/Compiler.h"
+
+#include "ProcessPOSIX.h"
+#if defined(__linux__) or defined(__FreeBSD__)
+#include "ProcessMonitor.h"
+#endif
+#include "RegisterContext_i386.h"
+#include "RegisterContext_x86.h"
+#include "RegisterContext_x86_64.h"
+#include "Plugins/Process/elf-core/ProcessElfCore.h"
+
+using namespace lldb_private;
+using namespace lldb;
+
+// Support ptrace extensions even when compiled without required kernel support
+#ifndef NT_X86_XSTATE
+  #define NT_X86_XSTATE 0x202
+#endif
+
+enum
+{
+    gcc_dwarf_gpr_rax = 0,
+    gcc_dwarf_gpr_rdx,
+    gcc_dwarf_gpr_rcx,
+    gcc_dwarf_gpr_rbx,
+    gcc_dwarf_gpr_rsi,
+    gcc_dwarf_gpr_rdi,
+    gcc_dwarf_gpr_rbp,
+    gcc_dwarf_gpr_rsp,
+    gcc_dwarf_gpr_r8,
+    gcc_dwarf_gpr_r9,
+    gcc_dwarf_gpr_r10,
+    gcc_dwarf_gpr_r11,
+    gcc_dwarf_gpr_r12,
+    gcc_dwarf_gpr_r13,
+    gcc_dwarf_gpr_r14,
+    gcc_dwarf_gpr_r15,
+    gcc_dwarf_gpr_rip,
+    gcc_dwarf_fpu_xmm0,
+    gcc_dwarf_fpu_xmm1,
+    gcc_dwarf_fpu_xmm2,
+    gcc_dwarf_fpu_xmm3,
+    gcc_dwarf_fpu_xmm4,
+    gcc_dwarf_fpu_xmm5,
+    gcc_dwarf_fpu_xmm6,
+    gcc_dwarf_fpu_xmm7,
+    gcc_dwarf_fpu_xmm8,
+    gcc_dwarf_fpu_xmm9,
+    gcc_dwarf_fpu_xmm10,
+    gcc_dwarf_fpu_xmm11,
+    gcc_dwarf_fpu_xmm12,
+    gcc_dwarf_fpu_xmm13,
+    gcc_dwarf_fpu_xmm14,
+    gcc_dwarf_fpu_xmm15,
+    gcc_dwarf_fpu_stmm0,
+    gcc_dwarf_fpu_stmm1,
+    gcc_dwarf_fpu_stmm2,
+    gcc_dwarf_fpu_stmm3,
+    gcc_dwarf_fpu_stmm4,
+    gcc_dwarf_fpu_stmm5,
+    gcc_dwarf_fpu_stmm6,
+    gcc_dwarf_fpu_stmm7,
+    gcc_dwarf_fpu_ymm0,
+    gcc_dwarf_fpu_ymm1,
+    gcc_dwarf_fpu_ymm2,
+    gcc_dwarf_fpu_ymm3,
+    gcc_dwarf_fpu_ymm4,
+    gcc_dwarf_fpu_ymm5,
+    gcc_dwarf_fpu_ymm6,
+    gcc_dwarf_fpu_ymm7,
+    gcc_dwarf_fpu_ymm8,
+    gcc_dwarf_fpu_ymm9,
+    gcc_dwarf_fpu_ymm10,
+    gcc_dwarf_fpu_ymm11,
+    gcc_dwarf_fpu_ymm12,
+    gcc_dwarf_fpu_ymm13,
+    gcc_dwarf_fpu_ymm14,
+    gcc_dwarf_fpu_ymm15
+};
+
+enum
+{
+    gdb_gpr_rax     =   0,
+    gdb_gpr_rbx     =   1,
+    gdb_gpr_rcx     =   2,
+    gdb_gpr_rdx     =   3,
+    gdb_gpr_rsi     =   4,
+    gdb_gpr_rdi     =   5,
+    gdb_gpr_rbp     =   6,
+    gdb_gpr_rsp     =   7,
+    gdb_gpr_r8      =   8,
+    gdb_gpr_r9      =   9,
+    gdb_gpr_r10     =  10,
+    gdb_gpr_r11     =  11,
+    gdb_gpr_r12     =  12,
+    gdb_gpr_r13     =  13,
+    gdb_gpr_r14     =  14,
+    gdb_gpr_r15     =  15,
+    gdb_gpr_rip     =  16,
+    gdb_gpr_rflags  =  17,
+    gdb_gpr_cs      =  18,
+    gdb_gpr_ss      =  19,
+    gdb_gpr_ds      =  20,
+    gdb_gpr_es      =  21,
+    gdb_gpr_fs      =  22,
+    gdb_gpr_gs      =  23,
+    gdb_fpu_stmm0   =  24,
+    gdb_fpu_stmm1   =  25,
+    gdb_fpu_stmm2   =  26,
+    gdb_fpu_stmm3   =  27,
+    gdb_fpu_stmm4   =  28,
+    gdb_fpu_stmm5   =  29,
+    gdb_fpu_stmm6   =  30,
+    gdb_fpu_stmm7   =  31,
+    gdb_fpu_fcw     =  32,
+    gdb_fpu_fsw     =  33,
+    gdb_fpu_ftw     =  34,
+    gdb_fpu_cs_64   =  35,
+    gdb_fpu_ip      =  36,
+    gdb_fpu_ds_64   =  37,
+    gdb_fpu_dp      =  38,
+    gdb_fpu_fop     =  39,
+    gdb_fpu_xmm0    =  40,
+    gdb_fpu_xmm1    =  41,
+    gdb_fpu_xmm2    =  42,
+    gdb_fpu_xmm3    =  43,
+    gdb_fpu_xmm4    =  44,
+    gdb_fpu_xmm5    =  45,
+    gdb_fpu_xmm6    =  46,
+    gdb_fpu_xmm7    =  47,
+    gdb_fpu_xmm8    =  48,
+    gdb_fpu_xmm9    =  49,
+    gdb_fpu_xmm10   =  50,
+    gdb_fpu_xmm11   =  51,
+    gdb_fpu_xmm12   =  52,
+    gdb_fpu_xmm13   =  53,
+    gdb_fpu_xmm14   =  54,
+    gdb_fpu_xmm15   =  55,
+    gdb_fpu_mxcsr   =  56,
+    gdb_fpu_ymm0    =  57,
+    gdb_fpu_ymm1    =  58,
+    gdb_fpu_ymm2    =  59,
+    gdb_fpu_ymm3    =  60,
+    gdb_fpu_ymm4    =  61,
+    gdb_fpu_ymm5    =  62,
+    gdb_fpu_ymm6    =  63,
+    gdb_fpu_ymm7    =  64,
+    gdb_fpu_ymm8    =  65,
+    gdb_fpu_ymm9    =  66,
+    gdb_fpu_ymm10   =  67,
+    gdb_fpu_ymm11   =  68,
+    gdb_fpu_ymm12   =  69,
+    gdb_fpu_ymm13   =  70,
+    gdb_fpu_ymm14   =  71,
+    gdb_fpu_ymm15   =  72
+};
+
+static const
+uint32_t g_gpr_regnums[k_num_gpr_registers] =
+{
+    gpr_rax,
+    gpr_rbx,
+    gpr_rcx,
+    gpr_rdx,
+    gpr_rdi,
+    gpr_rsi,
+    gpr_rbp,
+    gpr_rsp,
+    gpr_r8,
+    gpr_r9,
+    gpr_r10,
+    gpr_r11,
+    gpr_r12,
+    gpr_r13,
+    gpr_r14,
+    gpr_r15,
+    gpr_rip,
+    gpr_rflags,
+    gpr_cs,
+    gpr_fs,
+    gpr_gs,
+    gpr_ss,
+    gpr_ds,
+    gpr_es,
+    gpr_eax,
+    gpr_ebx,
+    gpr_ecx,
+    gpr_edx,
+    gpr_edi,
+    gpr_esi,
+    gpr_ebp,
+    gpr_esp,
+    gpr_eip,
+    gpr_eflags
+};
+
+static const uint32_t
+g_fpu_regnums[k_num_fpr_registers] =
+{
+    fpu_fcw,
+    fpu_fsw,
+    fpu_ftw,
+    fpu_fop,
+    fpu_ip,
+    fpu_cs,
+    fpu_dp,
+    fpu_ds,
+    fpu_mxcsr,
+    fpu_mxcsrmask,
+    fpu_stmm0,
+    fpu_stmm1,
+    fpu_stmm2,
+    fpu_stmm3,
+    fpu_stmm4,
+    fpu_stmm5,
+    fpu_stmm6,
+    fpu_stmm7,
+    fpu_xmm0,
+    fpu_xmm1,
+    fpu_xmm2,
+    fpu_xmm3,
+    fpu_xmm4,
+    fpu_xmm5,
+    fpu_xmm6,
+    fpu_xmm7,
+    fpu_xmm8,
+    fpu_xmm9,
+    fpu_xmm10,
+    fpu_xmm11,
+    fpu_xmm12,
+    fpu_xmm13,
+    fpu_xmm14,
+    fpu_xmm15
+};
+
+static const uint32_t
+g_avx_regnums[k_num_avx_registers] =
+{
+    fpu_ymm0,
+    fpu_ymm1,
+    fpu_ymm2,
+    fpu_ymm3,
+    fpu_ymm4,
+    fpu_ymm5,
+    fpu_ymm6,
+    fpu_ymm7,
+    fpu_ymm8,
+    fpu_ymm9,
+    fpu_ymm10,
+    fpu_ymm11,
+    fpu_ymm12,
+    fpu_ymm13,
+    fpu_ymm14,
+    fpu_ymm15
+};
+
+// Number of register sets provided by this context.
+enum
+{
+    k_num_extended_register_sets = 1,
+    k_num_register_sets = 3
+};
+
+static const RegisterSet
+g_reg_sets[k_num_register_sets] =
+{
+    { "General Purpose Registers",  "gpr", k_num_gpr_registers, g_gpr_regnums },
+    { "Floating Point Registers",   "fpu", k_num_fpr_registers, g_fpu_regnums },
+    { "Advanced Vector Extensions", "avx", k_num_avx_registers, g_avx_regnums }
+};
+
+// Computes the offset of the given FPR in the extended data area.
+#define FPR_OFFSET(regname) \
+    (offsetof(RegisterContext_x86_64::FPR, xstate) + \
+     offsetof(RegisterContext_x86_64::FXSAVE, regname))
+
+// Computes the offset of the YMM register assembled from register halves.
+#define YMM_OFFSET(regname) \
+    (offsetof(RegisterContext_x86_64::YMM, regname))
+
+// Number of bytes needed to represent a i386 GPR
+#define GPR_i386_SIZE(reg) sizeof(((RegisterContext_i386::GPR*)NULL)->reg)
+
+// Number of bytes needed to represent a FPR.
+#define FPR_SIZE(reg) sizeof(((RegisterContext_x86_64::FXSAVE*)NULL)->reg)
+
+// Number of bytes needed to represent the i'th FP register.
+#define FP_SIZE sizeof(((RegisterContext_x86_64::MMSReg*)NULL)->bytes)
+
+// Number of bytes needed to represent an XMM register.
+#define XMM_SIZE sizeof(RegisterContext_x86_64::XMMReg)
+
+// Number of bytes needed to represent a YMM register.
+#define YMM_SIZE sizeof(RegisterContext_x86_64::YMMReg)
+
+// Note that the size and offset will be updated by platform-specific classes.
+#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4)           \
+    { #reg, alt, 0, 0, eEncodingUint,                              \
+      eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg }, NULL, NULL }
+
+// Dummy data for RegisterInfo::value_regs as expected by DumpRegisterSet. 
+static uint32_t value_regs = LLDB_INVALID_REGNUM;
+
+#define DEFINE_GPR_i386(reg_i386, reg_x86_64, alt, kind1, kind2, kind3, kind4) \
+    { #reg_i386, alt, GPR_i386_SIZE(reg_i386), 0, eEncodingUint,   \
+      eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg_i386 }, &value_regs, NULL }
+
+#define DEFINE_FPR(reg, kind1, kind2, kind3, kind4)                \
+    { #reg, NULL, FPR_SIZE(reg), FPR_OFFSET(reg), eEncodingUint,   \
+      eFormatHex, { kind1, kind2, kind3, kind4, fpu_##reg }, NULL, NULL }
+
+#define DEFINE_FP(reg, i)                                          \
+    { #reg#i, NULL, FP_SIZE, LLVM_EXTENSION FPR_OFFSET(reg[i]),    \
+      eEncodingVector, eFormatVectorOfUInt8,                       \
+      { gcc_dwarf_fpu_##reg##i, gcc_dwarf_fpu_##reg##i,            \
+        LLDB_INVALID_REGNUM, gdb_fpu_##reg##i, fpu_##reg##i }, NULL, NULL }
+
+#define DEFINE_XMM(reg, i)                                         \
+    { #reg#i, NULL, XMM_SIZE, LLVM_EXTENSION FPR_OFFSET(reg[i]),   \
+      eEncodingVector, eFormatVectorOfUInt8,                       \
+      { gcc_dwarf_fpu_##reg##i, gcc_dwarf_fpu_##reg##i,            \
+        LLDB_INVALID_REGNUM, gdb_fpu_##reg##i, fpu_##reg##i }, NULL, NULL }
+
+#define DEFINE_YMM(reg, i)                                         \
+    { #reg#i, NULL, YMM_SIZE, LLVM_EXTENSION YMM_OFFSET(reg[i]),   \
+      eEncodingVector, eFormatVectorOfUInt8,                       \
+      { gcc_dwarf_fpu_##reg##i, gcc_dwarf_fpu_##reg##i,            \
+        LLDB_INVALID_REGNUM, gdb_fpu_##reg##i, fpu_##reg##i }, NULL, NULL }
+
+#define DEFINE_DR(reg, i)                                              \
+    { #reg#i, NULL, 0, 0, eEncodingUint, eFormatHex,                   \
+      { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \
+      LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, NULL, NULL }
+
+#define REG_CONTEXT_SIZE (GetGPRSize() + sizeof(RegisterContext_x86_64::FPR))
+
+static RegisterInfo
+g_register_infos[k_num_registers] =
+{
+    // General purpose registers.
+    DEFINE_GPR(rax,    NULL,    gcc_dwarf_gpr_rax,   gcc_dwarf_gpr_rax,   LLDB_INVALID_REGNUM,       gdb_gpr_rax),
+    DEFINE_GPR(rbx,    NULL,    gcc_dwarf_gpr_rbx,   gcc_dwarf_gpr_rbx,   LLDB_INVALID_REGNUM,       gdb_gpr_rbx),
+    DEFINE_GPR(rcx,    NULL,    gcc_dwarf_gpr_rcx,   gcc_dwarf_gpr_rcx,   LLDB_INVALID_REGNUM,       gdb_gpr_rcx),
+    DEFINE_GPR(rdx,    NULL,    gcc_dwarf_gpr_rdx,   gcc_dwarf_gpr_rdx,   LLDB_INVALID_REGNUM,       gdb_gpr_rdx),
+    DEFINE_GPR(rdi,    NULL,    gcc_dwarf_gpr_rdi,   gcc_dwarf_gpr_rdi,   LLDB_INVALID_REGNUM,       gdb_gpr_rdi),
+    DEFINE_GPR(rsi,    NULL,    gcc_dwarf_gpr_rsi,   gcc_dwarf_gpr_rsi,   LLDB_INVALID_REGNUM,       gdb_gpr_rsi),
+    DEFINE_GPR(rbp,    "fp",    gcc_dwarf_gpr_rbp,   gcc_dwarf_gpr_rbp,   LLDB_REGNUM_GENERIC_FP,    gdb_gpr_rbp),
+    DEFINE_GPR(rsp,    "sp",    gcc_dwarf_gpr_rsp,   gcc_dwarf_gpr_rsp,   LLDB_REGNUM_GENERIC_SP,    gdb_gpr_rsp),
+    DEFINE_GPR(r8,     NULL,    gcc_dwarf_gpr_r8,    gcc_dwarf_gpr_r8,    LLDB_INVALID_REGNUM,       gdb_gpr_r8),
+    DEFINE_GPR(r9,     NULL,    gcc_dwarf_gpr_r9,    gcc_dwarf_gpr_r9,    LLDB_INVALID_REGNUM,       gdb_gpr_r9),
+    DEFINE_GPR(r10,    NULL,    gcc_dwarf_gpr_r10,   gcc_dwarf_gpr_r10,   LLDB_INVALID_REGNUM,       gdb_gpr_r10),
+    DEFINE_GPR(r11,    NULL,    gcc_dwarf_gpr_r11,   gcc_dwarf_gpr_r11,   LLDB_INVALID_REGNUM,       gdb_gpr_r11),
+    DEFINE_GPR(r12,    NULL,    gcc_dwarf_gpr_r12,   gcc_dwarf_gpr_r12,   LLDB_INVALID_REGNUM,       gdb_gpr_r12),
+    DEFINE_GPR(r13,    NULL,    gcc_dwarf_gpr_r13,   gcc_dwarf_gpr_r13,   LLDB_INVALID_REGNUM,       gdb_gpr_r13),
+    DEFINE_GPR(r14,    NULL,    gcc_dwarf_gpr_r14,   gcc_dwarf_gpr_r14,   LLDB_INVALID_REGNUM,       gdb_gpr_r14),
+    DEFINE_GPR(r15,    NULL,    gcc_dwarf_gpr_r15,   gcc_dwarf_gpr_r15,   LLDB_INVALID_REGNUM,       gdb_gpr_r15),
+    DEFINE_GPR(rip,    "pc",    gcc_dwarf_gpr_rip,   gcc_dwarf_gpr_rip,   LLDB_REGNUM_GENERIC_PC,    gdb_gpr_rip),
+    DEFINE_GPR(rflags, "flags", LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_REGNUM_GENERIC_FLAGS, gdb_gpr_rflags),
+    DEFINE_GPR(cs,     NULL,    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,       gdb_gpr_cs),
+    DEFINE_GPR(fs,     NULL,    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,       gdb_gpr_fs),
+    DEFINE_GPR(gs,     NULL,    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,       gdb_gpr_gs),
+    DEFINE_GPR(ss,     NULL,    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,       gdb_gpr_ss),
+    DEFINE_GPR(ds,     NULL,    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,       gdb_gpr_ds),
+    DEFINE_GPR(es,     NULL,    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,       gdb_gpr_es),
+    // i386 registers
+    DEFINE_GPR_i386(eax,    rax,    NULL,    gcc_eax,    dwarf_eax,    LLDB_INVALID_REGNUM,       gdb_eax),
+    DEFINE_GPR_i386(ebx,    rbx,    NULL,    gcc_ebx,    dwarf_ebx,    LLDB_INVALID_REGNUM,       gdb_ebx),
+    DEFINE_GPR_i386(ecx,    rcx,    NULL,    gcc_ecx,    dwarf_ecx,    LLDB_INVALID_REGNUM,       gdb_ecx),
+    DEFINE_GPR_i386(edx,    rdx,    NULL,    gcc_edx,    dwarf_edx,    LLDB_INVALID_REGNUM,       gdb_edx),
+    DEFINE_GPR_i386(edi,    rdi,    NULL,    gcc_edi,    dwarf_edi,    LLDB_INVALID_REGNUM,       gdb_edi),
+    DEFINE_GPR_i386(esi,    rsi,    NULL,    gcc_esi,    dwarf_esi,    LLDB_INVALID_REGNUM,       gdb_esi),
+    DEFINE_GPR_i386(ebp,    rbp,    "fp",    gcc_ebp,    dwarf_ebp,    LLDB_REGNUM_GENERIC_FP,    gdb_ebp),
+    DEFINE_GPR_i386(esp,    rsp,    "sp",    gcc_esp,    dwarf_esp,    LLDB_REGNUM_GENERIC_SP,    gdb_esp),
+    DEFINE_GPR_i386(eip,    rip,    "pc",    gcc_eip,    dwarf_eip,    LLDB_REGNUM_GENERIC_PC,    gdb_eip),
+    DEFINE_GPR_i386(eflags, rflags, "flags", gcc_eflags, dwarf_eflags, LLDB_REGNUM_GENERIC_FLAGS, gdb_eflags),
+    // i387 Floating point registers.
+    DEFINE_FPR(fcw,       LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_fcw),
+    DEFINE_FPR(fsw,       LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_fsw),
+    DEFINE_FPR(ftw,       LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ftw),
+    DEFINE_FPR(fop,       LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_fop),
+    DEFINE_FPR(ip,        LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ip),
+    // FIXME: Extract segment from ip.
+    DEFINE_FPR(ip,        LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_cs_64),
+    DEFINE_FPR(dp,        LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_dp),
+    // FIXME: Extract segment from dp.
+    DEFINE_FPR(dp,        LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_ds_64),
+    DEFINE_FPR(mxcsr,     LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gdb_fpu_mxcsr),
+    DEFINE_FPR(mxcsrmask, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
+
+    // FP registers.
+    DEFINE_FP(stmm, 0),
+    DEFINE_FP(stmm, 1),
+    DEFINE_FP(stmm, 2),
+    DEFINE_FP(stmm, 3),
+    DEFINE_FP(stmm, 4),
+    DEFINE_FP(stmm, 5),
+    DEFINE_FP(stmm, 6),
+    DEFINE_FP(stmm, 7),
+
+    // XMM registers
+    DEFINE_XMM(xmm, 0),
+    DEFINE_XMM(xmm, 1),
+    DEFINE_XMM(xmm, 2),
+    DEFINE_XMM(xmm, 3),
+    DEFINE_XMM(xmm, 4),
+    DEFINE_XMM(xmm, 5),
+    DEFINE_XMM(xmm, 6),
+    DEFINE_XMM(xmm, 7),
+    DEFINE_XMM(xmm, 8),
+    DEFINE_XMM(xmm, 9),
+    DEFINE_XMM(xmm, 10),
+    DEFINE_XMM(xmm, 11),
+    DEFINE_XMM(xmm, 12),
+    DEFINE_XMM(xmm, 13),
+    DEFINE_XMM(xmm, 14),
+    DEFINE_XMM(xmm, 15),
+
+    // Copy of YMM registers assembled from xmm and ymmh
+    DEFINE_YMM(ymm, 0),
+    DEFINE_YMM(ymm, 1),
+    DEFINE_YMM(ymm, 2),
+    DEFINE_YMM(ymm, 3),
+    DEFINE_YMM(ymm, 4),
+    DEFINE_YMM(ymm, 5),
+    DEFINE_YMM(ymm, 6),
+    DEFINE_YMM(ymm, 7),
+    DEFINE_YMM(ymm, 8),
+    DEFINE_YMM(ymm, 9),
+    DEFINE_YMM(ymm, 10),
+    DEFINE_YMM(ymm, 11),
+    DEFINE_YMM(ymm, 12),
+    DEFINE_YMM(ymm, 13),
+    DEFINE_YMM(ymm, 14),
+    DEFINE_YMM(ymm, 15),
+
+    // Debug registers for lldb internal use
+    DEFINE_DR(dr, 0),
+    DEFINE_DR(dr, 1),
+    DEFINE_DR(dr, 2),
+    DEFINE_DR(dr, 3),
+    DEFINE_DR(dr, 4),
+    DEFINE_DR(dr, 5),
+    DEFINE_DR(dr, 6),
+    DEFINE_DR(dr, 7)
+};
+
+static bool IsGPR(unsigned reg)
+{
+    return reg <= k_last_gpr;   // GPR's come first.
+}
+
+static bool IsAVX(unsigned reg)
+{
+    return (k_first_avx <= reg && reg <= k_last_avx);
+}
+static bool IsFPR(unsigned reg)
+{
+    return (k_first_fpr <= reg && reg <= k_last_fpr);
+}
+
+
+bool RegisterContext_x86_64::IsFPR(unsigned reg, FPRType fpr_type)
+{
+    bool generic_fpr = ::IsFPR(reg);
+    if (fpr_type == eXSAVE)
+      return generic_fpr || IsAVX(reg);
+
+    return generic_fpr;
+}
+
+RegisterContext_x86_64::RegisterContext_x86_64(Thread &thread,
+                                               uint32_t concrete_frame_idx)
+    : RegisterContextPOSIX(thread, concrete_frame_idx)
+{
+    // Initialize m_iovec to point to the buffer and buffer size
+    // using the conventions of Berkeley style UIO structures, as required
+    // by PTRACE extensions.
+    m_iovec.iov_base = &m_fpr.xstate.xsave;
+    m_iovec.iov_len = sizeof(m_fpr.xstate.xsave);
+
+    ::memset(&m_fpr, 0, sizeof(RegisterContext_x86_64::FPR));
+
+    // elf-core yet to support ReadFPR()
+    ProcessSP base = CalculateProcess();
+    if (base.get()->GetPluginName() ==  ProcessElfCore::GetPluginNameStatic())
+        return;
+    
+    // TODO: Use assembly to call cpuid on the inferior and query ebx or ecx
+    m_fpr_type = eXSAVE; // extended floating-point registers, if available
+    if (false == ReadFPR())
+        m_fpr_type = eFXSAVE; // assume generic floating-point registers
+}
+
+RegisterContext_x86_64::~RegisterContext_x86_64()
+{
+}
+
+void
+RegisterContext_x86_64::Invalidate()
+{
+}
+
+void
+RegisterContext_x86_64::InvalidateAllRegisters()
+{
+}
+
+unsigned
+RegisterContext_x86_64::GetRegisterOffset(unsigned reg)
+{
+    assert(reg < k_num_registers && "Invalid register number.");
+    return GetRegisterInfo()[reg].byte_offset;
+}
+
+unsigned
+RegisterContext_x86_64::GetRegisterSize(unsigned reg)
+{
+    assert(reg < k_num_registers && "Invalid register number.");
+    return GetRegisterInfo()[reg].byte_size;
+}
+
+size_t
+RegisterContext_x86_64::GetRegisterCount()
+{
+    size_t num_registers = k_num_gpr_registers + k_num_fpr_registers;
+    if (m_fpr_type == eXSAVE)
+      return num_registers + k_num_avx_registers;
+    return num_registers;
+}
+
+const RegisterInfo *
+RegisterContext_x86_64::GetRegisterInfo()
+{
+    // Commonly, this method is overridden and g_register_infos is copied and specialized.
+    // So, use GetRegisterInfo() rather than g_register_infos in this scope.
+    return g_register_infos;
+}
+
+const RegisterInfo *
+RegisterContext_x86_64::GetRegisterInfoAtIndex(size_t reg)
+{
+    if (reg < k_num_registers)
+        return &GetRegisterInfo()[reg];
+    else
+        return NULL;
+}
+
+size_t
+RegisterContext_x86_64::GetRegisterSetCount()
+{
+    size_t sets = 0;
+    for (size_t set = 0; set < k_num_register_sets; ++set)
+        if (IsRegisterSetAvailable(set))
+            ++sets;
+
+    return sets;
+}
+
+const RegisterSet *
+RegisterContext_x86_64::GetRegisterSet(size_t set)
+{
+    if (IsRegisterSetAvailable(set))
+        return &g_reg_sets[set];
+    else
+        return NULL;
+}
+
+unsigned
+RegisterContext_x86_64::GetRegisterIndexFromOffset(unsigned offset)
+{
+    unsigned reg;
+    for (reg = 0; reg < k_num_registers; reg++)
+    {
+        if (GetRegisterInfo()[reg].byte_offset == offset)
+            break;
+    }
+    assert(reg < k_num_registers && "Invalid register offset.");
+    return reg;
+}
+
+const char *
+RegisterContext_x86_64::GetRegisterName(unsigned reg)
+{
+    assert(reg < k_num_registers && "Invalid register offset.");
+    return GetRegisterInfo()[reg].name;
+}
+
+lldb::ByteOrder
+RegisterContext_x86_64::GetByteOrder()
+{
+    // Get the target process whose privileged thread was used for the register read.
+    lldb::ByteOrder byte_order = eByteOrderInvalid;
+    Process *process = CalculateProcess().get();
+
+    if (process)
+        byte_order = process->GetByteOrder();
+    return byte_order;
+}
+
+// Parse ymm registers and into xmm.bytes and ymmh.bytes.
+bool RegisterContext_x86_64::CopyYMMtoXSTATE(uint32_t reg, lldb::ByteOrder byte_order)
+{
+    if (!IsAVX(reg))
+        return false;
+
+    if (byte_order == eByteOrderLittle) {
+      ::memcpy(m_fpr.xstate.fxsave.xmm[reg - fpu_ymm0].bytes,
+               m_ymm_set.ymm[reg - fpu_ymm0].bytes,
+               sizeof(RegisterContext_x86_64::XMMReg));
+      ::memcpy(m_fpr.xstate.xsave.ymmh[reg - fpu_ymm0].bytes,
+               m_ymm_set.ymm[reg - fpu_ymm0].bytes + sizeof(RegisterContext_x86_64::XMMReg),
+               sizeof(RegisterContext_x86_64::YMMHReg));
+      return true;
+    }
+
+    if (byte_order == eByteOrderBig) {
+      ::memcpy(m_fpr.xstate.fxsave.xmm[reg - fpu_ymm0].bytes,
+               m_ymm_set.ymm[reg - fpu_ymm0].bytes + sizeof(RegisterContext_x86_64::XMMReg),
+               sizeof(RegisterContext_x86_64::XMMReg));
+      ::memcpy(m_fpr.xstate.xsave.ymmh[reg - fpu_ymm0].bytes,
+               m_ymm_set.ymm[reg - fpu_ymm0].bytes,
+               sizeof(RegisterContext_x86_64::YMMHReg));
+      return true;
+    }
+    return false; // unsupported or invalid byte order
+}
+
+// Concatenate xmm.bytes with ymmh.bytes
+bool RegisterContext_x86_64::CopyXSTATEtoYMM(uint32_t reg, lldb::ByteOrder byte_order)
+{
+    if (!IsAVX(reg))
+        return false;
+
+    if (byte_order == eByteOrderLittle) {
+      ::memcpy(m_ymm_set.ymm[reg - fpu_ymm0].bytes,
+               m_fpr.xstate.fxsave.xmm[reg - fpu_ymm0].bytes,
+               sizeof(RegisterContext_x86_64::XMMReg));
+      ::memcpy(m_ymm_set.ymm[reg - fpu_ymm0].bytes + sizeof(RegisterContext_x86_64::XMMReg),
+               m_fpr.xstate.xsave.ymmh[reg - fpu_ymm0].bytes,
+               sizeof(RegisterContext_x86_64::YMMHReg));
+      return true;
+    }
+    if (byte_order == eByteOrderBig) {
+      ::memcpy(m_ymm_set.ymm[reg - fpu_ymm0].bytes + sizeof(RegisterContext_x86_64::XMMReg),
+               m_fpr.xstate.fxsave.xmm[reg - fpu_ymm0].bytes,
+               sizeof(RegisterContext_x86_64::XMMReg));
+      ::memcpy(m_ymm_set.ymm[reg - fpu_ymm0].bytes,
+               m_fpr.xstate.xsave.ymmh[reg - fpu_ymm0].bytes,
+               sizeof(RegisterContext_x86_64::YMMHReg));
+      return true;
+    }
+    return false; // unsupported or invalid byte order
+}
+
+bool
+RegisterContext_x86_64::IsRegisterSetAvailable(size_t set_index)
+{
+    // Note: Extended register sets are assumed to be at the end of g_reg_sets...
+    size_t num_sets = k_num_register_sets - k_num_extended_register_sets;
+    if (m_fpr_type == eXSAVE) // ...and to start with AVX registers.
+        ++num_sets;
+
+    return (set_index < num_sets);
+}   
+
+bool
+RegisterContext_x86_64::ReadRegister(const RegisterInfo *reg_info, RegisterValue &value)
+{
+    if (!reg_info)
+        return false;
+
+    const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
+
+    if (IsFPR(reg, m_fpr_type)) {
+        if (!ReadFPR())
+            return false;
+    }
+    else {
+        bool success = ReadRegister(reg, value);
+
+        // If an i386 register should be parsed from an x86_64 register...
+        if (success && reg >= k_first_i386 && reg <= k_last_i386)
+            if (value.GetByteSize() > reg_info->byte_size)
+                value.SetType(reg_info); // ...use the type specified by reg_info rather than the uint64_t default
+        return success; 
+    }
+
+    if (reg_info->encoding == eEncodingVector) {
+        ByteOrder byte_order = GetByteOrder();
+
+        if (byte_order != ByteOrder::eByteOrderInvalid) {
+            if (reg >= fpu_stmm0 && reg <= fpu_stmm7) {
+               value.SetBytes(m_fpr.xstate.fxsave.stmm[reg - fpu_stmm0].bytes, reg_info->byte_size, byte_order);
+            }
+            if (reg >= fpu_xmm0 && reg <= fpu_xmm15) {
+                value.SetBytes(m_fpr.xstate.fxsave.xmm[reg - fpu_xmm0].bytes, reg_info->byte_size, byte_order);
+            }
+            if (reg >= fpu_ymm0 && reg <= fpu_ymm15) {
+                // Concatenate ymm using the register halves in xmm.bytes and ymmh.bytes
+                if (m_fpr_type == eXSAVE && CopyXSTATEtoYMM(reg, byte_order))
+                    value.SetBytes(m_ymm_set.ymm[reg - fpu_ymm0].bytes, reg_info->byte_size, byte_order);
+                else
+                    return false;
+            }
+            return value.GetType() == RegisterValue::eTypeBytes;
+        }
+        return false;
+    }
+
+    // Note that lldb uses slightly different naming conventions from sys/user.h
+    switch (reg)
+    {
+    default:
+        return false;
+    case fpu_dp:
+        value = m_fpr.xstate.fxsave.dp;
+        break;
+    case fpu_fcw:
+        value = m_fpr.xstate.fxsave.fcw;
+        break;
+    case fpu_fsw:
+        value = m_fpr.xstate.fxsave.fsw;
+        break;
+    case fpu_ip:
+        value = m_fpr.xstate.fxsave.ip;
+        break;
+    case fpu_fop:
+        value = m_fpr.xstate.fxsave.fop;
+        break;
+    case fpu_ftw:
+        value = m_fpr.xstate.fxsave.ftw;
+        break;
+    case fpu_mxcsr:
+        value = m_fpr.xstate.fxsave.mxcsr;
+        break;
+    case fpu_mxcsrmask:
+        value = m_fpr.xstate.fxsave.mxcsrmask;
+        break;
+    }
+    return true;
+}
+
+bool
+RegisterContext_x86_64::ReadAllRegisterValues(DataBufferSP &data_sp)
+{
+    bool success = false;
+    data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0));
+    if (data_sp && ReadGPR () && ReadFPR ())
+    {
+        uint8_t *dst = data_sp->GetBytes();
+        success = dst != 0;
+
+        if (success) {
+            ::memcpy (dst, &m_gpr, GetGPRSize());
+            dst += GetGPRSize();
+        }
+        if (m_fpr_type == eFXSAVE)
+            ::memcpy (dst, &m_fpr.xstate.fxsave, sizeof(m_fpr.xstate.fxsave));
+        
+        if (m_fpr_type == eXSAVE) {
+            ByteOrder byte_order = GetByteOrder();
+
+            // Assemble the YMM register content from the register halves.
+            for (uint32_t reg = fpu_ymm0; success && reg <= fpu_ymm15; ++reg)
+                success = CopyXSTATEtoYMM(reg, byte_order);
+
+            if (success) {
+                // Copy the extended register state including the assembled ymm registers.
+                ::memcpy (dst, &m_fpr, sizeof(m_fpr));
+            }
+        }
+    }
+    return success;
+}
+
+bool
+RegisterContext_x86_64::WriteRegister(const lldb_private::RegisterInfo *reg_info,
+                                      const lldb_private::RegisterValue &value)
+{
+    const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
+    if (IsGPR(reg)) {
+        return WriteRegister(reg, value);
+    }
+
+    if (IsFPR(reg, m_fpr_type)) {
+        switch (reg)
+        {
+        default:
+            if (reg_info->encoding != eEncodingVector)
+                return false;
+
+            if (reg >= fpu_stmm0 && reg <= fpu_stmm7)
+               ::memcpy (m_fpr.xstate.fxsave.stmm[reg - fpu_stmm0].bytes, value.GetBytes(), value.GetByteSize());
+            
+            if (reg >= fpu_xmm0 && reg <= fpu_xmm15)
+               ::memcpy (m_fpr.xstate.fxsave.xmm[reg - fpu_xmm0].bytes, value.GetBytes(), value.GetByteSize());
+            
+            if (reg >= fpu_ymm0 && reg <= fpu_ymm15) {
+               if (m_fpr_type != eXSAVE)
+                   return false; // the target processor does not support AVX
+
+               // Store ymm register content, and split into the register halves in xmm.bytes and ymmh.bytes
+               ::memcpy (m_ymm_set.ymm[reg - fpu_ymm0].bytes, value.GetBytes(), value.GetByteSize());
+               if (false == CopyYMMtoXSTATE(reg, GetByteOrder()))
+                   return false;
+            }
+            break;
+        case fpu_dp:
+            m_fpr.xstate.fxsave.dp = value.GetAsUInt64();
+            break;
+        case fpu_fcw:
+            m_fpr.xstate.fxsave.fcw = value.GetAsUInt16();
+            break;
+        case fpu_fsw:
+            m_fpr.xstate.fxsave.fsw = value.GetAsUInt16();
+            break;
+        case fpu_ip:
+            m_fpr.xstate.fxsave.ip = value.GetAsUInt64();
+            break;
+        case fpu_fop:
+            m_fpr.xstate.fxsave.fop = value.GetAsUInt16();
+            break;
+        case fpu_ftw:
+            m_fpr.xstate.fxsave.ftw = value.GetAsUInt16();
+            break;
+        case fpu_mxcsr:
+            m_fpr.xstate.fxsave.mxcsr = value.GetAsUInt32();
+            break;
+        case fpu_mxcsrmask:
+            m_fpr.xstate.fxsave.mxcsrmask = value.GetAsUInt32();
+            break;
+        }
+        if (WriteFPR()) {
+            if (IsAVX(reg))
+                return CopyYMMtoXSTATE(reg, GetByteOrder());
+            return true;
+        }
+    }
+    return false;
+}
+
+bool
+RegisterContext_x86_64::WriteAllRegisterValues(const DataBufferSP &data_sp)
+{
+    bool success = false;
+    if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE)
+    {
+        uint8_t *src = data_sp->GetBytes();
+        if (src) {
+            ::memcpy (&m_gpr, src, GetGPRSize());
+
+            if (WriteGPR()) {
+                src += GetGPRSize();
+                if (m_fpr_type == eFXSAVE)
+                    ::memcpy (&m_fpr.xstate.fxsave, src, sizeof(m_fpr.xstate.fxsave));
+                if (m_fpr_type == eXSAVE)
+                    ::memcpy (&m_fpr.xstate.xsave, src, sizeof(m_fpr.xstate.xsave));
+
+                success = WriteFPR();
+                if (success) {
+                    success = true;
+
+                    if (m_fpr_type == eXSAVE) {
+                        ByteOrder byte_order = GetByteOrder();
+
+                        // Parse the YMM register content from the register halves.
+                        for (uint32_t reg = fpu_ymm0; success && reg <= fpu_ymm15; ++reg)
+                            success = CopyYMMtoXSTATE(reg, byte_order);
+                    }
+                }
+            }
+        }
+    }
+    return success;
+}
+
+bool
+RegisterContext_x86_64::UpdateAfterBreakpoint()
+{
+    // PC points one byte past the int3 responsible for the breakpoint.
+    lldb::addr_t pc;
+
+    if ((pc = GetPC()) == LLDB_INVALID_ADDRESS)
+        return false;
+
+    SetPC(pc - 1);
+    return true;
+}
+
+uint32_t
+RegisterContext_x86_64::ConvertRegisterKindToRegisterNumber(uint32_t kind,
+                                                                 uint32_t num)
+{
+    const Process *process = CalculateProcess().get();
+    if (process)
+    {
+        const ArchSpec arch = process->GetTarget().GetArchitecture();;
+        switch (arch.GetCore())
+        {
+        default:
+            assert(false && "CPU type not supported!");
+            break;
+
+        case ArchSpec::eCore_x86_32_i386:
+        case ArchSpec::eCore_x86_32_i486:
+        case ArchSpec::eCore_x86_32_i486sx:
+        {
+            if (kind == eRegisterKindGeneric)
+            {
+                switch (num)
+                {
+                case LLDB_REGNUM_GENERIC_PC:    return gpr_eip;
+                case LLDB_REGNUM_GENERIC_SP:    return gpr_esp;
+                case LLDB_REGNUM_GENERIC_FP:    return gpr_ebp;
+                case LLDB_REGNUM_GENERIC_FLAGS: return gpr_eflags;
+                case LLDB_REGNUM_GENERIC_RA:
+                default:
+                    return LLDB_INVALID_REGNUM;
+                }
+            }
+
+            if (kind == eRegisterKindGCC || kind == eRegisterKindDWARF)
+            {
+                switch (num)
+                {
+                case dwarf_eax:  return gpr_eax;
+                case dwarf_edx:  return gpr_edx;
+                case dwarf_ecx:  return gpr_ecx;
+                case dwarf_ebx:  return gpr_ebx;
+                case dwarf_esi:  return gpr_esi;
+                case dwarf_edi:  return gpr_edi;
+                case dwarf_ebp:  return gpr_ebp;
+                case dwarf_esp:  return gpr_esp;
+                case dwarf_eip:  return gpr_eip;
+                case dwarf_xmm0: return fpu_xmm0;
+                case dwarf_xmm1: return fpu_xmm1;
+                case dwarf_xmm2: return fpu_xmm2;
+                case dwarf_xmm3: return fpu_xmm3;
+                case dwarf_xmm4: return fpu_xmm4;
+                case dwarf_xmm5: return fpu_xmm5;
+                case dwarf_xmm6: return fpu_xmm6;
+                case dwarf_xmm7: return fpu_xmm7;
+                case dwarf_stmm0: return fpu_stmm0;
+                case dwarf_stmm1: return fpu_stmm1;
+                case dwarf_stmm2: return fpu_stmm2;
+                case dwarf_stmm3: return fpu_stmm3;
+                case dwarf_stmm4: return fpu_stmm4;
+                case dwarf_stmm5: return fpu_stmm5;
+                case dwarf_stmm6: return fpu_stmm6;
+                case dwarf_stmm7: return fpu_stmm7;
+                default:
+                    return LLDB_INVALID_REGNUM;
+                }
+            }
+
+            if (kind == eRegisterKindGDB)
+            {
+                switch (num)
+                {
+                case gdb_eax     : return gpr_eax;
+                case gdb_ebx     : return gpr_ebx;
+                case gdb_ecx     : return gpr_ecx;
+                case gdb_edx     : return gpr_edx;
+                case gdb_esi     : return gpr_esi;
+                case gdb_edi     : return gpr_edi;
+                case gdb_ebp     : return gpr_ebp;
+                case gdb_esp     : return gpr_esp;
+                case gdb_eip     : return gpr_eip;
+                case gdb_eflags  : return gpr_eflags;
+                case gdb_cs      : return gpr_cs;
+                case gdb_ss      : return gpr_ss;
+                case gdb_ds      : return gpr_ds;
+                case gdb_es      : return gpr_es;
+                case gdb_fs      : return gpr_fs;
+                case gdb_gs      : return gpr_gs;
+                case gdb_stmm0   : return fpu_stmm0;
+                case gdb_stmm1   : return fpu_stmm1;
+                case gdb_stmm2   : return fpu_stmm2;
+                case gdb_stmm3   : return fpu_stmm3;
+                case gdb_stmm4   : return fpu_stmm4;
+                case gdb_stmm5   : return fpu_stmm5;
+                case gdb_stmm6   : return fpu_stmm6;
+                case gdb_stmm7   : return fpu_stmm7;
+                case gdb_fcw     : return fpu_fcw;
+                case gdb_fsw     : return fpu_fsw;
+                case gdb_ftw     : return fpu_ftw;
+                case gdb_fpu_cs  : return fpu_cs;
+                case gdb_ip      : return fpu_ip;
+                case gdb_fpu_ds  : return fpu_ds; //fpu_fos
+                case gdb_dp      : return fpu_dp; //fpu_foo
+                case gdb_fop     : return fpu_fop;
+                case gdb_xmm0    : return fpu_xmm0;
+                case gdb_xmm1    : return fpu_xmm1;
+                case gdb_xmm2    : return fpu_xmm2;
+                case gdb_xmm3    : return fpu_xmm3;
+                case gdb_xmm4    : return fpu_xmm4;
+                case gdb_xmm5    : return fpu_xmm5;
+                case gdb_xmm6    : return fpu_xmm6;
+                case gdb_xmm7    : return fpu_xmm7;
+                case gdb_mxcsr   : return fpu_mxcsr;
+                default:
+                    return LLDB_INVALID_REGNUM;
+                }
+            }
+            else if (kind == eRegisterKindLLDB)
+            {
+                return num;
+            }
+
+            break;
+        }
+
+        case ArchSpec::eCore_x86_64_x86_64:
+        {
+            if (kind == eRegisterKindGeneric)
+            {
+                switch (num)
+                {
+                case LLDB_REGNUM_GENERIC_PC:    return gpr_rip;
+                case LLDB_REGNUM_GENERIC_SP:    return gpr_rsp;
+                case LLDB_REGNUM_GENERIC_FP:    return gpr_rbp;
+                case LLDB_REGNUM_GENERIC_FLAGS: return gpr_rflags;
+                case LLDB_REGNUM_GENERIC_RA:
+                default:
+                    return LLDB_INVALID_REGNUM;
+                }
+            }
+
+            if (kind == eRegisterKindGCC || kind == eRegisterKindDWARF)
+            {
+                switch (num)
+                {
+                case gcc_dwarf_gpr_rax:  return gpr_rax;
+                case gcc_dwarf_gpr_rdx:  return gpr_rdx;
+                case gcc_dwarf_gpr_rcx:  return gpr_rcx;
+                case gcc_dwarf_gpr_rbx:  return gpr_rbx;
+                case gcc_dwarf_gpr_rsi:  return gpr_rsi;
+                case gcc_dwarf_gpr_rdi:  return gpr_rdi;
+                case gcc_dwarf_gpr_rbp:  return gpr_rbp;
+                case gcc_dwarf_gpr_rsp:  return gpr_rsp;
+                case gcc_dwarf_gpr_r8:   return gpr_r8;
+                case gcc_dwarf_gpr_r9:   return gpr_r9;
+                case gcc_dwarf_gpr_r10:  return gpr_r10;
+                case gcc_dwarf_gpr_r11:  return gpr_r11;
+                case gcc_dwarf_gpr_r12:  return gpr_r12;
+                case gcc_dwarf_gpr_r13:  return gpr_r13;
+                case gcc_dwarf_gpr_r14:  return gpr_r14;
+                case gcc_dwarf_gpr_r15:  return gpr_r15;
+                case gcc_dwarf_gpr_rip:  return gpr_rip;
+                case gcc_dwarf_fpu_xmm0: return fpu_xmm0;
+                case gcc_dwarf_fpu_xmm1: return fpu_xmm1;
+                case gcc_dwarf_fpu_xmm2: return fpu_xmm2;
+                case gcc_dwarf_fpu_xmm3: return fpu_xmm3;
+                case gcc_dwarf_fpu_xmm4: return fpu_xmm4;
+                case gcc_dwarf_fpu_xmm5: return fpu_xmm5;
+                case gcc_dwarf_fpu_xmm6: return fpu_xmm6;
+                case gcc_dwarf_fpu_xmm7: return fpu_xmm7;
+                case gcc_dwarf_fpu_xmm8: return fpu_xmm8;
+                case gcc_dwarf_fpu_xmm9: return fpu_xmm9;
+                case gcc_dwarf_fpu_xmm10: return fpu_xmm10;
+                case gcc_dwarf_fpu_xmm11: return fpu_xmm11;
+                case gcc_dwarf_fpu_xmm12: return fpu_xmm12;
+                case gcc_dwarf_fpu_xmm13: return fpu_xmm13;
+                case gcc_dwarf_fpu_xmm14: return fpu_xmm14;
+                case gcc_dwarf_fpu_xmm15: return fpu_xmm15;
+                case gcc_dwarf_fpu_stmm0: return fpu_stmm0;
+                case gcc_dwarf_fpu_stmm1: return fpu_stmm1;
+                case gcc_dwarf_fpu_stmm2: return fpu_stmm2;
+                case gcc_dwarf_fpu_stmm3: return fpu_stmm3;
+                case gcc_dwarf_fpu_stmm4: return fpu_stmm4;
+                case gcc_dwarf_fpu_stmm5: return fpu_stmm5;
+                case gcc_dwarf_fpu_stmm6: return fpu_stmm6;
+                case gcc_dwarf_fpu_stmm7: return fpu_stmm7;
+                case gcc_dwarf_fpu_ymm0: return fpu_ymm0;
+                case gcc_dwarf_fpu_ymm1: return fpu_ymm1;
+                case gcc_dwarf_fpu_ymm2: return fpu_ymm2;
+                case gcc_dwarf_fpu_ymm3: return fpu_ymm3;
+                case gcc_dwarf_fpu_ymm4: return fpu_ymm4;
+                case gcc_dwarf_fpu_ymm5: return fpu_ymm5;
+                case gcc_dwarf_fpu_ymm6: return fpu_ymm6;
+                case gcc_dwarf_fpu_ymm7: return fpu_ymm7;
+                case gcc_dwarf_fpu_ymm8: return fpu_ymm8;
+                case gcc_dwarf_fpu_ymm9: return fpu_ymm9;
+                case gcc_dwarf_fpu_ymm10: return fpu_ymm10;
+                case gcc_dwarf_fpu_ymm11: return fpu_ymm11;
+                case gcc_dwarf_fpu_ymm12: return fpu_ymm12;
+                case gcc_dwarf_fpu_ymm13: return fpu_ymm13;
+                case gcc_dwarf_fpu_ymm14: return fpu_ymm14;
+                case gcc_dwarf_fpu_ymm15: return fpu_ymm15;
+                default:
+                    return LLDB_INVALID_REGNUM;
+                }
+            }
+
+            if (kind == eRegisterKindGDB)
+            {
+                switch (num)
+                {
+                case gdb_gpr_rax     : return gpr_rax;
+                case gdb_gpr_rbx     : return gpr_rbx;
+                case gdb_gpr_rcx     : return gpr_rcx;
+                case gdb_gpr_rdx     : return gpr_rdx;
+                case gdb_gpr_rsi     : return gpr_rsi;
+                case gdb_gpr_rdi     : return gpr_rdi;
+                case gdb_gpr_rbp     : return gpr_rbp;
+                case gdb_gpr_rsp     : return gpr_rsp;
+                case gdb_gpr_r8      : return gpr_r8;
+                case gdb_gpr_r9      : return gpr_r9;
+                case gdb_gpr_r10     : return gpr_r10;
+                case gdb_gpr_r11     : return gpr_r11;
+                case gdb_gpr_r12     : return gpr_r12;
+                case gdb_gpr_r13     : return gpr_r13;
+                case gdb_gpr_r14     : return gpr_r14;
+                case gdb_gpr_r15     : return gpr_r15;
+                case gdb_gpr_rip     : return gpr_rip;
+                case gdb_gpr_rflags  : return gpr_rflags;
+                case gdb_gpr_cs      : return gpr_cs;
+                case gdb_gpr_ss      : return gpr_ss;
+                case gdb_gpr_ds      : return gpr_ds;
+                case gdb_gpr_es      : return gpr_es;
+                case gdb_gpr_fs      : return gpr_fs;
+                case gdb_gpr_gs      : return gpr_gs;
+                case gdb_fpu_stmm0   : return fpu_stmm0;
+                case gdb_fpu_stmm1   : return fpu_stmm1;
+                case gdb_fpu_stmm2   : return fpu_stmm2;
+                case gdb_fpu_stmm3   : return fpu_stmm3;
+                case gdb_fpu_stmm4   : return fpu_stmm4;
+                case gdb_fpu_stmm5   : return fpu_stmm5;
+                case gdb_fpu_stmm6   : return fpu_stmm6;
+                case gdb_fpu_stmm7   : return fpu_stmm7;
+                case gdb_fpu_fcw     : return fpu_fcw;
+                case gdb_fpu_fsw     : return fpu_fsw;
+                case gdb_fpu_ftw     : return fpu_ftw;
+                case gdb_fpu_cs_64   : return fpu_cs;
+                case gdb_fpu_ip      : return fpu_ip;
+                case gdb_fpu_ds_64   : return fpu_ds;
+                case gdb_fpu_dp      : return fpu_dp;
+                case gdb_fpu_fop     : return fpu_fop;
+                case gdb_fpu_xmm0    : return fpu_xmm0;
+                case gdb_fpu_xmm1    : return fpu_xmm1;
+                case gdb_fpu_xmm2    : return fpu_xmm2;
+                case gdb_fpu_xmm3    : return fpu_xmm3;
+                case gdb_fpu_xmm4    : return fpu_xmm4;
+                case gdb_fpu_xmm5    : return fpu_xmm5;
+                case gdb_fpu_xmm6    : return fpu_xmm6;
+                case gdb_fpu_xmm7    : return fpu_xmm7;
+                case gdb_fpu_xmm8    : return fpu_xmm8;
+                case gdb_fpu_xmm9    : return fpu_xmm9;
+                case gdb_fpu_xmm10   : return fpu_xmm10;
+                case gdb_fpu_xmm11   : return fpu_xmm11;
+                case gdb_fpu_xmm12   : return fpu_xmm12;
+                case gdb_fpu_xmm13   : return fpu_xmm13;
+                case gdb_fpu_xmm14   : return fpu_xmm14;
+                case gdb_fpu_xmm15   : return fpu_xmm15;
+                case gdb_fpu_mxcsr   : return fpu_mxcsr;
+                case gdb_fpu_ymm0    : return fpu_ymm0;
+                case gdb_fpu_ymm1    : return fpu_ymm1;
+                case gdb_fpu_ymm2    : return fpu_ymm2;
+                case gdb_fpu_ymm3    : return fpu_ymm3;
+                case gdb_fpu_ymm4    : return fpu_ymm4;
+                case gdb_fpu_ymm5    : return fpu_ymm5;
+                case gdb_fpu_ymm6    : return fpu_ymm6;
+                case gdb_fpu_ymm7    : return fpu_ymm7;
+                case gdb_fpu_ymm8    : return fpu_ymm8;
+                case gdb_fpu_ymm9    : return fpu_ymm9;
+                case gdb_fpu_ymm10   : return fpu_ymm10;
+                case gdb_fpu_ymm11   : return fpu_ymm11;
+                case gdb_fpu_ymm12   : return fpu_ymm12;
+                case gdb_fpu_ymm13   : return fpu_ymm13;
+                case gdb_fpu_ymm14   : return fpu_ymm14;
+                case gdb_fpu_ymm15   : return fpu_ymm15;
+                default:
+                    return LLDB_INVALID_REGNUM;
+                }
+            }
+            else if (kind == eRegisterKindLLDB)
+            {
+                return num;
+            }
+        }
+        }
+    }
+
+    return LLDB_INVALID_REGNUM;
+}
+
+uint32_t
+RegisterContext_x86_64::NumSupportedHardwareWatchpoints()
+{
+    // Available debug address registers: dr0, dr1, dr2, dr3
+    return 4;
+}
+
+bool
+RegisterContext_x86_64::IsWatchpointVacant(uint32_t hw_index)
+{
+    bool is_vacant = false;
+    RegisterValue value;
+
+    assert(hw_index < NumSupportedHardwareWatchpoints());
+
+    if (m_watchpoints_initialized == false)
+    {
+        // Reset the debug status and debug control registers
+        RegisterValue zero_bits = RegisterValue(uint64_t(0));
+        if (!WriteRegister(dr6, zero_bits) || !WriteRegister(dr7, zero_bits))
+            assert(false && "Could not initialize watchpoint registers");
+        m_watchpoints_initialized = true;
+    }
+
+    if (ReadRegister(dr7, value))
+    {
+        uint64_t val = value.GetAsUInt64();
+        is_vacant = (val & (3 << 2*hw_index)) == 0;
+    }
+
+    return is_vacant;
+}
+
+static uint32_t
+size_and_rw_bits(size_t size, bool read, bool write)
+{
+    uint32_t rw;
+    if (read) {
+        rw = 0x3; // READ or READ/WRITE
+    } else if (write) {
+        rw = 0x1; // WRITE
+    } else {
+        assert(0 && "read and write cannot both be false");
+    }
+
+    switch (size) {
+    case 1:
+        return rw;
+    case 2:
+        return (0x1 << 2) | rw;
+    case 4:
+        return (0x3 << 2) | rw;
+    case 8:
+        return (0x2 << 2) | rw;
+    default:
+        assert(0 && "invalid size, must be one of 1, 2, 4, or 8");
+    }
+}
+
+uint32_t
+RegisterContext_x86_64::SetHardwareWatchpoint(addr_t addr, size_t size,
+                                              bool read, bool write)
+{
+    const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
+    uint32_t hw_index;
+
+    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 false;
+
+    if (read == false && write == false)
+        return false;
+
+    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:
+    //  global enable --. .-- local enable
+    //                  | |
+    //                  v v
+    //      dr0 -> bits{1-0}
+    //      dr1 -> bits{3-2}
+    //      dr2 -> bits{5-4}
+    //      dr3 -> bits{7-6}
+    //
+    // dr7{31-16} encodes the rw/len bits:
+    //  b_x+3, b_x+2, b_x+1, b_x
+    //      where bits{x+1, x} => rw
+    //            0b00: execute, 0b01: write, 0b11: read-or-write,
+    //            0b10: io read-or-write (unused)
+    //      and bits{x+3, x+2} => len
+    //            0b00: 1-byte, 0b01: 2-byte, 0b11: 4-byte, 0b10: 8-byte
+    //
+    //      dr0 -> bits{19-16}
+    //      dr1 -> bits{23-20}
+    //      dr2 -> bits{27-24}
+    //      dr3 -> bits{31-28}
+    if (hw_index < num_hw_watchpoints)
+    {
+        RegisterValue current_dr7_bits;
+
+        if (ReadRegister(dr7, current_dr7_bits))
+        {
+            uint64_t new_dr7_bits = current_dr7_bits.GetAsUInt64() |
+                                    (1 << (2*hw_index) |
+                                    size_and_rw_bits(size, read, write) <<
+                                    (16+4*hw_index));
+
+            if (WriteRegister(dr0 + hw_index, RegisterValue(addr)) &&
+                WriteRegister(dr7, RegisterValue(new_dr7_bits)))
+                return true;
+        }
+    }
+
+    return false;
+}
+
+bool
+RegisterContext_x86_64::ClearHardwareWatchpoint(uint32_t hw_index)
+{
+    if (hw_index < NumSupportedHardwareWatchpoints())
+    {
+        RegisterValue current_dr7_bits;
+
+        if (ReadRegister(dr7, current_dr7_bits))
+        {
+            uint64_t new_dr7_bits = current_dr7_bits.GetAsUInt64() & ~(3 << (2*hw_index));
+
+            if (WriteRegister(dr7, RegisterValue(new_dr7_bits)))
+                return true;
+        }
+    }
+
+    return false;
+}
+
+bool
+RegisterContext_x86_64::IsWatchpointHit(uint32_t hw_index)
+{
+    bool is_hit = false;
+
+    if (m_watchpoints_initialized == false)
+    {
+        // Reset the debug status and debug control registers
+        RegisterValue zero_bits = RegisterValue(uint64_t(0));
+        if (!WriteRegister(dr6, zero_bits) || !WriteRegister(dr7, zero_bits))
+            assert(false && "Could not initialize watchpoint registers");
+        m_watchpoints_initialized = true;
+    }
+
+    if (hw_index < NumSupportedHardwareWatchpoints())
+    {
+        RegisterValue value;
+
+        if (ReadRegister(dr6, value))
+        {
+            uint64_t val = value.GetAsUInt64();
+            is_hit = val & (1 << hw_index);
+        }
+    }
+
+    return is_hit;
+}
+
+addr_t
+RegisterContext_x86_64::GetWatchpointAddress(uint32_t hw_index)
+{
+    addr_t wp_monitor_addr = LLDB_INVALID_ADDRESS;
+
+    if (hw_index < NumSupportedHardwareWatchpoints())
+    {
+        if (!IsWatchpointVacant(hw_index))
+        {
+            RegisterValue value;
+
+            if (ReadRegister(dr0 + hw_index, value))
+                wp_monitor_addr = value.GetAsUInt64();
+        }
+    }
+
+    return wp_monitor_addr;
+}
+
+
+bool
+RegisterContext_x86_64::ClearWatchpointHits()
+{
+    return WriteRegister(dr6, RegisterValue((uint64_t)0));
+}
+
+bool
+RegisterContext_x86_64::HardwareSingleStep(bool enable)
+{
+    enum { TRACE_BIT = 0x100 };
+    uint64_t rflags;
+
+    if ((rflags = ReadRegisterAsUnsigned(gpr_rflags, -1UL)) == -1UL)
+        return false;
+    
+    if (enable)
+    {
+        if (rflags & TRACE_BIT)
+            return true;
+
+        rflags |= TRACE_BIT;
+    }
+    else
+    {
+        if (!(rflags & TRACE_BIT))
+            return false;
+
+        rflags &= ~TRACE_BIT;
+    }
+
+    return WriteRegisterFromUnsigned(gpr_rflags, rflags);
+}
+
+#if defined(__linux__) or defined(__FreeBSD__)
+
+ProcessMonitor &
+RegisterContext_x86_64::GetMonitor()
+{
+    ProcessSP base = CalculateProcess();
+    ProcessPOSIX *process = static_cast<ProcessPOSIX*>(base.get());
+    return process->GetMonitor();
+}
+
+bool
+RegisterContext_x86_64::ReadGPR()
+{
+     ProcessMonitor &monitor = GetMonitor();
+     return monitor.ReadGPR(m_thread.GetID(), &m_gpr, GetGPRSize());
+}
+
+bool
+RegisterContext_x86_64::ReadFPR()
+{
+    ProcessMonitor &monitor = GetMonitor();
+    if (m_fpr_type == eFXSAVE)
+        return monitor.ReadFPR(m_thread.GetID(), &m_fpr.xstate.fxsave, sizeof(m_fpr.xstate.fxsave));
+
+    if (m_fpr_type == eXSAVE)
+        return monitor.ReadRegisterSet(m_thread.GetID(), &m_iovec, sizeof(m_fpr.xstate.xsave), NT_X86_XSTATE);
+    return false;
+}
+
+bool
+RegisterContext_x86_64::WriteGPR()
+{
+    ProcessMonitor &monitor = GetMonitor();
+    return monitor.WriteGPR(m_thread.GetID(), &m_gpr, GetGPRSize());
+}
+
+bool
+RegisterContext_x86_64::WriteFPR()
+{
+    ProcessMonitor &monitor = GetMonitor();
+    if (m_fpr_type == eFXSAVE)
+        return monitor.WriteFPR(m_thread.GetID(), &m_fpr.xstate.fxsave, sizeof(m_fpr.xstate.fxsave));
+
+    if (m_fpr_type == eXSAVE)
+        return monitor.WriteRegisterSet(m_thread.GetID(), &m_iovec, sizeof(m_fpr.xstate.xsave), NT_X86_XSTATE);
+    return false;
+}
+
+bool
+RegisterContext_x86_64::ReadRegister(const unsigned reg,
+                                     RegisterValue &value)
+{
+    ProcessMonitor &monitor = GetMonitor();
+    return monitor.ReadRegisterValue(m_thread.GetID(),
+                                     GetRegisterOffset(reg),
+                                     GetRegisterName(reg),
+                                     GetRegisterSize(reg),
+                                     value);
+}
+
+bool
+RegisterContext_x86_64::WriteRegister(const unsigned reg,
+                                      const RegisterValue &value)
+{
+    ProcessMonitor &monitor = GetMonitor();
+    return monitor.WriteRegisterValue(m_thread.GetID(),
+                                      GetRegisterOffset(reg),
+                                      GetRegisterName(reg),
+                                      value);
+}
+
+#else
+
+bool
+RegisterContext_x86_64::ReadGPR()
+{
+    llvm_unreachable("not implemented");
+    return false;
+}
+
+bool
+RegisterContext_x86_64::ReadFPR()
+{
+    llvm_unreachable("not implemented");
+    return false;
+}
+
+bool
+RegisterContext_x86_64::WriteGPR()
+{
+    llvm_unreachable("not implemented");
+    return false;
+}
+
+bool
+RegisterContext_x86_64::WriteFPR()
+{
+    llvm_unreachable("not implemented");
+    return false;
+}
+
+bool
+RegisterContext_x86_64::ReadRegister(const unsigned reg,
+                                     RegisterValue &value)
+{
+    llvm_unreachable("not implemented");
+    return false;
+}
+
+bool
+RegisterContext_x86_64::WriteRegister(const unsigned reg,
+                                      const RegisterValue &value)
+{
+    llvm_unreachable("not implemented");
+    return false;
+}
+
+#endif
diff --git a/source/Plugins/Process/POSIX/RegisterContext_x86_64.h b/source/Plugins/Process/POSIX/RegisterContext_x86_64.h
new file mode 100644
index 000000000000..9d59bd78e547
--- /dev/null
+++ b/source/Plugins/Process/POSIX/RegisterContext_x86_64.h
@@ -0,0 +1,347 @@
+//===-- RegisterContext_x86_64.h ---------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_RegisterContext_x86_64_H_
+#define liblldb_RegisterContext_x86_64_H_
+
+#include "lldb/Core/Log.h"
+#include "RegisterContextPOSIX.h"
+
+class ProcessMonitor;
+
+// Internal codes for all x86_64 registers.
+enum
+{
+    k_first_gpr,
+    gpr_rax = k_first_gpr,
+    gpr_rbx,
+    gpr_rcx,
+    gpr_rdx,
+    gpr_rdi,
+    gpr_rsi,
+    gpr_rbp,
+    gpr_rsp,
+    gpr_r8,
+    gpr_r9,
+    gpr_r10,
+    gpr_r11,
+    gpr_r12,
+    gpr_r13,
+    gpr_r14,
+    gpr_r15,
+    gpr_rip,
+    gpr_rflags,
+    gpr_cs,
+    gpr_fs,
+    gpr_gs,
+    gpr_ss,
+    gpr_ds,
+    gpr_es,
+    k_first_i386,
+    gpr_eax = k_first_i386,
+    gpr_ebx,
+    gpr_ecx,
+    gpr_edx,
+    gpr_edi,
+    gpr_esi,
+    gpr_ebp,
+    gpr_esp,
+    gpr_eip,
+    gpr_eflags, // eRegisterKindLLDB == 33
+    k_last_i386 = gpr_eflags,
+    k_last_gpr = gpr_eflags,
+
+    k_first_fpr,
+    fpu_fcw = k_first_fpr,
+    fpu_fsw,
+    fpu_ftw,
+    fpu_fop,
+    fpu_ip,
+    fpu_cs,
+    fpu_dp,
+    fpu_ds,
+    fpu_mxcsr,
+    fpu_mxcsrmask,
+    fpu_stmm0,
+    fpu_stmm1,
+    fpu_stmm2,
+    fpu_stmm3,
+    fpu_stmm4,
+    fpu_stmm5,
+    fpu_stmm6,
+    fpu_stmm7,
+    fpu_xmm0,
+    fpu_xmm1,
+    fpu_xmm2,
+    fpu_xmm3,
+    fpu_xmm4,
+    fpu_xmm5,
+    fpu_xmm6,
+    fpu_xmm7,
+    fpu_xmm8,
+    fpu_xmm9,
+    fpu_xmm10,
+    fpu_xmm11,
+    fpu_xmm12,
+    fpu_xmm13,
+    fpu_xmm14,
+    fpu_xmm15,
+    k_last_fpr = fpu_xmm15,
+    k_first_avx,
+    fpu_ymm0 = k_first_avx,
+    fpu_ymm1,
+    fpu_ymm2,
+    fpu_ymm3,
+    fpu_ymm4,
+    fpu_ymm5,
+    fpu_ymm6,
+    fpu_ymm7,
+    fpu_ymm8,
+    fpu_ymm9,
+    fpu_ymm10,
+    fpu_ymm11,
+    fpu_ymm12,
+    fpu_ymm13,
+    fpu_ymm14,
+    fpu_ymm15,
+    k_last_avx = fpu_ymm15,
+
+    dr0,
+    dr1,
+    dr2,
+    dr3,
+    dr4,
+    dr5,
+    dr6,
+    dr7,
+
+    k_num_registers,
+    k_num_gpr_registers = k_last_gpr - k_first_gpr + 1,
+    k_num_fpr_registers = k_last_fpr - k_first_fpr + 1,
+    k_num_avx_registers = k_last_avx - k_first_avx + 1
+};
+
+class RegisterContext_x86_64
+  : public RegisterContextPOSIX
+{
+public:
+    RegisterContext_x86_64 (lldb_private::Thread &thread,
+                            uint32_t concrete_frame_idx);
+
+    ~RegisterContext_x86_64();
+
+    void
+    Invalidate();
+
+    void
+    InvalidateAllRegisters();
+
+    size_t
+    GetRegisterCount();
+
+    virtual size_t
+    GetGPRSize() = 0;
+
+    virtual unsigned
+    GetRegisterSize(unsigned reg);
+
+    virtual unsigned
+    GetRegisterOffset(unsigned reg);
+
+    const lldb_private::RegisterInfo *
+    GetRegisterInfoAtIndex(size_t reg);
+
+    size_t
+    GetRegisterSetCount();
+
+    const lldb_private::RegisterSet *
+    GetRegisterSet(size_t set);
+
+    unsigned
+    GetRegisterIndexFromOffset(unsigned offset);
+
+    const char *
+    GetRegisterName(unsigned reg);
+
+    virtual bool
+    ReadRegister(const lldb_private::RegisterInfo *reg_info,
+                 lldb_private::RegisterValue &value);
+
+    bool
+    ReadAllRegisterValues(lldb::DataBufferSP &data_sp);
+
+    virtual bool
+    WriteRegister(const lldb_private::RegisterInfo *reg_info,
+                  const lldb_private::RegisterValue &value);
+
+    bool
+    WriteAllRegisterValues(const lldb::DataBufferSP &data_sp);
+
+    uint32_t
+    ConvertRegisterKindToRegisterNumber(uint32_t kind, uint32_t num);
+
+    uint32_t
+    NumSupportedHardwareWatchpoints();
+
+    uint32_t
+    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
+    HardwareSingleStep(bool enable);
+
+    bool
+    UpdateAfterBreakpoint();
+
+    bool
+    IsWatchpointVacant(uint32_t hw_index);
+
+    bool
+    IsWatchpointHit (uint32_t hw_index);
+
+    lldb::addr_t
+    GetWatchpointAddress (uint32_t hw_index);
+
+    bool
+    ClearWatchpointHits();
+
+    //---------------------------------------------------------------------------
+    // Generic floating-point registers
+    //---------------------------------------------------------------------------
+
+    struct MMSReg
+    {
+        uint8_t bytes[10];
+        uint8_t pad[6];
+    };
+
+    struct XMMReg
+    {
+        uint8_t bytes[16]; // 128-bits for each XMM register
+    };
+
+    struct FXSAVE
+    {
+        uint16_t fcw;
+        uint16_t fsw;
+        uint16_t ftw;
+        uint16_t fop;
+        uint64_t ip;
+        uint64_t dp;
+        uint32_t mxcsr;
+        uint32_t mxcsrmask;
+        MMSReg   stmm[8];
+        XMMReg   xmm[16];
+        uint32_t padding[24];
+    };
+
+    //---------------------------------------------------------------------------
+    // Extended floating-point registers
+    //---------------------------------------------------------------------------
+    struct YMMHReg
+    {
+        uint8_t  bytes[16];     // 16 * 8 bits for the high bytes of each YMM register
+    };
+
+    struct YMMReg
+    {
+        uint8_t  bytes[32];     // 16 * 16 bits for each YMM register
+    };
+
+    struct YMM
+    {
+        YMMReg   ymm[16];       // assembled from ymmh and xmm registers
+    };
+
+    struct XSAVE_HDR
+    {
+        uint64_t  xstate_bv;    // OS enabled xstate mask to determine the extended states supported by the processor
+        uint64_t  reserved1[2];
+        uint64_t  reserved2[5];
+    } __attribute__((packed));
+
+    // x86 extensions to FXSAVE (i.e. for AVX processors) 
+    struct XSAVE 
+    {
+        FXSAVE    i387;         // floating point registers typical in i387_fxsave_struct
+        XSAVE_HDR header;       // The xsave_hdr_struct can be used to determine if the following extensions are usable
+        YMMHReg   ymmh[16];     // High 16 bytes of each of 16 YMM registers (the low bytes are in FXSAVE.xmm for compatibility with SSE)
+        // Slot any extensions to the register file here
+    } __attribute__((packed, aligned (64)));
+
+    struct IOVEC
+    {
+        void    *iov_base;      // pointer to XSAVE
+        size_t   iov_len;       // sizeof(XSAVE)
+    };
+
+    //---------------------------------------------------------------------------
+    // Note: prefer kernel definitions over user-land
+    //---------------------------------------------------------------------------
+    enum FPRType
+    {
+        eNotValid = 0,
+        eFSAVE,  // TODO
+        eFXSAVE,
+        eSOFT,   // TODO
+        eXSAVE
+    };
+
+    // Floating-point registers
+    struct FPR
+    {
+        // Thread state for the floating-point unit of the processor read by ptrace.
+        union XSTATE {
+            FXSAVE   fxsave;    // Generic floating-point registers.
+            XSAVE    xsave;     // x86 extended processor state.
+        } xstate;
+    };
+
+protected:
+    // Determines if an extended register set is supported on the processor running the inferior process.
+    virtual bool
+    IsRegisterSetAvailable(size_t set_index);
+
+    virtual const lldb_private::RegisterInfo *
+    GetRegisterInfo();
+
+    virtual bool
+    ReadRegister(const unsigned reg, lldb_private::RegisterValue &value);
+
+    virtual bool
+    WriteRegister(const unsigned reg, const lldb_private::RegisterValue &value);
+
+private:
+    uint64_t m_gpr[k_num_gpr_registers]; // general purpose registers.
+    FPRType  m_fpr_type;                 // determines the type of data stored by union FPR, if any.
+    FPR      m_fpr;                      // floating-point registers including extended register sets.
+    IOVEC    m_iovec;                    // wrapper for xsave.
+    YMM      m_ymm_set;                  // copy of ymmh and xmm register halves.
+
+    ProcessMonitor &GetMonitor();
+    lldb::ByteOrder GetByteOrder();
+
+    bool CopyXSTATEtoYMM(uint32_t reg, lldb::ByteOrder byte_order);
+    bool CopyYMMtoXSTATE(uint32_t reg, lldb::ByteOrder byte_order);
+    bool IsFPR(unsigned reg, FPRType fpr_type);
+
+    bool ReadGPR();
+    bool ReadFPR();
+
+    bool WriteGPR();
+    bool WriteFPR();
+};
+
+#endif // #ifndef liblldb_RegisterContext_x86_64_H_
diff --git a/source/Plugins/Process/Utility/ARMDefines.h b/source/Plugins/Process/Utility/ARMDefines.h
new file mode 100644
index 000000000000..4b1f06a2f9cd
--- /dev/null
+++ b/source/Plugins/Process/Utility/ARMDefines.h
@@ -0,0 +1,110 @@
+//===-- lldb_ARMDefines.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_ARMDefines_h_
+#define lldb_ARMDefines_h_
+
+// Common defintions for the ARM/Thumb Instruction Set Architecture.
+
+namespace lldb_private {
+
+// ARM shifter types
+typedef enum
+{
+    SRType_LSL,
+    SRType_LSR,
+    SRType_ASR,
+    SRType_ROR,
+    SRType_RRX,
+    SRType_Invalid
+} ARM_ShifterType;
+
+// ARM conditions          // Meaning (integer)         Meaning (floating-point)      Condition flags
+#define COND_EQ     0x0    // Equal                     Equal                         Z == 1
+#define COND_NE     0x1    // Not equal                 Not equal, or unordered       Z == 0
+#define COND_CS     0x2    // Carry set                 >, ==, or unordered           C == 1
+#define COND_HS     0x2
+#define COND_CC     0x3    // Carry clear               Less than                     C == 0
+#define COND_LO     0x3
+#define COND_MI     0x4    // Minus, negative           Less than                     N == 1
+#define COND_PL     0x5    // Plus, positive or zero    >, ==, or unordered           N == 0
+#define COND_VS     0x6    // Overflow                  Unordered                     V == 1
+#define COND_VC     0x7    // No overflow               Not unordered                 V == 0
+#define COND_HI     0x8    // Unsigned higher           Greater than, or unordered    C == 1 and Z == 0
+#define COND_LS     0x9    // Unsigned lower or same    Less than or equal            C == 0 or Z == 1
+#define COND_GE     0xA    // Greater than or equal     Greater than or equal         N == V
+#define COND_LT     0xB    // Less than                 Less than, or unordered       N != V
+#define COND_GT     0xC    // Greater than              Greater than                  Z == 0 and N == V
+#define COND_LE     0xD    // Less than or equal        <, ==, or unordered           Z == 1 or N != V
+#define COND_AL     0xE    // Always (unconditional)    Always (unconditional)        Any
+#define COND_UNCOND 0xF
+
+static inline const char *ARMCondCodeToString(uint32_t CC)
+{
+    switch (CC) {
+    default: assert(0 && "Unknown condition code");
+    case COND_EQ:  return "eq";
+    case COND_NE:  return "ne";
+    case COND_HS:  return "hs";
+    case COND_LO:  return "lo";
+    case COND_MI:  return "mi";
+    case COND_PL:  return "pl";
+    case COND_VS:  return "vs";
+    case COND_VC:  return "vc";
+    case COND_HI:  return "hi";
+    case COND_LS:  return "ls";
+    case COND_GE:  return "ge";
+    case COND_LT:  return "lt";
+    case COND_GT:  return "gt";
+    case COND_LE:  return "le";
+    case COND_AL:  return "al";
+    }
+}
+
+// Bit positions for CPSR
+#define CPSR_T_POS  5
+#define CPSR_F_POS  6
+#define CPSR_I_POS  7
+#define CPSR_A_POS  8
+#define CPSR_E_POS  9
+#define CPSR_J_POS 24
+#define CPSR_Q_POS 27
+#define CPSR_V_POS 28
+#define CPSR_C_POS 29
+#define CPSR_Z_POS 30
+#define CPSR_N_POS 31
+
+// CPSR mode definitions
+#define CPSR_MODE_USR  0x10u
+#define CPSR_MODE_FIQ  0x11u
+#define CPSR_MODE_IRQ  0x12u
+#define CPSR_MODE_SVC  0x13u
+#define CPSR_MODE_ABT  0x17u
+#define CPSR_MODE_UND  0x1bu
+#define CPSR_MODE_SYS  0x1fu
+    
+// Masks for CPSR
+#define MASK_CPSR_MODE_MASK (0x0000001fu)
+#define MASK_CPSR_IT_MASK   (0x0600fc00u)
+#define MASK_CPSR_T         (1u << CPSR_T_POS)
+#define MASK_CPSR_F         (1u << CPSR_F_POS)
+#define MASK_CPSR_I         (1u << CPSR_I_POS)
+#define MASK_CPSR_A         (1u << CPSR_A_POS)
+#define MASK_CPSR_E         (1u << CPSR_E_POS)
+#define MASK_CPSR_GE_MASK   (0x000f0000u)
+#define MASK_CPSR_J         (1u << CPSR_J_POS)
+#define MASK_CPSR_Q         (1u << CPSR_Q_POS)
+#define MASK_CPSR_V         (1u << CPSR_V_POS)
+#define MASK_CPSR_C         (1u << CPSR_C_POS)
+#define MASK_CPSR_Z         (1u << CPSR_Z_POS)
+#define MASK_CPSR_N         (1u << CPSR_N_POS)
+
+}   // namespace lldb_private
+
+#endif  // lldb_ARMDefines_h_
diff --git a/source/Plugins/Process/Utility/ARMUtils.h b/source/Plugins/Process/Utility/ARMUtils.h
new file mode 100644
index 000000000000..76d64e15a53e
--- /dev/null
+++ b/source/Plugins/Process/Utility/ARMUtils.h
@@ -0,0 +1,394 @@
+//===-- ARMUtils.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_ARMUtils_h_
+#define lldb_ARMUtils_h_
+
+#include "ARMDefines.h"
+#include "InstructionUtils.h"
+#include "llvm/Support/MathExtras.h" // for SignExtend64 template function
+
+// Common utilities for the ARM/Thumb Instruction Set Architecture.
+
+namespace lldb_private {
+
+static inline uint32_t Align(uint32_t val, uint32_t alignment)
+{
+    return alignment * (val / alignment);
+}
+
+static inline uint32_t DecodeImmShift(const uint32_t type, const uint32_t imm5, ARM_ShifterType &shift_t)
+{
+    switch (type)
+    {
+    default:
+        //assert(0 && "Invalid shift type");
+    case 0:
+        shift_t = SRType_LSL;
+        return imm5;
+    case 1:
+        shift_t = SRType_LSR;
+        return (imm5 == 0 ? 32 : imm5);
+    case 2:
+        shift_t = SRType_ASR;
+        return (imm5 == 0 ? 32 : imm5);
+    case 3:
+        if (imm5 == 0)
+        {
+            shift_t = SRType_RRX;
+            return 1;
+        }
+        else
+        {
+            shift_t = SRType_ROR;
+            return imm5;
+        }
+    }
+    shift_t = SRType_Invalid;
+    return UINT32_MAX;
+
+}
+
+// A8.6.35 CMP (register) -- Encoding T3
+// Convenience function.
+static inline uint32_t DecodeImmShiftThumb(const uint32_t opcode, ARM_ShifterType &shift_t)
+{
+    return DecodeImmShift(Bits32(opcode, 5, 4), Bits32(opcode, 14, 12)<<2 | Bits32(opcode, 7, 6), shift_t);
+}
+
+// A8.6.35 CMP (register) -- Encoding A1
+// Convenience function.
+static inline uint32_t DecodeImmShiftARM(const uint32_t opcode, ARM_ShifterType &shift_t)
+{
+    return DecodeImmShift(Bits32(opcode, 6, 5), Bits32(opcode, 11, 7), shift_t);
+}
+
+static inline uint32_t DecodeImmShift(const ARM_ShifterType shift_t, const uint32_t imm5)
+{
+    ARM_ShifterType dont_care;
+    return DecodeImmShift(shift_t, imm5, dont_care);
+}
+
+static inline ARM_ShifterType DecodeRegShift(const uint32_t type)
+{
+    switch (type) {
+    default:
+        //assert(0 && "Invalid shift type");
+        return SRType_Invalid;
+    case 0:
+        return SRType_LSL;
+    case 1:
+        return SRType_LSR;
+    case 2:
+        return SRType_ASR;
+    case 3:
+        return SRType_ROR;
+    }
+}
+
+static inline uint32_t LSL_C(const uint32_t value, const uint32_t amount, uint32_t &carry_out, bool *success)
+{
+    if (amount == 0) {
+        *success = false;
+        return 0;
+    }
+    *success = true;
+    carry_out = amount <= 32 ? Bit32(value, 32 - amount) : 0;
+    return value << amount;
+}
+
+static inline uint32_t LSL(const uint32_t value, const uint32_t amount, bool *success)
+{
+    *success = true;
+    if (amount == 0)
+        return value;
+    uint32_t dont_care;
+    uint32_t result = LSL_C(value, amount, dont_care, success);
+    if (*success)
+        return result;
+    else
+        return 0;
+}
+
+static inline uint32_t LSR_C(const uint32_t value, const uint32_t amount, uint32_t &carry_out, bool *success)
+{
+    if (amount == 0) {
+        *success = false;
+        return 0;
+    }
+    *success = true;
+    carry_out = amount <= 32 ? Bit32(value, amount - 1) : 0;
+    return value >> amount;
+}
+
+static inline uint32_t LSR(const uint32_t value, const uint32_t amount, bool *success)
+{
+    *success = true;
+    if (amount == 0)
+        return value;
+    uint32_t dont_care;
+    uint32_t result = LSR_C(value, amount, dont_care, success);
+    if (*success)
+        return result;
+    else
+        return 0;
+}
+
+static inline uint32_t ASR_C(const uint32_t value, const uint32_t amount, uint32_t &carry_out, bool *success)
+{
+    if (amount == 0 || amount > 32) {
+        *success = false;
+        return 0;
+    }
+    *success = true;
+    bool negative = BitIsSet(value, 31);
+    if (amount <= 32)
+    {
+        carry_out = Bit32(value, amount - 1);
+        int64_t extended = llvm::SignExtend64<32>(value);
+        return UnsignedBits(extended, amount + 31, amount);
+    }
+    else
+    {
+        carry_out = (negative ? 1 : 0);
+        return (negative ? 0xffffffff : 0);
+    }
+}
+
+static inline uint32_t ASR(const uint32_t value, const uint32_t amount, bool *success)
+{
+    *success = true;
+    if (amount == 0)
+        return value;
+    uint32_t dont_care;
+    uint32_t result = ASR_C(value, amount, dont_care, success);
+    if (*success)
+        return result;
+    else
+        return 0;
+}
+
+static inline uint32_t ROR_C(const uint32_t value, const uint32_t amount, uint32_t &carry_out, bool *success)
+{
+    if (amount == 0) {
+        *success = false;
+        return 0;
+    }
+    *success = true;
+    uint32_t amt = amount % 32;
+    uint32_t result = Rotr32(value, amt);
+    carry_out = Bit32(value, 31);
+    return result;
+}
+
+static inline uint32_t ROR(const uint32_t value, const uint32_t amount, bool *success)
+{
+    *success = true;
+    if (amount == 0)
+        return value;
+    uint32_t dont_care;
+    uint32_t result = ROR_C(value, amount, dont_care, success);
+    if (*success)
+        return result;
+    else
+        return 0;
+}
+
+static inline uint32_t RRX_C(const uint32_t value, const uint32_t carry_in, uint32_t &carry_out, bool *success)
+{
+    *success = true;
+    carry_out = Bit32(value, 0);
+    return Bit32(carry_in, 0) << 31 | Bits32(value, 31, 1);
+}
+
+static inline uint32_t RRX(const uint32_t value, const uint32_t carry_in, bool *success)
+{
+    *success = true;
+    uint32_t dont_care;
+    uint32_t result = RRX_C(value, carry_in, dont_care, success);
+    if (*success)
+        return result;
+    else
+        return 0;
+}
+
+static inline uint32_t Shift_C(const uint32_t value, ARM_ShifterType type, const uint32_t amount,
+                               const uint32_t carry_in, uint32_t &carry_out, bool *success)
+{
+    if (type == SRType_RRX && amount != 1) {
+        *success = false;
+        return 0;
+    }
+    *success = true;
+
+    if (amount == 0) {
+        carry_out = carry_in;
+        return value;
+    }
+    uint32_t result;
+    switch (type) {
+    case SRType_LSL:
+        result = LSL_C(value, amount, carry_out, success);
+        break;
+    case SRType_LSR:
+        result = LSR_C(value, amount, carry_out, success);
+        break;
+    case SRType_ASR:
+        result = ASR_C(value, amount, carry_out, success);
+        break;
+    case SRType_ROR:
+        result = ROR_C(value, amount, carry_out, success);
+        break;
+    case SRType_RRX:
+        result = RRX_C(value, carry_in, carry_out, success);
+        break;
+    default:
+        *success = false;
+        break;
+    }
+    if (*success)
+        return result;
+    else
+        return 0;
+}
+
+static inline uint32_t Shift(const uint32_t value, ARM_ShifterType type, const uint32_t amount,
+                             const uint32_t carry_in, bool *success)
+{
+    // Don't care about carry out in this case.
+    uint32_t dont_care;
+    uint32_t result = Shift_C(value, type, amount, carry_in, dont_care, success);
+    if (*success)
+        return result;
+    else
+        return 0;
+}
+
+static inline uint32_t bits(const uint32_t val, const uint32_t msbit, const uint32_t lsbit)
+{
+    return Bits32(val, msbit, lsbit);
+}
+
+static inline uint32_t bit(const uint32_t val, const uint32_t msbit)
+{
+    return bits(val, msbit, msbit);
+}
+
+static uint32_t ror(uint32_t val, uint32_t N, uint32_t shift)
+{
+    uint32_t m = shift % N;
+    return (val >> m) | (val << (N - m));
+}
+
+// (imm32, carry_out) = ARMExpandImm_C(imm12, carry_in)
+static inline uint32_t ARMExpandImm_C(uint32_t opcode, uint32_t carry_in, uint32_t &carry_out)
+{
+    uint32_t imm32;                         // the expanded result
+    uint32_t imm = bits(opcode, 7, 0);      // immediate value
+    uint32_t amt = 2 * bits(opcode, 11, 8); // rotate amount
+    if (amt == 0)
+    {
+        imm32 = imm;
+        carry_out = carry_in;
+    }
+    else
+    {
+        imm32 = ror(imm, 32, amt);
+        carry_out = Bit32(imm32, 31);
+    }
+    return imm32;
+}
+
+static inline uint32_t ARMExpandImm(uint32_t opcode)
+{
+    // 'carry_in' argument to following function call does not affect the imm32 result.
+    uint32_t carry_in = 0;
+    uint32_t carry_out;
+    return ARMExpandImm_C(opcode, carry_in, carry_out);
+}
+
+// (imm32, carry_out) = ThumbExpandImm_C(imm12, carry_in)
+static inline uint32_t ThumbExpandImm_C(uint32_t opcode, uint32_t carry_in, uint32_t &carry_out)
+{
+    uint32_t imm32; // the expaned result
+    const uint32_t i = bit(opcode, 26);
+    const uint32_t imm3 = bits(opcode, 14, 12);
+    const uint32_t abcdefgh = bits(opcode, 7, 0);
+    const uint32_t imm12 = i << 11 | imm3 << 8 | abcdefgh;
+
+    if (bits(imm12, 11, 10) == 0)
+    {
+        switch (bits(imm12, 9, 8)) {
+        default: // Keep static analyzer happy with a default case
+        case 0:
+            imm32 = abcdefgh;
+            break;
+
+        case 1:
+            imm32 = abcdefgh << 16 | abcdefgh;
+            break;
+
+        case 2:
+            imm32 = abcdefgh << 24 | abcdefgh << 8;
+            break;
+
+        case 3:
+            imm32 = abcdefgh  << 24 | abcdefgh << 16 | abcdefgh << 8 | abcdefgh; 
+            break;
+        }
+        carry_out = carry_in;
+    }
+    else
+    {
+        const uint32_t unrotated_value = 0x80 | bits(imm12, 6, 0);
+        imm32 = ror(unrotated_value, 32, bits(imm12, 11, 7));
+        carry_out = Bit32(imm32, 31);
+    }
+    return imm32;
+}
+
+static inline uint32_t ThumbExpandImm(uint32_t opcode)
+{
+    // 'carry_in' argument to following function call does not affect the imm32 result.
+    uint32_t carry_in = 0;
+    uint32_t carry_out;
+    return ThumbExpandImm_C(opcode, carry_in, carry_out);
+}
+
+// imm32 = ZeroExtend(i:imm3:imm8, 32)
+static inline uint32_t ThumbImm12(uint32_t opcode)
+{
+  const uint32_t i = bit(opcode, 26);
+  const uint32_t imm3 = bits(opcode, 14, 12);
+  const uint32_t imm8 = bits(opcode, 7, 0);
+  const uint32_t imm12 = i << 11 | imm3 << 8 | imm8;
+  return imm12;
+}
+
+// imm32 = ZeroExtend(imm7:'00', 32)
+static inline uint32_t ThumbImm7Scaled(uint32_t opcode)
+{
+  const uint32_t imm7 = bits(opcode, 6, 0);
+  return imm7 * 4;
+}
+
+// imm32 = ZeroExtend(imm8:'00', 32)
+static inline uint32_t ThumbImm8Scaled(uint32_t opcode)
+{
+  const uint32_t imm8 = bits(opcode, 7, 0);
+  return imm8 * 4;
+}
+
+// This function performs the check for the register numbers 13 and 15 that are
+// not permitted for many Thumb register specifiers.
+static inline bool BadReg(uint32_t n) { return n == 13 || n == 15; }
+
+}   // namespace lldb_private
+
+#endif  // lldb_ARMUtils_h_
diff --git a/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp b/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
new file mode 100644
index 000000000000..0c95d66cef94
--- /dev/null
+++ b/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp
@@ -0,0 +1,279 @@
+//===-- DynamicRegisterInfo.cpp ----------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/lldb-python.h"
+
+#include "DynamicRegisterInfo.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Interpreter/Args.h"
+
+#ifndef LLDB_DISABLE_PYTHON
+#include "lldb/Interpreter/PythonDataObjects.h"
+#endif
+
+using namespace lldb;
+using namespace lldb_private;
+
+DynamicRegisterInfo::DynamicRegisterInfo () :
+    m_regs (),
+    m_sets (),
+    m_set_reg_nums (),
+    m_set_names (),
+    m_reg_data_byte_size (0)
+{
+}
+
+DynamicRegisterInfo::DynamicRegisterInfo (const lldb_private::PythonDictionary &dict) :
+    m_regs (),
+    m_sets (),
+    m_set_reg_nums (),
+    m_set_names (),
+    m_reg_data_byte_size (0)
+{
+    SetRegisterInfo (dict);
+}
+
+DynamicRegisterInfo::~DynamicRegisterInfo ()
+{
+}
+
+
+size_t
+DynamicRegisterInfo::SetRegisterInfo (const lldb_private::PythonDictionary &dict)
+{
+#ifndef LLDB_DISABLE_PYTHON
+    PythonList sets (dict.GetItemForKey("sets"));
+    if (sets)
+    {
+        const uint32_t num_sets = sets.GetSize();
+        for (uint32_t i=0; i<num_sets; ++i)
+        {
+            PythonString py_set_name(sets.GetItemAtIndex(i));
+            ConstString set_name;
+            if (py_set_name)
+                set_name.SetCString(py_set_name.GetString());
+            if (set_name)
+            {
+                RegisterSet new_set = { set_name.AsCString(), NULL, 0, NULL };
+                m_sets.push_back (new_set);
+            }
+            else
+            {
+                Clear();
+                return 0;
+            }
+        }
+        m_set_reg_nums.resize(m_sets.size());
+    }
+    PythonList regs (dict.GetItemForKey("registers"));
+    if (regs)
+    {
+        const uint32_t num_regs = regs.GetSize();
+        PythonString name_pystr("name");
+        PythonString altname_pystr("alt-name");
+        PythonString bitsize_pystr("bitsize");
+        PythonString offset_pystr("offset");
+        PythonString encoding_pystr("encoding");
+        PythonString format_pystr("format");
+        PythonString set_pystr("set");
+        PythonString gcc_pystr("gcc");
+        PythonString dwarf_pystr("dwarf");
+        PythonString generic_pystr("generic");
+        for (uint32_t i=0; i<num_regs; ++i)
+        {
+            PythonDictionary reg_info_dict(regs.GetItemAtIndex(i));
+            if (reg_info_dict)
+            {
+                // { 'name':'rcx'       , 'bitsize' :  64, 'offset' :  16, 'encoding':'uint'  , 'format':'hex'         , 'set': 0, 'gcc' : 2, 'dwarf' : 2, 'generic':'arg4', 'alt-name':'arg4', },
+                RegisterInfo reg_info;
+                bzero (&reg_info, sizeof(reg_info));
+                
+                reg_info.name = ConstString (reg_info_dict.GetItemForKeyAsString(name_pystr)).GetCString();
+                if (reg_info.name == NULL)
+                {
+                    Clear();
+                    return 0;
+                }
+                    
+                reg_info.alt_name = ConstString (reg_info_dict.GetItemForKeyAsString(altname_pystr)).GetCString();
+                
+                reg_info.byte_offset = reg_info_dict.GetItemForKeyAsInteger(offset_pystr, UINT32_MAX);
+
+                if (reg_info.byte_offset == UINT32_MAX)
+                {
+                    Clear();
+                    return 0;
+                }
+                reg_info.byte_size = reg_info_dict.GetItemForKeyAsInteger(bitsize_pystr, 0) / 8;
+                
+                if (reg_info.byte_size == 0)
+                {
+                    Clear();
+                    return 0;
+                }
+                
+                const char *format_cstr = reg_info_dict.GetItemForKeyAsString(format_pystr);
+                if (format_cstr)
+                {
+                    if (Args::StringToFormat(format_cstr, reg_info.format, NULL).Fail())
+                    {
+                        Clear();
+                        return 0;
+                    }
+                }
+                else
+                    reg_info.format = eFormatHex;
+                    
+                const char *encoding_cstr = reg_info_dict.GetItemForKeyAsString(encoding_pystr);
+                if (encoding_cstr)
+                    reg_info.encoding = Args::StringToEncoding (encoding_cstr, eEncodingUint);
+                else
+                    reg_info.encoding = eEncodingUint;
+
+                const int64_t set = reg_info_dict.GetItemForKeyAsInteger(set_pystr, -1);
+                if (set >= m_sets.size())
+                {
+                    Clear();
+                    return 0;
+                }
+
+                reg_info.kinds[lldb::eRegisterKindLLDB]    = i;
+                reg_info.kinds[lldb::eRegisterKindGDB]     = i;
+                reg_info.kinds[lldb::eRegisterKindGCC]     = reg_info_dict.GetItemForKeyAsInteger(gcc_pystr, LLDB_INVALID_REGNUM);
+                reg_info.kinds[lldb::eRegisterKindDWARF]   = reg_info_dict.GetItemForKeyAsInteger(dwarf_pystr, LLDB_INVALID_REGNUM);
+                reg_info.kinds[lldb::eRegisterKindGeneric] = Args::StringToGenericRegister (reg_info_dict.GetItemForKeyAsString(generic_pystr));
+                const size_t end_reg_offset = reg_info.byte_offset + reg_info.byte_size;
+                if (m_reg_data_byte_size < end_reg_offset)
+                    m_reg_data_byte_size = end_reg_offset;
+
+                m_regs.push_back (reg_info);
+                m_set_reg_nums[set].push_back(i);
+
+            }
+            else
+            {
+                Clear();
+                return 0;
+            }
+        }
+        Finalize ();
+    }
+#endif
+    return 0;
+}
+
+
+void
+DynamicRegisterInfo::AddRegister (RegisterInfo &reg_info,
+                                  ConstString &reg_name, 
+                                  ConstString &reg_alt_name, 
+                                  ConstString &set_name)
+{
+    const uint32_t reg_num = m_regs.size();
+    reg_info.name = reg_name.AsCString();
+    assert (reg_info.name);
+    reg_info.alt_name = reg_alt_name.AsCString(NULL);
+    m_regs.push_back (reg_info);
+    uint32_t set = GetRegisterSetIndexByName (set_name, true);
+    assert (set < m_sets.size());
+    assert (set < m_set_reg_nums.size());
+    assert (set < m_set_names.size());
+    m_set_reg_nums[set].push_back(reg_num);
+    size_t end_reg_offset = reg_info.byte_offset + reg_info.byte_size;
+    if (m_reg_data_byte_size < end_reg_offset)
+        m_reg_data_byte_size = end_reg_offset;
+}
+
+void
+DynamicRegisterInfo::Finalize ()
+{
+    for (uint32_t set = 0; set < m_sets.size(); ++set)
+    {
+        assert (m_sets.size() == m_set_reg_nums.size());
+        m_sets[set].num_registers = m_set_reg_nums[set].size();
+        m_sets[set].registers = &m_set_reg_nums[set][0];
+    }
+}
+
+size_t
+DynamicRegisterInfo::GetNumRegisters() const
+{
+    return m_regs.size();
+}
+
+size_t
+DynamicRegisterInfo::GetNumRegisterSets() const
+{
+    return m_sets.size();
+}
+
+size_t
+DynamicRegisterInfo::GetRegisterDataByteSize() const
+{
+    return m_reg_data_byte_size;
+}
+
+const RegisterInfo *
+DynamicRegisterInfo::GetRegisterInfoAtIndex (uint32_t i) const
+{
+    if (i < m_regs.size())
+        return &m_regs[i];
+    return NULL;
+}
+
+const RegisterSet *
+DynamicRegisterInfo::GetRegisterSet (uint32_t i) const
+{
+    if (i < m_sets.size())
+        return &m_sets[i];
+    return NULL;
+}
+
+uint32_t
+DynamicRegisterInfo::GetRegisterSetIndexByName (ConstString &set_name, bool can_create)
+{
+    name_collection::iterator pos, end = m_set_names.end();
+    for (pos = m_set_names.begin(); pos != end; ++pos)
+    {
+        if (*pos == set_name)
+            return std::distance (m_set_names.begin(), pos);
+    }
+    
+    m_set_names.push_back(set_name);
+    m_set_reg_nums.resize(m_set_reg_nums.size()+1);
+    RegisterSet new_set = { set_name.AsCString(), NULL, 0, NULL };
+    m_sets.push_back (new_set);
+    return m_sets.size() - 1;
+}
+
+uint32_t
+DynamicRegisterInfo::ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num) const
+{
+    reg_collection::const_iterator pos, end = m_regs.end();
+    for (pos = m_regs.begin(); pos != end; ++pos)
+    {
+        if (pos->kinds[kind] == num)
+            return std::distance (m_regs.begin(), pos);
+    }
+    
+    return LLDB_INVALID_REGNUM;
+}
+
+void
+DynamicRegisterInfo::Clear()
+{
+    m_regs.clear();
+    m_sets.clear();
+    m_set_reg_nums.clear();
+    m_set_names.clear();
+}
diff --git a/source/Plugins/Process/Utility/DynamicRegisterInfo.h b/source/Plugins/Process/Utility/DynamicRegisterInfo.h
new file mode 100644
index 000000000000..a11cd333545f
--- /dev/null
+++ b/source/Plugins/Process/Utility/DynamicRegisterInfo.h
@@ -0,0 +1,85 @@
+//===-- DynamicRegisterInfo.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_DynamicRegisterInfo_h_
+#define lldb_DynamicRegisterInfo_h_
+
+// C Includes
+// C++ Includes
+#include <vector>
+
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Core/ConstString.h"
+
+class DynamicRegisterInfo
+{
+public:
+    DynamicRegisterInfo ();
+
+    DynamicRegisterInfo (const lldb_private::PythonDictionary &dict);
+    
+    virtual 
+    ~DynamicRegisterInfo ();
+
+    size_t
+    SetRegisterInfo (const lldb_private::PythonDictionary &dict);
+
+    void
+    AddRegister (lldb_private::RegisterInfo &reg_info, 
+                 lldb_private::ConstString &reg_name, 
+                 lldb_private::ConstString &reg_alt_name, 
+                 lldb_private::ConstString &set_name);
+
+    void
+    Finalize ();
+
+    size_t
+    GetNumRegisters() const;
+
+    size_t
+    GetNumRegisterSets() const;
+
+    size_t
+    GetRegisterDataByteSize() const;
+
+    const lldb_private::RegisterInfo *
+    GetRegisterInfoAtIndex (uint32_t i) const;
+
+    const lldb_private::RegisterSet *
+    GetRegisterSet (uint32_t i) const;
+
+    uint32_t
+    GetRegisterSetIndexByName (lldb_private::ConstString &set_name, bool can_create);
+
+    uint32_t
+    ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num) const;
+
+    void
+    Clear();
+
+protected:
+    //------------------------------------------------------------------
+    // Classes that inherit from DynamicRegisterInfo can see and modify these
+    //------------------------------------------------------------------
+    typedef std::vector <lldb_private::RegisterInfo> reg_collection;
+    typedef std::vector <lldb_private::RegisterSet> set_collection;
+    typedef std::vector <uint32_t> reg_num_collection;
+    typedef std::vector <reg_num_collection> set_reg_num_collection;
+    typedef std::vector <lldb_private::ConstString> name_collection;
+
+    reg_collection m_regs;
+    set_collection m_sets;
+    set_reg_num_collection m_set_reg_nums;
+    name_collection m_set_names;
+    size_t m_reg_data_byte_size;   // The number of bytes required to store all registers
+};
+
+#endif  // lldb_DynamicRegisterInfo_h_
diff --git a/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp b/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
new file mode 100644
index 000000000000..499d6d766150
--- /dev/null
+++ b/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
@@ -0,0 +1,274 @@
+//===-- InferiorCallPOSIX.cpp -----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "InferiorCallPOSIX.h"
+#include "lldb/Core/Address.h"
+#include "lldb/Core/StreamFile.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/ThreadPlanCallFunction.h"
+
+#include <sys/mman.h>
+
+using namespace lldb;
+using namespace lldb_private;
+
+bool lldb_private::InferiorCallMmap(Process *process, addr_t &allocated_addr,
+                                    addr_t addr, addr_t length, unsigned prot,
+                                    unsigned flags, addr_t fd, addr_t offset) {
+    Thread *thread = process->GetThreadList().GetSelectedThread().get();
+    if (thread == NULL)
+        return false;
+
+    const bool append = true;
+    const bool include_symbols = true;
+    const bool include_inlines = false;
+    SymbolContextList sc_list;
+    const uint32_t count
+      = process->GetTarget().GetImages().FindFunctions (ConstString ("mmap"), 
+                                                        eFunctionNameTypeFull,
+                                                        include_symbols,
+                                                        include_inlines,
+                                                        append, 
+                                                        sc_list);
+    if (count > 0)
+    {
+        SymbolContext sc;
+        if (sc_list.GetContextAtIndex(0, sc))
+        {
+            const uint32_t range_scope = eSymbolContextFunction | eSymbolContextSymbol;
+            const bool use_inline_block_range = false;
+            const bool stop_other_threads = true;
+            const bool unwind_on_error = true;
+            const bool ignore_breakpoints = true;
+            const bool try_all_threads = true;
+            const uint32_t timeout_usec = 500000;
+
+            addr_t prot_arg, flags_arg = 0;
+            if (prot == eMmapProtNone)
+              prot_arg = PROT_NONE;
+            else {
+              prot_arg = 0;
+              if (prot & eMmapProtExec)
+                prot_arg |= PROT_EXEC;
+              if (prot & eMmapProtRead)
+                prot_arg |= PROT_READ;
+              if (prot & eMmapProtWrite)
+                prot_arg |= PROT_WRITE;
+            }
+
+            if (flags & eMmapFlagsPrivate)
+              flags_arg |= MAP_PRIVATE;
+            if (flags & eMmapFlagsAnon)
+              flags_arg |= MAP_ANON;
+
+            AddressRange mmap_range;
+            if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, mmap_range))
+            {
+                ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext();
+                ClangASTType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
+                ThreadPlanCallFunction *call_function_thread_plan
+                  = new ThreadPlanCallFunction (*thread,
+                                                mmap_range.GetBaseAddress(),
+                                                clang_void_ptr_type,
+                                                stop_other_threads,
+                                                unwind_on_error,
+                                                ignore_breakpoints,
+                                                &addr,
+                                                &length,
+                                                &prot_arg,
+                                                &flags_arg,
+                                                &fd,
+                                                &offset);
+                lldb::ThreadPlanSP call_plan_sp (call_function_thread_plan);
+                if (call_plan_sp)
+                {
+                    StreamFile error_strm;
+                    // This plan is a utility plan, so set it to discard itself when done.
+                    call_plan_sp->SetIsMasterPlan (true);
+                    call_plan_sp->SetOkayToDiscard(true);
+                    
+                    StackFrame *frame = thread->GetStackFrameAtIndex (0).get();
+                    if (frame)
+                    {
+                        ExecutionContext exe_ctx;
+                        frame->CalculateExecutionContext (exe_ctx);
+                        ExecutionResults result = process->RunThreadPlan (exe_ctx,
+                                                                          call_plan_sp,        
+                                                                          stop_other_threads,
+                                                                          try_all_threads,
+                                                                          unwind_on_error,
+                                                                          ignore_breakpoints,
+                                                                          timeout_usec,
+                                                                          error_strm);
+                        if (result == eExecutionCompleted)
+                        {
+                            
+                            allocated_addr = call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
+                            if (process->GetAddressByteSize() == 4)
+                            {
+                                if (allocated_addr == UINT32_MAX)
+                                    return false;
+                            }
+                            else if (process->GetAddressByteSize() == 8)
+                            {
+                                if (allocated_addr == UINT64_MAX)
+                                    return false;
+                            }
+                            return true;
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    return false;
+}
+
+bool lldb_private::InferiorCallMunmap(Process *process, addr_t addr,
+                                      addr_t length) {
+   Thread *thread = process->GetThreadList().GetSelectedThread().get();
+   if (thread == NULL)
+       return false;
+   
+   const bool append = true;
+   const bool include_symbols = true;
+   const bool include_inlines = false;
+   SymbolContextList sc_list;
+   const uint32_t count
+     = process->GetTarget().GetImages().FindFunctions (ConstString ("munmap"), 
+                                                       eFunctionNameTypeFull,
+                                                       include_symbols, 
+                                                       include_inlines,
+                                                       append, 
+                                                       sc_list);
+   if (count > 0)
+   {
+       SymbolContext sc;
+       if (sc_list.GetContextAtIndex(0, sc))
+       {
+           const uint32_t range_scope = eSymbolContextFunction | eSymbolContextSymbol;
+           const bool use_inline_block_range = false;
+           const bool stop_other_threads = true;
+           const bool unwind_on_error = true;
+           const bool ignore_breakpoints = true;
+           const bool try_all_threads = true;
+           const uint32_t timeout_usec = 500000;
+           
+           AddressRange munmap_range;
+           if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, munmap_range))
+           {
+               lldb::ThreadPlanSP call_plan_sp (new ThreadPlanCallFunction (*thread,
+                                                                            munmap_range.GetBaseAddress(),
+                                                                            ClangASTType(),
+                                                                            stop_other_threads,
+                                                                            unwind_on_error,
+                                                                            ignore_breakpoints,
+                                                                            &addr,
+                                                                            &length));
+               if (call_plan_sp)
+               {
+                   StreamFile error_strm;
+                   // This plan is a utility plan, so set it to discard itself when done.
+                   call_plan_sp->SetIsMasterPlan (true);
+                   call_plan_sp->SetOkayToDiscard(true);
+                   
+                   StackFrame *frame = thread->GetStackFrameAtIndex (0).get();
+                   if (frame)
+                   {
+                       ExecutionContext exe_ctx;
+                       frame->CalculateExecutionContext (exe_ctx);
+                       ExecutionResults result = process->RunThreadPlan (exe_ctx,
+                                                                         call_plan_sp,        
+                                                                         stop_other_threads,
+                                                                         try_all_threads,
+                                                                         unwind_on_error,
+                                                                         ignore_breakpoints,
+                                                                         timeout_usec,
+                                                                         error_strm);
+                       if (result == eExecutionCompleted)
+                       {
+                           return true;
+                       }
+                   }
+               }
+           }
+       }
+   }
+
+   return false;
+}
+
+bool lldb_private::InferiorCall(Process *process, const Address *address, addr_t &returned_func) {
+    Thread *thread = process->GetThreadList().GetSelectedThread().get();
+    if (thread == NULL || address == NULL)
+        return false;
+
+    const bool stop_other_threads = true;
+    const bool unwind_on_error = true;
+    const bool ignore_breakpoints = true;
+    const bool try_all_threads = true;
+    const uint32_t timeout_usec = 500000;
+
+    ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext();
+    ClangASTType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
+    ThreadPlanCallFunction *call_function_thread_plan
+        = new ThreadPlanCallFunction (*thread,
+                                      *address,
+                                      clang_void_ptr_type,
+                                      stop_other_threads,
+                                      unwind_on_error,
+                                      ignore_breakpoints);
+    lldb::ThreadPlanSP call_plan_sp (call_function_thread_plan);
+    if (call_plan_sp)
+    {
+        StreamFile error_strm;
+        // This plan is a utility plan, so set it to discard itself when done.
+        call_plan_sp->SetIsMasterPlan (true);
+        call_plan_sp->SetOkayToDiscard(true);
+
+        StackFrame *frame = thread->GetStackFrameAtIndex (0).get();
+        if (frame)
+        {
+            ExecutionContext exe_ctx;
+            frame->CalculateExecutionContext (exe_ctx);
+            ExecutionResults result = process->RunThreadPlan (exe_ctx,
+                                                              call_plan_sp,
+                                                              stop_other_threads,
+                                                              try_all_threads,
+                                                              unwind_on_error,
+                                                              ignore_breakpoints,
+                                                              timeout_usec,
+                                                              error_strm);
+            if (result == eExecutionCompleted)
+            {
+                returned_func = call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
+
+                if (process->GetAddressByteSize() == 4)
+                {
+                    if (returned_func == UINT32_MAX)
+                        return false;
+                }
+                else if (process->GetAddressByteSize() == 8)
+                {
+                    if (returned_func == UINT64_MAX)
+                        return false;
+                }
+                return true;
+            }
+        }
+    }
+
+    return false;
+}
diff --git a/source/Plugins/Process/Utility/InferiorCallPOSIX.h b/source/Plugins/Process/Utility/InferiorCallPOSIX.h
new file mode 100644
index 000000000000..d8b6d0ed57fd
--- /dev/null
+++ b/source/Plugins/Process/Utility/InferiorCallPOSIX.h
@@ -0,0 +1,43 @@
+//===-- InferiorCallPOSIX.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_InferiorCallPOSIX_h_
+#define lldb_InferiorCallPOSIX_h_
+
+// Inferior execution of POSIX functions.
+
+#include "lldb/lldb-types.h"
+
+namespace lldb_private {
+
+class Process;
+
+enum MmapProt {
+  eMmapProtNone = 0,
+  eMmapProtExec = 1,
+  eMmapProtRead = 2,
+  eMmapProtWrite = 4
+};
+
+enum MmapFlags {
+  eMmapFlagsPrivate = 1,
+  eMmapFlagsAnon = 2
+};
+
+bool InferiorCallMmap(Process *proc, lldb::addr_t &allocated_addr,
+                      lldb::addr_t addr, lldb::addr_t length, unsigned prot,
+                      unsigned flags, lldb::addr_t fd, lldb::addr_t offset);
+
+bool InferiorCallMunmap(Process *proc, lldb::addr_t addr, lldb::addr_t length);
+
+bool InferiorCall(Process *proc, const Address *address, lldb::addr_t &returned_func);
+
+}   // namespace lldb_private
+
+#endif  // lldb_InferiorCallPOSIX_h_
diff --git a/source/Plugins/Process/Utility/InstructionUtils.h b/source/Plugins/Process/Utility/InstructionUtils.h
new file mode 100644
index 000000000000..4bb644e6efe6
--- /dev/null
+++ b/source/Plugins/Process/Utility/InstructionUtils.h
@@ -0,0 +1,136 @@
+//===-- InstructionUtils.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_InstructionUtils_h_
+#define lldb_InstructionUtils_h_
+
+// Common utilities for manipulating instruction bit fields.
+
+namespace lldb_private {
+
+// Return the bit field(s) from the most significant bit (msbit) to the
+// least significant bit (lsbit) of a 64-bit unsigned value.
+static inline uint64_t
+Bits64 (const uint64_t bits, const uint32_t msbit, const uint32_t lsbit)
+{
+    assert(msbit < 64 && lsbit <= msbit);
+    return (bits >> lsbit) & ((1u << (msbit - lsbit + 1)) - 1);
+}
+
+// Return the bit field(s) from the most significant bit (msbit) to the
+// least significant bit (lsbit) of a 32-bit unsigned value.
+static inline uint32_t
+Bits32 (const uint32_t bits, const uint32_t msbit, const uint32_t lsbit)
+{
+    assert(msbit < 32 && lsbit <= msbit);
+    return (bits >> lsbit) & ((1u << (msbit - lsbit + 1)) - 1);
+}
+
+// Return the bit value from the 'bit' position of a 32-bit unsigned value.
+static inline uint32_t
+Bit32 (const uint32_t bits, const uint32_t bit)
+{
+    return (bits >> bit) & 1u;
+}
+
+static inline uint64_t
+Bit64 (const uint64_t bits, const uint32_t bit)
+{
+    return (bits >> bit) & 1ull;
+}
+
+// Set the bit field(s) from the most significant bit (msbit) to the
+// least significant bit (lsbit) of a 32-bit unsigned value to 'val'.
+static inline void
+SetBits32(uint32_t &bits, const uint32_t msbit, const uint32_t lsbit, const uint32_t val)
+{
+    assert(msbit < 32 && lsbit < 32 && msbit >= lsbit);
+    uint32_t mask = ((1u << (msbit - lsbit + 1)) - 1);
+    bits &= ~(mask << lsbit);
+    bits |= (val & mask) << lsbit;
+}
+
+// Set the 'bit' position of a 32-bit unsigned value to 'val'.
+static inline void
+SetBit32(uint32_t &bits, const uint32_t bit, const uint32_t val)
+{
+    SetBits32(bits, bit, bit, val);
+}
+
+// Rotate a 32-bit unsigned value right by the specified amount.
+static inline uint32_t
+Rotr32 (uint32_t bits, uint32_t amt)
+{
+    assert(amt < 32 && "Invalid rotate amount");
+    return (bits >> amt) | (bits << ((32-amt)&31));
+}
+
+// Rotate a 32-bit unsigned value left by the specified amount.
+static inline uint32_t
+Rotl32 (uint32_t bits, uint32_t amt)
+{
+    assert(amt < 32 && "Invalid rotate amount");
+    return (bits << amt) | (bits >> ((32-amt)&31));
+}
+
+// Create a mask that starts at bit zero and includes "bit"
+static inline uint64_t
+MaskUpToBit (const uint64_t bit)
+{
+    return (1ull << (bit + 1ull)) - 1ull;
+}
+
+// Return an integer result equal to the number of bits of x that are ones.
+static inline uint32_t
+BitCount (uint64_t x)
+{
+    // c accumulates the total bits set in x
+    uint32_t c;
+    for (c = 0; x; ++c)
+    {
+        x &= x - 1; // clear the least significant bit set
+    }
+    return c;
+}
+
+static inline bool
+BitIsSet (const uint64_t value, const uint64_t bit)
+{
+    return (value & (1ull << bit)) != 0;
+}
+
+static inline bool
+BitIsClear (const uint64_t value, const uint64_t bit)
+{
+    return (value & (1ull << bit)) == 0;
+}
+
+static inline uint64_t
+UnsignedBits (const uint64_t value, const uint64_t msbit, const uint64_t lsbit)
+{
+    uint64_t result = value >> lsbit;
+    result &= MaskUpToBit (msbit - lsbit);
+    return result;
+}
+
+static inline int64_t
+SignedBits (const uint64_t value, const uint64_t msbit, const uint64_t lsbit)
+{
+    uint64_t result = UnsignedBits (value, msbit, lsbit);
+    if (BitIsSet(value, msbit))
+    {
+        // Sign extend
+        result |= ~MaskUpToBit (msbit - lsbit);
+    }
+    return result;
+}
+
+}   // namespace lldb_private
+
+#endif  // lldb_InstructionUtils_h_
diff --git a/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp b/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp
new file mode 100644
index 000000000000..4d77b6f20fdc
--- /dev/null
+++ b/source/Plugins/Process/Utility/RegisterContextDarwin_arm.cpp
@@ -0,0 +1,1226 @@
+//===-- RegisterContextDarwin_arm.cpp ---------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#if defined(__APPLE__)
+
+#include "RegisterContextDarwin_arm.h"
+
+// C Includes
+#include <mach/mach_types.h>
+#include <mach/thread_act.h>
+
+// C++ Includes
+// Other libraries and framework includes
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/RegisterValue.h"
+#include "lldb/Core/Scalar.h"
+#include "lldb/Host/Endian.h"
+#include "llvm/Support/Compiler.h"
+
+#include "Plugins/Process/Utility/InstructionUtils.h"
+
+// Support building against older versions of LLVM, this macro was added
+// recently.
+#ifndef LLVM_EXTENSION
+#define LLVM_EXTENSION
+#endif
+
+// Project includes
+#include "ARM_GCC_Registers.h"
+#include "ARM_DWARF_Registers.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+enum
+{
+    gpr_r0 = 0,
+    gpr_r1,
+    gpr_r2,
+    gpr_r3,
+    gpr_r4,
+    gpr_r5,
+    gpr_r6,
+    gpr_r7,
+    gpr_r8,
+    gpr_r9,
+    gpr_r10,
+    gpr_r11,
+    gpr_r12,
+    gpr_r13, gpr_sp = gpr_r13,
+    gpr_r14, gpr_lr = gpr_r14,
+    gpr_r15, gpr_pc = gpr_r15,
+    gpr_cpsr,
+
+    fpu_s0,
+    fpu_s1,
+    fpu_s2,
+    fpu_s3,
+    fpu_s4,
+    fpu_s5,
+    fpu_s6,
+    fpu_s7,
+    fpu_s8,
+    fpu_s9,
+    fpu_s10,
+    fpu_s11,
+    fpu_s12,
+    fpu_s13,
+    fpu_s14,
+    fpu_s15,
+    fpu_s16,
+    fpu_s17,
+    fpu_s18,
+    fpu_s19,
+    fpu_s20,
+    fpu_s21,
+    fpu_s22,
+    fpu_s23,
+    fpu_s24,
+    fpu_s25,
+    fpu_s26,
+    fpu_s27,
+    fpu_s28,
+    fpu_s29,
+    fpu_s30,
+    fpu_s31,
+    fpu_fpscr,
+
+    exc_exception,
+    exc_fsr,
+    exc_far,
+
+    dbg_bvr0,
+    dbg_bvr1,
+    dbg_bvr2,
+    dbg_bvr3,
+    dbg_bvr4,
+    dbg_bvr5,
+    dbg_bvr6,
+    dbg_bvr7,
+    dbg_bvr8,
+    dbg_bvr9,
+    dbg_bvr10,
+    dbg_bvr11,
+    dbg_bvr12,
+    dbg_bvr13,
+    dbg_bvr14,
+    dbg_bvr15,
+
+    dbg_bcr0,
+    dbg_bcr1,
+    dbg_bcr2,
+    dbg_bcr3,
+    dbg_bcr4,
+    dbg_bcr5,
+    dbg_bcr6,
+    dbg_bcr7,
+    dbg_bcr8,
+    dbg_bcr9,
+    dbg_bcr10,
+    dbg_bcr11,
+    dbg_bcr12,
+    dbg_bcr13,
+    dbg_bcr14,
+    dbg_bcr15,
+
+    dbg_wvr0,
+    dbg_wvr1,
+    dbg_wvr2,
+    dbg_wvr3,
+    dbg_wvr4,
+    dbg_wvr5,
+    dbg_wvr6,
+    dbg_wvr7,
+    dbg_wvr8,
+    dbg_wvr9,
+    dbg_wvr10,
+    dbg_wvr11,
+    dbg_wvr12,
+    dbg_wvr13,
+    dbg_wvr14,
+    dbg_wvr15,
+
+    dbg_wcr0,
+    dbg_wcr1,
+    dbg_wcr2,
+    dbg_wcr3,
+    dbg_wcr4,
+    dbg_wcr5,
+    dbg_wcr6,
+    dbg_wcr7,
+    dbg_wcr8,
+    dbg_wcr9,
+    dbg_wcr10,
+    dbg_wcr11,
+    dbg_wcr12,
+    dbg_wcr13,
+    dbg_wcr14,
+    dbg_wcr15,
+
+    k_num_registers
+};
+
+
+RegisterContextDarwin_arm::RegisterContextDarwin_arm(Thread &thread, uint32_t concrete_frame_idx) :
+    RegisterContext(thread, concrete_frame_idx),
+    gpr(),
+    fpu(),
+    exc()
+{
+    uint32_t i;
+    for (i=0; i<kNumErrors; i++)
+    {
+        gpr_errs[i] = -1;
+        fpu_errs[i] = -1;
+        exc_errs[i] = -1;
+    }
+}
+
+RegisterContextDarwin_arm::~RegisterContextDarwin_arm()
+{
+}
+
+
+#define GPR_OFFSET(idx) ((idx) * 4)
+#define FPU_OFFSET(idx) ((idx) * 4 + sizeof (RegisterContextDarwin_arm::GPR))
+#define EXC_OFFSET(idx) ((idx) * 4 + sizeof (RegisterContextDarwin_arm::GPR) + sizeof (RegisterContextDarwin_arm::FPU))
+#define DBG_OFFSET(reg) ((LLVM_EXTENSION offsetof (RegisterContextDarwin_arm::DBG, reg) + sizeof (RegisterContextDarwin_arm::GPR) + sizeof (RegisterContextDarwin_arm::FPU) + sizeof (RegisterContextDarwin_arm::EXC)))
+
+#define DEFINE_DBG(reg, i)  #reg, NULL, sizeof(((RegisterContextDarwin_arm::DBG *)NULL)->reg[i]), DBG_OFFSET(reg[i]), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, dbg_##reg##i }, NULL, NULL
+#define REG_CONTEXT_SIZE (sizeof (RegisterContextDarwin_arm::GPR) + sizeof (RegisterContextDarwin_arm::FPU) + sizeof (RegisterContextDarwin_arm::EXC))
+
+static RegisterInfo g_register_infos[] = {
+// General purpose registers
+//  NAME        ALT     SZ  OFFSET              ENCODING        FORMAT          COMPILER                DWARF               GENERIC                     GDB                     LLDB NATIVE   VALUE REGS    INVALIDATE REGS
+//  ======      ======= ==  =============       =============   ============    ===============         ===============     =========================   =====================   ============= ==========    ===============
+{   "r0",       NULL,   4,  GPR_OFFSET(0),      eEncodingUint,  eFormatHex,     { gcc_r0,               dwarf_r0,           LLDB_INVALID_REGNUM,        gdb_arm_r0,             gpr_r0      },      NULL,              NULL},
+{   "r1",       NULL,   4,  GPR_OFFSET(1),      eEncodingUint,  eFormatHex,     { gcc_r1,               dwarf_r1,           LLDB_INVALID_REGNUM,        gdb_arm_r1,             gpr_r1      },      NULL,              NULL},
+{   "r2",       NULL,   4,  GPR_OFFSET(2),      eEncodingUint,  eFormatHex,     { gcc_r2,               dwarf_r2,           LLDB_INVALID_REGNUM,        gdb_arm_r2,             gpr_r2      },      NULL,              NULL},
+{   "r3",       NULL,   4,  GPR_OFFSET(3),      eEncodingUint,  eFormatHex,     { gcc_r3,               dwarf_r3,           LLDB_INVALID_REGNUM,        gdb_arm_r3,             gpr_r3      },      NULL,              NULL},
+{   "r4",       NULL,   4,  GPR_OFFSET(4),      eEncodingUint,  eFormatHex,     { gcc_r4,               dwarf_r4,           LLDB_INVALID_REGNUM,        gdb_arm_r4,             gpr_r4      },      NULL,              NULL},
+{   "r5",       NULL,   4,  GPR_OFFSET(5),      eEncodingUint,  eFormatHex,     { gcc_r5,               dwarf_r5,           LLDB_INVALID_REGNUM,        gdb_arm_r5,             gpr_r5      },      NULL,              NULL},
+{   "r6",       NULL,   4,  GPR_OFFSET(6),      eEncodingUint,  eFormatHex,     { gcc_r6,               dwarf_r6,           LLDB_INVALID_REGNUM,        gdb_arm_r6,             gpr_r6      },      NULL,              NULL},
+{   "r7",       NULL,   4,  GPR_OFFSET(7),      eEncodingUint,  eFormatHex,     { gcc_r7,               dwarf_r7,           LLDB_REGNUM_GENERIC_FP,     gdb_arm_r7,             gpr_r7      },      NULL,              NULL},
+{   "r8",       NULL,   4,  GPR_OFFSET(8),      eEncodingUint,  eFormatHex,     { gcc_r8,               dwarf_r8,           LLDB_INVALID_REGNUM,        gdb_arm_r8,             gpr_r8      },      NULL,              NULL},
+{   "r9",       NULL,   4,  GPR_OFFSET(9),      eEncodingUint,  eFormatHex,     { gcc_r9,               dwarf_r9,           LLDB_INVALID_REGNUM,        gdb_arm_r9,             gpr_r9      },      NULL,              NULL},
+{   "r10",      NULL,   4,  GPR_OFFSET(10),     eEncodingUint,  eFormatHex,     { gcc_r10,              dwarf_r10,          LLDB_INVALID_REGNUM,        gdb_arm_r10,            gpr_r10     },      NULL,              NULL},
+{   "r11",      NULL,   4,  GPR_OFFSET(11),     eEncodingUint,  eFormatHex,     { gcc_r11,              dwarf_r11,          LLDB_INVALID_REGNUM,        gdb_arm_r11,            gpr_r11     },      NULL,              NULL},
+{   "r12",      NULL,   4,  GPR_OFFSET(12),     eEncodingUint,  eFormatHex,     { gcc_r12,              dwarf_r12,          LLDB_INVALID_REGNUM,        gdb_arm_r12,            gpr_r12     },      NULL,              NULL},
+{   "sp",       "r13",  4,  GPR_OFFSET(13),     eEncodingUint,  eFormatHex,     { gcc_sp,               dwarf_sp,           LLDB_REGNUM_GENERIC_SP,     gdb_arm_sp,             gpr_sp      },      NULL,              NULL},
+{   "lr",       "r14",  4,  GPR_OFFSET(14),     eEncodingUint,  eFormatHex,     { gcc_lr,               dwarf_lr,           LLDB_REGNUM_GENERIC_RA,     gdb_arm_lr,             gpr_lr      },      NULL,              NULL},
+{   "pc",       "r15",  4,  GPR_OFFSET(15),     eEncodingUint,  eFormatHex,     { gcc_pc,               dwarf_pc,           LLDB_REGNUM_GENERIC_PC,     gdb_arm_pc,             gpr_pc      },      NULL,              NULL},
+{   "cpsr",     "psr",  4,  GPR_OFFSET(16),     eEncodingUint,  eFormatHex,     { gcc_cpsr,             dwarf_cpsr,         LLDB_REGNUM_GENERIC_FLAGS,  gdb_arm_cpsr,           gpr_cpsr    },      NULL,              NULL},
+
+{   "s0",       NULL,   4,  FPU_OFFSET(0),      eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s0,           LLDB_INVALID_REGNUM,        gdb_arm_s0,             fpu_s0      },      NULL,              NULL},
+{   "s1",       NULL,   4,  FPU_OFFSET(1),      eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s1,           LLDB_INVALID_REGNUM,        gdb_arm_s1,             fpu_s1      },      NULL,              NULL},
+{   "s2",       NULL,   4,  FPU_OFFSET(2),      eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s2,           LLDB_INVALID_REGNUM,        gdb_arm_s2,             fpu_s2      },      NULL,              NULL},
+{   "s3",       NULL,   4,  FPU_OFFSET(3),      eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s3,           LLDB_INVALID_REGNUM,        gdb_arm_s3,             fpu_s3      },      NULL,              NULL},
+{   "s4",       NULL,   4,  FPU_OFFSET(4),      eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s4,           LLDB_INVALID_REGNUM,        gdb_arm_s4,             fpu_s4      },      NULL,              NULL},
+{   "s5",       NULL,   4,  FPU_OFFSET(5),      eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s5,           LLDB_INVALID_REGNUM,        gdb_arm_s5,             fpu_s5      },      NULL,              NULL},
+{   "s6",       NULL,   4,  FPU_OFFSET(6),      eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s6,           LLDB_INVALID_REGNUM,        gdb_arm_s6,             fpu_s6      },      NULL,              NULL},
+{   "s7",       NULL,   4,  FPU_OFFSET(7),      eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s7,           LLDB_INVALID_REGNUM,        gdb_arm_s7,             fpu_s7      },      NULL,              NULL},
+{   "s8",       NULL,   4,  FPU_OFFSET(8),      eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s8,           LLDB_INVALID_REGNUM,        gdb_arm_s8,             fpu_s8      },      NULL,              NULL},
+{   "s9",       NULL,   4,  FPU_OFFSET(9),      eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s9,           LLDB_INVALID_REGNUM,        gdb_arm_s9,             fpu_s9      },      NULL,              NULL},
+{   "s10",      NULL,   4,  FPU_OFFSET(10),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s10,          LLDB_INVALID_REGNUM,        gdb_arm_s10,            fpu_s10     },      NULL,              NULL},
+{   "s11",      NULL,   4,  FPU_OFFSET(11),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s11,          LLDB_INVALID_REGNUM,        gdb_arm_s11,            fpu_s11     },      NULL,              NULL},
+{   "s12",      NULL,   4,  FPU_OFFSET(12),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s12,          LLDB_INVALID_REGNUM,        gdb_arm_s12,            fpu_s12     },      NULL,              NULL},
+{   "s13",      NULL,   4,  FPU_OFFSET(13),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s13,          LLDB_INVALID_REGNUM,        gdb_arm_s13,            fpu_s13     },      NULL,              NULL},
+{   "s14",      NULL,   4,  FPU_OFFSET(14),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s14,          LLDB_INVALID_REGNUM,        gdb_arm_s14,            fpu_s14     },      NULL,              NULL},
+{   "s15",      NULL,   4,  FPU_OFFSET(15),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s15,          LLDB_INVALID_REGNUM,        gdb_arm_s15,            fpu_s15     },      NULL,              NULL},
+{   "s16",      NULL,   4,  FPU_OFFSET(16),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s16,          LLDB_INVALID_REGNUM,        gdb_arm_s16,            fpu_s16     },      NULL,              NULL},
+{   "s17",      NULL,   4,  FPU_OFFSET(17),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s17,          LLDB_INVALID_REGNUM,        gdb_arm_s17,            fpu_s17     },      NULL,              NULL},
+{   "s18",      NULL,   4,  FPU_OFFSET(18),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s18,          LLDB_INVALID_REGNUM,        gdb_arm_s18,            fpu_s18     },      NULL,              NULL},
+{   "s19",      NULL,   4,  FPU_OFFSET(19),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s19,          LLDB_INVALID_REGNUM,        gdb_arm_s19,            fpu_s19     },      NULL,              NULL},
+{   "s20",      NULL,   4,  FPU_OFFSET(20),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s20,          LLDB_INVALID_REGNUM,        gdb_arm_s20,            fpu_s20     },      NULL,              NULL},
+{   "s21",      NULL,   4,  FPU_OFFSET(21),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s21,          LLDB_INVALID_REGNUM,        gdb_arm_s21,            fpu_s21     },      NULL,              NULL},
+{   "s22",      NULL,   4,  FPU_OFFSET(22),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s22,          LLDB_INVALID_REGNUM,        gdb_arm_s22,            fpu_s22     },      NULL,              NULL},
+{   "s23",      NULL,   4,  FPU_OFFSET(23),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s23,          LLDB_INVALID_REGNUM,        gdb_arm_s23,            fpu_s23     },      NULL,              NULL},
+{   "s24",      NULL,   4,  FPU_OFFSET(24),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s24,          LLDB_INVALID_REGNUM,        gdb_arm_s24,            fpu_s24     },      NULL,              NULL},
+{   "s25",      NULL,   4,  FPU_OFFSET(25),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s25,          LLDB_INVALID_REGNUM,        gdb_arm_s25,            fpu_s25     },      NULL,              NULL},
+{   "s26",      NULL,   4,  FPU_OFFSET(26),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s26,          LLDB_INVALID_REGNUM,        gdb_arm_s26,            fpu_s26     },      NULL,              NULL},
+{   "s27",      NULL,   4,  FPU_OFFSET(27),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s27,          LLDB_INVALID_REGNUM,        gdb_arm_s27,            fpu_s27     },      NULL,              NULL},
+{   "s28",      NULL,   4,  FPU_OFFSET(28),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s28,          LLDB_INVALID_REGNUM,        gdb_arm_s28,            fpu_s28     },      NULL,              NULL},
+{   "s29",      NULL,   4,  FPU_OFFSET(29),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s29,          LLDB_INVALID_REGNUM,        gdb_arm_s29,            fpu_s29     },      NULL,              NULL},
+{   "s30",      NULL,   4,  FPU_OFFSET(30),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s30,          LLDB_INVALID_REGNUM,        gdb_arm_s30,            fpu_s30     },      NULL,              NULL},
+{   "s31",      NULL,   4,  FPU_OFFSET(31),     eEncodingIEEE754,eFormatFloat,  { LLDB_INVALID_REGNUM,  dwarf_s31,          LLDB_INVALID_REGNUM,        gdb_arm_s31,            fpu_s31     },      NULL,              NULL},
+{   "fpscr",    NULL,   4,  FPU_OFFSET(32),     eEncodingUint,  eFormatHex,     { LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM,        gdb_arm_fpscr,          fpu_fpscr   },      NULL,              NULL},
+
+{   "exception",NULL,   4,  EXC_OFFSET(0),      eEncodingUint,  eFormatHex,     { LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    exc_exception },    NULL,              NULL},
+{   "fsr",      NULL,   4,  EXC_OFFSET(1),      eEncodingUint,  eFormatHex,     { LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    exc_fsr       },    NULL,              NULL},
+{   "far",      NULL,   4,  EXC_OFFSET(2),      eEncodingUint,  eFormatHex,     { LLDB_INVALID_REGNUM,  LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM,        LLDB_INVALID_REGNUM,    exc_far       },    NULL,              NULL},
+
+{   DEFINE_DBG (bvr, 0) },
+{   DEFINE_DBG (bvr, 1) },
+{   DEFINE_DBG (bvr, 2) },
+{   DEFINE_DBG (bvr, 3) },
+{   DEFINE_DBG (bvr, 4) },
+{   DEFINE_DBG (bvr, 5) },
+{   DEFINE_DBG (bvr, 6) },
+{   DEFINE_DBG (bvr, 7) },
+{   DEFINE_DBG (bvr, 8) },
+{   DEFINE_DBG (bvr, 9) },
+{   DEFINE_DBG (bvr, 10) },
+{   DEFINE_DBG (bvr, 11) },
+{   DEFINE_DBG (bvr, 12) },
+{   DEFINE_DBG (bvr, 13) },
+{   DEFINE_DBG (bvr, 14) },
+{   DEFINE_DBG (bvr, 15) },
+
+{   DEFINE_DBG (bcr, 0) },
+{   DEFINE_DBG (bcr, 1) },
+{   DEFINE_DBG (bcr, 2) },
+{   DEFINE_DBG (bcr, 3) },
+{   DEFINE_DBG (bcr, 4) },
+{   DEFINE_DBG (bcr, 5) },
+{   DEFINE_DBG (bcr, 6) },
+{   DEFINE_DBG (bcr, 7) },
+{   DEFINE_DBG (bcr, 8) },
+{   DEFINE_DBG (bcr, 9) },
+{   DEFINE_DBG (bcr, 10) },
+{   DEFINE_DBG (bcr, 11) },
+{   DEFINE_DBG (bcr, 12) },
+{   DEFINE_DBG (bcr, 13) },
+{   DEFINE_DBG (bcr, 14) },
+{   DEFINE_DBG (bcr, 15) },
+
+{   DEFINE_DBG (wvr, 0) },
+{   DEFINE_DBG (wvr, 1) },
+{   DEFINE_DBG (wvr, 2) },
+{   DEFINE_DBG (wvr, 3) },
+{   DEFINE_DBG (wvr, 4) },
+{   DEFINE_DBG (wvr, 5) },
+{   DEFINE_DBG (wvr, 6) },
+{   DEFINE_DBG (wvr, 7) },
+{   DEFINE_DBG (wvr, 8) },
+{   DEFINE_DBG (wvr, 9) },
+{   DEFINE_DBG (wvr, 10) },
+{   DEFINE_DBG (wvr, 11) },
+{   DEFINE_DBG (wvr, 12) },
+{   DEFINE_DBG (wvr, 13) },
+{   DEFINE_DBG (wvr, 14) },
+{   DEFINE_DBG (wvr, 15) },
+
+{   DEFINE_DBG (wcr, 0) },
+{   DEFINE_DBG (wcr, 1) },
+{   DEFINE_DBG (wcr, 2) },
+{   DEFINE_DBG (wcr, 3) },
+{   DEFINE_DBG (wcr, 4) },
+{   DEFINE_DBG (wcr, 5) },
+{   DEFINE_DBG (wcr, 6) },
+{   DEFINE_DBG (wcr, 7) },
+{   DEFINE_DBG (wcr, 8) },
+{   DEFINE_DBG (wcr, 9) },
+{   DEFINE_DBG (wcr, 10) },
+{   DEFINE_DBG (wcr, 11) },
+{   DEFINE_DBG (wcr, 12) },
+{   DEFINE_DBG (wcr, 13) },
+{   DEFINE_DBG (wcr, 14) },
+{   DEFINE_DBG (wcr, 15) }
+};
+
+// General purpose registers
+static uint32_t
+g_gpr_regnums[] =
+{
+    gpr_r0,
+    gpr_r1,
+    gpr_r2,
+    gpr_r3,
+    gpr_r4,
+    gpr_r5,
+    gpr_r6,
+    gpr_r7,
+    gpr_r8,
+    gpr_r9,
+    gpr_r10,
+    gpr_r11,
+    gpr_r12,
+    gpr_sp,
+    gpr_lr,
+    gpr_pc,
+    gpr_cpsr
+};
+
+// Floating point registers
+static uint32_t
+g_fpu_regnums[] =
+{
+    fpu_s0,
+    fpu_s1,
+    fpu_s2,
+    fpu_s3,
+    fpu_s4,
+    fpu_s5,
+    fpu_s6,
+    fpu_s7,
+    fpu_s8,
+    fpu_s9,
+    fpu_s10,
+    fpu_s11,
+    fpu_s12,
+    fpu_s13,
+    fpu_s14,
+    fpu_s15,
+    fpu_s16,
+    fpu_s17,
+    fpu_s18,
+    fpu_s19,
+    fpu_s20,
+    fpu_s21,
+    fpu_s22,
+    fpu_s23,
+    fpu_s24,
+    fpu_s25,
+    fpu_s26,
+    fpu_s27,
+    fpu_s28,
+    fpu_s29,
+    fpu_s30,
+    fpu_s31,
+    fpu_fpscr,
+};
+
+// Exception registers
+
+static uint32_t
+g_exc_regnums[] =
+{
+    exc_exception,
+    exc_fsr,
+    exc_far,
+};
+
+static size_t k_num_register_infos = (sizeof(g_register_infos)/sizeof(RegisterInfo));
+
+void
+RegisterContextDarwin_arm::InvalidateAllRegisters ()
+{
+    InvalidateAllRegisterStates();
+}
+
+
+size_t
+RegisterContextDarwin_arm::GetRegisterCount ()
+{
+    assert(k_num_register_infos == k_num_registers);
+    return k_num_registers;
+}
+
+const RegisterInfo *
+RegisterContextDarwin_arm::GetRegisterInfoAtIndex (size_t reg)
+{
+    assert(k_num_register_infos == k_num_registers);
+    if (reg < k_num_registers)
+        return &g_register_infos[reg];
+    return NULL;
+}
+
+size_t
+RegisterContextDarwin_arm::GetRegisterInfosCount ()
+{
+    return k_num_register_infos;
+}
+
+const RegisterInfo *
+RegisterContextDarwin_arm::GetRegisterInfos ()
+{
+    return g_register_infos;
+}
+
+
+// Number of registers in each register set
+const size_t k_num_gpr_registers = sizeof(g_gpr_regnums) / sizeof(uint32_t);
+const size_t k_num_fpu_registers = sizeof(g_fpu_regnums) / sizeof(uint32_t);
+const size_t k_num_exc_registers = sizeof(g_exc_regnums) / sizeof(uint32_t);
+
+//----------------------------------------------------------------------
+// Register set definitions. The first definitions at register set index
+// of zero is for all registers, followed by other registers sets. The
+// register information for the all register set need not be filled in.
+//----------------------------------------------------------------------
+static const RegisterSet g_reg_sets[] =
+{
+    { "General Purpose Registers",  "gpr",  k_num_gpr_registers,    g_gpr_regnums,      },
+    { "Floating Point Registers",   "fpu",  k_num_fpu_registers,    g_fpu_regnums       },
+    { "Exception State Registers",  "exc",  k_num_exc_registers,    g_exc_regnums       }
+};
+
+const size_t k_num_regsets = sizeof(g_reg_sets) / sizeof(RegisterSet);
+
+
+size_t
+RegisterContextDarwin_arm::GetRegisterSetCount ()
+{
+    return k_num_regsets;
+}
+
+const RegisterSet *
+RegisterContextDarwin_arm::GetRegisterSet (size_t reg_set)
+{
+    if (reg_set < k_num_regsets)
+        return &g_reg_sets[reg_set];
+    return NULL;
+}
+
+
+//----------------------------------------------------------------------
+// Register information defintions for 32 bit i386.
+//----------------------------------------------------------------------
+int
+RegisterContextDarwin_arm::GetSetForNativeRegNum (int reg)
+{
+    if (reg < fpu_s0)
+        return GPRRegSet;
+    else if (reg < exc_exception)
+        return FPURegSet;
+    else if (reg < k_num_registers)
+        return EXCRegSet;
+    return -1;
+}
+
+int
+RegisterContextDarwin_arm::ReadGPR (bool force)
+{
+    int set = GPRRegSet;
+    if (force || !RegisterSetIsCached(set))
+    {
+        SetError(set, Read, DoReadGPR(GetThreadID(), set, gpr));
+    }
+    return GetError(GPRRegSet, Read);
+}
+
+int
+RegisterContextDarwin_arm::ReadFPU (bool force)
+{
+    int set = FPURegSet;
+    if (force || !RegisterSetIsCached(set))
+    {
+        SetError(set, Read, DoReadFPU(GetThreadID(), set, fpu));
+    }
+    return GetError(FPURegSet, Read);
+}
+
+int
+RegisterContextDarwin_arm::ReadEXC (bool force)
+{
+    int set = EXCRegSet;
+    if (force || !RegisterSetIsCached(set))
+    {
+        SetError(set, Read, DoReadEXC(GetThreadID(), set, exc));
+    }
+    return GetError(EXCRegSet, Read);
+}
+
+int
+RegisterContextDarwin_arm::ReadDBG (bool force)
+{
+    int set = DBGRegSet;
+    if (force || !RegisterSetIsCached(set))
+    {
+        SetError(set, Read, DoReadDBG(GetThreadID(), set, dbg));
+    }
+    return GetError(DBGRegSet, Read);
+}
+
+int
+RegisterContextDarwin_arm::WriteGPR ()
+{
+    int set = GPRRegSet;
+    if (!RegisterSetIsCached(set))
+    {
+        SetError (set, Write, -1);
+        return KERN_INVALID_ARGUMENT;
+    }
+    SetError (set, Write, DoWriteGPR(GetThreadID(), set, gpr));
+    SetError (set, Read, -1);
+    return GetError(GPRRegSet, Write);
+}
+
+int
+RegisterContextDarwin_arm::WriteFPU ()
+{
+    int set = FPURegSet;
+    if (!RegisterSetIsCached(set))
+    {
+        SetError (set, Write, -1);
+        return KERN_INVALID_ARGUMENT;
+    }
+    SetError (set, Write, DoWriteFPU(GetThreadID(), set, fpu));
+    SetError (set, Read, -1);
+    return GetError(FPURegSet, Write);
+}
+
+int
+RegisterContextDarwin_arm::WriteEXC ()
+{
+    int set = EXCRegSet;
+    if (!RegisterSetIsCached(set))
+    {
+        SetError (set, Write, -1);
+        return KERN_INVALID_ARGUMENT;
+    }
+    SetError (set, Write, DoWriteEXC(GetThreadID(), set, exc));
+    SetError (set, Read, -1);
+    return GetError(EXCRegSet, Write);
+}
+
+int
+RegisterContextDarwin_arm::WriteDBG ()
+{
+    int set = DBGRegSet;
+    if (!RegisterSetIsCached(set))
+    {
+        SetError (set, Write, -1);
+        return KERN_INVALID_ARGUMENT;
+    }
+    SetError (set, Write, DoWriteDBG(GetThreadID(), set, dbg));
+    SetError (set, Read, -1);
+    return GetError(DBGRegSet, Write);
+}
+
+
+int
+RegisterContextDarwin_arm::ReadRegisterSet (uint32_t set, bool force)
+{
+    switch (set)
+    {
+    case GPRRegSet:    return ReadGPR(force);
+    case FPURegSet:    return ReadFPU(force);
+    case EXCRegSet:    return ReadEXC(force);
+    case DBGRegSet:    return ReadDBG(force);
+    default: break;
+    }
+    return KERN_INVALID_ARGUMENT;
+}
+
+int
+RegisterContextDarwin_arm::WriteRegisterSet (uint32_t set)
+{
+    // Make sure we have a valid context to set.
+    if (RegisterSetIsCached(set))
+    {
+        switch (set)
+        {
+        case GPRRegSet:    return WriteGPR();
+        case FPURegSet:    return WriteFPU();
+        case EXCRegSet:    return WriteEXC();
+        case DBGRegSet:    return WriteDBG();
+        default: break;
+        }
+    }
+    return KERN_INVALID_ARGUMENT;
+}
+
+void
+RegisterContextDarwin_arm::LogDBGRegisters (Log *log, const DBG& dbg)
+{
+    if (log)
+    {
+        for (uint32_t i=0; i<16; i++)
+            log->Printf("BVR%-2u/BCR%-2u = { 0x%8.8x, 0x%8.8x } WVR%-2u/WCR%-2u = { 0x%8.8x, 0x%8.8x }",
+                i, i, dbg.bvr[i], dbg.bcr[i],
+                i, i, dbg.wvr[i], dbg.wcr[i]);
+    }
+}
+
+
+bool
+RegisterContextDarwin_arm::ReadRegister (const RegisterInfo *reg_info, RegisterValue &value)
+{
+    const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
+    int set = RegisterContextDarwin_arm::GetSetForNativeRegNum (reg);
+
+    if (set == -1)
+        return false;
+
+    if (ReadRegisterSet(set, false) != KERN_SUCCESS)
+        return false;
+
+    switch (reg)
+    {
+    case gpr_r0:
+    case gpr_r1:
+    case gpr_r2:
+    case gpr_r3:
+    case gpr_r4:
+    case gpr_r5:
+    case gpr_r6:
+    case gpr_r7:
+    case gpr_r8:
+    case gpr_r9:
+    case gpr_r10:
+    case gpr_r11:
+    case gpr_r12:
+    case gpr_sp:
+    case gpr_lr:
+    case gpr_pc:
+    case gpr_cpsr:
+        value.SetUInt32 (gpr.r[reg - gpr_r0]);
+        break;
+
+    case fpu_s0:
+    case fpu_s1:
+    case fpu_s2:
+    case fpu_s3:
+    case fpu_s4:
+    case fpu_s5:
+    case fpu_s6:
+    case fpu_s7:
+    case fpu_s8:
+    case fpu_s9:
+    case fpu_s10:
+    case fpu_s11:
+    case fpu_s12:
+    case fpu_s13:
+    case fpu_s14:
+    case fpu_s15:
+    case fpu_s16:
+    case fpu_s17:
+    case fpu_s18:
+    case fpu_s19:
+    case fpu_s20:
+    case fpu_s21:
+    case fpu_s22:
+    case fpu_s23:
+    case fpu_s24:
+    case fpu_s25:
+    case fpu_s26:
+    case fpu_s27:
+    case fpu_s28:
+    case fpu_s29:
+    case fpu_s30:
+    case fpu_s31:
+        value.SetUInt32 (fpu.floats.s[reg], RegisterValue::eTypeFloat);
+        break;
+
+    case fpu_fpscr:
+        value.SetUInt32 (fpu.fpscr);
+        break;
+
+    case exc_exception:
+        value.SetUInt32 (exc.exception);
+        break;
+    case exc_fsr:
+        value.SetUInt32 (exc.fsr);
+        break;
+    case exc_far:
+        value.SetUInt32 (exc.far);
+        break;
+
+    default:
+        value.SetValueToInvalid();
+        return false;
+
+    }
+    return true;
+}
+
+
+bool
+RegisterContextDarwin_arm::WriteRegister (const RegisterInfo *reg_info,
+                                        const RegisterValue &value)
+{
+    const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
+    int set = GetSetForNativeRegNum (reg);
+
+    if (set == -1)
+        return false;
+
+    if (ReadRegisterSet(set, false) != KERN_SUCCESS)
+        return false;
+
+    switch (reg)
+    {
+    case gpr_r0:
+    case gpr_r1:
+    case gpr_r2:
+    case gpr_r3:
+    case gpr_r4:
+    case gpr_r5:
+    case gpr_r6:
+    case gpr_r7:
+    case gpr_r8:
+    case gpr_r9:
+    case gpr_r10:
+    case gpr_r11:
+    case gpr_r12:
+    case gpr_sp:
+    case gpr_lr:
+    case gpr_pc:
+    case gpr_cpsr:
+            gpr.r[reg - gpr_r0] = value.GetAsUInt32();
+        break;
+
+    case fpu_s0:
+    case fpu_s1:
+    case fpu_s2:
+    case fpu_s3:
+    case fpu_s4:
+    case fpu_s5:
+    case fpu_s6:
+    case fpu_s7:
+    case fpu_s8:
+    case fpu_s9:
+    case fpu_s10:
+    case fpu_s11:
+    case fpu_s12:
+    case fpu_s13:
+    case fpu_s14:
+    case fpu_s15:
+    case fpu_s16:
+    case fpu_s17:
+    case fpu_s18:
+    case fpu_s19:
+    case fpu_s20:
+    case fpu_s21:
+    case fpu_s22:
+    case fpu_s23:
+    case fpu_s24:
+    case fpu_s25:
+    case fpu_s26:
+    case fpu_s27:
+    case fpu_s28:
+    case fpu_s29:
+    case fpu_s30:
+    case fpu_s31:
+        fpu.floats.s[reg] = value.GetAsUInt32();
+        break;
+
+    case fpu_fpscr:
+        fpu.fpscr = value.GetAsUInt32();
+        break;
+
+    case exc_exception:
+        exc.exception = value.GetAsUInt32();
+        break;
+    case exc_fsr:
+        exc.fsr = value.GetAsUInt32();
+        break;
+    case exc_far:
+        exc.far = value.GetAsUInt32();
+        break;
+
+    default:
+        return false;
+
+    }
+    return WriteRegisterSet(set) == KERN_SUCCESS;
+}
+
+bool
+RegisterContextDarwin_arm::ReadAllRegisterValues (lldb::DataBufferSP &data_sp)
+{
+    data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0));
+    if (data_sp &&
+        ReadGPR (false) == KERN_SUCCESS &&
+        ReadFPU (false) == KERN_SUCCESS &&
+        ReadEXC (false) == KERN_SUCCESS)
+    {
+        uint8_t *dst = data_sp->GetBytes();
+        ::memcpy (dst, &gpr, sizeof(gpr));
+        dst += sizeof(gpr);
+
+        ::memcpy (dst, &fpu, sizeof(fpu));
+        dst += sizeof(gpr);
+
+        ::memcpy (dst, &exc, sizeof(exc));
+        return true;
+    }
+    return false;
+}
+
+bool
+RegisterContextDarwin_arm::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp)
+{
+    if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE)
+    {
+        const uint8_t *src = data_sp->GetBytes();
+        ::memcpy (&gpr, src, sizeof(gpr));
+        src += sizeof(gpr);
+
+        ::memcpy (&fpu, src, sizeof(fpu));
+        src += sizeof(gpr);
+
+        ::memcpy (&exc, src, sizeof(exc));
+        uint32_t success_count = 0;
+        if (WriteGPR() == KERN_SUCCESS)
+            ++success_count;
+        if (WriteFPU() == KERN_SUCCESS)
+            ++success_count;
+        if (WriteEXC() == KERN_SUCCESS)
+            ++success_count;
+        return success_count == 3;
+    }
+    return false;
+}
+
+uint32_t
+RegisterContextDarwin_arm::ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t reg)
+{
+    if (kind == eRegisterKindGeneric)
+    {
+        switch (reg)
+        {
+        case LLDB_REGNUM_GENERIC_PC: return gpr_pc;
+        case LLDB_REGNUM_GENERIC_SP: return gpr_sp;
+        case LLDB_REGNUM_GENERIC_FP: return gpr_r7;
+        case LLDB_REGNUM_GENERIC_RA: return gpr_lr;
+        case LLDB_REGNUM_GENERIC_FLAGS: return gpr_cpsr;
+        default:
+            break;
+        }
+    }
+    else if (kind == eRegisterKindDWARF)
+    {
+        switch (reg)
+        {
+        case dwarf_r0:  return gpr_r0;
+        case dwarf_r1:  return gpr_r1;
+        case dwarf_r2:  return gpr_r2;
+        case dwarf_r3:  return gpr_r3;
+        case dwarf_r4:  return gpr_r4;
+        case dwarf_r5:  return gpr_r5;
+        case dwarf_r6:  return gpr_r6;
+        case dwarf_r7:  return gpr_r7;
+        case dwarf_r8:  return gpr_r8;
+        case dwarf_r9:  return gpr_r9;
+        case dwarf_r10: return gpr_r10;
+        case dwarf_r11: return gpr_r11;
+        case dwarf_r12: return gpr_r12;
+        case dwarf_sp:  return gpr_sp;
+        case dwarf_lr:  return gpr_lr;
+        case dwarf_pc:  return gpr_pc;
+        case dwarf_spsr: return gpr_cpsr;
+
+        case dwarf_s0:  return fpu_s0;
+        case dwarf_s1:  return fpu_s1;
+        case dwarf_s2:  return fpu_s2;
+        case dwarf_s3:  return fpu_s3;
+        case dwarf_s4:  return fpu_s4;
+        case dwarf_s5:  return fpu_s5;
+        case dwarf_s6:  return fpu_s6;
+        case dwarf_s7:  return fpu_s7;
+        case dwarf_s8:  return fpu_s8;
+        case dwarf_s9:  return fpu_s9;
+        case dwarf_s10: return fpu_s10;
+        case dwarf_s11: return fpu_s11;
+        case dwarf_s12: return fpu_s12;
+        case dwarf_s13: return fpu_s13;
+        case dwarf_s14: return fpu_s14;
+        case dwarf_s15: return fpu_s15;
+        case dwarf_s16: return fpu_s16;
+        case dwarf_s17: return fpu_s17;
+        case dwarf_s18: return fpu_s18;
+        case dwarf_s19: return fpu_s19;
+        case dwarf_s20: return fpu_s20;
+        case dwarf_s21: return fpu_s21;
+        case dwarf_s22: return fpu_s22;
+        case dwarf_s23: return fpu_s23;
+        case dwarf_s24: return fpu_s24;
+        case dwarf_s25: return fpu_s25;
+        case dwarf_s26: return fpu_s26;
+        case dwarf_s27: return fpu_s27;
+        case dwarf_s28: return fpu_s28;
+        case dwarf_s29: return fpu_s29;
+        case dwarf_s30: return fpu_s30;
+        case dwarf_s31: return fpu_s31;
+
+        default:
+            break;
+        }
+    }
+    else if (kind == eRegisterKindGCC)
+    {
+        switch (reg)
+        {
+        case gcc_r0:    return gpr_r0;
+        case gcc_r1:    return gpr_r1;
+        case gcc_r2:    return gpr_r2;
+        case gcc_r3:    return gpr_r3;
+        case gcc_r4:    return gpr_r4;
+        case gcc_r5:    return gpr_r5;
+        case gcc_r6:    return gpr_r6;
+        case gcc_r7:    return gpr_r7;
+        case gcc_r8:    return gpr_r8;
+        case gcc_r9:    return gpr_r9;
+        case gcc_r10:   return gpr_r10;
+        case gcc_r11:   return gpr_r11;
+        case gcc_r12:   return gpr_r12;
+        case gcc_sp:    return gpr_sp;
+        case gcc_lr:    return gpr_lr;
+        case gcc_pc:    return gpr_pc;
+        case gcc_cpsr:  return gpr_cpsr;
+        }
+    }
+    else if (kind == eRegisterKindLLDB)
+    {
+        return reg;
+    }
+    return LLDB_INVALID_REGNUM;
+}
+
+
+uint32_t
+RegisterContextDarwin_arm::NumSupportedHardwareBreakpoints ()
+{
+#if defined (__arm__)
+    // Set the init value to something that will let us know that we need to
+    // autodetect how many breakpoints are supported dynamically...
+    static uint32_t g_num_supported_hw_breakpoints = UINT32_MAX;
+    if (g_num_supported_hw_breakpoints == UINT32_MAX)
+    {
+        // Set this to zero in case we can't tell if there are any HW breakpoints
+        g_num_supported_hw_breakpoints = 0;
+
+        uint32_t register_DBGDIDR;
+
+        asm("mrc p14, 0, %0, c0, c0, 0" : "=r" (register_DBGDIDR));
+        g_num_supported_hw_breakpoints = Bits32 (register_DBGDIDR, 27, 24);
+        // Zero is reserved for the BRP count, so don't increment it if it is zero
+        if (g_num_supported_hw_breakpoints > 0)
+            g_num_supported_hw_breakpoints++;
+//        if (log) log->Printf ("DBGDIDR=0x%8.8x (number BRP pairs = %u)", register_DBGDIDR, g_num_supported_hw_breakpoints);
+
+    }
+    return g_num_supported_hw_breakpoints;
+#else
+    // TODO: figure out remote case here!
+    return 6;
+#endif
+}
+
+uint32_t
+RegisterContextDarwin_arm::SetHardwareBreakpoint (lldb::addr_t addr, size_t size)
+{
+    // Make sure our address isn't bogus
+    if (addr & 1)
+        return LLDB_INVALID_INDEX32;
+
+    int kret = ReadDBG (false);
+
+    if (kret == KERN_SUCCESS)
+    {
+        const uint32_t num_hw_breakpoints = NumSupportedHardwareBreakpoints();
+        uint32_t i;
+        for (i=0; i<num_hw_breakpoints; ++i)
+        {
+            if ((dbg.bcr[i] & BCR_ENABLE) == 0)
+                break; // We found an available hw breakpoint slot (in i)
+        }
+
+        // See if we found an available hw breakpoint slot above
+        if (i < num_hw_breakpoints)
+        {
+            // Make sure bits 1:0 are clear in our address
+            dbg.bvr[i] = addr & ~((lldb::addr_t)3);
+
+            if (size == 2 || addr & 2)
+            {
+                uint32_t byte_addr_select = (addr & 2) ? BAS_IMVA_2_3 : BAS_IMVA_0_1;
+
+                // We have a thumb breakpoint
+                // We have an ARM breakpoint
+                dbg.bcr[i] =  BCR_M_IMVA_MATCH |    // Stop on address mismatch
+                                        byte_addr_select |  // Set the correct byte address select so we only trigger on the correct opcode
+                                        S_USER |            // Which modes should this breakpoint stop in?
+                                        BCR_ENABLE;         // Enable this hardware breakpoint
+//                if (log) log->Printf ("RegisterContextDarwin_arm::EnableHardwareBreakpoint( addr = %8.8p, size = %u ) - BVR%u/BCR%u = 0x%8.8x / 0x%8.8x (Thumb)",
+//                        addr,
+//                        size,
+//                        i,
+//                        i,
+//                        dbg.bvr[i],
+//                        dbg.bcr[i]);
+            }
+            else if (size == 4)
+            {
+                // We have an ARM breakpoint
+                dbg.bcr[i] =  BCR_M_IMVA_MATCH |    // Stop on address mismatch
+                                        BAS_IMVA_ALL |      // Stop on any of the four bytes following the IMVA
+                                        S_USER |            // Which modes should this breakpoint stop in?
+                                        BCR_ENABLE;         // Enable this hardware breakpoint
+//                if (log) log->Printf ("RegisterContextDarwin_arm::EnableHardwareBreakpoint( addr = %8.8p, size = %u ) - BVR%u/BCR%u = 0x%8.8x / 0x%8.8x (ARM)",
+//                        addr,
+//                        size,
+//                        i,
+//                        i,
+//                        dbg.bvr[i],
+//                        dbg.bcr[i]);
+            }
+
+            kret = WriteDBG();
+//            if (log) log->Printf ("RegisterContextDarwin_arm::EnableHardwareBreakpoint() WriteDBG() => 0x%8.8x.", kret);
+
+            if (kret == KERN_SUCCESS)
+                return i;
+        }
+//        else
+//        {
+//            if (log) log->Printf ("RegisterContextDarwin_arm::EnableHardwareBreakpoint(addr = %8.8p, size = %u) => all hardware breakpoint resources are being used.", addr, size);
+//        }
+    }
+
+    return LLDB_INVALID_INDEX32;
+}
+
+bool
+RegisterContextDarwin_arm::ClearHardwareBreakpoint (uint32_t hw_index)
+{
+    int kret = ReadDBG (false);
+
+    const uint32_t num_hw_points = NumSupportedHardwareBreakpoints();
+    if (kret == KERN_SUCCESS)
+    {
+        if (hw_index < num_hw_points)
+        {
+            dbg.bcr[hw_index] = 0;
+//            if (log) log->Printf ("RegisterContextDarwin_arm::SetHardwareBreakpoint( %u ) - BVR%u = 0x%8.8x  BCR%u = 0x%8.8x",
+//                    hw_index,
+//                    hw_index,
+//                    dbg.bvr[hw_index],
+//                    hw_index,
+//                    dbg.bcr[hw_index]);
+
+            kret = WriteDBG();
+
+            if (kret == KERN_SUCCESS)
+                return true;
+        }
+    }
+    return false;
+}
+
+uint32_t
+RegisterContextDarwin_arm::NumSupportedHardwareWatchpoints ()
+{
+#if defined (__arm__)
+    // Set the init value to something that will let us know that we need to
+    // autodetect how many watchpoints are supported dynamically...
+    static uint32_t g_num_supported_hw_watchpoints = UINT32_MAX;
+    if (g_num_supported_hw_watchpoints == UINT32_MAX)
+    {
+        // Set this to zero in case we can't tell if there are any HW breakpoints
+        g_num_supported_hw_watchpoints = 0;
+
+        uint32_t register_DBGDIDR;
+        asm("mrc p14, 0, %0, c0, c0, 0" : "=r" (register_DBGDIDR));
+        g_num_supported_hw_watchpoints = Bits32 (register_DBGDIDR, 31, 28) + 1;
+//        if (log) log->Printf ("DBGDIDR=0x%8.8x (number WRP pairs = %u)", register_DBGDIDR, g_num_supported_hw_watchpoints);
+    }
+    return g_num_supported_hw_watchpoints;
+#else
+    // TODO: figure out remote case here!
+    return 2;
+#endif
+}
+
+
+uint32_t
+RegisterContextDarwin_arm::SetHardwareWatchpoint (lldb::addr_t addr, size_t size, bool read, bool write)
+{
+//    if (log) log->Printf ("RegisterContextDarwin_arm::EnableHardwareWatchpoint(addr = %8.8p, size = %u, read = %u, write = %u)", addr, size, read, write);
+
+    const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
+
+    // Can't watch zero bytes
+    if (size == 0)
+        return LLDB_INVALID_INDEX32;
+
+    // We must watch for either read or write
+    if (read == false && write == false)
+        return LLDB_INVALID_INDEX32;
+
+    // Can't watch more than 4 bytes per WVR/WCR pair
+    if (size > 4)
+        return LLDB_INVALID_INDEX32;
+
+    // We can only watch up to four bytes that follow a 4 byte aligned address
+    // per watchpoint register pair. Since we have at most so we can only watch
+    // until the next 4 byte boundary and we need to make sure we can properly
+    // encode this.
+    uint32_t addr_word_offset = addr % 4;
+//    if (log) log->Printf ("RegisterContextDarwin_arm::EnableHardwareWatchpoint() - addr_word_offset = 0x%8.8x", addr_word_offset);
+
+    uint32_t byte_mask = ((1u << size) - 1u) << addr_word_offset;
+//    if (log) log->Printf ("RegisterContextDarwin_arm::EnableHardwareWatchpoint() - byte_mask = 0x%8.8x", byte_mask);
+    if (byte_mask > 0xfu)
+        return LLDB_INVALID_INDEX32;
+
+    // Read the debug state
+    int kret = ReadDBG (false);
+
+    if (kret == KERN_SUCCESS)
+    {
+        // Check to make sure we have the needed hardware support
+        uint32_t i = 0;
+
+        for (i=0; i<num_hw_watchpoints; ++i)
+        {
+            if ((dbg.wcr[i] & WCR_ENABLE) == 0)
+                break; // We found an available hw breakpoint slot (in i)
+        }
+
+        // See if we found an available hw breakpoint slot above
+        if (i < num_hw_watchpoints)
+        {
+            // Make the byte_mask into a valid Byte Address Select mask
+            uint32_t byte_address_select = byte_mask << 5;
+            // Make sure bits 1:0 are clear in our address
+            dbg.wvr[i] = addr & ~((lldb::addr_t)3);
+            dbg.wcr[i] =  byte_address_select |       // Which bytes that follow the IMVA that we will watch
+                                    S_USER |                    // Stop only in user mode
+                                    (read ? WCR_LOAD : 0) |     // Stop on read access?
+                                    (write ? WCR_STORE : 0) |   // Stop on write access?
+                                    WCR_ENABLE;                 // Enable this watchpoint;
+
+            kret = WriteDBG();
+//            if (log) log->Printf ("RegisterContextDarwin_arm::EnableHardwareWatchpoint() WriteDBG() => 0x%8.8x.", kret);
+
+            if (kret == KERN_SUCCESS)
+                return i;
+        }
+        else
+        {
+//            if (log) log->Printf ("RegisterContextDarwin_arm::EnableHardwareWatchpoint(): All hardware resources (%u) are in use.", num_hw_watchpoints);
+        }
+    }
+    return LLDB_INVALID_INDEX32;
+}
+
+bool
+RegisterContextDarwin_arm::ClearHardwareWatchpoint (uint32_t hw_index)
+{
+    int kret = ReadDBG (false);
+
+    const uint32_t num_hw_points = NumSupportedHardwareWatchpoints();
+    if (kret == KERN_SUCCESS)
+    {
+        if (hw_index < num_hw_points)
+        {
+            dbg.wcr[hw_index] = 0;
+//            if (log) log->Printf ("RegisterContextDarwin_arm::ClearHardwareWatchpoint( %u ) - WVR%u = 0x%8.8x  WCR%u = 0x%8.8x",
+//                    hw_index,
+//                    hw_index,
+//                    dbg.wvr[hw_index],
+//                    hw_index,
+//                    dbg.wcr[hw_index]);
+
+            kret = WriteDBG();
+
+            if (kret == KERN_SUCCESS)
+                return true;
+        }
+    }
+    return false;
+}
+
+#endif
diff --git a/source/Plugins/Process/Utility/RegisterContextDarwin_arm.h b/source/Plugins/Process/Utility/RegisterContextDarwin_arm.h
new file mode 100644
index 000000000000..0bf204f57c80
--- /dev/null
+++ b/source/Plugins/Process/Utility/RegisterContextDarwin_arm.h
@@ -0,0 +1,333 @@
+//===-- RegisterContextDarwin_arm.h -----------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_RegisterContextDarwin_arm_h_
+#define liblldb_RegisterContextDarwin_arm_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Target/RegisterContext.h"
+
+// BCR address match type
+#define BCR_M_IMVA_MATCH        ((uint32_t)(0u << 21))
+#define BCR_M_CONTEXT_ID_MATCH  ((uint32_t)(1u << 21))
+#define BCR_M_IMVA_MISMATCH     ((uint32_t)(2u << 21))
+#define BCR_M_RESERVED          ((uint32_t)(3u << 21))
+
+// Link a BVR/BCR or WVR/WCR pair to another
+#define E_ENABLE_LINKING        ((uint32_t)(1u << 20))
+
+// Byte Address Select
+#define BAS_IMVA_PLUS_0         ((uint32_t)(1u << 5))
+#define BAS_IMVA_PLUS_1         ((uint32_t)(1u << 6))
+#define BAS_IMVA_PLUS_2         ((uint32_t)(1u << 7))
+#define BAS_IMVA_PLUS_3         ((uint32_t)(1u << 8))
+#define BAS_IMVA_0_1            ((uint32_t)(3u << 5))
+#define BAS_IMVA_2_3            ((uint32_t)(3u << 7))
+#define BAS_IMVA_ALL            ((uint32_t)(0xfu << 5))
+
+// Break only in privileged or user mode
+#define S_RSVD                  ((uint32_t)(0u << 1))
+#define S_PRIV                  ((uint32_t)(1u << 1))
+#define S_USER                  ((uint32_t)(2u << 1))
+#define S_PRIV_USER             ((S_PRIV) | (S_USER))
+
+#define BCR_ENABLE              ((uint32_t)(1u))
+#define WCR_ENABLE              ((uint32_t)(1u))
+
+// Watchpoint load/store
+#define WCR_LOAD                ((uint32_t)(1u << 3))
+#define WCR_STORE               ((uint32_t)(1u << 4))
+
+class RegisterContextDarwin_arm : public lldb_private::RegisterContext
+{
+public:
+
+    RegisterContextDarwin_arm(lldb_private::Thread &thread, uint32_t concrete_frame_idx);
+
+    virtual
+    ~RegisterContextDarwin_arm();
+
+    virtual void
+    InvalidateAllRegisters ();
+
+    virtual size_t
+    GetRegisterCount ();
+
+    virtual const lldb_private::RegisterInfo *
+    GetRegisterInfoAtIndex (size_t reg);
+
+    virtual size_t
+    GetRegisterSetCount ();
+
+    virtual const lldb_private::RegisterSet *
+    GetRegisterSet (size_t set);
+
+    virtual bool
+    ReadRegister (const lldb_private::RegisterInfo *reg_info, 
+                  lldb_private::RegisterValue &reg_value);
+    
+    virtual bool
+    WriteRegister (const lldb_private::RegisterInfo *reg_info,
+                   const lldb_private::RegisterValue &reg_value);
+    
+    virtual bool
+    ReadAllRegisterValues (lldb::DataBufferSP &data_sp);
+
+    virtual bool
+    WriteAllRegisterValues (const lldb::DataBufferSP &data_sp);
+
+    virtual uint32_t
+    ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num);
+
+    virtual uint32_t
+    NumSupportedHardwareBreakpoints ();
+
+    virtual uint32_t
+    SetHardwareBreakpoint (lldb::addr_t addr, size_t size);
+
+    virtual bool
+    ClearHardwareBreakpoint (uint32_t hw_idx);
+
+    virtual uint32_t
+    NumSupportedHardwareWatchpoints ();
+
+    virtual uint32_t
+    SetHardwareWatchpoint (lldb::addr_t addr, size_t size, bool read, bool write);
+
+    virtual bool
+    ClearHardwareWatchpoint (uint32_t hw_index);
+
+    struct GPR
+    {
+        uint32_t    r[16];  // R0-R15
+        uint32_t    cpsr;   // CPSR
+    };
+
+
+    struct QReg
+    {
+        uint8_t bytes[16];
+    };
+
+    struct FPU
+    {
+        union {
+            uint32_t s[32];
+            uint64_t d[32];
+            QReg     q[16];  // the 128-bit NEON registers
+        } floats;
+        uint32_t fpscr;
+    };
+
+//  struct NeonReg
+//  {
+//      uint8_t bytes[16];
+//  };
+//
+//  struct VFPv3
+//  {
+//      union {
+//          uint32_t s[32];
+//          uint64_t d[32];
+//          NeonReg  q[16];
+//      } v3;
+//      uint32_t fpscr;
+//  };
+
+    struct EXC
+    {
+        uint32_t    exception;
+        uint32_t    fsr; /* Fault status */
+        uint32_t    far; /* Virtual Fault Address */
+    };
+
+    struct DBG
+    {
+        uint32_t bvr[16];
+        uint32_t bcr[16];
+        uint32_t wvr[16];
+        uint32_t wcr[16];
+    };
+
+    static void
+    LogDBGRegisters (lldb_private::Log *log, const DBG& dbg);
+
+protected:
+
+    enum
+    {
+        GPRRegSet = 1, // ARM_THREAD_STATE
+        FPURegSet = 2, // ARM_VFP_STATE
+        EXCRegSet = 3, // ARM_EXCEPTION_STATE
+        DBGRegSet = 4  // ARM_DEBUG_STATE
+    };
+
+    enum
+    {
+        GPRWordCount = sizeof(GPR)/sizeof(uint32_t),
+        FPUWordCount = sizeof(FPU)/sizeof(uint32_t),
+        EXCWordCount = sizeof(EXC)/sizeof(uint32_t),
+        DBGWordCount = sizeof(DBG)/sizeof(uint32_t)
+    };
+
+    enum
+    {
+        Read = 0,
+        Write = 1,
+        kNumErrors = 2
+    };
+
+    GPR gpr;
+    FPU fpu;
+    EXC exc;
+    DBG dbg;
+    int gpr_errs[2]; // Read/Write errors
+    int fpu_errs[2]; // Read/Write errors
+    int exc_errs[2]; // Read/Write errors
+    int dbg_errs[2]; // Read/Write errors
+
+    void
+    InvalidateAllRegisterStates()
+    {
+        SetError (GPRRegSet, Read, -1);
+        SetError (FPURegSet, Read, -1);
+        SetError (EXCRegSet, Read, -1);
+    }
+
+    int
+    GetError (int flavor, uint32_t err_idx) const
+    {
+        if (err_idx < kNumErrors)
+        {
+            switch (flavor)
+            {
+            // When getting all errors, just OR all values together to see if
+            // we got any kind of error.
+            case GPRRegSet:    return gpr_errs[err_idx];
+            case FPURegSet:    return fpu_errs[err_idx];
+            case EXCRegSet:    return exc_errs[err_idx];
+            case DBGRegSet:    return dbg_errs[err_idx];
+            default: break;
+            }
+        }
+        return -1;
+    }
+
+    bool
+    SetError (int flavor, uint32_t err_idx, int err)
+    {
+        if (err_idx < kNumErrors)
+        {
+            switch (flavor)
+            {
+            case GPRRegSet:
+                gpr_errs[err_idx] = err;
+                return true;
+
+            case FPURegSet:
+                fpu_errs[err_idx] = err;
+                return true;
+
+            case EXCRegSet:
+                exc_errs[err_idx] = err;
+                return true;
+
+            case DBGRegSet:
+                exc_errs[err_idx] = err;
+                return true;
+
+            default: break;
+            }
+        }
+        return false;
+    }
+
+    bool
+    RegisterSetIsCached (int set) const
+    {
+        return GetError(set, Read) == 0;
+    }
+
+    int
+    ReadGPR (bool force);
+
+    int
+    ReadFPU (bool force);
+
+    int
+    ReadEXC (bool force);
+
+    int
+    ReadDBG (bool force);
+
+    int
+    WriteGPR ();
+
+    int
+    WriteFPU ();
+
+    int
+    WriteEXC ();
+
+    int
+    WriteDBG ();
+
+    
+    // Subclasses override these to do the actual reading.
+    virtual int
+    DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr)
+    {
+        return -1;
+    }
+    
+    virtual int
+    DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu) = 0;
+    
+    virtual int
+    DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc) = 0;
+
+    virtual int
+    DoReadDBG (lldb::tid_t tid, int flavor, DBG &dbg) = 0;
+
+    virtual int
+    DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr) = 0;
+    
+    virtual int
+    DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu) = 0;
+    
+    virtual int
+    DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc) = 0;
+
+    virtual int
+    DoWriteDBG (lldb::tid_t tid, int flavor, const DBG &dbg) = 0;
+
+    int
+    ReadRegisterSet (uint32_t set, bool force);
+
+    int
+    WriteRegisterSet (uint32_t set);
+
+    static uint32_t
+    GetRegisterNumber (uint32_t reg_kind, uint32_t reg_num);
+
+    static int
+    GetSetForNativeRegNum (int reg_num);
+
+    static size_t
+    GetRegisterInfosCount ();
+
+    static const lldb_private::RegisterInfo *
+    GetRegisterInfos ();
+};
+
+#endif  // liblldb_RegisterContextDarwin_arm_h_
diff --git a/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp b/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp
new file mode 100644
index 000000000000..a94d1f538a28
--- /dev/null
+++ b/source/Plugins/Process/Utility/RegisterContextDarwin_i386.cpp
@@ -0,0 +1,980 @@
+//===-- RegisterContextDarwin_i386.cpp --------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+
+// C Includes
+#include <stddef.h>  // offsetof
+
+// C++ Includes
+// Other libraries and framework includes
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/RegisterValue.h"
+#include "lldb/Core/Scalar.h"
+#include "lldb/Host/Endian.h"
+#include "llvm/Support/Compiler.h"
+
+// Support building against older versions of LLVM, this macro was added
+// recently.
+#ifndef LLVM_EXTENSION
+#define LLVM_EXTENSION
+#endif
+
+// Project includes
+#include "RegisterContextDarwin_i386.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+enum
+{
+    gpr_eax = 0,
+    gpr_ebx,
+    gpr_ecx,
+    gpr_edx,
+    gpr_edi,
+    gpr_esi,
+    gpr_ebp,
+    gpr_esp,
+    gpr_ss,
+    gpr_eflags,
+    gpr_eip,
+    gpr_cs,
+    gpr_ds,
+    gpr_es,
+    gpr_fs,
+    gpr_gs,
+
+    fpu_fcw,
+    fpu_fsw,
+    fpu_ftw,
+    fpu_fop,
+    fpu_ip,
+    fpu_cs,
+    fpu_dp,
+    fpu_ds,
+    fpu_mxcsr,
+    fpu_mxcsrmask,
+    fpu_stmm0,
+    fpu_stmm1,
+    fpu_stmm2,
+    fpu_stmm3,
+    fpu_stmm4,
+    fpu_stmm5,
+    fpu_stmm6,
+    fpu_stmm7,
+    fpu_xmm0,
+    fpu_xmm1,
+    fpu_xmm2,
+    fpu_xmm3,
+    fpu_xmm4,
+    fpu_xmm5,
+    fpu_xmm6,
+    fpu_xmm7,
+
+    exc_trapno,
+    exc_err,
+    exc_faultvaddr,
+
+    k_num_registers,
+
+    // Aliases
+    fpu_fctrl = fpu_fcw,
+    fpu_fstat = fpu_fsw,
+    fpu_ftag  = fpu_ftw,
+    fpu_fiseg = fpu_cs,
+    fpu_fioff = fpu_ip,
+    fpu_foseg = fpu_ds,
+    fpu_fooff = fpu_dp
+};
+
+enum
+{
+    gcc_eax = 0,
+    gcc_ecx,
+    gcc_edx,
+    gcc_ebx,
+    gcc_ebp,
+    gcc_esp,
+    gcc_esi,
+    gcc_edi,
+    gcc_eip,
+    gcc_eflags
+};
+
+enum
+{
+    dwarf_eax = 0,
+    dwarf_ecx,
+    dwarf_edx,
+    dwarf_ebx,
+    dwarf_esp,
+    dwarf_ebp,
+    dwarf_esi,
+    dwarf_edi,
+    dwarf_eip,
+    dwarf_eflags,
+    dwarf_stmm0 = 11,
+    dwarf_stmm1,
+    dwarf_stmm2,
+    dwarf_stmm3,
+    dwarf_stmm4,
+    dwarf_stmm5,
+    dwarf_stmm6,
+    dwarf_stmm7,
+    dwarf_xmm0 = 21,
+    dwarf_xmm1,
+    dwarf_xmm2,
+    dwarf_xmm3,
+    dwarf_xmm4,
+    dwarf_xmm5,
+    dwarf_xmm6,
+    dwarf_xmm7
+};
+
+enum
+{
+    gdb_eax        =  0,
+    gdb_ecx        =  1,
+    gdb_edx        =  2,
+    gdb_ebx        =  3,
+    gdb_esp        =  4,
+    gdb_ebp        =  5,
+    gdb_esi        =  6,
+    gdb_edi        =  7,
+    gdb_eip        =  8,
+    gdb_eflags     =  9,
+    gdb_cs         = 10,
+    gdb_ss         = 11,
+    gdb_ds         = 12,
+    gdb_es         = 13,
+    gdb_fs         = 14,
+    gdb_gs         = 15,
+    gdb_stmm0      = 16,
+    gdb_stmm1      = 17,
+    gdb_stmm2      = 18,
+    gdb_stmm3      = 19,
+    gdb_stmm4      = 20,
+    gdb_stmm5      = 21,
+    gdb_stmm6      = 22,
+    gdb_stmm7      = 23,
+    gdb_fctrl      = 24,    gdb_fcw     = gdb_fctrl,
+    gdb_fstat      = 25,    gdb_fsw     = gdb_fstat,
+    gdb_ftag       = 26,    gdb_ftw     = gdb_ftag,
+    gdb_fiseg      = 27,    gdb_fpu_cs  = gdb_fiseg,
+    gdb_fioff      = 28,    gdb_ip      = gdb_fioff,
+    gdb_foseg      = 29,    gdb_fpu_ds  = gdb_foseg,
+    gdb_fooff      = 30,    gdb_dp      = gdb_fooff,
+    gdb_fop        = 31,
+    gdb_xmm0       = 32,
+    gdb_xmm1       = 33,
+    gdb_xmm2       = 34,
+    gdb_xmm3       = 35,
+    gdb_xmm4       = 36,
+    gdb_xmm5       = 37,
+    gdb_xmm6       = 38,
+    gdb_xmm7       = 39,
+    gdb_mxcsr      = 40,
+    gdb_mm0        = 41,
+    gdb_mm1        = 42,
+    gdb_mm2        = 43,
+    gdb_mm3        = 44,
+    gdb_mm4        = 45,
+    gdb_mm5        = 46,
+    gdb_mm6        = 47,
+    gdb_mm7        = 48
+};
+
+RegisterContextDarwin_i386::RegisterContextDarwin_i386 (Thread &thread, uint32_t concrete_frame_idx) :
+    RegisterContext(thread, concrete_frame_idx),
+    gpr(),
+    fpu(),
+    exc()
+{
+    uint32_t i;
+    for (i=0; i<kNumErrors; i++)
+    {
+        gpr_errs[i] = -1;
+        fpu_errs[i] = -1;
+        exc_errs[i] = -1;
+    }
+}
+
+RegisterContextDarwin_i386::~RegisterContextDarwin_i386()
+{
+}
+
+
+
+#define GPR_OFFSET(reg) (LLVM_EXTENSION offsetof (RegisterContextDarwin_i386::GPR, reg))
+#define FPU_OFFSET(reg) (LLVM_EXTENSION offsetof (RegisterContextDarwin_i386::FPU, reg) + sizeof (RegisterContextDarwin_i386::GPR))
+#define EXC_OFFSET(reg) (LLVM_EXTENSION offsetof (RegisterContextDarwin_i386::EXC, reg) + sizeof (RegisterContextDarwin_i386::GPR) + sizeof (RegisterContextDarwin_i386::FPU))
+
+// These macros will auto define the register name, alt name, register size,
+// register offset, encoding, format and native register. This ensures that
+// the register state structures are defined correctly and have the correct
+// sizes and offsets.
+#define DEFINE_GPR(reg, alt)    #reg, alt, sizeof(((RegisterContextDarwin_i386::GPR *)NULL)->reg), GPR_OFFSET(reg), eEncodingUint, eFormatHex
+#define DEFINE_FPU_UINT(reg)    #reg, NULL, sizeof(((RegisterContextDarwin_i386::FPU *)NULL)->reg), FPU_OFFSET(reg), eEncodingUint, eFormatHex
+#define DEFINE_FPU_VECT(reg, i) #reg#i, NULL, sizeof(((RegisterContextDarwin_i386::FPU *)NULL)->reg[i].bytes), FPU_OFFSET(reg[i]), eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_##reg##i, LLDB_INVALID_REGNUM, gdb_##reg##i, fpu_##reg##i }, NULL, NULL
+
+#define DEFINE_EXC(reg)         #reg, NULL, sizeof(((RegisterContextDarwin_i386::EXC *)NULL)->reg), EXC_OFFSET(reg), eEncodingUint, eFormatHex
+#define REG_CONTEXT_SIZE (sizeof (RegisterContextDarwin_i386::GPR) + sizeof (RegisterContextDarwin_i386::FPU) + sizeof (RegisterContextDarwin_i386::EXC))
+
+static RegisterInfo g_register_infos[] =
+{
+//  Macro auto defines most stuff   GCC                     DWARF                 GENERIC                    GDB                  LLDB              VALUE REGS    INVALIDATE REGS
+//  =============================== ======================= ===================   =========================  ==================   ================= ==========    ===============
+    { DEFINE_GPR(eax    , NULL)     , { gcc_eax             , dwarf_eax          , LLDB_INVALID_REGNUM       , gdb_eax            , gpr_eax      },      NULL,              NULL},
+    { DEFINE_GPR(ebx    , NULL)     , { gcc_ebx             , dwarf_ebx          , LLDB_INVALID_REGNUM       , gdb_ebx            , gpr_ebx      },      NULL,              NULL},
+    { DEFINE_GPR(ecx    , NULL)     , { gcc_ecx             , dwarf_ecx          , LLDB_INVALID_REGNUM       , gdb_ecx            , gpr_ecx      },      NULL,              NULL},
+    { DEFINE_GPR(edx    , NULL)     , { gcc_edx             , dwarf_edx          , LLDB_INVALID_REGNUM       , gdb_edx            , gpr_edx      },      NULL,              NULL},
+    { DEFINE_GPR(edi    , NULL)     , { gcc_edi             , dwarf_edi          , LLDB_INVALID_REGNUM       , gdb_edi            , gpr_edi      },      NULL,              NULL},
+    { DEFINE_GPR(esi    , NULL)     , { gcc_esi             , dwarf_esi          , LLDB_INVALID_REGNUM       , gdb_esi            , gpr_esi      },      NULL,              NULL},
+    { DEFINE_GPR(ebp    , "fp")     , { gcc_ebp             , dwarf_ebp          , LLDB_REGNUM_GENERIC_FP    , gdb_ebp            , gpr_ebp      },      NULL,              NULL},
+    { DEFINE_GPR(esp    , "sp")     , { gcc_esp             , dwarf_esp          , LLDB_REGNUM_GENERIC_SP    , gdb_esp            , gpr_esp      },      NULL,              NULL},
+    { DEFINE_GPR(ss     , NULL)     , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM       , gdb_ss             , gpr_ss       },      NULL,              NULL},
+    { DEFINE_GPR(eflags , "flags")  , { gcc_eflags          , dwarf_eflags       , LLDB_REGNUM_GENERIC_FLAGS , gdb_eflags         , gpr_eflags   },      NULL,              NULL},
+    { DEFINE_GPR(eip    , "pc")     , { gcc_eip             , dwarf_eip          , LLDB_REGNUM_GENERIC_PC    , gdb_eip            , gpr_eip      },      NULL,              NULL},
+    { DEFINE_GPR(cs     , NULL)     , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM       , gdb_cs             , gpr_cs       },      NULL,              NULL},
+    { DEFINE_GPR(ds     , NULL)     , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM       , gdb_ds             , gpr_ds       },      NULL,              NULL},
+    { DEFINE_GPR(es     , NULL)     , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM       , gdb_es             , gpr_es       },      NULL,              NULL},
+    { DEFINE_GPR(fs     , NULL)     , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM       , gdb_fs             , gpr_fs       },      NULL,              NULL},
+    { DEFINE_GPR(gs     , NULL)     , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM       , gdb_gs             , gpr_gs       },      NULL,              NULL},
+
+    { DEFINE_FPU_UINT(fcw)          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM       , gdb_fcw            , fpu_fcw      },      NULL,              NULL},
+    { DEFINE_FPU_UINT(fsw)          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM       , gdb_fsw            , fpu_fsw      },      NULL,              NULL},
+    { DEFINE_FPU_UINT(ftw)          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM       , gdb_ftw            , fpu_ftw      },      NULL,              NULL},
+    { DEFINE_FPU_UINT(fop)          , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM       , gdb_fop            , fpu_fop      },      NULL,              NULL},
+    { DEFINE_FPU_UINT(ip)           , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM       , gdb_ip             , fpu_ip       },      NULL,              NULL},
+    { DEFINE_FPU_UINT(cs)           , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM       , gdb_cs             , fpu_cs       },      NULL,              NULL},
+    { DEFINE_FPU_UINT(dp)           , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM       , gdb_dp             , fpu_dp       },      NULL,              NULL},
+    { DEFINE_FPU_UINT(ds)           , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM       , gdb_ds             , fpu_ds       },      NULL,              NULL},
+    { DEFINE_FPU_UINT(mxcsr)        , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM       , gdb_mxcsr          , fpu_mxcsr    },      NULL,              NULL},
+    { DEFINE_FPU_UINT(mxcsrmask)    , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM       , LLDB_INVALID_REGNUM, fpu_mxcsrmask},      NULL,              NULL},
+    { DEFINE_FPU_VECT(stmm,0)   },
+    { DEFINE_FPU_VECT(stmm,1)   },
+    { DEFINE_FPU_VECT(stmm,2)   },
+    { DEFINE_FPU_VECT(stmm,3)   },
+    { DEFINE_FPU_VECT(stmm,4)   },
+    { DEFINE_FPU_VECT(stmm,5)   },
+    { DEFINE_FPU_VECT(stmm,6)   },
+    { DEFINE_FPU_VECT(stmm,7)   },
+    { DEFINE_FPU_VECT(xmm,0)    },
+    { DEFINE_FPU_VECT(xmm,1)    },
+    { DEFINE_FPU_VECT(xmm,2)    },
+    { DEFINE_FPU_VECT(xmm,3)    },
+    { DEFINE_FPU_VECT(xmm,4)    },
+    { DEFINE_FPU_VECT(xmm,5)    },
+    { DEFINE_FPU_VECT(xmm,6)    },
+    { DEFINE_FPU_VECT(xmm,7)    },
+
+    { DEFINE_EXC(trapno)            , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM   , LLDB_INVALID_REGNUM     , LLDB_INVALID_REGNUM, exc_trapno },       NULL,              NULL},
+    { DEFINE_EXC(err)               , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM   , LLDB_INVALID_REGNUM     , LLDB_INVALID_REGNUM, exc_err },          NULL,              NULL},
+    { DEFINE_EXC(faultvaddr)        , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM   , LLDB_INVALID_REGNUM     , LLDB_INVALID_REGNUM, exc_faultvaddr },   NULL,              NULL}
+};
+
+static size_t k_num_register_infos = (sizeof(g_register_infos)/sizeof(RegisterInfo));
+
+void
+RegisterContextDarwin_i386::InvalidateAllRegisters ()
+{
+    InvalidateAllRegisterStates();
+}
+
+
+size_t
+RegisterContextDarwin_i386::GetRegisterCount ()
+{
+    assert(k_num_register_infos == k_num_registers);
+    return k_num_registers;
+}
+
+const RegisterInfo *
+RegisterContextDarwin_i386::GetRegisterInfoAtIndex (size_t reg)
+{
+    assert(k_num_register_infos == k_num_registers);
+    if (reg < k_num_registers)
+        return &g_register_infos[reg];
+    return NULL;
+}
+
+size_t
+RegisterContextDarwin_i386::GetRegisterInfosCount ()
+{
+    return k_num_register_infos;
+}
+
+const RegisterInfo *
+RegisterContextDarwin_i386::GetRegisterInfos ()
+{
+    return g_register_infos;
+}
+
+
+// General purpose registers
+static uint32_t
+g_gpr_regnums[] =
+{
+    gpr_eax,
+    gpr_ebx,
+    gpr_ecx,
+    gpr_edx,
+    gpr_edi,
+    gpr_esi,
+    gpr_ebp,
+    gpr_esp,
+    gpr_ss,
+    gpr_eflags,
+    gpr_eip,
+    gpr_cs,
+    gpr_ds,
+    gpr_es,
+    gpr_fs,
+    gpr_gs
+};
+
+// Floating point registers
+static uint32_t
+g_fpu_regnums[] =
+{
+    fpu_fcw,
+    fpu_fsw,
+    fpu_ftw,
+    fpu_fop,
+    fpu_ip,
+    fpu_cs,
+    fpu_dp,
+    fpu_ds,
+    fpu_mxcsr,
+    fpu_mxcsrmask,
+    fpu_stmm0,
+    fpu_stmm1,
+    fpu_stmm2,
+    fpu_stmm3,
+    fpu_stmm4,
+    fpu_stmm5,
+    fpu_stmm6,
+    fpu_stmm7,
+    fpu_xmm0,
+    fpu_xmm1,
+    fpu_xmm2,
+    fpu_xmm3,
+    fpu_xmm4,
+    fpu_xmm5,
+    fpu_xmm6,
+    fpu_xmm7
+};
+
+// Exception registers
+
+static uint32_t
+g_exc_regnums[] =
+{
+    exc_trapno,
+    exc_err,
+    exc_faultvaddr
+};
+
+// Number of registers in each register set
+const size_t k_num_gpr_registers = sizeof(g_gpr_regnums) / sizeof(uint32_t);
+const size_t k_num_fpu_registers = sizeof(g_fpu_regnums) / sizeof(uint32_t);
+const size_t k_num_exc_registers = sizeof(g_exc_regnums) / sizeof(uint32_t);
+
+//----------------------------------------------------------------------
+// Register set definitions. The first definitions at register set index
+// of zero is for all registers, followed by other registers sets. The
+// register information for the all register set need not be filled in.
+//----------------------------------------------------------------------
+static const RegisterSet g_reg_sets[] =
+{
+    { "General Purpose Registers",  "gpr",  k_num_gpr_registers,    g_gpr_regnums,      },
+    { "Floating Point Registers",   "fpu",  k_num_fpu_registers,    g_fpu_regnums       },
+    { "Exception State Registers",  "exc",  k_num_exc_registers,    g_exc_regnums       }
+};
+
+const size_t k_num_regsets = sizeof(g_reg_sets) / sizeof(RegisterSet);
+
+
+size_t
+RegisterContextDarwin_i386::GetRegisterSetCount ()
+{
+    return k_num_regsets;
+}
+
+const RegisterSet *
+RegisterContextDarwin_i386::GetRegisterSet (size_t reg_set)
+{
+    if (reg_set < k_num_regsets)
+        return &g_reg_sets[reg_set];
+    return NULL;
+}
+
+
+//----------------------------------------------------------------------
+// Register information definitions for 32 bit i386.
+//----------------------------------------------------------------------
+int
+RegisterContextDarwin_i386::GetSetForNativeRegNum (int reg_num)
+{
+    if (reg_num < fpu_fcw)
+        return GPRRegSet;
+    else if (reg_num < exc_trapno)
+        return FPURegSet;
+    else if (reg_num < k_num_registers)
+        return EXCRegSet;
+    return -1;
+}
+
+
+void
+RegisterContextDarwin_i386::LogGPR(Log *log, const char *title)
+{
+    if (log)
+    {
+        if (title)
+            log->Printf ("%s", title);
+        for (uint32_t i=0; i<k_num_gpr_registers; i++)
+        {
+            uint32_t reg = gpr_eax + i;
+            log->Printf("%12s = 0x%8.8x", g_register_infos[reg].name, (&gpr.eax)[reg]);
+        }
+    }
+}
+
+
+
+int
+RegisterContextDarwin_i386::ReadGPR (bool force)
+{
+    int set = GPRRegSet;
+    if (force || !RegisterSetIsCached(set))
+    {
+        SetError(set, Read, DoReadGPR(GetThreadID(), set, gpr));
+    }
+    return GetError(set, Read);
+}
+
+int
+RegisterContextDarwin_i386::ReadFPU (bool force)
+{
+    int set = FPURegSet;
+    if (force || !RegisterSetIsCached(set))
+    {
+        SetError(set, Read, DoReadFPU(GetThreadID(), set, fpu));
+    }
+    return GetError(set, Read);
+}
+
+int
+RegisterContextDarwin_i386::ReadEXC (bool force)
+{
+    int set = EXCRegSet;
+    if (force || !RegisterSetIsCached(set))
+    {
+        SetError(set, Read, DoReadEXC(GetThreadID(), set, exc));
+    }
+    return GetError(set, Read);
+}
+
+int
+RegisterContextDarwin_i386::WriteGPR ()
+{
+    int set = GPRRegSet;
+    if (!RegisterSetIsCached(set))
+    {
+        SetError (set, Write, -1);
+        return -1;
+    }
+    SetError (set, Write, DoWriteGPR(GetThreadID(), set, gpr));
+    SetError (set, Read, -1);
+    return GetError(set, Write);
+}
+
+int
+RegisterContextDarwin_i386::WriteFPU ()
+{
+    int set = FPURegSet;
+    if (!RegisterSetIsCached(set))
+    {
+        SetError (set, Write, -1);
+        return -1;
+    }
+    SetError (set, Write, DoWriteFPU(GetThreadID(), set, fpu));
+    SetError (set, Read, -1);
+    return GetError(set, Write);
+}
+
+int
+RegisterContextDarwin_i386::WriteEXC ()
+{
+    int set = EXCRegSet;
+    if (!RegisterSetIsCached(set))
+    {
+        SetError (set, Write, -1);
+        return -1;
+    }
+    SetError (set, Write, DoWriteEXC(GetThreadID(), set, exc));
+    SetError (set, Read, -1);
+    return GetError(set, Write);
+}
+
+int
+RegisterContextDarwin_i386::ReadRegisterSet (uint32_t set, bool force)
+{
+    switch (set)
+    {
+    case GPRRegSet:    return ReadGPR(force);
+    case FPURegSet:    return ReadFPU(force);
+    case EXCRegSet:    return ReadEXC(force);
+    default: break;
+    }
+    return -1;
+}
+
+int
+RegisterContextDarwin_i386::WriteRegisterSet (uint32_t set)
+{
+    // Make sure we have a valid context to set.
+    if (RegisterSetIsCached(set))
+    {
+        switch (set)
+        {
+        case GPRRegSet:    return WriteGPR();
+        case FPURegSet:    return WriteFPU();
+        case EXCRegSet:    return WriteEXC();
+        default: break;
+        }
+    }
+    return -1;
+}
+
+bool
+RegisterContextDarwin_i386::ReadRegister (const RegisterInfo *reg_info,
+                                        RegisterValue &value)
+{
+    const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
+    int set = RegisterContextDarwin_i386::GetSetForNativeRegNum (reg);
+
+    if (set == -1)
+        return false;
+
+    if (ReadRegisterSet(set, false) != 0)
+        return false;
+
+    switch (reg)
+    {
+    case gpr_eax:
+    case gpr_ebx:
+    case gpr_ecx:
+    case gpr_edx:
+    case gpr_edi:
+    case gpr_esi:
+    case gpr_ebp:
+    case gpr_esp:
+    case gpr_ss:
+    case gpr_eflags:
+    case gpr_eip:
+    case gpr_cs:
+    case gpr_ds:
+    case gpr_es:
+    case gpr_fs:
+    case gpr_gs:
+        value = (&gpr.eax)[reg - gpr_eax];
+        break;
+
+    case fpu_fcw:
+        value = fpu.fcw;
+        break;
+
+    case fpu_fsw:
+        value = fpu.fsw;
+        break;
+
+    case fpu_ftw:
+        value  = fpu.ftw;
+        break;
+
+    case fpu_fop:
+        value = fpu.fop;
+        break;
+
+    case fpu_ip:
+        value = fpu.ip;
+        break;
+
+    case fpu_cs:
+        value = fpu.cs;
+        break;
+
+    case fpu_dp:
+        value = fpu.dp;
+        break;
+
+    case fpu_ds:
+        value = fpu.ds;
+        break;
+
+    case fpu_mxcsr:
+        value = fpu.mxcsr;
+        break;
+
+    case fpu_mxcsrmask:
+        value = fpu.mxcsrmask;
+        break;
+
+    case fpu_stmm0:
+    case fpu_stmm1:
+    case fpu_stmm2:
+    case fpu_stmm3:
+    case fpu_stmm4:
+    case fpu_stmm5:
+    case fpu_stmm6:
+    case fpu_stmm7:
+        // These values don't fit into scalar types,
+        // RegisterContext::ReadRegisterBytes() must be used for these
+        // registers
+        //::memcpy (reg_value.value.vector.uint8, fpu.stmm[reg - fpu_stmm0].bytes, 10);
+        return false;
+
+    case fpu_xmm0:
+    case fpu_xmm1:
+    case fpu_xmm2:
+    case fpu_xmm3:
+    case fpu_xmm4:
+    case fpu_xmm5:
+    case fpu_xmm6:
+    case fpu_xmm7:
+        // These values don't fit into scalar types, RegisterContext::ReadRegisterBytes()
+        // must be used for these registers
+        //::memcpy (reg_value.value.vector.uint8, fpu.xmm[reg - fpu_xmm0].bytes, 16);
+        return false;
+
+    case exc_trapno:
+        value = exc.trapno;
+        break;
+
+    case exc_err:
+        value = exc.err;
+        break;
+
+    case exc_faultvaddr:
+        value = exc.faultvaddr;
+        break;
+
+    default:
+        return false;
+    }
+    return true;
+}
+
+
+bool
+RegisterContextDarwin_i386::WriteRegister (const RegisterInfo *reg_info,
+                                         const RegisterValue &value)
+{
+    const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
+    int set = GetSetForNativeRegNum (reg);
+
+    if (set == -1)
+        return false;
+
+    if (ReadRegisterSet(set, false) != 0)
+        return false;
+
+    switch (reg)
+    {
+    case gpr_eax:
+    case gpr_ebx:
+    case gpr_ecx:
+    case gpr_edx:
+    case gpr_edi:
+    case gpr_esi:
+    case gpr_ebp:
+    case gpr_esp:
+    case gpr_ss:
+    case gpr_eflags:
+    case gpr_eip:
+    case gpr_cs:
+    case gpr_ds:
+    case gpr_es:
+    case gpr_fs:
+    case gpr_gs:
+        (&gpr.eax)[reg - gpr_eax] = value.GetAsUInt32();
+        break;
+
+    case fpu_fcw:
+        fpu.fcw = value.GetAsUInt16();
+        break;
+
+    case fpu_fsw:
+        fpu.fsw = value.GetAsUInt16();
+        break;
+
+    case fpu_ftw:
+        fpu.ftw = value.GetAsUInt8();
+        break;
+
+    case fpu_fop:
+        fpu.fop = value.GetAsUInt16();
+        break;
+
+    case fpu_ip:
+        fpu.ip = value.GetAsUInt32();
+        break;
+
+    case fpu_cs:
+        fpu.cs = value.GetAsUInt16();
+        break;
+
+    case fpu_dp:
+        fpu.dp = value.GetAsUInt32();
+        break;
+
+    case fpu_ds:
+        fpu.ds = value.GetAsUInt16();
+        break;
+
+    case fpu_mxcsr:
+        fpu.mxcsr = value.GetAsUInt32();
+        break;
+
+    case fpu_mxcsrmask:
+        fpu.mxcsrmask = value.GetAsUInt32();
+        break;
+
+    case fpu_stmm0:
+    case fpu_stmm1:
+    case fpu_stmm2:
+    case fpu_stmm3:
+    case fpu_stmm4:
+    case fpu_stmm5:
+    case fpu_stmm6:
+    case fpu_stmm7:
+        // These values don't fit into scalar types, RegisterContext::ReadRegisterBytes()
+        // must be used for these registers
+        ::memcpy (fpu.stmm[reg - fpu_stmm0].bytes, value.GetBytes(), value.GetByteSize());
+        return false;
+
+    case fpu_xmm0:
+    case fpu_xmm1:
+    case fpu_xmm2:
+    case fpu_xmm3:
+    case fpu_xmm4:
+    case fpu_xmm5:
+    case fpu_xmm6:
+    case fpu_xmm7:
+        // These values don't fit into scalar types, RegisterContext::ReadRegisterBytes()
+        // must be used for these registers
+        ::memcpy (fpu.xmm[reg - fpu_xmm0].bytes, value.GetBytes(), value.GetByteSize());
+        return false;
+
+    case exc_trapno:
+        exc.trapno = value.GetAsUInt32();
+        break;
+
+    case exc_err:
+        exc.err = value.GetAsUInt32();
+        break;
+
+    case exc_faultvaddr:
+        exc.faultvaddr = value.GetAsUInt32();
+        break;
+
+    default:
+        return false;
+    }
+    return WriteRegisterSet(set) == 0;
+}
+
+bool
+RegisterContextDarwin_i386::ReadAllRegisterValues (lldb::DataBufferSP &data_sp)
+{
+    data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0));
+    if (data_sp &&
+        ReadGPR (false) == 0 &&
+        ReadFPU (false) == 0 &&
+        ReadEXC (false) == 0)
+    {
+        uint8_t *dst = data_sp->GetBytes();
+        ::memcpy (dst, &gpr, sizeof(gpr));
+        dst += sizeof(gpr);
+
+        ::memcpy (dst, &fpu, sizeof(fpu));
+        dst += sizeof(gpr);
+
+        ::memcpy (dst, &exc, sizeof(exc));
+        return true;
+    }
+    return false;
+}
+
+bool
+RegisterContextDarwin_i386::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp)
+{
+    if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE)
+    {
+        const uint8_t *src = data_sp->GetBytes();
+        ::memcpy (&gpr, src, sizeof(gpr));
+        src += sizeof(gpr);
+
+        ::memcpy (&fpu, src, sizeof(fpu));
+        src += sizeof(gpr);
+
+        ::memcpy (&exc, src, sizeof(exc));
+        uint32_t success_count = 0;
+        if (WriteGPR() == 0)
+            ++success_count;
+        if (WriteFPU() == 0)
+            ++success_count;
+        if (WriteEXC() == 0)
+            ++success_count;
+        return success_count == 3;
+    }
+    return false;
+}
+
+
+uint32_t
+RegisterContextDarwin_i386::ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t reg)
+{
+    if (kind == eRegisterKindGeneric)
+    {
+        switch (reg)
+        {
+        case LLDB_REGNUM_GENERIC_PC:        return gpr_eip;
+        case LLDB_REGNUM_GENERIC_SP:        return gpr_esp;
+        case LLDB_REGNUM_GENERIC_FP:        return gpr_ebp;
+        case LLDB_REGNUM_GENERIC_FLAGS:     return gpr_eflags;
+        case LLDB_REGNUM_GENERIC_RA:
+        default:
+            break;
+        }
+    }
+    else if (kind == eRegisterKindGCC || kind == eRegisterKindDWARF)
+    {
+        switch (reg)
+        {
+        case dwarf_eax:     return gpr_eax;
+        case dwarf_ecx:     return gpr_ecx;
+        case dwarf_edx:     return gpr_edx;
+        case dwarf_ebx:     return gpr_ebx;
+        case dwarf_esp:     return gpr_esp;
+        case dwarf_ebp:     return gpr_ebp;
+        case dwarf_esi:     return gpr_esi;
+        case dwarf_edi:     return gpr_edi;
+        case dwarf_eip:     return gpr_eip;
+        case dwarf_eflags:  return gpr_eflags;
+        case dwarf_stmm0:   return fpu_stmm0;
+        case dwarf_stmm1:   return fpu_stmm1;
+        case dwarf_stmm2:   return fpu_stmm2;
+        case dwarf_stmm3:   return fpu_stmm3;
+        case dwarf_stmm4:   return fpu_stmm4;
+        case dwarf_stmm5:   return fpu_stmm5;
+        case dwarf_stmm6:   return fpu_stmm6;
+        case dwarf_stmm7:   return fpu_stmm7;
+        case dwarf_xmm0:    return fpu_xmm0;
+        case dwarf_xmm1:    return fpu_xmm1;
+        case dwarf_xmm2:    return fpu_xmm2;
+        case dwarf_xmm3:    return fpu_xmm3;
+        case dwarf_xmm4:    return fpu_xmm4;
+        case dwarf_xmm5:    return fpu_xmm5;
+        case dwarf_xmm6:    return fpu_xmm6;
+        case dwarf_xmm7:    return fpu_xmm7;
+        default:
+            break;
+        }
+    }
+    else if (kind == eRegisterKindGDB)
+    {
+        switch (reg)
+        {
+        case gdb_eax     : return gpr_eax;
+        case gdb_ebx     : return gpr_ebx;
+        case gdb_ecx     : return gpr_ecx;
+        case gdb_edx     : return gpr_edx;
+        case gdb_esi     : return gpr_esi;
+        case gdb_edi     : return gpr_edi;
+        case gdb_ebp     : return gpr_ebp;
+        case gdb_esp     : return gpr_esp;
+        case gdb_eip     : return gpr_eip;
+        case gdb_eflags  : return gpr_eflags;
+        case gdb_cs      : return gpr_cs;
+        case gdb_ss      : return gpr_ss;
+        case gdb_ds      : return gpr_ds;
+        case gdb_es      : return gpr_es;
+        case gdb_fs      : return gpr_fs;
+        case gdb_gs      : return gpr_gs;
+        case gdb_stmm0   : return fpu_stmm0;
+        case gdb_stmm1   : return fpu_stmm1;
+        case gdb_stmm2   : return fpu_stmm2;
+        case gdb_stmm3   : return fpu_stmm3;
+        case gdb_stmm4   : return fpu_stmm4;
+        case gdb_stmm5   : return fpu_stmm5;
+        case gdb_stmm6   : return fpu_stmm6;
+        case gdb_stmm7   : return fpu_stmm7;
+        case gdb_fctrl   : return fpu_fctrl;
+        case gdb_fstat   : return fpu_fstat;
+        case gdb_ftag    : return fpu_ftag;
+        case gdb_fiseg   : return fpu_fiseg;
+        case gdb_fioff   : return fpu_fioff;
+        case gdb_foseg   : return fpu_foseg;
+        case gdb_fooff   : return fpu_fooff;
+        case gdb_fop     : return fpu_fop;
+        case gdb_xmm0    : return fpu_xmm0;
+        case gdb_xmm1    : return fpu_xmm1;
+        case gdb_xmm2    : return fpu_xmm2;
+        case gdb_xmm3    : return fpu_xmm3;
+        case gdb_xmm4    : return fpu_xmm4;
+        case gdb_xmm5    : return fpu_xmm5;
+        case gdb_xmm6    : return fpu_xmm6;
+        case gdb_xmm7    : return fpu_xmm7;
+        case gdb_mxcsr   : return fpu_mxcsr;
+        default:
+            break;
+        }
+    }
+    else if (kind == eRegisterKindLLDB)
+    {
+        return reg;
+    }
+    return LLDB_INVALID_REGNUM;
+}
+
+
+bool
+RegisterContextDarwin_i386::HardwareSingleStep (bool enable)
+{
+    if (ReadGPR(false) != 0)
+        return false;
+
+    const uint32_t trace_bit = 0x100u;
+    if (enable)
+    {
+        // If the trace bit is already set, there is nothing to do
+        if (gpr.eflags & trace_bit)
+            return true;
+        else
+            gpr.eflags |= trace_bit;
+    }
+    else
+    {
+        // If the trace bit is already cleared, there is nothing to do
+        if (gpr.eflags & trace_bit)
+            gpr.eflags &= ~trace_bit;
+        else
+            return true;
+    }
+
+    return WriteGPR() == 0;
+}
+
+
+
diff --git a/source/Plugins/Process/Utility/RegisterContextDarwin_i386.h b/source/Plugins/Process/Utility/RegisterContextDarwin_i386.h
new file mode 100644
index 000000000000..a588494f9dcf
--- /dev/null
+++ b/source/Plugins/Process/Utility/RegisterContextDarwin_i386.h
@@ -0,0 +1,269 @@
+//===-- RegisterContextDarwin_i386.h ----------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_RegisterContextDarwin_i386_h_
+#define liblldb_RegisterContextDarwin_i386_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Target/RegisterContext.h"
+
+class RegisterContextDarwin_i386 : public lldb_private::RegisterContext
+{
+public:
+
+    RegisterContextDarwin_i386(lldb_private::Thread &thread,
+                             uint32_t concrete_frame_idx);
+
+    virtual
+    ~RegisterContextDarwin_i386();
+
+    virtual void
+    InvalidateAllRegisters ();
+
+    virtual size_t
+    GetRegisterCount ();
+
+    virtual const lldb_private::RegisterInfo *
+    GetRegisterInfoAtIndex (size_t reg);
+
+    virtual size_t
+    GetRegisterSetCount ();
+
+    virtual const lldb_private::RegisterSet *
+    GetRegisterSet (size_t set);
+
+    virtual bool
+    ReadRegister (const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value);
+
+    virtual bool
+    WriteRegister (const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value);
+    
+    virtual bool
+    ReadAllRegisterValues (lldb::DataBufferSP &data_sp);
+
+    virtual bool
+    WriteAllRegisterValues (const lldb::DataBufferSP &data_sp);
+
+    virtual uint32_t
+    ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num);
+
+    virtual bool
+    HardwareSingleStep (bool enable);
+
+    struct GPR
+    {
+        uint32_t eax;
+        uint32_t ebx;
+        uint32_t ecx;
+        uint32_t edx;
+        uint32_t edi;
+        uint32_t esi;
+        uint32_t ebp;
+        uint32_t esp;
+        uint32_t ss;
+        uint32_t eflags;
+        uint32_t eip;
+        uint32_t cs;
+        uint32_t ds;
+        uint32_t es;
+        uint32_t fs;
+        uint32_t gs;
+    };
+
+    struct MMSReg
+    {
+        uint8_t bytes[10];
+        uint8_t pad[6];
+    };
+
+    struct XMMReg
+    {
+        uint8_t bytes[16];
+    };
+
+    struct FPU
+    {
+        uint32_t    pad[2];
+        uint16_t    fcw;
+        uint16_t    fsw;
+        uint8_t     ftw;
+        uint8_t     pad1;
+        uint16_t    fop;
+        uint32_t    ip;
+        uint16_t    cs;
+        uint16_t    pad2;
+        uint32_t    dp;
+        uint16_t    ds;
+        uint16_t    pad3;
+        uint32_t    mxcsr;
+        uint32_t    mxcsrmask;
+        MMSReg      stmm[8];
+        XMMReg      xmm[8];
+        uint8_t     pad4[14*16];
+        int         pad5;
+    };
+
+    struct EXC
+    {
+        uint32_t trapno;
+        uint32_t err;
+        uint32_t faultvaddr;
+    };
+
+protected:
+
+    enum
+    {
+        GPRRegSet = 1,
+        FPURegSet = 2,
+        EXCRegSet = 3
+    };
+
+    enum
+    {
+        GPRWordCount = sizeof(GPR)/sizeof(uint32_t),
+        FPUWordCount = sizeof(FPU)/sizeof(uint32_t),
+        EXCWordCount = sizeof(EXC)/sizeof(uint32_t)
+    };
+
+    enum
+    {
+        Read = 0,
+        Write = 1,
+        kNumErrors = 2
+    };
+
+    GPR gpr;
+    FPU fpu;
+    EXC exc;
+    int gpr_errs[2]; // Read/Write errors
+    int fpu_errs[2]; // Read/Write errors
+    int exc_errs[2]; // Read/Write errors
+
+    void
+    InvalidateAllRegisterStates()
+    {
+        SetError (GPRRegSet, Read, -1);
+        SetError (FPURegSet, Read, -1);
+        SetError (EXCRegSet, Read, -1);
+    }
+
+    int
+    GetError (int flavor, uint32_t err_idx) const
+    {
+        if (err_idx < kNumErrors)
+        {
+            switch (flavor)
+            {
+            // When getting all errors, just OR all values together to see if
+            // we got any kind of error.
+            case GPRRegSet:    return gpr_errs[err_idx];
+            case FPURegSet:    return fpu_errs[err_idx];
+            case EXCRegSet:    return exc_errs[err_idx];
+            default: break;
+            }
+        }
+        return -1;
+    }
+
+    bool
+    SetError (int flavor, uint32_t err_idx, int err)
+    {
+        if (err_idx < kNumErrors)
+        {
+            switch (flavor)
+            {
+            case GPRRegSet:
+                gpr_errs[err_idx] = err;
+                return true;
+
+            case FPURegSet:
+                fpu_errs[err_idx] = err;
+                return true;
+
+            case EXCRegSet:
+                exc_errs[err_idx] = err;
+                return true;
+
+            default: break;
+            }
+        }
+        return false;
+    }
+
+    bool
+    RegisterSetIsCached (int set) const
+    {
+        return GetError(set, Read) == 0;
+    }
+
+    void
+    LogGPR (lldb_private::Log *log, const char *title);
+
+    int
+    ReadGPR (bool force);
+
+    int
+    ReadFPU (bool force);
+
+    int
+    ReadEXC (bool force);
+
+    int
+    WriteGPR ();
+
+    int
+    WriteFPU ();
+
+    int
+    WriteEXC ();
+
+    // Subclasses override these to do the actual reading.
+    virtual int
+    DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr) = 0;
+    
+    virtual int
+    DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu) = 0;
+
+    virtual int
+    DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc) = 0;
+
+    virtual int
+    DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr) = 0;
+    
+    virtual int
+    DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu) = 0;
+    
+    virtual int
+    DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc) = 0;
+
+    int
+    ReadRegisterSet (uint32_t set, bool force);
+
+    int
+    WriteRegisterSet (uint32_t set);
+
+    static uint32_t
+    GetRegisterNumber (uint32_t reg_kind, uint32_t reg_num);
+
+    static int
+    GetSetForNativeRegNum (int reg_num);
+
+    static size_t
+    GetRegisterInfosCount ();
+
+    static const lldb_private::RegisterInfo *
+    GetRegisterInfos ();
+};
+
+#endif  // liblldb_RegisterContextDarwin_i386_h_
diff --git a/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp b/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp
new file mode 100644
index 000000000000..433782fe20c0
--- /dev/null
+++ b/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.cpp
@@ -0,0 +1,1066 @@
+//===-- RegisterContextDarwin_x86_64.cpp ------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+
+// C Includes
+#include <stdarg.h>
+#include <stddef.h>  // offsetof
+
+// C++ Includes
+// Other libraries and framework includes
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/RegisterValue.h"
+#include "lldb/Core/Scalar.h"
+#include "lldb/Host/Endian.h"
+#include "llvm/Support/Compiler.h"
+
+// Support building against older versions of LLVM, this macro was added
+// recently.
+#ifndef LLVM_EXTENSION
+#define LLVM_EXTENSION
+#endif
+
+// Project includes
+#include "RegisterContextDarwin_x86_64.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+enum
+{
+    gpr_rax = 0,
+    gpr_rbx,
+    gpr_rcx,
+    gpr_rdx,
+    gpr_rdi,
+    gpr_rsi,
+    gpr_rbp,
+    gpr_rsp,
+    gpr_r8,
+    gpr_r9,
+    gpr_r10,
+    gpr_r11,
+    gpr_r12,
+    gpr_r13,
+    gpr_r14,
+    gpr_r15,
+    gpr_rip,
+    gpr_rflags,
+    gpr_cs,
+    gpr_fs,
+    gpr_gs,
+
+    fpu_fcw,
+    fpu_fsw,
+    fpu_ftw,
+    fpu_fop,
+    fpu_ip,
+    fpu_cs,
+    fpu_dp,
+    fpu_ds,
+    fpu_mxcsr,
+    fpu_mxcsrmask,
+    fpu_stmm0,
+    fpu_stmm1,
+    fpu_stmm2,
+    fpu_stmm3,
+    fpu_stmm4,
+    fpu_stmm5,
+    fpu_stmm6,
+    fpu_stmm7,
+    fpu_xmm0,
+    fpu_xmm1,
+    fpu_xmm2,
+    fpu_xmm3,
+    fpu_xmm4,
+    fpu_xmm5,
+    fpu_xmm6,
+    fpu_xmm7,
+    fpu_xmm8,
+    fpu_xmm9,
+    fpu_xmm10,
+    fpu_xmm11,
+    fpu_xmm12,
+    fpu_xmm13,
+    fpu_xmm14,
+    fpu_xmm15,
+
+    exc_trapno,
+    exc_err,
+    exc_faultvaddr,
+
+    k_num_registers,
+
+    // Aliases
+    fpu_fctrl = fpu_fcw,
+    fpu_fstat = fpu_fsw,
+    fpu_ftag  = fpu_ftw,
+    fpu_fiseg = fpu_cs,
+    fpu_fioff = fpu_ip,
+    fpu_foseg = fpu_ds,
+    fpu_fooff = fpu_dp
+};
+
+enum gcc_dwarf_regnums
+{
+    gcc_dwarf_gpr_rax = 0,
+    gcc_dwarf_gpr_rdx,
+    gcc_dwarf_gpr_rcx,
+    gcc_dwarf_gpr_rbx,
+    gcc_dwarf_gpr_rsi,
+    gcc_dwarf_gpr_rdi,
+    gcc_dwarf_gpr_rbp,
+    gcc_dwarf_gpr_rsp,
+    gcc_dwarf_gpr_r8,
+    gcc_dwarf_gpr_r9,
+    gcc_dwarf_gpr_r10,
+    gcc_dwarf_gpr_r11,
+    gcc_dwarf_gpr_r12,
+    gcc_dwarf_gpr_r13,
+    gcc_dwarf_gpr_r14,
+    gcc_dwarf_gpr_r15,
+    gcc_dwarf_gpr_rip,
+    gcc_dwarf_fpu_xmm0,
+    gcc_dwarf_fpu_xmm1,
+    gcc_dwarf_fpu_xmm2,
+    gcc_dwarf_fpu_xmm3,
+    gcc_dwarf_fpu_xmm4,
+    gcc_dwarf_fpu_xmm5,
+    gcc_dwarf_fpu_xmm6,
+    gcc_dwarf_fpu_xmm7,
+    gcc_dwarf_fpu_xmm8,
+    gcc_dwarf_fpu_xmm9,
+    gcc_dwarf_fpu_xmm10,
+    gcc_dwarf_fpu_xmm11,
+    gcc_dwarf_fpu_xmm12,
+    gcc_dwarf_fpu_xmm13,
+    gcc_dwarf_fpu_xmm14,
+    gcc_dwarf_fpu_xmm15,
+    gcc_dwarf_fpu_stmm0,
+    gcc_dwarf_fpu_stmm1,
+    gcc_dwarf_fpu_stmm2,
+    gcc_dwarf_fpu_stmm3,
+    gcc_dwarf_fpu_stmm4,
+    gcc_dwarf_fpu_stmm5,
+    gcc_dwarf_fpu_stmm6,
+    gcc_dwarf_fpu_stmm7
+
+};
+
+enum gdb_regnums
+{
+    gdb_gpr_rax     =   0,
+    gdb_gpr_rbx     =   1,
+    gdb_gpr_rcx     =   2,
+    gdb_gpr_rdx     =   3,
+    gdb_gpr_rsi     =   4,
+    gdb_gpr_rdi     =   5,
+    gdb_gpr_rbp     =   6,
+    gdb_gpr_rsp     =   7,
+    gdb_gpr_r8      =   8,
+    gdb_gpr_r9      =   9,
+    gdb_gpr_r10     =  10,
+    gdb_gpr_r11     =  11,
+    gdb_gpr_r12     =  12,
+    gdb_gpr_r13     =  13,
+    gdb_gpr_r14     =  14,
+    gdb_gpr_r15     =  15,
+    gdb_gpr_rip     =  16,
+    gdb_gpr_rflags  =  17,
+    gdb_gpr_cs      =  18,
+    gdb_gpr_ss      =  19,
+    gdb_gpr_ds      =  20,
+    gdb_gpr_es      =  21,
+    gdb_gpr_fs      =  22,
+    gdb_gpr_gs      =  23,
+    gdb_fpu_stmm0   =  24,
+    gdb_fpu_stmm1   =  25,
+    gdb_fpu_stmm2   =  26,
+    gdb_fpu_stmm3   =  27,
+    gdb_fpu_stmm4   =  28,
+    gdb_fpu_stmm5   =  29,
+    gdb_fpu_stmm6   =  30,
+    gdb_fpu_stmm7   =  31,
+    gdb_fpu_fctrl   =  32,  gdb_fpu_fcw = gdb_fpu_fctrl,
+    gdb_fpu_fstat   =  33,  gdb_fpu_fsw = gdb_fpu_fstat,
+    gdb_fpu_ftag    =  34,  gdb_fpu_ftw = gdb_fpu_ftag,
+    gdb_fpu_fiseg   =  35,  gdb_fpu_cs  = gdb_fpu_fiseg,
+    gdb_fpu_fioff   =  36,  gdb_fpu_ip  = gdb_fpu_fioff,
+    gdb_fpu_foseg   =  37,  gdb_fpu_ds  = gdb_fpu_foseg,
+    gdb_fpu_fooff   =  38,  gdb_fpu_dp  = gdb_fpu_fooff,
+    gdb_fpu_fop     =  39,
+    gdb_fpu_xmm0    =  40,
+    gdb_fpu_xmm1    =  41,
+    gdb_fpu_xmm2    =  42,
+    gdb_fpu_xmm3    =  43,
+    gdb_fpu_xmm4    =  44,
+    gdb_fpu_xmm5    =  45,
+    gdb_fpu_xmm6    =  46,
+    gdb_fpu_xmm7    =  47,
+    gdb_fpu_xmm8    =  48,
+    gdb_fpu_xmm9    =  49,
+    gdb_fpu_xmm10   =  50,
+    gdb_fpu_xmm11   =  51,
+    gdb_fpu_xmm12   =  52,
+    gdb_fpu_xmm13   =  53,
+    gdb_fpu_xmm14   =  54,
+    gdb_fpu_xmm15   =  55,
+    gdb_fpu_mxcsr   =  56
+};
+
+RegisterContextDarwin_x86_64::RegisterContextDarwin_x86_64 (Thread &thread, uint32_t concrete_frame_idx) :
+    RegisterContext (thread, concrete_frame_idx),
+    gpr(),
+    fpu(),
+    exc()
+{
+    uint32_t i;
+    for (i=0; i<kNumErrors; i++)
+    {
+        gpr_errs[i] = -1;
+        fpu_errs[i] = -1;
+        exc_errs[i] = -1;
+    }
+}
+
+RegisterContextDarwin_x86_64::~RegisterContextDarwin_x86_64()
+{
+}
+
+#define GPR_OFFSET(reg) (LLVM_EXTENSION offsetof (RegisterContextDarwin_x86_64::GPR, reg))
+#define FPU_OFFSET(reg) (LLVM_EXTENSION offsetof (RegisterContextDarwin_x86_64::FPU, reg) + sizeof (RegisterContextDarwin_x86_64::GPR))
+#define EXC_OFFSET(reg) (LLVM_EXTENSION offsetof (RegisterContextDarwin_x86_64::EXC, reg) + sizeof (RegisterContextDarwin_x86_64::GPR) + sizeof (RegisterContextDarwin_x86_64::FPU))
+
+// These macros will auto define the register name, alt name, register size,
+// register offset, encoding, format and native register. This ensures that
+// the register state structures are defined correctly and have the correct
+// sizes and offsets.
+#define DEFINE_GPR(reg, alt)    #reg, alt, sizeof(((RegisterContextDarwin_x86_64::GPR *)NULL)->reg), GPR_OFFSET(reg), eEncodingUint, eFormatHex
+#define DEFINE_FPU_UINT(reg)    #reg, NULL, sizeof(((RegisterContextDarwin_x86_64::FPU *)NULL)->reg), FPU_OFFSET(reg), eEncodingUint, eFormatHex
+#define DEFINE_FPU_VECT(reg, i) #reg#i, NULL, sizeof(((RegisterContextDarwin_x86_64::FPU *)NULL)->reg[i].bytes), FPU_OFFSET(reg[i]), eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_fpu_##reg##i, gcc_dwarf_fpu_##reg##i, LLDB_INVALID_REGNUM, gdb_fpu_##reg##i, fpu_##reg##i }, NULL, NULL
+#define DEFINE_EXC(reg)         #reg, NULL, sizeof(((RegisterContextDarwin_x86_64::EXC *)NULL)->reg), EXC_OFFSET(reg), eEncodingUint, eFormatHex
+
+#define REG_CONTEXT_SIZE (sizeof (RegisterContextDarwin_x86_64::GPR) + sizeof (RegisterContextDarwin_x86_64::FPU) + sizeof (RegisterContextDarwin_x86_64::EXC))
+
+// General purpose registers for 64 bit
+static RegisterInfo g_register_infos[] =
+{
+//  Macro auto defines most stuff   GCC                    DWARF                GENERIC                    GDB                  LLDB                VALUE REGS    INVALIDATE REGS
+//  =============================== ====================== ===================  ========================== ==================== =================== ==========    ===============
+    { DEFINE_GPR (rax   , NULL)     , { gcc_dwarf_gpr_rax  , gcc_dwarf_gpr_rax  , LLDB_INVALID_REGNUM      , gdb_gpr_rax        , gpr_rax       },       NULL,              NULL},
+    { DEFINE_GPR (rbx   , NULL)     , { gcc_dwarf_gpr_rbx  , gcc_dwarf_gpr_rbx  , LLDB_INVALID_REGNUM      , gdb_gpr_rbx        , gpr_rbx       },       NULL,              NULL},
+    { DEFINE_GPR (rcx   , NULL)     , { gcc_dwarf_gpr_rcx  , gcc_dwarf_gpr_rcx  , LLDB_INVALID_REGNUM      , gdb_gpr_rcx        , gpr_rcx       },       NULL,              NULL},
+    { DEFINE_GPR (rdx   , NULL)     , { gcc_dwarf_gpr_rdx  , gcc_dwarf_gpr_rdx  , LLDB_INVALID_REGNUM      , gdb_gpr_rdx        , gpr_rdx       },       NULL,              NULL},
+    { DEFINE_GPR (rdi   , NULL)     , { gcc_dwarf_gpr_rdi  , gcc_dwarf_gpr_rdi  , LLDB_INVALID_REGNUM      , gdb_gpr_rdi        , gpr_rdi       },       NULL,              NULL},
+    { DEFINE_GPR (rsi   , NULL)     , { gcc_dwarf_gpr_rsi  , gcc_dwarf_gpr_rsi  , LLDB_INVALID_REGNUM      , gdb_gpr_rsi        , gpr_rsi       },       NULL,              NULL},
+    { DEFINE_GPR (rbp   , "fp")     , { gcc_dwarf_gpr_rbp  , gcc_dwarf_gpr_rbp  , LLDB_REGNUM_GENERIC_FP   , gdb_gpr_rbp        , gpr_rbp       },       NULL,              NULL},
+    { DEFINE_GPR (rsp   , "sp")     , { gcc_dwarf_gpr_rsp  , gcc_dwarf_gpr_rsp  , LLDB_REGNUM_GENERIC_SP   , gdb_gpr_rsp        , gpr_rsp       },       NULL,              NULL},
+    { DEFINE_GPR (r8    , NULL)     , { gcc_dwarf_gpr_r8   , gcc_dwarf_gpr_r8   , LLDB_INVALID_REGNUM      , gdb_gpr_r8         , gpr_r8        },       NULL,              NULL},
+    { DEFINE_GPR (r9    , NULL)     , { gcc_dwarf_gpr_r9   , gcc_dwarf_gpr_r9   , LLDB_INVALID_REGNUM      , gdb_gpr_r9         , gpr_r9        },       NULL,              NULL},
+    { DEFINE_GPR (r10   , NULL)     , { gcc_dwarf_gpr_r10  , gcc_dwarf_gpr_r10  , LLDB_INVALID_REGNUM      , gdb_gpr_r10        , gpr_r10       },       NULL,              NULL},
+    { DEFINE_GPR (r11   , NULL)     , { gcc_dwarf_gpr_r11  , gcc_dwarf_gpr_r11  , LLDB_INVALID_REGNUM      , gdb_gpr_r11        , gpr_r11       },       NULL,              NULL},
+    { DEFINE_GPR (r12   , NULL)     , { gcc_dwarf_gpr_r12  , gcc_dwarf_gpr_r12  , LLDB_INVALID_REGNUM      , gdb_gpr_r12        , gpr_r12       },       NULL,              NULL},
+    { DEFINE_GPR (r13   , NULL)     , { gcc_dwarf_gpr_r13  , gcc_dwarf_gpr_r13  , LLDB_INVALID_REGNUM      , gdb_gpr_r13        , gpr_r13       },       NULL,              NULL},
+    { DEFINE_GPR (r14   , NULL)     , { gcc_dwarf_gpr_r14  , gcc_dwarf_gpr_r14  , LLDB_INVALID_REGNUM      , gdb_gpr_r14        , gpr_r14       },       NULL,              NULL},
+    { DEFINE_GPR (r15   , NULL)     , { gcc_dwarf_gpr_r15  , gcc_dwarf_gpr_r15  , LLDB_INVALID_REGNUM      , gdb_gpr_r15        , gpr_r15       },       NULL,              NULL},
+    { DEFINE_GPR (rip   , "pc")     , { gcc_dwarf_gpr_rip  , gcc_dwarf_gpr_rip  , LLDB_REGNUM_GENERIC_PC   , gdb_gpr_rip        , gpr_rip       },       NULL,              NULL},
+    { DEFINE_GPR (rflags, "flags")  , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_REGNUM_GENERIC_FLAGS, gdb_gpr_rflags     , gpr_rflags    },       NULL,              NULL},
+    { DEFINE_GPR (cs    , NULL)     , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM      , gdb_gpr_cs         , gpr_cs        },       NULL,              NULL},
+    { DEFINE_GPR (fs    , NULL)     , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM      , gdb_gpr_fs         , gpr_fs        },       NULL,              NULL},
+    { DEFINE_GPR (gs    , NULL)     , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM      , gdb_gpr_gs         , gpr_gs        },       NULL,              NULL},
+
+    { DEFINE_FPU_UINT(fcw)          , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM      , gdb_fpu_fcw        , fpu_fcw       },       NULL,              NULL},
+    { DEFINE_FPU_UINT(fsw)          , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM      , gdb_fpu_fsw        , fpu_fsw       },       NULL,              NULL},
+    { DEFINE_FPU_UINT(ftw)          , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM      , gdb_fpu_ftw        , fpu_ftw       },       NULL,              NULL},
+    { DEFINE_FPU_UINT(fop)          , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM      , gdb_fpu_fop        , fpu_fop       },       NULL,              NULL},
+    { DEFINE_FPU_UINT(ip)           , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM      , gdb_fpu_ip         , fpu_ip        },       NULL,              NULL},
+    { DEFINE_FPU_UINT(cs)           , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM      , gdb_fpu_cs         , fpu_cs        },       NULL,              NULL},
+    { DEFINE_FPU_UINT(dp)           , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM      , gdb_fpu_dp         , fpu_dp        },       NULL,              NULL},
+    { DEFINE_FPU_UINT(ds)           , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM      , gdb_fpu_ds         , fpu_ds        },       NULL,              NULL},
+    { DEFINE_FPU_UINT(mxcsr)        , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM      , gdb_fpu_mxcsr      , fpu_mxcsr     },       NULL,              NULL},
+    { DEFINE_FPU_UINT(mxcsrmask)    , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM, fpu_mxcsrmask },       NULL,              NULL},
+    { DEFINE_FPU_VECT(stmm,0)   },
+    { DEFINE_FPU_VECT(stmm,1)   },
+    { DEFINE_FPU_VECT(stmm,2)   },
+    { DEFINE_FPU_VECT(stmm,3)   },
+    { DEFINE_FPU_VECT(stmm,4)   },
+    { DEFINE_FPU_VECT(stmm,5)   },
+    { DEFINE_FPU_VECT(stmm,6)   },
+    { DEFINE_FPU_VECT(stmm,7)   },
+    { DEFINE_FPU_VECT(xmm,0)    },
+    { DEFINE_FPU_VECT(xmm,1)    },
+    { DEFINE_FPU_VECT(xmm,2)    },
+    { DEFINE_FPU_VECT(xmm,3)    },
+    { DEFINE_FPU_VECT(xmm,4)    },
+    { DEFINE_FPU_VECT(xmm,5)    },
+    { DEFINE_FPU_VECT(xmm,6)    },
+    { DEFINE_FPU_VECT(xmm,7)    },
+    { DEFINE_FPU_VECT(xmm,8)    },
+    { DEFINE_FPU_VECT(xmm,9)    },
+    { DEFINE_FPU_VECT(xmm,10)   },
+    { DEFINE_FPU_VECT(xmm,11)   },
+    { DEFINE_FPU_VECT(xmm,12)   },
+    { DEFINE_FPU_VECT(xmm,13)   },
+    { DEFINE_FPU_VECT(xmm,14)   },
+    { DEFINE_FPU_VECT(xmm,15)   },
+
+    { DEFINE_EXC(trapno)            , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM, exc_trapno     },      NULL,              NULL},
+    { DEFINE_EXC(err)               , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM, exc_err        },      NULL,              NULL},
+    { DEFINE_EXC(faultvaddr)        , { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM      , LLDB_INVALID_REGNUM, exc_faultvaddr },      NULL,              NULL}
+};
+
+static size_t k_num_register_infos = (sizeof(g_register_infos)/sizeof(RegisterInfo));
+
+
+void
+RegisterContextDarwin_x86_64::InvalidateAllRegisters ()
+{
+    InvalidateAllRegisterStates();
+}
+
+
+size_t
+RegisterContextDarwin_x86_64::GetRegisterCount ()
+{
+    assert(k_num_register_infos == k_num_registers);
+    return k_num_registers;
+}
+
+
+const RegisterInfo *
+RegisterContextDarwin_x86_64::GetRegisterInfoAtIndex (size_t reg)
+{
+    assert(k_num_register_infos == k_num_registers);
+    if (reg < k_num_registers)
+        return &g_register_infos[reg];
+    return NULL;
+}
+
+
+size_t
+RegisterContextDarwin_x86_64::GetRegisterInfosCount ()
+{
+    return k_num_register_infos;
+}
+
+const lldb_private::RegisterInfo *
+RegisterContextDarwin_x86_64::GetRegisterInfos ()
+{
+    return g_register_infos;
+}
+
+
+
+static uint32_t g_gpr_regnums[] =
+{
+    gpr_rax,
+    gpr_rbx,
+    gpr_rcx,
+    gpr_rdx,
+    gpr_rdi,
+    gpr_rsi,
+    gpr_rbp,
+    gpr_rsp,
+    gpr_r8,
+    gpr_r9,
+    gpr_r10,
+    gpr_r11,
+    gpr_r12,
+    gpr_r13,
+    gpr_r14,
+    gpr_r15,
+    gpr_rip,
+    gpr_rflags,
+    gpr_cs,
+    gpr_fs,
+    gpr_gs
+};
+
+static uint32_t g_fpu_regnums[] =
+{
+    fpu_fcw,
+    fpu_fsw,
+    fpu_ftw,
+    fpu_fop,
+    fpu_ip,
+    fpu_cs,
+    fpu_dp,
+    fpu_ds,
+    fpu_mxcsr,
+    fpu_mxcsrmask,
+    fpu_stmm0,
+    fpu_stmm1,
+    fpu_stmm2,
+    fpu_stmm3,
+    fpu_stmm4,
+    fpu_stmm5,
+    fpu_stmm6,
+    fpu_stmm7,
+    fpu_xmm0,
+    fpu_xmm1,
+    fpu_xmm2,
+    fpu_xmm3,
+    fpu_xmm4,
+    fpu_xmm5,
+    fpu_xmm6,
+    fpu_xmm7,
+    fpu_xmm8,
+    fpu_xmm9,
+    fpu_xmm10,
+    fpu_xmm11,
+    fpu_xmm12,
+    fpu_xmm13,
+    fpu_xmm14,
+    fpu_xmm15
+};
+
+static uint32_t
+g_exc_regnums[] =
+{
+    exc_trapno,
+    exc_err,
+    exc_faultvaddr
+};
+
+// Number of registers in each register set
+const size_t k_num_gpr_registers = sizeof(g_gpr_regnums) / sizeof(uint32_t);
+const size_t k_num_fpu_registers = sizeof(g_fpu_regnums) / sizeof(uint32_t);
+const size_t k_num_exc_registers = sizeof(g_exc_regnums) / sizeof(uint32_t);
+
+//----------------------------------------------------------------------
+// Register set definitions. The first definitions at register set index
+// of zero is for all registers, followed by other registers sets. The
+// register information for the all register set need not be filled in.
+//----------------------------------------------------------------------
+static const RegisterSet g_reg_sets[] =
+{
+    { "General Purpose Registers",  "gpr",  k_num_gpr_registers,    g_gpr_regnums,      },
+    { "Floating Point Registers",   "fpu",  k_num_fpu_registers,    g_fpu_regnums       },
+    { "Exception State Registers",  "exc",  k_num_exc_registers,    g_exc_regnums       }
+};
+
+const size_t k_num_regsets = sizeof(g_reg_sets) / sizeof(RegisterSet);
+
+
+size_t
+RegisterContextDarwin_x86_64::GetRegisterSetCount ()
+{
+    return k_num_regsets;
+}
+
+const RegisterSet *
+RegisterContextDarwin_x86_64::GetRegisterSet (size_t reg_set)
+{
+    if (reg_set < k_num_regsets)
+        return &g_reg_sets[reg_set];
+    return NULL;
+}
+
+int
+RegisterContextDarwin_x86_64::GetSetForNativeRegNum (int reg_num)
+{
+    if (reg_num < fpu_fcw)
+        return GPRRegSet;
+    else if (reg_num < exc_trapno)
+        return FPURegSet;
+    else if (reg_num < k_num_registers)
+        return EXCRegSet;
+    return -1;
+}
+
+void
+RegisterContextDarwin_x86_64::LogGPR(Log *log, const char *format, ...)
+{
+    if (log)
+    {
+        if (format)
+        {
+            va_list args;
+            va_start (args, format);
+            log->VAPrintf (format, args);
+            va_end (args);
+        }
+        for (uint32_t i=0; i<k_num_gpr_registers; i++)
+        {
+            uint32_t reg = gpr_rax + i;
+            log->Printf("%12s = 0x%16.16" PRIx64, g_register_infos[reg].name, (&gpr.rax)[reg]);
+        }
+    }
+}
+
+int
+RegisterContextDarwin_x86_64::ReadGPR (bool force)
+{
+    int set = GPRRegSet;
+    if (force || !RegisterSetIsCached(set))
+    {
+        SetError(set, Read, DoReadGPR(GetThreadID(), set, gpr));
+    }
+    return GetError(GPRRegSet, Read);
+}
+
+int
+RegisterContextDarwin_x86_64::ReadFPU (bool force)
+{
+    int set = FPURegSet;
+    if (force || !RegisterSetIsCached(set))
+    {
+        SetError(set, Read, DoReadFPU(GetThreadID(), set, fpu));
+    }
+    return GetError(FPURegSet, Read);
+}
+
+int
+RegisterContextDarwin_x86_64::ReadEXC (bool force)
+{
+    int set = EXCRegSet;
+    if (force || !RegisterSetIsCached(set))
+    {
+        SetError(set, Read, DoReadEXC(GetThreadID(), set, exc));
+    }
+    return GetError(EXCRegSet, Read);
+}
+
+int
+RegisterContextDarwin_x86_64::WriteGPR ()
+{
+    int set = GPRRegSet;
+    if (!RegisterSetIsCached(set))
+    {
+        SetError (set, Write, -1);
+        return -1;
+    }
+    SetError (set, Write, DoWriteGPR(GetThreadID(), set, gpr));
+    SetError (set, Read, -1);
+    return GetError (set, Write);
+}
+
+int
+RegisterContextDarwin_x86_64::WriteFPU ()
+{
+    int set = FPURegSet;
+    if (!RegisterSetIsCached(set))
+    {
+        SetError (set, Write, -1);
+        return -1;
+    }
+    SetError (set, Write, DoWriteFPU(GetThreadID(), set, fpu));
+    SetError (set, Read, -1);
+    return GetError (set, Write);
+}
+
+int
+RegisterContextDarwin_x86_64::WriteEXC ()
+{
+    int set = EXCRegSet;
+    if (!RegisterSetIsCached(set))
+    {
+        SetError (set, Write, -1);
+        return -1;
+    }
+    SetError (set, Write, DoWriteEXC(GetThreadID(), set, exc));
+    SetError (set, Read, -1);
+    return GetError (set, Write);
+}
+
+int
+RegisterContextDarwin_x86_64::ReadRegisterSet(uint32_t set, bool force)
+{
+    switch (set)
+    {
+    case GPRRegSet:    return ReadGPR (force);
+    case FPURegSet:    return ReadFPU (force);
+    case EXCRegSet:    return ReadEXC (force);
+    default: break;
+    }
+    return -1;
+}
+
+int
+RegisterContextDarwin_x86_64::WriteRegisterSet(uint32_t set)
+{
+    // Make sure we have a valid context to set.
+    switch (set)
+    {
+    case GPRRegSet:    return WriteGPR ();
+    case FPURegSet:    return WriteFPU ();
+    case EXCRegSet:    return WriteEXC ();
+    default: break;
+    }
+    return -1;
+}
+
+
+bool
+RegisterContextDarwin_x86_64::ReadRegister (const RegisterInfo *reg_info,
+                                          RegisterValue &value)
+{
+    const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
+    int set = RegisterContextDarwin_x86_64::GetSetForNativeRegNum (reg);
+    if (set == -1)
+        return false;
+
+    if (ReadRegisterSet(set, false) != 0)
+        return false;
+
+    switch (reg)
+    {
+    case gpr_rax:
+    case gpr_rbx:
+    case gpr_rcx:
+    case gpr_rdx:
+    case gpr_rdi:
+    case gpr_rsi:
+    case gpr_rbp:
+    case gpr_rsp:
+    case gpr_r8:
+    case gpr_r9:
+    case gpr_r10:
+    case gpr_r11:
+    case gpr_r12:
+    case gpr_r13:
+    case gpr_r14:
+    case gpr_r15:
+    case gpr_rip:
+    case gpr_rflags:
+    case gpr_cs:
+    case gpr_fs:
+    case gpr_gs:
+        value = (&gpr.rax)[reg - gpr_rax];
+        break;
+
+    case fpu_fcw:
+        value = fpu.fcw;
+        break;
+
+    case fpu_fsw:
+        value = fpu.fsw;
+        break;
+
+    case fpu_ftw:
+        value = fpu.ftw;
+        break;
+
+    case fpu_fop:
+        value = fpu.fop;
+        break;
+
+    case fpu_ip:
+        value = fpu.ip;
+        break;
+
+    case fpu_cs:
+        value = fpu.cs;
+        break;
+
+    case fpu_dp:
+        value = fpu.dp;
+        break;
+
+    case fpu_ds:
+        value = fpu.ds;
+        break;
+
+    case fpu_mxcsr:
+        value = fpu.mxcsr;
+        break;
+
+    case fpu_mxcsrmask:
+        value = fpu.mxcsrmask;
+        break;
+
+    case fpu_stmm0:
+    case fpu_stmm1:
+    case fpu_stmm2:
+    case fpu_stmm3:
+    case fpu_stmm4:
+    case fpu_stmm5:
+    case fpu_stmm6:
+    case fpu_stmm7:
+        value.SetBytes(fpu.stmm[reg - fpu_stmm0].bytes, reg_info->byte_size, lldb::endian::InlHostByteOrder());
+        break;
+
+    case fpu_xmm0:
+    case fpu_xmm1:
+    case fpu_xmm2:
+    case fpu_xmm3:
+    case fpu_xmm4:
+    case fpu_xmm5:
+    case fpu_xmm6:
+    case fpu_xmm7:
+    case fpu_xmm8:
+    case fpu_xmm9:
+    case fpu_xmm10:
+    case fpu_xmm11:
+    case fpu_xmm12:
+    case fpu_xmm13:
+    case fpu_xmm14:
+    case fpu_xmm15:
+        value.SetBytes(fpu.xmm[reg - fpu_xmm0].bytes, reg_info->byte_size, lldb::endian::InlHostByteOrder());
+        break;
+
+    case exc_trapno:
+        value = exc.trapno;
+        break;
+
+    case exc_err:
+        value = exc.err;
+        break;
+
+    case exc_faultvaddr:
+        value = exc.faultvaddr;
+        break;
+
+    default:
+        return false;
+    }
+    return true;
+}
+
+
+bool
+RegisterContextDarwin_x86_64::WriteRegister (const RegisterInfo *reg_info,
+                                           const RegisterValue &value)
+{
+    const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
+    int set = RegisterContextDarwin_x86_64::GetSetForNativeRegNum (reg);
+
+    if (set == -1)
+        return false;
+
+    if (ReadRegisterSet(set, false) != 0)
+        return false;
+
+    switch (reg)
+    {
+    case gpr_rax:
+    case gpr_rbx:
+    case gpr_rcx:
+    case gpr_rdx:
+    case gpr_rdi:
+    case gpr_rsi:
+    case gpr_rbp:
+    case gpr_rsp:
+    case gpr_r8:
+    case gpr_r9:
+    case gpr_r10:
+    case gpr_r11:
+    case gpr_r12:
+    case gpr_r13:
+    case gpr_r14:
+    case gpr_r15:
+    case gpr_rip:
+    case gpr_rflags:
+    case gpr_cs:
+    case gpr_fs:
+    case gpr_gs:
+        (&gpr.rax)[reg - gpr_rax] = value.GetAsUInt64();
+        break;
+
+    case fpu_fcw:
+        fpu.fcw = value.GetAsUInt16();
+        break;
+
+    case fpu_fsw:
+        fpu.fsw = value.GetAsUInt16();
+        break;
+
+    case fpu_ftw:
+        fpu.ftw = value.GetAsUInt8();
+        break;
+
+    case fpu_fop:
+        fpu.fop = value.GetAsUInt16();
+        break;
+
+    case fpu_ip:
+        fpu.ip = value.GetAsUInt32();
+        break;
+
+    case fpu_cs:
+        fpu.cs = value.GetAsUInt16();
+        break;
+
+    case fpu_dp:
+        fpu.dp = value.GetAsUInt32();
+        break;
+
+    case fpu_ds:
+        fpu.ds = value.GetAsUInt16();
+        break;
+
+    case fpu_mxcsr:
+        fpu.mxcsr = value.GetAsUInt32();
+        break;
+
+    case fpu_mxcsrmask:
+        fpu.mxcsrmask = value.GetAsUInt32();
+        break;
+
+    case fpu_stmm0:
+    case fpu_stmm1:
+    case fpu_stmm2:
+    case fpu_stmm3:
+    case fpu_stmm4:
+    case fpu_stmm5:
+    case fpu_stmm6:
+    case fpu_stmm7:
+        ::memcpy (fpu.stmm[reg - fpu_stmm0].bytes, value.GetBytes(), value.GetByteSize());
+        break;
+
+    case fpu_xmm0:
+    case fpu_xmm1:
+    case fpu_xmm2:
+    case fpu_xmm3:
+    case fpu_xmm4:
+    case fpu_xmm5:
+    case fpu_xmm6:
+    case fpu_xmm7:
+    case fpu_xmm8:
+    case fpu_xmm9:
+    case fpu_xmm10:
+    case fpu_xmm11:
+    case fpu_xmm12:
+    case fpu_xmm13:
+    case fpu_xmm14:
+    case fpu_xmm15:
+        ::memcpy (fpu.xmm[reg - fpu_xmm0].bytes, value.GetBytes(), value.GetByteSize());
+        return false;
+
+    case exc_trapno:
+        exc.trapno = value.GetAsUInt32();
+        break;
+
+    case exc_err:
+        exc.err = value.GetAsUInt32();
+        break;
+
+    case exc_faultvaddr:
+        exc.faultvaddr = value.GetAsUInt64();
+        break;
+
+    default:
+        return false;
+    }
+    return WriteRegisterSet(set) == 0;
+}
+
+bool
+RegisterContextDarwin_x86_64::ReadAllRegisterValues (lldb::DataBufferSP &data_sp)
+{
+    data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0));
+    if (data_sp &&
+        ReadGPR (false) == 0 &&
+        ReadFPU (false) == 0 &&
+        ReadEXC (false) == 0)
+    {
+        uint8_t *dst = data_sp->GetBytes();
+        ::memcpy (dst, &gpr, sizeof(gpr));
+        dst += sizeof(gpr);
+
+        ::memcpy (dst, &fpu, sizeof(fpu));
+        dst += sizeof(gpr);
+
+        ::memcpy (dst, &exc, sizeof(exc));
+        return true;
+    }
+    return false;
+}
+
+bool
+RegisterContextDarwin_x86_64::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp)
+{
+    if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE)
+    {
+        const uint8_t *src = data_sp->GetBytes();
+        ::memcpy (&gpr, src, sizeof(gpr));
+        src += sizeof(gpr);
+
+        ::memcpy (&fpu, src, sizeof(fpu));
+        src += sizeof(gpr);
+
+        ::memcpy (&exc, src, sizeof(exc));
+        uint32_t success_count = 0;
+        if (WriteGPR() == 0)
+            ++success_count;
+        if (WriteFPU() == 0)
+            ++success_count;
+        if (WriteEXC() == 0)
+            ++success_count;
+        return success_count == 3;
+    }
+    return false;
+}
+
+
+uint32_t
+RegisterContextDarwin_x86_64::ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t reg)
+{
+    if (kind == eRegisterKindGeneric)
+    {
+        switch (reg)
+        {
+        case LLDB_REGNUM_GENERIC_PC:    return gpr_rip;
+        case LLDB_REGNUM_GENERIC_SP:    return gpr_rsp;
+        case LLDB_REGNUM_GENERIC_FP:    return gpr_rbp;
+        case LLDB_REGNUM_GENERIC_FLAGS: return gpr_rflags;
+        case LLDB_REGNUM_GENERIC_RA:
+        default:
+            break;
+        }
+    }
+    else if (kind == eRegisterKindGCC || kind == eRegisterKindDWARF)
+    {
+        switch (reg)
+        {
+        case gcc_dwarf_gpr_rax:  return gpr_rax;
+        case gcc_dwarf_gpr_rdx:  return gpr_rdx;
+        case gcc_dwarf_gpr_rcx:  return gpr_rcx;
+        case gcc_dwarf_gpr_rbx:  return gpr_rbx;
+        case gcc_dwarf_gpr_rsi:  return gpr_rsi;
+        case gcc_dwarf_gpr_rdi:  return gpr_rdi;
+        case gcc_dwarf_gpr_rbp:  return gpr_rbp;
+        case gcc_dwarf_gpr_rsp:  return gpr_rsp;
+        case gcc_dwarf_gpr_r8:   return gpr_r8;
+        case gcc_dwarf_gpr_r9:   return gpr_r9;
+        case gcc_dwarf_gpr_r10:  return gpr_r10;
+        case gcc_dwarf_gpr_r11:  return gpr_r11;
+        case gcc_dwarf_gpr_r12:  return gpr_r12;
+        case gcc_dwarf_gpr_r13:  return gpr_r13;
+        case gcc_dwarf_gpr_r14:  return gpr_r14;
+        case gcc_dwarf_gpr_r15:  return gpr_r15;
+        case gcc_dwarf_gpr_rip:  return gpr_rip;
+        case gcc_dwarf_fpu_xmm0: return fpu_xmm0;
+        case gcc_dwarf_fpu_xmm1: return fpu_xmm1;
+        case gcc_dwarf_fpu_xmm2: return fpu_xmm2;
+        case gcc_dwarf_fpu_xmm3: return fpu_xmm3;
+        case gcc_dwarf_fpu_xmm4: return fpu_xmm4;
+        case gcc_dwarf_fpu_xmm5: return fpu_xmm5;
+        case gcc_dwarf_fpu_xmm6: return fpu_xmm6;
+        case gcc_dwarf_fpu_xmm7: return fpu_xmm7;
+        case gcc_dwarf_fpu_xmm8: return fpu_xmm8;
+        case gcc_dwarf_fpu_xmm9: return fpu_xmm9;
+        case gcc_dwarf_fpu_xmm10: return fpu_xmm10;
+        case gcc_dwarf_fpu_xmm11: return fpu_xmm11;
+        case gcc_dwarf_fpu_xmm12: return fpu_xmm12;
+        case gcc_dwarf_fpu_xmm13: return fpu_xmm13;
+        case gcc_dwarf_fpu_xmm14: return fpu_xmm14;
+        case gcc_dwarf_fpu_xmm15: return fpu_xmm15;
+        case gcc_dwarf_fpu_stmm0: return fpu_stmm0;
+        case gcc_dwarf_fpu_stmm1: return fpu_stmm1;
+        case gcc_dwarf_fpu_stmm2: return fpu_stmm2;
+        case gcc_dwarf_fpu_stmm3: return fpu_stmm3;
+        case gcc_dwarf_fpu_stmm4: return fpu_stmm4;
+        case gcc_dwarf_fpu_stmm5: return fpu_stmm5;
+        case gcc_dwarf_fpu_stmm6: return fpu_stmm6;
+        case gcc_dwarf_fpu_stmm7: return fpu_stmm7;
+        default:
+            break;
+        }
+    }
+    else if (kind == eRegisterKindGDB)
+    {
+        switch (reg)
+        {
+        case gdb_gpr_rax     : return gpr_rax;
+        case gdb_gpr_rbx     : return gpr_rbx;
+        case gdb_gpr_rcx     : return gpr_rcx;
+        case gdb_gpr_rdx     : return gpr_rdx;
+        case gdb_gpr_rsi     : return gpr_rsi;
+        case gdb_gpr_rdi     : return gpr_rdi;
+        case gdb_gpr_rbp     : return gpr_rbp;
+        case gdb_gpr_rsp     : return gpr_rsp;
+        case gdb_gpr_r8      : return gpr_r8;
+        case gdb_gpr_r9      : return gpr_r9;
+        case gdb_gpr_r10     : return gpr_r10;
+        case gdb_gpr_r11     : return gpr_r11;
+        case gdb_gpr_r12     : return gpr_r12;
+        case gdb_gpr_r13     : return gpr_r13;
+        case gdb_gpr_r14     : return gpr_r14;
+        case gdb_gpr_r15     : return gpr_r15;
+        case gdb_gpr_rip     : return gpr_rip;
+        case gdb_gpr_rflags  : return gpr_rflags;
+        case gdb_gpr_cs      : return gpr_cs;
+        case gdb_gpr_ss      : return gpr_gs;   // HACK: For now for "ss", just copy what is in "gs"
+        case gdb_gpr_ds      : return gpr_gs;   // HACK: For now for "ds", just copy what is in "gs"
+        case gdb_gpr_es      : return gpr_gs;   // HACK: For now for "es", just copy what is in "gs"
+        case gdb_gpr_fs      : return gpr_fs;
+        case gdb_gpr_gs      : return gpr_gs;
+        case gdb_fpu_stmm0   : return fpu_stmm0;
+        case gdb_fpu_stmm1   : return fpu_stmm1;
+        case gdb_fpu_stmm2   : return fpu_stmm2;
+        case gdb_fpu_stmm3   : return fpu_stmm3;
+        case gdb_fpu_stmm4   : return fpu_stmm4;
+        case gdb_fpu_stmm5   : return fpu_stmm5;
+        case gdb_fpu_stmm6   : return fpu_stmm6;
+        case gdb_fpu_stmm7   : return fpu_stmm7;
+        case gdb_fpu_fctrl   : return fpu_fctrl;
+        case gdb_fpu_fstat   : return fpu_fstat;
+        case gdb_fpu_ftag    : return fpu_ftag;
+        case gdb_fpu_fiseg   : return fpu_fiseg;
+        case gdb_fpu_fioff   : return fpu_fioff;
+        case gdb_fpu_foseg   : return fpu_foseg;
+        case gdb_fpu_fooff   : return fpu_fooff;
+        case gdb_fpu_fop     : return fpu_fop;
+        case gdb_fpu_xmm0    : return fpu_xmm0;
+        case gdb_fpu_xmm1    : return fpu_xmm1;
+        case gdb_fpu_xmm2    : return fpu_xmm2;
+        case gdb_fpu_xmm3    : return fpu_xmm3;
+        case gdb_fpu_xmm4    : return fpu_xmm4;
+        case gdb_fpu_xmm5    : return fpu_xmm5;
+        case gdb_fpu_xmm6    : return fpu_xmm6;
+        case gdb_fpu_xmm7    : return fpu_xmm7;
+        case gdb_fpu_xmm8    : return fpu_xmm8;
+        case gdb_fpu_xmm9    : return fpu_xmm9;
+        case gdb_fpu_xmm10   : return fpu_xmm10;
+        case gdb_fpu_xmm11   : return fpu_xmm11;
+        case gdb_fpu_xmm12   : return fpu_xmm12;
+        case gdb_fpu_xmm13   : return fpu_xmm13;
+        case gdb_fpu_xmm14   : return fpu_xmm14;
+        case gdb_fpu_xmm15   : return fpu_xmm15;
+        case gdb_fpu_mxcsr   : return fpu_mxcsr;
+        default:
+            break;
+        }
+    }
+    else if (kind == eRegisterKindLLDB)
+    {
+        return reg;
+    }
+    return LLDB_INVALID_REGNUM;
+}
+
+bool
+RegisterContextDarwin_x86_64::HardwareSingleStep (bool enable)
+{
+    if (ReadGPR(true) != 0)
+        return false;
+
+    const uint64_t trace_bit = 0x100ull;
+    if (enable)
+    {
+
+        if (gpr.rflags & trace_bit)
+            return true;    // trace bit is already set, there is nothing to do
+        else
+            gpr.rflags |= trace_bit;
+    }
+    else
+    {
+        if (gpr.rflags & trace_bit)
+            gpr.rflags &= ~trace_bit;
+        else
+            return true;    // trace bit is clear, there is nothing to do
+    }
+
+    return WriteGPR() == 0;
+}
+
diff --git a/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.h b/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.h
new file mode 100644
index 000000000000..4b8127af997c
--- /dev/null
+++ b/source/Plugins/Process/Utility/RegisterContextDarwin_x86_64.h
@@ -0,0 +1,274 @@
+//===-- RegisterContextDarwin_x86_64.h --------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_RegisterContextDarwin_x86_64_h_
+#define liblldb_RegisterContextDarwin_x86_64_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Target/RegisterContext.h"
+
+class RegisterContextDarwin_x86_64 : public lldb_private::RegisterContext
+{
+public:
+    RegisterContextDarwin_x86_64 (lldb_private::Thread &thread,
+                                  uint32_t concrete_frame_idx);
+
+    virtual
+    ~RegisterContextDarwin_x86_64();
+
+    virtual void
+    InvalidateAllRegisters ();
+
+    virtual size_t
+    GetRegisterCount ();
+
+    virtual const lldb_private::RegisterInfo *
+    GetRegisterInfoAtIndex (size_t reg);
+
+    virtual size_t
+    GetRegisterSetCount ();
+
+    virtual const lldb_private::RegisterSet *
+    GetRegisterSet (size_t set);
+
+    virtual bool
+    ReadRegister (const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value);
+
+    virtual bool
+    WriteRegister (const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value);
+    
+    virtual bool
+    ReadAllRegisterValues (lldb::DataBufferSP &data_sp);
+
+    virtual bool
+    WriteAllRegisterValues (const lldb::DataBufferSP &data_sp);
+
+    virtual uint32_t
+    ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num);
+
+    virtual bool
+    HardwareSingleStep (bool enable);
+
+    struct GPR
+    {
+        uint64_t rax;
+        uint64_t rbx;
+        uint64_t rcx;
+        uint64_t rdx;
+        uint64_t rdi;
+        uint64_t rsi;
+        uint64_t rbp;
+        uint64_t rsp;
+        uint64_t r8;
+        uint64_t r9;
+        uint64_t r10;
+        uint64_t r11;
+        uint64_t r12;
+        uint64_t r13;
+        uint64_t r14;
+        uint64_t r15;
+        uint64_t rip;
+        uint64_t rflags;
+        uint64_t cs;
+        uint64_t fs;
+        uint64_t gs;
+    };
+
+    struct MMSReg
+    {
+        uint8_t bytes[10];
+        uint8_t pad[6];
+    };
+
+    struct XMMReg
+    {
+        uint8_t bytes[16];
+    };
+
+    struct FPU
+    {
+        uint32_t    pad[2];
+        uint16_t    fcw;    // "fctrl"
+        uint16_t    fsw;    // "fstat"
+        uint8_t     ftw;    // "ftag"
+        uint8_t     pad1;
+        uint16_t    fop;    // "fop"
+        uint32_t    ip;     // "fioff"
+        uint16_t    cs;     // "fiseg"
+        uint16_t    pad2;
+        uint32_t    dp;     // "fooff"
+        uint16_t    ds;     // "foseg"
+        uint16_t    pad3;
+        uint32_t    mxcsr;
+        uint32_t    mxcsrmask;
+        MMSReg      stmm[8];
+        XMMReg      xmm[16];
+        uint8_t     pad4[6*16];
+        int         pad5;
+    };
+
+    struct EXC
+    {
+        uint32_t trapno;
+        uint32_t err;
+        uint64_t faultvaddr;
+    };
+
+protected:
+
+    enum
+    {
+        GPRRegSet = 4,
+        FPURegSet = 5,
+        EXCRegSet = 6
+    };
+
+    enum
+    {
+        GPRWordCount = sizeof(GPR)/sizeof(uint32_t),
+        FPUWordCount = sizeof(FPU)/sizeof(uint32_t),
+        EXCWordCount = sizeof(EXC)/sizeof(uint32_t)
+    };
+
+    enum
+    {
+        Read = 0,
+        Write = 1,
+        kNumErrors = 2
+    };
+
+    GPR gpr;
+    FPU fpu;
+    EXC exc;
+    int gpr_errs[2]; // Read/Write errors
+    int fpu_errs[2]; // Read/Write errors
+    int exc_errs[2]; // Read/Write errors
+
+    void
+    InvalidateAllRegisterStates()
+    {
+        SetError (GPRRegSet, Read, -1);
+        SetError (FPURegSet, Read, -1);
+        SetError (EXCRegSet, Read, -1);
+    }
+
+    int
+    GetError (int flavor, uint32_t err_idx) const
+    {
+        if (err_idx < kNumErrors)
+        {
+            switch (flavor)
+            {
+            // When getting all errors, just OR all values together to see if
+            // we got any kind of error.
+            case GPRRegSet:    return gpr_errs[err_idx];
+            case FPURegSet:    return fpu_errs[err_idx];
+            case EXCRegSet:    return exc_errs[err_idx];
+            default: break;
+            }
+        }
+        return -1;
+    }
+
+    bool
+    SetError (int flavor, uint32_t err_idx, int err)
+    {
+        if (err_idx < kNumErrors)
+        {
+            switch (flavor)
+            {
+            case GPRRegSet:
+                gpr_errs[err_idx] = err;
+                return true;
+
+            case FPURegSet:
+                fpu_errs[err_idx] = err;
+                return true;
+
+            case EXCRegSet:
+                exc_errs[err_idx] = err;
+                return true;
+
+            default: break;
+            }
+        }
+        return false;
+    }
+
+    bool
+    RegisterSetIsCached (int set) const
+    {
+        return GetError(set, Read) == 0;
+    }
+
+    void
+    LogGPR (lldb_private::Log *log, const char *format, ...);
+
+    int
+    ReadGPR (bool force);
+
+    int
+    ReadFPU (bool force);
+
+    int
+    ReadEXC (bool force);
+
+    int
+    WriteGPR ();
+
+    int
+    WriteFPU ();
+
+    int
+    WriteEXC ();
+
+    // Subclasses override these to do the actual reading.
+    virtual int
+    DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr) = 0;
+    
+    virtual int
+    DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu) = 0;
+    
+    virtual int
+    DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc) = 0;
+    
+    virtual int
+    DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr) = 0;
+    
+    virtual int
+    DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu) = 0;
+    
+    virtual int
+    DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc) = 0;
+    
+    int
+    ReadRegisterSet (uint32_t set, bool force);
+
+    int
+    WriteRegisterSet (uint32_t set);
+
+    static uint32_t
+    GetRegisterNumber (uint32_t reg_kind, uint32_t reg_num);
+
+    static int
+    GetSetForNativeRegNum (int reg_num);
+
+    static size_t
+    GetRegisterInfosCount ();
+
+    static const lldb_private::RegisterInfo *
+    GetRegisterInfos ();
+
+};
+
+#endif  // liblldb_RegisterContextDarwin_x86_64_h_
diff --git a/source/Plugins/Process/Utility/RegisterContextDummy.cpp b/source/Plugins/Process/Utility/RegisterContextDummy.cpp
new file mode 100644
index 000000000000..1e282ce74f2e
--- /dev/null
+++ b/source/Plugins/Process/Utility/RegisterContextDummy.cpp
@@ -0,0 +1,137 @@
+//===-- RegisterContextDummy.cpp ---------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+
+#include "lldb/lldb-private.h"
+#include "lldb/Core/Address.h"
+#include "lldb/Core/AddressRange.h"
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/RegisterValue.h"
+#include "lldb/Core/Value.h"
+#include "lldb/Expression/DWARFExpression.h"
+#include "lldb/Symbol/FuncUnwinders.h"
+#include "lldb/Symbol/Function.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Symbol/Symbol.h"
+#include "lldb/Target/ABI.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/DynamicLoader.h"
+
+#include "RegisterContextDummy.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+RegisterContextDummy::RegisterContextDummy (Thread &thread, uint32_t concrete_frame_idx, uint32_t address_byte_size) :
+RegisterContext (thread, concrete_frame_idx)
+{
+    m_reg_set0.name = "General Purpose Registers";
+    m_reg_set0.short_name = "GPR";
+    m_reg_set0.num_registers = 1;
+    m_reg_set0.registers = new uint32_t(0);
+    
+    m_pc_reg_info.name = "pc";
+    m_pc_reg_info.alt_name = "pc";
+    m_pc_reg_info.byte_offset = 0;
+    m_pc_reg_info.byte_size = address_byte_size;
+    m_pc_reg_info.encoding = eEncodingUint;
+    m_pc_reg_info.format = eFormatPointer;
+    m_pc_reg_info.invalidate_regs = NULL;
+    m_pc_reg_info.value_regs = NULL;
+    m_pc_reg_info.kinds[eRegisterKindGCC] = LLDB_INVALID_REGNUM;
+    m_pc_reg_info.kinds[eRegisterKindDWARF] = LLDB_INVALID_REGNUM;
+    m_pc_reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC;
+    m_pc_reg_info.kinds[eRegisterKindGDB] = LLDB_INVALID_REGNUM;
+    m_pc_reg_info.kinds[eRegisterKindLLDB] = LLDB_INVALID_REGNUM;
+}
+
+RegisterContextDummy::~RegisterContextDummy ()
+{
+    delete m_reg_set0.registers;
+    delete m_pc_reg_info.invalidate_regs;
+    delete m_pc_reg_info.value_regs;
+}
+
+void
+RegisterContextDummy::InvalidateAllRegisters () {}
+
+size_t
+RegisterContextDummy::GetRegisterCount ()
+{
+    return 1;
+}
+
+const lldb_private::RegisterInfo *
+RegisterContextDummy::GetRegisterInfoAtIndex (size_t reg)
+{
+    if (reg)
+        return NULL;
+    return &m_pc_reg_info;
+}
+
+size_t
+RegisterContextDummy::GetRegisterSetCount ()
+{
+    return 1;
+}
+
+const lldb_private::RegisterSet *
+RegisterContextDummy::GetRegisterSet (size_t reg_set)
+{
+    if (reg_set)
+        return NULL;
+    return &m_reg_set0;
+}
+
+bool
+RegisterContextDummy::ReadRegister (const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value)
+{
+    if (!reg_info)
+        return false;
+    uint32_t reg_number = reg_info->kinds[eRegisterKindGeneric];
+    if (reg_number == LLDB_REGNUM_GENERIC_PC)
+    {
+        value.SetUInt(LLDB_INVALID_ADDRESS, reg_info->byte_size);
+        return true;
+    }
+    return false;
+}
+
+bool
+RegisterContextDummy::WriteRegister (const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value)
+{
+    return false;
+}
+
+bool
+RegisterContextDummy::ReadAllRegisterValues (lldb::DataBufferSP &data_sp)
+{
+    return false;
+}
+
+bool
+RegisterContextDummy::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp)
+{
+    return false;
+}
+
+uint32_t
+RegisterContextDummy::ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num)
+{
+    if (kind == eRegisterKindGeneric && num == LLDB_REGNUM_GENERIC_PC)
+        return 0;
+    return LLDB_INVALID_REGNUM;
+}
diff --git a/source/Plugins/Process/Utility/RegisterContextDummy.h b/source/Plugins/Process/Utility/RegisterContextDummy.h
new file mode 100644
index 000000000000..ee8d5a134bbc
--- /dev/null
+++ b/source/Plugins/Process/Utility/RegisterContextDummy.h
@@ -0,0 +1,77 @@
+//===-- RegisterContextDummy.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_RegisterContextDummy_h_
+#define lldb_RegisterContextDummy_h_
+
+#include <vector>
+
+#include "lldb/lldb-private.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Symbol/SymbolContext.h"
+
+namespace lldb_private {
+    
+class RegisterContextDummy : public lldb_private::RegisterContext
+{
+public:
+    typedef std::shared_ptr<RegisterContextDummy> SharedPtr;
+    
+    RegisterContextDummy (Thread &thread, uint32_t concrete_frame_idx, uint32_t address_byte_size);
+    
+    ///
+    // pure virtual functions from the base class that we must implement
+    ///
+
+    virtual
+    ~RegisterContextDummy ();
+
+    virtual void
+    InvalidateAllRegisters ();
+
+    virtual size_t
+    GetRegisterCount ();
+
+    virtual const lldb_private::RegisterInfo *
+    GetRegisterInfoAtIndex (size_t reg);
+
+    virtual size_t
+    GetRegisterSetCount ();
+
+    virtual const lldb_private::RegisterSet *
+    GetRegisterSet (size_t reg_set);
+
+    virtual bool
+    ReadRegister (const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value);
+
+    virtual bool
+    WriteRegister (const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value);
+
+    virtual bool
+    ReadAllRegisterValues (lldb::DataBufferSP &data_sp);
+
+    virtual bool
+    WriteAllRegisterValues (const lldb::DataBufferSP &data_sp);
+
+    virtual uint32_t
+    ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num);
+    
+private:
+    //------------------------------------------------------------------
+    // For RegisterContextLLDB only
+    //------------------------------------------------------------------
+    
+    lldb_private::RegisterSet m_reg_set0; // register set 0 (PC only)
+    lldb_private::RegisterInfo m_pc_reg_info;
+    
+    DISALLOW_COPY_AND_ASSIGN (RegisterContextDummy);
+};
+} // namespace lldb_private
+
+#endif  // lldb_RegisterContextDummy_h_
diff --git a/source/Plugins/Process/Utility/RegisterContextLLDB.cpp b/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
new file mode 100644
index 000000000000..1ffc30da5762
--- /dev/null
+++ b/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
@@ -0,0 +1,1541 @@
+//===-- RegisterContextLLDB.cpp --------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+
+#include "lldb/lldb-private.h"
+#include "lldb/Core/Address.h"
+#include "lldb/Core/AddressRange.h"
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/RegisterValue.h"
+#include "lldb/Core/Value.h"
+#include "lldb/Expression/DWARFExpression.h"
+#include "lldb/Symbol/DWARFCallFrameInfo.h"
+#include "lldb/Symbol/FuncUnwinders.h"
+#include "lldb/Symbol/Function.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Symbol/Symbol.h"
+#include "lldb/Target/ABI.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/DynamicLoader.h"
+
+#include "RegisterContextLLDB.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+RegisterContextLLDB::RegisterContextLLDB
+(
+    Thread& thread,
+    const SharedPtr &next_frame,
+    SymbolContext& sym_ctx,
+    uint32_t frame_number,
+    UnwindLLDB& unwind_lldb
+) :
+    RegisterContext (thread, frame_number),
+    m_thread(thread),
+    m_fast_unwind_plan_sp (),
+    m_full_unwind_plan_sp (),
+    m_all_registers_available(false),
+    m_frame_type (-1),
+    m_cfa (LLDB_INVALID_ADDRESS),
+    m_start_pc (),
+    m_current_pc (),
+    m_current_offset (0),
+    m_current_offset_backed_up_one (0),
+    m_sym_ctx(sym_ctx),
+    m_sym_ctx_valid (false),
+    m_frame_number (frame_number),
+    m_registers(),
+    m_parent_unwind (unwind_lldb)
+{
+    m_sym_ctx.Clear(false);
+    m_sym_ctx_valid = false;
+
+    if (IsFrameZero ())
+    {
+        InitializeZerothFrame ();
+    }
+    else
+    {
+        InitializeNonZerothFrame ();
+    }
+
+    // This same code exists over in the GetFullUnwindPlanForFrame() but it may not have been executed yet
+    if (IsFrameZero()
+        || next_frame->m_frame_type == eSigtrampFrame
+        || next_frame->m_frame_type == eDebuggerFrame)
+    {
+        m_all_registers_available = true;
+    }
+}
+
+// Initialize a RegisterContextLLDB which is the first frame of a stack -- the zeroth frame or currently
+// executing frame.
+
+void
+RegisterContextLLDB::InitializeZerothFrame()
+{
+    Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
+    ExecutionContext exe_ctx(m_thread.shared_from_this());
+    RegisterContextSP reg_ctx_sp = m_thread.GetRegisterContext();
+
+    if (reg_ctx_sp.get() == NULL)
+    {
+        m_frame_type = eNotAValidFrame;
+        return;
+    }
+
+    addr_t current_pc = reg_ctx_sp->GetPC();
+
+    if (current_pc == LLDB_INVALID_ADDRESS)
+    {
+        m_frame_type = eNotAValidFrame;
+        return;
+    }
+
+    Process *process = exe_ctx.GetProcessPtr();
+
+    // Let ABIs fixup code addresses to make sure they are valid. In ARM ABIs
+    // this will strip bit zero in case we read a PC from memory or from the LR.
+    // (which would be a no-op in frame 0 where we get it from the register set,
+    // but still a good idea to make the call here for other ABIs that may exist.)
+    ABI *abi = process->GetABI().get();
+    if (abi)
+        current_pc = abi->FixCodeAddress(current_pc);
+
+    // Initialize m_current_pc, an Address object, based on current_pc, an addr_t.
+    process->GetTarget().GetSectionLoadList().ResolveLoadAddress (current_pc, m_current_pc);
+
+    // If we don't have a Module for some reason, we're not going to find symbol/function information - just
+    // stick in some reasonable defaults and hope we can unwind past this frame.
+    ModuleSP pc_module_sp (m_current_pc.GetModule());
+    if (!m_current_pc.IsValid() || !pc_module_sp)
+    {
+        UnwindLogMsg ("using architectural default unwind method");
+    }
+
+    // We require that eSymbolContextSymbol be successfully filled in or this context is of no use to us.
+    if (pc_module_sp.get()
+        && (pc_module_sp->ResolveSymbolContextForAddress (m_current_pc, eSymbolContextFunction| eSymbolContextSymbol, m_sym_ctx) & eSymbolContextSymbol) == eSymbolContextSymbol)
+    {
+        m_sym_ctx_valid = true;
+    }
+
+    AddressRange addr_range;
+    m_sym_ctx.GetAddressRange (eSymbolContextFunction | eSymbolContextSymbol, 0, false, addr_range);
+
+    static ConstString g_sigtramp_name ("_sigtramp");
+    if ((m_sym_ctx.function && m_sym_ctx.function->GetName() == g_sigtramp_name) ||
+        (m_sym_ctx.symbol   && m_sym_ctx.symbol->GetName()   == g_sigtramp_name))
+    {
+        m_frame_type = eSigtrampFrame;
+    }
+    else
+    {
+        // FIXME:  Detect eDebuggerFrame here.
+        m_frame_type = eNormalFrame;
+    }
+
+    // If we were able to find a symbol/function, set addr_range to the bounds of that symbol/function.
+    // else treat the current pc value as the start_pc and record no offset.
+    if (addr_range.GetBaseAddress().IsValid())
+    {
+        m_start_pc = addr_range.GetBaseAddress();
+        if (m_current_pc.GetSection() == m_start_pc.GetSection())
+        {
+            m_current_offset = m_current_pc.GetOffset() - m_start_pc.GetOffset();
+        }
+        else if (m_current_pc.GetModule() == m_start_pc.GetModule())
+        {
+            // This means that whatever symbol we kicked up isn't really correct
+            // --- we should not cross section boundaries ... We really should NULL out
+            // the function/symbol in this case unless there is a bad assumption
+            // here due to inlined functions?
+            m_current_offset = m_current_pc.GetFileAddress() - m_start_pc.GetFileAddress();
+        }
+        m_current_offset_backed_up_one = m_current_offset;
+    }
+    else
+    {
+        m_start_pc = m_current_pc;
+        m_current_offset = -1;
+        m_current_offset_backed_up_one = -1;
+    }
+
+    // We've set m_frame_type and m_sym_ctx before these calls.
+
+    m_fast_unwind_plan_sp = GetFastUnwindPlanForFrame ();
+    m_full_unwind_plan_sp = GetFullUnwindPlanForFrame ();
+
+    UnwindPlan::RowSP active_row;
+    int cfa_offset = 0;
+    int row_register_kind = -1;
+    if (m_full_unwind_plan_sp && m_full_unwind_plan_sp->PlanValidAtAddress (m_current_pc))
+    {
+        active_row = m_full_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset);
+        row_register_kind = m_full_unwind_plan_sp->GetRegisterKind ();
+        if (active_row.get() && log)
+        {
+            StreamString active_row_strm;
+            active_row->Dump(active_row_strm, m_full_unwind_plan_sp.get(), &m_thread, m_start_pc.GetLoadAddress(exe_ctx.GetTargetPtr()));
+            UnwindLogMsg ("%s", active_row_strm.GetString().c_str());
+        }
+    }
+
+    if (!active_row.get())
+    {
+        m_frame_type = eNotAValidFrame;
+        return;
+    }
+
+
+    addr_t cfa_regval = LLDB_INVALID_ADDRESS;
+    if (!ReadGPRValue (row_register_kind, active_row->GetCFARegister(), cfa_regval))
+    {
+        m_frame_type = eNotAValidFrame;
+        return;
+    }
+
+    cfa_offset = active_row->GetCFAOffset ();
+    m_cfa = cfa_regval + cfa_offset;
+
+    UnwindLogMsg ("cfa_regval = 0x%16.16" PRIx64 " (cfa_regval = 0x%16.16" PRIx64 ", cfa_offset = %i)", m_cfa, cfa_regval, cfa_offset);
+    UnwindLogMsg ("initialized frame current pc is 0x%" PRIx64 " cfa is 0x%" PRIx64 " using %s UnwindPlan",
+            (uint64_t) m_current_pc.GetLoadAddress (exe_ctx.GetTargetPtr()),
+            (uint64_t) m_cfa,
+            m_full_unwind_plan_sp->GetSourceName().GetCString());
+}
+
+// Initialize a RegisterContextLLDB for the non-zeroth frame -- rely on the RegisterContextLLDB "below" it
+// to provide things like its current pc value.
+
+void
+RegisterContextLLDB::InitializeNonZerothFrame()
+{
+    Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
+    if (IsFrameZero ())
+    {
+        m_frame_type = eNotAValidFrame;
+        return;
+    }
+
+    if (!GetNextFrame().get() || !GetNextFrame()->IsValid())
+    {
+        m_frame_type = eNotAValidFrame;
+        return;
+    }
+    if (!m_thread.GetRegisterContext())
+    {
+        m_frame_type = eNotAValidFrame;
+        return;
+    }
+
+    addr_t pc;
+    if (!ReadGPRValue (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, pc))
+    {
+        UnwindLogMsg ("could not get pc value");
+        m_frame_type = eNotAValidFrame;
+        return;
+    }
+
+    if (log)
+    {
+        UnwindLogMsg ("pc = 0x%16.16" PRIx64, pc);
+        addr_t reg_val;
+        if (ReadGPRValue (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP, reg_val))
+            UnwindLogMsg ("fp = 0x%16.16" PRIx64, reg_val);
+        if (ReadGPRValue (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, reg_val))
+            UnwindLogMsg ("sp = 0x%16.16" PRIx64, reg_val);
+    }
+
+    // A pc of 0x0 means it's the end of the stack crawl
+    if (pc == 0)
+    {
+        m_frame_type = eNotAValidFrame;
+        return;
+    }
+
+    ExecutionContext exe_ctx(m_thread.shared_from_this());
+    Process *process = exe_ctx.GetProcessPtr();
+    // Let ABIs fixup code addresses to make sure they are valid. In ARM ABIs
+    // this will strip bit zero in case we read a PC from memory or from the LR.
+    ABI *abi = process->GetABI().get();
+    if (abi)
+        pc = abi->FixCodeAddress(pc);
+
+    process->GetTarget().GetSectionLoadList().ResolveLoadAddress (pc, m_current_pc);
+
+    // If we don't have a Module for some reason, we're not going to find symbol/function information - just
+    // stick in some reasonable defaults and hope we can unwind past this frame.
+    ModuleSP pc_module_sp (m_current_pc.GetModule());
+    if (!m_current_pc.IsValid() || !pc_module_sp)
+    {
+        UnwindLogMsg ("using architectural default unwind method");
+
+        // Test the pc value to see if we know it's in an unmapped/non-executable region of memory.
+        uint32_t permissions;
+        if (process->GetLoadAddressPermissions(pc, permissions)
+            && (permissions & ePermissionsExecutable) == 0)
+        {
+            // If this is the second frame off the stack, we may have unwound the first frame
+            // incorrectly.  But using the architecture default unwind plan may get us back on
+            // track -- albeit possibly skipping a real frame.  Give this frame a clearly-invalid
+            // pc and see if we can get any further.
+            if (GetNextFrame().get() && GetNextFrame()->IsValid() && GetNextFrame()->IsFrameZero())
+            {
+                UnwindLogMsg ("had a pc of 0x%" PRIx64 " which is not in executable memory but on frame 1 -- allowing it once.",
+                         (uint64_t) pc);
+                m_frame_type = eSkipFrame;
+            }
+            else
+            {
+                // anywhere other than the second frame, a non-executable pc means we're off in the weeds -- stop now.
+                m_frame_type = eNotAValidFrame;
+                return;
+            }
+        }
+
+        if (abi)
+        {
+            m_fast_unwind_plan_sp.reset ();
+            m_full_unwind_plan_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
+            abi->CreateDefaultUnwindPlan(*m_full_unwind_plan_sp);
+            if (m_frame_type != eSkipFrame)  // don't override eSkipFrame
+            {
+                m_frame_type = eNormalFrame;
+            }
+            m_all_registers_available = false;
+            m_current_offset = -1;
+            m_current_offset_backed_up_one = -1;
+            addr_t cfa_regval = LLDB_INVALID_ADDRESS;
+            int row_register_kind = m_full_unwind_plan_sp->GetRegisterKind ();
+            UnwindPlan::RowSP row = m_full_unwind_plan_sp->GetRowForFunctionOffset(0);
+            if (row.get())
+            {
+                uint32_t cfa_regnum = row->GetCFARegister();
+                int cfa_offset = row->GetCFAOffset();
+                if (!ReadGPRValue (row_register_kind, cfa_regnum, cfa_regval))
+                {
+                    UnwindLogMsg ("failed to get cfa value");
+                    if (m_frame_type != eSkipFrame)   // don't override eSkipFrame
+                    {
+                        m_frame_type = eNormalFrame;
+                    }
+                    return;
+                }
+                m_cfa = cfa_regval + cfa_offset;
+
+                // A couple of sanity checks..
+                if (cfa_regval == LLDB_INVALID_ADDRESS || cfa_regval == 0 || cfa_regval == 1)
+                {
+                    UnwindLogMsg ("could not find a valid cfa address");
+                    m_frame_type = eNotAValidFrame;
+                    return;
+                }
+
+                // cfa_regval should point into the stack memory; if we can query memory region permissions,
+                // see if the memory is allocated & readable.
+                if (process->GetLoadAddressPermissions(cfa_regval, permissions)
+                    && (permissions & ePermissionsReadable) == 0)
+                {
+                    m_frame_type = eNotAValidFrame;
+                    return;
+                }
+            }
+            else
+            {
+                UnwindLogMsg ("could not find a row for function offset zero");
+                m_frame_type = eNotAValidFrame;
+                return;
+            }
+
+            UnwindLogMsg ("initialized frame cfa is 0x%" PRIx64, (uint64_t) m_cfa);
+            return;
+        }
+        m_frame_type = eNotAValidFrame;
+        return;
+    }
+
+    // We require that eSymbolContextSymbol be successfully filled in or this context is of no use to us.
+    if ((pc_module_sp->ResolveSymbolContextForAddress (m_current_pc, eSymbolContextFunction| eSymbolContextSymbol, m_sym_ctx) & eSymbolContextSymbol) == eSymbolContextSymbol)
+    {
+        m_sym_ctx_valid = true;
+    }
+
+    AddressRange addr_range;
+    if (!m_sym_ctx.GetAddressRange (eSymbolContextFunction | eSymbolContextSymbol, 0, false, addr_range))
+    {
+        m_sym_ctx_valid = false;
+    }
+
+    bool decr_pc_and_recompute_addr_range = false;
+
+    // If the symbol lookup failed...
+    if (m_sym_ctx_valid == false)
+       decr_pc_and_recompute_addr_range = true;
+
+    // Or if we're in the middle of the stack (and not "above" an asynchronous event like sigtramp),
+    // and our "current" pc is the start of a function...
+    if (m_sym_ctx_valid
+        && GetNextFrame()->m_frame_type != eSigtrampFrame
+        && GetNextFrame()->m_frame_type != eDebuggerFrame
+        && addr_range.GetBaseAddress().IsValid()
+        && addr_range.GetBaseAddress().GetSection() == m_current_pc.GetSection()
+        && addr_range.GetBaseAddress().GetOffset() == m_current_pc.GetOffset())
+    {
+        decr_pc_and_recompute_addr_range = true;
+    }
+
+    // We need to back up the pc by 1 byte and re-search for the Symbol to handle the case where the "saved pc"
+    // value is pointing to the next function, e.g. if a function ends with a CALL instruction.
+    // FIXME this may need to be an architectural-dependent behavior; if so we'll need to add a member function
+    // to the ABI plugin and consult that.
+    if (decr_pc_and_recompute_addr_range)
+    {
+        Address temporary_pc(m_current_pc);
+        temporary_pc.SetOffset(m_current_pc.GetOffset() - 1);
+        m_sym_ctx.Clear(false);
+        m_sym_ctx_valid = false;
+        if ((pc_module_sp->ResolveSymbolContextForAddress (temporary_pc, eSymbolContextFunction| eSymbolContextSymbol, m_sym_ctx) & eSymbolContextSymbol) == eSymbolContextSymbol)
+        {
+            m_sym_ctx_valid = true;
+        }
+        if (!m_sym_ctx.GetAddressRange (eSymbolContextFunction | eSymbolContextSymbol, 0, false,  addr_range))
+        {
+            m_sym_ctx_valid = false;
+        }
+    }
+
+    // If we were able to find a symbol/function, set addr_range_ptr to the bounds of that symbol/function.
+    // else treat the current pc value as the start_pc and record no offset.
+    if (addr_range.GetBaseAddress().IsValid())
+    {
+        m_start_pc = addr_range.GetBaseAddress();
+        m_current_offset = m_current_pc.GetOffset() - m_start_pc.GetOffset();
+        m_current_offset_backed_up_one = m_current_offset;
+        if (decr_pc_and_recompute_addr_range && m_current_offset_backed_up_one > 0)
+        {
+            m_current_offset_backed_up_one--;
+            if (m_sym_ctx_valid)
+                m_current_pc.SetOffset(m_current_pc.GetOffset() - 1);
+        }
+    }
+    else
+    {
+        m_start_pc = m_current_pc;
+        m_current_offset = -1;
+        m_current_offset_backed_up_one = -1;
+    }
+
+    static ConstString sigtramp_name ("_sigtramp");
+    if ((m_sym_ctx.function && m_sym_ctx.function->GetMangled().GetMangledName() == sigtramp_name)
+        || (m_sym_ctx.symbol && m_sym_ctx.symbol->GetMangled().GetMangledName() == sigtramp_name))
+    {
+        m_frame_type = eSigtrampFrame;
+    }
+    else
+    {
+        // FIXME:  Detect eDebuggerFrame here.
+        if (m_frame_type != eSkipFrame) // don't override eSkipFrame
+        {
+            m_frame_type = eNormalFrame;
+        }
+    }
+
+    // We've set m_frame_type and m_sym_ctx before this call.
+    m_fast_unwind_plan_sp = GetFastUnwindPlanForFrame ();
+
+    UnwindPlan::RowSP active_row;
+    int cfa_offset = 0;
+    int row_register_kind = -1;
+
+    // Try to get by with just the fast UnwindPlan if possible - the full UnwindPlan may be expensive to get
+    // (e.g. if we have to parse the entire eh_frame section of an ObjectFile for the first time.)
+
+    if (m_fast_unwind_plan_sp && m_fast_unwind_plan_sp->PlanValidAtAddress (m_current_pc))
+    {
+        active_row = m_fast_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset);
+        row_register_kind = m_fast_unwind_plan_sp->GetRegisterKind ();
+        if (active_row.get() && log)
+        {
+            StreamString active_row_strm;
+            active_row->Dump(active_row_strm, m_fast_unwind_plan_sp.get(), &m_thread, m_start_pc.GetLoadAddress(exe_ctx.GetTargetPtr()));
+            UnwindLogMsg ("active row: %s", active_row_strm.GetString().c_str());
+        }
+    }
+    else
+    {
+        m_full_unwind_plan_sp = GetFullUnwindPlanForFrame ();
+        if (m_full_unwind_plan_sp && m_full_unwind_plan_sp->PlanValidAtAddress (m_current_pc))
+        {
+            active_row = m_full_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset);
+            row_register_kind = m_full_unwind_plan_sp->GetRegisterKind ();
+            if (active_row.get() && log)
+            {
+                StreamString active_row_strm;
+                active_row->Dump(active_row_strm, m_full_unwind_plan_sp.get(), &m_thread, m_start_pc.GetLoadAddress(exe_ctx.GetTargetPtr()));
+                UnwindLogMsg ("active row: %s", active_row_strm.GetString().c_str());
+            }
+        }
+    }
+
+    if (!active_row.get())
+    {
+        m_frame_type = eNotAValidFrame;
+        return;
+    }
+
+    addr_t cfa_regval = LLDB_INVALID_ADDRESS;
+    if (!ReadGPRValue (row_register_kind, active_row->GetCFARegister(), cfa_regval))
+    {
+        UnwindLogMsg ("failed to get cfa reg %d/%d", row_register_kind, active_row->GetCFARegister());
+        m_frame_type = eNotAValidFrame;
+        return;
+    }
+
+    cfa_offset = active_row->GetCFAOffset ();
+    m_cfa = cfa_regval + cfa_offset;
+
+    UnwindLogMsg ("cfa_regval = 0x%16.16" PRIx64 " (cfa_regval = 0x%16.16" PRIx64 ", cfa_offset = %i)", m_cfa, cfa_regval, cfa_offset);
+
+    // A couple of sanity checks..
+    if (cfa_regval == LLDB_INVALID_ADDRESS || cfa_regval == 0 || cfa_regval == 1)
+    {
+        UnwindLogMsg ("could not find a valid cfa address");
+        m_frame_type = eNotAValidFrame;
+        return;
+    }
+
+    // If we have a bad stack setup, we can get the same CFA value multiple times -- or even
+    // more devious, we can actually oscillate between two CFA values.  Detect that here and
+    // break out to avoid a possible infinite loop in lldb trying to unwind the stack.
+    addr_t next_frame_cfa;
+    addr_t next_next_frame_cfa = LLDB_INVALID_ADDRESS;
+    if (GetNextFrame().get() && GetNextFrame()->GetCFA(next_frame_cfa))
+    {
+        bool repeating_frames = false;
+        if (next_frame_cfa == m_cfa)
+        {
+            repeating_frames = true;
+        }
+        else
+        {
+            if (GetNextFrame()->GetNextFrame() && GetNextFrame()->GetNextFrame()->GetCFA(next_next_frame_cfa)
+                && next_next_frame_cfa == m_cfa)
+            {
+                repeating_frames = true;
+            }
+        }
+        if (repeating_frames && abi->FunctionCallsChangeCFA())
+        {
+            UnwindLogMsg ("same CFA address as next frame, assuming the unwind is looping - stopping");
+            m_frame_type = eNotAValidFrame;
+            return;
+        }
+    }
+
+    UnwindLogMsg ("initialized frame current pc is 0x%" PRIx64 " cfa is 0x%" PRIx64,
+            (uint64_t) m_current_pc.GetLoadAddress (exe_ctx.GetTargetPtr()), (uint64_t) m_cfa);
+}
+
+
+bool
+RegisterContextLLDB::IsFrameZero () const
+{
+    return m_frame_number == 0;
+}
+
+
+// Find a fast unwind plan for this frame, if possible.
+//
+// On entry to this method,
+//
+//   1. m_frame_type should already be set to eSigtrampFrame/eDebuggerFrame if either of those are correct,
+//   2. m_sym_ctx should already be filled in, and
+//   3. m_current_pc should have the current pc value for this frame
+//   4. m_current_offset_backed_up_one should have the current byte offset into the function, maybe backed up by 1, -1 if unknown
+
+UnwindPlanSP
+RegisterContextLLDB::GetFastUnwindPlanForFrame ()
+{
+    UnwindPlanSP unwind_plan_sp;
+    ModuleSP pc_module_sp (m_current_pc.GetModule());
+
+    if (!m_current_pc.IsValid() || !pc_module_sp || pc_module_sp->GetObjectFile() == NULL)
+        return unwind_plan_sp;
+
+    if (IsFrameZero ())
+        return unwind_plan_sp;
+
+    FuncUnwindersSP func_unwinders_sp (pc_module_sp->GetObjectFile()->GetUnwindTable().GetFuncUnwindersContainingAddress (m_current_pc, m_sym_ctx));
+    if (!func_unwinders_sp)
+        return unwind_plan_sp;
+
+    // If we're in _sigtramp(), unwinding past this frame requires special knowledge.
+    if (m_frame_type == eSigtrampFrame || m_frame_type == eDebuggerFrame)
+        return unwind_plan_sp;
+
+    unwind_plan_sp = func_unwinders_sp->GetUnwindPlanFastUnwind (m_thread);
+    if (unwind_plan_sp)
+    {
+        if (unwind_plan_sp->PlanValidAtAddress (m_current_pc))
+        {
+            Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
+            if (log && log->GetVerbose())
+            {
+                if (m_fast_unwind_plan_sp)
+                    UnwindLogMsgVerbose ("frame, and has a fast UnwindPlan");
+                else
+                    UnwindLogMsgVerbose ("frame");
+            }
+            m_frame_type = eNormalFrame;
+            return unwind_plan_sp;
+        }
+        else
+        {
+            unwind_plan_sp.reset();
+        }
+    }
+    return unwind_plan_sp;
+}
+
+// On entry to this method,
+//
+//   1. m_frame_type should already be set to eSigtrampFrame/eDebuggerFrame if either of those are correct,
+//   2. m_sym_ctx should already be filled in, and
+//   3. m_current_pc should have the current pc value for this frame
+//   4. m_current_offset_backed_up_one should have the current byte offset into the function, maybe backed up by 1, -1 if unknown
+
+UnwindPlanSP
+RegisterContextLLDB::GetFullUnwindPlanForFrame ()
+{
+    UnwindPlanSP unwind_plan_sp;
+    UnwindPlanSP arch_default_unwind_plan_sp;
+    ExecutionContext exe_ctx(m_thread.shared_from_this());
+    Process *process = exe_ctx.GetProcessPtr();
+    ABI *abi = process ? process->GetABI().get() : NULL;
+    if (abi)
+    {
+        arch_default_unwind_plan_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
+        abi->CreateDefaultUnwindPlan(*arch_default_unwind_plan_sp);
+    }
+
+    bool behaves_like_zeroth_frame = false;
+    if (IsFrameZero ()
+        || GetNextFrame()->m_frame_type == eSigtrampFrame
+        || GetNextFrame()->m_frame_type == eDebuggerFrame)
+    {
+        behaves_like_zeroth_frame = true;
+        // If this frame behaves like a 0th frame (currently executing or
+        // interrupted asynchronously), all registers can be retrieved.
+        m_all_registers_available = true;
+    }
+
+    // If we've done a jmp 0x0 / bl 0x0 (called through a null function pointer) so the pc is 0x0
+    // in the zeroth frame, we need to use the "unwind at first instruction" arch default UnwindPlan
+    // Also, if this Process can report on memory region attributes, any non-executable region means
+    // we jumped through a bad function pointer - handle the same way as 0x0.
+    // Note, if the symbol context has a function for the symbol, then we don't need to do this check.
+
+    if ((!m_sym_ctx_valid  || m_sym_ctx.function == NULL) && behaves_like_zeroth_frame && m_current_pc.IsValid())
+    {
+        uint32_t permissions;
+        addr_t current_pc_addr = m_current_pc.GetLoadAddress (exe_ctx.GetTargetPtr());
+        if (current_pc_addr == 0
+            || (process->GetLoadAddressPermissions(current_pc_addr, permissions)
+                && (permissions & ePermissionsExecutable) == 0))
+        {
+            unwind_plan_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
+            abi->CreateFunctionEntryUnwindPlan(*unwind_plan_sp);
+            m_frame_type = eNormalFrame;
+            return unwind_plan_sp;
+        }
+    }
+
+    // No Module for the current pc, try using the architecture default unwind.
+    ModuleSP pc_module_sp (m_current_pc.GetModule());
+    if (!m_current_pc.IsValid() || !pc_module_sp || pc_module_sp->GetObjectFile() == NULL)
+    {
+        m_frame_type = eNormalFrame;
+        return arch_default_unwind_plan_sp;
+    }
+
+    FuncUnwindersSP func_unwinders_sp;
+    if (m_sym_ctx_valid)
+    {
+        func_unwinders_sp = pc_module_sp->GetObjectFile()->GetUnwindTable().GetFuncUnwindersContainingAddress (m_current_pc, m_sym_ctx);
+    }
+
+    // No FuncUnwinders available for this pc (i.e. a stripped function symbol and -fomit-frame-pointer).
+    // Try using the eh_frame information relative to the current PC,
+    // and finally fall back on the architectural default unwind.
+    if (!func_unwinders_sp)
+    {
+        DWARFCallFrameInfo *eh_frame = pc_module_sp && pc_module_sp->GetObjectFile() ? 
+            pc_module_sp->GetObjectFile()->GetUnwindTable().GetEHFrameInfo() : nullptr;
+
+        m_frame_type = eNormalFrame;
+        if (eh_frame && m_current_pc.IsValid())
+        {
+            unwind_plan_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
+            // Even with -fomit-frame-pointer, we can try eh_frame to get back on track.
+            if (eh_frame->GetUnwindPlan (m_current_pc, *unwind_plan_sp))
+                return unwind_plan_sp;
+            else
+                unwind_plan_sp.reset();
+        }
+        return arch_default_unwind_plan_sp;
+    }
+
+    // If we're in _sigtramp(), unwinding past this frame requires special knowledge.  On Mac OS X this knowledge
+    // is properly encoded in the eh_frame section, so prefer that if available.
+    // On other platforms we may need to provide a platform-specific UnwindPlan which encodes the details of
+    // how to unwind out of sigtramp.
+    if (m_frame_type == eSigtrampFrame)
+    {
+        m_fast_unwind_plan_sp.reset();
+        unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtCallSite (m_current_offset_backed_up_one);
+        if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress (m_current_pc))
+            return unwind_plan_sp;
+    }
+
+    // Ask the DynamicLoader if the eh_frame CFI should be trusted in this frame even when it's frame zero
+    // This comes up if we have hand-written functions in a Module and hand-written eh_frame.  The assembly
+    // instruction inspection may fail and the eh_frame CFI were probably written with some care to do the
+    // right thing.  It'd be nice if there was a way to ask the eh_frame directly if it is asynchronous
+    // (can be trusted at every instruction point) or synchronous (the normal case - only at call sites).
+    // But there is not.
+    if (process && process->GetDynamicLoader() && process->GetDynamicLoader()->AlwaysRelyOnEHUnwindInfo (m_sym_ctx))
+    {
+        unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtCallSite (m_current_offset_backed_up_one);
+        if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress (m_current_pc))
+        {
+            UnwindLogMsgVerbose ("frame uses %s for full UnwindPlan because the DynamicLoader suggested we prefer it",
+                           unwind_plan_sp->GetSourceName().GetCString());
+            return unwind_plan_sp;
+        }
+    }
+
+    // Typically the NonCallSite UnwindPlan is the unwind created by inspecting the assembly language instructions
+    if (behaves_like_zeroth_frame)
+    {
+        unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtNonCallSite (m_thread);
+        if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress (m_current_pc))
+        {
+            UnwindLogMsgVerbose ("frame uses %s for full UnwindPlan", unwind_plan_sp->GetSourceName().GetCString());
+            return unwind_plan_sp;
+        }
+    }
+
+    // Typically this is unwind info from an eh_frame section intended for exception handling; only valid at call sites
+    unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtCallSite (m_current_offset_backed_up_one);
+    if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress (m_current_pc))
+    {
+        UnwindLogMsgVerbose ("frame uses %s for full UnwindPlan", unwind_plan_sp->GetSourceName().GetCString());
+        return unwind_plan_sp;
+    }
+
+    // We'd prefer to use an UnwindPlan intended for call sites when we're at a call site but if we've
+    // struck out on that, fall back to using the non-call-site assembly inspection UnwindPlan if possible.
+    unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtNonCallSite (m_thread);
+    if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress (m_current_pc))
+    {
+        UnwindLogMsgVerbose ("frame uses %s for full UnwindPlan", unwind_plan_sp->GetSourceName().GetCString());
+        return unwind_plan_sp;
+    }
+
+    // If nothing else, use the architectural default UnwindPlan and hope that does the job.
+    UnwindLogMsgVerbose ("frame uses %s for full UnwindPlan", arch_default_unwind_plan_sp->GetSourceName().GetCString());
+    return arch_default_unwind_plan_sp;
+}
+
+
+void
+RegisterContextLLDB::InvalidateAllRegisters ()
+{
+    m_frame_type = eNotAValidFrame;
+}
+
+size_t
+RegisterContextLLDB::GetRegisterCount ()
+{
+    return m_thread.GetRegisterContext()->GetRegisterCount();
+}
+
+const RegisterInfo *
+RegisterContextLLDB::GetRegisterInfoAtIndex (size_t reg)
+{
+    return m_thread.GetRegisterContext()->GetRegisterInfoAtIndex (reg);
+}
+
+size_t
+RegisterContextLLDB::GetRegisterSetCount ()
+{
+    return m_thread.GetRegisterContext()->GetRegisterSetCount ();
+}
+
+const RegisterSet *
+RegisterContextLLDB::GetRegisterSet (size_t reg_set)
+{
+    return m_thread.GetRegisterContext()->GetRegisterSet (reg_set);
+}
+
+uint32_t
+RegisterContextLLDB::ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num)
+{
+    return m_thread.GetRegisterContext()->ConvertRegisterKindToRegisterNumber (kind, num);
+}
+
+bool
+RegisterContextLLDB::ReadRegisterValueFromRegisterLocation (lldb_private::UnwindLLDB::RegisterLocation regloc,
+                                                            const RegisterInfo *reg_info,
+                                                            RegisterValue &value)
+{
+    if (!IsValid())
+        return false;
+    bool success = false;
+
+    switch (regloc.type)
+    {
+    case UnwindLLDB::RegisterLocation::eRegisterInRegister:
+        {
+            const RegisterInfo *other_reg_info = GetRegisterInfoAtIndex(regloc.location.register_number);
+
+            if (!other_reg_info)
+                return false;
+
+            if (IsFrameZero ())
+            {
+                success = m_thread.GetRegisterContext()->ReadRegister (other_reg_info, value);
+            }
+            else
+            {
+                success = GetNextFrame()->ReadRegister (other_reg_info, value);
+            }
+        }
+        break;
+    case UnwindLLDB::RegisterLocation::eRegisterValueInferred:
+        success = value.SetUInt (regloc.location.inferred_value, reg_info->byte_size);
+        break;
+
+    case UnwindLLDB::RegisterLocation::eRegisterNotSaved:
+        break;
+    case UnwindLLDB::RegisterLocation::eRegisterSavedAtHostMemoryLocation:
+        assert ("FIXME debugger inferior function call unwind");
+        break;
+    case UnwindLLDB::RegisterLocation::eRegisterSavedAtMemoryLocation:
+        {
+            Error error (ReadRegisterValueFromMemory(reg_info,
+                                                     regloc.location.target_memory_location,
+                                                     reg_info->byte_size,
+                                                     value));
+            success = error.Success();
+        }
+        break;
+    default:
+        assert ("Unknown RegisterLocation type.");
+        break;
+    }
+    return success;
+}
+
+bool
+RegisterContextLLDB::WriteRegisterValueToRegisterLocation (lldb_private::UnwindLLDB::RegisterLocation regloc,
+                                                           const RegisterInfo *reg_info,
+                                                           const RegisterValue &value)
+{
+    if (!IsValid())
+        return false;
+
+    bool success = false;
+
+    switch (regloc.type)
+    {
+        case UnwindLLDB::RegisterLocation::eRegisterInRegister:
+            {
+                const RegisterInfo *other_reg_info = GetRegisterInfoAtIndex(regloc.location.register_number);
+                if (IsFrameZero ())
+                {
+                    success = m_thread.GetRegisterContext()->WriteRegister (other_reg_info, value);
+                }
+                else
+                {
+                    success = GetNextFrame()->WriteRegister (other_reg_info, value);
+                }
+            }
+            break;
+        case UnwindLLDB::RegisterLocation::eRegisterValueInferred:
+        case UnwindLLDB::RegisterLocation::eRegisterNotSaved:
+            break;
+        case UnwindLLDB::RegisterLocation::eRegisterSavedAtHostMemoryLocation:
+            assert ("FIXME debugger inferior function call unwind");
+            break;
+        case UnwindLLDB::RegisterLocation::eRegisterSavedAtMemoryLocation:
+            {
+                Error error (WriteRegisterValueToMemory (reg_info,
+                                                         regloc.location.target_memory_location,
+                                                         reg_info->byte_size,
+                                                         value));
+                success = error.Success();
+            }
+            break;
+        default:
+            assert ("Unknown RegisterLocation type.");
+            break;
+    }
+    return success;
+}
+
+
+bool
+RegisterContextLLDB::IsValid () const
+{
+    return m_frame_type != eNotAValidFrame;
+}
+
+// A skip frame is a bogus frame on the stack -- but one where we're likely to find a real frame farther
+// up the stack if we keep looking.  It's always the second frame in an unwind (i.e. the first frame after
+// frame zero) where unwinding can be the trickiest.  Ideally we'll mark up this frame in some way so the
+// user knows we're displaying bad data and we may have skipped one frame of their real program in the
+// process of getting back on track.
+
+bool
+RegisterContextLLDB::IsSkipFrame () const
+{
+    return m_frame_type == eSkipFrame;
+}
+
+// Answer the question: Where did THIS frame save the CALLER frame ("previous" frame)'s register value?
+
+enum UnwindLLDB::RegisterSearchResult
+RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation &regloc)
+{
+    // Have we already found this register location?
+    if (!m_registers.empty())
+    {
+        std::map<uint32_t, lldb_private::UnwindLLDB::RegisterLocation>::const_iterator iterator;
+        iterator = m_registers.find (lldb_regnum);
+        if (iterator != m_registers.end())
+        {
+            regloc = iterator->second;
+            UnwindLogMsg ("supplying caller's saved reg %d's location, cached", lldb_regnum);
+            return UnwindLLDB::RegisterSearchResult::eRegisterFound;
+        }
+    }
+
+    uint32_t sp_regnum = LLDB_INVALID_REGNUM;
+    uint32_t pc_regnum = LLDB_INVALID_REGNUM;
+    m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, eRegisterKindLLDB, sp_regnum);
+    m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, eRegisterKindLLDB, pc_regnum);
+
+    // Are we looking for the CALLER's stack pointer?  The stack pointer is defined to be the same as THIS frame's
+    // CFA so just return the CFA value.  This is true on x86-32/x86-64 at least.
+    if (sp_regnum != LLDB_INVALID_REGNUM && sp_regnum == lldb_regnum)
+    {
+        // make sure we won't lose precision copying an addr_t (m_cfa) into a uint64_t (.inferred_value)
+        assert (sizeof (addr_t) <= sizeof (uint64_t));
+        regloc.type = UnwindLLDB::RegisterLocation::eRegisterValueInferred;
+        regloc.location.inferred_value = m_cfa;
+        m_registers[lldb_regnum] = regloc;
+        UnwindLogMsg ("supplying caller's stack pointer (%d) value, computed from CFA", lldb_regnum);
+        return UnwindLLDB::RegisterSearchResult::eRegisterFound;
+    }
+
+    // Look through the available UnwindPlans for the register location.
+
+    UnwindPlan::Row::RegisterLocation unwindplan_regloc;
+    bool have_unwindplan_regloc = false;
+    RegisterKind unwindplan_registerkind = (RegisterKind)-1;
+
+    if (m_fast_unwind_plan_sp)
+    {
+        UnwindPlan::RowSP active_row = m_fast_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset);
+        unwindplan_registerkind = m_fast_unwind_plan_sp->GetRegisterKind ();
+        uint32_t row_regnum;
+        if (!m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindLLDB, lldb_regnum, unwindplan_registerkind, row_regnum))
+        {
+            UnwindLogMsg ("could not convert lldb regnum %d into %d RegisterKind reg numbering scheme",
+                    lldb_regnum, (int) unwindplan_registerkind);
+            return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
+        }
+        if (active_row->GetRegisterInfo (row_regnum, unwindplan_regloc))
+        {
+            UnwindLogMsg ("supplying caller's saved reg %d's location using FastUnwindPlan", lldb_regnum);
+            have_unwindplan_regloc = true;
+        }
+    }
+
+    if (!have_unwindplan_regloc)
+    {
+        // m_full_unwind_plan_sp being NULL means that we haven't tried to find a full UnwindPlan yet
+        if (!m_full_unwind_plan_sp)
+            m_full_unwind_plan_sp = GetFullUnwindPlanForFrame ();
+
+        if (m_full_unwind_plan_sp)
+        {
+            UnwindPlan::RowSP active_row = m_full_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset);
+            unwindplan_registerkind = m_full_unwind_plan_sp->GetRegisterKind ();
+            uint32_t row_regnum;
+            bool row_register_rewritten_to_return_address_reg = false;
+
+            // If we're fetching the saved pc and this UnwindPlan defines a ReturnAddress register (e.g. lr on arm),
+            // look for the return address register number in the UnwindPlan's row.
+            if (lldb_regnum == pc_regnum && m_full_unwind_plan_sp->GetReturnAddressRegister() != LLDB_INVALID_REGNUM)
+            {
+               row_regnum = m_full_unwind_plan_sp->GetReturnAddressRegister();
+               row_register_rewritten_to_return_address_reg = true;
+               UnwindLogMsg ("requested caller's saved PC but this UnwindPlan uses a RA reg; getting reg %d instead",
+                       row_regnum);
+            }
+            else
+            {
+                if (!m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindLLDB, lldb_regnum, unwindplan_registerkind, row_regnum))
+                {
+                    if (unwindplan_registerkind == eRegisterKindGeneric)
+                        UnwindLogMsg ("could not convert lldb regnum %d into eRegisterKindGeneric reg numbering scheme", lldb_regnum);
+                    else
+                        UnwindLogMsg ("could not convert lldb regnum %d into %d RegisterKind reg numbering scheme",
+                                lldb_regnum, (int) unwindplan_registerkind);
+                    return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
+                }
+            }
+
+            if (active_row->GetRegisterInfo (row_regnum, unwindplan_regloc))
+            {
+                have_unwindplan_regloc = true;
+                UnwindLogMsg ("supplying caller's saved reg %d's location using %s UnwindPlan", lldb_regnum,
+                              m_full_unwind_plan_sp->GetSourceName().GetCString());
+            }
+
+            // This is frame 0 and we're retrieving the PC and it's saved in a Return Address register and
+            // it hasn't been saved anywhere yet -- that is, it's still live in the actual register.
+            // Handle this specially.
+
+            if (have_unwindplan_regloc == false 
+                && row_register_rewritten_to_return_address_reg == true 
+                && IsFrameZero()
+                && row_regnum != LLDB_INVALID_REGNUM)
+            {
+                uint32_t ra_regnum_in_lldb_reg_numbering;
+                if (m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (unwindplan_registerkind, row_regnum, eRegisterKindLLDB, ra_regnum_in_lldb_reg_numbering))
+                {
+                    lldb_private::UnwindLLDB::RegisterLocation new_regloc;
+                    new_regloc.type = UnwindLLDB::RegisterLocation::eRegisterInRegister;
+                    new_regloc.location.register_number = ra_regnum_in_lldb_reg_numbering;
+                    m_registers[lldb_regnum] = new_regloc;
+                    regloc = new_regloc;
+                    UnwindLogMsg ("supplying caller's register %d from the live RegisterContext at frame 0, saved in %d", lldb_regnum, ra_regnum_in_lldb_reg_numbering);
+                    return UnwindLLDB::RegisterSearchResult::eRegisterFound;
+                }
+            }
+
+            // If this architecture stores the return address in a register (it defines a Return Address register)
+            // and we're on a non-zero stack frame and the Full UnwindPlan says that the pc is stored in the
+            // RA registers (e.g. lr on arm), then we know that the full unwindplan is not trustworthy -- this
+            // is an impossible situation and the instruction emulation code has likely been misled.  
+            // If this stack frame meets those criteria, we need to throw away the Full UnwindPlan that the 
+            // instruction emulation came up with and fall back to the architecture's Default UnwindPlan so
+            // the stack walk can get past this point.
+
+            // Special note:  If the Full UnwindPlan was generated from the compiler, don't second-guess it 
+            // when we're at a call site location.
+
+            // arch_default_ra_regnum is the return address register # in the Full UnwindPlan register numbering
+            uint32_t arch_default_ra_regnum = LLDB_INVALID_REGNUM; 
+            if (m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, unwindplan_registerkind, arch_default_ra_regnum)
+                && arch_default_ra_regnum != LLDB_INVALID_REGNUM
+                && pc_regnum != LLDB_INVALID_REGNUM
+                && pc_regnum == lldb_regnum
+                && unwindplan_regloc.IsInOtherRegister()
+                && unwindplan_regloc.GetRegisterNumber() == arch_default_ra_regnum
+                && m_full_unwind_plan_sp->GetSourcedFromCompiler() != eLazyBoolYes
+                && !m_all_registers_available)
+            {
+                UnwindLogMsg ("%s UnwindPlan tried to restore the pc from the link register but this is a non-zero frame",
+                              m_full_unwind_plan_sp->GetSourceName().GetCString());
+
+                // Throw away the full unwindplan; install the arch default unwindplan
+                InvalidateFullUnwindPlan();
+
+                // Now re-fetch the pc value we're searching for
+                uint32_t arch_default_pc_reg = LLDB_INVALID_REGNUM;
+                UnwindPlan::RowSP active_row = m_full_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset);
+                if (m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, m_full_unwind_plan_sp->GetRegisterKind(), arch_default_pc_reg)
+                    && arch_default_pc_reg != LLDB_INVALID_REGNUM
+                    && active_row
+                    && active_row->GetRegisterInfo (arch_default_pc_reg, unwindplan_regloc))
+                {
+                    have_unwindplan_regloc = true;
+                }
+                else
+                {
+                    have_unwindplan_regloc = false;
+                }
+            }
+        }
+    }
+
+
+    ExecutionContext exe_ctx(m_thread.shared_from_this());
+    Process *process = exe_ctx.GetProcessPtr();
+    if (have_unwindplan_regloc == false)
+    {
+        // If a volatile register is being requested, we don't want to forward the next frame's register contents
+        // up the stack -- the register is not retrievable at this frame.
+        ABI *abi = process ? process->GetABI().get() : NULL;
+        if (abi)
+        {
+            const RegisterInfo *reg_info = GetRegisterInfoAtIndex(lldb_regnum);
+            if (reg_info && abi->RegisterIsVolatile (reg_info))
+            {
+                UnwindLogMsg ("did not supply reg location for %d because it is volatile", lldb_regnum);
+                return UnwindLLDB::RegisterSearchResult::eRegisterIsVolatile;
+            }
+        }
+
+        if (IsFrameZero ())
+        {
+            // This is frame 0 - we should return the actual live register context value
+            lldb_private::UnwindLLDB::RegisterLocation new_regloc;
+            new_regloc.type = UnwindLLDB::RegisterLocation::eRegisterInRegister;
+            new_regloc.location.register_number = lldb_regnum;
+            m_registers[lldb_regnum] = new_regloc;
+            regloc = new_regloc;
+            UnwindLogMsg ("supplying caller's register %d from the live RegisterContext at frame 0", lldb_regnum);
+            return UnwindLLDB::RegisterSearchResult::eRegisterFound;
+        }
+        else
+        UnwindLogMsg ("could not supply caller's reg %d location", lldb_regnum);
+        return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
+    }
+
+    // unwindplan_regloc has valid contents about where to retrieve the register
+    if (unwindplan_regloc.IsUnspecified())
+    {
+        lldb_private::UnwindLLDB::RegisterLocation new_regloc;
+        new_regloc.type = UnwindLLDB::RegisterLocation::eRegisterNotSaved;
+        m_registers[lldb_regnum] = new_regloc;
+        UnwindLogMsg ("could not supply caller's reg %d location", lldb_regnum);
+        return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
+    }
+
+    if (unwindplan_regloc.IsSame())
+    {
+        if (IsFrameZero ())
+        {
+            UnwindLogMsg ("could not supply caller's reg %d location", lldb_regnum);
+            return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
+        }
+        else
+        {
+            return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
+        }
+    }
+
+    if (unwindplan_regloc.IsCFAPlusOffset())
+    {
+        int offset = unwindplan_regloc.GetOffset();
+        regloc.type = UnwindLLDB::RegisterLocation::eRegisterValueInferred;
+        regloc.location.inferred_value = m_cfa + offset;
+        m_registers[lldb_regnum] = regloc;
+        UnwindLogMsg ("supplying caller's register %d, value is CFA plus offset", lldb_regnum);
+        return UnwindLLDB::RegisterSearchResult::eRegisterFound;
+    }
+
+    if (unwindplan_regloc.IsAtCFAPlusOffset())
+    {
+        int offset = unwindplan_regloc.GetOffset();
+        regloc.type = UnwindLLDB::RegisterLocation::eRegisterSavedAtMemoryLocation;
+        regloc.location.target_memory_location = m_cfa + offset;
+        m_registers[lldb_regnum] = regloc;
+        UnwindLogMsg ("supplying caller's register %d from the stack, saved at CFA plus offset", lldb_regnum);
+        return UnwindLLDB::RegisterSearchResult::eRegisterFound;
+    }
+
+    if (unwindplan_regloc.IsInOtherRegister())
+    {
+        uint32_t unwindplan_regnum = unwindplan_regloc.GetRegisterNumber();
+        uint32_t row_regnum_in_lldb;
+        if (!m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (unwindplan_registerkind, unwindplan_regnum, eRegisterKindLLDB, row_regnum_in_lldb))
+        {
+            UnwindLogMsg ("could not supply caller's reg %d location", lldb_regnum);
+            return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
+        }
+        regloc.type = UnwindLLDB::RegisterLocation::eRegisterInRegister;
+        regloc.location.register_number = row_regnum_in_lldb;
+        m_registers[lldb_regnum] = regloc;
+        UnwindLogMsg ("supplying caller's register %d, saved in register %d", lldb_regnum, row_regnum_in_lldb);
+        return UnwindLLDB::RegisterSearchResult::eRegisterFound;
+    }
+
+    if (unwindplan_regloc.IsDWARFExpression() || unwindplan_regloc.IsAtDWARFExpression())
+    {
+        DataExtractor dwarfdata (unwindplan_regloc.GetDWARFExpressionBytes(),
+                                 unwindplan_regloc.GetDWARFExpressionLength(),
+                                 process->GetByteOrder(), process->GetAddressByteSize());
+        DWARFExpression dwarfexpr (dwarfdata, 0, unwindplan_regloc.GetDWARFExpressionLength());
+        dwarfexpr.SetRegisterKind (unwindplan_registerkind);
+        Value result;
+        Error error;
+        if (dwarfexpr.Evaluate (&exe_ctx, NULL, NULL, this, 0, NULL, result, &error))
+        {
+            addr_t val;
+            val = result.GetScalar().ULongLong();
+            if (unwindplan_regloc.IsDWARFExpression())
+             {
+                regloc.type = UnwindLLDB::RegisterLocation::eRegisterValueInferred;
+                regloc.location.inferred_value = val;
+                m_registers[lldb_regnum] = regloc;
+                UnwindLogMsg ("supplying caller's register %d via DWARF expression (IsDWARFExpression)", lldb_regnum);
+                return UnwindLLDB::RegisterSearchResult::eRegisterFound;
+            }
+            else
+            {
+                regloc.type = UnwindLLDB::RegisterLocation::eRegisterSavedAtMemoryLocation;
+                regloc.location.target_memory_location = val;
+                m_registers[lldb_regnum] = regloc;
+                UnwindLogMsg ("supplying caller's register %d via DWARF expression (IsAtDWARFExpression)", lldb_regnum);
+                return UnwindLLDB::RegisterSearchResult::eRegisterFound;
+            }
+        }
+        UnwindLogMsg ("tried to use IsDWARFExpression or IsAtDWARFExpression for reg %d but failed", lldb_regnum);
+        return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
+    }
+
+    UnwindLogMsg ("could not supply caller's reg %d location", lldb_regnum);
+
+    // FIXME UnwindPlan::Row types atDWARFExpression and isDWARFExpression are unsupported.
+
+    return UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
+}
+
+// If the Full unwindplan has been determined to be incorrect, this method will
+// replace it with the architecture's default unwindplna, if one is defined.
+// It will also find the FuncUnwinders object for this function and replace the
+// Full unwind method for the function there so we don't use the errant Full unwindplan
+// again in the future of this debug session.
+// We're most likely doing this because the Full unwindplan was generated by assembly
+// instruction profiling and the profiler got something wrong.
+
+void
+RegisterContextLLDB::InvalidateFullUnwindPlan ()
+{
+    UnwindPlan::Row::RegisterLocation unwindplan_regloc;
+    ExecutionContext exe_ctx (m_thread.shared_from_this());
+    Process *process = exe_ctx.GetProcessPtr();
+    ABI *abi = process ? process->GetABI().get() : NULL;
+    if (abi)
+    {
+        UnwindPlanSP original_full_unwind_plan_sp = m_full_unwind_plan_sp;
+        UnwindPlanSP arch_default_unwind_plan_sp;
+        arch_default_unwind_plan_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
+        abi->CreateDefaultUnwindPlan(*arch_default_unwind_plan_sp);
+        if (arch_default_unwind_plan_sp)
+        {
+            UnwindPlan::RowSP active_row = arch_default_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset);
+        
+            if (active_row && active_row->GetCFARegister() != LLDB_INVALID_REGNUM)
+            {
+                FuncUnwindersSP func_unwinders_sp;
+                if (m_sym_ctx_valid && m_current_pc.IsValid() && m_current_pc.GetModule())
+                {
+                    func_unwinders_sp = m_current_pc.GetModule()->GetObjectFile()->GetUnwindTable().GetFuncUnwindersContainingAddress (m_current_pc, m_sym_ctx);
+                    if (func_unwinders_sp)
+                    {
+                        func_unwinders_sp->InvalidateNonCallSiteUnwindPlan (m_thread);
+                    }
+                }
+                m_registers.clear();
+                m_full_unwind_plan_sp = arch_default_unwind_plan_sp;
+                addr_t cfa_regval = LLDB_INVALID_ADDRESS;
+                if (ReadGPRValue (arch_default_unwind_plan_sp->GetRegisterKind(), active_row->GetCFARegister(), cfa_regval))
+                {
+                    m_cfa = cfa_regval + active_row->GetCFAOffset ();
+                }
+
+                UnwindLogMsg ("full unwind plan '%s' has been replaced by architecture default unwind plan '%s' for this function from now on.",
+                              original_full_unwind_plan_sp->GetSourceName().GetCString(), arch_default_unwind_plan_sp->GetSourceName().GetCString());
+            }
+        }
+    }
+}
+
+// Retrieve a general purpose register value for THIS frame, as saved by the NEXT frame, i.e. the frame that
+// this frame called.  e.g.
+//
+//  foo () { }
+//  bar () { foo (); }
+//  main () { bar (); }
+//
+//  stopped in foo() so
+//     frame 0 - foo
+//     frame 1 - bar
+//     frame 2 - main
+//  and this RegisterContext is for frame 1 (bar) - if we want to get the pc value for frame 1, we need to ask
+//  where frame 0 (the "next" frame) saved that and retrieve the value.
+
+bool
+RegisterContextLLDB::ReadGPRValue (int register_kind, uint32_t regnum, addr_t &value)
+{
+    if (!IsValid())
+        return false;
+
+    uint32_t lldb_regnum;
+    if (register_kind == eRegisterKindLLDB)
+    {
+        lldb_regnum = regnum;
+    }
+    else if (!m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (register_kind, regnum, eRegisterKindLLDB, lldb_regnum))
+    {
+        return false;
+    }
+
+    const RegisterInfo *reg_info = GetRegisterInfoAtIndex(lldb_regnum);
+    RegisterValue reg_value;
+    // if this is frame 0 (currently executing frame), get the requested reg contents from the actual thread registers
+    if (IsFrameZero ())
+    {
+        if (m_thread.GetRegisterContext()->ReadRegister (reg_info, reg_value))
+        {
+            value = reg_value.GetAsUInt64();
+            return true;
+        }
+        return false;
+    }
+
+    bool pc_register = false;
+    uint32_t generic_regnum;
+    if (register_kind == eRegisterKindGeneric && regnum == LLDB_REGNUM_GENERIC_PC)
+    {
+        pc_register = true;
+    }
+    else if (m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (register_kind, regnum, eRegisterKindGeneric, generic_regnum)
+             && generic_regnum == LLDB_REGNUM_GENERIC_PC)
+    {
+        pc_register = true;
+    }
+
+    lldb_private::UnwindLLDB::RegisterLocation regloc;
+    if (!m_parent_unwind.SearchForSavedLocationForRegister (lldb_regnum, regloc, m_frame_number - 1, pc_register))
+    {
+        return false;
+    }
+    if (ReadRegisterValueFromRegisterLocation (regloc, reg_info, reg_value))
+    {
+        value = reg_value.GetAsUInt64();
+        return true;
+    }
+    return false;
+}
+
+// Find the value of a register in THIS frame
+
+bool
+RegisterContextLLDB::ReadRegister (const RegisterInfo *reg_info, RegisterValue &value)
+{
+    if (!IsValid())
+        return false;
+
+    const uint32_t lldb_regnum = reg_info->kinds[eRegisterKindLLDB];
+    UnwindLogMsgVerbose ("looking for register saved location for reg %d", lldb_regnum);
+
+    // If this is the 0th frame, hand this over to the live register context
+    if (IsFrameZero ())
+    {
+        UnwindLogMsgVerbose ("passing along to the live register context for reg %d", lldb_regnum);
+        return m_thread.GetRegisterContext()->ReadRegister (reg_info, value);
+    }
+
+    lldb_private::UnwindLLDB::RegisterLocation regloc;
+    // Find out where the NEXT frame saved THIS frame's register contents
+    if (!m_parent_unwind.SearchForSavedLocationForRegister (lldb_regnum, regloc, m_frame_number - 1, false))
+        return false;
+
+    return ReadRegisterValueFromRegisterLocation (regloc, reg_info, value);
+}
+
+bool
+RegisterContextLLDB::WriteRegister (const RegisterInfo *reg_info, const RegisterValue &value)
+{
+    if (!IsValid())
+        return false;
+
+    const uint32_t lldb_regnum = reg_info->kinds[eRegisterKindLLDB];
+    UnwindLogMsgVerbose ("looking for register saved location for reg %d", lldb_regnum);
+
+    // If this is the 0th frame, hand this over to the live register context
+    if (IsFrameZero ())
+    {
+        UnwindLogMsgVerbose ("passing along to the live register context for reg %d", lldb_regnum);
+        return m_thread.GetRegisterContext()->WriteRegister (reg_info, value);
+    }
+
+    lldb_private::UnwindLLDB::RegisterLocation regloc;
+    // Find out where the NEXT frame saved THIS frame's register contents
+    if (!m_parent_unwind.SearchForSavedLocationForRegister (lldb_regnum, regloc, m_frame_number - 1, false))
+        return false;
+
+    return WriteRegisterValueToRegisterLocation (regloc, reg_info, value);
+}
+
+// Don't need to implement this one
+bool
+RegisterContextLLDB::ReadAllRegisterValues (lldb::DataBufferSP &data_sp)
+{
+    return false;
+}
+
+// Don't need to implement this one
+bool
+RegisterContextLLDB::WriteAllRegisterValues (const lldb::DataBufferSP& data_sp)
+{
+    return false;
+}
+
+// Retrieve the pc value for THIS from
+
+bool
+RegisterContextLLDB::GetCFA (addr_t& cfa)
+{
+    if (!IsValid())
+    {
+        return false;
+    }
+    if (m_cfa == LLDB_INVALID_ADDRESS)
+    {
+        return false;
+    }
+    cfa = m_cfa;
+    return true;
+}
+
+
+RegisterContextLLDB::SharedPtr
+RegisterContextLLDB::GetNextFrame () const
+{
+    RegisterContextLLDB::SharedPtr regctx;
+    if (m_frame_number == 0)
+      return regctx;
+    return m_parent_unwind.GetRegisterContextForFrameNum (m_frame_number - 1);
+}
+
+RegisterContextLLDB::SharedPtr
+RegisterContextLLDB::GetPrevFrame () const
+{
+    RegisterContextLLDB::SharedPtr regctx;
+    return m_parent_unwind.GetRegisterContextForFrameNum (m_frame_number + 1);
+}
+
+// Retrieve the address of the start of the function of THIS frame
+
+bool
+RegisterContextLLDB::GetStartPC (addr_t& start_pc)
+{
+    if (!IsValid())
+        return false;
+
+    if (!m_start_pc.IsValid())
+    {
+        return ReadPC (start_pc);
+    }
+    start_pc = m_start_pc.GetLoadAddress (CalculateTarget().get());
+    return true;
+}
+
+// Retrieve the current pc value for THIS frame, as saved by the NEXT frame.
+
+bool
+RegisterContextLLDB::ReadPC (addr_t& pc)
+{
+    if (!IsValid())
+        return false;
+
+    if (ReadGPRValue (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, pc))
+    {
+        // A pc value of 0 or 1 is impossible in the middle of the stack -- it indicates the end of a stack walk.
+        // On the currently executing frame (or such a frame interrupted asynchronously by sigtramp et al) this may
+        // occur if code has jumped through a NULL pointer -- we want to be able to unwind past that frame to help
+        // find the bug.
+
+        if (m_all_registers_available == false
+            && (pc == 0 || pc == 1))
+        {
+            return false;
+        }
+        else
+        {
+            return true;
+        }
+    }
+    else
+    {
+        return false;
+    }
+}
+
+
+void
+RegisterContextLLDB::UnwindLogMsg (const char *fmt, ...)
+{
+    Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
+    if (log)
+    {
+        va_list args;
+        va_start (args, fmt);
+
+        char *logmsg;
+        if (vasprintf (&logmsg, fmt, args) == -1 || logmsg == NULL)
+        {
+            if (logmsg)
+                free (logmsg);
+            va_end (args);
+            return;
+        }
+        va_end (args);
+
+        log->Printf ("%*sth%d/fr%u %s",
+                      m_frame_number < 100 ? m_frame_number : 100, "", m_thread.GetIndexID(), m_frame_number,
+                      logmsg);
+        free (logmsg);
+    }
+}
+
+void
+RegisterContextLLDB::UnwindLogMsgVerbose (const char *fmt, ...)
+{
+    Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
+    if (log && log->GetVerbose())
+    {
+        va_list args;
+        va_start (args, fmt);
+
+        char *logmsg;
+        if (vasprintf (&logmsg, fmt, args) == -1 || logmsg == NULL)
+        {
+            if (logmsg)
+                free (logmsg);
+            va_end (args);
+            return;
+        }
+        va_end (args);
+
+        log->Printf ("%*sth%d/fr%u %s",
+                      m_frame_number < 100 ? m_frame_number : 100, "", m_thread.GetIndexID(), m_frame_number,
+                      logmsg);
+        free (logmsg);
+    }
+}
+
diff --git a/source/Plugins/Process/Utility/RegisterContextLLDB.h b/source/Plugins/Process/Utility/RegisterContextLLDB.h
new file mode 100644
index 000000000000..dc6d8c61fa4a
--- /dev/null
+++ b/source/Plugins/Process/Utility/RegisterContextLLDB.h
@@ -0,0 +1,212 @@
+//===-- RegisterContextLLDB.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_RegisterContextLLDB_h_
+#define lldb_RegisterContextLLDB_h_
+
+#include <vector>
+
+#include "lldb/lldb-private.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Symbol/UnwindPlan.h"
+#include "lldb/Symbol/SymbolContext.h"
+#include "UnwindLLDB.h"
+
+namespace lldb_private {
+
+class UnwindLLDB;
+
+class RegisterContextLLDB : public lldb_private::RegisterContext
+{
+public:
+    typedef std::shared_ptr<RegisterContextLLDB> SharedPtr;
+
+    RegisterContextLLDB (lldb_private::Thread &thread,
+                         const SharedPtr& next_frame,
+                         lldb_private::SymbolContext& sym_ctx,
+                         uint32_t frame_number, lldb_private::UnwindLLDB& unwind_lldb);
+
+    ///
+    // pure virtual functions from the base class that we must implement
+    ///
+
+    virtual
+    ~RegisterContextLLDB () { }
+
+    virtual void
+    InvalidateAllRegisters ();
+
+    virtual size_t
+    GetRegisterCount ();
+
+    virtual const lldb_private::RegisterInfo *
+    GetRegisterInfoAtIndex (size_t reg);
+
+    virtual size_t
+    GetRegisterSetCount ();
+
+    virtual const lldb_private::RegisterSet *
+    GetRegisterSet (size_t reg_set);
+
+    virtual bool
+    ReadRegister (const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value);
+
+    virtual bool
+    WriteRegister (const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value);
+
+    virtual bool
+    ReadAllRegisterValues (lldb::DataBufferSP &data_sp);
+
+    virtual bool
+    WriteAllRegisterValues (const lldb::DataBufferSP &data_sp);
+
+    virtual uint32_t
+    ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num);
+
+    bool
+    IsValid () const;
+
+    bool
+    GetCFA (lldb::addr_t& cfa);
+
+    bool
+    GetStartPC (lldb::addr_t& start_pc);
+
+    bool
+    ReadPC (lldb::addr_t& start_pc);
+
+private:
+
+    enum FrameType
+    {
+        eNormalFrame,
+        eSigtrampFrame,
+        eDebuggerFrame,  // a debugger inferior function call frame; we get caller's registers from debugger
+        eSkipFrame,      // The unwind resulted in a bogus frame but may get back on track so we don't want to give up yet
+        eNotAValidFrame  // this frame is invalid for some reason - most likely it is past the top (end) of the stack
+    };
+
+    // UnwindLLDB needs to pass around references to RegisterLocations
+    friend class UnwindLLDB;
+
+    // Indicates whether this frame is frame zero -- the currently
+    // executing frame -- or not.
+    bool
+    IsFrameZero () const;
+
+    void
+    InitializeZerothFrame ();
+
+    void
+    InitializeNonZerothFrame();
+
+    SharedPtr
+    GetNextFrame () const;
+
+    SharedPtr
+    GetPrevFrame () const;
+
+    // A SkipFrame occurs when the unwind out of frame 0 didn't go right -- we've got one bogus frame at frame #1.
+    // There is a good chance we'll get back on track if we follow the frame pointer chain (or whatever is appropriate
+    // on this ABI) so we allow one invalid frame to be in the stack.  Ideally we'll mark this frame specially at some
+    // point and indicate to the user that the unwinder had a hiccup.  Often when this happens we will miss a frame of
+    // the program's actual stack in the unwind and we want to flag that for the user somehow.
+    bool
+    IsSkipFrame () const;
+
+    // Provide a location for where THIS function saved the CALLER's register value
+    // Or a frame "below" this one saved it, i.e. a function called by this one, preserved a register that this
+    // function didn't modify/use.
+    //
+    // The RegisterLocation type may be set to eRegisterNotAvailable -- this will happen for a volatile register
+    // being queried mid-stack.  Instead of floating frame 0's contents of that register up the stack (which may
+    // or may not be the value of that reg when the function was executing), we won't return any value.
+    //
+    // If a non-volatile register (a "preserved" register) is requested mid-stack and no frames "below" the requested
+    // stack have saved the register anywhere, it is safe to assume that frame 0's register values are still the same
+    // as the requesting frame's.
+    lldb_private::UnwindLLDB::RegisterSearchResult
+    SavedLocationForRegister (uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation &regloc);
+
+    bool
+    ReadRegisterValueFromRegisterLocation (lldb_private::UnwindLLDB::RegisterLocation regloc,
+                                           const lldb_private::RegisterInfo *reg_info,
+                                           lldb_private::RegisterValue &value);
+
+    bool
+    WriteRegisterValueToRegisterLocation (lldb_private::UnwindLLDB::RegisterLocation regloc,
+                                          const lldb_private::RegisterInfo *reg_info,
+                                          const lldb_private::RegisterValue &value);
+
+    void
+    InvalidateFullUnwindPlan ();
+
+    // Get the contents of a general purpose (address-size) register for this frame
+    // (usually retrieved from the next frame)
+    bool
+    ReadGPRValue (int register_kind, uint32_t regnum, lldb::addr_t &value);
+
+    lldb::UnwindPlanSP
+    GetFastUnwindPlanForFrame ();
+
+    lldb::UnwindPlanSP
+    GetFullUnwindPlanForFrame ();
+
+    void
+    UnwindLogMsg (const char *fmt, ...) __attribute__ ((format (printf, 2, 3)));
+
+    void
+    UnwindLogMsgVerbose (const char *fmt, ...) __attribute__ ((format (printf, 2, 3)));
+
+    lldb_private::Thread& m_thread;
+
+    ///
+    // The following tell us how to retrieve the CALLER's register values (ie the "previous" frame, aka the frame above)
+    // i.e. where THIS frame saved them
+    ///
+
+    lldb::UnwindPlanSP m_fast_unwind_plan_sp;  // may be NULL
+    lldb::UnwindPlanSP m_full_unwind_plan_sp;
+    bool m_all_registers_available;               // Can we retrieve all regs or just nonvolatile regs?
+    int m_frame_type;                             // enum FrameType
+
+    lldb::addr_t m_cfa;
+    lldb_private::Address m_start_pc;
+    lldb_private::Address m_current_pc;
+
+    int m_current_offset;                         // how far into the function we've executed; -1 if unknown
+                                                  // 0 if no instructions have been executed yet.
+
+    int m_current_offset_backed_up_one;           // how far into the function we've executed; -1 if unknown
+                                                  // 0 if no instructions have been executed yet.
+                                                  // On architectures where the return address on the stack points
+                                                  // to the instruction after the CALL, this value will have 1
+                                                  // subtracted from it.  Else a function that ends in a CALL will
+                                                  // have an offset pointing into the next function's address range.
+                                                  // m_current_pc has the actual address of the "current" pc.
+
+    lldb_private::SymbolContext& m_sym_ctx;
+    bool m_sym_ctx_valid;                         // if ResolveSymbolContextForAddress fails, don't try to use m_sym_ctx
+
+    uint32_t m_frame_number;                      // What stack frame this RegisterContext is
+
+    std::map<uint32_t, lldb_private::UnwindLLDB::RegisterLocation> m_registers; // where to find reg values for this frame
+
+    lldb_private::UnwindLLDB& m_parent_unwind;    // The UnwindLLDB that is creating this RegisterContextLLDB
+
+    //------------------------------------------------------------------
+    // For RegisterContextLLDB only
+    //------------------------------------------------------------------
+
+    DISALLOW_COPY_AND_ASSIGN (RegisterContextLLDB);
+};
+
+} // namespace lldb_private
+
+#endif  // lldb_RegisterContextLLDB_h_
diff --git a/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp b/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp
new file mode 100644
index 000000000000..2c3eee452488
--- /dev/null
+++ b/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp
@@ -0,0 +1,206 @@
+//===-- RegisterContextMacOSXFrameBackchain.cpp -----------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "RegisterContextMacOSXFrameBackchain.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/RegisterValue.h"
+#include "lldb/Core/Scalar.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Target/Thread.h"
+// Project includes
+#include "Utility/StringExtractorGDBRemote.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// RegisterContextMacOSXFrameBackchain constructor
+//----------------------------------------------------------------------
+RegisterContextMacOSXFrameBackchain::RegisterContextMacOSXFrameBackchain
+(
+    Thread &thread,
+    uint32_t concrete_frame_idx,
+    const UnwindMacOSXFrameBackchain::Cursor &cursor
+) :
+    RegisterContext (thread, concrete_frame_idx),
+    m_cursor (cursor),
+    m_cursor_is_valid (true)
+{
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+RegisterContextMacOSXFrameBackchain::~RegisterContextMacOSXFrameBackchain()
+{
+}
+
+void
+RegisterContextMacOSXFrameBackchain::InvalidateAllRegisters ()
+{
+    m_cursor_is_valid = false;
+}
+
+size_t
+RegisterContextMacOSXFrameBackchain::GetRegisterCount ()
+{
+    return m_thread.GetRegisterContext()->GetRegisterCount();
+}
+
+const RegisterInfo *
+RegisterContextMacOSXFrameBackchain::GetRegisterInfoAtIndex (size_t reg)
+{
+    return m_thread.GetRegisterContext()->GetRegisterInfoAtIndex(reg);
+}
+
+size_t
+RegisterContextMacOSXFrameBackchain::GetRegisterSetCount ()
+{
+    return m_thread.GetRegisterContext()->GetRegisterSetCount();
+}
+
+
+
+const RegisterSet *
+RegisterContextMacOSXFrameBackchain::GetRegisterSet (size_t reg_set)
+{
+    return m_thread.GetRegisterContext()->GetRegisterSet (reg_set);
+}
+
+
+
+bool
+RegisterContextMacOSXFrameBackchain::ReadRegister (const RegisterInfo *reg_info,
+                                                   RegisterValue &value)
+{
+    if (!m_cursor_is_valid)
+        return false;
+
+    uint64_t reg_value = LLDB_INVALID_ADDRESS;
+    
+    switch (reg_info->kinds[eRegisterKindGeneric])
+    {
+    case LLDB_REGNUM_GENERIC_PC:
+        if (m_cursor.pc == LLDB_INVALID_ADDRESS)
+            return false;
+        reg_value = m_cursor.pc;
+        break;
+    
+    case LLDB_REGNUM_GENERIC_FP:
+        if (m_cursor.fp == LLDB_INVALID_ADDRESS)
+            return false;
+        reg_value = m_cursor.fp;
+        break;
+    
+    default:
+        return false;    
+    }
+    
+    switch (reg_info->encoding)
+    {
+    case eEncodingInvalid:
+    case eEncodingVector:
+        break;
+
+    case eEncodingUint:
+    case eEncodingSint:
+        value.SetUInt(reg_value, reg_info->byte_size);
+        return true;
+
+    case eEncodingIEEE754:
+        switch (reg_info->byte_size)
+        {
+        case sizeof (float):
+            if (sizeof (float) == sizeof(uint32_t))
+            {
+                value.SetUInt32(reg_value, RegisterValue::eTypeFloat);
+                return true;
+            }
+            else if (sizeof (float) == sizeof(uint64_t))
+            {
+                value.SetUInt64(reg_value, RegisterValue::eTypeFloat);
+                return true;
+            }
+            break;
+
+        case sizeof (double):
+            if (sizeof (double) == sizeof(uint32_t))
+            {
+                value.SetUInt32(reg_value, RegisterValue::eTypeDouble);
+                return true;
+            }
+            else if (sizeof (double) == sizeof(uint64_t))
+            {
+                value.SetUInt64(reg_value, RegisterValue::eTypeDouble);
+                return true;
+            }
+            break;
+
+            // TOOD: need a better way to detect when "long double" types are 
+            // the same bytes size as "double"
+#if !defined(__arm__)
+        case sizeof (long double):
+            if (sizeof (long double) == sizeof(uint32_t))
+            {
+                value.SetUInt32(reg_value, RegisterValue::eTypeLongDouble);
+                return true;
+            }
+            else if (sizeof (long double) == sizeof(uint64_t))
+            {
+                value.SetUInt64(reg_value, RegisterValue::eTypeLongDouble);
+                return true;
+            }
+            break;
+#endif
+        }
+        break;
+    }
+    return false;
+}
+
+bool
+RegisterContextMacOSXFrameBackchain::WriteRegister (const RegisterInfo *reg_info,
+                                                    const RegisterValue &value)
+{
+    // Not supported yet. We could easily add support for this by remembering
+    // the address of each entry (it would need to be part of the cursor)
+    return false;
+}
+
+bool
+RegisterContextMacOSXFrameBackchain::ReadAllRegisterValues (lldb::DataBufferSP &data_sp)
+{
+    // libunwind frames can't handle this it doesn't always have all register
+    // values. This call should only be called on frame zero anyway so there
+    // shouldn't be any problem
+    return false;
+}
+
+bool
+RegisterContextMacOSXFrameBackchain::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp)
+{
+    // Since this class doesn't respond to "ReadAllRegisterValues()", it must
+    // not have been the one that saved all the register values. So we just let
+    // the thread's register context (the register context for frame zero) do
+    // the writing.
+    return m_thread.GetRegisterContext()->WriteAllRegisterValues(data_sp);
+}
+
+
+uint32_t
+RegisterContextMacOSXFrameBackchain::ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num)
+{
+    return m_thread.GetRegisterContext()->ConvertRegisterKindToRegisterNumber (kind, num);
+}
+
diff --git a/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.h b/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.h
new file mode 100644
index 000000000000..449e053e5ef1
--- /dev/null
+++ b/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.h
@@ -0,0 +1,77 @@
+//===-- RegisterContextMacOSXFrameBackchain.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_RegisterContextMacOSXFrameBackchain_h_
+#define lldb_RegisterContextMacOSXFrameBackchain_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Target/RegisterContext.h"
+
+#include "UnwindMacOSXFrameBackchain.h"
+
+class RegisterContextMacOSXFrameBackchain : public lldb_private::RegisterContext
+{
+public:
+    //------------------------------------------------------------------
+    // Constructors and Destructors
+    //------------------------------------------------------------------
+    RegisterContextMacOSXFrameBackchain (lldb_private::Thread &thread,
+                                         uint32_t concrete_frame_idx,
+                                         const UnwindMacOSXFrameBackchain::Cursor &cursor);
+
+    virtual
+    ~RegisterContextMacOSXFrameBackchain ();
+
+    //------------------------------------------------------------------
+    // Subclasses must override these functions
+    //------------------------------------------------------------------
+    virtual void
+    InvalidateAllRegisters ();
+
+    virtual size_t
+    GetRegisterCount ();
+
+    virtual const lldb_private::RegisterInfo *
+    GetRegisterInfoAtIndex (size_t reg);
+
+    virtual size_t
+    GetRegisterSetCount ();
+
+    virtual const lldb_private::RegisterSet *
+    GetRegisterSet (size_t reg_set);
+
+    virtual bool
+    ReadRegister (const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value);
+
+    virtual bool
+    WriteRegister (const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value);
+    
+    virtual bool
+    ReadAllRegisterValues (lldb::DataBufferSP &data_sp);
+
+    virtual bool
+    WriteAllRegisterValues (const lldb::DataBufferSP &data_sp);
+
+    virtual uint32_t
+    ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num);
+    
+private:
+    UnwindMacOSXFrameBackchain::Cursor m_cursor;
+    bool m_cursor_is_valid;
+    //------------------------------------------------------------------
+    // For RegisterContextMacOSXFrameBackchain only
+    //------------------------------------------------------------------
+    DISALLOW_COPY_AND_ASSIGN (RegisterContextMacOSXFrameBackchain);
+};
+
+#endif  // lldb_RegisterContextMacOSXFrameBackchain_h_
diff --git a/source/Plugins/Process/Utility/RegisterContextMach_arm.cpp b/source/Plugins/Process/Utility/RegisterContextMach_arm.cpp
new file mode 100644
index 000000000000..7ceb536272f4
--- /dev/null
+++ b/source/Plugins/Process/Utility/RegisterContextMach_arm.cpp
@@ -0,0 +1,87 @@
+//===-- RegisterContextMach_arm.cpp -----------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#if defined(__APPLE__)
+
+#include "RegisterContextMach_arm.h"
+
+// C Includes
+#include <mach/mach_types.h>
+#include <mach/thread_act.h>
+
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+RegisterContextMach_arm::RegisterContextMach_arm(Thread &thread, uint32_t concrete_frame_idx) :
+    RegisterContextDarwin_arm (thread, concrete_frame_idx)
+{
+}
+
+RegisterContextMach_arm::~RegisterContextMach_arm()
+{
+}
+
+int
+RegisterContextMach_arm::DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr)
+{
+    mach_msg_type_number_t count = GPRWordCount;
+    return ::thread_get_state(tid, flavor, (thread_state_t)&gpr, &count);
+}
+
+int
+RegisterContextMach_arm::DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu)
+{
+    mach_msg_type_number_t count = FPUWordCount;
+    return ::thread_get_state(tid, flavor, (thread_state_t)&fpu, &count);
+}
+
+int
+RegisterContextMach_arm::DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc)
+{
+    mach_msg_type_number_t count = EXCWordCount;
+    return ::thread_get_state(tid, flavor, (thread_state_t)&exc, &count);
+}
+
+int
+RegisterContextMach_arm::DoReadDBG (lldb::tid_t tid, int flavor, DBG &dbg)
+{
+    mach_msg_type_number_t count = DBGWordCount;
+    return ::thread_get_state(tid, flavor, (thread_state_t)&dbg, &count);
+}
+
+int
+RegisterContextMach_arm::DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr)
+{
+    return ::thread_set_state(tid, flavor, (thread_state_t)&gpr, GPRWordCount);
+}
+
+int
+RegisterContextMach_arm::DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu)
+{
+    return ::thread_set_state(tid, flavor, (thread_state_t)&fpu, FPUWordCount);
+}
+
+int
+RegisterContextMach_arm::DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc)
+{
+    return ::thread_set_state(tid, flavor, (thread_state_t)&exc, EXCWordCount);
+}
+
+int
+RegisterContextMach_arm::DoWriteDBG (lldb::tid_t tid, int flavor, const DBG &dbg)
+{
+    return ::thread_set_state(tid, flavor, (thread_state_t)&dbg, DBGWordCount);
+}
+
+#endif
diff --git a/source/Plugins/Process/Utility/RegisterContextMach_arm.h b/source/Plugins/Process/Utility/RegisterContextMach_arm.h
new file mode 100644
index 000000000000..e97a4bfff2b6
--- /dev/null
+++ b/source/Plugins/Process/Utility/RegisterContextMach_arm.h
@@ -0,0 +1,56 @@
+//===-- RegisterContextMach_arm.h -------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_RegisterContextMach_arm_h_
+#define liblldb_RegisterContextMach_arm_h_
+
+// C Includes
+
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "RegisterContextDarwin_arm.h"
+
+class RegisterContextMach_arm : public RegisterContextDarwin_arm
+{
+public:
+
+    RegisterContextMach_arm(lldb_private::Thread &thread, uint32_t concrete_frame_idx);
+
+    virtual
+    ~RegisterContextMach_arm();
+
+protected:
+
+    virtual int
+    DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr);
+    
+    int
+    DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu);
+    
+    int
+    DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc);
+    
+    int
+    DoReadDBG (lldb::tid_t tid, int flavor, DBG &dbg);
+    
+    int
+    DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr);
+    
+    int
+    DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu);
+    
+    int
+    DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc);
+    
+    int
+    DoWriteDBG (lldb::tid_t tid, int flavor, const DBG &dbg);
+};
+
+#endif  // liblldb_RegisterContextMach_arm_h_
diff --git a/source/Plugins/Process/Utility/RegisterContextMach_i386.cpp b/source/Plugins/Process/Utility/RegisterContextMach_i386.cpp
new file mode 100644
index 000000000000..3d6c9a6baca6
--- /dev/null
+++ b/source/Plugins/Process/Utility/RegisterContextMach_i386.cpp
@@ -0,0 +1,72 @@
+//===-- RegisterContextMach_i386.cpp ----------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#if defined(__APPLE__)
+
+// C Includes
+#include <mach/thread_act.h>
+
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "RegisterContextMach_i386.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+RegisterContextMach_i386::RegisterContextMach_i386(Thread &thread, uint32_t concrete_frame_idx) :
+    RegisterContextDarwin_i386 (thread, concrete_frame_idx)
+{
+}
+
+RegisterContextMach_i386::~RegisterContextMach_i386()
+{
+}
+
+int
+RegisterContextMach_i386::DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr)
+{
+    mach_msg_type_number_t count = GPRWordCount;
+    return ::thread_get_state(tid, flavor, (thread_state_t)&gpr, &count);
+}
+
+int
+RegisterContextMach_i386::DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu)
+{
+    mach_msg_type_number_t count = FPUWordCount;
+    return ::thread_get_state(tid, flavor, (thread_state_t)&fpu, &count);
+}
+
+int
+RegisterContextMach_i386::DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc)
+{
+    mach_msg_type_number_t count = EXCWordCount;
+    return ::thread_get_state(tid, flavor, (thread_state_t)&exc, &count);
+}
+
+int
+RegisterContextMach_i386::DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr)
+{
+    return ::thread_set_state(tid, flavor, (thread_state_t)&gpr, GPRWordCount);
+}
+
+int
+RegisterContextMach_i386::DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu)
+{
+    return ::thread_set_state(tid, flavor, (thread_state_t)&fpu, FPUWordCount);
+}
+
+int
+RegisterContextMach_i386::DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc)
+{
+    return ::thread_set_state(tid, flavor, (thread_state_t)&exc, EXCWordCount);
+}
+
+#endif
diff --git a/source/Plugins/Process/Utility/RegisterContextMach_i386.h b/source/Plugins/Process/Utility/RegisterContextMach_i386.h
new file mode 100644
index 000000000000..ad0f69d1c052
--- /dev/null
+++ b/source/Plugins/Process/Utility/RegisterContextMach_i386.h
@@ -0,0 +1,49 @@
+//===-- RegisterContextMach_i386.h ------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_RegisterContextMach_i386_h_
+#define liblldb_RegisterContextMach_i386_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "RegisterContextDarwin_i386.h"
+
+class RegisterContextMach_i386 : public RegisterContextDarwin_i386
+{
+public:
+    
+    RegisterContextMach_i386(lldb_private::Thread &thread, uint32_t concrete_frame_idx);
+    
+    virtual
+    ~RegisterContextMach_i386();
+    
+protected:
+    
+    virtual int
+    DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr);
+    
+    int
+    DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu);
+    
+    int
+    DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc);
+    
+    int
+    DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr);
+    
+    int
+    DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu);
+    
+    int
+    DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc);
+};
+
+#endif  // liblldb_RegisterContextMach_i386_h_
diff --git a/source/Plugins/Process/Utility/RegisterContextMach_x86_64.cpp b/source/Plugins/Process/Utility/RegisterContextMach_x86_64.cpp
new file mode 100644
index 000000000000..f03685e1313f
--- /dev/null
+++ b/source/Plugins/Process/Utility/RegisterContextMach_x86_64.cpp
@@ -0,0 +1,72 @@
+//===-- RegisterContextMach_x86_64.cpp --------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#if defined(__APPLE__)
+
+// C Includes
+#include <mach/thread_act.h>
+
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "RegisterContextMach_x86_64.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+RegisterContextMach_x86_64::RegisterContextMach_x86_64(Thread &thread, uint32_t concrete_frame_idx) :
+    RegisterContextDarwin_x86_64 (thread, concrete_frame_idx)
+{
+}
+
+RegisterContextMach_x86_64::~RegisterContextMach_x86_64()
+{
+}
+
+int
+RegisterContextMach_x86_64::DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr)
+{
+    mach_msg_type_number_t count = GPRWordCount;
+    return ::thread_get_state(tid, flavor, (thread_state_t)&gpr, &count);
+}
+
+int
+RegisterContextMach_x86_64::DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu)
+{
+    mach_msg_type_number_t count = FPUWordCount;
+    return ::thread_get_state(tid, flavor, (thread_state_t)&fpu, &count);
+}
+
+int
+RegisterContextMach_x86_64::DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc)
+{
+    mach_msg_type_number_t count = EXCWordCount;
+    return ::thread_get_state(tid, flavor, (thread_state_t)&exc, &count);
+}
+
+int
+RegisterContextMach_x86_64::DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr)
+{
+    return ::thread_set_state(tid, flavor, (thread_state_t)&gpr, GPRWordCount);
+}
+
+int
+RegisterContextMach_x86_64::DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu)
+{
+    return ::thread_set_state(tid, flavor, (thread_state_t)&fpu, FPUWordCount);
+}
+
+int
+RegisterContextMach_x86_64::DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc)
+{
+    return ::thread_set_state(tid, flavor, (thread_state_t)&exc, EXCWordCount);
+}
+
+#endif
diff --git a/source/Plugins/Process/Utility/RegisterContextMach_x86_64.h b/source/Plugins/Process/Utility/RegisterContextMach_x86_64.h
new file mode 100644
index 000000000000..9e6dfa395500
--- /dev/null
+++ b/source/Plugins/Process/Utility/RegisterContextMach_x86_64.h
@@ -0,0 +1,49 @@
+//===-- RegisterContextMach_x86_64.h ------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_RegisterContextMach_x86_64_h_
+#define liblldb_RegisterContextMach_x86_64_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "RegisterContextDarwin_x86_64.h"
+
+class RegisterContextMach_x86_64 : public RegisterContextDarwin_x86_64
+{
+public:
+    
+    RegisterContextMach_x86_64(lldb_private::Thread &thread, uint32_t concrete_frame_idx);
+    
+    virtual
+    ~RegisterContextMach_x86_64();
+    
+protected:
+    
+    virtual int
+    DoReadGPR (lldb::tid_t tid, int flavor, GPR &gpr);
+    
+    int
+    DoReadFPU (lldb::tid_t tid, int flavor, FPU &fpu);
+    
+    int
+    DoReadEXC (lldb::tid_t tid, int flavor, EXC &exc);
+    
+    int
+    DoWriteGPR (lldb::tid_t tid, int flavor, const GPR &gpr);
+    
+    int
+    DoWriteFPU (lldb::tid_t tid, int flavor, const FPU &fpu);
+    
+    int
+    DoWriteEXC (lldb::tid_t tid, int flavor, const EXC &exc);
+};
+
+#endif  // liblldb_RegisterContextMach_x86_64_h_
diff --git a/source/Plugins/Process/Utility/RegisterContextMemory.cpp b/source/Plugins/Process/Utility/RegisterContextMemory.cpp
new file mode 100644
index 000000000000..8c33a6814acc
--- /dev/null
+++ b/source/Plugins/Process/Utility/RegisterContextMemory.cpp
@@ -0,0 +1,174 @@
+//===-- RegisterContextMemory.cpp -------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "RegisterContextMemory.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "DynamicRegisterInfo.h"
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/RegisterValue.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Thread.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// RegisterContextMemory constructor
+//----------------------------------------------------------------------
+RegisterContextMemory::RegisterContextMemory
+(
+    Thread &thread,
+    uint32_t concrete_frame_idx,
+    DynamicRegisterInfo &reg_infos,
+    addr_t reg_data_addr
+) :
+    RegisterContext (thread, concrete_frame_idx),
+    m_reg_infos (reg_infos),
+    m_reg_valid (),
+    m_reg_data (),
+    m_reg_data_addr (reg_data_addr)
+{
+    // Resize our vector of bools to contain one bool for every register.
+    // We will use these boolean values to know when a register value
+    // is valid in m_reg_data.
+    const size_t num_regs = reg_infos.GetNumRegisters();
+    assert (num_regs > 0);
+    m_reg_valid.resize (num_regs);
+
+    // Make a heap based buffer that is big enough to store all registers
+    DataBufferSP reg_data_sp(new DataBufferHeap (reg_infos.GetRegisterDataByteSize(), 0));
+    m_reg_data.SetData (reg_data_sp);
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+RegisterContextMemory::~RegisterContextMemory()
+{
+}
+
+void
+RegisterContextMemory::InvalidateAllRegisters ()
+{
+    if (m_reg_data_addr != LLDB_INVALID_ADDRESS)
+        SetAllRegisterValid (false);
+}
+
+void
+RegisterContextMemory::SetAllRegisterValid (bool b)
+{
+    std::vector<bool>::iterator pos, end = m_reg_valid.end();
+    for (pos = m_reg_valid.begin(); pos != end; ++pos)
+        *pos = b;
+}
+
+size_t
+RegisterContextMemory::GetRegisterCount ()
+{
+    return m_reg_infos.GetNumRegisters ();
+}
+
+const RegisterInfo *
+RegisterContextMemory::GetRegisterInfoAtIndex (size_t reg)
+{
+    return m_reg_infos.GetRegisterInfoAtIndex (reg);
+}
+
+size_t
+RegisterContextMemory::GetRegisterSetCount ()
+{
+    return m_reg_infos.GetNumRegisterSets ();
+}
+
+const RegisterSet *
+RegisterContextMemory::GetRegisterSet (size_t reg_set)
+{
+    return m_reg_infos.GetRegisterSet (reg_set);
+}
+
+uint32_t
+RegisterContextMemory::ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num)
+{
+    return m_reg_infos.ConvertRegisterKindToRegisterNumber (kind, num);
+}
+
+bool
+RegisterContextMemory::ReadRegister (const RegisterInfo *reg_info, RegisterValue &reg_value)
+{
+    const uint32_t reg_num = reg_info->kinds[eRegisterKindLLDB];
+    if (!m_reg_valid[reg_num])
+    {                         
+        if (!ReadAllRegisterValues(m_reg_data.GetSharedDataBuffer ()))
+            return false;
+    }
+    const bool partial_data_ok = false;
+    return reg_value.SetValueFromData(reg_info, m_reg_data, reg_info->byte_offset, partial_data_ok).Success();
+}
+
+bool
+RegisterContextMemory::WriteRegister (const RegisterInfo *reg_info, const RegisterValue &reg_value)
+{
+    if (m_reg_data_addr != LLDB_INVALID_ADDRESS)
+    {
+        const uint32_t reg_num = reg_info->kinds[eRegisterKindLLDB];
+        addr_t reg_addr = m_reg_data_addr + reg_info->byte_offset;
+        Error error (WriteRegisterValueToMemory(reg_info, reg_addr, reg_info->byte_size, reg_value));
+        m_reg_valid[reg_num] = false;
+        return error.Success();
+    }
+    return false;
+}
+
+bool
+RegisterContextMemory::ReadAllRegisterValues (DataBufferSP &data_sp)
+{
+    if (m_reg_data_addr != LLDB_INVALID_ADDRESS)
+    {
+        ProcessSP process_sp (CalculateProcess());
+        if (process_sp)
+        {
+            Error error;
+            if (process_sp->ReadMemory(m_reg_data_addr, data_sp->GetBytes(), data_sp->GetByteSize(), error) == data_sp->GetByteSize())
+            {
+                SetAllRegisterValid (true);
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+bool
+RegisterContextMemory::WriteAllRegisterValues (const DataBufferSP &data_sp)
+{
+    if (m_reg_data_addr != LLDB_INVALID_ADDRESS)
+    {
+        ProcessSP process_sp (CalculateProcess());
+        if (process_sp)
+        {
+            Error error;
+            SetAllRegisterValid (false);
+            if (process_sp->WriteMemory(m_reg_data_addr, data_sp->GetBytes(), data_sp->GetByteSize(), error) == data_sp->GetByteSize())
+                return true;
+        }
+    }
+    return false;
+}
+
+void
+RegisterContextMemory::SetAllRegisterData  (const lldb::DataBufferSP &data_sp)
+{
+    m_reg_data.SetData(data_sp);
+    SetAllRegisterValid (true);    
+}
diff --git a/source/Plugins/Process/Utility/RegisterContextMemory.h b/source/Plugins/Process/Utility/RegisterContextMemory.h
new file mode 100644
index 000000000000..8bba52c627f3
--- /dev/null
+++ b/source/Plugins/Process/Utility/RegisterContextMemory.h
@@ -0,0 +1,102 @@
+//===-- RegisterContextMemory.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_RegisterContextMemory_h_
+#define lldb_RegisterContextMemory_h_
+
+// C Includes
+// C++ Includes
+#include <vector>
+
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Target/RegisterContext.h"
+
+class DynamicRegisterInfo;
+
+class RegisterContextMemory : public lldb_private::RegisterContext
+{
+public:
+    //------------------------------------------------------------------
+    // Constructors and Destructors
+    //------------------------------------------------------------------
+    RegisterContextMemory (lldb_private::Thread &thread,
+                            uint32_t concrete_frame_idx,
+                            DynamicRegisterInfo &reg_info,
+                            lldb::addr_t reg_data_addr);
+
+    virtual
+    ~RegisterContextMemory ();
+
+    //------------------------------------------------------------------
+    // Subclasses must override these functions
+    //------------------------------------------------------------------
+    virtual void
+    InvalidateAllRegisters ();
+
+    virtual size_t
+    GetRegisterCount ();
+
+    virtual const lldb_private::RegisterInfo *
+    GetRegisterInfoAtIndex (size_t reg);
+
+    virtual size_t
+    GetRegisterSetCount ();
+
+    virtual const lldb_private::RegisterSet *
+    GetRegisterSet (size_t reg_set);
+
+    virtual uint32_t
+    ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num);
+
+    
+    //------------------------------------------------------------------
+    // If all of the thread register are in a contiguous buffer in 
+    // memory, then the default ReadRegister/WriteRegister and
+    // ReadAllRegisterValues/WriteAllRegisterValues will work. If thread
+    // registers are not contiguous, clients will want to subclass this
+    // class and modify the read/write functions as needed.
+    //------------------------------------------------------------------
+
+    virtual bool
+    ReadRegister (const lldb_private::RegisterInfo *reg_info, 
+                  lldb_private::RegisterValue &reg_value);
+    
+    virtual bool
+    WriteRegister (const lldb_private::RegisterInfo *reg_info, 
+                   const lldb_private::RegisterValue &reg_value);
+    
+    virtual bool
+    ReadAllRegisterValues (lldb::DataBufferSP &data_sp);
+    
+    virtual bool
+    WriteAllRegisterValues (const lldb::DataBufferSP &data_sp);
+
+    void
+    SetAllRegisterData  (const lldb::DataBufferSP &data_sp);
+protected:
+    
+    void
+    SetAllRegisterValid (bool b);
+
+    DynamicRegisterInfo &m_reg_infos;
+    std::vector<bool> m_reg_valid;
+    lldb_private::DataExtractor m_reg_data;
+    lldb::addr_t m_reg_data_addr; // If this is valid, then we have a register context that is stored in memmory
+
+private:
+    //------------------------------------------------------------------
+    // For RegisterContextMemory only
+    //------------------------------------------------------------------
+    DISALLOW_COPY_AND_ASSIGN (RegisterContextMemory);
+};
+
+#endif  // lldb_RegisterContextMemory_h_
diff --git a/source/Plugins/Process/Utility/RegisterContextThreadMemory.cpp b/source/Plugins/Process/Utility/RegisterContextThreadMemory.cpp
new file mode 100644
index 000000000000..d35a5d095705
--- /dev/null
+++ b/source/Plugins/Process/Utility/RegisterContextThreadMemory.cpp
@@ -0,0 +1,261 @@
+//===-- RegisterContextThreadMemory.cpp -------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/lldb-private.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Target/OperatingSystem.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Thread.h"
+
+#include "RegisterContextThreadMemory.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+RegisterContextThreadMemory::RegisterContextThreadMemory (Thread &thread,
+                                                          lldb::addr_t register_data_addr) :
+    RegisterContext (thread, 0),
+    m_thread_wp (thread.shared_from_this()),
+    m_reg_ctx_sp (),
+    m_register_data_addr (register_data_addr),
+    m_stop_id(0)
+{
+}
+
+RegisterContextThreadMemory::~RegisterContextThreadMemory()
+{
+}
+
+void
+RegisterContextThreadMemory::UpdateRegisterContext ()
+{
+    ThreadSP thread_sp (m_thread_wp.lock());
+    if (thread_sp)
+    {
+        ProcessSP process_sp (thread_sp->GetProcess());
+
+        if (process_sp)
+        {
+            const uint32_t stop_id = process_sp->GetModID().GetStopID();
+            if (m_stop_id != stop_id)
+            {
+                m_stop_id = stop_id;
+                m_reg_ctx_sp.reset();
+            }
+            if (!m_reg_ctx_sp)
+            {
+                ThreadSP backing_thread_sp (thread_sp->GetBackingThread());
+                if (backing_thread_sp)
+                {
+                    m_reg_ctx_sp = backing_thread_sp->GetRegisterContext();
+                }
+                else
+                {
+                    OperatingSystem *os = process_sp->GetOperatingSystem ();
+                    if (os->IsOperatingSystemPluginThread (thread_sp))
+                        m_reg_ctx_sp = os->CreateRegisterContextForThread (thread_sp.get(), LLDB_INVALID_ADDRESS);
+                }                
+            }
+        }
+        else
+        {
+            m_reg_ctx_sp.reset();
+        }
+    }
+    else
+    {
+        m_reg_ctx_sp.reset();
+    }
+}
+
+//------------------------------------------------------------------
+// Subclasses must override these functions
+//------------------------------------------------------------------
+void
+RegisterContextThreadMemory::InvalidateAllRegisters ()
+{
+    UpdateRegisterContext ();
+    if (m_reg_ctx_sp)
+        m_reg_ctx_sp->InvalidateAllRegisters();
+}
+
+size_t
+RegisterContextThreadMemory::GetRegisterCount ()
+{
+    UpdateRegisterContext ();
+    if (m_reg_ctx_sp)
+        return m_reg_ctx_sp->GetRegisterCount();
+    return 0;
+}
+
+const RegisterInfo *
+RegisterContextThreadMemory::GetRegisterInfoAtIndex (size_t reg)
+{
+    UpdateRegisterContext ();
+    if (m_reg_ctx_sp)
+        return m_reg_ctx_sp->GetRegisterInfoAtIndex(reg);
+    return NULL;
+}
+
+size_t
+RegisterContextThreadMemory::GetRegisterSetCount ()
+{
+    UpdateRegisterContext ();
+    if (m_reg_ctx_sp)
+        return m_reg_ctx_sp->GetRegisterSetCount();
+    return 0;
+}
+
+const RegisterSet *
+RegisterContextThreadMemory::GetRegisterSet (size_t reg_set)
+{
+    UpdateRegisterContext ();
+    if (m_reg_ctx_sp)
+        return m_reg_ctx_sp->GetRegisterSet(reg_set);
+    return NULL;
+}
+
+bool
+RegisterContextThreadMemory::ReadRegister (const RegisterInfo *reg_info, RegisterValue &reg_value)
+{
+    UpdateRegisterContext ();
+    if (m_reg_ctx_sp)
+        return m_reg_ctx_sp->ReadRegister(reg_info, reg_value);
+    return false;
+}
+
+bool
+RegisterContextThreadMemory::WriteRegister (const RegisterInfo *reg_info, const RegisterValue &reg_value)
+{
+    UpdateRegisterContext ();
+    if (m_reg_ctx_sp)
+        return m_reg_ctx_sp->WriteRegister (reg_info, reg_value);
+    return false;
+}
+
+bool
+RegisterContextThreadMemory::ReadAllRegisterValues (lldb::DataBufferSP &data_sp)
+{
+    UpdateRegisterContext ();
+    if (m_reg_ctx_sp)
+        return m_reg_ctx_sp->ReadAllRegisterValues(data_sp);
+    return false;
+}
+
+bool
+RegisterContextThreadMemory::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp)
+{
+    UpdateRegisterContext ();
+    if (m_reg_ctx_sp)
+        return m_reg_ctx_sp->WriteAllRegisterValues (data_sp);
+    return false;
+}
+
+bool
+RegisterContextThreadMemory::CopyFromRegisterContext (lldb::RegisterContextSP reg_ctx_sp)
+{
+    UpdateRegisterContext ();
+    if (m_reg_ctx_sp)
+        return m_reg_ctx_sp->CopyFromRegisterContext(reg_ctx_sp);
+    return false;
+}
+
+uint32_t
+RegisterContextThreadMemory::ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num)
+{
+    UpdateRegisterContext ();
+    if (m_reg_ctx_sp)
+        return m_reg_ctx_sp->ConvertRegisterKindToRegisterNumber(kind, num);
+    return false;
+}
+
+uint32_t
+RegisterContextThreadMemory::NumSupportedHardwareBreakpoints ()
+{
+    UpdateRegisterContext ();
+    if (m_reg_ctx_sp)
+        return m_reg_ctx_sp->NumSupportedHardwareBreakpoints();
+    return false;
+}
+
+uint32_t
+RegisterContextThreadMemory::SetHardwareBreakpoint (lldb::addr_t addr, size_t size)
+{
+    UpdateRegisterContext ();
+    if (m_reg_ctx_sp)
+        return m_reg_ctx_sp->SetHardwareBreakpoint(addr, size);
+    return 0;
+}
+
+bool
+RegisterContextThreadMemory::ClearHardwareBreakpoint (uint32_t hw_idx)
+{
+    UpdateRegisterContext ();
+    if (m_reg_ctx_sp)
+        return m_reg_ctx_sp->ClearHardwareBreakpoint (hw_idx);
+    return false;
+}
+
+uint32_t
+RegisterContextThreadMemory::NumSupportedHardwareWatchpoints ()
+{
+    UpdateRegisterContext ();
+    if (m_reg_ctx_sp)
+        return m_reg_ctx_sp->NumSupportedHardwareWatchpoints();
+    return 0;
+}
+
+uint32_t
+RegisterContextThreadMemory::SetHardwareWatchpoint (lldb::addr_t addr, size_t size, bool read, bool write)
+{
+    UpdateRegisterContext ();
+    if (m_reg_ctx_sp)
+        return m_reg_ctx_sp->SetHardwareWatchpoint(addr, size, read, write);
+    return 0;
+}
+
+bool
+RegisterContextThreadMemory::ClearHardwareWatchpoint (uint32_t hw_index)
+{
+    UpdateRegisterContext ();
+    if (m_reg_ctx_sp)
+        return m_reg_ctx_sp->ClearHardwareWatchpoint(hw_index);
+    return false;
+}
+
+bool
+RegisterContextThreadMemory::HardwareSingleStep (bool enable)
+{
+    UpdateRegisterContext ();
+    if (m_reg_ctx_sp)
+        return m_reg_ctx_sp->HardwareSingleStep(enable);
+    return false;
+}
+
+Error
+RegisterContextThreadMemory::ReadRegisterValueFromMemory (const lldb_private::RegisterInfo *reg_info, lldb::addr_t src_addr, uint32_t src_len, RegisterValue &reg_value)
+{
+    UpdateRegisterContext ();
+    if (m_reg_ctx_sp)
+        return m_reg_ctx_sp->ReadRegisterValueFromMemory (reg_info, src_addr, src_len, reg_value);
+    Error error;
+    error.SetErrorString("invalid register context");
+    return error;
+}
+
+Error
+RegisterContextThreadMemory::WriteRegisterValueToMemory (const lldb_private::RegisterInfo *reg_info, lldb::addr_t dst_addr, uint32_t dst_len, const RegisterValue &reg_value)
+{
+    UpdateRegisterContext ();
+    if (m_reg_ctx_sp)
+        return m_reg_ctx_sp->WriteRegisterValueToMemory (reg_info, dst_addr, dst_len, reg_value);
+    Error error;
+    error.SetErrorString("invalid register context");
+    return error;
+}
diff --git a/source/Plugins/Process/Utility/RegisterContextThreadMemory.h b/source/Plugins/Process/Utility/RegisterContextThreadMemory.h
new file mode 100644
index 000000000000..8d7a4b622fe8
--- /dev/null
+++ b/source/Plugins/Process/Utility/RegisterContextThreadMemory.h
@@ -0,0 +1,114 @@
+//===-- RegisterContextThreadMemory.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_RegisterContextThreadMemory_h_
+#define lldb_RegisterContextThreadMemory_h_
+
+#include <vector>
+
+#include "lldb/lldb-private.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Symbol/SymbolContext.h"
+
+namespace lldb_private {
+    
+class RegisterContextThreadMemory : public lldb_private::RegisterContext
+{
+public:
+    RegisterContextThreadMemory (Thread &thread,
+                                 lldb::addr_t register_data_addr);
+    
+    virtual ~RegisterContextThreadMemory();
+    //------------------------------------------------------------------
+    // Subclasses must override these functions
+    //------------------------------------------------------------------
+    virtual void
+    InvalidateAllRegisters ();
+    
+    virtual size_t
+    GetRegisterCount ();
+    
+    virtual const RegisterInfo *
+    GetRegisterInfoAtIndex (size_t reg);
+    
+    virtual size_t
+    GetRegisterSetCount ();
+    
+    virtual const RegisterSet *
+    GetRegisterSet (size_t reg_set);
+    
+    virtual bool
+    ReadRegister (const RegisterInfo *reg_info, RegisterValue &reg_value);
+    
+    virtual bool
+    WriteRegister (const RegisterInfo *reg_info, const RegisterValue &reg_value);
+    
+    // These two functions are used to implement "push" and "pop" of register states.  They are used primarily
+    // for expression evaluation, where we need to push a new state (storing the old one in data_sp) and then
+    // restoring the original state by passing the data_sp we got from ReadAllRegisters to WriteAllRegisterValues.
+    // ReadAllRegisters will do what is necessary to return a coherent set of register values for this thread, which
+    // may mean e.g. interrupting a thread that is sitting in a kernel trap.  That is a somewhat disruptive operation,
+    // so these API's should only be used when this behavior is needed.
+    
+    virtual bool
+    ReadAllRegisterValues (lldb::DataBufferSP &data_sp);
+    
+    virtual bool
+    WriteAllRegisterValues (const lldb::DataBufferSP &data_sp);
+    
+    bool
+    CopyFromRegisterContext (lldb::RegisterContextSP context);
+    
+    virtual uint32_t
+    ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num);
+    
+    //------------------------------------------------------------------
+    // Subclasses can override these functions if desired
+    //------------------------------------------------------------------
+    virtual uint32_t
+    NumSupportedHardwareBreakpoints ();
+    
+    virtual uint32_t
+    SetHardwareBreakpoint (lldb::addr_t addr, size_t size);
+    
+    virtual bool
+    ClearHardwareBreakpoint (uint32_t hw_idx);
+    
+    virtual uint32_t
+    NumSupportedHardwareWatchpoints ();
+    
+    virtual uint32_t
+    SetHardwareWatchpoint (lldb::addr_t addr, size_t size, bool read, bool write);
+    
+    virtual bool
+    ClearHardwareWatchpoint (uint32_t hw_index);
+    
+    virtual bool
+    HardwareSingleStep (bool enable);
+    
+    virtual Error
+    ReadRegisterValueFromMemory (const lldb_private::RegisterInfo *reg_info, lldb::addr_t src_addr, uint32_t src_len, RegisterValue &reg_value);
+    
+    virtual Error
+    WriteRegisterValueToMemory (const lldb_private::RegisterInfo *reg_info, lldb::addr_t dst_addr, uint32_t dst_len, const RegisterValue &reg_value);
+    
+protected:
+    void
+    UpdateRegisterContext ();
+    
+    lldb::ThreadWP m_thread_wp;
+    lldb::RegisterContextSP m_reg_ctx_sp;
+    lldb::addr_t m_register_data_addr;
+    uint32_t m_stop_id;
+private:
+    DISALLOW_COPY_AND_ASSIGN (RegisterContextThreadMemory);
+};
+} // namespace lldb_private
+
+#endif  // lldb_RegisterContextThreadMemory_h_
diff --git a/source/Plugins/Process/Utility/StopInfoMachException.cpp b/source/Plugins/Process/Utility/StopInfoMachException.cpp
new file mode 100644
index 000000000000..51d2052e1931
--- /dev/null
+++ b/source/Plugins/Process/Utility/StopInfoMachException.cpp
@@ -0,0 +1,482 @@
+//===-- StopInfoMachException.cpp -------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "StopInfoMachException.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Breakpoint/Watchpoint.h"
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Symbol/Symbol.h"
+#include "lldb/Target/DynamicLoader.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/ThreadPlan.h"
+#include "lldb/Target/UnixSignals.h"
+
+using namespace lldb;
+using namespace lldb_private;
+    
+const char *
+StopInfoMachException::GetDescription ()
+{
+    if (m_description.empty() && m_value != 0)
+    {
+        ExecutionContext exe_ctx (m_thread_wp.lock());
+        Target *target = exe_ctx.GetTargetPtr();
+        const llvm::Triple::ArchType cpu = target ? target->GetArchitecture().GetMachine() : llvm::Triple::UnknownArch;
+
+        const char *exc_desc = NULL;
+        const char *code_label = "code";
+        const char *code_desc = NULL;
+        const char *subcode_label = "subcode";
+        const char *subcode_desc = NULL;
+        switch (m_value)
+        {
+        case 1: // EXC_BAD_ACCESS
+            exc_desc = "EXC_BAD_ACCESS";
+            subcode_label = "address";
+            switch (cpu)
+            {
+            case llvm::Triple::x86:
+            case llvm::Triple::x86_64:
+                switch (m_exc_code)
+                {
+                case 0xd: code_desc = "EXC_I386_GPFLT"; m_exc_data_count = 1; break;
+                }
+                break;
+            case llvm::Triple::arm:
+                switch (m_exc_code)
+                {
+                case 0x101: code_desc = "EXC_ARM_DA_ALIGN"; break;
+                case 0x102: code_desc = "EXC_ARM_DA_DEBUG"; break;
+                }
+                break;
+
+            case llvm::Triple::ppc:
+            case llvm::Triple::ppc64:
+                switch (m_exc_code)
+                {
+                case 0x101: code_desc = "EXC_PPC_VM_PROT_READ"; break;
+                case 0x102: code_desc = "EXC_PPC_BADSPACE";     break;
+                case 0x103: code_desc = "EXC_PPC_UNALIGNED";    break;
+                }
+                break;
+
+            default:
+                break;
+            }
+            break;
+
+        case 2: // EXC_BAD_INSTRUCTION
+            exc_desc = "EXC_BAD_INSTRUCTION";
+            switch (cpu)
+            {
+            case llvm::Triple::x86:
+            case llvm::Triple::x86_64:
+                if (m_exc_code == 1)
+                    code_desc = "EXC_I386_INVOP";
+                break;
+
+            case llvm::Triple::ppc:
+            case llvm::Triple::ppc64:
+                switch (m_exc_code)
+                {
+                case 1: code_desc = "EXC_PPC_INVALID_SYSCALL"; break; 
+                case 2: code_desc = "EXC_PPC_UNIPL_INST"; break; 
+                case 3: code_desc = "EXC_PPC_PRIVINST"; break; 
+                case 4: code_desc = "EXC_PPC_PRIVREG"; break; 
+                case 5: code_desc = "EXC_PPC_TRACE"; break; 
+                case 6: code_desc = "EXC_PPC_PERFMON"; break; 
+                }
+                break;
+
+            case llvm::Triple::arm:
+                if (m_exc_code == 1)
+                    code_desc = "EXC_ARM_UNDEFINED";
+                break;
+
+            default:
+                break;
+            }
+            break;
+
+        case 3: // EXC_ARITHMETIC
+            exc_desc = "EXC_ARITHMETIC";
+            switch (cpu)
+            {
+            case llvm::Triple::x86:
+            case llvm::Triple::x86_64:
+                switch (m_exc_code)
+                {
+                case 1: code_desc = "EXC_I386_DIV"; break;
+                case 2: code_desc = "EXC_I386_INTO"; break;
+                case 3: code_desc = "EXC_I386_NOEXT"; break;
+                case 4: code_desc = "EXC_I386_EXTOVR"; break;
+                case 5: code_desc = "EXC_I386_EXTERR"; break;
+                case 6: code_desc = "EXC_I386_EMERR"; break;
+                case 7: code_desc = "EXC_I386_BOUND"; break;
+                case 8: code_desc = "EXC_I386_SSEEXTERR"; break;
+                }
+                break;
+
+            case llvm::Triple::ppc:
+            case llvm::Triple::ppc64:
+                switch (m_exc_code)
+                {
+                case 1: code_desc = "EXC_PPC_OVERFLOW"; break;
+                case 2: code_desc = "EXC_PPC_ZERO_DIVIDE"; break;
+                case 3: code_desc = "EXC_PPC_FLT_INEXACT"; break;
+                case 4: code_desc = "EXC_PPC_FLT_ZERO_DIVIDE"; break;
+                case 5: code_desc = "EXC_PPC_FLT_UNDERFLOW"; break;
+                case 6: code_desc = "EXC_PPC_FLT_OVERFLOW"; break;
+                case 7: code_desc = "EXC_PPC_FLT_NOT_A_NUMBER"; break;
+                }
+                break;
+
+            default:
+                break;
+            }
+            break;
+
+        case 4: // EXC_EMULATION
+            exc_desc = "EXC_EMULATION";
+            break;
+
+
+        case 5: // EXC_SOFTWARE
+            exc_desc = "EXC_SOFTWARE";
+            if (m_exc_code == 0x10003)
+            {
+                subcode_desc = "EXC_SOFT_SIGNAL";
+                subcode_label = "signo";
+            }
+            break;
+        
+        case 6: // EXC_BREAKPOINT
+            {
+                exc_desc = "EXC_BREAKPOINT";
+                switch (cpu)
+                {
+                case llvm::Triple::x86:
+                case llvm::Triple::x86_64:
+                    switch (m_exc_code)
+                    {
+                    case 1: code_desc = "EXC_I386_SGL"; break;
+                    case 2: code_desc = "EXC_I386_BPT"; break;
+                    }
+                    break;
+
+                case llvm::Triple::ppc:
+                case llvm::Triple::ppc64:
+                    switch (m_exc_code)
+                    {
+                    case 1: code_desc = "EXC_PPC_BREAKPOINT"; break;
+                    }
+                    break;
+                
+                case llvm::Triple::arm:
+                    switch (m_exc_code)
+                    {
+                    case 0x101: code_desc = "EXC_ARM_DA_ALIGN"; break;
+                    case 0x102: code_desc = "EXC_ARM_DA_DEBUG"; break;
+                    case 1: code_desc = "EXC_ARM_BREAKPOINT"; break;
+                    // FIXME temporary workaround, exc_code 0 does not really mean EXC_ARM_BREAKPOINT
+                    case 0: code_desc = "EXC_ARM_BREAKPOINT"; break;
+                    }
+                    break;
+
+                default:
+                    break;
+                }
+            }
+            break;
+
+        case 7:
+            exc_desc = "EXC_SYSCALL";
+            break;
+
+        case 8:
+            exc_desc = "EXC_MACH_SYSCALL";
+            break;
+
+        case 9:
+            exc_desc = "EXC_RPC_ALERT";
+            break;
+
+        case 10:
+            exc_desc = "EXC_CRASH";
+            break;
+        case 11:
+            exc_desc = "EXC_RESOURCE";
+            break;
+        case 12:
+            exc_desc = "EXC_GUARD";
+            break;
+        }
+        
+        StreamString strm;
+
+        if (exc_desc)
+            strm.PutCString(exc_desc);
+        else
+            strm.Printf("EXC_??? (%" PRIu64 ")", m_value);
+
+        if (m_exc_data_count >= 1)
+        {
+            if (code_desc)
+                strm.Printf(" (%s=%s", code_label, code_desc);
+            else
+                strm.Printf(" (%s=%" PRIu64, code_label, m_exc_code);
+        }
+
+        if (m_exc_data_count >= 2)
+        {
+            if (subcode_desc)
+                strm.Printf(", %s=%s", subcode_label, subcode_desc);
+            else
+                strm.Printf(", %s=0x%" PRIx64, subcode_label, m_exc_subcode);
+        }
+        
+        if (m_exc_data_count > 0)
+            strm.PutChar(')');
+        
+        m_description.swap (strm.GetString());
+    }
+    return m_description.c_str();
+}
+
+
+
+
+
+StopInfoSP
+StopInfoMachException::CreateStopReasonWithMachException 
+(
+    Thread &thread,
+    uint32_t exc_type, 
+    uint32_t exc_data_count,
+    uint64_t exc_code,
+    uint64_t exc_sub_code,
+    uint64_t exc_sub_sub_code,
+    bool pc_already_adjusted,
+    bool adjust_pc_if_needed
+)
+{
+    if (exc_type != 0)
+    {
+        uint32_t pc_decrement = 0;
+        ExecutionContext exe_ctx (thread.shared_from_this());
+        Target *target = exe_ctx.GetTargetPtr();
+        const llvm::Triple::ArchType cpu = target ? target->GetArchitecture().GetMachine() : llvm::Triple::UnknownArch;
+
+        switch (exc_type)
+        {
+        case 1: // EXC_BAD_ACCESS
+            break;
+
+        case 2: // EXC_BAD_INSTRUCTION
+            switch (cpu)
+            {
+            case llvm::Triple::ppc:
+            case llvm::Triple::ppc64:
+                switch (exc_code)
+                {
+                case 1: // EXC_PPC_INVALID_SYSCALL
+                case 2: // EXC_PPC_UNIPL_INST
+                case 3: // EXC_PPC_PRIVINST
+                case 4: // EXC_PPC_PRIVREG
+                    break;
+                case 5: // EXC_PPC_TRACE
+                    return StopInfo::CreateStopReasonToTrace (thread);
+                case 6: // EXC_PPC_PERFMON
+                    break;
+                }
+                break;
+
+            default:
+                break;
+            }
+            break;
+
+        case 3: // EXC_ARITHMETIC
+        case 4: // EXC_EMULATION
+            break;
+
+        case 5: // EXC_SOFTWARE
+            if (exc_code == 0x10003) // EXC_SOFT_SIGNAL
+            {
+                if (exc_sub_code == 5)
+                {
+                    // On MacOSX, a SIGTRAP can signify that a process has called
+                    // exec, so we should check with our dynamic loader to verify.
+                    ProcessSP process_sp (thread.GetProcess());
+                    if (process_sp)
+                    {
+                        DynamicLoader *dynamic_loader = process_sp->GetDynamicLoader();
+                        if (dynamic_loader && dynamic_loader->ProcessDidExec())
+                        {
+                            // The program was re-exec'ed
+                            return StopInfo::CreateStopReasonWithExec (thread);
+                        }
+//                        if (!process_did_exec)
+//                        {
+//                            // We have a SIGTRAP, make sure we didn't exec by checking
+//                            // for the PC being at "_dyld_start"...
+//                            lldb::StackFrameSP frame_sp (thread.GetStackFrameAtIndex(0));
+//                            if (frame_sp)
+//                            {
+//                                const Symbol *symbol = frame_sp->GetSymbolContext(eSymbolContextSymbol).symbol;
+//                                if (symbol)
+//                                {
+//                                    if (symbol->GetName() == ConstString("_dyld_start"))
+//                                        process_did_exec = true;
+//                                }
+//                            }
+//                        }
+                    }
+                }
+                return StopInfo::CreateStopReasonWithSignal (thread, exc_sub_code);
+            }
+            break;
+        
+        case 6: // EXC_BREAKPOINT
+            {
+                bool is_actual_breakpoint = false;
+                bool is_trace_if_actual_breakpoint_missing = false;
+                switch (cpu)
+                {
+                case llvm::Triple::x86:
+                case llvm::Triple::x86_64:
+                    if (exc_code == 1) // EXC_I386_SGL
+                    {
+                        if (!exc_sub_code)
+                            return StopInfo::CreateStopReasonToTrace(thread);
+
+                        // It's a watchpoint, then.
+                        // The exc_sub_code indicates the data break address.
+                        lldb::WatchpointSP wp_sp;
+                        if (target)
+                            wp_sp = target->GetWatchpointList().FindByAddress((lldb::addr_t)exc_sub_code);
+                        if (wp_sp && wp_sp->IsEnabled())
+                        {
+                            // Debugserver may piggyback the hardware index of the fired watchpoint in the exception data.
+                            // Set the hardware index if that's the case.
+                            if (exc_data_count >=3)
+                                wp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code);
+                            return StopInfo::CreateStopReasonWithWatchpointID(thread, wp_sp->GetID());
+                        }
+                    }
+                    else if (exc_code == 2 ||   // EXC_I386_BPT
+                             exc_code == 3)     // EXC_I386_BPTFLT
+                    {
+                        // KDP returns EXC_I386_BPTFLT for trace breakpoints
+                        if (exc_code == 3)
+                            is_trace_if_actual_breakpoint_missing = true;
+
+                        is_actual_breakpoint = true;
+                        if (!pc_already_adjusted)
+                            pc_decrement = 1;
+                    }
+                    break;
+
+                case llvm::Triple::ppc:
+                case llvm::Triple::ppc64:
+                    is_actual_breakpoint = exc_code == 1; // EXC_PPC_BREAKPOINT
+                    break;
+                
+                case llvm::Triple::arm:
+                    if (exc_code == 0x102) // EXC_ARM_DA_DEBUG
+                    {
+                        // It's a watchpoint, then, if the exc_sub_code indicates a known/enabled
+                        // data break address from our watchpoint list.
+                        lldb::WatchpointSP wp_sp;
+                        if (target)
+                            wp_sp = target->GetWatchpointList().FindByAddress((lldb::addr_t)exc_sub_code);
+                        if (wp_sp && wp_sp->IsEnabled())
+                        {
+                            // Debugserver may piggyback the hardware index of the fired watchpoint in the exception data.
+                            // Set the hardware index if that's the case.
+                            if (exc_data_count >=3)
+                                wp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code);
+                            return StopInfo::CreateStopReasonWithWatchpointID(thread, wp_sp->GetID());
+                        }
+                        // EXC_ARM_DA_DEBUG seems to be reused for EXC_BREAKPOINT as well as EXC_BAD_ACCESS
+                        if (thread.GetTemporaryResumeState() == eStateStepping)
+                            return StopInfo::CreateStopReasonToTrace(thread);
+                    }
+                    else if (exc_code == 1) // EXC_ARM_BREAKPOINT
+                    {
+                        is_actual_breakpoint = true;
+                        is_trace_if_actual_breakpoint_missing = true;
+                    }
+                    else if (exc_code == 0) // FIXME not EXC_ARM_BREAKPOINT but a kernel is currently returning this so accept it as indicating a breakpoint until the kernel is fixed
+                    {
+                        is_actual_breakpoint = true;
+                        is_trace_if_actual_breakpoint_missing = true;
+                    }
+                    break;
+
+                default:
+                    break;
+                }
+
+                if (is_actual_breakpoint)
+                {
+                    RegisterContextSP reg_ctx_sp (thread.GetRegisterContext());
+                    addr_t pc = reg_ctx_sp->GetPC() - pc_decrement;
+
+                    ProcessSP process_sp (thread.CalculateProcess());
+
+                    lldb::BreakpointSiteSP bp_site_sp;
+                    if (process_sp)
+                        bp_site_sp = process_sp->GetBreakpointSiteList().FindByAddress(pc);
+                    if (bp_site_sp && bp_site_sp->IsEnabled())
+                    {
+                        // Update the PC if we were asked to do so, but only do
+                        // so if we find a breakpoint that we know about cause
+                        // this could be a trap instruction in the code
+                        if (pc_decrement > 0 && adjust_pc_if_needed)
+                            reg_ctx_sp->SetPC (pc);
+
+                        // If the breakpoint is for this thread, then we'll report the hit, but if it is for another thread,
+                        // we can just report no reason.  We don't need to worry about stepping over the breakpoint here, that
+                        // will be taken care of when the thread resumes and notices that there's a breakpoint under the pc.
+                        if (bp_site_sp->ValidForThisThread (&thread))
+                            return StopInfo::CreateStopReasonWithBreakpointSiteID (thread, bp_site_sp->GetID());
+                        else
+                            return StopInfoSP();
+                    }
+                    
+                    // Don't call this a trace if we weren't single stepping this thread.
+                    if (is_trace_if_actual_breakpoint_missing && thread.GetTemporaryResumeState() == eStateStepping)
+                    {
+                        return StopInfo::CreateStopReasonToTrace (thread);
+                    }
+                }
+            }
+            break;
+
+        case 7:     // EXC_SYSCALL
+        case 8:     // EXC_MACH_SYSCALL
+        case 9:     // EXC_RPC_ALERT
+        case 10:    // EXC_CRASH
+            break;
+        }
+        
+        return StopInfoSP(new StopInfoMachException (thread, exc_type, exc_data_count, exc_code, exc_sub_code));
+    }
+    return StopInfoSP();
+}
diff --git a/source/Plugins/Process/Utility/StopInfoMachException.h b/source/Plugins/Process/Utility/StopInfoMachException.h
new file mode 100644
index 000000000000..130ee0b709b0
--- /dev/null
+++ b/source/Plugins/Process/Utility/StopInfoMachException.h
@@ -0,0 +1,77 @@
+//===-- StopInfoMachException.h ---------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_StopInfoMachException_h_
+#define liblldb_StopInfoMachException_h_
+
+// C Includes
+// C++ Includes
+#include <string>
+
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Target/StopInfo.h"
+
+namespace lldb_private {
+
+class StopInfoMachException : public StopInfo
+{
+public:
+    //------------------------------------------------------------------
+    // Constructors and Destructors
+    //------------------------------------------------------------------
+    StopInfoMachException (Thread &thread, 
+                           uint32_t exc_type, 
+                           uint32_t exc_data_count,
+                           uint64_t exc_code, 
+                           uint64_t exc_subcode) :
+        StopInfo (thread, exc_type),
+        m_exc_data_count (exc_data_count),
+        m_exc_code (exc_code),
+        m_exc_subcode (exc_subcode)
+    {
+    }
+
+    virtual ~StopInfoMachException()
+    {
+    }
+
+
+    virtual lldb::StopReason
+    GetStopReason () const
+    {
+        return lldb::eStopReasonException;
+    }
+
+    virtual const char *
+    GetDescription ();
+
+    // Since some mach exceptions will be reported as breakpoints, signals,
+    // or trace, we use this static accessor which will translate the mach
+    // exception into the correct StopInfo.
+    static lldb::StopInfoSP
+    CreateStopReasonWithMachException (Thread &thread, 
+                                       uint32_t exc_type, 
+                                       uint32_t exc_data_count,
+                                       uint64_t exc_code, 
+                                       uint64_t exc_sub_code,
+                                       uint64_t exc_sub_sub_code,
+                                       bool pc_already_adjusted = true,
+                                       bool adjust_pc_if_needed = false);
+
+protected:
+    uint32_t m_exc_data_count;
+    uint64_t m_exc_code;
+    uint64_t m_exc_subcode;
+};
+
+
+} // namespace lldb_private
+
+#endif  // liblldb_StopInfoMachException_h_
diff --git a/source/Plugins/Process/Utility/ThreadMemory.cpp b/source/Plugins/Process/Utility/ThreadMemory.cpp
new file mode 100644
index 000000000000..56e5a9a59fab
--- /dev/null
+++ b/source/Plugins/Process/Utility/ThreadMemory.cpp
@@ -0,0 +1,140 @@
+//===-- ThreadMemory.cpp ----------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Plugins/Process/Utility/ThreadMemory.h"
+#include "lldb/Target/OperatingSystem.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/StopInfo.h"
+#include "lldb/Target/Unwind.h"
+#include "Plugins/Process/Utility/RegisterContextThreadMemory.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+ThreadMemory::ThreadMemory (Process &process,
+                            tid_t tid,
+                            const ValueObjectSP &thread_info_valobj_sp) :
+    Thread (process, tid),
+    m_backing_thread_sp (),
+    m_thread_info_valobj_sp (thread_info_valobj_sp),
+    m_name(),
+    m_queue()
+{
+}
+
+
+ThreadMemory::ThreadMemory (Process &process,
+                            lldb::tid_t tid,
+                            const char *name,
+                            const char *queue,
+                            lldb::addr_t register_data_addr) :
+    Thread (process, tid),
+    m_backing_thread_sp (),
+    m_thread_info_valobj_sp (),
+    m_name(),
+    m_queue(),
+    m_register_data_addr (register_data_addr)
+{
+    if (name)
+        m_name = name;
+    if (queue)
+        m_queue = queue;
+}
+
+
+ThreadMemory::~ThreadMemory()
+{
+    DestroyThread();
+}
+
+void
+ThreadMemory::WillResume (StateType resume_state)
+{
+    if (m_backing_thread_sp)
+        m_backing_thread_sp->WillResume(resume_state);
+}
+
+void
+ThreadMemory::ClearStackFrames ()
+{
+    if (m_backing_thread_sp)
+        m_backing_thread_sp->ClearStackFrames();
+    Thread::ClearStackFrames();
+}
+
+RegisterContextSP
+ThreadMemory::GetRegisterContext ()
+{
+    if (!m_reg_context_sp)
+        m_reg_context_sp.reset (new RegisterContextThreadMemory (*this, m_register_data_addr));
+    return m_reg_context_sp;
+}
+
+RegisterContextSP
+ThreadMemory::CreateRegisterContextForFrame (StackFrame *frame)
+{
+    RegisterContextSP reg_ctx_sp;
+    uint32_t concrete_frame_idx = 0;
+    
+    if (frame)
+        concrete_frame_idx = frame->GetConcreteFrameIndex ();
+    
+    if (concrete_frame_idx == 0)
+    {
+        reg_ctx_sp = GetRegisterContext ();
+    }
+    else
+    {
+        Unwind *unwinder = GetUnwinder ();
+        if (unwinder)
+            reg_ctx_sp = unwinder->CreateRegisterContextForFrame (frame);
+    }
+    return reg_ctx_sp;
+}
+
+bool
+ThreadMemory::CalculateStopInfo ()
+{
+    if (m_backing_thread_sp)
+    {
+        lldb::StopInfoSP backing_stop_info_sp (m_backing_thread_sp->GetPrivateStopInfo());
+        if (backing_stop_info_sp)
+        {
+            backing_stop_info_sp->SetThread (shared_from_this());
+            SetStopInfo (backing_stop_info_sp);
+            return true;
+        }
+    }
+    else
+    {
+        ProcessSP process_sp (GetProcess());
+
+        if (process_sp)
+        {
+            OperatingSystem *os = process_sp->GetOperatingSystem ();
+            if (os)
+            {
+                SetStopInfo (os->CreateThreadStopReason (this));
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+void
+ThreadMemory::RefreshStateAfterStop()
+{
+    if (m_backing_thread_sp)
+        return m_backing_thread_sp->RefreshStateAfterStop();
+    
+    if (m_reg_context_sp)
+        m_reg_context_sp->InvalidateAllRegisters();
+}
diff --git a/source/Plugins/Process/Utility/ThreadMemory.h b/source/Plugins/Process/Utility/ThreadMemory.h
new file mode 100644
index 000000000000..07eb45dcb431
--- /dev/null
+++ b/source/Plugins/Process/Utility/ThreadMemory.h
@@ -0,0 +1,152 @@
+//===-- ThreadMemory.h -----------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ThreadMemory_h_
+#define liblldb_ThreadMemory_h_
+
+#include "lldb/Target/Thread.h"
+
+class ThreadMemory :
+    public lldb_private::Thread
+{
+public:
+
+    ThreadMemory (lldb_private::Process &process,
+                  lldb::tid_t tid,
+                  const lldb::ValueObjectSP &thread_info_valobj_sp);
+
+    ThreadMemory (lldb_private::Process &process,
+                  lldb::tid_t tid,
+                  const char *name,
+                  const char *queue,
+                  lldb::addr_t register_data_addr);
+
+    virtual
+    ~ThreadMemory();
+
+    //------------------------------------------------------------------
+    // lldb_private::Thread methods
+    //------------------------------------------------------------------
+    virtual lldb::RegisterContextSP
+    GetRegisterContext ();
+
+    virtual lldb::RegisterContextSP
+    CreateRegisterContextForFrame (lldb_private::StackFrame *frame);
+
+    virtual bool
+    CalculateStopInfo ();
+
+    virtual const char *
+    GetInfo ()
+    {
+        if (m_backing_thread_sp)
+            m_backing_thread_sp->GetInfo();
+        return NULL;
+    }
+
+    virtual const char *
+    GetName ()
+    {
+        if (!m_name.empty())
+            return m_name.c_str();
+        if (m_backing_thread_sp)
+            m_backing_thread_sp->GetName();
+        return NULL;
+    }
+    
+    virtual const char *
+    GetQueueName ()
+    {
+        if (!m_queue.empty())
+            return m_queue.c_str();
+        if (m_backing_thread_sp)
+            m_backing_thread_sp->GetQueueName();
+        return NULL;
+    }
+
+    virtual void
+    WillResume (lldb::StateType resume_state);
+
+    virtual void
+    DidResume ()
+    {
+        if (m_backing_thread_sp)
+            m_backing_thread_sp->DidResume();
+    }
+    
+    virtual lldb::user_id_t
+    GetProtocolID () const
+    {
+        if (m_backing_thread_sp)
+            return m_backing_thread_sp->GetProtocolID();
+        return Thread::GetProtocolID();
+    }
+
+    virtual void
+    RefreshStateAfterStop();
+    
+    lldb::ValueObjectSP &
+    GetValueObject ()
+    {
+        return m_thread_info_valobj_sp;
+    }
+    
+    virtual void
+    ClearStackFrames ();
+
+    virtual void
+    ClearBackingThread ()
+    {
+        m_backing_thread_sp.reset();
+    }
+
+    virtual bool
+    SetBackingThread (const lldb::ThreadSP &thread_sp)
+    {
+        //printf ("Thread 0x%llx is being backed by thread 0x%llx\n", GetID(), thread_sp->GetID());
+        m_backing_thread_sp = thread_sp;
+        return (bool)thread_sp;
+    }
+    
+    virtual lldb::ThreadSP
+    GetBackingThread () const
+    {
+        return m_backing_thread_sp;
+    }
+
+protected:
+    
+    virtual bool
+    IsOperatingSystemPluginThread () const
+    {
+        return true;
+    }
+    
+
+    //------------------------------------------------------------------
+    // For ThreadMemory and subclasses
+    //------------------------------------------------------------------
+    // If this memory thread is actually represented by a thread from the
+    // lldb_private::Process subclass, then fill in the thread here and
+    // all APIs will be routed through this thread object. If m_backing_thread_sp
+    // is empty, then this thread is simply in memory with no representation
+    // through the process plug-in.
+    lldb::ThreadSP m_backing_thread_sp;
+    lldb::ValueObjectSP m_thread_info_valobj_sp;
+    std::string m_name;
+    std::string m_queue;
+    lldb::addr_t m_register_data_addr;
+private:
+    //------------------------------------------------------------------
+    // For ThreadMemory only
+    //------------------------------------------------------------------
+    DISALLOW_COPY_AND_ASSIGN (ThreadMemory);
+};
+
+#endif  // liblldb_ThreadMemory_h_
diff --git a/source/Plugins/Process/Utility/UnwindLLDB.cpp b/source/Plugins/Process/Utility/UnwindLLDB.cpp
new file mode 100644
index 000000000000..0eea00363498
--- /dev/null
+++ b/source/Plugins/Process/Utility/UnwindLLDB.cpp
@@ -0,0 +1,322 @@
+//===-- UnwindLLDB.cpp -------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Core/Module.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Symbol/FuncUnwinders.h"
+#include "lldb/Symbol/Function.h"
+#include "lldb/Symbol/UnwindPlan.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+
+#include "UnwindLLDB.h"
+#include "RegisterContextLLDB.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+UnwindLLDB::UnwindLLDB (Thread &thread) :
+    Unwind (thread),
+    m_frames(),
+    m_unwind_complete(false)
+{
+}
+
+uint32_t
+UnwindLLDB::DoGetFrameCount()
+{
+    if (!m_unwind_complete)
+    {
+//#define DEBUG_FRAME_SPEED 1
+#if DEBUG_FRAME_SPEED
+#define FRAME_COUNT 10000
+        TimeValue time_value (TimeValue::Now());
+#endif
+        if (!AddFirstFrame ())
+            return 0;
+
+        ProcessSP process_sp (m_thread.GetProcess());
+        ABI *abi = process_sp ? process_sp->GetABI().get() : NULL;
+
+        while (AddOneMoreFrame (abi))
+        {
+#if DEBUG_FRAME_SPEED
+            if ((m_frames.size() % FRAME_COUNT) == 0)
+            {
+                TimeValue now(TimeValue::Now());
+                uint64_t delta_t = now - time_value;
+                printf ("%u frames in %" PRIu64 ".%09llu ms (%g frames/sec)\n",
+                        FRAME_COUNT,
+                        delta_t / TimeValue::NanoSecPerSec, 
+                        delta_t % TimeValue::NanoSecPerSec,
+                        (float)FRAME_COUNT / ((float)delta_t / (float)TimeValue::NanoSecPerSec));
+                time_value = now;
+            }
+#endif
+        }
+    }
+    return m_frames.size ();
+}
+
+bool
+UnwindLLDB::AddFirstFrame ()
+{
+    if (m_frames.size() > 0)
+        return true;
+        
+    // First, set up the 0th (initial) frame
+    CursorSP first_cursor_sp(new Cursor ());
+    RegisterContextLLDBSP reg_ctx_sp (new RegisterContextLLDB (m_thread, 
+                                                               RegisterContextLLDBSP(), 
+                                                               first_cursor_sp->sctx, 
+                                                               0, *this));
+    if (reg_ctx_sp.get() == NULL)
+        goto unwind_done;
+    
+    if (!reg_ctx_sp->IsValid())
+        goto unwind_done;
+
+    if (!reg_ctx_sp->GetCFA (first_cursor_sp->cfa))
+        goto unwind_done;
+
+    if (!reg_ctx_sp->ReadPC (first_cursor_sp->start_pc))
+        goto unwind_done;
+
+    // Everything checks out, so release the auto pointer value and let the
+    // cursor own it in its shared pointer
+    first_cursor_sp->reg_ctx_lldb_sp = reg_ctx_sp;
+    m_frames.push_back (first_cursor_sp);
+    return true;
+unwind_done:
+    m_unwind_complete = true;
+    return false;
+}
+
+// For adding a non-zero stack frame to m_frames.
+bool
+UnwindLLDB::AddOneMoreFrame (ABI *abi)
+{
+    // If we've already gotten to the end of the stack, don't bother to try again...
+    if (m_unwind_complete)
+        return false;
+        
+    Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
+    CursorSP cursor_sp(new Cursor ());
+
+    // Frame zero is a little different
+    if (m_frames.size() == 0)
+        return false;
+
+    uint32_t cur_idx = m_frames.size ();
+    RegisterContextLLDBSP reg_ctx_sp(new RegisterContextLLDB (m_thread, 
+                                                              m_frames[cur_idx - 1]->reg_ctx_lldb_sp, 
+                                                              cursor_sp->sctx, 
+                                                              cur_idx, 
+                                                              *this));
+
+    // We want to detect an unwind that cycles erronously and stop backtracing.
+    // Don't want this maximum unwind limit to be too low -- if you have a backtrace
+    // with an "infinitely recursing" bug, it will crash when the stack blows out
+    // and the first 35,000 frames are uninteresting - it's the top most 5 frames that
+    // you actually care about.  So you can't just cap the unwind at 10,000 or something.
+    // Realistically anything over around 200,000 is going to blow out the stack space.
+    // If we're still unwinding at that point, we're probably never going to finish.
+    if (cur_idx > 300000)
+    {
+        if (log)
+            log->Printf ("%*sFrame %d unwound too many frames, assuming unwind has gone astray, stopping.", 
+                         cur_idx < 100 ? cur_idx : 100, "", cur_idx);
+        goto unwind_done;
+    }
+
+    if (reg_ctx_sp.get() == NULL)
+        goto unwind_done;
+
+    if (!reg_ctx_sp->IsValid())
+    {
+        if (log)
+        {
+            log->Printf("%*sFrame %d invalid RegisterContext for this frame, stopping stack walk", 
+                        cur_idx < 100 ? cur_idx : 100, "", cur_idx);
+        }
+        goto unwind_done;
+    }
+    if (!reg_ctx_sp->GetCFA (cursor_sp->cfa))
+    {
+        if (log)
+        {
+            log->Printf("%*sFrame %d did not get CFA for this frame, stopping stack walk",
+                        cur_idx < 100 ? cur_idx : 100, "", cur_idx);
+        }
+        goto unwind_done;
+    }
+    if (abi && !abi->CallFrameAddressIsValid(cursor_sp->cfa))
+    {
+        if (log)
+        {
+            log->Printf("%*sFrame %d did not get a valid CFA for this frame, stopping stack walk",
+                        cur_idx < 100 ? cur_idx : 100, "", cur_idx);
+        }
+        goto unwind_done;
+    }
+    if (!reg_ctx_sp->ReadPC (cursor_sp->start_pc))
+    {
+        if (log)
+        {
+            log->Printf("%*sFrame %d did not get PC for this frame, stopping stack walk",
+                        cur_idx < 100 ? cur_idx : 100, "", cur_idx);
+        }
+        goto unwind_done;
+    }
+    if (abi && !abi->CodeAddressIsValid (cursor_sp->start_pc))
+    {
+        if (log)
+        {
+            log->Printf("%*sFrame %d did not get a valid PC, stopping stack walk",
+                        cur_idx < 100 ? cur_idx : 100, "", cur_idx);
+        }
+        goto unwind_done;
+    }
+    if (!m_frames.empty())
+    {
+        if (m_frames.back()->start_pc == cursor_sp->start_pc)
+        {
+            if (m_frames.back()->cfa == cursor_sp->cfa)
+                goto unwind_done; // Infinite loop where the current cursor is the same as the previous one...
+            else if (abi && abi->StackUsesFrames())
+            {
+                // We might have a CFA that is not using the frame pointer and
+                // we want to validate that the frame pointer is valid.
+                if (reg_ctx_sp->GetFP() == 0)
+                    goto unwind_done;
+            }
+        }
+    }
+    cursor_sp->reg_ctx_lldb_sp = reg_ctx_sp;
+    m_frames.push_back (cursor_sp);
+    return true;
+    
+unwind_done:
+    m_unwind_complete = true;
+    return false;
+}
+
+bool
+UnwindLLDB::DoGetFrameInfoAtIndex (uint32_t idx, addr_t& cfa, addr_t& pc)
+{
+    if (m_frames.size() == 0)
+    {
+        if (!AddFirstFrame())
+            return false;
+    }
+
+    ProcessSP process_sp (m_thread.GetProcess());
+    ABI *abi = process_sp ? process_sp->GetABI().get() : NULL;
+
+    while (idx >= m_frames.size() && AddOneMoreFrame (abi))
+        ;
+
+    if (idx < m_frames.size ())
+    {
+        cfa = m_frames[idx]->cfa;
+        pc = m_frames[idx]->start_pc;
+        return true;
+    }
+    return false;
+}
+
+lldb::RegisterContextSP
+UnwindLLDB::DoCreateRegisterContextForFrame (StackFrame *frame)
+{
+    lldb::RegisterContextSP reg_ctx_sp;
+    uint32_t idx = frame->GetConcreteFrameIndex ();
+
+    if (idx == 0)
+    {
+        return m_thread.GetRegisterContext();
+    }
+
+    if (m_frames.size() == 0)
+    {
+        if (!AddFirstFrame())
+            return reg_ctx_sp;
+    }
+
+    ProcessSP process_sp (m_thread.GetProcess());
+    ABI *abi = process_sp ? process_sp->GetABI().get() : NULL;
+
+    while (idx >= m_frames.size())
+    {
+        if (!AddOneMoreFrame (abi))
+            break;
+    }
+
+    const uint32_t num_frames = m_frames.size();
+    if (idx < num_frames)
+    {
+        Cursor *frame_cursor = m_frames[idx].get();
+        reg_ctx_sp = frame_cursor->reg_ctx_lldb_sp;
+    }
+    return reg_ctx_sp;
+}
+
+UnwindLLDB::RegisterContextLLDBSP
+UnwindLLDB::GetRegisterContextForFrameNum (uint32_t frame_num)
+{
+    RegisterContextLLDBSP reg_ctx_sp;
+    if (frame_num < m_frames.size())
+        reg_ctx_sp = m_frames[frame_num]->reg_ctx_lldb_sp;
+    return reg_ctx_sp;
+}
+
+bool
+UnwindLLDB::SearchForSavedLocationForRegister (uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation &regloc, uint32_t starting_frame_num, bool pc_reg)
+{
+    int64_t frame_num = starting_frame_num;
+    if (frame_num >= m_frames.size())
+        return false;
+
+    // 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_reg)
+    {
+        UnwindLLDB::RegisterSearchResult result;
+        result = m_frames[frame_num]->reg_ctx_lldb_sp->SavedLocationForRegister (lldb_regnum, regloc);
+        if (result == UnwindLLDB::RegisterSearchResult::eRegisterFound)
+          return true;
+        else
+          return false;
+    }
+    while (frame_num >= 0)
+    {
+        UnwindLLDB::RegisterSearchResult result;
+        result = m_frames[frame_num]->reg_ctx_lldb_sp->SavedLocationForRegister (lldb_regnum, regloc);
+
+        // If we have unwind instructions saying that register N is saved in register M in the middle of
+        // the stack (and N can equal M here, meaning the register was not used in this function), then
+        // change the register number we're looking for to M and keep looking for a concrete  location 
+        // down the stack, or an actual value from a live RegisterContext at frame 0.
+        if (result == UnwindLLDB::RegisterSearchResult::eRegisterFound
+            && regloc.type == UnwindLLDB::RegisterLocation::eRegisterInRegister
+            && frame_num > 0)
+        {
+            result = UnwindLLDB::RegisterSearchResult::eRegisterNotFound;
+            lldb_regnum = regloc.location.register_number;
+        }
+
+        if (result == UnwindLLDB::RegisterSearchResult::eRegisterFound)
+            return true;
+        if (result == UnwindLLDB::RegisterSearchResult::eRegisterIsVolatile)
+            return false;
+        frame_num--;
+    }
+    return false;
+}
diff --git a/source/Plugins/Process/Utility/UnwindLLDB.h b/source/Plugins/Process/Utility/UnwindLLDB.h
new file mode 100644
index 000000000000..5725654a6869
--- /dev/null
+++ b/source/Plugins/Process/Utility/UnwindLLDB.h
@@ -0,0 +1,125 @@
+//===-- UnwindLLDB.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_UnwindLLDB_h_
+#define lldb_UnwindLLDB_h_
+
+#include <vector>
+
+#include "lldb/lldb-public.h"
+#include "lldb/Symbol/FuncUnwinders.h"
+#include "lldb/Symbol/UnwindPlan.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/Unwind.h"
+
+namespace lldb_private {
+
+class RegisterContextLLDB;
+
+class UnwindLLDB : public lldb_private::Unwind
+{
+public: 
+    UnwindLLDB (lldb_private::Thread &thread);
+    
+    virtual
+    ~UnwindLLDB() { }
+
+    enum RegisterSearchResult
+    {
+        eRegisterFound = 0,
+        eRegisterNotFound,
+        eRegisterIsVolatile
+    };
+
+protected:
+    friend class lldb_private::RegisterContextLLDB;
+
+    struct RegisterLocation {
+        enum RegisterLocationTypes
+        {
+            eRegisterNotSaved = 0,              // register was not preserved by callee.  If volatile reg, is unavailable
+            eRegisterSavedAtMemoryLocation,     // register is saved at a specific word of target mem (target_memory_location)
+            eRegisterInRegister,                // register is available in a (possible other) register (register_number)
+            eRegisterSavedAtHostMemoryLocation, // register is saved at a word in lldb's address space
+            eRegisterValueInferred              // register val was computed (and is in inferred_value)
+        };
+        int type;
+        union
+        {
+            lldb::addr_t target_memory_location;
+            uint32_t     register_number;       // in eRegisterKindLLDB register numbering system
+            void*        host_memory_location;
+            uint64_t     inferred_value;        // eRegisterValueInferred - e.g. stack pointer == cfa + offset
+        } location;
+    };
+
+    void
+    DoClear()
+    {
+        m_frames.clear();
+        m_unwind_complete = false;
+    }
+
+    virtual uint32_t
+    DoGetFrameCount();
+
+    bool
+    DoGetFrameInfoAtIndex (uint32_t frame_idx,
+                         lldb::addr_t& cfa, 
+                         lldb::addr_t& start_pc);
+    
+    lldb::RegisterContextSP
+    DoCreateRegisterContextForFrame (lldb_private::StackFrame *frame);
+
+    typedef std::shared_ptr<RegisterContextLLDB> RegisterContextLLDBSP;
+
+    // Needed to retrieve the "next" frame (e.g. frame 2 needs to retrieve frame 1's RegisterContextLLDB)
+    // The RegisterContext for frame_num must already exist or this returns an empty shared pointer.
+    RegisterContextLLDBSP
+    GetRegisterContextForFrameNum (uint32_t frame_num);
+
+    // 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 &regloc, uint32_t starting_frame_num, bool pc_register);
+
+
+private:
+
+    struct Cursor
+    {
+        lldb::addr_t start_pc;  // The start address of the function/symbol for this frame - current pc if unknown
+        lldb::addr_t cfa;       // The canonical frame address for this stack frame
+        lldb_private::SymbolContext sctx;  // A symbol context we'll contribute to & provide to the StackFrame creation
+        RegisterContextLLDBSP reg_ctx_lldb_sp; // These are all RegisterContextLLDB's
+
+        Cursor () : start_pc (LLDB_INVALID_ADDRESS), cfa (LLDB_INVALID_ADDRESS), sctx(), reg_ctx_lldb_sp() { }
+    private:
+        DISALLOW_COPY_AND_ASSIGN (Cursor);
+    };
+
+    typedef std::shared_ptr<Cursor> CursorSP;
+    std::vector<CursorSP> m_frames;
+    bool m_unwind_complete; // If this is true, we've enumerated all the frames in the stack, and m_frames.size() is the 
+                            // number of frames, etc.  Otherwise we've only gone as far as directly asked, and m_frames.size()
+                            // is how far we've currently gone.
+ 
+
+    bool AddOneMoreFrame (ABI *abi);
+    bool AddFirstFrame ();
+
+    //------------------------------------------------------------------
+    // For UnwindLLDB only
+    //------------------------------------------------------------------
+    DISALLOW_COPY_AND_ASSIGN (UnwindLLDB);
+};
+
+}   // namespace lldb_private
+
+#endif  // lldb_UnwindLLDB_h_
diff --git a/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp b/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp
new file mode 100644
index 000000000000..d011314b0963
--- /dev/null
+++ b/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.cpp
@@ -0,0 +1,275 @@
+//===-- UnwindMacOSXFrameBackchain.cpp --------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Symbol/Function.h"
+#include "lldb/Symbol/Symbol.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+
+#include "RegisterContextMacOSXFrameBackchain.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+UnwindMacOSXFrameBackchain::UnwindMacOSXFrameBackchain (Thread &thread) :
+    Unwind (thread),
+    m_cursors()
+{
+}
+
+uint32_t
+UnwindMacOSXFrameBackchain::DoGetFrameCount()
+{
+    if (m_cursors.empty())
+    {
+        ExecutionContext exe_ctx (m_thread.shared_from_this());
+        Target *target = exe_ctx.GetTargetPtr();
+        if (target)
+        {
+            const ArchSpec& target_arch = target->GetArchitecture ();
+            // Frame zero should always be supplied by the thread...
+            exe_ctx.SetFrameSP (m_thread.GetStackFrameAtIndex (0));
+            
+            if (target_arch.GetAddressByteSize() == 8)
+                GetStackFrameData_x86_64 (exe_ctx);
+            else
+                GetStackFrameData_i386 (exe_ctx);
+        }
+    }
+    return m_cursors.size();
+}
+
+bool
+UnwindMacOSXFrameBackchain::DoGetFrameInfoAtIndex (uint32_t idx, addr_t& cfa, addr_t& pc)
+{
+    const uint32_t frame_count = GetFrameCount();
+    if (idx < frame_count)
+    {
+        if (m_cursors[idx].pc == LLDB_INVALID_ADDRESS)
+            return false;
+        if (m_cursors[idx].fp == LLDB_INVALID_ADDRESS)
+            return false;
+
+        pc = m_cursors[idx].pc;
+        cfa = m_cursors[idx].fp;
+
+        return true;
+    }
+    return false;
+}
+    
+lldb::RegisterContextSP
+UnwindMacOSXFrameBackchain::DoCreateRegisterContextForFrame (StackFrame *frame)
+{
+    lldb::RegisterContextSP reg_ctx_sp;
+    uint32_t concrete_idx = frame->GetConcreteFrameIndex ();
+    const uint32_t frame_count = GetFrameCount();
+    if (concrete_idx < frame_count)
+        reg_ctx_sp.reset (new RegisterContextMacOSXFrameBackchain (m_thread, concrete_idx, m_cursors[concrete_idx]));
+    return reg_ctx_sp;
+}
+
+size_t
+UnwindMacOSXFrameBackchain::GetStackFrameData_i386 (const ExecutionContext &exe_ctx)
+{
+    m_cursors.clear();
+    
+    StackFrame *first_frame = exe_ctx.GetFramePtr();
+
+    Process *process = exe_ctx.GetProcessPtr();
+    if (process == NULL)
+        return 0;
+    
+    std::pair<lldb::addr_t, lldb::addr_t> fp_pc_pair;
+
+    struct Frame_i386
+    {
+        uint32_t fp;
+        uint32_t pc;
+    };
+
+    RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
+    assert (reg_ctx);
+
+    Cursor cursor;
+    cursor.pc = reg_ctx->GetPC (LLDB_INVALID_ADDRESS);
+    cursor.fp = reg_ctx->GetFP (0);
+    
+    Frame_i386 frame = { static_cast<uint32_t>(cursor.fp), static_cast<uint32_t>(cursor.pc) };
+
+    m_cursors.push_back(cursor);
+
+    const size_t k_frame_size = sizeof(frame);
+    Error error;
+    while (frame.fp != 0 && frame.pc != 0 && ((frame.fp & 7) == 0))
+    {
+        // Read both the FP and PC (8 bytes)
+        if (process->ReadMemory (frame.fp, &frame.fp, k_frame_size, error) != k_frame_size)
+            break;
+        if (frame.pc >= 0x1000)
+        {
+            cursor.pc = frame.pc;
+            cursor.fp = frame.fp;
+            m_cursors.push_back (cursor);
+        }
+    }
+    if (!m_cursors.empty())
+    {
+        lldb::addr_t first_frame_pc = m_cursors.front().pc;
+        if (first_frame_pc != LLDB_INVALID_ADDRESS)
+        {
+            const uint32_t resolve_scope = eSymbolContextModule |
+                                           eSymbolContextCompUnit |
+                                           eSymbolContextFunction |
+                                           eSymbolContextSymbol;
+
+            SymbolContext first_frame_sc (first_frame->GetSymbolContext(resolve_scope));
+            const AddressRange *addr_range_ptr = NULL;
+            AddressRange range;
+            if (first_frame_sc.function)
+                addr_range_ptr = &first_frame_sc.function->GetAddressRange();
+            else if (first_frame_sc.symbol)
+            {
+                range.GetBaseAddress() = first_frame_sc.symbol->GetAddress();
+                range.SetByteSize (first_frame_sc.symbol->GetByteSize());
+                addr_range_ptr = &range;
+            }
+
+            if (addr_range_ptr)
+            {
+                if (first_frame->GetFrameCodeAddress() == addr_range_ptr->GetBaseAddress())
+                {
+                    // We are at the first instruction, so we can recover the
+                    // previous PC by dereferencing the SP
+                    lldb::addr_t first_frame_sp = reg_ctx->GetSP (0);
+                    // Read the real second frame return address into frame.pc
+                    if (first_frame_sp && process->ReadMemory (first_frame_sp, &frame.pc, sizeof(frame.pc), error) == sizeof(frame.pc))
+                    {
+                        cursor.fp = m_cursors.front().fp;
+                        cursor.pc = frame.pc;           // Set the new second frame PC
+
+                        // Insert the second frame
+                        m_cursors.insert(m_cursors.begin()+1, cursor);
+                        
+                        m_cursors.front().fp = first_frame_sp;
+                    }
+                }
+            }
+        }
+    }
+//    uint32_t i=0;
+//    printf("      PC                 FP\n");
+//    printf("      ------------------ ------------------ \n");
+//    for (i=0; i<m_cursors.size(); ++i)
+//    {
+//        printf("[%3u] 0x%16.16" PRIx64 " 0x%16.16" PRIx64 "\n", i, m_cursors[i].pc, m_cursors[i].fp);
+//    }
+    return m_cursors.size();
+}
+
+
+size_t
+UnwindMacOSXFrameBackchain::GetStackFrameData_x86_64 (const ExecutionContext &exe_ctx)
+{
+    m_cursors.clear();
+
+    Process *process = exe_ctx.GetProcessPtr();
+    if (process == NULL)
+        return 0;
+    
+    StackFrame *first_frame = exe_ctx.GetFramePtr();
+
+    std::pair<lldb::addr_t, lldb::addr_t> fp_pc_pair;
+
+    struct Frame_x86_64
+    {
+        uint64_t fp;
+        uint64_t pc;
+    };
+
+    RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
+    assert (reg_ctx);
+
+    Cursor cursor;
+    cursor.pc = reg_ctx->GetPC (LLDB_INVALID_ADDRESS);
+    cursor.fp = reg_ctx->GetFP (0);
+    
+    Frame_x86_64 frame = { cursor.fp, cursor.pc };
+
+    m_cursors.push_back(cursor);
+    Error error;
+    const size_t k_frame_size = sizeof(frame);
+    while (frame.fp != 0 && frame.pc != 0 && ((frame.fp & 7) == 0))
+    {
+        // Read both the FP and PC (16 bytes)
+        if (process->ReadMemory (frame.fp, &frame.fp, k_frame_size, error) != k_frame_size)
+            break;
+
+        if (frame.pc >= 0x1000)
+        {
+            cursor.pc = frame.pc;
+            cursor.fp = frame.fp;
+            m_cursors.push_back (cursor);
+        }
+    }
+    if (!m_cursors.empty())
+    {
+        lldb::addr_t first_frame_pc = m_cursors.front().pc;
+        if (first_frame_pc != LLDB_INVALID_ADDRESS)
+        {
+            const uint32_t resolve_scope = eSymbolContextModule |
+                                           eSymbolContextCompUnit |
+                                           eSymbolContextFunction |
+                                           eSymbolContextSymbol;
+
+            SymbolContext first_frame_sc(first_frame->GetSymbolContext(resolve_scope));
+            const AddressRange *addr_range_ptr = NULL;
+            AddressRange range;
+            if (first_frame_sc.function)
+                addr_range_ptr = &first_frame_sc.function->GetAddressRange();
+            else if (first_frame_sc.symbol)
+            {
+                range.GetBaseAddress() = first_frame_sc.symbol->GetAddress();
+                range.SetByteSize (first_frame_sc.symbol->GetByteSize());
+                addr_range_ptr = &range;
+            }
+
+            if (addr_range_ptr)
+            {
+                if (first_frame->GetFrameCodeAddress() == addr_range_ptr->GetBaseAddress())
+                {
+                    // We are at the first instruction, so we can recover the
+                    // previous PC by dereferencing the SP
+                    lldb::addr_t first_frame_sp = reg_ctx->GetSP (0);
+                    // Read the real second frame return address into frame.pc
+                    if (process->ReadMemory (first_frame_sp, &frame.pc, sizeof(frame.pc), error) == sizeof(frame.pc))
+                    {
+                        cursor.fp = m_cursors.front().fp;
+                        cursor.pc = frame.pc;           // Set the new second frame PC
+
+                        // Insert the second frame
+                        m_cursors.insert(m_cursors.begin()+1, cursor);
+                        
+                        m_cursors.front().fp = first_frame_sp;
+                    }
+                }
+            }
+        }
+    }
+    return m_cursors.size();
+}
+
diff --git a/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.h b/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.h
new file mode 100644
index 000000000000..2695376fd6e0
--- /dev/null
+++ b/source/Plugins/Process/Utility/UnwindMacOSXFrameBackchain.h
@@ -0,0 +1,74 @@
+//===-- UnwindMacOSXFrameBackchain.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_UnwindMacOSXFrameBackchain_h_
+#define lldb_UnwindMacOSXFrameBackchain_h_
+
+// C Includes
+// C++ Includes
+#include <vector>
+
+// Other libraries and framework includes
+
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Target/Unwind.h"
+
+class UnwindMacOSXFrameBackchain : public lldb_private::Unwind
+{
+public: 
+    UnwindMacOSXFrameBackchain (lldb_private::Thread &thread);
+    
+    virtual
+    ~UnwindMacOSXFrameBackchain()
+    {
+    }
+    
+protected:
+    virtual void
+    DoClear()
+    {
+        m_cursors.clear();
+    }
+
+    virtual uint32_t
+    DoGetFrameCount();
+
+    bool
+    DoGetFrameInfoAtIndex (uint32_t frame_idx,
+                         lldb::addr_t& cfa, 
+                         lldb::addr_t& pc);
+    
+    lldb::RegisterContextSP
+    DoCreateRegisterContextForFrame (lldb_private::StackFrame *frame);
+
+    friend class RegisterContextMacOSXFrameBackchain;
+
+    struct Cursor
+    {
+        lldb::addr_t pc;    // Program counter
+        lldb::addr_t fp;    // Frame pointer for us with backchain
+    };
+
+private:
+    std::vector<Cursor> m_cursors;
+
+    size_t
+    GetStackFrameData_i386 (const lldb_private::ExecutionContext &exe_ctx);
+
+    size_t
+    GetStackFrameData_x86_64 (const lldb_private::ExecutionContext &exe_ctx);
+
+    //------------------------------------------------------------------
+    // For UnwindMacOSXFrameBackchain only
+    //------------------------------------------------------------------
+    DISALLOW_COPY_AND_ASSIGN (UnwindMacOSXFrameBackchain);
+};
+
+#endif  // lldb_UnwindMacOSXFrameBackchain_h_
diff --git a/source/Plugins/Process/elf-core/ProcessElfCore.cpp b/source/Plugins/Process/elf-core/ProcessElfCore.cpp
new file mode 100644
index 000000000000..dd553ce36c89
--- /dev/null
+++ b/source/Plugins/Process/elf-core/ProcessElfCore.cpp
@@ -0,0 +1,619 @@
+//===-- ProcessElfCore.cpp --------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+#include <stdlib.h>
+
+// Other libraries and framework includes
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Core/Section.h"
+#include "lldb/Core/State.h"
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/DynamicLoader.h"
+#include "ProcessPOSIXLog.h"
+
+#include "Plugins/ObjectFile/ELF/ObjectFileELF.h"
+#include "Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h"
+
+// Project includes
+#include "ProcessElfCore.h"
+#include "ThreadElfCore.h"
+
+using namespace lldb_private;
+
+ConstString
+ProcessElfCore::GetPluginNameStatic()
+{
+    static ConstString g_name("elf-core");
+    return g_name;
+}
+
+const char *
+ProcessElfCore::GetPluginDescriptionStatic()
+{
+    return "ELF core dump plug-in.";
+}
+
+void
+ProcessElfCore::Terminate()
+{
+    PluginManager::UnregisterPlugin (ProcessElfCore::CreateInstance);
+}
+
+
+lldb::ProcessSP
+ProcessElfCore::CreateInstance (Target &target, Listener &listener, const FileSpec *crash_file)
+{
+    lldb::ProcessSP process_sp;
+    if (crash_file) 
+        process_sp.reset(new ProcessElfCore (target, listener, *crash_file));
+    return process_sp;
+}
+
+bool
+ProcessElfCore::CanDebug(Target &target, bool plugin_specified_by_name)
+{
+    // For now we are just making sure the file exists for a given module
+    if (!m_core_module_sp && m_core_file.Exists())
+    {
+        ModuleSpec core_module_spec(m_core_file, target.GetArchitecture());
+        Error error (ModuleList::GetSharedModule (core_module_spec, m_core_module_sp, 
+                                                  NULL, NULL, NULL));
+        if (m_core_module_sp)
+        {
+            ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
+            if (core_objfile && core_objfile->GetType() == ObjectFile::eTypeCoreFile)
+                return true;
+        }
+    }
+    return false;
+}
+
+//----------------------------------------------------------------------
+// ProcessElfCore constructor
+//----------------------------------------------------------------------
+ProcessElfCore::ProcessElfCore(Target& target, Listener &listener,
+                               const FileSpec &core_file) :
+    Process (target, listener),
+    m_core_module_sp (),
+    m_core_file (core_file),
+    m_dyld_plugin_name (),
+    m_thread_data_valid(false),
+    m_thread_data(),
+    m_core_aranges ()
+{
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+ProcessElfCore::~ProcessElfCore()
+{
+    Clear();
+    // We need to call finalize on the process before destroying ourselves
+    // to make sure all of the broadcaster cleanup goes as planned. If we
+    // destruct this class, then Process::~Process() might have problems
+    // trying to fully destroy the broadcaster.
+    Finalize();
+}
+
+//----------------------------------------------------------------------
+// PluginInterface
+//----------------------------------------------------------------------
+ConstString
+ProcessElfCore::GetPluginName()
+{
+    return GetPluginNameStatic();
+}
+
+uint32_t
+ProcessElfCore::GetPluginVersion()
+{
+    return 1;
+}
+
+lldb::addr_t
+ProcessElfCore::AddAddressRangeFromLoadSegment(const elf::ELFProgramHeader *header)
+{
+    lldb::addr_t addr = header->p_vaddr;
+    FileRange file_range (header->p_offset, header->p_filesz);
+    VMRangeToFileOffset::Entry range_entry(addr, header->p_memsz, file_range);
+
+    VMRangeToFileOffset::Entry *last_entry = m_core_aranges.Back();
+    if (last_entry &&
+        last_entry->GetRangeEnd() == range_entry.GetRangeBase() &&
+        last_entry->data.GetRangeEnd() == range_entry.data.GetRangeBase())
+    {
+        last_entry->SetRangeEnd (range_entry.GetRangeEnd());
+        last_entry->data.SetRangeEnd (range_entry.data.GetRangeEnd());
+    }
+    else
+    {
+        m_core_aranges.Append(range_entry);
+    }
+
+    return addr;
+}
+
+//----------------------------------------------------------------------
+// Process Control
+//----------------------------------------------------------------------
+Error
+ProcessElfCore::DoLoadCore ()
+{
+    Error error;
+    if (!m_core_module_sp)
+    {
+        error.SetErrorString ("invalid core module");   
+        return error;
+    }
+
+    ObjectFileELF *core = (ObjectFileELF *)(m_core_module_sp->GetObjectFile());
+    if (core == NULL)
+    {
+        error.SetErrorString ("invalid core object file");   
+        return error;
+    }
+
+    const uint32_t num_segments = core->GetProgramHeaderCount();
+    if (num_segments == 0)
+    {
+        error.SetErrorString ("core file has no sections");   
+        return error;
+    }
+
+    SetCanJIT(false);
+
+    m_thread_data_valid = true;
+
+    bool ranges_are_sorted = true;
+    lldb::addr_t vm_addr = 0;
+    /// Walk through segments and Thread and Address Map information.
+    /// PT_NOTE - Contains Thread and Register information
+    /// PT_LOAD - Contains a contiguous range of Process Address Space
+    for(uint32_t i = 1; i <= num_segments; i++)
+    {
+        const elf::ELFProgramHeader *header = core->GetProgramHeaderByIndex(i);
+        assert(header != NULL);
+
+        DataExtractor data = core->GetSegmentDataByIndex(i);
+
+        // Parse thread contexts and auxv structure
+        if (header->p_type == llvm::ELF::PT_NOTE)
+            ParseThreadContextsFromNoteSegment(header, data);
+
+        // PT_LOAD segments contains address map
+        if (header->p_type == llvm::ELF::PT_LOAD)
+        {
+            lldb::addr_t last_addr = AddAddressRangeFromLoadSegment(header);
+            if (vm_addr > last_addr)
+                ranges_are_sorted = false;
+            vm_addr = last_addr;
+        }
+    }
+
+    if (!ranges_are_sorted)
+        m_core_aranges.Sort();
+
+    // Even if the architecture is set in the target, we need to override
+    // it to match the core file which is always single arch.
+    ArchSpec arch (m_core_module_sp->GetArchitecture());
+    if (arch.IsValid())
+        m_target.SetArchitecture(arch);            
+
+    return error;
+}
+
+lldb_private::DynamicLoader *
+ProcessElfCore::GetDynamicLoader ()
+{
+    if (m_dyld_ap.get() == NULL)
+        m_dyld_ap.reset (DynamicLoader::FindPlugin(this, DynamicLoaderPOSIXDYLD::GetPluginNameStatic().GetCString()));
+    return m_dyld_ap.get();
+}
+
+bool
+ProcessElfCore::UpdateThreadList (ThreadList &old_thread_list, ThreadList &new_thread_list)
+{
+    const uint32_t num_threads = GetNumThreadContexts ();
+    if (!m_thread_data_valid)
+        return false;
+
+    for (lldb::tid_t tid = 0; tid < num_threads; ++tid)
+    {
+        const ThreadData &td = m_thread_data[tid];
+        lldb::ThreadSP thread_sp(new ThreadElfCore (*this, tid, td));
+        new_thread_list.AddThread (thread_sp);
+    }
+    return new_thread_list.GetSize(false) > 0;
+}
+
+void
+ProcessElfCore::RefreshStateAfterStop ()
+{
+}
+
+Error
+ProcessElfCore::DoDestroy ()
+{
+    return Error();
+}
+
+//------------------------------------------------------------------
+// Process Queries
+//------------------------------------------------------------------
+
+bool
+ProcessElfCore::IsAlive ()
+{
+    return true;
+}
+
+//------------------------------------------------------------------
+// Process Memory
+//------------------------------------------------------------------
+size_t
+ProcessElfCore::ReadMemory (lldb::addr_t addr, void *buf, size_t size, Error &error)
+{
+    // Don't allow the caching that lldb_private::Process::ReadMemory does
+    // since in core files we have it all cached our our core file anyway.
+    return DoReadMemory (addr, buf, size, error);
+}
+
+size_t
+ProcessElfCore::DoReadMemory (lldb::addr_t addr, void *buf, size_t size, Error &error)
+{
+    ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
+
+    if (core_objfile == NULL)
+        return 0;
+
+    // Get the address range
+    const VMRangeToFileOffset::Entry *address_range = m_core_aranges.FindEntryThatContains (addr);
+    if (address_range == NULL || address_range->GetRangeEnd() < addr)
+    {
+        error.SetErrorStringWithFormat ("core file does not contain 0x%" PRIx64, addr);
+        return 0;
+    }
+
+    // Convert the address into core file offset
+    const lldb::addr_t offset = addr - address_range->GetRangeBase();
+    const lldb::addr_t file_start = address_range->data.GetRangeBase();
+    const lldb::addr_t file_end = address_range->data.GetRangeEnd();
+    size_t bytes_to_read = size; // Number of bytes to read from the core file
+    size_t bytes_copied = 0;     // Number of bytes actually read from the core file
+    size_t zero_fill_size = 0;   // Padding
+    lldb::addr_t bytes_left = 0; // Number of bytes available in the core file from the given address
+
+    if (file_end > offset)
+        bytes_left = file_end - offset;
+
+    if (bytes_to_read > bytes_left)
+    {
+        zero_fill_size = bytes_to_read - bytes_left;
+        bytes_to_read = bytes_left;
+    }
+
+    // If there is data available on the core file read it
+    if (bytes_to_read)
+        bytes_copied = core_objfile->CopyData(offset + file_start, bytes_to_read, buf);
+
+    assert(zero_fill_size <= size);
+    // Pad remaining bytes
+    if (zero_fill_size)
+        memset(((char *)buf) + bytes_copied, 0, zero_fill_size);
+
+    return bytes_copied + zero_fill_size;
+}
+
+void
+ProcessElfCore::Clear()
+{
+    m_thread_list.Clear();
+}
+
+void
+ProcessElfCore::Initialize()
+{
+    static bool g_initialized = false;
+    
+    if (g_initialized == false)
+    {
+        g_initialized = true;
+        PluginManager::RegisterPlugin (GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance);
+    }
+}
+
+lldb::addr_t
+ProcessElfCore::GetImageInfoAddress()
+{
+    Target *target = &GetTarget();
+    ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile();
+    Address addr = obj_file->GetImageInfoAddress();
+
+    if (addr.IsValid()) 
+        return addr.GetLoadAddress(target);
+    return LLDB_INVALID_ADDRESS;
+}
+
+/// Core files PT_NOTE segment descriptor types
+enum {
+    NT_PRSTATUS     = 1,
+    NT_FPREGSET,
+    NT_PRPSINFO,
+    NT_TASKSTRUCT,
+    NT_PLATFORM,
+    NT_AUXV
+};
+
+enum {
+    NT_FREEBSD_PRSTATUS      = 1,
+    NT_FREEBSD_FPREGSET,
+    NT_FREEBSD_PRPSINFO,
+    NT_FREEBSD_THRMISC       = 7,
+    NT_FREEBSD_PROCSTAT_AUXV = 16
+};
+
+/// Align the given value to next boundary specified by the alignment bytes
+static uint32_t
+AlignToNext(uint32_t value, int alignment_bytes)
+{
+    return (value + alignment_bytes - 1) & ~(alignment_bytes - 1);
+}
+
+/// Note Structure found in ELF core dumps.
+/// This is PT_NOTE type program/segments in the core file.
+struct ELFNote
+{
+    elf::elf_word n_namesz;
+    elf::elf_word n_descsz;
+    elf::elf_word n_type;
+
+    std::string n_name;
+
+    ELFNote() : n_namesz(0), n_descsz(0), n_type(0)
+    {
+    }
+
+    /// Parse an ELFNote entry from the given DataExtractor starting at position
+    /// \p offset.
+    ///
+    /// @param[in] data
+    ///    The DataExtractor to read from.
+    ///
+    /// @param[in,out] offset
+    ///    Pointer to an offset in the data.  On return the offset will be
+    ///    advanced by the number of bytes read.
+    ///
+    /// @return
+    ///    True if the ELFRel entry was successfully read and false otherwise.
+    bool
+    Parse(const DataExtractor &data, lldb::offset_t *offset)
+    {
+        // Read all fields.
+        if (data.GetU32(offset, &n_namesz, 3) == NULL)
+            return false;
+
+        // The name field is required to be nul-terminated, and n_namesz
+        // includes the terminating nul in observed implementations (contrary
+        // to the ELF-64 spec).  A special case is needed for cores generated
+        // by some older Linux versions, which write a note named "CORE"
+        // without a nul terminator and n_namesz = 4.
+        if (n_namesz == 4)
+        {
+            char buf[4];
+            if (data.ExtractBytes (*offset, 4, data.GetByteOrder(), buf) != 4)
+                return false;
+            if (strncmp (buf, "CORE", 4) == 0)
+            {
+                n_name = "CORE";
+                *offset += 4;
+                return true;
+            }
+        }
+
+        const char *cstr = data.GetCStr(offset, AlignToNext(n_namesz, 4));
+        if (cstr == NULL)
+        {
+            Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
+            if (log)
+                log->Printf("Failed to parse note name lacking nul terminator");
+
+            return false;
+        }
+        n_name = cstr;
+        return true;
+    }
+};
+
+// Parse a FreeBSD NT_PRSTATUS note - see FreeBSD sys/procfs.h for details.
+static void
+ParseFreeBSDPrStatus(ThreadData *thread_data, DataExtractor &data,
+                     ArchSpec &arch)
+{
+    lldb::offset_t offset = 0;
+    bool have_padding = (arch.GetMachine() == llvm::Triple::x86_64);
+    int pr_version = data.GetU32(&offset);
+
+    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
+    if (log)
+    {
+        if (pr_version > 1)
+            log->Printf("FreeBSD PRSTATUS unexpected version %d", pr_version);
+    }
+
+    if (have_padding)
+        offset += 4;
+    offset += 28;       // pr_statussz, pr_gregsetsz, pr_fpregsetsz, pr_osreldate
+    thread_data->signo = data.GetU32(&offset); // pr_cursig
+    offset += 4;        // pr_pid
+    if (have_padding)
+        offset += 4;
+    
+    size_t len = data.GetByteSize() - offset;
+    thread_data->gpregset = DataExtractor(data, offset, len);
+}
+
+static void
+ParseFreeBSDThrMisc(ThreadData *thread_data, DataExtractor &data)
+{
+    lldb::offset_t offset = 0;
+    thread_data->name = data.GetCStr(&offset, 20);
+}
+
+/// Parse Thread context from PT_NOTE segment and store it in the thread list
+/// Notes:
+/// 1) A PT_NOTE segment is composed of one or more NOTE entries.
+/// 2) NOTE Entry contains a standard header followed by variable size data.
+///   (see ELFNote structure)
+/// 3) A Thread Context in a core file usually described by 3 NOTE entries.
+///    a) NT_PRSTATUS - Register context
+///    b) NT_PRPSINFO - Process info(pid..)
+///    c) NT_FPREGSET - Floating point registers
+/// 4) The NOTE entries can be in any order
+/// 5) If a core file contains multiple thread contexts then there is two data forms
+///    a) Each thread context(2 or more NOTE entries) contained in its own segment (PT_NOTE)
+///    b) All thread context is stored in a single segment(PT_NOTE).
+///        This case is little tricker since while parsing we have to find where the
+///        new thread starts. The current implementation marks beginning of 
+///        new thread when it finds NT_PRSTATUS or NT_PRPSINFO NOTE entry.
+///    For case (b) there may be either one NT_PRPSINFO per thread, or a single
+///    one that applies to all threads (depending on the platform type).
+void
+ProcessElfCore::ParseThreadContextsFromNoteSegment(const elf::ELFProgramHeader *segment_header, 
+                                                   DataExtractor segment_data)
+{
+    assert(segment_header && segment_header->p_type == llvm::ELF::PT_NOTE);
+
+    lldb::offset_t offset = 0;
+    ThreadData *thread_data = new ThreadData();
+    bool have_prstatus = false;
+    bool have_prpsinfo = false;
+
+    ArchSpec arch = GetArchitecture();
+    ELFLinuxPrPsInfo prpsinfo;
+    ELFLinuxPrStatus prstatus;
+    size_t header_size;
+    size_t len;
+
+    // Loop through the NOTE entires in the segment
+    while (offset < segment_header->p_filesz)
+    {
+        ELFNote note = ELFNote();
+        note.Parse(segment_data, &offset);
+
+        // Beginning of new thread
+        if ((note.n_type == NT_PRSTATUS && have_prstatus) ||
+            (note.n_type == NT_PRPSINFO && have_prpsinfo))
+        {
+            assert(thread_data->gpregset.GetByteSize() > 0);
+            // Add the new thread to thread list
+            m_thread_data.push_back(*thread_data);
+            thread_data = new ThreadData();
+            have_prstatus = false;
+            have_prpsinfo = false;
+        }
+
+        size_t note_start, note_size;
+        note_start = offset;
+        note_size = AlignToNext(note.n_descsz, 4);
+
+        // Store the NOTE information in the current thread
+        DataExtractor note_data (segment_data, note_start, note_size);
+        if (note.n_name == "FreeBSD")
+        {
+            switch (note.n_type)
+            {
+                case NT_FREEBSD_PRSTATUS:
+                    have_prstatus = true;
+                    ParseFreeBSDPrStatus(thread_data, note_data, arch);
+                    break;
+                case NT_FREEBSD_FPREGSET:
+                    thread_data->fpregset = note_data;
+                    break;
+                case NT_FREEBSD_PRPSINFO:
+                    have_prpsinfo = true;
+                    break;
+                case NT_FREEBSD_THRMISC:
+                    ParseFreeBSDThrMisc(thread_data, note_data);
+                    break;
+                case NT_FREEBSD_PROCSTAT_AUXV:
+                    // FIXME: FreeBSD sticks an int at the beginning of the note
+                    m_auxv = DataExtractor(segment_data, note_start + 4, note_size - 4);
+                    break;
+                default:
+                    break;
+            }
+        }
+        else
+        {
+            switch (note.n_type)
+            {
+                case NT_PRSTATUS:
+                    have_prstatus = true;
+                    prstatus.Parse(note_data, arch);
+                    thread_data->signo = prstatus.pr_cursig;
+                    header_size = ELFLinuxPrStatus::GetSize(arch);
+                    len = note_data.GetByteSize() - header_size;
+                    thread_data->gpregset = DataExtractor(note_data, header_size, len);
+                    break;
+                case NT_FPREGSET:
+                    thread_data->fpregset = note_data;
+                    break;
+                case NT_PRPSINFO:
+                    have_prpsinfo = true;
+                    prpsinfo.Parse(note_data, arch);
+                    thread_data->name = prpsinfo.pr_fname;
+                    break;
+                case NT_AUXV:
+                    m_auxv = DataExtractor(note_data);
+                    break;
+                default:
+                    break;
+            }
+        }
+
+        offset += note_size;
+    }
+    // Add last entry in the note section
+    if (thread_data && thread_data->gpregset.GetByteSize() > 0)
+    {
+        m_thread_data.push_back(*thread_data);
+    }
+}
+
+uint32_t
+ProcessElfCore::GetNumThreadContexts ()
+{
+    if (!m_thread_data_valid)
+        DoLoadCore();
+    return m_thread_data.size();
+}
+
+ArchSpec
+ProcessElfCore::GetArchitecture()
+{
+    ObjectFileELF *core_file = (ObjectFileELF *)(m_core_module_sp->GetObjectFile());
+    ArchSpec arch;
+    core_file->GetArchitecture(arch);
+    return arch;
+}
+
+const lldb::DataBufferSP
+ProcessElfCore::GetAuxvData()
+{
+    const uint8_t *start = m_auxv.GetDataStart();
+    size_t len = m_auxv.GetByteSize();
+    lldb::DataBufferSP buffer(new lldb_private::DataBufferHeap(start, len));
+    return buffer;
+}
+
diff --git a/source/Plugins/Process/elf-core/ProcessElfCore.h b/source/Plugins/Process/elf-core/ProcessElfCore.h
new file mode 100644
index 000000000000..1c1ed98ce17a
--- /dev/null
+++ b/source/Plugins/Process/elf-core/ProcessElfCore.h
@@ -0,0 +1,171 @@
+//===-- ProcessElfCore.h ---------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+// Notes about Linux Process core dumps:
+//  1) Linux core dump is stored as ELF file.
+//  2) The ELF file's PT_NOTE and PT_LOAD segments describes the program's
+//     address space and thread contexts.
+//  3) PT_NOTE segment contains note entries which describes a thread context.
+//  4) PT_LOAD segment describes a valid contigous range of process address
+//     space.
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ProcessElfCore_h_
+#define liblldb_ProcessElfCore_h_
+
+// C++ Includes
+#include <list>
+#include <vector>
+
+// Other libraries and framework includes
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Target/Process.h"
+
+#include "Plugins/ObjectFile/ELF/ELFHeader.h"
+
+struct ThreadData;
+
+class ProcessElfCore : public lldb_private::Process
+{
+public:
+    //------------------------------------------------------------------
+    // Constructors and Destructors
+    //------------------------------------------------------------------
+    static lldb::ProcessSP
+    CreateInstance (lldb_private::Target& target, 
+                    lldb_private::Listener &listener, 
+                    const lldb_private::FileSpec *crash_file_path);
+    
+    static void
+    Initialize();
+    
+    static void
+    Terminate();
+    
+    static lldb_private::ConstString
+    GetPluginNameStatic();
+    
+    static const char *
+    GetPluginDescriptionStatic();
+    
+    //------------------------------------------------------------------
+    // Constructors and Destructors
+    //------------------------------------------------------------------
+    ProcessElfCore(lldb_private::Target& target, 
+                    lldb_private::Listener &listener,
+                    const lldb_private::FileSpec &core_file);
+    
+    virtual
+    ~ProcessElfCore();
+    
+    //------------------------------------------------------------------
+    // Check if a given Process
+    //------------------------------------------------------------------
+    virtual bool
+    CanDebug (lldb_private::Target &target,
+              bool plugin_specified_by_name);
+    
+    //------------------------------------------------------------------
+    // Creating a new process, or attaching to an existing one
+    //------------------------------------------------------------------
+    virtual lldb_private::Error
+    DoLoadCore ();
+    
+    virtual lldb_private::DynamicLoader *
+    GetDynamicLoader ();
+
+    //------------------------------------------------------------------
+    // PluginInterface protocol
+    //------------------------------------------------------------------
+    virtual lldb_private::ConstString
+    GetPluginName();
+    
+    virtual uint32_t
+    GetPluginVersion();
+    
+    //------------------------------------------------------------------
+    // Process Control
+    //------------------------------------------------------------------    
+    virtual lldb_private::Error
+    DoDestroy ();
+    
+    virtual void
+    RefreshStateAfterStop();
+    
+    //------------------------------------------------------------------
+    // Process Queries
+    //------------------------------------------------------------------
+    virtual bool
+    IsAlive ();
+
+    //------------------------------------------------------------------
+    // Process Memory
+    //------------------------------------------------------------------
+    virtual size_t
+    ReadMemory (lldb::addr_t addr, void *buf, size_t size, lldb_private::Error &error);
+    
+    virtual size_t
+    DoReadMemory (lldb::addr_t addr, void *buf, size_t size, lldb_private::Error &error);
+    
+    virtual lldb::addr_t
+    GetImageInfoAddress ();
+
+    lldb_private::ArchSpec
+    GetArchitecture();
+
+    // Returns AUXV structure found in the core file
+    const lldb::DataBufferSP
+    GetAuxvData();
+
+protected:
+    void
+    Clear ( );
+    
+    virtual bool
+    UpdateThreadList (lldb_private::ThreadList &old_thread_list, 
+                      lldb_private::ThreadList &new_thread_list);
+   
+private:
+    //------------------------------------------------------------------
+    // For ProcessElfCore only
+    //------------------------------------------------------------------
+    typedef lldb_private::Range<lldb::addr_t, lldb::addr_t> FileRange;
+    typedef lldb_private::RangeDataArray<lldb::addr_t, lldb::addr_t, FileRange, 1> VMRangeToFileOffset;
+
+    lldb::ModuleSP m_core_module_sp;
+    lldb_private::FileSpec m_core_file;
+    std::string  m_dyld_plugin_name;
+    DISALLOW_COPY_AND_ASSIGN (ProcessElfCore);
+
+    // True if m_thread_contexts contains valid entries
+    bool m_thread_data_valid;
+
+    // Contain thread data read from NOTE segments
+    std::vector<ThreadData> m_thread_data;
+
+    // AUXV structure found from the NOTE segment
+    lldb_private::DataExtractor m_auxv;
+
+    // Address ranges found in the core
+    VMRangeToFileOffset m_core_aranges;
+
+    // Parse thread(s) data structures(prstatus, prpsinfo) from given NOTE segment
+    void
+    ParseThreadContextsFromNoteSegment (const elf::ELFProgramHeader *segment_header,
+                                        lldb_private::DataExtractor segment_data);
+
+    // Returns number of thread contexts stored in the core file
+    uint32_t
+    GetNumThreadContexts();
+
+    // Parse a contiguous address range of the process from LOAD segment
+    lldb::addr_t
+    AddAddressRangeFromLoadSegment(const elf::ELFProgramHeader *header);
+};
+
+#endif  // liblldb_ProcessElffCore_h_
diff --git a/source/Plugins/Process/elf-core/RegisterContextCoreFreeBSD_x86_64.cpp b/source/Plugins/Process/elf-core/RegisterContextCoreFreeBSD_x86_64.cpp
new file mode 100644
index 000000000000..6210175f9a7f
--- /dev/null
+++ b/source/Plugins/Process/elf-core/RegisterContextCoreFreeBSD_x86_64.cpp
@@ -0,0 +1,68 @@
+//===-- RegisterContextCoreFreeBSD_x86_64.cpp -------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/RegisterValue.h"
+#include "lldb/Target/Thread.h"
+#include "RegisterContextCoreFreeBSD_x86_64.h"
+
+RegisterContextCoreFreeBSD_x86_64::RegisterContextCoreFreeBSD_x86_64(Thread &thread,
+                        const DataExtractor &gpregset, const DataExtractor &fpregset)
+    : RegisterContextFreeBSD_x86_64(thread, 0)
+{
+    size_t size, len;
+
+    size = GetGPRSize();
+    m_gpregset = new uint8_t[size];
+    len = gpregset.ExtractBytes(0, size, lldb::eByteOrderLittle, m_gpregset);
+    assert(len == size);
+}
+
+RegisterContextCoreFreeBSD_x86_64::~RegisterContextCoreFreeBSD_x86_64()
+{
+    delete [] m_gpregset;
+}
+
+bool
+RegisterContextCoreFreeBSD_x86_64::ReadRegister(const RegisterInfo *reg_info, RegisterValue &value)
+{
+    value = *(uint64_t *)(m_gpregset + reg_info->byte_offset);
+    return true;
+}
+
+bool
+RegisterContextCoreFreeBSD_x86_64::ReadAllRegisterValues(lldb::DataBufferSP &data_sp)
+{
+    return false;
+}
+
+bool
+RegisterContextCoreFreeBSD_x86_64::WriteRegister(const RegisterInfo *reg_info, const RegisterValue &value)
+{
+    return false;
+}
+
+bool
+RegisterContextCoreFreeBSD_x86_64::WriteAllRegisterValues(const lldb::DataBufferSP &data_sp)
+{
+    return false;
+}
+
+bool
+RegisterContextCoreFreeBSD_x86_64::UpdateAfterBreakpoint()
+{
+    return false;
+}
+
+bool
+RegisterContextCoreFreeBSD_x86_64::HardwareSingleStep(bool enable)
+{
+    return false;
+}
+
diff --git a/source/Plugins/Process/elf-core/RegisterContextCoreFreeBSD_x86_64.h b/source/Plugins/Process/elf-core/RegisterContextCoreFreeBSD_x86_64.h
new file mode 100644
index 000000000000..acd594a6e666
--- /dev/null
+++ b/source/Plugins/Process/elf-core/RegisterContextCoreFreeBSD_x86_64.h
@@ -0,0 +1,47 @@
+//===-- RegisterContextCoreFreeBSD_x86_64.h ----------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+
+#ifndef liblldb_RegisterContextCoreFreeBSD_x86_64_H_
+#define liblldb_RegisterContextCoreFreeBSD_x86_64_H_
+
+#include "Plugins/Process/POSIX/RegisterContextFreeBSD_x86_64.h"
+
+using namespace lldb_private;
+
+class RegisterContextCoreFreeBSD_x86_64: public RegisterContextFreeBSD_x86_64
+{
+public:
+    RegisterContextCoreFreeBSD_x86_64 (Thread &thread, const DataExtractor &gpregset,
+                                       const DataExtractor &fpregset);
+
+    ~RegisterContextCoreFreeBSD_x86_64();
+
+    virtual bool
+    ReadRegister(const RegisterInfo *reg_info, RegisterValue &value);
+
+    bool
+    ReadAllRegisterValues(lldb::DataBufferSP &data_sp);
+
+    virtual bool
+    WriteRegister(const RegisterInfo *reg_info, const RegisterValue &value);
+
+    bool
+    WriteAllRegisterValues(const lldb::DataBufferSP &data_sp);
+
+    bool
+    HardwareSingleStep(bool enable);
+
+    bool
+    UpdateAfterBreakpoint();
+
+private:
+    uint8_t *m_gpregset;
+};
+
+#endif // #ifndef liblldb_RegisterContextCoreFreeBSD_x86_64_H_
diff --git a/source/Plugins/Process/elf-core/RegisterContextCoreLinux_x86_64.cpp b/source/Plugins/Process/elf-core/RegisterContextCoreLinux_x86_64.cpp
new file mode 100644
index 000000000000..d9e3f6d5f90b
--- /dev/null
+++ b/source/Plugins/Process/elf-core/RegisterContextCoreLinux_x86_64.cpp
@@ -0,0 +1,68 @@
+//===-- RegisterContextCoreLinux_x86_64.cpp -------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/RegisterValue.h"
+#include "lldb/Target/Thread.h"
+#include "RegisterContextCoreLinux_x86_64.h"
+
+RegisterContextCoreLinux_x86_64::RegisterContextCoreLinux_x86_64(Thread &thread,
+                                                const DataExtractor &gpregset,
+                                                const DataExtractor &fpregset)
+    : RegisterContextLinux_x86_64(thread, 0)
+{
+    size_t size, len;
+
+    size = GetGPRSize();
+    m_gpregset = new uint8_t[size];
+    len = gpregset.ExtractBytes(0, size, lldb::eByteOrderLittle, m_gpregset);
+    assert(len == size);
+}
+
+RegisterContextCoreLinux_x86_64::~RegisterContextCoreLinux_x86_64()
+{
+    delete [] m_gpregset;
+}
+
+bool
+RegisterContextCoreLinux_x86_64::ReadRegister(const RegisterInfo *reg_info, RegisterValue &value)
+{
+    value = *(uint64_t *)(m_gpregset + reg_info->byte_offset);
+    return true;
+}
+
+bool
+RegisterContextCoreLinux_x86_64::ReadAllRegisterValues(lldb::DataBufferSP &data_sp)
+{
+    return false;
+}
+
+bool
+RegisterContextCoreLinux_x86_64::WriteRegister(const RegisterInfo *reg_info, const RegisterValue &value)
+{
+    return false;
+}
+
+bool
+RegisterContextCoreLinux_x86_64::WriteAllRegisterValues(const lldb::DataBufferSP &data_sp)
+{
+    return false;
+}
+
+bool
+RegisterContextCoreLinux_x86_64::UpdateAfterBreakpoint()
+{
+    return false;
+}
+
+bool
+RegisterContextCoreLinux_x86_64::HardwareSingleStep(bool enable)
+{
+    return false;
+}
diff --git a/source/Plugins/Process/elf-core/RegisterContextCoreLinux_x86_64.h b/source/Plugins/Process/elf-core/RegisterContextCoreLinux_x86_64.h
new file mode 100644
index 000000000000..9cf545afd56a
--- /dev/null
+++ b/source/Plugins/Process/elf-core/RegisterContextCoreLinux_x86_64.h
@@ -0,0 +1,54 @@
+//===-- RegisterContextCoreLinux_x86_64.h ----------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+
+#ifndef liblldb_RegisterContextCoreLinux_x86_64_H_
+#define liblldb_RegisterContextCoreLinux_x86_64_H_
+
+#include "Plugins/Process/POSIX/RegisterContextLinux_x86_64.h"
+
+using namespace lldb_private;
+
+class RegisterContextCoreLinux_x86_64: public RegisterContextLinux_x86_64
+{
+public:
+    RegisterContextCoreLinux_x86_64 (Thread &thread, const DataExtractor &gpregset,
+                                     const DataExtractor &fpregset);
+
+    ~RegisterContextCoreLinux_x86_64();
+
+    virtual bool
+    ReadRegister(const RegisterInfo *reg_info, RegisterValue &value);
+
+    bool
+    ReadAllRegisterValues(lldb::DataBufferSP &data_sp);
+
+    virtual bool
+    WriteRegister(const RegisterInfo *reg_info, const RegisterValue &value);
+
+    bool
+    WriteAllRegisterValues(const lldb::DataBufferSP &data_sp);
+
+    bool
+    HardwareSingleStep(bool enable);
+
+    bool
+    UpdateAfterBreakpoint();
+
+protected:
+    bool
+    ReadFPR()
+    {
+        assert(0);
+    }
+
+private:
+    uint8_t *m_gpregset;
+};
+
+#endif // #ifndef liblldb_RegisterContextCoreLinux_x86_64_H_
diff --git a/source/Plugins/Process/elf-core/ThreadElfCore.cpp b/source/Plugins/Process/elf-core/ThreadElfCore.cpp
new file mode 100644
index 000000000000..a7229663dc89
--- /dev/null
+++ b/source/Plugins/Process/elf-core/ThreadElfCore.cpp
@@ -0,0 +1,176 @@
+//===-- ThreadElfCore.cpp --------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/StopInfo.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Unwind.h"
+#include "ProcessPOSIXLog.h"
+
+#include "ThreadElfCore.h"
+#include "ProcessElfCore.h"
+#include "RegisterContextCoreFreeBSD_x86_64.h"
+#include "RegisterContextCoreLinux_x86_64.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// Construct a Thread object with given data
+//----------------------------------------------------------------------
+ThreadElfCore::ThreadElfCore (Process &process, tid_t tid,
+                              const ThreadData &td) :
+    Thread(process, tid),
+    m_thread_name(td.name),
+    m_thread_reg_ctx_sp (),
+    m_signo(td.signo),
+    m_gpregset_data(td.gpregset),
+    m_fpregset_data(td.fpregset)
+{
+}
+
+ThreadElfCore::~ThreadElfCore ()
+{
+    DestroyThread();
+}
+
+void
+ThreadElfCore::RefreshStateAfterStop()
+{
+    GetRegisterContext()->InvalidateIfNeeded (false);
+}
+
+void
+ThreadElfCore::ClearStackFrames ()
+{
+    Unwind *unwinder = GetUnwinder ();
+    if (unwinder)
+        unwinder->Clear();
+    Thread::ClearStackFrames();
+}
+
+RegisterContextSP
+ThreadElfCore::GetRegisterContext ()
+{
+    if (m_reg_context_sp.get() == NULL) {
+        m_reg_context_sp = CreateRegisterContextForFrame (NULL);
+    }
+    return m_reg_context_sp;
+}
+
+RegisterContextSP
+ThreadElfCore::CreateRegisterContextForFrame (StackFrame *frame)
+{
+    RegisterContextSP reg_ctx_sp;
+    uint32_t concrete_frame_idx = 0;
+    Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
+
+    if (frame)
+        concrete_frame_idx = frame->GetConcreteFrameIndex ();
+
+    if (concrete_frame_idx == 0)
+    {
+        if (m_thread_reg_ctx_sp)
+            return m_thread_reg_ctx_sp;
+
+        ProcessElfCore *process = static_cast<ProcessElfCore *>(GetProcess().get());
+        ArchSpec arch = process->GetArchitecture();
+        switch (arch.GetMachine())
+        {
+            case llvm::Triple::x86_64:
+                switch (arch.GetTriple().getOS())
+                {
+                    case llvm::Triple::FreeBSD:
+                        m_thread_reg_ctx_sp.reset(new RegisterContextCoreFreeBSD_x86_64 (*this, m_gpregset_data, m_fpregset_data));
+                        break;
+                    case llvm::Triple::Linux:
+                        m_thread_reg_ctx_sp.reset(new RegisterContextCoreLinux_x86_64 (*this, m_gpregset_data, m_fpregset_data));
+                        break;
+                    default:
+                        if (log)
+                            log->Printf ("elf-core::%s:: OS(%d) not supported",
+                                         __FUNCTION__, arch.GetTriple().getOS());
+                        assert (false && "OS not supported");
+                        break;
+                }
+                break;
+            default:
+                if (log)
+                    log->Printf ("elf-core::%s:: Architecture(%d) not supported",
+                                 __FUNCTION__, arch.GetMachine());
+                assert (false && "Architecture not supported");
+        }
+        reg_ctx_sp = m_thread_reg_ctx_sp;
+    }
+    else if (m_unwinder_ap.get())
+    {
+        reg_ctx_sp = m_unwinder_ap->CreateRegisterContextForFrame (frame);
+    }
+    return reg_ctx_sp;
+}
+
+bool
+ThreadElfCore::CalculateStopInfo ()
+{
+    ProcessSP process_sp (GetProcess());
+    if (process_sp)
+    {
+        SetStopInfo(StopInfo::CreateStopReasonWithSignal (*this, m_signo));
+        return true;
+    }
+    return false;
+}
+
+//----------------------------------------------------------------
+// Parse PRSTATUS from NOTE entry
+//----------------------------------------------------------------
+ELFLinuxPrStatus::ELFLinuxPrStatus()
+{
+    memset(this, 0, sizeof(ELFLinuxPrStatus));
+}
+
+bool
+ELFLinuxPrStatus::Parse(DataExtractor &data, ArchSpec &arch)
+{
+    ByteOrder byteorder = data.GetByteOrder();
+    size_t len;
+    switch(arch.GetCore())
+    {
+        case ArchSpec::eCore_x86_64_x86_64:
+            len = data.ExtractBytes(0, ELFLINUXPRSTATUS64_SIZE, byteorder, this);
+            return len == ELFLINUXPRSTATUS64_SIZE;
+        default:
+            return false;
+    }
+}
+
+//----------------------------------------------------------------
+// Parse PRPSINFO from NOTE entry
+//----------------------------------------------------------------
+ELFLinuxPrPsInfo::ELFLinuxPrPsInfo()
+{
+    memset(this, 0, sizeof(ELFLinuxPrPsInfo));
+}
+
+bool
+ELFLinuxPrPsInfo::Parse(DataExtractor &data, ArchSpec &arch)
+{
+    ByteOrder byteorder = data.GetByteOrder();
+    size_t len;
+    switch(arch.GetCore())
+    {
+        case ArchSpec::eCore_x86_64_x86_64:
+            len = data.ExtractBytes(0, ELFLINUXPRPSINFO64_SIZE, byteorder, this);
+            return len == ELFLINUXPRPSINFO64_SIZE;
+        default:
+            return false;
+    }
+}
+
diff --git a/source/Plugins/Process/elf-core/ThreadElfCore.h b/source/Plugins/Process/elf-core/ThreadElfCore.h
new file mode 100644
index 000000000000..ca6339d7ec9d
--- /dev/null
+++ b/source/Plugins/Process/elf-core/ThreadElfCore.h
@@ -0,0 +1,174 @@
+//===-- ThreadElfCore.h ----------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ThreadElfCore_h_
+#define liblldb_ThreadElfCore_h_
+
+#include <string>
+
+#include "lldb/Target/Thread.h"
+#include "lldb/Core/DataExtractor.h"
+
+struct compat_timeval
+{
+    int64_t tv_sec;
+    int32_t tv_usec;
+};
+
+// PRSTATUS structure's size differs based on architecture.
+// Currently parsing done only for x86-64 architecture by
+// simply reading data from the buffer.
+// The following macros are used to specify the size.
+// Calculating size using sizeof() wont work because of padding.
+#define ELFLINUXPRSTATUS64_SIZE (112)
+#define ELFLINUXPRPSINFO64_SIZE (132)
+
+struct ELFLinuxPrStatus
+{
+    int32_t         si_signo;
+    int32_t         si_code;
+    int32_t         si_errno;
+
+    int16_t         pr_cursig;
+    
+    uint64_t        pr_sigpend;
+    uint64_t        pr_sighold;
+
+    uint32_t        pr_pid;
+    uint32_t        pr_ppid;
+    uint32_t        pr_pgrp;
+    uint32_t        pr_sid;
+
+    compat_timeval  pr_utime;
+    compat_timeval  pr_stime;
+    compat_timeval  pr_cutime;
+    compat_timeval  pr_cstime;
+
+    ELFLinuxPrStatus();
+
+    bool
+    Parse(lldb_private::DataExtractor &data, lldb_private::ArchSpec &arch);
+
+    static size_t
+    GetSize(lldb_private::ArchSpec &arch)
+    {
+        switch(arch.GetCore())
+        {
+            case lldb_private::ArchSpec::eCore_x86_64_x86_64:
+                return ELFLINUXPRSTATUS64_SIZE;
+            default:
+                return 0;
+        }
+    }
+};
+
+struct ELFLinuxPrPsInfo
+{
+    char        pr_state;
+    char        pr_sname;
+    char        pr_zomb;
+    char        pr_nice;
+    uint64_t    pr_flag;
+    uint32_t    pr_uid;
+    uint32_t    pr_gid;
+    int32_t     pr_pid;
+    int32_t     pr_ppid;
+    int32_t     pr_pgrp;
+    int32_t     pr_sid;
+    char        pr_fname[16];
+    char        pr_psargs[80];
+
+    ELFLinuxPrPsInfo();
+
+    bool
+    Parse(lldb_private::DataExtractor &data, lldb_private::ArchSpec &arch);
+
+    static size_t
+    GetSize(lldb_private::ArchSpec &arch)
+    {
+        switch(arch.GetCore())
+        {
+            case lldb_private::ArchSpec::eCore_x86_64_x86_64:
+                return ELFLINUXPRPSINFO64_SIZE;
+            default:
+                return 0;
+        }
+    }
+
+};
+
+struct ThreadData
+{
+    lldb_private::DataExtractor gpregset;
+    lldb_private::DataExtractor fpregset;
+    int signo;
+    std::string name;
+};
+
+class ThreadElfCore : public lldb_private::Thread
+{
+public:
+    ThreadElfCore (lldb_private::Process &process, lldb::tid_t tid,
+                   const ThreadData &td);
+
+    virtual
+    ~ThreadElfCore ();
+
+    virtual void
+    RefreshStateAfterStop();
+
+    virtual lldb::RegisterContextSP
+    GetRegisterContext ();
+
+    virtual lldb::RegisterContextSP
+    CreateRegisterContextForFrame (lldb_private::StackFrame *frame);
+
+    virtual void
+    ClearStackFrames ();
+
+    static bool
+    ThreadIDIsValid (lldb::tid_t thread)
+    {
+        return thread != 0;
+    }
+
+    virtual const char *
+    GetName ()
+    {
+        if (m_thread_name.empty())
+            return NULL;
+        return m_thread_name.c_str();
+    }
+
+    void
+    SetName (const char *name)
+    {
+        if (name && name[0])
+            m_thread_name.assign (name);
+        else
+            m_thread_name.clear();
+    }
+
+protected:
+    //------------------------------------------------------------------
+    // Member variables.
+    //------------------------------------------------------------------
+    std::string m_thread_name;
+    lldb::RegisterContextSP m_thread_reg_ctx_sp;
+
+    int m_signo;
+
+    lldb_private::DataExtractor m_gpregset_data;
+    lldb_private::DataExtractor m_fpregset_data;
+
+    virtual bool CalculateStopInfo();
+
+};
+
+#endif  // liblldb_ThreadElfCore_h_
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
new file mode 100644
index 000000000000..d7efdf2302d8
--- /dev/null
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
@@ -0,0 +1,643 @@
+//===-- GDBRemoteCommunication.cpp ------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+
+#include "GDBRemoteCommunication.h"
+
+// C Includes
+#include <limits.h>
+#include <string.h>
+
+// C++ Includes
+// Other libraries and framework includes
+#include "lldb/Core/Log.h"
+#include "lldb/Core/StreamFile.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Host/FileSpec.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Host/TimeValue.h"
+#include "lldb/Target/Process.h"
+
+// Project includes
+#include "ProcessGDBRemoteLog.h"
+
+#define DEBUGSERVER_BASENAME    "debugserver"
+
+using namespace lldb;
+using namespace lldb_private;
+
+GDBRemoteCommunication::History::History (uint32_t size) :
+    m_packets(),
+    m_curr_idx (0),
+    m_total_packet_count (0),
+    m_dumped_to_log (false)
+{
+    m_packets.resize(size);
+}
+
+GDBRemoteCommunication::History::~History ()
+{
+}
+
+void
+GDBRemoteCommunication::History::AddPacket (char packet_char,
+                                            PacketType type,
+                                            uint32_t bytes_transmitted)
+{
+    const size_t size = m_packets.size();
+    if (size > 0)
+    {
+        const uint32_t idx = GetNextIndex();
+        m_packets[idx].packet.assign (1, packet_char);
+        m_packets[idx].type = type;
+        m_packets[idx].bytes_transmitted = bytes_transmitted;
+        m_packets[idx].packet_idx = m_total_packet_count;
+        m_packets[idx].tid = Host::GetCurrentThreadID();
+    }
+}
+
+void
+GDBRemoteCommunication::History::AddPacket (const std::string &src,
+                                            uint32_t src_len,
+                                            PacketType type,
+                                            uint32_t bytes_transmitted)
+{
+    const size_t size = m_packets.size();
+    if (size > 0)
+    {
+        const uint32_t idx = GetNextIndex();
+        m_packets[idx].packet.assign (src, 0, src_len);
+        m_packets[idx].type = type;
+        m_packets[idx].bytes_transmitted = bytes_transmitted;
+        m_packets[idx].packet_idx = m_total_packet_count;
+        m_packets[idx].tid = Host::GetCurrentThreadID();
+    }
+}
+
+void
+GDBRemoteCommunication::History::Dump (lldb_private::Stream &strm) const
+{
+    const uint32_t size = GetNumPacketsInHistory ();
+    const uint32_t first_idx = GetFirstSavedPacketIndex ();
+    const uint32_t stop_idx = m_curr_idx + size;
+    for (uint32_t i = first_idx;  i < stop_idx; ++i)
+    {
+        const uint32_t idx = NormalizeIndex (i);
+        const Entry &entry = m_packets[idx];
+        if (entry.type == ePacketTypeInvalid || entry.packet.empty())
+            break;
+        strm.Printf ("history[%u] tid=0x%4.4" PRIx64 " <%4u> %s packet: %s\n",
+                     entry.packet_idx,
+                     entry.tid,
+                     entry.bytes_transmitted,
+                     (entry.type == ePacketTypeSend) ? "send" : "read",
+                     entry.packet.c_str());
+    }
+}
+
+void
+GDBRemoteCommunication::History::Dump (lldb_private::Log *log) const
+{
+    if (log && !m_dumped_to_log)
+    {
+        m_dumped_to_log = true;
+        const uint32_t size = GetNumPacketsInHistory ();
+        const uint32_t first_idx = GetFirstSavedPacketIndex ();
+        const uint32_t stop_idx = m_curr_idx + size;
+        for (uint32_t i = first_idx;  i < stop_idx; ++i)
+        {
+            const uint32_t idx = NormalizeIndex (i);
+            const Entry &entry = m_packets[idx];
+            if (entry.type == ePacketTypeInvalid || entry.packet.empty())
+                break;
+            log->Printf ("history[%u] tid=0x%4.4" PRIx64 " <%4u> %s packet: %s",
+                         entry.packet_idx,
+                         entry.tid,
+                         entry.bytes_transmitted,
+                         (entry.type == ePacketTypeSend) ? "send" : "read",
+                         entry.packet.c_str());
+        }
+    }
+}
+
+//----------------------------------------------------------------------
+// GDBRemoteCommunication constructor
+//----------------------------------------------------------------------
+GDBRemoteCommunication::GDBRemoteCommunication(const char *comm_name, 
+                                               const char *listener_name, 
+                                               bool is_platform) :
+    Communication(comm_name),
+    m_packet_timeout (1),
+    m_sequence_mutex (Mutex::eMutexTypeRecursive),
+    m_public_is_running (false),
+    m_private_is_running (false),
+    m_history (512),
+    m_send_acks (true),
+    m_is_platform (is_platform)
+{
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+GDBRemoteCommunication::~GDBRemoteCommunication()
+{
+    if (IsConnected())
+    {
+        Disconnect();
+    }
+}
+
+char
+GDBRemoteCommunication::CalculcateChecksum (const char *payload, size_t payload_length)
+{
+    int checksum = 0;
+
+    for (size_t i = 0; i < payload_length; ++i)
+        checksum += payload[i];
+
+    return checksum & 255;
+}
+
+size_t
+GDBRemoteCommunication::SendAck ()
+{
+    Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
+    ConnectionStatus status = eConnectionStatusSuccess;
+    char ch = '+';
+    const size_t bytes_written = Write (&ch, 1, status, NULL);
+    if (log)
+        log->Printf ("<%4zu> send packet: %c", bytes_written, ch);
+    m_history.AddPacket (ch, History::ePacketTypeSend, bytes_written);
+    return bytes_written;
+}
+
+size_t
+GDBRemoteCommunication::SendNack ()
+{
+    Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
+    ConnectionStatus status = eConnectionStatusSuccess;
+    char ch = '-';
+    const size_t bytes_written = Write (&ch, 1, status, NULL);
+    if (log)
+        log->Printf ("<%4zu> send packet: %c", bytes_written, ch);
+    m_history.AddPacket (ch, History::ePacketTypeSend, bytes_written);
+    return bytes_written;
+}
+
+size_t
+GDBRemoteCommunication::SendPacket (const char *payload, size_t payload_length)
+{
+    Mutex::Locker locker(m_sequence_mutex);
+    return SendPacketNoLock (payload, payload_length);
+}
+
+size_t
+GDBRemoteCommunication::SendPacketNoLock (const char *payload, size_t payload_length)
+{
+    if (IsConnected())
+    {
+        StreamString packet(0, 4, eByteOrderBig);
+
+        packet.PutChar('$');
+        packet.Write (payload, payload_length);
+        packet.PutChar('#');
+        packet.PutHex8(CalculcateChecksum (payload, payload_length));
+
+        Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
+        ConnectionStatus status = eConnectionStatusSuccess;
+        size_t bytes_written = Write (packet.GetData(), packet.GetSize(), status, NULL);
+        if (log)
+        {
+            // If logging was just enabled and we have history, then dump out what
+            // we have to the log so we get the historical context. The Dump() call that
+            // logs all of the packet will set a boolean so that we don't dump this more
+            // than once
+            if (!m_history.DidDumpToLog ())
+                m_history.Dump (log);
+
+            log->Printf ("<%4zu> send packet: %.*s", bytes_written, (int)packet.GetSize(), packet.GetData());
+        }
+
+        m_history.AddPacket (packet.GetString(), packet.GetSize(), History::ePacketTypeSend, bytes_written);
+
+
+        if (bytes_written == packet.GetSize())
+        {
+            if (GetSendAcks ())
+            {
+                if (GetAck () != '+')
+                {
+                    if (log)
+                        log->Printf("get ack failed...");
+                    return 0;
+                }
+            }
+        }
+        else
+        {
+            if (log)
+                log->Printf ("error: failed to send packet: %.*s", (int)packet.GetSize(), packet.GetData());
+        }
+        return bytes_written;
+    }
+    return 0;
+}
+
+char
+GDBRemoteCommunication::GetAck ()
+{
+    StringExtractorGDBRemote packet;
+    if (WaitForPacketWithTimeoutMicroSecondsNoLock (packet, GetPacketTimeoutInMicroSeconds ()) == 1)
+        return packet.GetChar();
+    return 0;
+}
+
+bool
+GDBRemoteCommunication::GetSequenceMutex (Mutex::Locker& locker, const char *failure_message)
+{
+    if (IsRunning())
+        return locker.TryLock (m_sequence_mutex, failure_message);
+
+    locker.Lock (m_sequence_mutex);
+    return true;
+}
+
+
+bool
+GDBRemoteCommunication::WaitForNotRunningPrivate (const TimeValue *timeout_ptr)
+{
+    return m_private_is_running.WaitForValueEqualTo (false, timeout_ptr, NULL);
+}
+
+size_t
+GDBRemoteCommunication::WaitForPacketWithTimeoutMicroSecondsNoLock (StringExtractorGDBRemote &packet, uint32_t timeout_usec)
+{
+    uint8_t buffer[8192];
+    Error error;
+
+    Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS | GDBR_LOG_VERBOSE));
+
+    // Check for a packet from our cache first without trying any reading...
+    if (CheckForPacket (NULL, 0, packet))
+        return packet.GetStringRef().size();
+
+    bool timed_out = false;
+    while (IsConnected() && !timed_out)
+    {
+        lldb::ConnectionStatus status = eConnectionStatusNoConnection;
+        size_t bytes_read = Read (buffer, sizeof(buffer), timeout_usec, status, &error);
+        
+        if (log)
+            log->Printf ("%s: Read (buffer, (sizeof(buffer), timeout_usec = 0x%x, status = %s, error = %s) => bytes_read = %" PRIu64,
+                         __PRETTY_FUNCTION__,
+                         timeout_usec, 
+                         Communication::ConnectionStatusAsCString (status),
+                         error.AsCString(), 
+                         (uint64_t)bytes_read);
+
+        if (bytes_read > 0)
+        {
+            if (CheckForPacket (buffer, bytes_read, packet))
+                return packet.GetStringRef().size();
+        }
+        else
+        {
+            switch (status)
+            {
+            case eConnectionStatusTimedOut:
+                timed_out = true;
+                break;
+            case eConnectionStatusSuccess:
+                //printf ("status = success but error = %s\n", error.AsCString("<invalid>"));
+                break;
+                
+            case eConnectionStatusEndOfFile:
+            case eConnectionStatusNoConnection:
+            case eConnectionStatusLostConnection:
+            case eConnectionStatusError:
+                Disconnect();
+                break;
+            }
+        }
+    }
+    packet.Clear ();    
+    return 0;
+}
+
+bool
+GDBRemoteCommunication::CheckForPacket (const uint8_t *src, size_t src_len, StringExtractorGDBRemote &packet)
+{
+    // Put the packet data into the buffer in a thread safe fashion
+    Mutex::Locker locker(m_bytes_mutex);
+    
+    Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
+
+    if (src && src_len > 0)
+    {
+        if (log && log->GetVerbose())
+        {
+            StreamString s;
+            log->Printf ("GDBRemoteCommunication::%s adding %u bytes: %.*s",
+                         __FUNCTION__, 
+                         (uint32_t)src_len, 
+                         (uint32_t)src_len, 
+                         src);
+        }
+        m_bytes.append ((const char *)src, src_len);
+    }
+
+    // Parse up the packets into gdb remote packets
+    if (!m_bytes.empty())
+    {
+        // end_idx must be one past the last valid packet byte. Start
+        // it off with an invalid value that is the same as the current
+        // index.
+        size_t content_start = 0;
+        size_t content_length = 0;
+        size_t total_length = 0;
+        size_t checksum_idx = std::string::npos;
+
+        switch (m_bytes[0])
+        {
+            case '+':       // Look for ack
+            case '-':       // Look for cancel
+            case '\x03':    // ^C to halt target
+                content_length = total_length = 1;  // The command is one byte long...
+                break;
+
+            case '$':
+                // Look for a standard gdb packet?
+                {
+                    size_t hash_pos = m_bytes.find('#');
+                    if (hash_pos != std::string::npos)
+                    {
+                        if (hash_pos + 2 < m_bytes.size())
+                        {
+                            checksum_idx = hash_pos + 1;
+                            // Skip the dollar sign
+                            content_start = 1; 
+                            // Don't include the # in the content or the $ in the content length
+                            content_length = hash_pos - 1;  
+                            
+                            total_length = hash_pos + 3; // Skip the # and the two hex checksum bytes
+                        }
+                        else
+                        {
+                            // Checksum bytes aren't all here yet
+                            content_length = std::string::npos;
+                        }
+                    }
+                }
+                break;
+
+            default:
+                {
+                    // We have an unexpected byte and we need to flush all bad 
+                    // data that is in m_bytes, so we need to find the first
+                    // byte that is a '+' (ACK), '-' (NACK), \x03 (CTRL+C interrupt),
+                    // or '$' character (start of packet header) or of course,
+                    // the end of the data in m_bytes...
+                    const size_t bytes_len = m_bytes.size();
+                    bool done = false;
+                    uint32_t idx;
+                    for (idx = 1; !done && idx < bytes_len; ++idx)
+                    {
+                        switch (m_bytes[idx])
+                        {
+                        case '+':
+                        case '-':
+                        case '\x03':
+                        case '$':
+                            done = true;
+                            break;
+                                
+                        default:
+                            break;
+                        }
+                    }
+                    if (log)
+                        log->Printf ("GDBRemoteCommunication::%s tossing %u junk bytes: '%.*s'",
+                                     __FUNCTION__, idx, idx, m_bytes.c_str());
+                    m_bytes.erase(0, idx);
+                }
+                break;
+        }
+
+        if (content_length == std::string::npos)
+        {
+            packet.Clear();
+            return false;
+        }
+        else if (total_length > 0)
+        {
+
+            // We have a valid packet...
+            assert (content_length <= m_bytes.size());
+            assert (total_length <= m_bytes.size());
+            assert (content_length <= total_length);
+            
+            bool success = true;
+            std::string &packet_str = packet.GetStringRef();
+            
+            
+            if (log)
+            {
+                // If logging was just enabled and we have history, then dump out what
+                // we have to the log so we get the historical context. The Dump() call that
+                // logs all of the packet will set a boolean so that we don't dump this more
+                // than once
+                if (!m_history.DidDumpToLog ())
+                    m_history.Dump (log);
+                
+                log->Printf ("<%4zu> read packet: %.*s", total_length, (int)(total_length), m_bytes.c_str());
+            }
+
+            m_history.AddPacket (m_bytes.c_str(), total_length, History::ePacketTypeRecv, total_length);
+
+            packet_str.assign (m_bytes, content_start, content_length);
+            
+            if (m_bytes[0] == '$')
+            {
+                assert (checksum_idx < m_bytes.size());
+                if (::isxdigit (m_bytes[checksum_idx+0]) || 
+                    ::isxdigit (m_bytes[checksum_idx+1]))
+                {
+                    if (GetSendAcks ())
+                    {
+                        const char *packet_checksum_cstr = &m_bytes[checksum_idx];
+                        char packet_checksum = strtol (packet_checksum_cstr, NULL, 16);
+                        char actual_checksum = CalculcateChecksum (packet_str.c_str(), packet_str.size());
+                        success = packet_checksum == actual_checksum;
+                        if (!success)
+                        {
+                            if (log)
+                                log->Printf ("error: checksum mismatch: %.*s expected 0x%2.2x, got 0x%2.2x", 
+                                             (int)(total_length), 
+                                             m_bytes.c_str(),
+                                             (uint8_t)packet_checksum,
+                                             (uint8_t)actual_checksum);
+                        }
+                        // Send the ack or nack if needed
+                        if (!success)
+                            SendNack();
+                        else
+                            SendAck();
+                    }
+                }
+                else
+                {
+                    success = false;
+                    if (log)
+                        log->Printf ("error: invalid checksum in packet: '%s'\n", m_bytes.c_str());
+                }
+            }
+            
+            m_bytes.erase(0, total_length);
+            packet.SetFilePos(0);
+            return success;
+        }
+    }
+    packet.Clear();
+    return false;
+}
+
+Error
+GDBRemoteCommunication::StartDebugserverProcess (const char *debugserver_url,
+                                                 const char *unix_socket_name,  // For handshaking
+                                                 lldb_private::ProcessLaunchInfo &launch_info)
+{
+    Error error;
+    // If we locate debugserver, keep that located version around
+    static FileSpec g_debugserver_file_spec;
+    
+    // This function will fill in the launch information for the debugserver
+    // instance that gets launched.
+    launch_info.Clear();
+    
+    char debugserver_path[PATH_MAX];
+    FileSpec &debugserver_file_spec = launch_info.GetExecutableFile();
+    
+    // Always check to see if we have an environment override for the path
+    // to the debugserver to use and use it if we do.
+    const char *env_debugserver_path = getenv("LLDB_DEBUGSERVER_PATH");
+    if (env_debugserver_path)
+        debugserver_file_spec.SetFile (env_debugserver_path, false);
+    else
+        debugserver_file_spec = g_debugserver_file_spec;
+    bool debugserver_exists = debugserver_file_spec.Exists();
+    if (!debugserver_exists)
+    {
+        // The debugserver binary is in the LLDB.framework/Resources
+        // directory. 
+        if (Host::GetLLDBPath (ePathTypeSupportExecutableDir, debugserver_file_spec))
+        {
+            debugserver_file_spec.GetFilename().SetCString(DEBUGSERVER_BASENAME);
+            debugserver_exists = debugserver_file_spec.Exists();
+            if (debugserver_exists)
+            {
+                g_debugserver_file_spec = debugserver_file_spec;
+            }
+            else
+            {
+                g_debugserver_file_spec.Clear();
+                debugserver_file_spec.Clear();
+            }
+        }
+    }
+    
+    if (debugserver_exists)
+    {
+        debugserver_file_spec.GetPath (debugserver_path, sizeof(debugserver_path));
+
+        Args &debugserver_args = launch_info.GetArguments();
+        debugserver_args.Clear();
+        char arg_cstr[PATH_MAX];
+        
+        // Start args with "debugserver /file/path -r --"
+        debugserver_args.AppendArgument(debugserver_path);
+        debugserver_args.AppendArgument(debugserver_url);
+        // use native registers, not the GDB registers
+        debugserver_args.AppendArgument("--native-regs");   
+        // make debugserver run in its own session so signals generated by 
+        // special terminal key sequences (^C) don't affect debugserver
+        debugserver_args.AppendArgument("--setsid");
+        
+        if (unix_socket_name && unix_socket_name[0])
+        {
+            debugserver_args.AppendArgument("--unix-socket");
+            debugserver_args.AppendArgument(unix_socket_name);
+        }
+
+        const char *env_debugserver_log_file = getenv("LLDB_DEBUGSERVER_LOG_FILE");
+        if (env_debugserver_log_file)
+        {
+            ::snprintf (arg_cstr, sizeof(arg_cstr), "--log-file=%s", env_debugserver_log_file);
+            debugserver_args.AppendArgument(arg_cstr);
+        }
+        
+        const char *env_debugserver_log_flags = getenv("LLDB_DEBUGSERVER_LOG_FLAGS");
+        if (env_debugserver_log_flags)
+        {
+            ::snprintf (arg_cstr, sizeof(arg_cstr), "--log-flags=%s", env_debugserver_log_flags);
+            debugserver_args.AppendArgument(arg_cstr);
+        }
+        //            debugserver_args.AppendArgument("--log-file=/tmp/debugserver.txt");
+        //            debugserver_args.AppendArgument("--log-flags=0x802e0e");
+        
+        // We currently send down all arguments, attach pids, or attach 
+        // process names in dedicated GDB server packets, so we don't need
+        // to pass them as arguments. This is currently because of all the
+        // things we need to setup prior to launching: the environment,
+        // current working dir, file actions, etc.
+#if 0
+        // Now append the program arguments
+        if (inferior_argv)
+        {
+            // Terminate the debugserver args so we can now append the inferior args
+            debugserver_args.AppendArgument("--");
+            
+            for (int i = 0; inferior_argv[i] != NULL; ++i)
+                debugserver_args.AppendArgument (inferior_argv[i]);
+        }
+        else if (attach_pid != LLDB_INVALID_PROCESS_ID)
+        {
+            ::snprintf (arg_cstr, sizeof(arg_cstr), "--attach=%u", attach_pid);
+            debugserver_args.AppendArgument (arg_cstr);
+        }
+        else if (attach_name && attach_name[0])
+        {
+            if (wait_for_launch)
+                debugserver_args.AppendArgument ("--waitfor");
+            else
+                debugserver_args.AppendArgument ("--attach");
+            debugserver_args.AppendArgument (attach_name);
+        }
+#endif
+        
+        // Close STDIN, STDOUT and STDERR. We might need to redirect them
+        // to "/dev/null" if we run into any problems.
+//        launch_info.AppendCloseFileAction (STDIN_FILENO);
+//        launch_info.AppendCloseFileAction (STDOUT_FILENO);
+//        launch_info.AppendCloseFileAction (STDERR_FILENO);
+        
+        error = Host::LaunchProcess(launch_info);
+    }
+    else
+    {
+        error.SetErrorStringWithFormat ("unable to locate " DEBUGSERVER_BASENAME );
+    }
+    return error;
+}
+
+void
+GDBRemoteCommunication::DumpHistory(Stream &strm)
+{
+    m_history.Dump (strm);
+}
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
new file mode 100644
index 000000000000..a1077957c6a6
--- /dev/null
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
@@ -0,0 +1,268 @@
+//===-- GDBRemoteCommunication.h --------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_GDBRemoteCommunication_h_
+#define liblldb_GDBRemoteCommunication_h_
+
+// C Includes
+// C++ Includes
+#include <list>
+#include <string>
+
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-public.h"
+#include "lldb/Core/Communication.h"
+#include "lldb/Core/Listener.h"
+#include "lldb/Host/Mutex.h"
+#include "lldb/Host/Predicate.h"
+#include "lldb/Host/TimeValue.h"
+
+#include "Utility/StringExtractorGDBRemote.h"
+
+class ProcessGDBRemote;
+
+class GDBRemoteCommunication : public lldb_private::Communication
+{
+public:
+    enum
+    {
+        eBroadcastBitRunPacketSent = kLoUserBroadcastBit
+    };
+    //------------------------------------------------------------------
+    // Constructors and Destructors
+    //------------------------------------------------------------------
+    GDBRemoteCommunication(const char *comm_name, 
+                           const char *listener_name,
+                           bool is_platform);
+
+    virtual
+    ~GDBRemoteCommunication();
+
+    char
+    GetAck ();
+
+    size_t
+    SendAck ();
+
+    size_t
+    SendNack ();
+
+    char
+    CalculcateChecksum (const char *payload,
+                        size_t payload_length);
+
+    bool
+    GetSequenceMutex (lldb_private::Mutex::Locker& locker, const char *failure_message = NULL);
+
+    bool
+    CheckForPacket (const uint8_t *src, 
+                    size_t src_len, 
+                    StringExtractorGDBRemote &packet);
+    bool
+    IsRunning() const
+    {
+        return m_public_is_running.GetValue();
+    }
+
+    bool
+    GetSendAcks ()
+    {
+        return m_send_acks;
+    }
+
+    //------------------------------------------------------------------
+    // Client and server must implement these pure virtual functions
+    //------------------------------------------------------------------
+    virtual bool
+    GetThreadSuffixSupported () = 0;
+
+    //------------------------------------------------------------------
+    // Set the global packet timeout.
+    //
+    // For clients, this is the timeout that gets used when sending
+    // packets and waiting for responses. For servers, this might not
+    // get used, and if it doesn't this should be moved to the
+    // GDBRemoteCommunicationClient.
+    //------------------------------------------------------------------
+    uint32_t 
+    SetPacketTimeout (uint32_t packet_timeout)
+    {
+        const uint32_t old_packet_timeout = m_packet_timeout;
+        m_packet_timeout = packet_timeout;
+        return old_packet_timeout;
+    }
+
+    uint32_t
+    GetPacketTimeoutInMicroSeconds () const
+    {
+        return m_packet_timeout * lldb_private::TimeValue::MicroSecPerSec;
+    }
+    //------------------------------------------------------------------
+    // Start a debugserver instance on the current host using the
+    // supplied connection URL.
+    //------------------------------------------------------------------
+    lldb_private::Error
+    StartDebugserverProcess (const char *connect_url,
+                             const char *unix_socket_name,
+                             lldb_private::ProcessLaunchInfo &launch_info); 
+
+    void
+    DumpHistory(lldb_private::Stream &strm);
+    
+protected:
+
+    class History
+    {
+    public:
+        enum PacketType
+        {
+            ePacketTypeInvalid = 0,
+            ePacketTypeSend,
+            ePacketTypeRecv
+        };
+
+        struct Entry
+        {
+            Entry() :
+                packet(),
+                type (ePacketTypeInvalid),
+                bytes_transmitted (0),
+                packet_idx (0),
+                tid (LLDB_INVALID_THREAD_ID)
+            {
+            }
+            
+            void
+            Clear ()
+            {
+                packet.clear();
+                type = ePacketTypeInvalid;
+                bytes_transmitted = 0;
+                packet_idx = 0;
+                tid = LLDB_INVALID_THREAD_ID;
+            }
+            std::string packet;
+            PacketType type;
+            uint32_t bytes_transmitted;
+            uint32_t packet_idx;
+            lldb::tid_t tid;
+        };
+
+        History (uint32_t size);
+        
+        ~History ();
+
+        // For single char packets for ack, nack and /x03
+        void
+        AddPacket (char packet_char,
+                   PacketType type,
+                   uint32_t bytes_transmitted);
+        void
+        AddPacket (const std::string &src,
+                   uint32_t src_len,
+                   PacketType type,
+                   uint32_t bytes_transmitted);
+        
+        void
+        Dump (lldb_private::Stream &strm) const;
+
+        void
+        Dump (lldb_private::Log *log) const;
+
+        bool
+        DidDumpToLog () const
+        {
+            return m_dumped_to_log;
+        }
+    
+protected:
+        uint32_t
+        GetFirstSavedPacketIndex () const
+        {
+            if (m_total_packet_count < m_packets.size())
+                return 0;
+            else
+                return m_curr_idx + 1;
+        }
+
+        uint32_t
+        GetNumPacketsInHistory () const
+        {
+            if (m_total_packet_count < m_packets.size())
+                return m_total_packet_count;
+            else
+                return (uint32_t)m_packets.size();
+        }
+
+        uint32_t
+        GetNextIndex()
+        {
+            ++m_total_packet_count;
+            const uint32_t idx = m_curr_idx;
+            m_curr_idx = NormalizeIndex(idx + 1);
+            return idx;
+        }
+
+        uint32_t
+        NormalizeIndex (uint32_t i) const
+        {
+            return i % m_packets.size();
+        }
+
+        
+        std::vector<Entry> m_packets;
+        uint32_t m_curr_idx;
+        uint32_t m_total_packet_count;
+        mutable bool m_dumped_to_log;
+    };
+
+    size_t
+    SendPacket (const char *payload,
+                size_t payload_length);
+
+    size_t
+    SendPacketNoLock (const char *payload, 
+                      size_t payload_length);
+
+    size_t
+    WaitForPacketWithTimeoutMicroSecondsNoLock (StringExtractorGDBRemote &response, 
+                                                uint32_t timeout_usec);
+
+    bool
+    WaitForNotRunningPrivate (const lldb_private::TimeValue *timeout_ptr);
+
+    //------------------------------------------------------------------
+    // Classes that inherit from GDBRemoteCommunication can see and modify these
+    //------------------------------------------------------------------
+    uint32_t m_packet_timeout;
+#ifdef LLDB_CONFIGURATION_DEBUG
+    lldb_private::TrackingMutex m_sequence_mutex;
+#else
+    lldb_private::Mutex m_sequence_mutex;    // Restrict access to sending/receiving packets to a single thread at a time
+#endif
+    lldb_private::Predicate<bool> m_public_is_running;
+    lldb_private::Predicate<bool> m_private_is_running;
+    History m_history;
+    bool m_send_acks;
+    bool m_is_platform; // Set to true if this class represents a platform,
+                        // false if this class represents a debug session for
+                        // a single process
+    
+
+
+
+private:
+    //------------------------------------------------------------------
+    // For GDBRemoteCommunication only
+    //------------------------------------------------------------------
+    DISALLOW_COPY_AND_ASSIGN (GDBRemoteCommunication);
+};
+
+#endif  // liblldb_GDBRemoteCommunication_h_
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
new file mode 100644
index 000000000000..ca594a8f3fd5
--- /dev/null
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -0,0 +1,2348 @@
+//===-- GDBRemoteCommunicationClient.cpp ------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+
+#include "GDBRemoteCommunicationClient.h"
+
+// C Includes
+// C++ Includes
+#include <sstream>
+
+// Other libraries and framework includes
+#include "llvm/ADT/Triple.h"
+#include "lldb/Interpreter/Args.h"
+#include "lldb/Core/ConnectionFileDescriptor.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/State.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Host/Endian.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Host/TimeValue.h"
+
+// Project includes
+#include "Utility/StringExtractorGDBRemote.h"
+#include "ProcessGDBRemote.h"
+#include "ProcessGDBRemoteLog.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// GDBRemoteCommunicationClient constructor
+//----------------------------------------------------------------------
+GDBRemoteCommunicationClient::GDBRemoteCommunicationClient(bool is_platform) :
+    GDBRemoteCommunication("gdb-remote.client", "gdb-remote.client.rx_packet", is_platform),
+    m_supports_not_sending_acks (eLazyBoolCalculate),
+    m_supports_thread_suffix (eLazyBoolCalculate),
+    m_supports_threads_in_stop_reply (eLazyBoolCalculate),
+    m_supports_vCont_all (eLazyBoolCalculate),
+    m_supports_vCont_any (eLazyBoolCalculate),
+    m_supports_vCont_c (eLazyBoolCalculate),
+    m_supports_vCont_C (eLazyBoolCalculate),
+    m_supports_vCont_s (eLazyBoolCalculate),
+    m_supports_vCont_S (eLazyBoolCalculate),
+    m_qHostInfo_is_valid (eLazyBoolCalculate),
+    m_qProcessInfo_is_valid (eLazyBoolCalculate),
+    m_supports_alloc_dealloc_memory (eLazyBoolCalculate),
+    m_supports_memory_region_info  (eLazyBoolCalculate),
+    m_supports_watchpoint_support_info  (eLazyBoolCalculate),
+    m_supports_detach_stay_stopped (eLazyBoolCalculate),
+    m_watchpoints_trigger_after_instruction(eLazyBoolCalculate),
+    m_attach_or_wait_reply(eLazyBoolCalculate),
+    m_prepare_for_reg_writing_reply (eLazyBoolCalculate),
+    m_supports_qProcessInfoPID (true),
+    m_supports_qfProcessInfo (true),
+    m_supports_qUserName (true),
+    m_supports_qGroupName (true),
+    m_supports_qThreadStopInfo (true),
+    m_supports_z0 (true),
+    m_supports_z1 (true),
+    m_supports_z2 (true),
+    m_supports_z3 (true),
+    m_supports_z4 (true),
+    m_curr_tid (LLDB_INVALID_THREAD_ID),
+    m_curr_tid_run (LLDB_INVALID_THREAD_ID),
+    m_num_supported_hardware_watchpoints (0),
+    m_async_mutex (Mutex::eMutexTypeRecursive),
+    m_async_packet_predicate (false),
+    m_async_packet (),
+    m_async_response (),
+    m_async_signal (-1),
+    m_thread_id_to_used_usec_map (),
+    m_host_arch(),
+    m_process_arch(),
+    m_os_version_major (UINT32_MAX),
+    m_os_version_minor (UINT32_MAX),
+    m_os_version_update (UINT32_MAX)
+{
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+GDBRemoteCommunicationClient::~GDBRemoteCommunicationClient()
+{
+    if (IsConnected())
+        Disconnect();
+}
+
+bool
+GDBRemoteCommunicationClient::HandshakeWithServer (Error *error_ptr)
+{
+    // Start the read thread after we send the handshake ack since if we
+    // fail to send the handshake ack, there is no reason to continue...
+    if (SendAck())
+        return true;
+    
+    if (error_ptr)
+        error_ptr->SetErrorString("failed to send the handshake ack");
+    return false;
+}
+
+void
+GDBRemoteCommunicationClient::QueryNoAckModeSupported ()
+{
+    if (m_supports_not_sending_acks == eLazyBoolCalculate)
+    {
+        m_send_acks = true;
+        m_supports_not_sending_acks = eLazyBoolNo;
+
+        StringExtractorGDBRemote response;
+        if (SendPacketAndWaitForResponse("QStartNoAckMode", response, false))
+        {
+            if (response.IsOKResponse())
+            {
+                m_send_acks = false;
+                m_supports_not_sending_acks = eLazyBoolYes;
+            }
+        }
+    }
+}
+
+void
+GDBRemoteCommunicationClient::GetListThreadsInStopReplySupported ()
+{
+    if (m_supports_threads_in_stop_reply == eLazyBoolCalculate)
+    {
+        m_supports_threads_in_stop_reply = eLazyBoolNo;
+        
+        StringExtractorGDBRemote response;
+        if (SendPacketAndWaitForResponse("QListThreadsInStopReply", response, false))
+        {
+            if (response.IsOKResponse())
+                m_supports_threads_in_stop_reply = eLazyBoolYes;
+        }
+    }
+}
+
+bool
+GDBRemoteCommunicationClient::GetVAttachOrWaitSupported ()
+{
+    if (m_attach_or_wait_reply == eLazyBoolCalculate)
+    {
+        m_attach_or_wait_reply = eLazyBoolNo;
+        
+        StringExtractorGDBRemote response;
+        if (SendPacketAndWaitForResponse("qVAttachOrWaitSupported", response, false))
+        {
+            if (response.IsOKResponse())
+                m_attach_or_wait_reply = eLazyBoolYes;
+        }
+    }
+    if (m_attach_or_wait_reply == eLazyBoolYes)
+        return true;
+    else
+        return false;
+}
+
+bool
+GDBRemoteCommunicationClient::GetSyncThreadStateSupported ()
+{
+    if (m_prepare_for_reg_writing_reply == eLazyBoolCalculate)
+    {
+        m_prepare_for_reg_writing_reply = eLazyBoolNo;
+        
+        StringExtractorGDBRemote response;
+        if (SendPacketAndWaitForResponse("qSyncThreadStateSupported", response, false))
+        {
+            if (response.IsOKResponse())
+                m_prepare_for_reg_writing_reply = eLazyBoolYes;
+        }
+    }
+    if (m_prepare_for_reg_writing_reply == eLazyBoolYes)
+        return true;
+    else
+        return false;
+}
+
+
+void
+GDBRemoteCommunicationClient::ResetDiscoverableSettings()
+{
+    m_supports_not_sending_acks = eLazyBoolCalculate;
+    m_supports_thread_suffix = eLazyBoolCalculate;
+    m_supports_threads_in_stop_reply = eLazyBoolCalculate;
+    m_supports_vCont_c = eLazyBoolCalculate;
+    m_supports_vCont_C = eLazyBoolCalculate;
+    m_supports_vCont_s = eLazyBoolCalculate;
+    m_supports_vCont_S = eLazyBoolCalculate;
+    m_qHostInfo_is_valid = eLazyBoolCalculate;
+    m_qProcessInfo_is_valid = eLazyBoolCalculate;
+    m_supports_alloc_dealloc_memory = eLazyBoolCalculate;
+    m_supports_memory_region_info = eLazyBoolCalculate;
+    m_prepare_for_reg_writing_reply = eLazyBoolCalculate;
+    m_attach_or_wait_reply = eLazyBoolCalculate;
+
+    m_supports_qProcessInfoPID = true;
+    m_supports_qfProcessInfo = true;
+    m_supports_qUserName = true;
+    m_supports_qGroupName = true;
+    m_supports_qThreadStopInfo = true;
+    m_supports_z0 = true;
+    m_supports_z1 = true;
+    m_supports_z2 = true;
+    m_supports_z3 = true;
+    m_supports_z4 = true;
+    m_host_arch.Clear();
+    m_process_arch.Clear();
+}
+
+
+bool
+GDBRemoteCommunicationClient::GetThreadSuffixSupported ()
+{
+    if (m_supports_thread_suffix == eLazyBoolCalculate)
+    {
+        StringExtractorGDBRemote response;
+        m_supports_thread_suffix = eLazyBoolNo;
+        if (SendPacketAndWaitForResponse("QThreadSuffixSupported", response, false))
+        {
+            if (response.IsOKResponse())
+                m_supports_thread_suffix = eLazyBoolYes;
+        }
+    }
+    return m_supports_thread_suffix;
+}
+bool
+GDBRemoteCommunicationClient::GetVContSupported (char flavor)
+{
+    if (m_supports_vCont_c == eLazyBoolCalculate)
+    {
+        StringExtractorGDBRemote response;
+        m_supports_vCont_any = eLazyBoolNo;
+        m_supports_vCont_all = eLazyBoolNo;
+        m_supports_vCont_c = eLazyBoolNo;
+        m_supports_vCont_C = eLazyBoolNo;
+        m_supports_vCont_s = eLazyBoolNo;
+        m_supports_vCont_S = eLazyBoolNo;
+        if (SendPacketAndWaitForResponse("vCont?", response, false))
+        {
+            const char *response_cstr = response.GetStringRef().c_str();
+            if (::strstr (response_cstr, ";c"))
+                m_supports_vCont_c = eLazyBoolYes;
+
+            if (::strstr (response_cstr, ";C"))
+                m_supports_vCont_C = eLazyBoolYes;
+
+            if (::strstr (response_cstr, ";s"))
+                m_supports_vCont_s = eLazyBoolYes;
+
+            if (::strstr (response_cstr, ";S"))
+                m_supports_vCont_S = eLazyBoolYes;
+
+            if (m_supports_vCont_c == eLazyBoolYes &&
+                m_supports_vCont_C == eLazyBoolYes &&
+                m_supports_vCont_s == eLazyBoolYes &&
+                m_supports_vCont_S == eLazyBoolYes)
+            {
+                m_supports_vCont_all = eLazyBoolYes;
+            }
+            
+            if (m_supports_vCont_c == eLazyBoolYes ||
+                m_supports_vCont_C == eLazyBoolYes ||
+                m_supports_vCont_s == eLazyBoolYes ||
+                m_supports_vCont_S == eLazyBoolYes)
+            {
+                m_supports_vCont_any = eLazyBoolYes;
+            }
+        }
+    }
+    
+    switch (flavor)
+    {
+    case 'a': return m_supports_vCont_any;
+    case 'A': return m_supports_vCont_all;
+    case 'c': return m_supports_vCont_c;
+    case 'C': return m_supports_vCont_C;
+    case 's': return m_supports_vCont_s;
+    case 'S': return m_supports_vCont_S;
+    default: break;
+    }
+    return false;
+}
+
+
+size_t
+GDBRemoteCommunicationClient::SendPacketAndWaitForResponse
+(
+    const char *payload,
+    StringExtractorGDBRemote &response,
+    bool send_async
+)
+{
+    return SendPacketAndWaitForResponse (payload, 
+                                         ::strlen (payload),
+                                         response,
+                                         send_async);
+}
+
+size_t
+GDBRemoteCommunicationClient::SendPacketAndWaitForResponse
+(
+    const char *payload,
+    size_t payload_length,
+    StringExtractorGDBRemote &response,
+    bool send_async
+)
+{
+    Mutex::Locker locker;
+    Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
+    size_t response_len = 0;
+    if (GetSequenceMutex (locker))
+    {
+        if (SendPacketNoLock (payload, payload_length))
+           response_len = WaitForPacketWithTimeoutMicroSecondsNoLock (response, GetPacketTimeoutInMicroSeconds ());
+        else 
+        {
+            if (log)
+                log->Printf("error: failed to send '%*s'", (int) payload_length, payload);   
+        }
+    }
+    else
+    {
+        if (send_async)
+        {
+            if (IsRunning())
+            {
+                Mutex::Locker async_locker (m_async_mutex);
+                m_async_packet.assign(payload, payload_length);
+                m_async_packet_predicate.SetValue (true, eBroadcastNever);
+                
+                if (log) 
+                    log->Printf ("async: async packet = %s", m_async_packet.c_str());
+
+                bool timed_out = false;
+                if (SendInterrupt(locker, 2, timed_out))
+                {
+                    if (m_interrupt_sent)
+                    {
+                        m_interrupt_sent = false;
+                        TimeValue timeout_time;
+                        timeout_time = TimeValue::Now();
+                        timeout_time.OffsetWithSeconds (m_packet_timeout);
+
+                        if (log) 
+                            log->Printf ("async: sent interrupt");
+
+                        if (m_async_packet_predicate.WaitForValueEqualTo (false, &timeout_time, &timed_out))
+                        {
+                            if (log) 
+                                log->Printf ("async: got response");
+
+                            // Swap the response buffer to avoid malloc and string copy
+                            response.GetStringRef().swap (m_async_response.GetStringRef());
+                            response_len = response.GetStringRef().size();
+                        }
+                        else
+                        {
+                            if (log) 
+                                log->Printf ("async: timed out waiting for response");
+                        }
+                        
+                        // Make sure we wait until the continue packet has been sent again...
+                        if (m_private_is_running.WaitForValueEqualTo (true, &timeout_time, &timed_out))
+                        {
+                            if (log)
+                            {
+                                if (timed_out) 
+                                    log->Printf ("async: timed out waiting for process to resume, but process was resumed");
+                                else
+                                    log->Printf ("async: async packet sent");
+                            }
+                        }
+                        else
+                        {
+                            if (log) 
+                                log->Printf ("async: timed out waiting for process to resume");
+                        }
+                    }
+                    else
+                    {
+                        // We had a racy condition where we went to send the interrupt
+                        // yet we were able to get the lock, so the process must have
+                        // just stopped?
+                        if (log) 
+                            log->Printf ("async: got lock without sending interrupt");
+                        // Send the packet normally since we got the lock
+                        if (SendPacketNoLock (payload, payload_length))
+                            response_len = WaitForPacketWithTimeoutMicroSecondsNoLock (response, GetPacketTimeoutInMicroSeconds ());
+                        else 
+                        {
+                            if (log)
+                                log->Printf("error: failed to send '%*s'", (int) payload_length, payload);   
+                        }
+                    }
+                }
+                else
+                {
+                    if (log) 
+                        log->Printf ("async: failed to interrupt");
+                }
+            }
+            else
+            {
+                if (log) 
+                    log->Printf ("async: not running, async is ignored");
+            }
+        }
+        else
+        {
+            if (log) 
+                log->Printf("error: failed to get packet sequence mutex, not sending packet '%*s'", (int) payload_length, payload);
+        }
+    }
+    if (response_len == 0)
+    {
+        if (log) 
+            log->Printf("error: failed to get response for '%*s'", (int) payload_length, payload);
+    }        
+    return response_len;
+}
+
+static const char *end_delimiter = "--end--;";
+static const int end_delimiter_len = 8;
+
+std::string
+GDBRemoteCommunicationClient::HarmonizeThreadIdsForProfileData
+(   ProcessGDBRemote *process,
+    StringExtractorGDBRemote& profileDataExtractor
+)
+{
+    std::map<uint64_t, uint32_t> new_thread_id_to_used_usec_map;
+    std::stringstream final_output;
+    std::string name, value;
+
+    // Going to assuming thread_used_usec comes first, else bail out.
+    while (profileDataExtractor.GetNameColonValue(name, value))
+    {
+        if (name.compare("thread_used_id") == 0)
+        {
+            StringExtractor threadIDHexExtractor(value.c_str());
+            uint64_t thread_id = threadIDHexExtractor.GetHexMaxU64(false, 0);
+            
+            bool has_used_usec = false;
+            uint32_t curr_used_usec = 0;
+            std::string usec_name, usec_value;
+            uint32_t input_file_pos = profileDataExtractor.GetFilePos();
+            if (profileDataExtractor.GetNameColonValue(usec_name, usec_value))
+            {
+                if (usec_name.compare("thread_used_usec") == 0)
+                {
+                    has_used_usec = true;
+                    curr_used_usec = strtoull(usec_value.c_str(), NULL, 0);
+                }
+                else
+                {
+                    // We didn't find what we want, it is probably
+                    // an older version. Bail out.
+                    profileDataExtractor.SetFilePos(input_file_pos);
+                }
+            }
+
+            if (has_used_usec)
+            {
+                uint32_t prev_used_usec = 0;
+                std::map<uint64_t, uint32_t>::iterator iterator = m_thread_id_to_used_usec_map.find(thread_id);
+                if (iterator != m_thread_id_to_used_usec_map.end())
+                {
+                    prev_used_usec = m_thread_id_to_used_usec_map[thread_id];
+                }
+                
+                uint32_t real_used_usec = curr_used_usec - prev_used_usec;
+                // A good first time record is one that runs for at least 0.25 sec
+                bool good_first_time = (prev_used_usec == 0) && (real_used_usec > 250000);
+                bool good_subsequent_time = (prev_used_usec > 0) &&
+                    ((real_used_usec > 0) || (process->HasAssignedIndexIDToThread(thread_id)));
+                
+                if (good_first_time || good_subsequent_time)
+                {
+                    // We try to avoid doing too many index id reservation,
+                    // resulting in fast increase of index ids.
+                    
+                    final_output << name << ":";
+                    int32_t index_id = process->AssignIndexIDToThread(thread_id);
+                    final_output << index_id << ";";
+                    
+                    final_output << usec_name << ":" << usec_value << ";";
+                }
+                else
+                {
+                    // Skip past 'thread_used_name'.
+                    std::string local_name, local_value;
+                    profileDataExtractor.GetNameColonValue(local_name, local_value);
+                }
+                
+                // Store current time as previous time so that they can be compared later.
+                new_thread_id_to_used_usec_map[thread_id] = curr_used_usec;
+            }
+            else
+            {
+                // Bail out and use old string.
+                final_output << name << ":" << value << ";";
+            }
+        }
+        else
+        {
+            final_output << name << ":" << value << ";";
+        }
+    }
+    final_output << end_delimiter;
+    m_thread_id_to_used_usec_map = new_thread_id_to_used_usec_map;
+    
+    return final_output.str();
+}
+
+StateType
+GDBRemoteCommunicationClient::SendContinuePacketAndWaitForResponse
+(
+    ProcessGDBRemote *process,
+    const char *payload,
+    size_t packet_length,
+    StringExtractorGDBRemote &response
+)
+{
+    m_curr_tid = LLDB_INVALID_THREAD_ID;
+    Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
+    if (log)
+        log->Printf ("GDBRemoteCommunicationClient::%s ()", __FUNCTION__);
+
+    Mutex::Locker locker(m_sequence_mutex);
+    StateType state = eStateRunning;
+
+    BroadcastEvent(eBroadcastBitRunPacketSent, NULL);
+    m_public_is_running.SetValue (true, eBroadcastNever);
+    // Set the starting continue packet into "continue_packet". This packet
+    // may change if we are interrupted and we continue after an async packet...
+    std::string continue_packet(payload, packet_length);
+    
+    bool got_async_packet = false;
+    
+    while (state == eStateRunning)
+    {
+        if (!got_async_packet)
+        {
+            if (log)
+                log->Printf ("GDBRemoteCommunicationClient::%s () sending continue packet: %s", __FUNCTION__, continue_packet.c_str());
+            if (SendPacketNoLock(continue_packet.c_str(), continue_packet.size()) == 0)
+                state = eStateInvalid;
+        
+            m_private_is_running.SetValue (true, eBroadcastAlways);
+        }
+        
+        got_async_packet = false;
+
+        if (log)
+            log->Printf ("GDBRemoteCommunicationClient::%s () WaitForPacket(%s)", __FUNCTION__, continue_packet.c_str());
+
+        if (WaitForPacketWithTimeoutMicroSecondsNoLock(response, UINT32_MAX))
+        {
+            if (response.Empty())
+                state = eStateInvalid;
+            else
+            {
+                const char stop_type = response.GetChar();
+                if (log)
+                    log->Printf ("GDBRemoteCommunicationClient::%s () got packet: %s", __FUNCTION__, response.GetStringRef().c_str());
+                switch (stop_type)
+                {
+                case 'T':
+                case 'S':
+                    {
+                        if (process->GetStopID() == 0)
+                        {
+                            if (process->GetID() == LLDB_INVALID_PROCESS_ID)
+                            {
+                                lldb::pid_t pid = GetCurrentProcessID ();
+                                if (pid != LLDB_INVALID_PROCESS_ID)
+                                    process->SetID (pid);
+                            }
+                            process->BuildDynamicRegisterInfo (true);
+                        }
+
+                        // Privately notify any internal threads that we have stopped
+                        // in case we wanted to interrupt our process, yet we might
+                        // send a packet and continue without returning control to the
+                        // user.
+                        m_private_is_running.SetValue (false, eBroadcastAlways);
+
+                        const uint8_t signo = response.GetHexU8 (UINT8_MAX);
+
+                        bool continue_after_async = m_async_signal != -1 || m_async_packet_predicate.GetValue();
+                        if (continue_after_async || m_interrupt_sent)
+                        {
+                            // We sent an interrupt packet to stop the inferior process
+                            // for an async signal or to send an async packet while running
+                            // but we might have been single stepping and received the
+                            // stop packet for the step instead of for the interrupt packet.
+                            // Typically when an interrupt is sent a SIGINT or SIGSTOP
+                            // is used, so if we get anything else, we need to try and
+                            // get another stop reply packet that may have been sent
+                            // due to sending the interrupt when the target is stopped
+                            // which will just re-send a copy of the last stop reply
+                            // packet. If we don't do this, then the reply for our
+                            // async packet will be the repeat stop reply packet and cause
+                            // a lot of trouble for us!
+                            if (signo != SIGINT && signo != SIGSTOP)
+                            {
+                                continue_after_async = false;
+
+                                // We didn't get a a SIGINT or SIGSTOP, so try for a
+                                // very brief time (1 ms) to get another stop reply
+                                // packet to make sure it doesn't get in the way
+                                StringExtractorGDBRemote extra_stop_reply_packet;
+                                uint32_t timeout_usec = 1000;
+                                if (WaitForPacketWithTimeoutMicroSecondsNoLock (extra_stop_reply_packet, timeout_usec))
+                                {
+                                    switch (extra_stop_reply_packet.GetChar())
+                                    {
+                                    case 'T':
+                                    case 'S':
+                                        // We did get an extra stop reply, which means
+                                        // our interrupt didn't stop the target so we
+                                        // shouldn't continue after the async signal
+                                        // or packet is sent...
+                                        continue_after_async = false;
+                                        break;
+                                    }
+                                }
+                            }
+                        }
+
+                        if (m_async_signal != -1)
+                        {
+                            if (log)
+                                log->Printf ("async: send signo = %s", Host::GetSignalAsCString (m_async_signal));
+
+                            // Save off the async signal we are supposed to send
+                            const int async_signal = m_async_signal;
+                            // Clear the async signal member so we don't end up
+                            // sending the signal multiple times...
+                            m_async_signal = -1;
+                            // Check which signal we stopped with
+                            if (signo == async_signal)
+                            {
+                                if (log) 
+                                    log->Printf ("async: stopped with signal %s, we are done running", Host::GetSignalAsCString (signo));
+
+                                // We already stopped with a signal that we wanted
+                                // to stop with, so we are done
+                            }
+                            else
+                            {
+                                // We stopped with a different signal that the one
+                                // we wanted to stop with, so now we must resume
+                                // with the signal we want
+                                char signal_packet[32];
+                                int signal_packet_len = 0;
+                                signal_packet_len = ::snprintf (signal_packet,
+                                                                sizeof (signal_packet),
+                                                                "C%2.2x",
+                                                                async_signal);
+
+                                if (log) 
+                                    log->Printf ("async: stopped with signal %s, resume with %s", 
+                                                       Host::GetSignalAsCString (signo),
+                                                       Host::GetSignalAsCString (async_signal));
+
+                                // Set the continue packet to resume even if the
+                                // interrupt didn't cause our stop (ignore continue_after_async)
+                                continue_packet.assign(signal_packet, signal_packet_len);
+                                continue;
+                            }
+                        }
+                        else if (m_async_packet_predicate.GetValue())
+                        {
+                            Log * packet_log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
+
+                            // We are supposed to send an asynchronous packet while
+                            // we are running. 
+                            m_async_response.Clear();
+                            if (m_async_packet.empty())
+                            {
+                                if (packet_log) 
+                                    packet_log->Printf ("async: error: empty async packet");                            
+
+                            }
+                            else
+                            {
+                                if (packet_log) 
+                                    packet_log->Printf ("async: sending packet");
+                                
+                                SendPacketAndWaitForResponse (&m_async_packet[0], 
+                                                              m_async_packet.size(),
+                                                              m_async_response,
+                                                              false);
+                            }
+                            // Let the other thread that was trying to send the async
+                            // packet know that the packet has been sent and response is
+                            // ready...
+                            m_async_packet_predicate.SetValue(false, eBroadcastAlways);
+
+                            if (packet_log) 
+                                packet_log->Printf ("async: sent packet, continue_after_async = %i", continue_after_async);
+
+                            // Set the continue packet to resume if our interrupt
+                            // for the async packet did cause the stop
+                            if (continue_after_async)
+                            {
+                                // Reverting this for now as it is causing deadlocks
+                                // in programs (<rdar://problem/11529853>). In the future
+                                // we should check our thread list and "do the right thing"
+                                // for new threads that show up while we stop and run async
+                                // packets. Setting the packet to 'c' to continue all threads
+                                // is the right thing to do 99.99% of the time because if a
+                                // thread was single stepping, and we sent an interrupt, we
+                                // will notice above that we didn't stop due to an interrupt
+                                // but stopped due to stepping and we would _not_ continue.
+                                continue_packet.assign (1, 'c');
+                                continue;
+                            }
+                        }
+                        // Stop with signal and thread info
+                        state = eStateStopped;
+                    }
+                    break;
+
+                case 'W':
+                case 'X':
+                    // process exited
+                    state = eStateExited;
+                    break;
+
+                case 'O':
+                    // STDOUT
+                    {
+                        got_async_packet = true;
+                        std::string inferior_stdout;
+                        inferior_stdout.reserve(response.GetBytesLeft () / 2);
+                        char ch;
+                        while ((ch = response.GetHexU8()) != '\0')
+                            inferior_stdout.append(1, ch);
+                        process->AppendSTDOUT (inferior_stdout.c_str(), inferior_stdout.size());
+                    }
+                    break;
+
+                case 'A':
+                    // Async miscellaneous reply. Right now, only profile data is coming through this channel.
+                    {
+                        got_async_packet = true;
+                        std::string input = response.GetStringRef().substr(1); // '1' to move beyond 'A'
+                        if (m_partial_profile_data.length() > 0)
+                        {
+                            m_partial_profile_data.append(input);
+                            input = m_partial_profile_data;
+                            m_partial_profile_data.clear();
+                        }
+                        
+                        size_t found, pos = 0, len = input.length();
+                        while ((found = input.find(end_delimiter, pos)) != std::string::npos)
+                        {
+                            StringExtractorGDBRemote profileDataExtractor(input.substr(pos, found).c_str());
+                            std::string profile_data = HarmonizeThreadIdsForProfileData(process, profileDataExtractor);
+                            process->BroadcastAsyncProfileData (profile_data);
+                            
+                            pos = found + end_delimiter_len;
+                        }
+                        
+                        if (pos < len)
+                        {
+                            // Last incomplete chunk.
+                            m_partial_profile_data = input.substr(pos);
+                        }
+                    }
+                    break;
+
+                case 'E':
+                    // ERROR
+                    state = eStateInvalid;
+                    break;
+
+                default:
+                    if (log)
+                        log->Printf ("GDBRemoteCommunicationClient::%s () unrecognized async packet", __FUNCTION__);
+                    state = eStateInvalid;
+                    break;
+                }
+            }
+        }
+        else
+        {
+            if (log)
+                log->Printf ("GDBRemoteCommunicationClient::%s () WaitForPacket(...) => false", __FUNCTION__);
+            state = eStateInvalid;
+        }
+    }
+    if (log)
+        log->Printf ("GDBRemoteCommunicationClient::%s () => %s", __FUNCTION__, StateAsCString(state));
+    response.SetFilePos(0);
+    m_private_is_running.SetValue (false, eBroadcastAlways);
+    m_public_is_running.SetValue (false, eBroadcastAlways);
+    return state;
+}
+
+bool
+GDBRemoteCommunicationClient::SendAsyncSignal (int signo)
+{
+    Mutex::Locker async_locker (m_async_mutex);
+    m_async_signal = signo;
+    bool timed_out = false;
+    Mutex::Locker locker;
+    if (SendInterrupt (locker, 1, timed_out))
+        return true;
+    m_async_signal = -1;
+    return false;
+}
+
+// This function takes a mutex locker as a parameter in case the GetSequenceMutex
+// actually succeeds. If it doesn't succeed in acquiring the sequence mutex 
+// (the expected result), then it will send the halt packet. If it does succeed
+// then the caller that requested the interrupt will want to keep the sequence
+// locked down so that no one else can send packets while the caller has control.
+// This function usually gets called when we are running and need to stop the 
+// target. It can also be used when we are running and and we need to do something
+// else (like read/write memory), so we need to interrupt the running process
+// (gdb remote protocol requires this), and do what we need to do, then resume.
+
+bool
+GDBRemoteCommunicationClient::SendInterrupt
+(
+    Mutex::Locker& locker, 
+    uint32_t seconds_to_wait_for_stop,             
+    bool &timed_out
+)
+{
+    timed_out = false;
+    Log *log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_PROCESS | GDBR_LOG_PACKETS));
+
+    if (IsRunning())
+    {
+        // Only send an interrupt if our debugserver is running...
+        if (GetSequenceMutex (locker))
+        {
+            if (log)
+                log->Printf ("SendInterrupt () - got sequence mutex without having to interrupt");
+        }
+        else
+        {
+            // Someone has the mutex locked waiting for a response or for the
+            // inferior to stop, so send the interrupt on the down low...
+            char ctrl_c = '\x03';
+            ConnectionStatus status = eConnectionStatusSuccess;
+            size_t bytes_written = Write (&ctrl_c, 1, status, NULL);
+            if (log)
+                log->PutCString("send packet: \\x03");
+            if (bytes_written > 0)
+            {
+                m_interrupt_sent = true;
+                if (seconds_to_wait_for_stop)
+                {
+                    TimeValue timeout;
+                    if (seconds_to_wait_for_stop)
+                    {
+                        timeout = TimeValue::Now();
+                        timeout.OffsetWithSeconds (seconds_to_wait_for_stop);
+                    }
+                    if (m_private_is_running.WaitForValueEqualTo (false, &timeout, &timed_out))
+                    {
+                        if (log)
+                            log->PutCString ("SendInterrupt () - sent interrupt, private state stopped");
+                        return true;
+                    }
+                    else
+                    {
+                        if (log)
+                            log->Printf ("SendInterrupt () - sent interrupt, timed out wating for async thread resume");
+                    }
+                }
+                else
+                {
+                    if (log)
+                        log->Printf ("SendInterrupt () - sent interrupt, not waiting for stop...");
+                    return true;
+                }
+            }
+            else
+            {
+                if (log)
+                    log->Printf ("SendInterrupt () - failed to write interrupt");
+            }
+            return false;
+        }
+    }
+    else
+    {
+        if (log)
+            log->Printf ("SendInterrupt () - not running");
+    }
+    return true;
+}
+
+lldb::pid_t
+GDBRemoteCommunicationClient::GetCurrentProcessID ()
+{
+    StringExtractorGDBRemote response;
+    if (SendPacketAndWaitForResponse("qC", strlen("qC"), response, false))
+    {
+        if (response.GetChar() == 'Q')
+            if (response.GetChar() == 'C')
+                return response.GetHexMaxU32 (false, LLDB_INVALID_PROCESS_ID);
+    }
+    return LLDB_INVALID_PROCESS_ID;
+}
+
+bool
+GDBRemoteCommunicationClient::GetLaunchSuccess (std::string &error_str)
+{
+    error_str.clear();
+    StringExtractorGDBRemote response;
+    if (SendPacketAndWaitForResponse("qLaunchSuccess", strlen("qLaunchSuccess"), response, false))
+    {
+        if (response.IsOKResponse())
+            return true;
+        if (response.GetChar() == 'E')
+        {
+            // A string the describes what failed when launching...
+            error_str = response.GetStringRef().substr(1);
+        }
+        else
+        {
+            error_str.assign ("unknown error occurred launching process");
+        }
+    }
+    else
+    {
+        error_str.assign ("timed out waiting for app to launch");
+    }
+    return false;
+}
+
+int
+GDBRemoteCommunicationClient::SendArgumentsPacket (char const *argv[])
+{
+    if (argv && argv[0])
+    {
+        StreamString packet;
+        packet.PutChar('A');
+        const char *arg;
+        for (uint32_t i = 0; (arg = argv[i]) != NULL; ++i)
+        {
+            const int arg_len = strlen(arg);
+            if (i > 0)
+                packet.PutChar(',');
+            packet.Printf("%i,%i,", arg_len * 2, i);
+            packet.PutBytesAsRawHex8 (arg, arg_len);
+        }
+
+        StringExtractorGDBRemote response;
+        if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false))
+        {
+            if (response.IsOKResponse())
+                return 0;
+            uint8_t error = response.GetError();
+            if (error)
+                return error;
+        }
+    }
+    return -1;
+}
+
+int
+GDBRemoteCommunicationClient::SendEnvironmentPacket (char const *name_equal_value)
+{
+    if (name_equal_value && name_equal_value[0])
+    {
+        StreamString packet;
+        packet.Printf("QEnvironment:%s", name_equal_value);
+        StringExtractorGDBRemote response;
+        if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false))
+        {
+            if (response.IsOKResponse())
+                return 0;
+            uint8_t error = response.GetError();
+            if (error)
+                return error;
+        }
+    }
+    return -1;
+}
+
+int
+GDBRemoteCommunicationClient::SendLaunchArchPacket (char const *arch)
+{
+    if (arch && arch[0])
+    {
+        StreamString packet;
+        packet.Printf("QLaunchArch:%s", arch);
+        StringExtractorGDBRemote response;
+        if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false))
+        {
+            if (response.IsOKResponse())
+                return 0;
+            uint8_t error = response.GetError();
+            if (error)
+                return error;
+        }
+    }
+    return -1;
+}
+
+bool
+GDBRemoteCommunicationClient::GetOSVersion (uint32_t &major, 
+                                            uint32_t &minor, 
+                                            uint32_t &update)
+{
+    if (GetHostInfo ())
+    {
+        if (m_os_version_major != UINT32_MAX)
+        {
+            major = m_os_version_major;
+            minor = m_os_version_minor;
+            update = m_os_version_update;
+            return true;
+        }
+    }
+    return false;
+}
+
+bool
+GDBRemoteCommunicationClient::GetOSBuildString (std::string &s)
+{
+    if (GetHostInfo ())
+    {
+        if (!m_os_build.empty())
+        {
+            s = m_os_build;
+            return true;
+        }
+    }
+    s.clear();
+    return false;
+}
+
+
+bool
+GDBRemoteCommunicationClient::GetOSKernelDescription (std::string &s)
+{
+    if (GetHostInfo ())
+    {
+        if (!m_os_kernel.empty())
+        {
+            s = m_os_kernel;
+            return true;
+        }
+    }
+    s.clear();
+    return false;
+}
+
+bool
+GDBRemoteCommunicationClient::GetHostname (std::string &s)
+{
+    if (GetHostInfo ())
+    {
+        if (!m_hostname.empty())
+        {
+            s = m_hostname;
+            return true;
+        }
+    }
+    s.clear();
+    return false;
+}
+
+ArchSpec
+GDBRemoteCommunicationClient::GetSystemArchitecture ()
+{
+    if (GetHostInfo ())
+        return m_host_arch;
+    return ArchSpec();
+}
+
+const lldb_private::ArchSpec &
+GDBRemoteCommunicationClient::GetProcessArchitecture ()
+{
+    if (m_qProcessInfo_is_valid == eLazyBoolCalculate)
+        GetCurrentProcessInfo ();
+    return m_process_arch;
+}
+
+
+bool
+GDBRemoteCommunicationClient::GetHostInfo (bool force)
+{
+    if (force || m_qHostInfo_is_valid == eLazyBoolCalculate)
+    {
+        m_qHostInfo_is_valid = eLazyBoolNo;
+        StringExtractorGDBRemote response;
+        if (SendPacketAndWaitForResponse ("qHostInfo", response, false))
+        {
+            if (response.IsNormalResponse())
+            {
+                std::string name;
+                std::string value;
+                uint32_t cpu = LLDB_INVALID_CPUTYPE;
+                uint32_t sub = 0;
+                std::string arch_name;
+                std::string os_name;
+                std::string vendor_name;
+                std::string triple;
+                uint32_t pointer_byte_size = 0;
+                StringExtractor extractor;
+                ByteOrder byte_order = eByteOrderInvalid;
+                uint32_t num_keys_decoded = 0;
+                while (response.GetNameColonValue(name, value))
+                {
+                    if (name.compare("cputype") == 0)
+                    {
+                        // exception type in big endian hex
+                        cpu = Args::StringToUInt32 (value.c_str(), LLDB_INVALID_CPUTYPE, 0);
+                        if (cpu != LLDB_INVALID_CPUTYPE)
+                            ++num_keys_decoded;
+                    }
+                    else if (name.compare("cpusubtype") == 0)
+                    {
+                        // exception count in big endian hex
+                        sub = Args::StringToUInt32 (value.c_str(), 0, 0);
+                        if (sub != 0)
+                            ++num_keys_decoded;
+                    }
+                    else if (name.compare("arch") == 0)
+                    {
+                        arch_name.swap (value);
+                        ++num_keys_decoded;
+                    }
+                    else if (name.compare("triple") == 0)
+                    {
+                        // The triple comes as ASCII hex bytes since it contains '-' chars
+                        extractor.GetStringRef().swap(value);
+                        extractor.SetFilePos(0);
+                        extractor.GetHexByteString (triple);
+                        ++num_keys_decoded;
+                    }
+                    else if (name.compare("os_build") == 0)
+                    {
+                        extractor.GetStringRef().swap(value);
+                        extractor.SetFilePos(0);
+                        extractor.GetHexByteString (m_os_build);
+                        ++num_keys_decoded;
+                    }
+                    else if (name.compare("hostname") == 0)
+                    {
+                        extractor.GetStringRef().swap(value);
+                        extractor.SetFilePos(0);
+                        extractor.GetHexByteString (m_hostname);
+                        ++num_keys_decoded;
+                    }
+                    else if (name.compare("os_kernel") == 0)
+                    {
+                        extractor.GetStringRef().swap(value);
+                        extractor.SetFilePos(0);
+                        extractor.GetHexByteString (m_os_kernel);
+                        ++num_keys_decoded;
+                    }
+                    else if (name.compare("ostype") == 0)
+                    {
+                        os_name.swap (value);
+                        ++num_keys_decoded;
+                    }
+                    else if (name.compare("vendor") == 0)
+                    {
+                        vendor_name.swap(value);
+                        ++num_keys_decoded;
+                    }
+                    else if (name.compare("endian") == 0)
+                    {
+                        ++num_keys_decoded;
+                        if (value.compare("little") == 0)
+                            byte_order = eByteOrderLittle;
+                        else if (value.compare("big") == 0)
+                            byte_order = eByteOrderBig;
+                        else if (value.compare("pdp") == 0)
+                            byte_order = eByteOrderPDP;
+                        else
+                            --num_keys_decoded;
+                    }
+                    else if (name.compare("ptrsize") == 0)
+                    {
+                        pointer_byte_size = Args::StringToUInt32 (value.c_str(), 0, 0);
+                        if (pointer_byte_size != 0)
+                            ++num_keys_decoded;
+                    }
+                    else if (name.compare("os_version") == 0)
+                    {
+                        Args::StringToVersion (value.c_str(), 
+                                               m_os_version_major,
+                                               m_os_version_minor,
+                                               m_os_version_update);
+                        if (m_os_version_major != UINT32_MAX)
+                            ++num_keys_decoded;
+                    }
+                    else if (name.compare("watchpoint_exceptions_received") == 0)
+                    {
+                        ++num_keys_decoded;
+                        if (strcmp(value.c_str(),"before") == 0)
+                            m_watchpoints_trigger_after_instruction = eLazyBoolNo;
+                        else if (strcmp(value.c_str(),"after") == 0)
+                            m_watchpoints_trigger_after_instruction = eLazyBoolYes;
+                        else
+                            --num_keys_decoded;
+                    }
+
+                }
+                
+                if (num_keys_decoded > 0)
+                    m_qHostInfo_is_valid = eLazyBoolYes;
+
+                if (triple.empty())
+                {
+                    if (arch_name.empty())
+                    {
+                        if (cpu != LLDB_INVALID_CPUTYPE)
+                        {
+                            m_host_arch.SetArchitecture (eArchTypeMachO, cpu, sub);
+                            if (pointer_byte_size)
+                            {
+                                assert (pointer_byte_size == m_host_arch.GetAddressByteSize());
+                            }
+                            if (byte_order != eByteOrderInvalid)
+                            {
+                                assert (byte_order == m_host_arch.GetByteOrder());
+                            }
+
+                            if (!os_name.empty() && vendor_name.compare("apple") == 0 && os_name.find("darwin") == 0)
+                            {
+                                switch (m_host_arch.GetMachine())
+                                {
+                                case llvm::Triple::arm:
+                                case llvm::Triple::thumb:
+                                    os_name = "ios";
+                                    break;
+                                default:
+                                    os_name = "macosx";
+                                    break;
+                                }
+                            }
+                            if (!vendor_name.empty())
+                                m_host_arch.GetTriple().setVendorName (llvm::StringRef (vendor_name));
+                            if (!os_name.empty())
+                                m_host_arch.GetTriple().setOSName (llvm::StringRef (os_name));
+                                
+                        }
+                    }
+                    else
+                    {
+                        std::string triple;
+                        triple += arch_name;
+                        if (!vendor_name.empty() || !os_name.empty())
+                        {
+                            triple += '-';
+                            if (vendor_name.empty())
+                                triple += "unknown";
+                            else
+                                triple += vendor_name;
+                            triple += '-';
+                            if (os_name.empty())
+                                triple += "unknown";
+                            else
+                                triple += os_name;
+                        }
+                        m_host_arch.SetTriple (triple.c_str());
+                        
+                        llvm::Triple &host_triple = m_host_arch.GetTriple();
+                        if (host_triple.getVendor() == llvm::Triple::Apple && host_triple.getOS() == llvm::Triple::Darwin)
+                        {
+                            switch (m_host_arch.GetMachine())
+                            {
+                                case llvm::Triple::arm:
+                                case llvm::Triple::thumb:
+                                    host_triple.setOS(llvm::Triple::IOS);
+                                    break;
+                                default:
+                                    host_triple.setOS(llvm::Triple::MacOSX);
+                                    break;
+                            }
+                        }
+                        if (pointer_byte_size)
+                        {
+                            assert (pointer_byte_size == m_host_arch.GetAddressByteSize());
+                        }
+                        if (byte_order != eByteOrderInvalid)
+                        {
+                            assert (byte_order == m_host_arch.GetByteOrder());
+                        }
+                        
+                    }
+                }
+                else
+                {
+                    m_host_arch.SetTriple (triple.c_str());
+                    if (pointer_byte_size)
+                    {
+                        assert (pointer_byte_size == m_host_arch.GetAddressByteSize());
+                    }
+                    if (byte_order != eByteOrderInvalid)
+                    {
+                        assert (byte_order == m_host_arch.GetByteOrder());
+                    }
+                }       
+            }
+        }
+    }
+    return m_qHostInfo_is_valid == eLazyBoolYes;
+}
+
+int
+GDBRemoteCommunicationClient::SendAttach 
+(
+    lldb::pid_t pid, 
+    StringExtractorGDBRemote& response
+)
+{
+    if (pid != LLDB_INVALID_PROCESS_ID)
+    {
+        char packet[64];
+        const int packet_len = ::snprintf (packet, sizeof(packet), "vAttach;%" PRIx64, pid);
+        assert (packet_len < (int)sizeof(packet));
+        if (SendPacketAndWaitForResponse (packet, packet_len, response, false))
+        {
+            if (response.IsErrorResponse())
+                return response.GetError();
+            return 0;
+        }
+    }
+    return -1;
+}
+
+const lldb_private::ArchSpec &
+GDBRemoteCommunicationClient::GetHostArchitecture ()
+{
+    if (m_qHostInfo_is_valid == eLazyBoolCalculate)
+        GetHostInfo ();
+    return m_host_arch;
+}
+
+addr_t
+GDBRemoteCommunicationClient::AllocateMemory (size_t size, uint32_t permissions)
+{
+    if (m_supports_alloc_dealloc_memory != eLazyBoolNo)
+    {
+        m_supports_alloc_dealloc_memory = eLazyBoolYes;
+        char packet[64];
+        const int packet_len = ::snprintf (packet, sizeof(packet), "_M%" PRIx64 ",%s%s%s",
+                                           (uint64_t)size,
+                                           permissions & lldb::ePermissionsReadable ? "r" : "",
+                                           permissions & lldb::ePermissionsWritable ? "w" : "",
+                                           permissions & lldb::ePermissionsExecutable ? "x" : "");
+        assert (packet_len < (int)sizeof(packet));
+        StringExtractorGDBRemote response;
+        if (SendPacketAndWaitForResponse (packet, packet_len, response, false))
+        {
+            if (!response.IsErrorResponse())
+                return response.GetHexMaxU64(false, LLDB_INVALID_ADDRESS);
+        }
+        else
+        {
+            m_supports_alloc_dealloc_memory = eLazyBoolNo;
+        }
+    }
+    return LLDB_INVALID_ADDRESS;
+}
+
+bool
+GDBRemoteCommunicationClient::DeallocateMemory (addr_t addr)
+{
+    if (m_supports_alloc_dealloc_memory != eLazyBoolNo)
+    {
+        m_supports_alloc_dealloc_memory = eLazyBoolYes;
+        char packet[64];
+        const int packet_len = ::snprintf(packet, sizeof(packet), "_m%" PRIx64, (uint64_t)addr);
+        assert (packet_len < (int)sizeof(packet));
+        StringExtractorGDBRemote response;
+        if (SendPacketAndWaitForResponse (packet, packet_len, response, false))
+        {
+            if (response.IsOKResponse())
+                return true;
+        }
+        else
+        {
+            m_supports_alloc_dealloc_memory = eLazyBoolNo;
+        }
+    }
+    return false;
+}
+
+Error
+GDBRemoteCommunicationClient::Detach (bool keep_stopped)
+{
+    Error error;
+    
+    if (keep_stopped)
+    {
+        if (m_supports_detach_stay_stopped == eLazyBoolCalculate)
+        {
+            char packet[64];
+            const int packet_len = ::snprintf(packet, sizeof(packet), "qSupportsDetachAndStayStopped:");
+            assert (packet_len < (int)sizeof(packet));
+            StringExtractorGDBRemote response;
+            if (SendPacketAndWaitForResponse (packet, packet_len, response, false))
+            {
+                m_supports_detach_stay_stopped = eLazyBoolYes;        
+            }
+            else
+            {
+                m_supports_detach_stay_stopped = eLazyBoolNo;
+            }
+        }
+
+        if (m_supports_detach_stay_stopped == eLazyBoolNo)
+        {
+            error.SetErrorString("Stays stopped not supported by this target.");
+            return error;
+        }
+        else
+        {
+            size_t num_sent = SendPacket ("D1", 2);
+            if (num_sent == 0)
+                error.SetErrorString ("Sending extended disconnect packet failed.");
+        }
+    }
+    else
+    {
+        size_t num_sent = SendPacket ("D", 1);
+        if (num_sent == 0)
+            error.SetErrorString ("Sending disconnect packet failed.");
+    }
+    return error;
+}
+
+Error
+GDBRemoteCommunicationClient::GetMemoryRegionInfo (lldb::addr_t addr, 
+                                                  lldb_private::MemoryRegionInfo &region_info)
+{
+    Error error;
+    region_info.Clear();
+
+    if (m_supports_memory_region_info != eLazyBoolNo)
+    {
+        m_supports_memory_region_info = eLazyBoolYes;
+        char packet[64];
+        const int packet_len = ::snprintf(packet, sizeof(packet), "qMemoryRegionInfo:%" PRIx64, (uint64_t)addr);
+        assert (packet_len < (int)sizeof(packet));
+        StringExtractorGDBRemote response;
+        if (SendPacketAndWaitForResponse (packet, packet_len, response, false))
+        {
+            std::string name;
+            std::string value;
+            addr_t addr_value;
+            bool success = true;
+            bool saw_permissions = false;
+            while (success && response.GetNameColonValue(name, value))
+            {
+                if (name.compare ("start") == 0)
+                {
+                    addr_value = Args::StringToUInt64(value.c_str(), LLDB_INVALID_ADDRESS, 16, &success);
+                    if (success)
+                        region_info.GetRange().SetRangeBase(addr_value);
+                }
+                else if (name.compare ("size") == 0)
+                {
+                    addr_value = Args::StringToUInt64(value.c_str(), 0, 16, &success);
+                    if (success)
+                        region_info.GetRange().SetByteSize (addr_value);
+                }
+                else if (name.compare ("permissions") == 0 && region_info.GetRange().IsValid())
+                {
+                    saw_permissions = true;
+                    if (region_info.GetRange().Contains (addr))
+                    {
+                        if (value.find('r') != std::string::npos)
+                            region_info.SetReadable (MemoryRegionInfo::eYes);
+                        else
+                            region_info.SetReadable (MemoryRegionInfo::eNo);
+
+                        if (value.find('w') != std::string::npos)
+                            region_info.SetWritable (MemoryRegionInfo::eYes);
+                        else
+                            region_info.SetWritable (MemoryRegionInfo::eNo);
+
+                        if (value.find('x') != std::string::npos)
+                            region_info.SetExecutable (MemoryRegionInfo::eYes);
+                        else
+                            region_info.SetExecutable (MemoryRegionInfo::eNo);
+                    }
+                    else
+                    {
+                        // The reported region does not contain this address -- we're looking at an unmapped page
+                        region_info.SetReadable (MemoryRegionInfo::eNo);
+                        region_info.SetWritable (MemoryRegionInfo::eNo);
+                        region_info.SetExecutable (MemoryRegionInfo::eNo);
+                    }
+                }
+                else if (name.compare ("error") == 0)
+                {
+                    StringExtractorGDBRemote name_extractor;
+                    // Swap "value" over into "name_extractor"
+                    name_extractor.GetStringRef().swap(value);
+                    // Now convert the HEX bytes into a string value
+                    name_extractor.GetHexByteString (value);
+                    error.SetErrorString(value.c_str());
+                }
+            }
+
+            // We got a valid address range back but no permissions -- which means this is an unmapped page
+            if (region_info.GetRange().IsValid() && saw_permissions == false)
+            {
+                region_info.SetReadable (MemoryRegionInfo::eNo);
+                region_info.SetWritable (MemoryRegionInfo::eNo);
+                region_info.SetExecutable (MemoryRegionInfo::eNo);
+            }
+        }
+        else
+        {
+            m_supports_memory_region_info = eLazyBoolNo;
+        }
+    }
+
+    if (m_supports_memory_region_info == eLazyBoolNo)
+    {
+        error.SetErrorString("qMemoryRegionInfo is not supported");
+    }
+    if (error.Fail())
+        region_info.Clear();
+    return error;
+
+}
+
+Error
+GDBRemoteCommunicationClient::GetWatchpointSupportInfo (uint32_t &num)
+{
+    Error error;
+
+    if (m_supports_watchpoint_support_info == eLazyBoolYes)
+    {
+        num = m_num_supported_hardware_watchpoints;
+        return error;
+    }
+
+    // Set num to 0 first.
+    num = 0;
+    if (m_supports_watchpoint_support_info != eLazyBoolNo)
+    {
+        char packet[64];
+        const int packet_len = ::snprintf(packet, sizeof(packet), "qWatchpointSupportInfo:");
+        assert (packet_len < (int)sizeof(packet));
+        StringExtractorGDBRemote response;
+        if (SendPacketAndWaitForResponse (packet, packet_len, response, false))
+        {
+            m_supports_watchpoint_support_info = eLazyBoolYes;        
+            std::string name;
+            std::string value;
+            while (response.GetNameColonValue(name, value))
+            {
+                if (name.compare ("num") == 0)
+                {
+                    num = Args::StringToUInt32(value.c_str(), 0, 0);
+                    m_num_supported_hardware_watchpoints = num;
+                }
+            }
+        }
+        else
+        {
+            m_supports_watchpoint_support_info = eLazyBoolNo;
+        }
+    }
+
+    if (m_supports_watchpoint_support_info == eLazyBoolNo)
+    {
+        error.SetErrorString("qWatchpointSupportInfo is not supported");
+    }
+    return error;
+
+}
+
+lldb_private::Error
+GDBRemoteCommunicationClient::GetWatchpointSupportInfo (uint32_t &num, bool& after)
+{
+    Error error(GetWatchpointSupportInfo(num));
+    if (error.Success())
+        error = GetWatchpointsTriggerAfterInstruction(after);
+    return error;
+}
+
+lldb_private::Error
+GDBRemoteCommunicationClient::GetWatchpointsTriggerAfterInstruction (bool &after)
+{
+    Error error;
+    
+    // we assume watchpoints will happen after running the relevant opcode
+    // and we only want to override this behavior if we have explicitly
+    // received a qHostInfo telling us otherwise
+    if (m_qHostInfo_is_valid != eLazyBoolYes)
+        after = true;
+    else
+        after = (m_watchpoints_trigger_after_instruction != eLazyBoolNo);
+    return error;
+}
+
+int
+GDBRemoteCommunicationClient::SetSTDIN (char const *path)
+{
+    if (path && path[0])
+    {
+        StreamString packet;
+        packet.PutCString("QSetSTDIN:");
+        packet.PutBytesAsRawHex8(path, strlen(path));
+
+        StringExtractorGDBRemote response;
+        if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false))
+        {
+            if (response.IsOKResponse())
+                return 0;
+            uint8_t error = response.GetError();
+            if (error)
+                return error;
+        }
+    }
+    return -1;
+}
+
+int
+GDBRemoteCommunicationClient::SetSTDOUT (char const *path)
+{
+    if (path && path[0])
+    {
+        StreamString packet;
+        packet.PutCString("QSetSTDOUT:");
+        packet.PutBytesAsRawHex8(path, strlen(path));
+        
+        StringExtractorGDBRemote response;
+        if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false))
+        {
+            if (response.IsOKResponse())
+                return 0;
+            uint8_t error = response.GetError();
+            if (error)
+                return error;
+        }
+    }
+    return -1;
+}
+
+int
+GDBRemoteCommunicationClient::SetSTDERR (char const *path)
+{
+    if (path && path[0])
+    {
+        StreamString packet;
+        packet.PutCString("QSetSTDERR:");
+        packet.PutBytesAsRawHex8(path, strlen(path));
+        
+        StringExtractorGDBRemote response;
+        if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false))
+        {
+            if (response.IsOKResponse())
+                return 0;
+            uint8_t error = response.GetError();
+            if (error)
+                return error;
+        }
+    }
+    return -1;
+}
+
+int
+GDBRemoteCommunicationClient::SetWorkingDir (char const *path)
+{
+    if (path && path[0])
+    {
+        StreamString packet;
+        packet.PutCString("QSetWorkingDir:");
+        packet.PutBytesAsRawHex8(path, strlen(path));
+        
+        StringExtractorGDBRemote response;
+        if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false))
+        {
+            if (response.IsOKResponse())
+                return 0;
+            uint8_t error = response.GetError();
+            if (error)
+                return error;
+        }
+    }
+    return -1;
+}
+
+int
+GDBRemoteCommunicationClient::SetDisableASLR (bool enable)
+{
+    char packet[32];
+    const int packet_len = ::snprintf (packet, sizeof (packet), "QSetDisableASLR:%i", enable ? 1 : 0);
+    assert (packet_len < (int)sizeof(packet));
+    StringExtractorGDBRemote response;
+    if (SendPacketAndWaitForResponse (packet, packet_len, response, false))
+    {
+        if (response.IsOKResponse())
+            return 0;
+        uint8_t error = response.GetError();
+        if (error)
+            return error;
+    }
+    return -1;
+}
+
+bool
+GDBRemoteCommunicationClient::DecodeProcessInfoResponse (StringExtractorGDBRemote &response, ProcessInstanceInfo &process_info)
+{
+    if (response.IsNormalResponse())
+    {
+        std::string name;
+        std::string value;
+        StringExtractor extractor;
+        
+        while (response.GetNameColonValue(name, value))
+        {
+            if (name.compare("pid") == 0)
+            {
+                process_info.SetProcessID (Args::StringToUInt32 (value.c_str(), LLDB_INVALID_PROCESS_ID, 0));
+            }
+            else if (name.compare("ppid") == 0)
+            {
+                process_info.SetParentProcessID (Args::StringToUInt32 (value.c_str(), LLDB_INVALID_PROCESS_ID, 0));
+            }
+            else if (name.compare("uid") == 0)
+            {
+                process_info.SetUserID (Args::StringToUInt32 (value.c_str(), UINT32_MAX, 0));
+            }
+            else if (name.compare("euid") == 0)
+            {
+                process_info.SetEffectiveUserID (Args::StringToUInt32 (value.c_str(), UINT32_MAX, 0));
+            }
+            else if (name.compare("gid") == 0)
+            {
+                process_info.SetGroupID (Args::StringToUInt32 (value.c_str(), UINT32_MAX, 0));
+            }
+            else if (name.compare("egid") == 0)
+            {
+                process_info.SetEffectiveGroupID (Args::StringToUInt32 (value.c_str(), UINT32_MAX, 0));
+            }
+            else if (name.compare("triple") == 0)
+            {
+                // The triple comes as ASCII hex bytes since it contains '-' chars
+                extractor.GetStringRef().swap(value);
+                extractor.SetFilePos(0);
+                extractor.GetHexByteString (value);
+                process_info.GetArchitecture ().SetTriple (value.c_str());
+            }
+            else if (name.compare("name") == 0)
+            {
+                StringExtractor extractor;
+                // The process name from ASCII hex bytes since we can't 
+                // control the characters in a process name
+                extractor.GetStringRef().swap(value);
+                extractor.SetFilePos(0);
+                extractor.GetHexByteString (value);
+                process_info.GetExecutableFile().SetFile (value.c_str(), false);
+            }
+        }
+        
+        if (process_info.GetProcessID() != LLDB_INVALID_PROCESS_ID)
+            return true;
+    }
+    return false;
+}
+
+bool
+GDBRemoteCommunicationClient::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
+{
+    process_info.Clear();
+    
+    if (m_supports_qProcessInfoPID)
+    {
+        char packet[32];
+        const int packet_len = ::snprintf (packet, sizeof (packet), "qProcessInfoPID:%" PRIu64, pid);
+        assert (packet_len < (int)sizeof(packet));
+        StringExtractorGDBRemote response;
+        if (SendPacketAndWaitForResponse (packet, packet_len, response, false))
+        {
+            return DecodeProcessInfoResponse (response, process_info);
+        }
+        else
+        {
+            m_supports_qProcessInfoPID = false;
+            return false;
+        }
+    }
+    return false;
+}
+
+bool
+GDBRemoteCommunicationClient::GetCurrentProcessInfo ()
+{
+    if (m_qProcessInfo_is_valid == eLazyBoolYes)
+        return true;
+    if (m_qProcessInfo_is_valid == eLazyBoolNo)
+        return false;
+
+    GetHostInfo ();
+
+    StringExtractorGDBRemote response;
+    if (SendPacketAndWaitForResponse ("qProcessInfo", response, false))
+    {
+        if (response.IsNormalResponse())
+        {
+            std::string name;
+            std::string value;
+            uint32_t cpu = LLDB_INVALID_CPUTYPE;
+            uint32_t sub = 0;
+            std::string arch_name;
+            std::string os_name;
+            std::string vendor_name;
+            std::string triple;
+            uint32_t pointer_byte_size = 0;
+            StringExtractor extractor;
+            ByteOrder byte_order = eByteOrderInvalid;
+            uint32_t num_keys_decoded = 0;
+            while (response.GetNameColonValue(name, value))
+            {
+                if (name.compare("cputype") == 0)
+                {
+                    cpu = Args::StringToUInt32 (value.c_str(), LLDB_INVALID_CPUTYPE, 16);
+                    if (cpu != LLDB_INVALID_CPUTYPE)
+                        ++num_keys_decoded;
+                }
+                else if (name.compare("cpusubtype") == 0)
+                {
+                    sub = Args::StringToUInt32 (value.c_str(), 0, 16);
+                    if (sub != 0)
+                        ++num_keys_decoded;
+                }
+                else if (name.compare("ostype") == 0)
+                {
+                    os_name.swap (value);
+                    ++num_keys_decoded;
+                }
+                else if (name.compare("vendor") == 0)
+                {
+                    vendor_name.swap(value);
+                    ++num_keys_decoded;
+                }
+                else if (name.compare("endian") == 0)
+                {
+                    ++num_keys_decoded;
+                    if (value.compare("little") == 0)
+                        byte_order = eByteOrderLittle;
+                    else if (value.compare("big") == 0)
+                        byte_order = eByteOrderBig;
+                    else if (value.compare("pdp") == 0)
+                        byte_order = eByteOrderPDP;
+                    else
+                        --num_keys_decoded;
+                }
+                else if (name.compare("ptrsize") == 0)
+                {
+                    pointer_byte_size = Args::StringToUInt32 (value.c_str(), 0, 16);
+                    if (pointer_byte_size != 0)
+                        ++num_keys_decoded;
+                }
+            }
+            if (num_keys_decoded > 0)
+                m_qProcessInfo_is_valid = eLazyBoolYes;
+            if (cpu != LLDB_INVALID_CPUTYPE && !os_name.empty() && !vendor_name.empty())
+            {
+                m_process_arch.SetArchitecture (eArchTypeMachO, cpu, sub);
+                if (pointer_byte_size)
+                {
+                    assert (pointer_byte_size == m_process_arch.GetAddressByteSize());
+                }
+                m_host_arch.GetTriple().setVendorName (llvm::StringRef (vendor_name));
+                m_host_arch.GetTriple().setOSName (llvm::StringRef (os_name));
+                return true;
+            }
+        }
+    }
+    else
+    {
+        m_qProcessInfo_is_valid = eLazyBoolNo;
+    }
+
+    return false;
+}
+
+
+uint32_t
+GDBRemoteCommunicationClient::FindProcesses (const ProcessInstanceInfoMatch &match_info,
+                                             ProcessInstanceInfoList &process_infos)
+{
+    process_infos.Clear();
+    
+    if (m_supports_qfProcessInfo)
+    {
+        StreamString packet;
+        packet.PutCString ("qfProcessInfo");
+        if (!match_info.MatchAllProcesses())
+        {
+            packet.PutChar (':');
+            const char *name = match_info.GetProcessInfo().GetName();
+            bool has_name_match = false;
+            if (name && name[0])
+            {
+                has_name_match = true;
+                NameMatchType name_match_type = match_info.GetNameMatchType();
+                switch (name_match_type)
+                {
+                case eNameMatchIgnore:  
+                    has_name_match = false;
+                    break;
+
+                case eNameMatchEquals:  
+                    packet.PutCString ("name_match:equals;"); 
+                    break;
+
+                case eNameMatchContains:
+                    packet.PutCString ("name_match:contains;"); 
+                    break;
+                
+                case eNameMatchStartsWith:
+                    packet.PutCString ("name_match:starts_with;"); 
+                    break;
+                
+                case eNameMatchEndsWith:
+                    packet.PutCString ("name_match:ends_with;"); 
+                    break;
+
+                case eNameMatchRegularExpression:
+                    packet.PutCString ("name_match:regex;"); 
+                    break;
+                }
+                if (has_name_match)
+                {
+                    packet.PutCString ("name:");
+                    packet.PutBytesAsRawHex8(name, ::strlen(name));
+                    packet.PutChar (';');
+                }
+            }
+            
+            if (match_info.GetProcessInfo().ProcessIDIsValid())
+                packet.Printf("pid:%" PRIu64 ";",match_info.GetProcessInfo().GetProcessID());
+            if (match_info.GetProcessInfo().ParentProcessIDIsValid())
+                packet.Printf("parent_pid:%" PRIu64 ";",match_info.GetProcessInfo().GetParentProcessID());
+            if (match_info.GetProcessInfo().UserIDIsValid())
+                packet.Printf("uid:%u;",match_info.GetProcessInfo().GetUserID());
+            if (match_info.GetProcessInfo().GroupIDIsValid())
+                packet.Printf("gid:%u;",match_info.GetProcessInfo().GetGroupID());
+            if (match_info.GetProcessInfo().EffectiveUserIDIsValid())
+                packet.Printf("euid:%u;",match_info.GetProcessInfo().GetEffectiveUserID());
+            if (match_info.GetProcessInfo().EffectiveGroupIDIsValid())
+                packet.Printf("egid:%u;",match_info.GetProcessInfo().GetEffectiveGroupID());
+            if (match_info.GetProcessInfo().EffectiveGroupIDIsValid())
+                packet.Printf("all_users:%u;",match_info.GetMatchAllUsers() ? 1 : 0);
+            if (match_info.GetProcessInfo().GetArchitecture().IsValid())
+            {
+                const ArchSpec &match_arch = match_info.GetProcessInfo().GetArchitecture();
+                const llvm::Triple &triple = match_arch.GetTriple();
+                packet.PutCString("triple:");
+                packet.PutCStringAsRawHex8(triple.getTriple().c_str());
+                packet.PutChar (';');
+            }
+        }
+        StringExtractorGDBRemote response;
+        if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false))
+        {
+            do
+            {
+                ProcessInstanceInfo process_info;
+                if (!DecodeProcessInfoResponse (response, process_info))
+                    break;
+                process_infos.Append(process_info);
+                response.GetStringRef().clear();
+                response.SetFilePos(0);
+            } while (SendPacketAndWaitForResponse ("qsProcessInfo", strlen ("qsProcessInfo"), response, false));
+        }
+        else
+        {
+            m_supports_qfProcessInfo = false;
+            return 0;
+        }
+    }
+    return process_infos.GetSize();
+    
+}
+
+bool
+GDBRemoteCommunicationClient::GetUserName (uint32_t uid, std::string &name)
+{
+    if (m_supports_qUserName)
+    {
+        char packet[32];
+        const int packet_len = ::snprintf (packet, sizeof (packet), "qUserName:%i", uid);
+        assert (packet_len < (int)sizeof(packet));
+        StringExtractorGDBRemote response;
+        if (SendPacketAndWaitForResponse (packet, packet_len, response, false))
+        {
+            if (response.IsNormalResponse())
+            {
+                // Make sure we parsed the right number of characters. The response is
+                // the hex encoded user name and should make up the entire packet.
+                // If there are any non-hex ASCII bytes, the length won't match below..
+                if (response.GetHexByteString (name) * 2 == response.GetStringRef().size())
+                    return true;
+            }
+        }
+        else
+        {
+            m_supports_qUserName = false;
+            return false;
+        }        
+    }
+    return false;
+
+}
+
+bool
+GDBRemoteCommunicationClient::GetGroupName (uint32_t gid, std::string &name)
+{
+    if (m_supports_qGroupName)
+    {
+        char packet[32];
+        const int packet_len = ::snprintf (packet, sizeof (packet), "qGroupName:%i", gid);
+        assert (packet_len < (int)sizeof(packet));
+        StringExtractorGDBRemote response;
+        if (SendPacketAndWaitForResponse (packet, packet_len, response, false))
+        {
+            if (response.IsNormalResponse())
+            {
+                // Make sure we parsed the right number of characters. The response is
+                // the hex encoded group name and should make up the entire packet.
+                // If there are any non-hex ASCII bytes, the length won't match below..
+                if (response.GetHexByteString (name) * 2 == response.GetStringRef().size())
+                    return true;
+            }
+        }
+        else
+        {
+            m_supports_qGroupName = false;
+            return false;
+        }
+    }
+    return false;
+}
+
+void
+GDBRemoteCommunicationClient::TestPacketSpeed (const uint32_t num_packets)
+{
+    uint32_t i;
+    TimeValue start_time, end_time;
+    uint64_t total_time_nsec;
+    float packets_per_second;
+    if (SendSpeedTestPacket (0, 0))
+    {
+        for (uint32_t send_size = 0; send_size <= 1024; send_size *= 2)
+        {
+            for (uint32_t recv_size = 0; recv_size <= 1024; recv_size *= 2)
+            {
+                start_time = TimeValue::Now();
+                for (i=0; i<num_packets; ++i)
+                {
+                    SendSpeedTestPacket (send_size, recv_size);
+                }
+                end_time = TimeValue::Now();
+                total_time_nsec = end_time.GetAsNanoSecondsSinceJan1_1970() - start_time.GetAsNanoSecondsSinceJan1_1970();
+                packets_per_second = (((float)num_packets)/(float)total_time_nsec) * (float)TimeValue::NanoSecPerSec;
+                printf ("%u qSpeedTest(send=%-5u, recv=%-5u) in %" PRIu64 ".%9.9" PRIu64 " sec for %f packets/sec.\n",
+                        num_packets, 
+                        send_size,
+                        recv_size,
+                        total_time_nsec / TimeValue::NanoSecPerSec,
+                        total_time_nsec % TimeValue::NanoSecPerSec, 
+                        packets_per_second);
+                if (recv_size == 0)
+                    recv_size = 32;
+            }
+            if (send_size == 0)
+                send_size = 32;
+        }
+    }
+    else
+    {
+        start_time = TimeValue::Now();
+        for (i=0; i<num_packets; ++i)
+        {
+            GetCurrentProcessID ();
+        }
+        end_time = TimeValue::Now();
+        total_time_nsec = end_time.GetAsNanoSecondsSinceJan1_1970() - start_time.GetAsNanoSecondsSinceJan1_1970();
+        packets_per_second = (((float)num_packets)/(float)total_time_nsec) * (float)TimeValue::NanoSecPerSec;
+        printf ("%u 'qC' packets packets in 0x%" PRIu64 "%9.9" PRIu64 " sec for %f packets/sec.\n",
+                num_packets, 
+                total_time_nsec / TimeValue::NanoSecPerSec, 
+                total_time_nsec % TimeValue::NanoSecPerSec, 
+                packets_per_second);
+    }
+}
+
+bool
+GDBRemoteCommunicationClient::SendSpeedTestPacket (uint32_t send_size, uint32_t recv_size)
+{
+    StreamString packet;
+    packet.Printf ("qSpeedTest:response_size:%i;data:", recv_size);
+    uint32_t bytes_left = send_size;
+    while (bytes_left > 0)
+    {
+        if (bytes_left >= 26)
+        {
+            packet.PutCString("abcdefghijklmnopqrstuvwxyz");
+            bytes_left -= 26;
+        }
+        else
+        {
+            packet.Printf ("%*.*s;", bytes_left, bytes_left, "abcdefghijklmnopqrstuvwxyz");
+            bytes_left = 0;
+        }
+    }
+
+    StringExtractorGDBRemote response;
+    return SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false) > 0;
+    return false;
+}
+
+uint16_t
+GDBRemoteCommunicationClient::LaunchGDBserverAndGetPort ()
+{
+    StringExtractorGDBRemote response;
+    if (SendPacketAndWaitForResponse("qLaunchGDBServer", strlen("qLaunchGDBServer"), response, false))
+    {
+        std::string name;
+        std::string value;
+        uint16_t port = 0;
+        //lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
+        while (response.GetNameColonValue(name, value))
+        {
+            if (name.size() == 4 && name.compare("port") == 0)
+                port = Args::StringToUInt32(value.c_str(), 0, 0);
+//            if (name.size() == 3 && name.compare("pid") == 0)
+//                pid = Args::StringToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0);
+        }
+        return port;
+    }
+    return 0;
+}
+
+bool
+GDBRemoteCommunicationClient::SetCurrentThread (uint64_t tid)
+{
+    if (m_curr_tid == tid)
+        return true;
+
+    char packet[32];
+    int packet_len;
+    if (tid == UINT64_MAX)
+        packet_len = ::snprintf (packet, sizeof(packet), "Hg-1");
+    else
+        packet_len = ::snprintf (packet, sizeof(packet), "Hg%" PRIx64, tid);
+    assert (packet_len + 1 < (int)sizeof(packet));
+    StringExtractorGDBRemote response;
+    if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+    {
+        if (response.IsOKResponse())
+        {
+            m_curr_tid = tid;
+            return true;
+        }
+    }
+    return false;
+}
+
+bool
+GDBRemoteCommunicationClient::SetCurrentThreadForRun (uint64_t tid)
+{
+    if (m_curr_tid_run == tid)
+        return true;
+
+    char packet[32];
+    int packet_len;
+    if (tid == UINT64_MAX)
+        packet_len = ::snprintf (packet, sizeof(packet), "Hc-1");
+    else
+        packet_len = ::snprintf (packet, sizeof(packet), "Hc%" PRIx64, tid);
+
+    assert (packet_len + 1 < (int)sizeof(packet));
+    StringExtractorGDBRemote response;
+    if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+    {
+        if (response.IsOKResponse())
+        {
+            m_curr_tid_run = tid;
+            return true;
+        }
+    }
+    return false;
+}
+
+bool
+GDBRemoteCommunicationClient::GetStopReply (StringExtractorGDBRemote &response)
+{
+    if (SendPacketAndWaitForResponse("?", 1, response, false))
+        return response.IsNormalResponse();
+    return false;
+}
+
+bool
+GDBRemoteCommunicationClient::GetThreadStopInfo (lldb::tid_t tid, StringExtractorGDBRemote &response)
+{
+    if (m_supports_qThreadStopInfo)
+    {
+        char packet[256];
+        int packet_len = ::snprintf(packet, sizeof(packet), "qThreadStopInfo%" PRIx64, tid);
+        assert (packet_len < (int)sizeof(packet));
+        if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+        {
+            if (response.IsNormalResponse())
+                return true;
+            else
+                return false;
+        }
+        else
+        {
+            m_supports_qThreadStopInfo = false;
+        }
+    }
+//    if (SetCurrentThread (tid))
+//        return GetStopReply (response);
+    return false;
+}
+
+
+uint8_t
+GDBRemoteCommunicationClient::SendGDBStoppointTypePacket (GDBStoppointType type, bool insert,  addr_t addr, uint32_t length)
+{
+    switch (type)
+    {
+    case eBreakpointSoftware:   if (!m_supports_z0) return UINT8_MAX; break;
+    case eBreakpointHardware:   if (!m_supports_z1) return UINT8_MAX; break;
+    case eWatchpointWrite:      if (!m_supports_z2) return UINT8_MAX; break;
+    case eWatchpointRead:       if (!m_supports_z3) return UINT8_MAX; break;
+    case eWatchpointReadWrite:  if (!m_supports_z4) return UINT8_MAX; break;
+    }
+
+    char packet[64];
+    const int packet_len = ::snprintf (packet, 
+                                       sizeof(packet), 
+                                       "%c%i,%" PRIx64 ",%x",
+                                       insert ? 'Z' : 'z', 
+                                       type, 
+                                       addr, 
+                                       length);
+
+    assert (packet_len + 1 < (int)sizeof(packet));
+    StringExtractorGDBRemote response;
+    if (SendPacketAndWaitForResponse(packet, packet_len, response, true))
+    {
+        if (response.IsOKResponse())
+            return 0;
+        else if (response.IsErrorResponse())
+            return response.GetError();
+    }
+    else
+    {
+        switch (type)
+        {
+            case eBreakpointSoftware:   m_supports_z0 = false; break;
+            case eBreakpointHardware:   m_supports_z1 = false; break;
+            case eWatchpointWrite:      m_supports_z2 = false; break;
+            case eWatchpointRead:       m_supports_z3 = false; break;
+            case eWatchpointReadWrite:  m_supports_z4 = false; break;
+        }
+    }
+
+    return UINT8_MAX;
+}
+
+size_t
+GDBRemoteCommunicationClient::GetCurrentThreadIDs (std::vector<lldb::tid_t> &thread_ids, 
+                                                   bool &sequence_mutex_unavailable)
+{
+    Mutex::Locker locker;
+    thread_ids.clear();
+    
+    if (GetSequenceMutex (locker, "ProcessGDBRemote::UpdateThreadList() failed due to not getting the sequence mutex"))
+    {
+        sequence_mutex_unavailable = false;
+        StringExtractorGDBRemote response;
+        
+        for (SendPacketNoLock ("qfThreadInfo", strlen("qfThreadInfo")) && WaitForPacketWithTimeoutMicroSecondsNoLock (response, GetPacketTimeoutInMicroSeconds ());
+             response.IsNormalResponse();
+             SendPacketNoLock ("qsThreadInfo", strlen("qsThreadInfo")) && WaitForPacketWithTimeoutMicroSecondsNoLock (response, GetPacketTimeoutInMicroSeconds ()))
+        {
+            char ch = response.GetChar();
+            if (ch == 'l')
+                break;
+            if (ch == 'm')
+            {
+                do
+                {
+                    tid_t tid = response.GetHexMaxU64(false, LLDB_INVALID_THREAD_ID);
+                    
+                    if (tid != LLDB_INVALID_THREAD_ID)
+                    {
+                        thread_ids.push_back (tid);
+                    }
+                    ch = response.GetChar();    // Skip the command separator
+                } while (ch == ',');            // Make sure we got a comma separator
+            }
+        }
+    }
+    else
+    {
+#if defined (LLDB_CONFIGURATION_DEBUG)
+        // assert(!"ProcessGDBRemote::UpdateThreadList() failed due to not getting the sequence mutex");
+#else
+        Log *log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_PROCESS | GDBR_LOG_PACKETS));
+        if (log)
+            log->Printf("error: failed to get packet sequence mutex, not sending packet 'qfThreadInfo'");
+#endif
+        sequence_mutex_unavailable = true;
+    }
+    return thread_ids.size();
+}
+
+lldb::addr_t
+GDBRemoteCommunicationClient::GetShlibInfoAddr()
+{
+    if (!IsRunning())
+    {
+        StringExtractorGDBRemote response;
+        if (SendPacketAndWaitForResponse("qShlibInfoAddr", ::strlen ("qShlibInfoAddr"), response, false))
+        {
+            if (response.IsNormalResponse())
+                return response.GetHexMaxU64(false, LLDB_INVALID_ADDRESS);
+        }
+    }
+    return LLDB_INVALID_ADDRESS;
+}
+
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
new file mode 100644
index 000000000000..5bb8387b9094
--- /dev/null
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
@@ -0,0 +1,430 @@
+//===-- GDBRemoteCommunicationClient.h --------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_GDBRemoteCommunicationClient_h_
+#define liblldb_GDBRemoteCommunicationClient_h_
+
+// C Includes
+// C++ Includes
+#include <vector>
+
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Target/Process.h"
+
+#include "GDBRemoteCommunication.h"
+
+typedef enum 
+{
+    eBreakpointSoftware = 0,
+    eBreakpointHardware,
+    eWatchpointWrite,
+    eWatchpointRead,
+    eWatchpointReadWrite
+} GDBStoppointType;
+
+class GDBRemoteCommunicationClient : public GDBRemoteCommunication
+{
+public:
+    //------------------------------------------------------------------
+    // Constructors and Destructors
+    //------------------------------------------------------------------
+    GDBRemoteCommunicationClient(bool is_platform);
+
+    virtual
+    ~GDBRemoteCommunicationClient();
+
+    //------------------------------------------------------------------
+    // After connecting, send the handshake to the server to make sure
+    // we are communicating with it.
+    //------------------------------------------------------------------
+    bool
+    HandshakeWithServer (lldb_private::Error *error_ptr);
+
+    size_t
+    SendPacketAndWaitForResponse (const char *send_payload,
+                                  StringExtractorGDBRemote &response,
+                                  bool send_async);
+
+    size_t
+    SendPacketAndWaitForResponse (const char *send_payload,
+                                  size_t send_length,
+                                  StringExtractorGDBRemote &response,
+                                  bool send_async);
+
+    lldb::StateType
+    SendContinuePacketAndWaitForResponse (ProcessGDBRemote *process,
+                                          const char *packet_payload,
+                                          size_t packet_length,
+                                          StringExtractorGDBRemote &response);
+
+    virtual bool
+    GetThreadSuffixSupported ();
+
+    void
+    QueryNoAckModeSupported ();
+
+    void
+    GetListThreadsInStopReplySupported ();
+
+    bool
+    SendAsyncSignal (int signo);
+
+    bool
+    SendInterrupt (lldb_private::Mutex::Locker &locker, 
+                   uint32_t seconds_to_wait_for_stop, 
+                   bool &timed_out);
+
+    lldb::pid_t
+    GetCurrentProcessID ();
+
+    bool
+    GetLaunchSuccess (std::string &error_str);
+
+    uint16_t
+    LaunchGDBserverAndGetPort ();
+
+    //------------------------------------------------------------------
+    /// Sends a GDB remote protocol 'A' packet that delivers program
+    /// arguments to the remote server.
+    ///
+    /// @param[in] argv
+    ///     A NULL terminated array of const C strings to use as the
+    ///     arguments.
+    ///
+    /// @return
+    ///     Zero if the response was "OK", a positive value if the
+    ///     the response was "Exx" where xx are two hex digits, or
+    ///     -1 if the call is unsupported or any other unexpected
+    ///     response was received.
+    //------------------------------------------------------------------
+    int
+    SendArgumentsPacket (char const *argv[]);
+
+    //------------------------------------------------------------------
+    /// Sends a "QEnvironment:NAME=VALUE" packet that will build up the
+    /// environment that will get used when launching an application
+    /// in conjunction with the 'A' packet. This function can be called
+    /// multiple times in a row in order to pass on the desired
+    /// environment that the inferior should be launched with.
+    ///
+    /// @param[in] name_equal_value
+    ///     A NULL terminated C string that contains a single environment
+    ///     in the format "NAME=VALUE".
+    ///
+    /// @return
+    ///     Zero if the response was "OK", a positive value if the
+    ///     the response was "Exx" where xx are two hex digits, or
+    ///     -1 if the call is unsupported or any other unexpected
+    ///     response was received.
+    //------------------------------------------------------------------
+    int
+    SendEnvironmentPacket (char const *name_equal_value);
+
+    int
+    SendLaunchArchPacket (const char *arch);
+    //------------------------------------------------------------------
+    /// Sends a "vAttach:PID" where PID is in hex. 
+    ///
+    /// @param[in] pid
+    ///     A process ID for the remote gdb server to attach to.
+    ///
+    /// @param[out] response
+    ///     The response received from the gdb server. If the return
+    ///     value is zero, \a response will contain a stop reply 
+    ///     packet.
+    ///
+    /// @return
+    ///     Zero if the attach was successful, or an error indicating
+    ///     an error code.
+    //------------------------------------------------------------------
+    int
+    SendAttach (lldb::pid_t pid, 
+                StringExtractorGDBRemote& response);
+
+
+    //------------------------------------------------------------------
+    /// Sets the path to use for stdin/out/err for a process
+    /// that will be launched with the 'A' packet.
+    ///
+    /// @param[in] path
+    ///     The path to use for stdin/out/err
+    ///
+    /// @return
+    ///     Zero if the for success, or an error code for failure.
+    //------------------------------------------------------------------
+    int
+    SetSTDIN (char const *path);
+    int
+    SetSTDOUT (char const *path);
+    int
+    SetSTDERR (char const *path);
+
+    //------------------------------------------------------------------
+    /// Sets the disable ASLR flag to \a enable for a process that will 
+    /// be launched with the 'A' packet.
+    ///
+    /// @param[in] enable
+    ///     A boolean value indicating wether to disable ASLR or not.
+    ///
+    /// @return
+    ///     Zero if the for success, or an error code for failure.
+    //------------------------------------------------------------------
+    int
+    SetDisableASLR (bool enable);
+
+    //------------------------------------------------------------------
+    /// Sets the working directory to \a path for a process that will 
+    /// be launched with the 'A' packet.
+    ///
+    /// @param[in] path
+    ///     The path to a directory to use when launching our processs
+    ///
+    /// @return
+    ///     Zero if the for success, or an error code for failure.
+    //------------------------------------------------------------------
+    int
+    SetWorkingDir (char const *path);
+
+    lldb::addr_t
+    AllocateMemory (size_t size, uint32_t permissions);
+
+    bool
+    DeallocateMemory (lldb::addr_t addr);
+
+    lldb_private::Error
+    Detach (bool keep_stopped);
+
+    lldb_private::Error
+    GetMemoryRegionInfo (lldb::addr_t addr, 
+                        lldb_private::MemoryRegionInfo &range_info); 
+
+    lldb_private::Error
+    GetWatchpointSupportInfo (uint32_t &num); 
+
+    lldb_private::Error
+    GetWatchpointSupportInfo (uint32_t &num, bool& after);
+    
+    lldb_private::Error
+    GetWatchpointsTriggerAfterInstruction (bool &after);
+
+    const lldb_private::ArchSpec &
+    GetHostArchitecture ();
+
+    const lldb_private::ArchSpec &
+    GetProcessArchitecture ();
+
+    bool
+    GetVContSupported (char flavor);
+
+    bool
+    GetVAttachOrWaitSupported ();
+    
+    bool
+    GetSyncThreadStateSupported();
+    
+    void
+    ResetDiscoverableSettings();
+
+    bool
+    GetHostInfo (bool force = false);
+    
+    bool
+    GetOSVersion (uint32_t &major, 
+                  uint32_t &minor, 
+                  uint32_t &update);
+
+    bool
+    GetOSBuildString (std::string &s);
+    
+    bool
+    GetOSKernelDescription (std::string &s);
+
+    lldb_private::ArchSpec
+    GetSystemArchitecture ();
+
+    bool
+    GetHostname (std::string &s);
+
+    lldb::addr_t
+    GetShlibInfoAddr();
+
+    bool
+    GetSupportsThreadSuffix ();
+
+    bool
+    GetProcessInfo (lldb::pid_t pid, 
+                    lldb_private::ProcessInstanceInfo &process_info);
+
+    uint32_t
+    FindProcesses (const lldb_private::ProcessInstanceInfoMatch &process_match_info,
+                   lldb_private::ProcessInstanceInfoList &process_infos);
+
+    bool
+    GetUserName (uint32_t uid, std::string &name);
+    
+    bool
+    GetGroupName (uint32_t gid, std::string &name);
+
+    bool
+    HasFullVContSupport ()
+    {
+        return GetVContSupported ('A');
+    }
+
+    bool
+    HasAnyVContSupport ()
+    {
+        return GetVContSupported ('a');
+    }
+    
+    bool
+    GetStopReply (StringExtractorGDBRemote &response);
+
+    bool
+    GetThreadStopInfo (lldb::tid_t tid, 
+                       StringExtractorGDBRemote &response);
+
+    bool
+    SupportsGDBStoppointPacket (GDBStoppointType type)
+    {
+        switch (type)
+        {
+        case eBreakpointSoftware:   return m_supports_z0;
+        case eBreakpointHardware:   return m_supports_z1;
+        case eWatchpointWrite:      return m_supports_z2;
+        case eWatchpointRead:       return m_supports_z3;
+        case eWatchpointReadWrite:  return m_supports_z4;
+        }
+        return false;
+    }
+    uint8_t
+    SendGDBStoppointTypePacket (GDBStoppointType type,   // Type of breakpoint or watchpoint
+                                bool insert,              // Insert or remove?
+                                lldb::addr_t addr,        // Address of breakpoint or watchpoint
+                                uint32_t length);         // Byte Size of breakpoint or watchpoint
+
+    void
+    TestPacketSpeed (const uint32_t num_packets);
+
+    // This packet is for testing the speed of the interface only. Both
+    // the client and server need to support it, but this allows us to
+    // measure the packet speed without any other work being done on the
+    // other end and avoids any of that work affecting the packet send
+    // and response times.
+    bool
+    SendSpeedTestPacket (uint32_t send_size, 
+                         uint32_t recv_size);
+    
+    bool
+    SetCurrentThread (uint64_t tid);
+    
+    bool
+    SetCurrentThreadForRun (uint64_t tid);
+
+    lldb_private::LazyBool
+    SupportsAllocDeallocMemory () // const
+    {
+        // Uncomment this to have lldb pretend the debug server doesn't respond to alloc/dealloc memory packets.
+        // m_supports_alloc_dealloc_memory = lldb_private::eLazyBoolNo;
+        return m_supports_alloc_dealloc_memory;
+    }
+
+    size_t
+    GetCurrentThreadIDs (std::vector<lldb::tid_t> &thread_ids,
+                         bool &sequence_mutex_unavailable);
+    
+    bool
+    GetInterruptWasSent () const
+    {
+        return m_interrupt_sent;
+    }
+    
+    std::string
+    HarmonizeThreadIdsForProfileData (ProcessGDBRemote *process,
+                                      StringExtractorGDBRemote &inputStringExtractor);
+    
+protected:
+
+    bool
+    GetCurrentProcessInfo ();
+
+    //------------------------------------------------------------------
+    // Classes that inherit from GDBRemoteCommunicationClient can see and modify these
+    //------------------------------------------------------------------
+    lldb_private::LazyBool m_supports_not_sending_acks;
+    lldb_private::LazyBool m_supports_thread_suffix;
+    lldb_private::LazyBool m_supports_threads_in_stop_reply;
+    lldb_private::LazyBool m_supports_vCont_all;
+    lldb_private::LazyBool m_supports_vCont_any;
+    lldb_private::LazyBool m_supports_vCont_c;
+    lldb_private::LazyBool m_supports_vCont_C;
+    lldb_private::LazyBool m_supports_vCont_s;
+    lldb_private::LazyBool m_supports_vCont_S;
+    lldb_private::LazyBool m_qHostInfo_is_valid;
+    lldb_private::LazyBool m_qProcessInfo_is_valid;
+    lldb_private::LazyBool m_supports_alloc_dealloc_memory;
+    lldb_private::LazyBool m_supports_memory_region_info;
+    lldb_private::LazyBool m_supports_watchpoint_support_info;
+    lldb_private::LazyBool m_supports_detach_stay_stopped;
+    lldb_private::LazyBool m_watchpoints_trigger_after_instruction;
+    lldb_private::LazyBool m_attach_or_wait_reply;
+    lldb_private::LazyBool m_prepare_for_reg_writing_reply;
+    
+    bool
+        m_supports_qProcessInfoPID:1,
+        m_supports_qfProcessInfo:1,
+        m_supports_qUserName:1,
+        m_supports_qGroupName:1,
+        m_supports_qThreadStopInfo:1,
+        m_supports_z0:1,
+        m_supports_z1:1,
+        m_supports_z2:1,
+        m_supports_z3:1,
+        m_supports_z4:1;
+    
+
+    lldb::tid_t m_curr_tid;         // Current gdb remote protocol thread index for all other operations
+    lldb::tid_t m_curr_tid_run;     // Current gdb remote protocol thread index for continue, step, etc
+
+
+    uint32_t m_num_supported_hardware_watchpoints;
+
+    // If we need to send a packet while the target is running, the m_async_XXX
+    // member variables take care of making this happen.
+    lldb_private::Mutex m_async_mutex;
+    lldb_private::Predicate<bool> m_async_packet_predicate;
+    std::string m_async_packet;
+    StringExtractorGDBRemote m_async_response;
+    int m_async_signal; // We were asked to deliver a signal to the inferior process.
+    bool m_interrupt_sent;
+    std::string m_partial_profile_data;
+    std::map<uint64_t, uint32_t> m_thread_id_to_used_usec_map;
+    
+    lldb_private::ArchSpec m_host_arch;
+    lldb_private::ArchSpec m_process_arch;
+    uint32_t m_os_version_major;
+    uint32_t m_os_version_minor;
+    uint32_t m_os_version_update;
+    std::string m_os_build;
+    std::string m_os_kernel;
+    std::string m_hostname;
+    
+    bool
+    DecodeProcessInfoResponse (StringExtractorGDBRemote &response, 
+                               lldb_private::ProcessInstanceInfo &process_info);
+private:
+    //------------------------------------------------------------------
+    // For GDBRemoteCommunicationClient only
+    //------------------------------------------------------------------
+    DISALLOW_COPY_AND_ASSIGN (GDBRemoteCommunicationClient);
+};
+
+#endif  // liblldb_GDBRemoteCommunicationClient_h_
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
new file mode 100644
index 000000000000..3a14e9fe759a
--- /dev/null
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
@@ -0,0 +1,839 @@
+//===-- GDBRemoteCommunicationServer.cpp ------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+
+#include "GDBRemoteCommunicationServer.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+#include "llvm/ADT/Triple.h"
+#include "lldb/Interpreter/Args.h"
+#include "lldb/Core/ConnectionFileDescriptor.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/State.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Host/Endian.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Host/TimeValue.h"
+#include "lldb/Target/Process.h"
+
+// Project includes
+#include "Utility/StringExtractorGDBRemote.h"
+#include "ProcessGDBRemote.h"
+#include "ProcessGDBRemoteLog.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// GDBRemoteCommunicationServer constructor
+//----------------------------------------------------------------------
+GDBRemoteCommunicationServer::GDBRemoteCommunicationServer(bool is_platform) :
+    GDBRemoteCommunication ("gdb-remote.server", "gdb-remote.server.rx_packet", is_platform),
+    m_async_thread (LLDB_INVALID_HOST_THREAD),
+    m_process_launch_info (),
+    m_process_launch_error (),
+    m_proc_infos (),
+    m_proc_infos_index (0),
+    m_lo_port_num (0),
+    m_hi_port_num (0)
+{
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+GDBRemoteCommunicationServer::~GDBRemoteCommunicationServer()
+{
+}
+
+
+//void *
+//GDBRemoteCommunicationServer::AsyncThread (void *arg)
+//{
+//    GDBRemoteCommunicationServer *server = (GDBRemoteCommunicationServer*) arg;
+//
+//    Log *log;// (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
+//    if (log)
+//        log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %i) thread starting...", __FUNCTION__, arg, process->GetID());
+//
+//    StringExtractorGDBRemote packet;
+//    
+//    while ()
+//    {
+//        if (packet.
+//    }
+//
+//    if (log)
+//        log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %i) thread exiting...", __FUNCTION__, arg, process->GetID());
+//
+//    process->m_async_thread = LLDB_INVALID_HOST_THREAD;
+//    return NULL;
+//}
+//
+bool
+GDBRemoteCommunicationServer::GetPacketAndSendResponse (uint32_t timeout_usec, 
+                                                        Error &error,
+                                                        bool &interrupt, 
+                                                        bool &quit)
+{
+    StringExtractorGDBRemote packet;
+    if (WaitForPacketWithTimeoutMicroSecondsNoLock (packet, timeout_usec))
+    {
+        const StringExtractorGDBRemote::ServerPacketType packet_type = packet.GetServerPacketType ();
+        switch (packet_type)
+        {
+            case StringExtractorGDBRemote::eServerPacketType_nack:
+            case StringExtractorGDBRemote::eServerPacketType_ack:
+                break;
+
+            case StringExtractorGDBRemote::eServerPacketType_invalid:
+                error.SetErrorString("invalid packet");
+                quit = true;
+                break;
+
+            case StringExtractorGDBRemote::eServerPacketType_interrupt:
+                error.SetErrorString("interrupt received");
+                interrupt = true;
+                break;
+            
+            case StringExtractorGDBRemote::eServerPacketType_unimplemented:
+                return SendUnimplementedResponse (packet.GetStringRef().c_str()) > 0;
+
+            case StringExtractorGDBRemote::eServerPacketType_A:
+                return Handle_A (packet);
+
+            case StringExtractorGDBRemote::eServerPacketType_qfProcessInfo:
+                return Handle_qfProcessInfo (packet);
+                
+            case StringExtractorGDBRemote::eServerPacketType_qsProcessInfo:
+                return Handle_qsProcessInfo (packet);
+                
+            case StringExtractorGDBRemote::eServerPacketType_qC:
+                return Handle_qC (packet);
+                
+            case StringExtractorGDBRemote::eServerPacketType_qHostInfo:
+                return Handle_qHostInfo (packet);
+                
+            case StringExtractorGDBRemote::eServerPacketType_qLaunchGDBServer:
+                return Handle_qLaunchGDBServer (packet);
+                
+            case StringExtractorGDBRemote::eServerPacketType_qLaunchSuccess:
+                return Handle_qLaunchSuccess (packet);
+                
+            case StringExtractorGDBRemote::eServerPacketType_qGroupName:
+                return Handle_qGroupName (packet);
+
+            case StringExtractorGDBRemote::eServerPacketType_qProcessInfoPID:
+                return Handle_qProcessInfoPID (packet);
+
+            case StringExtractorGDBRemote::eServerPacketType_qSpeedTest:
+                return Handle_qSpeedTest (packet);
+
+            case StringExtractorGDBRemote::eServerPacketType_qUserName:
+                return Handle_qUserName (packet);
+
+            case StringExtractorGDBRemote::eServerPacketType_QEnvironment:
+                return Handle_QEnvironment (packet);
+            
+            case StringExtractorGDBRemote::eServerPacketType_QSetDisableASLR:
+                return Handle_QSetDisableASLR (packet);
+            
+            case StringExtractorGDBRemote::eServerPacketType_QSetSTDIN:
+                return Handle_QSetSTDIN (packet);
+            
+            case StringExtractorGDBRemote::eServerPacketType_QSetSTDOUT:
+                return Handle_QSetSTDOUT (packet);
+            
+            case StringExtractorGDBRemote::eServerPacketType_QSetSTDERR:
+                return Handle_QSetSTDERR (packet);
+            
+            case StringExtractorGDBRemote::eServerPacketType_QSetWorkingDir:
+                return Handle_QSetWorkingDir (packet);
+
+            case StringExtractorGDBRemote::eServerPacketType_QStartNoAckMode:
+                return Handle_QStartNoAckMode (packet);
+        }
+        return true;
+    }
+    else
+    {
+        if (!IsConnected())
+            error.SetErrorString("lost connection");
+        else
+            error.SetErrorString("timeout");
+    }
+
+    return false;
+}
+
+size_t
+GDBRemoteCommunicationServer::SendUnimplementedResponse (const char *)
+{
+    // TODO: Log the packet we aren't handling...
+    return SendPacketNoLock ("", 0);
+}
+
+size_t
+GDBRemoteCommunicationServer::SendErrorResponse (uint8_t err)
+{
+    char packet[16];
+    int packet_len = ::snprintf (packet, sizeof(packet), "E%2.2x", err);
+    assert (packet_len < (int)sizeof(packet));
+    return SendPacketNoLock (packet, packet_len);
+}
+
+
+size_t
+GDBRemoteCommunicationServer::SendOKResponse ()
+{
+    return SendPacketNoLock ("OK", 2);
+}
+
+bool
+GDBRemoteCommunicationServer::HandshakeWithClient(Error *error_ptr)
+{
+    return GetAck();
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_qHostInfo (StringExtractorGDBRemote &packet)
+{
+    StreamString response;
+    
+    // $cputype:16777223;cpusubtype:3;ostype:Darwin;vendor:apple;endian:little;ptrsize:8;#00
+
+    ArchSpec host_arch (Host::GetArchitecture ());
+    const llvm::Triple &host_triple = host_arch.GetTriple();
+    response.PutCString("triple:");
+    response.PutCStringAsRawHex8(host_triple.getTriple().c_str());
+    response.Printf (";ptrsize:%u;",host_arch.GetAddressByteSize());
+
+    uint32_t cpu = host_arch.GetMachOCPUType();
+    uint32_t sub = host_arch.GetMachOCPUSubType();
+    if (cpu != LLDB_INVALID_CPUTYPE)
+        response.Printf ("cputype:%u;", cpu);
+    if (sub != LLDB_INVALID_CPUTYPE)
+        response.Printf ("cpusubtype:%u;", sub);
+    
+    if (cpu == ArchSpec::kCore_arm_any)
+        response.Printf("watchpoint_exceptions_received:before;");   // On armv7 we use "synchronous" watchpoints which means the exception is delivered before the instruction executes.
+    else
+        response.Printf("watchpoint_exceptions_received:after;");
+    
+    switch (lldb::endian::InlHostByteOrder())
+    {
+    case eByteOrderBig:     response.PutCString ("endian:big;"); break;
+    case eByteOrderLittle:  response.PutCString ("endian:little;"); break;
+    case eByteOrderPDP:     response.PutCString ("endian:pdp;"); break;
+    default:                response.PutCString ("endian:unknown;"); break;
+    }
+    
+    uint32_t major = UINT32_MAX;
+    uint32_t minor = UINT32_MAX;
+    uint32_t update = UINT32_MAX;
+    if (Host::GetOSVersion (major, minor, update))
+    {
+        if (major != UINT32_MAX)
+        {
+            response.Printf("os_version:%u", major);
+            if (minor != UINT32_MAX)
+            {
+                response.Printf(".%u", minor);
+                if (update != UINT32_MAX)
+                    response.Printf(".%u", update);
+            }
+            response.PutChar(';');
+        }
+    }
+
+    std::string s;
+    if (Host::GetOSBuildString (s))
+    {
+        response.PutCString ("os_build:");
+        response.PutCStringAsRawHex8(s.c_str());
+        response.PutChar(';');
+    }
+    if (Host::GetOSKernelDescription (s))
+    {
+        response.PutCString ("os_kernel:");
+        response.PutCStringAsRawHex8(s.c_str());
+        response.PutChar(';');
+    }
+    if (Host::GetHostname (s))
+    {
+        response.PutCString ("hostname:");
+        response.PutCStringAsRawHex8(s.c_str());
+        response.PutChar(';');
+    }
+    
+    return SendPacketNoLock (response.GetData(), response.GetSize()) > 0;
+}
+
+static void
+CreateProcessInfoResponse (const ProcessInstanceInfo &proc_info, StreamString &response)
+{
+    response.Printf ("pid:%" PRIu64 ";ppid:%" PRIu64 ";uid:%i;gid:%i;euid:%i;egid:%i;",
+                     proc_info.GetProcessID(),
+                     proc_info.GetParentProcessID(),
+                     proc_info.GetUserID(),
+                     proc_info.GetGroupID(),
+                     proc_info.GetEffectiveUserID(),
+                     proc_info.GetEffectiveGroupID());
+    response.PutCString ("name:");
+    response.PutCStringAsRawHex8(proc_info.GetName());
+    response.PutChar(';');
+    const ArchSpec &proc_arch = proc_info.GetArchitecture();
+    if (proc_arch.IsValid())
+    {
+        const llvm::Triple &proc_triple = proc_arch.GetTriple();
+        response.PutCString("triple:");
+        response.PutCStringAsRawHex8(proc_triple.getTriple().c_str());
+        response.PutChar(';');
+    }
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_qProcessInfoPID (StringExtractorGDBRemote &packet)
+{
+    // Packet format: "qProcessInfoPID:%i" where %i is the pid
+    packet.SetFilePos(::strlen ("qProcessInfoPID:"));
+    lldb::pid_t pid = packet.GetU32 (LLDB_INVALID_PROCESS_ID);
+    if (pid != LLDB_INVALID_PROCESS_ID)
+    {
+        ProcessInstanceInfo proc_info;
+        if (Host::GetProcessInfo(pid, proc_info))
+        {
+            StreamString response;
+            CreateProcessInfoResponse (proc_info, response);
+            return SendPacketNoLock (response.GetData(), response.GetSize());
+        }
+    }
+    return SendErrorResponse (1);
+}
+
+bool 
+GDBRemoteCommunicationServer::Handle_qfProcessInfo (StringExtractorGDBRemote &packet)
+{
+    m_proc_infos_index = 0;
+    m_proc_infos.Clear();
+
+    ProcessInstanceInfoMatch match_info;
+    packet.SetFilePos(::strlen ("qfProcessInfo"));
+    if (packet.GetChar() == ':')
+    {
+    
+        std::string key;
+        std::string value;
+        while (packet.GetNameColonValue(key, value))
+        {
+            bool success = true;
+            if (key.compare("name") == 0)
+            {
+                StringExtractor extractor;
+                extractor.GetStringRef().swap(value);
+                extractor.GetHexByteString (value);
+                match_info.GetProcessInfo().GetExecutableFile().SetFile(value.c_str(), false);
+            }
+            else if (key.compare("name_match") == 0)
+            {
+                if (value.compare("equals") == 0)
+                {
+                    match_info.SetNameMatchType (eNameMatchEquals);
+                }
+                else if (value.compare("starts_with") == 0)
+                {
+                    match_info.SetNameMatchType (eNameMatchStartsWith);
+                }
+                else if (value.compare("ends_with") == 0)
+                {
+                    match_info.SetNameMatchType (eNameMatchEndsWith);
+                }
+                else if (value.compare("contains") == 0)
+                {
+                    match_info.SetNameMatchType (eNameMatchContains);
+                }
+                else if (value.compare("regex") == 0)       
+                {
+                    match_info.SetNameMatchType (eNameMatchRegularExpression);
+                }
+                else 
+                {
+                    success = false;
+                }
+            }
+            else if (key.compare("pid") == 0)
+            {
+                match_info.GetProcessInfo().SetProcessID (Args::StringToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0, &success));
+            }
+            else if (key.compare("parent_pid") == 0)
+            {
+                match_info.GetProcessInfo().SetParentProcessID (Args::StringToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0, &success));
+            }
+            else if (key.compare("uid") == 0)
+            {
+                match_info.GetProcessInfo().SetUserID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
+            }
+            else if (key.compare("gid") == 0)
+            {
+                match_info.GetProcessInfo().SetGroupID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
+            }
+            else if (key.compare("euid") == 0)
+            {
+                match_info.GetProcessInfo().SetEffectiveUserID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
+            }
+            else if (key.compare("egid") == 0)
+            {
+                match_info.GetProcessInfo().SetEffectiveGroupID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
+            }
+            else if (key.compare("all_users") == 0)
+            {
+                match_info.SetMatchAllUsers(Args::StringToBoolean(value.c_str(), false, &success));
+            }
+            else if (key.compare("triple") == 0)
+            {
+                match_info.GetProcessInfo().GetArchitecture().SetTriple (value.c_str(), NULL);
+            }
+            else
+            {
+                success = false;
+            }
+            
+            if (!success)
+                return SendErrorResponse (2);
+        }
+    }
+
+    if (Host::FindProcesses (match_info, m_proc_infos))
+    {
+        // We found something, return the first item by calling the get
+        // subsequent process info packet handler...
+        return Handle_qsProcessInfo (packet);
+    }
+    return SendErrorResponse (3);
+}
+
+bool 
+GDBRemoteCommunicationServer::Handle_qsProcessInfo (StringExtractorGDBRemote &packet)
+{
+    if (m_proc_infos_index < m_proc_infos.GetSize())
+    {
+        StreamString response;
+        CreateProcessInfoResponse (m_proc_infos.GetProcessInfoAtIndex(m_proc_infos_index), response);
+        ++m_proc_infos_index;
+        return SendPacketNoLock (response.GetData(), response.GetSize());
+    }
+    return SendErrorResponse (4);
+}
+
+bool 
+GDBRemoteCommunicationServer::Handle_qUserName (StringExtractorGDBRemote &packet)
+{
+    // Packet format: "qUserName:%i" where %i is the uid
+    packet.SetFilePos(::strlen ("qUserName:"));
+    uint32_t uid = packet.GetU32 (UINT32_MAX);
+    if (uid != UINT32_MAX)
+    {
+        std::string name;
+        if (Host::GetUserName (uid, name))
+        {
+            StreamString response;
+            response.PutCStringAsRawHex8 (name.c_str());
+            return SendPacketNoLock (response.GetData(), response.GetSize());
+        }
+    }
+    return SendErrorResponse (5);
+    
+}
+
+bool 
+GDBRemoteCommunicationServer::Handle_qGroupName (StringExtractorGDBRemote &packet)
+{
+    // Packet format: "qGroupName:%i" where %i is the gid
+    packet.SetFilePos(::strlen ("qGroupName:"));
+    uint32_t gid = packet.GetU32 (UINT32_MAX);
+    if (gid != UINT32_MAX)
+    {
+        std::string name;
+        if (Host::GetGroupName (gid, name))
+        {
+            StreamString response;
+            response.PutCStringAsRawHex8 (name.c_str());
+            return SendPacketNoLock (response.GetData(), response.GetSize());
+        }
+    }
+    return SendErrorResponse (6);
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_qSpeedTest (StringExtractorGDBRemote &packet)
+{
+    packet.SetFilePos(::strlen ("qSpeedTest:"));
+
+    std::string key;
+    std::string value;
+    bool success = packet.GetNameColonValue(key, value);
+    if (success && key.compare("response_size") == 0)
+    {
+        uint32_t response_size = Args::StringToUInt32(value.c_str(), 0, 0, &success);
+        if (success)
+        {
+            if (response_size == 0)
+                return SendOKResponse();
+            StreamString response;
+            uint32_t bytes_left = response_size;
+            response.PutCString("data:");
+            while (bytes_left > 0)
+            {
+                if (bytes_left >= 26)
+                {
+                    response.PutCString("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
+                    bytes_left -= 26;
+                }
+                else
+                {
+                    response.Printf ("%*.*s;", bytes_left, bytes_left, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
+                    bytes_left = 0;
+                }
+            }
+            return SendPacketNoLock (response.GetData(), response.GetSize());
+        }
+    }
+    return SendErrorResponse (7);
+}
+
+
+static void *
+AcceptPortFromInferior (void *arg)
+{
+    const char *connect_url = (const char *)arg;
+    ConnectionFileDescriptor file_conn;
+    Error error;
+    if (file_conn.Connect (connect_url, &error) == eConnectionStatusSuccess)
+    {
+        char pid_str[256];
+        ::memset (pid_str, 0, sizeof(pid_str));
+        ConnectionStatus status;
+        const size_t pid_str_len = file_conn.Read (pid_str, sizeof(pid_str), 0, status, NULL);
+        if (pid_str_len > 0)
+        {
+            int pid = atoi (pid_str);
+            return (void *)(intptr_t)pid;
+        }
+    }
+    return NULL;
+}
+//
+//static bool
+//WaitForProcessToSIGSTOP (const lldb::pid_t pid, const int timeout_in_seconds)
+//{
+//    const int time_delta_usecs = 100000;
+//    const int num_retries = timeout_in_seconds/time_delta_usecs;
+//    for (int i=0; i<num_retries; i++)
+//    {
+//        struct proc_bsdinfo bsd_info;
+//        int error = ::proc_pidinfo (pid, PROC_PIDTBSDINFO, 
+//                                    (uint64_t) 0, 
+//                                    &bsd_info, 
+//                                    PROC_PIDTBSDINFO_SIZE);
+//        
+//        switch (error)
+//        {
+//            case EINVAL:
+//            case ENOTSUP:
+//            case ESRCH:
+//            case EPERM:
+//                return false;
+//                
+//            default:
+//                break;
+//                
+//            case 0:
+//                if (bsd_info.pbi_status == SSTOP)
+//                    return true;
+//        }
+//        ::usleep (time_delta_usecs);
+//    }
+//    return false;
+//}
+
+bool
+GDBRemoteCommunicationServer::Handle_A (StringExtractorGDBRemote &packet)
+{
+    // The 'A' packet is the most over designed packet ever here with 
+    // redundant argument indexes, redundant argument lengths and needed hex 
+    // encoded argument string values. Really all that is needed is a comma 
+    // separated hex encoded argument value list, but we will stay true to the
+    // documented version of the 'A' packet here...
+
+    packet.SetFilePos(1); // Skip the 'A'
+    bool success = true;
+    while (success && packet.GetBytesLeft() > 0)
+    {
+        // Decode the decimal argument string length. This length is the
+        // number of hex nibbles in the argument string value.
+        const uint32_t arg_len = packet.GetU32(UINT32_MAX);
+        if (arg_len == UINT32_MAX)
+            success = false;
+        else
+        {
+            // Make sure the argument hex string length is followed by a comma
+            if (packet.GetChar() != ',')
+                success = false;
+            else
+            {
+                // Decode the argument index. We ignore this really becuase
+                // who would really send down the arguments in a random order???
+                const uint32_t arg_idx = packet.GetU32(UINT32_MAX);
+                if (arg_idx == UINT32_MAX)
+                    success = false;
+                else
+                {
+                    // Make sure the argument index is followed by a comma
+                    if (packet.GetChar() != ',')
+                        success = false;
+                    else
+                    {
+                        // Decode the argument string value from hex bytes
+                        // back into a UTF8 string and make sure the length
+                        // matches the one supplied in the packet
+                        std::string arg;
+                        if (packet.GetHexByteString(arg) != (arg_len / 2))
+                            success = false;
+                        else
+                        {
+                            // If there are any bytes lft
+                            if (packet.GetBytesLeft())
+                            {
+                                if (packet.GetChar() != ',')
+                                    success = false;
+                            }
+                            
+                            if (success)
+                            {
+                                if (arg_idx == 0)
+                                    m_process_launch_info.GetExecutableFile().SetFile(arg.c_str(), false);
+                                m_process_launch_info.GetArguments().AppendArgument(arg.c_str());
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    if (success)
+    {
+        m_process_launch_info.GetFlags().Set (eLaunchFlagDebug);
+        m_process_launch_error = Host::LaunchProcess (m_process_launch_info);
+        if (m_process_launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID)
+        {
+            return SendOKResponse ();
+        }
+    }
+    return SendErrorResponse (8);
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_qC (StringExtractorGDBRemote &packet)
+{
+    lldb::pid_t pid = m_process_launch_info.GetProcessID();
+    StreamString response;
+    response.Printf("QC%" PRIx64, pid);
+    if (m_is_platform)
+    {
+        // If we launch a process and this GDB server is acting as a platform, 
+        // then we need to clear the process launch state so we can start 
+        // launching another process. In order to launch a process a bunch or
+        // packets need to be sent: environment packets, working directory,
+        // disable ASLR, and many more settings. When we launch a process we 
+        // then need to know when to clear this information. Currently we are
+        // selecting the 'qC' packet as that packet which seems to make the most
+        // sense.
+        if (pid != LLDB_INVALID_PROCESS_ID)
+        {
+            m_process_launch_info.Clear();
+        }
+    }
+    return SendPacketNoLock (response.GetData(), response.GetSize());
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet)
+{
+    // Spawn a local debugserver as a platform so we can then attach or launch
+    // a process...
+
+    if (m_is_platform)
+    {
+        // Sleep and wait a bit for debugserver to start to listen...
+        ConnectionFileDescriptor file_conn;
+        char connect_url[PATH_MAX];
+        Error error;
+        char unix_socket_name[PATH_MAX] = "/tmp/XXXXXX";    
+        if (::mktemp (unix_socket_name) == NULL)
+        {
+            error.SetErrorString ("failed to make temporary path for a unix socket");
+        }
+        else
+        {
+            ::snprintf (connect_url, sizeof(connect_url), "unix-accept://%s", unix_socket_name);
+            // Spawn a new thread to accept the port that gets bound after
+            // binding to port 0 (zero).
+            lldb::thread_t accept_thread = Host::ThreadCreate (unix_socket_name,
+                                                               AcceptPortFromInferior,
+                                                               connect_url,
+                                                               &error);
+            
+            if (IS_VALID_LLDB_HOST_THREAD(accept_thread))
+            {
+                // Spawn a debugserver and try to get
+                ProcessLaunchInfo debugserver_launch_info;
+                error = StartDebugserverProcess ("localhost:0", 
+                                                 unix_socket_name, 
+                                                 debugserver_launch_info);
+                
+                lldb::pid_t debugserver_pid = debugserver_launch_info.GetProcessID();
+                if (error.Success())
+                {
+                    bool success = false;
+                    
+                    thread_result_t accept_thread_result = NULL;
+                    if (Host::ThreadJoin (accept_thread, &accept_thread_result, &error))
+                    {
+                        if (accept_thread_result)
+                        {
+                            uint16_t port = (intptr_t)accept_thread_result;
+                            char response[256];
+                            const int response_len = ::snprintf (response, sizeof(response), "pid:%" PRIu64 ";port:%u;", debugserver_pid, port);
+                            assert (response_len < (int)sizeof(response));
+                            //m_port_to_pid_map[port] = debugserver_launch_info.GetProcessID();
+                            success = SendPacketNoLock (response, response_len) > 0;
+                        }
+                    }
+                    ::unlink (unix_socket_name);
+                    
+                    if (!success)
+                    {
+                        if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
+                            ::kill (debugserver_pid, SIGINT);
+                    }
+                    return success;
+                }
+            }
+        }
+    }
+    return SendErrorResponse (13);
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_qLaunchSuccess (StringExtractorGDBRemote &packet)
+{
+    if (m_process_launch_error.Success())
+        return SendOKResponse();
+    StreamString response;    
+    response.PutChar('E');
+    response.PutCString(m_process_launch_error.AsCString("<unknown error>"));
+    return SendPacketNoLock (response.GetData(), response.GetSize());
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_QEnvironment  (StringExtractorGDBRemote &packet)
+{
+    packet.SetFilePos(::strlen ("QEnvironment:"));
+    const uint32_t bytes_left = packet.GetBytesLeft();
+    if (bytes_left > 0)
+    {
+        m_process_launch_info.GetEnvironmentEntries ().AppendArgument (packet.Peek());
+        return SendOKResponse ();
+    }
+    return SendErrorResponse (9);
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_QSetDisableASLR (StringExtractorGDBRemote &packet)
+{
+    packet.SetFilePos(::strlen ("QSetDisableASLR:"));
+    if (packet.GetU32(0))
+        m_process_launch_info.GetFlags().Set (eLaunchFlagDisableASLR);
+    else
+        m_process_launch_info.GetFlags().Clear (eLaunchFlagDisableASLR);
+    return SendOKResponse ();
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_QSetWorkingDir (StringExtractorGDBRemote &packet)
+{
+    packet.SetFilePos(::strlen ("QSetWorkingDir:"));
+    std::string path;
+    packet.GetHexByteString(path);
+    m_process_launch_info.SwapWorkingDirectory (path);
+    return SendOKResponse ();
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_QSetSTDIN (StringExtractorGDBRemote &packet)
+{
+    packet.SetFilePos(::strlen ("QSetSTDIN:"));
+    ProcessLaunchInfo::FileAction file_action;
+    std::string path;
+    packet.GetHexByteString(path);
+    const bool read = false;
+    const bool write = true;
+    if (file_action.Open(STDIN_FILENO, path.c_str(), read, write))
+    {
+        m_process_launch_info.AppendFileAction(file_action);
+        return SendOKResponse ();
+    }
+    return SendErrorResponse (10);
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_QSetSTDOUT (StringExtractorGDBRemote &packet)
+{
+    packet.SetFilePos(::strlen ("QSetSTDOUT:"));
+    ProcessLaunchInfo::FileAction file_action;
+    std::string path;
+    packet.GetHexByteString(path);
+    const bool read = true;
+    const bool write = false;
+    if (file_action.Open(STDOUT_FILENO, path.c_str(), read, write))
+    {
+        m_process_launch_info.AppendFileAction(file_action);
+        return SendOKResponse ();
+    }
+    return SendErrorResponse (11);
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_QSetSTDERR (StringExtractorGDBRemote &packet)
+{
+    packet.SetFilePos(::strlen ("QSetSTDERR:"));
+    ProcessLaunchInfo::FileAction file_action;
+    std::string path;
+    packet.GetHexByteString(path);
+    const bool read = true;
+    const bool write = false;
+    if (file_action.Open(STDERR_FILENO, path.c_str(), read, write))
+    {
+        m_process_launch_info.AppendFileAction(file_action);
+        return SendOKResponse ();
+    }
+    return SendErrorResponse (12);
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_QStartNoAckMode (StringExtractorGDBRemote &packet)
+{
+    // Send response first before changing m_send_acks to we ack this packet
+    SendOKResponse ();
+    m_send_acks = false;
+    return true;
+}
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
new file mode 100644
index 000000000000..cce0e4e64c1e
--- /dev/null
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
@@ -0,0 +1,147 @@
+//===-- GDBRemoteCommunicationServer.h --------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_GDBRemoteCommunicationServer_h_
+#define liblldb_GDBRemoteCommunicationServer_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Target/Process.h"
+
+#include "GDBRemoteCommunication.h"
+
+class ProcessGDBRemote;
+class StringExtractorGDBRemote;
+
+class GDBRemoteCommunicationServer : public GDBRemoteCommunication
+{
+public:
+    enum
+    {
+        eBroadcastBitRunPacketSent = kLoUserBroadcastBit
+    };
+    //------------------------------------------------------------------
+    // Constructors and Destructors
+    //------------------------------------------------------------------
+    GDBRemoteCommunicationServer(bool is_platform);
+
+    virtual
+    ~GDBRemoteCommunicationServer();
+
+    bool
+    GetPacketAndSendResponse (uint32_t timeout_usec,
+                              lldb_private::Error &error,
+                              bool &interrupt, 
+                              bool &quit);
+
+    virtual bool
+    GetThreadSuffixSupported ()
+    {
+        return true;
+    }
+
+    // After connecting, do a little handshake with the client to make sure
+    // we are at least communicating
+    bool
+    HandshakeWithClient (lldb_private::Error *error_ptr);
+
+    // Set both ports to zero to let the platform automatically bind to 
+    // a port chosen by the OS.
+    void
+    SetPortRange (uint16_t lo_port_num, uint16_t hi_port_num)
+    {
+        m_lo_port_num = lo_port_num;
+        m_hi_port_num = hi_port_num;
+    }
+
+protected:
+    //typedef std::map<uint16_t, lldb::pid_t> PortToPIDMap;
+
+    lldb::thread_t m_async_thread;
+    lldb_private::ProcessLaunchInfo m_process_launch_info;
+    lldb_private::Error m_process_launch_error;
+    lldb_private::ProcessInstanceInfoList m_proc_infos;
+    uint32_t m_proc_infos_index;
+    uint16_t m_lo_port_num;
+    uint16_t m_hi_port_num;
+    //PortToPIDMap m_port_to_pid_map;
+
+    size_t
+    SendUnimplementedResponse (const char *packet);
+
+    size_t
+    SendErrorResponse (uint8_t error);
+
+    size_t
+    SendOKResponse ();
+
+    bool
+    Handle_A (StringExtractorGDBRemote &packet);
+
+    bool
+    Handle_qLaunchSuccess (StringExtractorGDBRemote &packet);
+
+    bool
+    Handle_qHostInfo (StringExtractorGDBRemote &packet);
+    
+    bool
+    Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet);
+
+    bool
+    Handle_qProcessInfoPID (StringExtractorGDBRemote &packet);
+    
+    bool
+    Handle_qfProcessInfo (StringExtractorGDBRemote &packet);
+    
+    bool 
+    Handle_qsProcessInfo (StringExtractorGDBRemote &packet);
+
+    bool
+    Handle_qC (StringExtractorGDBRemote &packet);
+
+    bool 
+    Handle_qUserName (StringExtractorGDBRemote &packet);
+
+    bool 
+    Handle_qGroupName (StringExtractorGDBRemote &packet);
+
+    bool
+    Handle_qSpeedTest (StringExtractorGDBRemote &packet);
+
+    bool
+    Handle_QEnvironment  (StringExtractorGDBRemote &packet);
+    
+    bool
+    Handle_QSetDisableASLR (StringExtractorGDBRemote &packet);
+
+    bool
+    Handle_QSetWorkingDir (StringExtractorGDBRemote &packet);
+
+    bool
+    Handle_QStartNoAckMode (StringExtractorGDBRemote &packet);
+
+    bool
+    Handle_QSetSTDIN (StringExtractorGDBRemote &packet);
+
+    bool
+    Handle_QSetSTDOUT (StringExtractorGDBRemote &packet);
+
+    bool
+    Handle_QSetSTDERR (StringExtractorGDBRemote &packet);
+    
+private:
+    //------------------------------------------------------------------
+    // For GDBRemoteCommunicationServer only
+    //------------------------------------------------------------------
+    DISALLOW_COPY_AND_ASSIGN (GDBRemoteCommunicationServer);
+};
+
+#endif  // liblldb_GDBRemoteCommunicationServer_h_
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
new file mode 100644
index 000000000000..b1612a5f3c2f
--- /dev/null
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
@@ -0,0 +1,971 @@
+//===-- GDBRemoteRegisterContext.cpp ----------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "GDBRemoteRegisterContext.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/RegisterValue.h"
+#include "lldb/Core/Scalar.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Utility/Utils.h"
+// Project includes
+#include "Utility/StringExtractorGDBRemote.h"
+#include "ProcessGDBRemote.h"
+#include "ProcessGDBRemoteLog.h"
+#include "ThreadGDBRemote.h"
+#include "Utility/ARM_GCC_Registers.h"
+#include "Utility/ARM_DWARF_Registers.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// GDBRemoteRegisterContext constructor
+//----------------------------------------------------------------------
+GDBRemoteRegisterContext::GDBRemoteRegisterContext
+(
+    ThreadGDBRemote &thread,
+    uint32_t concrete_frame_idx,
+    GDBRemoteDynamicRegisterInfo &reg_info,
+    bool read_all_at_once
+) :
+    RegisterContext (thread, concrete_frame_idx),
+    m_reg_info (reg_info),
+    m_reg_valid (),
+    m_reg_data (),
+    m_read_all_at_once (read_all_at_once)
+{
+    // Resize our vector of bools to contain one bool for every register.
+    // We will use these boolean values to know when a register value
+    // is valid in m_reg_data.
+    m_reg_valid.resize (reg_info.GetNumRegisters());
+
+    // Make a heap based buffer that is big enough to store all registers
+    DataBufferSP reg_data_sp(new DataBufferHeap (reg_info.GetRegisterDataByteSize(), 0));
+    m_reg_data.SetData (reg_data_sp);
+
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+GDBRemoteRegisterContext::~GDBRemoteRegisterContext()
+{
+}
+
+void
+GDBRemoteRegisterContext::InvalidateAllRegisters ()
+{
+    SetAllRegisterValid (false);
+}
+
+void
+GDBRemoteRegisterContext::SetAllRegisterValid (bool b)
+{
+    std::vector<bool>::iterator pos, end = m_reg_valid.end();
+    for (pos = m_reg_valid.begin(); pos != end; ++pos)
+        *pos = b;
+}
+
+size_t
+GDBRemoteRegisterContext::GetRegisterCount ()
+{
+    return m_reg_info.GetNumRegisters ();
+}
+
+const RegisterInfo *
+GDBRemoteRegisterContext::GetRegisterInfoAtIndex (size_t reg)
+{
+    return m_reg_info.GetRegisterInfoAtIndex (reg);
+}
+
+size_t
+GDBRemoteRegisterContext::GetRegisterSetCount ()
+{
+    return m_reg_info.GetNumRegisterSets ();
+}
+
+
+
+const RegisterSet *
+GDBRemoteRegisterContext::GetRegisterSet (size_t reg_set)
+{
+    return m_reg_info.GetRegisterSet (reg_set);
+}
+
+
+
+bool
+GDBRemoteRegisterContext::ReadRegister (const RegisterInfo *reg_info, RegisterValue &value)
+{
+    // Read the register
+    if (ReadRegisterBytes (reg_info, m_reg_data))
+    {
+        const bool partial_data_ok = false;
+        Error error (value.SetValueFromData(reg_info, m_reg_data, reg_info->byte_offset, partial_data_ok));
+        return error.Success();
+    }
+    return false;
+}
+
+bool
+GDBRemoteRegisterContext::PrivateSetRegisterValue (uint32_t reg, StringExtractor &response)
+{
+    const RegisterInfo *reg_info = GetRegisterInfoAtIndex (reg);
+    if (reg_info == NULL)
+        return false;
+
+    // Invalidate if needed
+    InvalidateIfNeeded(false);
+
+    const uint32_t reg_byte_size = reg_info->byte_size;
+    const size_t bytes_copied = response.GetHexBytes (const_cast<uint8_t*>(m_reg_data.PeekData(reg_info->byte_offset, reg_byte_size)), reg_byte_size, '\xcc');
+    bool success = bytes_copied == reg_byte_size;
+    if (success)
+    {
+        SetRegisterIsValid(reg, true);
+    }
+    else if (bytes_copied > 0)
+    {
+        // Only set register is valid to false if we copied some bytes, else
+        // leave it as it was.
+        SetRegisterIsValid(reg, false);
+    }
+    return success;
+}
+
+// Helper function for GDBRemoteRegisterContext::ReadRegisterBytes().
+bool
+GDBRemoteRegisterContext::GetPrimordialRegister(const lldb_private::RegisterInfo *reg_info,
+                                                GDBRemoteCommunicationClient &gdb_comm)
+{
+    char packet[64];
+    StringExtractorGDBRemote response;
+    int packet_len = 0;
+    const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
+    if (gdb_comm.GetThreadSuffixSupported())
+        packet_len = ::snprintf (packet, sizeof(packet), "p%x;thread:%4.4" PRIx64 ";", reg, m_thread.GetProtocolID());
+    else
+        packet_len = ::snprintf (packet, sizeof(packet), "p%x", reg);
+    assert (packet_len < ((int)sizeof(packet) - 1));
+    if (gdb_comm.SendPacketAndWaitForResponse(packet, response, false))
+        return PrivateSetRegisterValue (reg, response);
+
+    return false;
+}
+bool
+GDBRemoteRegisterContext::ReadRegisterBytes (const RegisterInfo *reg_info, DataExtractor &data)
+{
+    ExecutionContext exe_ctx (CalculateThread());
+
+    Process *process = exe_ctx.GetProcessPtr();
+    Thread *thread = exe_ctx.GetThreadPtr();
+    if (process == NULL || thread == NULL)
+        return false;
+
+    GDBRemoteCommunicationClient &gdb_comm (((ProcessGDBRemote *)process)->GetGDBRemote());
+
+    InvalidateIfNeeded(false);
+
+    const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
+
+    if (!GetRegisterIsValid(reg))
+    {
+        Mutex::Locker locker;
+        if (gdb_comm.GetSequenceMutex (locker, "Didn't get sequence mutex for read register."))
+        {
+            const bool thread_suffix_supported = gdb_comm.GetThreadSuffixSupported();
+            ProcessSP process_sp (m_thread.GetProcess());
+            if (thread_suffix_supported || static_cast<ProcessGDBRemote *>(process_sp.get())->GetGDBRemote().SetCurrentThread(m_thread.GetProtocolID()))
+            {
+                char packet[64];
+                StringExtractorGDBRemote response;
+                int packet_len = 0;
+                if (m_read_all_at_once)
+                {
+                    // Get all registers in one packet
+                    if (thread_suffix_supported)
+                        packet_len = ::snprintf (packet, sizeof(packet), "g;thread:%4.4" PRIx64 ";", m_thread.GetProtocolID());
+                    else
+                        packet_len = ::snprintf (packet, sizeof(packet), "g");
+                    assert (packet_len < ((int)sizeof(packet) - 1));
+                    if (gdb_comm.SendPacketAndWaitForResponse(packet, response, false))
+                    {
+                        if (response.IsNormalResponse())
+                            if (response.GetHexBytes ((void *)m_reg_data.GetDataStart(), m_reg_data.GetByteSize(), '\xcc') == m_reg_data.GetByteSize())
+                                SetAllRegisterValid (true);
+                    }
+                }
+                else if (reg_info->value_regs)
+                {
+                    // Process this composite register request by delegating to the constituent
+                    // primordial registers.
+                    
+                    // Index of the primordial register.
+                    bool success = true;
+                    for (uint32_t idx = 0; success; ++idx)
+                    {
+                        const uint32_t prim_reg = reg_info->value_regs[idx];
+                        if (prim_reg == LLDB_INVALID_REGNUM)
+                            break;
+                        // We have a valid primordial regsiter as our constituent.
+                        // Grab the corresponding register info.
+                        const RegisterInfo *prim_reg_info = GetRegisterInfoAtIndex(prim_reg);
+                        if (prim_reg_info == NULL)
+                            success = false;
+                        else
+                        {
+                            // Read the containing register if it hasn't already been read
+                            if (!GetRegisterIsValid(prim_reg))
+                                success = GetPrimordialRegister(prim_reg_info, gdb_comm);
+                        }
+                    }
+
+                    if (success)
+                    {
+                        // If we reach this point, all primordial register requests have succeeded.
+                        // Validate this composite register.
+                        SetRegisterIsValid (reg_info, true);
+                    }
+                }
+                else
+                {
+                    // Get each register individually
+                    GetPrimordialRegister(reg_info, gdb_comm);
+                }
+            }
+        }
+        else
+        {
+#if LLDB_CONFIGURATION_DEBUG
+            StreamString strm;
+            gdb_comm.DumpHistory(strm);
+            Host::SetCrashDescription (strm.GetData());
+            assert (!"Didn't get sequence mutex for read register.");
+#else
+            Log *log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_THREAD | GDBR_LOG_PACKETS));
+            if (log)
+            {
+                if (log->GetVerbose())
+                {
+                    StreamString strm;
+                    gdb_comm.DumpHistory(strm);
+                    log->Printf("error: failed to get packet sequence mutex, not sending read register for \"%s\":\n%s", reg_info->name, strm.GetData());
+                }
+                else
+                {
+                    log->Printf("error: failed to get packet sequence mutex, not sending read register for \"%s\"", reg_info->name);
+                }
+            }
+#endif
+        }
+
+        // Make sure we got a valid register value after reading it
+        if (!GetRegisterIsValid(reg))
+            return false;
+    }
+
+    if (&data != &m_reg_data)
+    {
+        // If we aren't extracting into our own buffer (which
+        // only happens when this function is called from
+        // ReadRegisterValue(uint32_t, Scalar&)) then
+        // we transfer bytes from our buffer into the data
+        // buffer that was passed in
+        data.SetByteOrder (m_reg_data.GetByteOrder());
+        data.SetData (m_reg_data, reg_info->byte_offset, reg_info->byte_size);
+    }
+    return true;
+}
+
+bool
+GDBRemoteRegisterContext::WriteRegister (const RegisterInfo *reg_info,
+                                         const RegisterValue &value)
+{
+    DataExtractor data;
+    if (value.GetData (data))
+        return WriteRegisterBytes (reg_info, data, 0);
+    return false;
+}
+
+// Helper function for GDBRemoteRegisterContext::WriteRegisterBytes().
+bool
+GDBRemoteRegisterContext::SetPrimordialRegister(const lldb_private::RegisterInfo *reg_info,
+                                                GDBRemoteCommunicationClient &gdb_comm)
+{
+    StreamString packet;
+    StringExtractorGDBRemote response;
+    const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
+    packet.Printf ("P%x=", reg);
+    packet.PutBytesAsRawHex8 (m_reg_data.PeekData(reg_info->byte_offset, reg_info->byte_size),
+                              reg_info->byte_size,
+                              lldb::endian::InlHostByteOrder(),
+                              lldb::endian::InlHostByteOrder());
+
+    if (gdb_comm.GetThreadSuffixSupported())
+        packet.Printf (";thread:%4.4" PRIx64 ";", m_thread.GetProtocolID());
+
+    // Invalidate just this register
+    SetRegisterIsValid(reg, false);
+    if (gdb_comm.SendPacketAndWaitForResponse(packet.GetString().c_str(),
+                                              packet.GetString().size(),
+                                              response,
+                                              false))
+    {
+        if (response.IsOKResponse())
+            return true;
+    }
+    return false;
+}
+
+void
+GDBRemoteRegisterContext::SyncThreadState(Process *process)
+{
+    // NB.  We assume our caller has locked the sequence mutex.
+    
+    GDBRemoteCommunicationClient &gdb_comm (((ProcessGDBRemote *) process)->GetGDBRemote());
+    if (!gdb_comm.GetSyncThreadStateSupported())
+        return;
+
+    StreamString packet;
+    StringExtractorGDBRemote response;
+    packet.Printf ("QSyncThreadState:%4.4" PRIx64 ";", m_thread.GetProtocolID());
+    if (gdb_comm.SendPacketAndWaitForResponse(packet.GetString().c_str(),
+                                              packet.GetString().size(),
+                                              response,
+                                              false))
+    {
+        if (response.IsOKResponse())
+            InvalidateAllRegisters();
+    }
+}
+
+bool
+GDBRemoteRegisterContext::WriteRegisterBytes (const lldb_private::RegisterInfo *reg_info, DataExtractor &data, uint32_t data_offset)
+{
+    ExecutionContext exe_ctx (CalculateThread());
+
+    Process *process = exe_ctx.GetProcessPtr();
+    Thread *thread = exe_ctx.GetThreadPtr();
+    if (process == NULL || thread == NULL)
+        return false;
+
+    GDBRemoteCommunicationClient &gdb_comm (((ProcessGDBRemote *)process)->GetGDBRemote());
+// FIXME: This check isn't right because IsRunning checks the Public state, but this
+// is work you need to do - for instance in ShouldStop & friends - before the public
+// state has been changed.
+//    if (gdb_comm.IsRunning())
+//        return false;
+
+    // Grab a pointer to where we are going to put this register
+    uint8_t *dst = const_cast<uint8_t*>(m_reg_data.PeekData(reg_info->byte_offset, reg_info->byte_size));
+
+    if (dst == NULL)
+        return false;
+
+
+    if (data.CopyByteOrderedData (data_offset,                  // src offset
+                                  reg_info->byte_size,          // src length
+                                  dst,                          // dst
+                                  reg_info->byte_size,          // dst length
+                                  m_reg_data.GetByteOrder()))   // dst byte order
+    {
+        Mutex::Locker locker;
+        if (gdb_comm.GetSequenceMutex (locker, "Didn't get sequence mutex for write register."))
+        {
+            const bool thread_suffix_supported = gdb_comm.GetThreadSuffixSupported();
+            ProcessSP process_sp (m_thread.GetProcess());
+            if (thread_suffix_supported || static_cast<ProcessGDBRemote *>(process_sp.get())->GetGDBRemote().SetCurrentThread(m_thread.GetProtocolID()))
+            {
+                StreamString packet;
+                StringExtractorGDBRemote response;
+                
+                if (m_read_all_at_once)
+                {
+                    // Set all registers in one packet
+                    packet.PutChar ('G');
+                    packet.PutBytesAsRawHex8 (m_reg_data.GetDataStart(),
+                                              m_reg_data.GetByteSize(),
+                                              lldb::endian::InlHostByteOrder(),
+                                              lldb::endian::InlHostByteOrder());
+
+                    if (thread_suffix_supported)
+                        packet.Printf (";thread:%4.4" PRIx64 ";", m_thread.GetProtocolID());
+
+                    // Invalidate all register values
+                    InvalidateIfNeeded (true);
+
+                    if (gdb_comm.SendPacketAndWaitForResponse(packet.GetString().c_str(),
+                                                              packet.GetString().size(),
+                                                              response,
+                                                              false))
+                    {
+                        SetAllRegisterValid (false);
+                        if (response.IsOKResponse())
+                        {
+                            return true;
+                        }
+                    }
+                }
+                else
+                {
+                    bool success = true;
+
+                    if (reg_info->value_regs)
+                    {
+                        // This register is part of another register. In this case we read the actual
+                        // register data for any "value_regs", and once all that data is read, we will
+                        // have enough data in our register context bytes for the value of this register
+                        
+                        // Invalidate this composite register first.
+                        
+                        for (uint32_t idx = 0; success; ++idx)
+                        {
+                            const uint32_t reg = reg_info->value_regs[idx];
+                            if (reg == LLDB_INVALID_REGNUM)
+                                break;
+                            // We have a valid primordial regsiter as our constituent.
+                            // Grab the corresponding register info.
+                            const RegisterInfo *value_reg_info = GetRegisterInfoAtIndex(reg);
+                            if (value_reg_info == NULL)
+                                success = false;
+                            else
+                                success = SetPrimordialRegister(value_reg_info, gdb_comm);
+                        }
+                    }
+                    else
+                    {
+                        // This is an actual register, write it
+                        success = SetPrimordialRegister(reg_info, gdb_comm);
+                    }
+
+                    // Check if writing this register will invalidate any other register values?
+                    // If so, invalidate them
+                    if (reg_info->invalidate_regs)
+                    {
+                        for (uint32_t idx = 0, reg = reg_info->invalidate_regs[0];
+                             reg != LLDB_INVALID_REGNUM;
+                             reg = reg_info->invalidate_regs[++idx])
+                        {
+                            SetRegisterIsValid(reg, false);
+                        }
+                    }
+                    
+                    return success;
+                }
+            }
+        }
+        else
+        {
+            Log *log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_THREAD | GDBR_LOG_PACKETS));
+            if (log)
+            {
+                if (log->GetVerbose())
+                {
+                    StreamString strm;
+                    gdb_comm.DumpHistory(strm);
+                    log->Printf("error: failed to get packet sequence mutex, not sending write register for \"%s\":\n%s", reg_info->name, strm.GetData());
+                }
+                else
+                    log->Printf("error: failed to get packet sequence mutex, not sending write register for \"%s\"", reg_info->name);
+            }
+        }
+    }
+    return false;
+}
+
+
+bool
+GDBRemoteRegisterContext::ReadAllRegisterValues (lldb::DataBufferSP &data_sp)
+{
+    ExecutionContext exe_ctx (CalculateThread());
+
+    Process *process = exe_ctx.GetProcessPtr();
+    Thread *thread = exe_ctx.GetThreadPtr();
+    if (process == NULL || thread == NULL)
+        return false;
+
+    GDBRemoteCommunicationClient &gdb_comm (((ProcessGDBRemote *)process)->GetGDBRemote());
+
+    StringExtractorGDBRemote response;
+
+    Mutex::Locker locker;
+    if (gdb_comm.GetSequenceMutex (locker, "Didn't get sequence mutex for read all registers."))
+    {
+        SyncThreadState(process);
+        
+        char packet[32];
+        const bool thread_suffix_supported = gdb_comm.GetThreadSuffixSupported();
+        ProcessSP process_sp (m_thread.GetProcess());
+        if (thread_suffix_supported || static_cast<ProcessGDBRemote *>(process_sp.get())->GetGDBRemote().SetCurrentThread(m_thread.GetProtocolID()))
+        {
+            int packet_len = 0;
+            if (thread_suffix_supported)
+                packet_len = ::snprintf (packet, sizeof(packet), "g;thread:%4.4" PRIx64, m_thread.GetProtocolID());
+            else
+                packet_len = ::snprintf (packet, sizeof(packet), "g");
+            assert (packet_len < ((int)sizeof(packet) - 1));
+
+            if (gdb_comm.SendPacketAndWaitForResponse(packet, packet_len, response, false))
+            {
+                if (response.IsErrorResponse())
+                    return false;
+
+                std::string &response_str = response.GetStringRef();
+                if (isxdigit(response_str[0]))
+                {
+                    response_str.insert(0, 1, 'G');
+                    if (thread_suffix_supported)
+                    {
+                        char thread_id_cstr[64];
+                        ::snprintf (thread_id_cstr, sizeof(thread_id_cstr), ";thread:%4.4" PRIx64 ";", m_thread.GetProtocolID());
+                        response_str.append (thread_id_cstr);
+                    }
+                    data_sp.reset (new DataBufferHeap (response_str.c_str(), response_str.size()));
+                    return true;
+                }
+            }
+        }
+    }
+    else
+    {
+        Log *log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_THREAD | GDBR_LOG_PACKETS));
+        if (log)
+        {
+            if (log->GetVerbose())
+            {
+                StreamString strm;
+                gdb_comm.DumpHistory(strm);
+                log->Printf("error: failed to get packet sequence mutex, not sending read all registers:\n%s", strm.GetData());
+            }
+            else
+                log->Printf("error: failed to get packet sequence mutex, not sending read all registers");
+        }
+    }
+
+    data_sp.reset();
+    return false;
+}
+
+bool
+GDBRemoteRegisterContext::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp)
+{
+    if (!data_sp || data_sp->GetBytes() == NULL || data_sp->GetByteSize() == 0)
+        return false;
+
+    ExecutionContext exe_ctx (CalculateThread());
+
+    Process *process = exe_ctx.GetProcessPtr();
+    Thread *thread = exe_ctx.GetThreadPtr();
+    if (process == NULL || thread == NULL)
+        return false;
+
+    GDBRemoteCommunicationClient &gdb_comm (((ProcessGDBRemote *)process)->GetGDBRemote());
+
+    StringExtractorGDBRemote response;
+    Mutex::Locker locker;
+    if (gdb_comm.GetSequenceMutex (locker, "Didn't get sequence mutex for write all registers."))
+    {
+        const bool thread_suffix_supported = gdb_comm.GetThreadSuffixSupported();
+        ProcessSP process_sp (m_thread.GetProcess());
+        if (thread_suffix_supported || static_cast<ProcessGDBRemote *>(process_sp.get())->GetGDBRemote().SetCurrentThread(m_thread.GetProtocolID()))
+        {
+            // The data_sp contains the entire G response packet including the
+            // G, and if the thread suffix is supported, it has the thread suffix
+            // as well.
+            const char *G_packet = (const char *)data_sp->GetBytes();
+            size_t G_packet_len = data_sp->GetByteSize();
+            if (gdb_comm.SendPacketAndWaitForResponse (G_packet,
+                                                       G_packet_len,
+                                                       response,
+                                                       false))
+            {
+                if (response.IsOKResponse())
+                    return true;
+                else if (response.IsErrorResponse())
+                {
+                    uint32_t num_restored = 0;
+                    // We need to manually go through all of the registers and
+                    // restore them manually
+
+                    response.GetStringRef().assign (G_packet, G_packet_len);
+                    response.SetFilePos(1); // Skip the leading 'G'
+                    DataBufferHeap buffer (m_reg_data.GetByteSize(), 0);
+                    DataExtractor restore_data (buffer.GetBytes(),
+                                                buffer.GetByteSize(),
+                                                m_reg_data.GetByteOrder(),
+                                                m_reg_data.GetAddressByteSize());
+
+                    const uint32_t bytes_extracted = response.GetHexBytes ((void *)restore_data.GetDataStart(),
+                                                                           restore_data.GetByteSize(),
+                                                                           '\xcc');
+
+                    if (bytes_extracted < restore_data.GetByteSize())
+                        restore_data.SetData(restore_data.GetDataStart(), bytes_extracted, m_reg_data.GetByteOrder());
+
+                    //ReadRegisterBytes (const RegisterInfo *reg_info, RegisterValue &value, DataExtractor &data)
+                    const RegisterInfo *reg_info;
+                    // We have to march the offset of each register along in the
+                    // buffer to make sure we get the right offset.
+                    uint32_t reg_byte_offset = 0;
+                    for (uint32_t reg_idx=0; (reg_info = GetRegisterInfoAtIndex (reg_idx)) != NULL; ++reg_idx, reg_byte_offset += reg_info->byte_size)
+                    {
+                        const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
+
+                        // Skip composite registers.
+                        if (reg_info->value_regs)
+                            continue;
+
+                        // Only write down the registers that need to be written
+                        // if we are going to be doing registers individually.
+                        bool write_reg = true;
+                        const uint32_t reg_byte_size = reg_info->byte_size;
+
+                        const char *restore_src = (const char *)restore_data.PeekData(reg_byte_offset, reg_byte_size);
+                        if (restore_src)
+                        {
+                            if (GetRegisterIsValid(reg))
+                            {
+                                const char *current_src = (const char *)m_reg_data.PeekData(reg_byte_offset, reg_byte_size);
+                                if (current_src)
+                                    write_reg = memcmp (current_src, restore_src, reg_byte_size) != 0;
+                            }
+
+                            if (write_reg)
+                            {
+                                StreamString packet;
+                                packet.Printf ("P%x=", reg);
+                                packet.PutBytesAsRawHex8 (restore_src,
+                                                          reg_byte_size,
+                                                          lldb::endian::InlHostByteOrder(),
+                                                          lldb::endian::InlHostByteOrder());
+
+                                if (thread_suffix_supported)
+                                    packet.Printf (";thread:%4.4" PRIx64 ";", m_thread.GetProtocolID());
+
+                                SetRegisterIsValid(reg, false);
+                                if (gdb_comm.SendPacketAndWaitForResponse(packet.GetString().c_str(),
+                                                                          packet.GetString().size(),
+                                                                          response,
+                                                                          false))
+                                {
+                                    if (response.IsOKResponse())
+                                        ++num_restored;
+                                }
+                            }
+                        }
+                    }
+                    return num_restored > 0;
+                }
+            }
+        }
+    }
+    else
+    {
+        Log *log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_THREAD | GDBR_LOG_PACKETS));
+        if (log)
+        {
+            if (log->GetVerbose())
+            {
+                StreamString strm;
+                gdb_comm.DumpHistory(strm);
+                log->Printf("error: failed to get packet sequence mutex, not sending write all registers:\n%s", strm.GetData());
+            }
+            else
+                log->Printf("error: failed to get packet sequence mutex, not sending write all registers");
+        }
+    }
+    return false;
+}
+
+
+uint32_t
+GDBRemoteRegisterContext::ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num)
+{
+    return m_reg_info.ConvertRegisterKindToRegisterNumber (kind, num);
+}
+
+void
+GDBRemoteDynamicRegisterInfo::HardcodeARMRegisters(bool from_scratch)
+{
+    // For Advanced SIMD and VFP register mapping.
+    static uint32_t g_d0_regs[] =  { 26, 27, LLDB_INVALID_REGNUM }; // (s0, s1)
+    static uint32_t g_d1_regs[] =  { 28, 29, LLDB_INVALID_REGNUM }; // (s2, s3)
+    static uint32_t g_d2_regs[] =  { 30, 31, LLDB_INVALID_REGNUM }; // (s4, s5)
+    static uint32_t g_d3_regs[] =  { 32, 33, LLDB_INVALID_REGNUM }; // (s6, s7)
+    static uint32_t g_d4_regs[] =  { 34, 35, LLDB_INVALID_REGNUM }; // (s8, s9)
+    static uint32_t g_d5_regs[] =  { 36, 37, LLDB_INVALID_REGNUM }; // (s10, s11)
+    static uint32_t g_d6_regs[] =  { 38, 39, LLDB_INVALID_REGNUM }; // (s12, s13)
+    static uint32_t g_d7_regs[] =  { 40, 41, LLDB_INVALID_REGNUM }; // (s14, s15)
+    static uint32_t g_d8_regs[] =  { 42, 43, LLDB_INVALID_REGNUM }; // (s16, s17)
+    static uint32_t g_d9_regs[] =  { 44, 45, LLDB_INVALID_REGNUM }; // (s18, s19)
+    static uint32_t g_d10_regs[] = { 46, 47, LLDB_INVALID_REGNUM }; // (s20, s21)
+    static uint32_t g_d11_regs[] = { 48, 49, LLDB_INVALID_REGNUM }; // (s22, s23)
+    static uint32_t g_d12_regs[] = { 50, 51, LLDB_INVALID_REGNUM }; // (s24, s25)
+    static uint32_t g_d13_regs[] = { 52, 53, LLDB_INVALID_REGNUM }; // (s26, s27)
+    static uint32_t g_d14_regs[] = { 54, 55, LLDB_INVALID_REGNUM }; // (s28, s29)
+    static uint32_t g_d15_regs[] = { 56, 57, LLDB_INVALID_REGNUM }; // (s30, s31)
+    static uint32_t g_q0_regs[] =  { 26, 27, 28, 29, LLDB_INVALID_REGNUM }; // (d0, d1) -> (s0, s1, s2, s3)
+    static uint32_t g_q1_regs[] =  { 30, 31, 32, 33, LLDB_INVALID_REGNUM }; // (d2, d3) -> (s4, s5, s6, s7)
+    static uint32_t g_q2_regs[] =  { 34, 35, 36, 37, LLDB_INVALID_REGNUM }; // (d4, d5) -> (s8, s9, s10, s11)
+    static uint32_t g_q3_regs[] =  { 38, 39, 40, 41, LLDB_INVALID_REGNUM }; // (d6, d7) -> (s12, s13, s14, s15)
+    static uint32_t g_q4_regs[] =  { 42, 43, 44, 45, LLDB_INVALID_REGNUM }; // (d8, d9) -> (s16, s17, s18, s19)
+    static uint32_t g_q5_regs[] =  { 46, 47, 48, 49, LLDB_INVALID_REGNUM }; // (d10, d11) -> (s20, s21, s22, s23)
+    static uint32_t g_q6_regs[] =  { 50, 51, 52, 53, LLDB_INVALID_REGNUM }; // (d12, d13) -> (s24, s25, s26, s27)
+    static uint32_t g_q7_regs[] =  { 54, 55, 56, 57, LLDB_INVALID_REGNUM }; // (d14, d15) -> (s28, s29, s30, s31)
+    static uint32_t g_q8_regs[] =  { 59, 60, LLDB_INVALID_REGNUM }; // (d16, d17)
+    static uint32_t g_q9_regs[] =  { 61, 62, LLDB_INVALID_REGNUM }; // (d18, d19)
+    static uint32_t g_q10_regs[] = { 63, 64, LLDB_INVALID_REGNUM }; // (d20, d21)
+    static uint32_t g_q11_regs[] = { 65, 66, LLDB_INVALID_REGNUM }; // (d22, d23)
+    static uint32_t g_q12_regs[] = { 67, 68, LLDB_INVALID_REGNUM }; // (d24, d25)
+    static uint32_t g_q13_regs[] = { 69, 70, LLDB_INVALID_REGNUM }; // (d26, d27)
+    static uint32_t g_q14_regs[] = { 71, 72, LLDB_INVALID_REGNUM }; // (d28, d29)
+    static uint32_t g_q15_regs[] = { 73, 74, LLDB_INVALID_REGNUM }; // (d30, d31)
+
+    // This is our array of composite registers, with each element coming from the above register mappings.
+    static uint32_t *g_composites[] = {
+        g_d0_regs, g_d1_regs,  g_d2_regs,  g_d3_regs,  g_d4_regs,  g_d5_regs,  g_d6_regs,  g_d7_regs,
+        g_d8_regs, g_d9_regs, g_d10_regs, g_d11_regs, g_d12_regs, g_d13_regs, g_d14_regs, g_d15_regs,
+        g_q0_regs, g_q1_regs,  g_q2_regs,  g_q3_regs,  g_q4_regs,  g_q5_regs,  g_q6_regs,  g_q7_regs,
+        g_q8_regs, g_q9_regs, g_q10_regs, g_q11_regs, g_q12_regs, g_q13_regs, g_q14_regs, g_q15_regs
+    };
+
+    static RegisterInfo g_register_infos[] = {
+//   NAME    ALT    SZ  OFF  ENCODING          FORMAT          COMPILER             DWARF                GENERIC                 GDB    LLDB      VALUE REGS    INVALIDATE REGS
+//   ======  ====== === ===  =============     ============    ===================  ===================  ======================  ===    ====      ==========    ===============
+    { "r0", "arg1",   4,   0, eEncodingUint,    eFormatHex,   { gcc_r0,              dwarf_r0,            LLDB_REGNUM_GENERIC_ARG1,0,      0 },        NULL,              NULL},
+    { "r1", "arg2",   4,   0, eEncodingUint,    eFormatHex,   { gcc_r1,              dwarf_r1,            LLDB_REGNUM_GENERIC_ARG2,1,      1 },        NULL,              NULL},
+    { "r2", "arg3",   4,   0, eEncodingUint,    eFormatHex,   { gcc_r2,              dwarf_r2,            LLDB_REGNUM_GENERIC_ARG3,2,      2 },        NULL,              NULL},
+    { "r3", "arg4",   4,   0, eEncodingUint,    eFormatHex,   { gcc_r3,              dwarf_r3,            LLDB_REGNUM_GENERIC_ARG4,3,      3 },        NULL,              NULL},
+    { "r4",   NULL,   4,   0, eEncodingUint,    eFormatHex,   { gcc_r4,              dwarf_r4,            LLDB_INVALID_REGNUM,     4,      4 },        NULL,              NULL},
+    { "r5",   NULL,   4,   0, eEncodingUint,    eFormatHex,   { gcc_r5,              dwarf_r5,            LLDB_INVALID_REGNUM,     5,      5 },        NULL,              NULL},
+    { "r6",   NULL,   4,   0, eEncodingUint,    eFormatHex,   { gcc_r6,              dwarf_r6,            LLDB_INVALID_REGNUM,     6,      6 },        NULL,              NULL},
+    { "r7",   "fp",   4,   0, eEncodingUint,    eFormatHex,   { gcc_r7,              dwarf_r7,            LLDB_REGNUM_GENERIC_FP,  7,      7 },        NULL,              NULL},
+    { "r8",   NULL,   4,   0, eEncodingUint,    eFormatHex,   { gcc_r8,              dwarf_r8,            LLDB_INVALID_REGNUM,     8,      8 },        NULL,              NULL},
+    { "r9",   NULL,   4,   0, eEncodingUint,    eFormatHex,   { gcc_r9,              dwarf_r9,            LLDB_INVALID_REGNUM,     9,      9 },        NULL,              NULL},
+    { "r10",  NULL,   4,   0, eEncodingUint,    eFormatHex,   { gcc_r10,             dwarf_r10,           LLDB_INVALID_REGNUM,    10,     10 },        NULL,              NULL},
+    { "r11",  NULL,   4,   0, eEncodingUint,    eFormatHex,   { gcc_r11,             dwarf_r11,           LLDB_INVALID_REGNUM,    11,     11 },        NULL,              NULL},
+    { "r12",  NULL,   4,   0, eEncodingUint,    eFormatHex,   { gcc_r12,             dwarf_r12,           LLDB_INVALID_REGNUM,    12,     12 },        NULL,              NULL},
+    { "sp",   "r13",  4,   0, eEncodingUint,    eFormatHex,   { gcc_sp,              dwarf_sp,            LLDB_REGNUM_GENERIC_SP, 13,     13 },        NULL,              NULL},
+    { "lr",   "r14",  4,   0, eEncodingUint,    eFormatHex,   { gcc_lr,              dwarf_lr,            LLDB_REGNUM_GENERIC_RA, 14,     14 },        NULL,              NULL},
+    { "pc",   "r15",  4,   0, eEncodingUint,    eFormatHex,   { gcc_pc,              dwarf_pc,            LLDB_REGNUM_GENERIC_PC, 15,     15 },        NULL,              NULL},
+    { "f0",   NULL,  12,   0, eEncodingUint,    eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    16,     16 },        NULL,              NULL},
+    { "f1",   NULL,  12,   0, eEncodingUint,    eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    17,     17 },        NULL,              NULL},
+    { "f2",   NULL,  12,   0, eEncodingUint,    eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    18,     18 },        NULL,              NULL},
+    { "f3",   NULL,  12,   0, eEncodingUint,    eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    19,     19 },        NULL,              NULL},
+    { "f4",   NULL,  12,   0, eEncodingUint,    eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    20,     20 },        NULL,              NULL},
+    { "f5",   NULL,  12,   0, eEncodingUint,    eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    21,     21 },        NULL,              NULL},
+    { "f6",   NULL,  12,   0, eEncodingUint,    eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    22,     22 },        NULL,              NULL},
+    { "f7",   NULL,  12,   0, eEncodingUint,    eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    23,     23 },        NULL,              NULL},
+    { "fps",  NULL,   4,   0, eEncodingUint,    eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    24,     24 },        NULL,              NULL},
+    { "cpsr","flags", 4,   0, eEncodingUint,    eFormatHex,   { gcc_cpsr,            dwarf_cpsr,          LLDB_INVALID_REGNUM,    25,     25 },        NULL,              NULL},
+    { "s0",   NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s0,            LLDB_INVALID_REGNUM,    26,     26 },        NULL,              NULL},
+    { "s1",   NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s1,            LLDB_INVALID_REGNUM,    27,     27 },        NULL,              NULL},
+    { "s2",   NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s2,            LLDB_INVALID_REGNUM,    28,     28 },        NULL,              NULL},
+    { "s3",   NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s3,            LLDB_INVALID_REGNUM,    29,     29 },        NULL,              NULL},
+    { "s4",   NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s4,            LLDB_INVALID_REGNUM,    30,     30 },        NULL,              NULL},
+    { "s5",   NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s5,            LLDB_INVALID_REGNUM,    31,     31 },        NULL,              NULL},
+    { "s6",   NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s6,            LLDB_INVALID_REGNUM,    32,     32 },        NULL,              NULL},
+    { "s7",   NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s7,            LLDB_INVALID_REGNUM,    33,     33 },        NULL,              NULL},
+    { "s8",   NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s8,            LLDB_INVALID_REGNUM,    34,     34 },        NULL,              NULL},
+    { "s9",   NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s9,            LLDB_INVALID_REGNUM,    35,     35 },        NULL,              NULL},
+    { "s10",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s10,           LLDB_INVALID_REGNUM,    36,     36 },        NULL,              NULL},
+    { "s11",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s11,           LLDB_INVALID_REGNUM,    37,     37 },        NULL,              NULL},
+    { "s12",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s12,           LLDB_INVALID_REGNUM,    38,     38 },        NULL,              NULL},
+    { "s13",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s13,           LLDB_INVALID_REGNUM,    39,     39 },        NULL,              NULL},
+    { "s14",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s14,           LLDB_INVALID_REGNUM,    40,     40 },        NULL,              NULL},
+    { "s15",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s15,           LLDB_INVALID_REGNUM,    41,     41 },        NULL,              NULL},
+    { "s16",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s16,           LLDB_INVALID_REGNUM,    42,     42 },        NULL,              NULL},
+    { "s17",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s17,           LLDB_INVALID_REGNUM,    43,     43 },        NULL,              NULL},
+    { "s18",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s18,           LLDB_INVALID_REGNUM,    44,     44 },        NULL,              NULL},
+    { "s19",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s19,           LLDB_INVALID_REGNUM,    45,     45 },        NULL,              NULL},
+    { "s20",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s20,           LLDB_INVALID_REGNUM,    46,     46 },        NULL,              NULL},
+    { "s21",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s21,           LLDB_INVALID_REGNUM,    47,     47 },        NULL,              NULL},
+    { "s22",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s22,           LLDB_INVALID_REGNUM,    48,     48 },        NULL,              NULL},
+    { "s23",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s23,           LLDB_INVALID_REGNUM,    49,     49 },        NULL,              NULL},
+    { "s24",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s24,           LLDB_INVALID_REGNUM,    50,     50 },        NULL,              NULL},
+    { "s25",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s25,           LLDB_INVALID_REGNUM,    51,     51 },        NULL,              NULL},
+    { "s26",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s26,           LLDB_INVALID_REGNUM,    52,     52 },        NULL,              NULL},
+    { "s27",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s27,           LLDB_INVALID_REGNUM,    53,     53 },        NULL,              NULL},
+    { "s28",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s28,           LLDB_INVALID_REGNUM,    54,     54 },        NULL,              NULL},
+    { "s29",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s29,           LLDB_INVALID_REGNUM,    55,     55 },        NULL,              NULL},
+    { "s30",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s30,           LLDB_INVALID_REGNUM,    56,     56 },        NULL,              NULL},
+    { "s31",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s31,           LLDB_INVALID_REGNUM,    57,     57 },        NULL,              NULL},
+    { "fpscr",NULL,   4,   0, eEncodingUint,    eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    58,     58 },        NULL,              NULL},
+    { "d16",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d16,           LLDB_INVALID_REGNUM,    59,     59 },        NULL,              NULL},
+    { "d17",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d17,           LLDB_INVALID_REGNUM,    60,     60 },        NULL,              NULL},
+    { "d18",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d18,           LLDB_INVALID_REGNUM,    61,     61 },        NULL,              NULL},
+    { "d19",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d19,           LLDB_INVALID_REGNUM,    62,     62 },        NULL,              NULL},
+    { "d20",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d20,           LLDB_INVALID_REGNUM,    63,     63 },        NULL,              NULL},
+    { "d21",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d21,           LLDB_INVALID_REGNUM,    64,     64 },        NULL,              NULL},
+    { "d22",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d22,           LLDB_INVALID_REGNUM,    65,     65 },        NULL,              NULL},
+    { "d23",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d23,           LLDB_INVALID_REGNUM,    66,     66 },        NULL,              NULL},
+    { "d24",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d24,           LLDB_INVALID_REGNUM,    67,     67 },        NULL,              NULL},
+    { "d25",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d25,           LLDB_INVALID_REGNUM,    68,     68 },        NULL,              NULL},
+    { "d26",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d26,           LLDB_INVALID_REGNUM,    69,     69 },        NULL,              NULL},
+    { "d27",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d27,           LLDB_INVALID_REGNUM,    70,     70 },        NULL,              NULL},
+    { "d28",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d28,           LLDB_INVALID_REGNUM,    71,     71 },        NULL,              NULL},
+    { "d29",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d29,           LLDB_INVALID_REGNUM,    72,     72 },        NULL,              NULL},
+    { "d30",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d30,           LLDB_INVALID_REGNUM,    73,     73 },        NULL,              NULL},
+    { "d31",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d31,           LLDB_INVALID_REGNUM,    74,     74 },        NULL,              NULL},
+    { "d0",   NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d0,            LLDB_INVALID_REGNUM,    75,     75 },   g_d0_regs,              NULL},
+    { "d1",   NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d1,            LLDB_INVALID_REGNUM,    76,     76 },   g_d1_regs,              NULL},
+    { "d2",   NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d2,            LLDB_INVALID_REGNUM,    77,     77 },   g_d2_regs,              NULL},
+    { "d3",   NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d3,            LLDB_INVALID_REGNUM,    78,     78 },   g_d3_regs,              NULL},
+    { "d4",   NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d4,            LLDB_INVALID_REGNUM,    79,     79 },   g_d4_regs,              NULL},
+    { "d5",   NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d5,            LLDB_INVALID_REGNUM,    80,     80 },   g_d5_regs,              NULL},
+    { "d6",   NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d6,            LLDB_INVALID_REGNUM,    81,     81 },   g_d6_regs,              NULL},
+    { "d7",   NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d7,            LLDB_INVALID_REGNUM,    82,     82 },   g_d7_regs,              NULL},
+    { "d8",   NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d8,            LLDB_INVALID_REGNUM,    83,     83 },   g_d8_regs,              NULL},
+    { "d9",   NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d9,            LLDB_INVALID_REGNUM,    84,     84 },   g_d9_regs,              NULL},
+    { "d10",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d10,           LLDB_INVALID_REGNUM,    85,     85 },  g_d10_regs,              NULL},
+    { "d11",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d11,           LLDB_INVALID_REGNUM,    86,     86 },  g_d11_regs,              NULL},
+    { "d12",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d12,           LLDB_INVALID_REGNUM,    87,     87 },  g_d12_regs,              NULL},
+    { "d13",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d13,           LLDB_INVALID_REGNUM,    88,     88 },  g_d13_regs,              NULL},
+    { "d14",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d14,           LLDB_INVALID_REGNUM,    89,     89 },  g_d14_regs,              NULL},
+    { "d15",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d15,           LLDB_INVALID_REGNUM,    90,     90 },  g_d15_regs,              NULL},
+    { "q0",   NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q0,    LLDB_INVALID_REGNUM,    91,     91 },   g_q0_regs,              NULL},
+    { "q1",   NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q1,    LLDB_INVALID_REGNUM,    92,     92 },   g_q1_regs,              NULL},
+    { "q2",   NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q2,    LLDB_INVALID_REGNUM,    93,     93 },   g_q2_regs,              NULL},
+    { "q3",   NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q3,    LLDB_INVALID_REGNUM,    94,     94 },   g_q3_regs,              NULL},
+    { "q4",   NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q4,    LLDB_INVALID_REGNUM,    95,     95 },   g_q4_regs,              NULL},
+    { "q5",   NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q5,    LLDB_INVALID_REGNUM,    96,     96 },   g_q5_regs,              NULL},
+    { "q6",   NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q6,    LLDB_INVALID_REGNUM,    97,     97 },   g_q6_regs,              NULL},
+    { "q7",   NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q7,    LLDB_INVALID_REGNUM,    98,     98 },   g_q7_regs,              NULL},
+    { "q8",   NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q8,    LLDB_INVALID_REGNUM,    99,     99 },   g_q8_regs,              NULL},
+    { "q9",   NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q9,    LLDB_INVALID_REGNUM,   100,    100 },   g_q9_regs,              NULL},
+    { "q10",  NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q10,   LLDB_INVALID_REGNUM,   101,    101 },  g_q10_regs,              NULL},
+    { "q11",  NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q11,   LLDB_INVALID_REGNUM,   102,    102 },  g_q11_regs,              NULL},
+    { "q12",  NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q12,   LLDB_INVALID_REGNUM,   103,    103 },  g_q12_regs,              NULL},
+    { "q13",  NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q13,   LLDB_INVALID_REGNUM,   104,    104 },  g_q13_regs,              NULL},
+    { "q14",  NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q14,   LLDB_INVALID_REGNUM,   105,    105 },  g_q14_regs,              NULL},
+    { "q15",  NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q15,   LLDB_INVALID_REGNUM,   106,    106 },  g_q15_regs,              NULL}
+    };
+
+    static const uint32_t num_registers = llvm::array_lengthof(g_register_infos);
+    static ConstString gpr_reg_set ("General Purpose Registers");
+    static ConstString sfp_reg_set ("Software Floating Point Registers");
+    static ConstString vfp_reg_set ("Floating Point Registers");
+    size_t i;
+    if (from_scratch)
+    {
+        // Calculate the offsets of the registers
+        // Note that the layout of the "composite" registers (d0-d15 and q0-q15) which comes after the
+        // "primordial" registers is important.  This enables us to calculate the offset of the composite
+        // register by using the offset of its first primordial register.  For example, to calculate the
+        // offset of q0, use s0's offset.
+        if (g_register_infos[2].byte_offset == 0)
+        {
+            uint32_t byte_offset = 0;
+            for (i=0; i<num_registers; ++i)
+            {
+                // For primordial registers, increment the byte_offset by the byte_size to arrive at the
+                // byte_offset for the next register.  Otherwise, we have a composite register whose
+                // offset can be calculated by consulting the offset of its first primordial register.
+                if (!g_register_infos[i].value_regs)
+                {
+                    g_register_infos[i].byte_offset = byte_offset;
+                    byte_offset += g_register_infos[i].byte_size;
+                }
+                else
+                {
+                    const uint32_t first_primordial_reg = g_register_infos[i].value_regs[0];
+                    g_register_infos[i].byte_offset = g_register_infos[first_primordial_reg].byte_offset;
+                }
+            }
+        }
+        for (i=0; i<num_registers; ++i)
+        {
+            ConstString name;
+            ConstString alt_name;
+            if (g_register_infos[i].name && g_register_infos[i].name[0])
+                name.SetCString(g_register_infos[i].name);
+            if (g_register_infos[i].alt_name && g_register_infos[i].alt_name[0])
+                alt_name.SetCString(g_register_infos[i].alt_name);
+
+            if (i <= 15 || i == 25)
+                AddRegister (g_register_infos[i], name, alt_name, gpr_reg_set);
+            else if (i <= 24)
+                AddRegister (g_register_infos[i], name, alt_name, sfp_reg_set);
+            else
+                AddRegister (g_register_infos[i], name, alt_name, vfp_reg_set);
+        }
+    }
+    else
+    {
+        // Add composite registers to our primordial registers, then.
+        const size_t num_composites = llvm::array_lengthof(g_composites);
+        const size_t num_dynamic_regs = GetNumRegisters();
+        const size_t num_common_regs = num_registers - num_composites;
+        RegisterInfo *g_comp_register_infos = g_register_infos + num_common_regs;
+
+        // First we need to validate that all registers that we already have match the non composite regs.
+        // If so, then we can add the registers, else we need to bail
+        bool match = true;
+        if (num_dynamic_regs == num_common_regs)
+        {
+            for (i=0; match && i<num_dynamic_regs; ++i)
+            {
+                // Make sure all register names match
+                if (m_regs[i].name && g_register_infos[i].name)
+                {
+                    if (strcmp(m_regs[i].name, g_register_infos[i].name))
+                    {
+                        match = false;
+                        break;
+                    }
+                }
+                
+                // Make sure all register byte sizes match
+                if (m_regs[i].byte_size != g_register_infos[i].byte_size)
+                {
+                    match = false;
+                    break;
+                }
+            }
+        }
+        else
+        {
+            // Wrong number of registers.
+            match = false;
+        }
+        // If "match" is true, then we can add extra registers.
+        if (match)
+        {
+            for (i=0; i<num_composites; ++i)
+            {
+                ConstString name;
+                ConstString alt_name;
+                const uint32_t first_primordial_reg = g_comp_register_infos[i].value_regs[0];
+                const char *reg_name = g_register_infos[first_primordial_reg].name;
+                if (reg_name && reg_name[0])
+                {
+                    for (uint32_t j = 0; j < num_dynamic_regs; ++j)
+                    {
+                        const RegisterInfo *reg_info = GetRegisterInfoAtIndex(j);
+                        // Find a matching primordial register info entry.
+                        if (reg_info && reg_info->name && ::strcasecmp(reg_info->name, reg_name) == 0)
+                        {
+                            // The name matches the existing primordial entry.
+                            // Find and assign the offset, and then add this composite register entry.
+                            g_comp_register_infos[i].byte_offset = reg_info->byte_offset;
+                            name.SetCString(g_comp_register_infos[i].name);
+                            AddRegister(g_comp_register_infos[i], name, alt_name, vfp_reg_set);
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
new file mode 100644
index 000000000000..3110ddf8edf9
--- /dev/null
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
@@ -0,0 +1,311 @@
+//===-- GDBRemoteRegisterContext.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_GDBRemoteRegisterContext_h_
+#define lldb_GDBRemoteRegisterContext_h_
+
+// C Includes
+// C++ Includes
+#include <vector>
+
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/lldb-enumerations.h"
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Target/RegisterContext.h"
+#include "GDBRemoteCommunicationClient.h"
+
+class ThreadGDBRemote;
+class ProcessGDBRemote;
+class StringExtractor;
+
+class GDBRemoteDynamicRegisterInfo
+{
+public:
+    GDBRemoteDynamicRegisterInfo () :
+        m_regs (),
+        m_sets (),
+        m_set_reg_nums (),
+        m_reg_names (),
+        m_reg_alt_names (),
+        m_set_names (),
+        m_reg_data_byte_size (0)
+    {
+    }
+
+    ~GDBRemoteDynamicRegisterInfo ()
+    {
+    }
+
+    void
+    AddRegister (lldb_private::RegisterInfo reg_info, 
+                 lldb_private::ConstString &reg_name, 
+                 lldb_private::ConstString &reg_alt_name, 
+                 lldb_private::ConstString &set_name)
+    {
+        const uint32_t reg_num = (uint32_t)m_regs.size();
+        m_reg_names.push_back (reg_name);
+        m_reg_alt_names.push_back (reg_alt_name);
+        reg_info.name = reg_name.AsCString();
+        assert (reg_info.name);
+        reg_info.alt_name = reg_alt_name.AsCString(NULL);
+        uint32_t i;
+        if (reg_info.value_regs)
+        {
+            for (i=0; reg_info.value_regs[i] != LLDB_INVALID_REGNUM; ++i)
+                m_value_regs_map[reg_num].push_back(reg_info.value_regs[i]);
+            m_value_regs_map[reg_num].push_back(LLDB_INVALID_REGNUM);
+            reg_info.value_regs = m_value_regs_map[reg_num].data();
+        }
+        if (reg_info.invalidate_regs)
+        {
+            for (i=0; reg_info.invalidate_regs[i] != LLDB_INVALID_REGNUM; ++i)
+                m_invalidate_regs_map[reg_num].push_back(reg_info.invalidate_regs[i]);
+            m_invalidate_regs_map[reg_num].push_back(LLDB_INVALID_REGNUM);
+            reg_info.invalidate_regs = m_invalidate_regs_map[reg_num].data();
+        }
+        m_regs.push_back (reg_info);
+        uint32_t set = GetRegisterSetIndexByName (set_name);
+        assert (set < m_sets.size());
+        assert (set < m_set_reg_nums.size());
+        assert (set < m_set_names.size());
+        m_set_reg_nums[set].push_back(reg_num);
+        size_t end_reg_offset = reg_info.byte_offset + reg_info.byte_size;
+        if (m_reg_data_byte_size < end_reg_offset)
+            m_reg_data_byte_size = end_reg_offset;
+    }
+
+    void
+    Finalize ()
+    {
+        for (uint32_t set = 0; set < m_sets.size(); ++set)
+        {
+            assert (m_sets.size() == m_set_reg_nums.size());
+            m_sets[set].num_registers = m_set_reg_nums[set].size();
+            m_sets[set].registers = &m_set_reg_nums[set][0];
+        }
+    }
+
+    size_t
+    GetNumRegisters() const
+    {
+        return m_regs.size();
+    }
+
+    size_t
+    GetNumRegisterSets() const
+    {
+        return m_sets.size();
+    }
+
+    size_t
+    GetRegisterDataByteSize() const
+    {
+        return m_reg_data_byte_size;
+    }
+
+    const lldb_private::RegisterInfo *
+    GetRegisterInfoAtIndex (uint32_t i) const
+    {
+        if (i < m_regs.size())
+            return &m_regs[i];
+        return NULL;
+    }
+
+    const lldb_private::RegisterSet *
+    GetRegisterSet (uint32_t i) const
+    {
+        if (i < m_sets.size())
+            return &m_sets[i];
+        return NULL;
+    }
+
+    uint32_t
+    GetRegisterSetIndexByName (lldb_private::ConstString &set_name)
+    {
+        name_collection::iterator pos, end = m_set_names.end();
+        for (pos = m_set_names.begin(); pos != end; ++pos)
+        {
+            if (*pos == set_name)
+                return static_cast<uint32_t>(std::distance (m_set_names.begin(), pos));
+        }
+
+        m_set_names.push_back(set_name);
+        m_set_reg_nums.resize(m_set_reg_nums.size()+1);
+        lldb_private::RegisterSet new_set = { set_name.AsCString(), NULL, 0, NULL };
+        m_sets.push_back (new_set);
+        return static_cast<uint32_t>(m_sets.size() - 1);
+    }
+
+    uint32_t
+    ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num) const
+    {
+        reg_collection::const_iterator pos, end = m_regs.end();
+        for (pos = m_regs.begin(); pos != end; ++pos)
+        {
+            if (pos->kinds[kind] == num)
+                return static_cast<uint32_t>(std::distance (m_regs.begin(), pos));
+        }
+
+        return LLDB_INVALID_REGNUM;
+    }
+    void
+    Clear()
+    {
+        m_regs.clear();
+        m_sets.clear();
+        m_set_reg_nums.clear();
+        m_reg_names.clear();
+        m_reg_alt_names.clear();
+        m_set_names.clear();
+    }
+
+    void
+    HardcodeARMRegisters(bool from_scratch);
+
+protected:
+    //------------------------------------------------------------------
+    // Classes that inherit from GDBRemoteRegisterContext can see and modify these
+    //------------------------------------------------------------------
+    typedef std::vector <lldb_private::RegisterInfo> reg_collection;
+    typedef std::vector <lldb_private::RegisterSet> set_collection;
+    typedef std::vector <uint32_t> reg_num_collection;
+    typedef std::vector <reg_num_collection> set_reg_num_collection;
+    typedef std::vector <lldb_private::ConstString> name_collection;
+    typedef std::map<uint32_t, reg_num_collection> reg_to_regs_map;
+
+    reg_collection m_regs;
+    set_collection m_sets;
+    set_reg_num_collection m_set_reg_nums;
+    name_collection m_reg_names;
+    name_collection m_reg_alt_names;
+    name_collection m_set_names;
+    reg_to_regs_map m_value_regs_map;
+    reg_to_regs_map m_invalidate_regs_map;
+    size_t m_reg_data_byte_size;   // The number of bytes required to store all registers
+};
+
+class GDBRemoteRegisterContext : public lldb_private::RegisterContext
+{
+public:
+    //------------------------------------------------------------------
+    // Constructors and Destructors
+    //------------------------------------------------------------------
+    GDBRemoteRegisterContext (ThreadGDBRemote &thread,
+                              uint32_t concrete_frame_idx,
+                              GDBRemoteDynamicRegisterInfo &reg_info,
+                              bool read_all_at_once);
+
+    virtual
+    ~GDBRemoteRegisterContext ();
+
+    //------------------------------------------------------------------
+    // Subclasses must override these functions
+    //------------------------------------------------------------------
+    virtual void
+    InvalidateAllRegisters ();
+
+    virtual size_t
+    GetRegisterCount ();
+
+    virtual const lldb_private::RegisterInfo *
+    GetRegisterInfoAtIndex (size_t reg);
+
+    virtual size_t
+    GetRegisterSetCount ();
+
+    virtual const lldb_private::RegisterSet *
+    GetRegisterSet (size_t reg_set);
+
+    virtual bool
+    ReadRegister (const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value);
+
+    virtual bool
+    WriteRegister (const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value);
+    
+    virtual bool
+    ReadAllRegisterValues (lldb::DataBufferSP &data_sp);
+
+    virtual bool
+    WriteAllRegisterValues (const lldb::DataBufferSP &data_sp);
+
+    virtual uint32_t
+    ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num);
+
+protected:
+    friend class ThreadGDBRemote;
+
+    bool
+    ReadRegisterBytes (const lldb_private::RegisterInfo *reg_info,
+                       lldb_private::DataExtractor &data);
+
+    bool
+    WriteRegisterBytes (const lldb_private::RegisterInfo *reg_info,
+                        lldb_private::DataExtractor &data, 
+                        uint32_t data_offset);
+
+    bool
+    PrivateSetRegisterValue (uint32_t reg, StringExtractor &response);
+    
+    void
+    SetAllRegisterValid (bool b);
+
+    bool
+    GetRegisterIsValid (uint32_t reg) const
+    {
+#if defined (LLDB_CONFIGURATION_DEBUG)
+        assert (reg < m_reg_valid.size());
+#endif
+        if (reg < m_reg_valid.size())
+            return m_reg_valid[reg];
+        return false;
+    }
+
+    void
+    SetRegisterIsValid (const lldb_private::RegisterInfo *reg_info, bool valid)
+    {
+        if (reg_info)
+            return SetRegisterIsValid (reg_info->kinds[lldb::eRegisterKindLLDB], valid);
+    }
+
+    void
+    SetRegisterIsValid (uint32_t reg, bool valid)
+    {
+#if defined (LLDB_CONFIGURATION_DEBUG)
+        assert (reg < m_reg_valid.size());
+#endif
+        if (reg < m_reg_valid.size())
+            m_reg_valid[reg] = valid;
+    }
+
+    void
+    SyncThreadState(lldb_private::Process *process);  // Assumes the sequence mutex has already been acquired.
+    
+    GDBRemoteDynamicRegisterInfo &m_reg_info;
+    std::vector<bool> m_reg_valid;
+    lldb_private::DataExtractor m_reg_data;
+    bool m_read_all_at_once;
+
+private:
+    // Helper function for ReadRegisterBytes().
+    bool GetPrimordialRegister(const lldb_private::RegisterInfo *reg_info,
+                               GDBRemoteCommunicationClient &gdb_comm);
+    // Helper function for WriteRegisterBytes().
+    bool SetPrimordialRegister(const lldb_private::RegisterInfo *reg_info,
+                               GDBRemoteCommunicationClient &gdb_comm);
+
+    //------------------------------------------------------------------
+    // For GDBRemoteRegisterContext only
+    //------------------------------------------------------------------
+    DISALLOW_COPY_AND_ASSIGN (GDBRemoteRegisterContext);
+};
+
+#endif  // lldb_GDBRemoteRegisterContext_h_
diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
new file mode 100644
index 000000000000..d27207f121d3
--- /dev/null
+++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -0,0 +1,3291 @@
+//===-- ProcessGDBRemote.cpp ------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/lldb-python.h"
+
+// C Includes
+#include <errno.h>
+#include <spawn.h>
+#include <stdlib.h>
+#include <netinet/in.h>
+#include <sys/mman.h>       // for mmap
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <time.h>
+
+// C++ Includes
+#include <algorithm>
+#include <map>
+
+// Other libraries and framework includes
+
+#include "lldb/Breakpoint/Watchpoint.h"
+#include "lldb/Interpreter/Args.h"
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Core/ConnectionFileDescriptor.h"
+#include "lldb/Host/FileSpec.h"
+#include "lldb/Core/InputReader.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/State.h"
+#include "lldb/Core/StreamFile.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Core/Timer.h"
+#include "lldb/Core/Value.h"
+#include "lldb/Host/Symbols.h"
+#include "lldb/Host/TimeValue.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/CommandObject.h"
+#include "lldb/Interpreter/CommandObjectMultiword.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Target/DynamicLoader.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/TargetList.h"
+#include "lldb/Target/ThreadPlanCallFunction.h"
+#include "lldb/Utility/PseudoTerminal.h"
+
+// Project includes
+#include "lldb/Host/Host.h"
+#include "Plugins/Process/Utility/InferiorCallPOSIX.h"
+#include "Plugins/Process/Utility/StopInfoMachException.h"
+#include "Plugins/Platform/MacOSX/PlatformRemoteiOS.h"
+#include "Utility/StringExtractorGDBRemote.h"
+#include "GDBRemoteRegisterContext.h"
+#include "ProcessGDBRemote.h"
+#include "ProcessGDBRemoteLog.h"
+#include "ThreadGDBRemote.h"
+
+
+namespace lldb
+{
+    // Provide a function that can easily dump the packet history if we know a
+    // ProcessGDBRemote * value (which we can get from logs or from debugging).
+    // We need the function in the lldb namespace so it makes it into the final
+    // executable since the LLDB shared library only exports stuff in the lldb
+    // namespace. This allows you to attach with a debugger and call this
+    // function and get the packet history dumped to a file.
+    void
+    DumpProcessGDBRemotePacketHistory (void *p, const char *path)
+    {
+        lldb_private::StreamFile strm;
+        lldb_private::Error error (strm.GetFile().Open(path, lldb_private::File::eOpenOptionWrite | lldb_private::File::eOpenOptionCanCreate));
+        if (error.Success())
+            ((ProcessGDBRemote *)p)->GetGDBRemote().DumpHistory (strm);
+    }
+}
+
+#define DEBUGSERVER_BASENAME    "debugserver"
+using namespace lldb;
+using namespace lldb_private;
+
+
+namespace {
+    
+    static PropertyDefinition
+    g_properties[] =
+    {
+        { "packet-timeout" , OptionValue::eTypeUInt64 , true , 1, NULL, NULL, "Specify the default packet timeout in seconds." },
+        {  NULL            , OptionValue::eTypeInvalid, false, 0, NULL, NULL, NULL  }
+    };
+    
+    enum
+    {
+        ePropertyPacketTimeout
+    };
+    
+    class PluginProperties : public Properties
+    {
+    public:
+        
+        static ConstString
+        GetSettingName ()
+        {
+            return ProcessGDBRemote::GetPluginNameStatic();
+        }
+        
+        PluginProperties() :
+        Properties ()
+        {
+            m_collection_sp.reset (new OptionValueProperties(GetSettingName()));
+            m_collection_sp->Initialize(g_properties);
+        }
+        
+        virtual
+        ~PluginProperties()
+        {
+        }
+        
+        uint64_t
+        GetPacketTimeout()
+        {
+            const uint32_t idx = ePropertyPacketTimeout;
+            return m_collection_sp->GetPropertyAtIndexAsUInt64(NULL, idx, g_properties[idx].default_uint_value);
+        }
+    };
+    
+    typedef std::shared_ptr<PluginProperties> ProcessKDPPropertiesSP;
+    
+    static const ProcessKDPPropertiesSP &
+    GetGlobalPluginProperties()
+    {
+        static ProcessKDPPropertiesSP g_settings_sp;
+        if (!g_settings_sp)
+            g_settings_sp.reset (new PluginProperties ());
+        return g_settings_sp;
+    }
+    
+} // anonymous namespace end
+
+static bool rand_initialized = false;
+
+// TODO Randomly assigning a port is unsafe.  We should get an unused
+// ephemeral port from the kernel and make sure we reserve it before passing
+// it to debugserver.
+
+#if defined (__APPLE__)
+#define LOW_PORT    (IPPORT_RESERVED)
+#define HIGH_PORT   (IPPORT_HIFIRSTAUTO)
+#else
+#define LOW_PORT    (1024u)
+#define HIGH_PORT   (49151u)
+#endif
+
+static inline uint16_t
+get_random_port ()
+{
+    if (!rand_initialized)
+    {
+        time_t seed = time(NULL);
+
+        rand_initialized = true;
+        srand(seed);
+    }
+    return (rand() % (HIGH_PORT - LOW_PORT)) + LOW_PORT;
+}
+
+
+lldb_private::ConstString
+ProcessGDBRemote::GetPluginNameStatic()
+{
+    static ConstString g_name("gdb-remote");
+    return g_name;
+}
+
+const char *
+ProcessGDBRemote::GetPluginDescriptionStatic()
+{
+    return "GDB Remote protocol based debugging plug-in.";
+}
+
+void
+ProcessGDBRemote::Terminate()
+{
+    PluginManager::UnregisterPlugin (ProcessGDBRemote::CreateInstance);
+}
+
+
+lldb::ProcessSP
+ProcessGDBRemote::CreateInstance (Target &target, Listener &listener, const FileSpec *crash_file_path)
+{
+    lldb::ProcessSP process_sp;
+    if (crash_file_path == NULL)
+        process_sp.reset (new ProcessGDBRemote (target, listener));
+    return process_sp;
+}
+
+bool
+ProcessGDBRemote::CanDebug (Target &target, bool plugin_specified_by_name)
+{
+    if (plugin_specified_by_name)
+        return true;
+
+    // For now we are just making sure the file exists for a given module
+    Module *exe_module = target.GetExecutableModulePointer();
+    if (exe_module)
+    {
+        ObjectFile *exe_objfile = exe_module->GetObjectFile();
+        // We can't debug core files...
+        switch (exe_objfile->GetType())
+        {
+            case ObjectFile::eTypeInvalid:
+            case ObjectFile::eTypeCoreFile:
+            case ObjectFile::eTypeDebugInfo:
+            case ObjectFile::eTypeObjectFile:
+            case ObjectFile::eTypeSharedLibrary:
+            case ObjectFile::eTypeStubLibrary:
+                return false;
+            case ObjectFile::eTypeExecutable:
+            case ObjectFile::eTypeDynamicLinker:
+            case ObjectFile::eTypeUnknown:
+                break;
+        }
+        return exe_module->GetFileSpec().Exists();
+    }
+    // However, if there is no executable module, we return true since we might be preparing to attach.
+    return true;
+}
+
+//----------------------------------------------------------------------
+// ProcessGDBRemote constructor
+//----------------------------------------------------------------------
+ProcessGDBRemote::ProcessGDBRemote(Target& target, Listener &listener) :
+    Process (target, listener),
+    m_flags (0),
+    m_gdb_comm(false),
+    m_debugserver_pid (LLDB_INVALID_PROCESS_ID),
+    m_last_stop_packet (),
+    m_last_stop_packet_mutex (Mutex::eMutexTypeNormal),
+    m_register_info (),
+    m_async_broadcaster (NULL, "lldb.process.gdb-remote.async-broadcaster"),
+    m_async_thread (LLDB_INVALID_HOST_THREAD),
+    m_async_thread_state(eAsyncThreadNotStarted),
+    m_async_thread_state_mutex(Mutex::eMutexTypeRecursive),
+    m_thread_ids (),
+    m_continue_c_tids (),
+    m_continue_C_tids (),
+    m_continue_s_tids (),
+    m_continue_S_tids (),
+    m_dispatch_queue_offsets_addr (LLDB_INVALID_ADDRESS),
+    m_max_memory_size (512),
+    m_addr_to_mmap_size (),
+    m_thread_create_bp_sp (),
+    m_waiting_for_attach (false),
+    m_destroy_tried_resuming (false),
+    m_command_sp ()
+{
+    m_async_broadcaster.SetEventName (eBroadcastBitAsyncThreadShouldExit,   "async thread should exit");
+    m_async_broadcaster.SetEventName (eBroadcastBitAsyncContinue,           "async thread continue");
+    m_async_broadcaster.SetEventName (eBroadcastBitAsyncThreadDidExit,      "async thread did exit");
+    const uint64_t timeout_seconds = GetGlobalPluginProperties()->GetPacketTimeout();
+    if (timeout_seconds > 0)
+        m_gdb_comm.SetPacketTimeout(timeout_seconds);
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+ProcessGDBRemote::~ProcessGDBRemote()
+{
+    //  m_mach_process.UnregisterNotificationCallbacks (this);
+    Clear();
+    // We need to call finalize on the process before destroying ourselves
+    // to make sure all of the broadcaster cleanup goes as planned. If we
+    // destruct this class, then Process::~Process() might have problems
+    // trying to fully destroy the broadcaster.
+    Finalize();
+    
+    // The general Finalize is going to try to destroy the process and that SHOULD
+    // shut down the async thread.  However, if we don't kill it it will get stranded and
+    // its connection will go away so when it wakes up it will crash.  So kill it for sure here.
+    StopAsyncThread();
+    KillDebugserverProcess();
+}
+
+//----------------------------------------------------------------------
+// PluginInterface
+//----------------------------------------------------------------------
+ConstString
+ProcessGDBRemote::GetPluginName()
+{
+    return GetPluginNameStatic();
+}
+
+uint32_t
+ProcessGDBRemote::GetPluginVersion()
+{
+    return 1;
+}
+
+void
+ProcessGDBRemote::BuildDynamicRegisterInfo (bool force)
+{
+    if (!force && m_register_info.GetNumRegisters() > 0)
+        return;
+
+    char packet[128];
+    m_register_info.Clear();
+    uint32_t reg_offset = 0;
+    uint32_t reg_num = 0;
+    for (StringExtractorGDBRemote::ResponseType response_type = StringExtractorGDBRemote::eResponse;
+         response_type == StringExtractorGDBRemote::eResponse; 
+         ++reg_num)
+    {
+        const int packet_len = ::snprintf (packet, sizeof(packet), "qRegisterInfo%x", reg_num);
+        assert (packet_len < (int)sizeof(packet));
+        StringExtractorGDBRemote response;
+        if (m_gdb_comm.SendPacketAndWaitForResponse(packet, packet_len, response, false))
+        {
+            response_type = response.GetResponseType();
+            if (response_type == StringExtractorGDBRemote::eResponse)
+            {
+                std::string name;
+                std::string value;
+                ConstString reg_name;
+                ConstString alt_name;
+                ConstString set_name;
+                std::vector<uint32_t> value_regs;
+                std::vector<uint32_t> invalidate_regs;
+                RegisterInfo reg_info = { NULL,                 // Name
+                    NULL,                 // Alt name
+                    0,                    // byte size
+                    reg_offset,           // offset
+                    eEncodingUint,        // encoding
+                    eFormatHex,           // formate
+                    {
+                        LLDB_INVALID_REGNUM, // GCC reg num
+                        LLDB_INVALID_REGNUM, // DWARF reg num
+                        LLDB_INVALID_REGNUM, // generic reg num
+                        reg_num,             // GDB reg num
+                        reg_num           // native register number
+                    },
+                    NULL,
+                    NULL
+                };
+
+                while (response.GetNameColonValue(name, value))
+                {
+                    if (name.compare("name") == 0)
+                    {
+                        reg_name.SetCString(value.c_str());
+                    }
+                    else if (name.compare("alt-name") == 0)
+                    {
+                        alt_name.SetCString(value.c_str());
+                    }
+                    else if (name.compare("bitsize") == 0)
+                    {
+                        reg_info.byte_size = Args::StringToUInt32(value.c_str(), 0, 0) / CHAR_BIT;
+                    }
+                    else if (name.compare("offset") == 0)
+                    {
+                        uint32_t offset = Args::StringToUInt32(value.c_str(), UINT32_MAX, 0);
+                        if (reg_offset != offset)
+                        {
+                            reg_offset = offset;
+                        }
+                    }
+                    else if (name.compare("encoding") == 0)
+                    {
+                        const Encoding encoding = Args::StringToEncoding (value.c_str());
+                        if (encoding != eEncodingInvalid)
+                            reg_info.encoding = encoding;
+                    }
+                    else if (name.compare("format") == 0)
+                    {
+                        Format format = eFormatInvalid;
+                        if (Args::StringToFormat (value.c_str(), format, NULL).Success())
+                            reg_info.format = format;
+                        else if (value.compare("binary") == 0)
+                            reg_info.format = eFormatBinary;
+                        else if (value.compare("decimal") == 0)
+                            reg_info.format = eFormatDecimal;
+                        else if (value.compare("hex") == 0)
+                            reg_info.format = eFormatHex;
+                        else if (value.compare("float") == 0)
+                            reg_info.format = eFormatFloat;
+                        else if (value.compare("vector-sint8") == 0)
+                            reg_info.format = eFormatVectorOfSInt8;
+                        else if (value.compare("vector-uint8") == 0)
+                            reg_info.format = eFormatVectorOfUInt8;
+                        else if (value.compare("vector-sint16") == 0)
+                            reg_info.format = eFormatVectorOfSInt16;
+                        else if (value.compare("vector-uint16") == 0)
+                            reg_info.format = eFormatVectorOfUInt16;
+                        else if (value.compare("vector-sint32") == 0)
+                            reg_info.format = eFormatVectorOfSInt32;
+                        else if (value.compare("vector-uint32") == 0)
+                            reg_info.format = eFormatVectorOfUInt32;
+                        else if (value.compare("vector-float32") == 0)
+                            reg_info.format = eFormatVectorOfFloat32;
+                        else if (value.compare("vector-uint128") == 0)
+                            reg_info.format = eFormatVectorOfUInt128;
+                    }
+                    else if (name.compare("set") == 0)
+                    {
+                        set_name.SetCString(value.c_str());
+                    }
+                    else if (name.compare("gcc") == 0)
+                    {
+                        reg_info.kinds[eRegisterKindGCC] = Args::StringToUInt32(value.c_str(), LLDB_INVALID_REGNUM, 0);
+                    }
+                    else if (name.compare("dwarf") == 0)
+                    {
+                        reg_info.kinds[eRegisterKindDWARF] = Args::StringToUInt32(value.c_str(), LLDB_INVALID_REGNUM, 0);
+                    }
+                    else if (name.compare("generic") == 0)
+                    {
+                        reg_info.kinds[eRegisterKindGeneric] = Args::StringToGenericRegister (value.c_str());
+                    }
+                    else if (name.compare("container-regs") == 0)
+                    {
+                        std::pair<llvm::StringRef, llvm::StringRef> value_pair;
+                        value_pair.second = value;
+                        do
+                        {
+                            value_pair = value_pair.second.split(',');
+                            if (!value_pair.first.empty())
+                            {
+                                uint32_t reg = Args::StringToUInt32 (value_pair.first.str().c_str(), LLDB_INVALID_REGNUM, 16);
+                                if (reg != LLDB_INVALID_REGNUM)
+                                    value_regs.push_back (reg);
+                            }
+                        } while (!value_pair.second.empty());
+                    }
+                    else if (name.compare("invalidate-regs") == 0)
+                    {
+                        std::pair<llvm::StringRef, llvm::StringRef> value_pair;
+                        value_pair.second = value;
+                        do
+                        {
+                            value_pair = value_pair.second.split(',');
+                            if (!value_pair.first.empty())
+                            {
+                                uint32_t reg = Args::StringToUInt32 (value_pair.first.str().c_str(), LLDB_INVALID_REGNUM, 16);
+                                if (reg != LLDB_INVALID_REGNUM)
+                                    invalidate_regs.push_back (reg);
+                            }
+                        } while (!value_pair.second.empty());
+                    }
+                }
+
+                reg_info.byte_offset = reg_offset;
+                assert (reg_info.byte_size != 0);
+                reg_offset += reg_info.byte_size;
+                if (!value_regs.empty())
+                {
+                    value_regs.push_back(LLDB_INVALID_REGNUM);
+                    reg_info.value_regs = value_regs.data();
+                }
+                if (!invalidate_regs.empty())
+                {
+                    invalidate_regs.push_back(LLDB_INVALID_REGNUM);
+                    reg_info.invalidate_regs = invalidate_regs.data();
+                }
+
+                m_register_info.AddRegister(reg_info, reg_name, alt_name, set_name);
+            }
+        }
+        else
+        {
+            break;
+        }
+    }
+
+    // We didn't get anything if the accumulated reg_num is zero.  See if we are
+    // debugging ARM and fill with a hard coded register set until we can get an
+    // updated debugserver down on the devices.
+    // On the other hand, if the accumulated reg_num is positive, see if we can
+    // add composite registers to the existing primordial ones.
+    bool from_scratch = (reg_num == 0);
+
+    const ArchSpec &target_arch = GetTarget().GetArchitecture();
+    const ArchSpec &remote_host_arch = m_gdb_comm.GetHostArchitecture();
+    const ArchSpec &remote_process_arch = m_gdb_comm.GetProcessArchitecture();
+
+    // Use the process' architecture instead of the host arch, if available
+    ArchSpec remote_arch;
+    if (remote_process_arch.IsValid ())
+        remote_arch = remote_process_arch;
+    else
+        remote_arch = remote_host_arch;
+
+    if (!target_arch.IsValid())
+    {
+        if (remote_arch.IsValid()
+              && remote_arch.GetMachine() == llvm::Triple::arm
+              && remote_arch.GetTriple().getVendor() == llvm::Triple::Apple)
+            m_register_info.HardcodeARMRegisters(from_scratch);
+    }
+    else if (target_arch.GetMachine() == llvm::Triple::arm)
+    {
+        m_register_info.HardcodeARMRegisters(from_scratch);
+    }
+
+    // At this point, we can finalize our register info.
+    m_register_info.Finalize ();
+}
+
+Error
+ProcessGDBRemote::WillLaunch (Module* module)
+{
+    return WillLaunchOrAttach ();
+}
+
+Error
+ProcessGDBRemote::WillAttachToProcessWithID (lldb::pid_t pid)
+{
+    return WillLaunchOrAttach ();
+}
+
+Error
+ProcessGDBRemote::WillAttachToProcessWithName (const char *process_name, bool wait_for_launch)
+{
+    return WillLaunchOrAttach ();
+}
+
+Error
+ProcessGDBRemote::DoConnectRemote (Stream *strm, const char *remote_url)
+{
+    Error error (WillLaunchOrAttach ());
+    
+    if (error.Fail())
+        return error;
+
+    error = ConnectToDebugserver (remote_url);
+
+    if (error.Fail())
+        return error;
+    StartAsyncThread ();
+
+    lldb::pid_t pid = m_gdb_comm.GetCurrentProcessID ();
+    if (pid == LLDB_INVALID_PROCESS_ID)
+    {
+        // We don't have a valid process ID, so note that we are connected
+        // and could now request to launch or attach, or get remote process 
+        // listings...
+        SetPrivateState (eStateConnected);
+    }
+    else
+    {
+        // We have a valid process
+        SetID (pid);
+        GetThreadList();
+        if (m_gdb_comm.SendPacketAndWaitForResponse("?", 1, m_last_stop_packet, false))
+        {
+            const StateType state = SetThreadStopInfo (m_last_stop_packet);
+            if (state == eStateStopped)
+            {
+                SetPrivateState (state);
+            }
+            else
+                error.SetErrorStringWithFormat ("Process %" PRIu64 " was reported after connecting to '%s', but state was not stopped: %s", pid, remote_url, StateAsCString (state));
+        }
+        else
+            error.SetErrorStringWithFormat ("Process %" PRIu64 " was reported after connecting to '%s', but no stop reply packet was received", pid, remote_url);
+    }
+
+    if (error.Success() 
+        && !GetTarget().GetArchitecture().IsValid()
+        && m_gdb_comm.GetHostArchitecture().IsValid())
+    {
+        // Prefer the *process'* architecture over that of the *host*, if available.
+        if (m_gdb_comm.GetProcessArchitecture().IsValid())
+            GetTarget().SetArchitecture(m_gdb_comm.GetProcessArchitecture());
+        else
+            GetTarget().SetArchitecture(m_gdb_comm.GetHostArchitecture());
+    }
+
+    return error;
+}
+
+Error
+ProcessGDBRemote::WillLaunchOrAttach ()
+{
+    Error error;
+    m_stdio_communication.Clear ();
+    return error;
+}
+
+//----------------------------------------------------------------------
+// Process Control
+//----------------------------------------------------------------------
+Error
+ProcessGDBRemote::DoLaunch (Module *exe_module, const ProcessLaunchInfo &launch_info)
+{
+    Error error;
+
+    uint32_t launch_flags = launch_info.GetFlags().Get();
+    const char *stdin_path = NULL;
+    const char *stdout_path = NULL;
+    const char *stderr_path = NULL;
+    const char *working_dir = launch_info.GetWorkingDirectory();
+
+    const ProcessLaunchInfo::FileAction *file_action;
+    file_action = launch_info.GetFileActionForFD (STDIN_FILENO);
+    if (file_action)
+    {
+        if (file_action->GetAction () == ProcessLaunchInfo::FileAction::eFileActionOpen)
+            stdin_path = file_action->GetPath();
+    }
+    file_action = launch_info.GetFileActionForFD (STDOUT_FILENO);
+    if (file_action)
+    {
+        if (file_action->GetAction () == ProcessLaunchInfo::FileAction::eFileActionOpen)
+            stdout_path = file_action->GetPath();
+    }
+    file_action = launch_info.GetFileActionForFD (STDERR_FILENO);
+    if (file_action)
+    {
+        if (file_action->GetAction () == ProcessLaunchInfo::FileAction::eFileActionOpen)
+            stderr_path = file_action->GetPath();
+    }
+
+    //  ::LogSetBitMask (GDBR_LOG_DEFAULT);
+    //  ::LogSetOptions (LLDB_LOG_OPTION_THREADSAFE | LLDB_LOG_OPTION_PREPEND_TIMESTAMP | LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD);
+    //  ::LogSetLogFile ("/dev/stdout");
+    Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
+
+    ObjectFile * object_file = exe_module->GetObjectFile();
+    if (object_file)
+    {
+        char host_port[128];
+        snprintf (host_port, sizeof(host_port), "localhost:%u", get_random_port ());
+        char connect_url[128];
+        snprintf (connect_url, sizeof(connect_url), "connect://%s", host_port);
+
+        // Make sure we aren't already connected?
+        if (!m_gdb_comm.IsConnected())
+        {
+            error = StartDebugserverProcess (host_port, launch_info);
+            if (error.Fail())
+            {
+                if (log)
+                    log->Printf("failed to start debugserver process: %s", error.AsCString());
+                return error;
+            }
+
+            error = ConnectToDebugserver (connect_url);
+        }
+        
+        if (error.Success())
+        {
+            lldb_utility::PseudoTerminal pty;
+            const bool disable_stdio = (launch_flags & eLaunchFlagDisableSTDIO) != 0;
+
+            // If the debugserver is local and we aren't disabling STDIO, lets use
+            // a pseudo terminal to instead of relying on the 'O' packets for stdio
+            // since 'O' packets can really slow down debugging if the inferior 
+            // does a lot of output.
+            PlatformSP platform_sp (m_target.GetPlatform());
+            if (platform_sp && platform_sp->IsHost() && !disable_stdio)
+            {
+                const char *slave_name = NULL;
+                if (stdin_path == NULL || stdout_path == NULL || stderr_path == NULL)
+                {
+                    if (pty.OpenFirstAvailableMaster(O_RDWR|O_NOCTTY, NULL, 0))
+                        slave_name = pty.GetSlaveName (NULL, 0);
+                }
+                if (stdin_path == NULL) 
+                    stdin_path = slave_name;
+
+                if (stdout_path == NULL)
+                    stdout_path = slave_name;
+
+                if (stderr_path == NULL)
+                    stderr_path = slave_name;
+            }
+
+            // Set STDIN to /dev/null if we want STDIO disabled or if either
+            // STDOUT or STDERR have been set to something and STDIN hasn't
+            if (disable_stdio || (stdin_path == NULL && (stdout_path || stderr_path)))
+                stdin_path = "/dev/null";
+            
+            // Set STDOUT to /dev/null if we want STDIO disabled or if either
+            // STDIN or STDERR have been set to something and STDOUT hasn't
+            if (disable_stdio || (stdout_path == NULL && (stdin_path || stderr_path)))
+                stdout_path = "/dev/null";
+            
+            // Set STDERR to /dev/null if we want STDIO disabled or if either
+            // STDIN or STDOUT have been set to something and STDERR hasn't
+            if (disable_stdio || (stderr_path == NULL && (stdin_path || stdout_path)))
+                stderr_path = "/dev/null";
+
+            if (stdin_path) 
+                m_gdb_comm.SetSTDIN (stdin_path);
+            if (stdout_path)
+                m_gdb_comm.SetSTDOUT (stdout_path);
+            if (stderr_path)
+                m_gdb_comm.SetSTDERR (stderr_path);
+
+            m_gdb_comm.SetDisableASLR (launch_flags & eLaunchFlagDisableASLR);
+
+            m_gdb_comm.SendLaunchArchPacket (m_target.GetArchitecture().GetArchitectureName());
+            
+            if (working_dir && working_dir[0])
+            {
+                m_gdb_comm.SetWorkingDir (working_dir);
+            }
+
+            // Send the environment and the program + arguments after we connect
+            const Args &environment = launch_info.GetEnvironmentEntries();
+            if (environment.GetArgumentCount())
+            {
+                size_t num_environment_entries = environment.GetArgumentCount();
+                for (size_t i=0; i<num_environment_entries; ++i)
+                {
+                    const char *env_entry = environment.GetArgumentAtIndex(i);
+                    if (env_entry == NULL || m_gdb_comm.SendEnvironmentPacket(env_entry) != 0)
+                        break;
+                }
+            }
+
+            const uint32_t old_packet_timeout = m_gdb_comm.SetPacketTimeout (10);
+            int arg_packet_err = m_gdb_comm.SendArgumentsPacket (launch_info.GetArguments().GetConstArgumentVector());
+            if (arg_packet_err == 0)
+            {
+                std::string error_str;
+                if (m_gdb_comm.GetLaunchSuccess (error_str))
+                {
+                    SetID (m_gdb_comm.GetCurrentProcessID ());
+                }
+                else
+                {
+                    error.SetErrorString (error_str.c_str());
+                }
+            }
+            else
+            {
+                error.SetErrorStringWithFormat("'A' packet returned an error: %i", arg_packet_err);
+            }
+            
+            m_gdb_comm.SetPacketTimeout (old_packet_timeout);
+                
+            if (GetID() == LLDB_INVALID_PROCESS_ID)
+            {
+                if (log)
+                    log->Printf("failed to connect to debugserver: %s", error.AsCString());
+                KillDebugserverProcess ();
+                return error;
+            }
+
+            if (m_gdb_comm.SendPacketAndWaitForResponse("?", 1, m_last_stop_packet, false))
+            {
+                SetPrivateState (SetThreadStopInfo (m_last_stop_packet));
+                
+                if (!disable_stdio)
+                {
+                    if (pty.GetMasterFileDescriptor() != lldb_utility::PseudoTerminal::invalid_fd)
+                        SetSTDIOFileDescriptor (pty.ReleaseMasterFileDescriptor());
+                }
+            }
+        }
+        else
+        {
+            if (log)
+                log->Printf("failed to connect to debugserver: %s", error.AsCString());
+        }
+    }
+    else
+    {
+        // Set our user ID to an invalid process ID.
+        SetID(LLDB_INVALID_PROCESS_ID);
+        error.SetErrorStringWithFormat ("failed to get object file from '%s' for arch %s", 
+                                        exe_module->GetFileSpec().GetFilename().AsCString(), 
+                                        exe_module->GetArchitecture().GetArchitectureName());
+    }
+    return error;
+
+}
+
+
+Error
+ProcessGDBRemote::ConnectToDebugserver (const char *connect_url)
+{
+    Error error;
+    // Sleep and wait a bit for debugserver to start to listen...
+    std::unique_ptr<ConnectionFileDescriptor> conn_ap(new ConnectionFileDescriptor());
+    if (conn_ap.get())
+    {
+        const uint32_t max_retry_count = 50;
+        uint32_t retry_count = 0;
+        while (!m_gdb_comm.IsConnected())
+        {
+            if (conn_ap->Connect(connect_url, &error) == eConnectionStatusSuccess)
+            {
+                m_gdb_comm.SetConnection (conn_ap.release());
+                break;
+            }
+            else if (error.WasInterrupted())
+            {
+                // If we were interrupted, don't keep retrying.
+                break;
+            }
+            
+            retry_count++;
+            
+            if (retry_count >= max_retry_count)
+                break;
+
+            usleep (100000);
+        }
+    }
+
+    if (!m_gdb_comm.IsConnected())
+    {
+        if (error.Success())
+            error.SetErrorString("not connected to remote gdb server");
+        return error;
+    }
+
+    // We always seem to be able to open a connection to a local port
+    // so we need to make sure we can then send data to it. If we can't
+    // then we aren't actually connected to anything, so try and do the
+    // handshake with the remote GDB server and make sure that goes 
+    // alright.
+    if (!m_gdb_comm.HandshakeWithServer (NULL))
+    {
+        m_gdb_comm.Disconnect();
+        if (error.Success())
+            error.SetErrorString("not connected to remote gdb server");
+        return error;
+    }
+    m_gdb_comm.ResetDiscoverableSettings();
+    m_gdb_comm.QueryNoAckModeSupported ();
+    m_gdb_comm.GetThreadSuffixSupported ();
+    m_gdb_comm.GetListThreadsInStopReplySupported ();
+    m_gdb_comm.GetHostInfo ();
+    m_gdb_comm.GetVContSupported ('c');
+    m_gdb_comm.GetVAttachOrWaitSupported();
+    
+    size_t num_cmds = GetExtraStartupCommands().GetArgumentCount();
+    for (size_t idx = 0; idx < num_cmds; idx++)
+    {
+        StringExtractorGDBRemote response;
+        m_gdb_comm.SendPacketAndWaitForResponse (GetExtraStartupCommands().GetArgumentAtIndex(idx), response, false);
+    }
+    return error;
+}
+
+void
+ProcessGDBRemote::DidLaunchOrAttach ()
+{
+    Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
+    if (log)
+        log->Printf ("ProcessGDBRemote::DidLaunch()");
+    if (GetID() != LLDB_INVALID_PROCESS_ID)
+    {
+        m_dispatch_queue_offsets_addr = LLDB_INVALID_ADDRESS;
+
+        BuildDynamicRegisterInfo (false);
+
+        // See if the GDB server supports the qHostInfo information
+
+        ArchSpec gdb_remote_arch = m_gdb_comm.GetHostArchitecture();
+
+        // See if the GDB server supports the qProcessInfo packet, if so
+        // prefer that over the Host information as it will be more specific
+        // to our process.
+
+        if (m_gdb_comm.GetProcessArchitecture().IsValid())
+            gdb_remote_arch = m_gdb_comm.GetProcessArchitecture();
+
+        if (gdb_remote_arch.IsValid())
+        {
+            ArchSpec &target_arch = GetTarget().GetArchitecture();
+
+            if (target_arch.IsValid())
+            {
+                // If the remote host is ARM and we have apple as the vendor, then 
+                // ARM executables and shared libraries can have mixed ARM architectures.
+                // You can have an armv6 executable, and if the host is armv7, then the
+                // system will load the best possible architecture for all shared libraries
+                // it has, so we really need to take the remote host architecture as our
+                // defacto architecture in this case.
+
+                if (gdb_remote_arch.GetMachine() == llvm::Triple::arm &&
+                    gdb_remote_arch.GetTriple().getVendor() == llvm::Triple::Apple)
+                {
+                    target_arch = gdb_remote_arch;
+                }
+                else
+                {
+                    // Fill in what is missing in the triple
+                    const llvm::Triple &remote_triple = gdb_remote_arch.GetTriple();
+                    llvm::Triple &target_triple = target_arch.GetTriple();
+                    if (target_triple.getVendorName().size() == 0)
+                    {
+                        target_triple.setVendor (remote_triple.getVendor());
+
+                        if (target_triple.getOSName().size() == 0)
+                        {
+                            target_triple.setOS (remote_triple.getOS());
+
+                            if (target_triple.getEnvironmentName().size() == 0)
+                                target_triple.setEnvironment (remote_triple.getEnvironment());
+                        }
+                    }
+                }
+            }
+            else
+            {
+                // The target doesn't have a valid architecture yet, set it from
+                // the architecture we got from the remote GDB server
+                target_arch = gdb_remote_arch;
+            }
+        }
+    }
+}
+
+void
+ProcessGDBRemote::DidLaunch ()
+{
+    DidLaunchOrAttach ();
+}
+
+Error
+ProcessGDBRemote::DoAttachToProcessWithID (lldb::pid_t attach_pid)
+{
+    ProcessAttachInfo attach_info;
+    return DoAttachToProcessWithID(attach_pid, attach_info);
+}
+
+Error
+ProcessGDBRemote::DoAttachToProcessWithID (lldb::pid_t attach_pid, const ProcessAttachInfo &attach_info)
+{
+    Error error;
+    // Clear out and clean up from any current state
+    Clear();
+    if (attach_pid != LLDB_INVALID_PROCESS_ID)
+    {
+        // Make sure we aren't already connected?
+        if (!m_gdb_comm.IsConnected())
+        {
+            char host_port[128];
+            snprintf (host_port, sizeof(host_port), "localhost:%u", get_random_port ());
+            char connect_url[128];
+            snprintf (connect_url, sizeof(connect_url), "connect://%s", host_port);
+
+            error = StartDebugserverProcess (host_port, attach_info);
+            
+            if (error.Fail())
+            {
+                const char *error_string = error.AsCString();
+                if (error_string == NULL)
+                    error_string = "unable to launch " DEBUGSERVER_BASENAME;
+
+                SetExitStatus (-1, error_string);
+            }
+            else
+            {
+                error = ConnectToDebugserver (connect_url);
+            }
+        }
+    
+        if (error.Success())
+        {
+            char packet[64];
+            const int packet_len = ::snprintf (packet, sizeof(packet), "vAttach;%" PRIx64, attach_pid);
+            SetID (attach_pid);            
+            m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncContinue, new EventDataBytes (packet, packet_len));
+        }
+    }
+    return error;
+}
+
+size_t
+ProcessGDBRemote::AttachInputReaderCallback
+(
+    void *baton, 
+    InputReader *reader, 
+    lldb::InputReaderAction notification,
+    const char *bytes, 
+    size_t bytes_len
+)
+{
+    if (notification == eInputReaderGotToken)
+    {
+        ProcessGDBRemote *gdb_process = (ProcessGDBRemote *)baton;
+        if (gdb_process->m_waiting_for_attach)
+            gdb_process->m_waiting_for_attach = false;
+        reader->SetIsDone(true);
+        return 1;
+    }
+    return 0;
+}
+
+Error
+ProcessGDBRemote::DoAttachToProcessWithName (const char *process_name, bool wait_for_launch, const ProcessAttachInfo &attach_info)
+{
+    Error error;
+    // Clear out and clean up from any current state
+    Clear();
+
+    if (process_name && process_name[0])
+    {
+        // Make sure we aren't already connected?
+        if (!m_gdb_comm.IsConnected())
+        {
+            char host_port[128];
+            snprintf (host_port, sizeof(host_port), "localhost:%u", get_random_port ());
+            char connect_url[128];
+            snprintf (connect_url, sizeof(connect_url), "connect://%s", host_port);
+
+            error = StartDebugserverProcess (host_port, attach_info);
+            if (error.Fail())
+            {
+                const char *error_string = error.AsCString();
+                if (error_string == NULL)
+                    error_string = "unable to launch " DEBUGSERVER_BASENAME;
+
+                SetExitStatus (-1, error_string);
+            }
+            else
+            {
+                error = ConnectToDebugserver (connect_url);
+            }
+        }
+
+        if (error.Success())
+        {
+            StreamString packet;
+            
+            if (wait_for_launch)
+            {
+                if (!m_gdb_comm.GetVAttachOrWaitSupported())
+                {
+                    packet.PutCString ("vAttachWait");
+                }
+                else
+                {
+                    if (attach_info.GetIgnoreExisting())
+                        packet.PutCString("vAttachWait");
+                    else
+                        packet.PutCString ("vAttachOrWait");
+                }
+            }
+            else
+                packet.PutCString("vAttachName");
+            packet.PutChar(';');
+            packet.PutBytesAsRawHex8(process_name, strlen(process_name), lldb::endian::InlHostByteOrder(), lldb::endian::InlHostByteOrder());
+            
+            m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncContinue, new EventDataBytes (packet.GetData(), packet.GetSize()));
+
+        }
+    }
+    return error;
+}
+
+
+void
+ProcessGDBRemote::DidAttach ()
+{
+    DidLaunchOrAttach ();
+}
+
+
+Error
+ProcessGDBRemote::WillResume ()
+{
+    m_continue_c_tids.clear();
+    m_continue_C_tids.clear();
+    m_continue_s_tids.clear();
+    m_continue_S_tids.clear();
+    return Error();
+}
+
+Error
+ProcessGDBRemote::DoResume ()
+{
+    Error error;
+    Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
+    if (log)
+        log->Printf ("ProcessGDBRemote::Resume()");
+    
+    Listener listener ("gdb-remote.resume-packet-sent");
+    if (listener.StartListeningForEvents (&m_gdb_comm, GDBRemoteCommunication::eBroadcastBitRunPacketSent))
+    {
+        listener.StartListeningForEvents (&m_async_broadcaster, ProcessGDBRemote::eBroadcastBitAsyncThreadDidExit);
+        
+        const size_t num_threads = GetThreadList().GetSize();
+
+        StreamString continue_packet;
+        bool continue_packet_error = false;
+        if (m_gdb_comm.HasAnyVContSupport ())
+        {
+            if (m_continue_c_tids.size() == num_threads)
+            {
+                // All threads are continuing, just send a "c" packet
+                continue_packet.PutCString ("c");
+            }
+            else
+            {
+                continue_packet.PutCString ("vCont");
+            
+                if (!m_continue_c_tids.empty())
+                {
+                    if (m_gdb_comm.GetVContSupported ('c'))
+                    {
+                        for (tid_collection::const_iterator t_pos = m_continue_c_tids.begin(), t_end = m_continue_c_tids.end(); t_pos != t_end; ++t_pos)
+                            continue_packet.Printf(";c:%4.4" PRIx64, *t_pos);
+                    }
+                    else 
+                        continue_packet_error = true;
+                }
+                
+                if (!continue_packet_error && !m_continue_C_tids.empty())
+                {
+                    if (m_gdb_comm.GetVContSupported ('C'))
+                    {
+                        for (tid_sig_collection::const_iterator s_pos = m_continue_C_tids.begin(), s_end = m_continue_C_tids.end(); s_pos != s_end; ++s_pos)
+                            continue_packet.Printf(";C%2.2x:%4.4" PRIx64, s_pos->second, s_pos->first);
+                    }
+                    else 
+                        continue_packet_error = true;
+                }
+
+                if (!continue_packet_error && !m_continue_s_tids.empty())
+                {
+                    if (m_gdb_comm.GetVContSupported ('s'))
+                    {
+                        for (tid_collection::const_iterator t_pos = m_continue_s_tids.begin(), t_end = m_continue_s_tids.end(); t_pos != t_end; ++t_pos)
+                            continue_packet.Printf(";s:%4.4" PRIx64, *t_pos);
+                    }
+                    else 
+                        continue_packet_error = true;
+                }
+                
+                if (!continue_packet_error && !m_continue_S_tids.empty())
+                {
+                    if (m_gdb_comm.GetVContSupported ('S'))
+                    {
+                        for (tid_sig_collection::const_iterator s_pos = m_continue_S_tids.begin(), s_end = m_continue_S_tids.end(); s_pos != s_end; ++s_pos)
+                            continue_packet.Printf(";S%2.2x:%4.4" PRIx64, s_pos->second, s_pos->first);
+                    }
+                    else
+                        continue_packet_error = true;
+                }
+                
+                if (continue_packet_error)
+                    continue_packet.GetString().clear();
+            }
+        }
+        else
+            continue_packet_error = true;
+        
+        if (continue_packet_error)
+        {
+            // Either no vCont support, or we tried to use part of the vCont
+            // packet that wasn't supported by the remote GDB server.
+            // We need to try and make a simple packet that can do our continue
+            const size_t num_continue_c_tids = m_continue_c_tids.size();
+            const size_t num_continue_C_tids = m_continue_C_tids.size();
+            const size_t num_continue_s_tids = m_continue_s_tids.size();
+            const size_t num_continue_S_tids = m_continue_S_tids.size();
+            if (num_continue_c_tids > 0)
+            {
+                if (num_continue_c_tids == num_threads)
+                {
+                    // All threads are resuming...
+                    m_gdb_comm.SetCurrentThreadForRun (-1);
+                    continue_packet.PutChar ('c'); 
+                    continue_packet_error = false;
+                }
+                else if (num_continue_c_tids == 1 &&
+                         num_continue_C_tids == 0 && 
+                         num_continue_s_tids == 0 && 
+                         num_continue_S_tids == 0 )
+                {
+                    // Only one thread is continuing
+                    m_gdb_comm.SetCurrentThreadForRun (m_continue_c_tids.front());
+                    continue_packet.PutChar ('c');                
+                    continue_packet_error = false;
+                }
+            }
+
+            if (continue_packet_error && num_continue_C_tids > 0)
+            {
+                if ((num_continue_C_tids + num_continue_c_tids) == num_threads && 
+                    num_continue_C_tids > 0 && 
+                    num_continue_s_tids == 0 && 
+                    num_continue_S_tids == 0 )
+                {
+                    const int continue_signo = m_continue_C_tids.front().second;
+                    // Only one thread is continuing
+                    if (num_continue_C_tids > 1)
+                    {
+                        // More that one thread with a signal, yet we don't have 
+                        // vCont support and we are being asked to resume each
+                        // thread with a signal, we need to make sure they are
+                        // all the same signal, or we can't issue the continue
+                        // accurately with the current support...
+                        if (num_continue_C_tids > 1)
+                        {
+                            continue_packet_error = false;
+                            for (size_t i=1; i<m_continue_C_tids.size(); ++i)
+                            {
+                                if (m_continue_C_tids[i].second != continue_signo)
+                                    continue_packet_error = true;
+                            }
+                        }
+                        if (!continue_packet_error)
+                            m_gdb_comm.SetCurrentThreadForRun (-1);
+                    }
+                    else
+                    {
+                        // Set the continue thread ID
+                        continue_packet_error = false;
+                        m_gdb_comm.SetCurrentThreadForRun (m_continue_C_tids.front().first);
+                    }
+                    if (!continue_packet_error)
+                    {
+                        // Add threads continuing with the same signo...
+                        continue_packet.Printf("C%2.2x", continue_signo);
+                    }
+                }
+            }
+
+            if (continue_packet_error && num_continue_s_tids > 0)
+            {
+                if (num_continue_s_tids == num_threads)
+                {
+                    // All threads are resuming...
+                    m_gdb_comm.SetCurrentThreadForRun (-1);
+                    continue_packet.PutChar ('s');
+                    continue_packet_error = false;
+                }
+                else if (num_continue_c_tids == 0 &&
+                         num_continue_C_tids == 0 && 
+                         num_continue_s_tids == 1 && 
+                         num_continue_S_tids == 0 )
+                {
+                    // Only one thread is stepping
+                    m_gdb_comm.SetCurrentThreadForRun (m_continue_s_tids.front());
+                    continue_packet.PutChar ('s');                
+                    continue_packet_error = false;
+                }
+            }
+
+            if (!continue_packet_error && num_continue_S_tids > 0)
+            {
+                if (num_continue_S_tids == num_threads)
+                {
+                    const int step_signo = m_continue_S_tids.front().second;
+                    // Are all threads trying to step with the same signal?
+                    continue_packet_error = false;
+                    if (num_continue_S_tids > 1)
+                    {
+                        for (size_t i=1; i<num_threads; ++i)
+                        {
+                            if (m_continue_S_tids[i].second != step_signo)
+                                continue_packet_error = true;
+                        }
+                    }
+                    if (!continue_packet_error)
+                    {
+                        // Add threads stepping with the same signo...
+                        m_gdb_comm.SetCurrentThreadForRun (-1);
+                        continue_packet.Printf("S%2.2x", step_signo);
+                    }
+                }
+                else if (num_continue_c_tids == 0 &&
+                         num_continue_C_tids == 0 && 
+                         num_continue_s_tids == 0 && 
+                         num_continue_S_tids == 1 )
+                {
+                    // Only one thread is stepping with signal
+                    m_gdb_comm.SetCurrentThreadForRun (m_continue_S_tids.front().first);
+                    continue_packet.Printf("S%2.2x", m_continue_S_tids.front().second);
+                    continue_packet_error = false;
+                }
+            }
+        }
+
+        if (continue_packet_error)
+        {
+            error.SetErrorString ("can't make continue packet for this resume");
+        }
+        else
+        {
+            EventSP event_sp;
+            TimeValue timeout;
+            timeout = TimeValue::Now();
+            timeout.OffsetWithSeconds (5);
+            if (!IS_VALID_LLDB_HOST_THREAD(m_async_thread))
+            {
+                error.SetErrorString ("Trying to resume but the async thread is dead.");
+                if (log)
+                    log->Printf ("ProcessGDBRemote::DoResume: Trying to resume but the async thread is dead.");
+                return error;
+            }
+            
+            m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncContinue, new EventDataBytes (continue_packet.GetData(), continue_packet.GetSize()));
+
+            if (listener.WaitForEvent (&timeout, event_sp) == false)
+            {
+                error.SetErrorString("Resume timed out.");
+                if (log)
+                    log->Printf ("ProcessGDBRemote::DoResume: Resume timed out.");
+            }
+            else if (event_sp->BroadcasterIs (&m_async_broadcaster))
+            {
+                error.SetErrorString ("Broadcast continue, but the async thread was killed before we got an ack back.");
+                if (log)
+                    log->Printf ("ProcessGDBRemote::DoResume: Broadcast continue, but the async thread was killed before we got an ack back.");
+                return error;
+            }
+        }
+    }
+
+    return error;
+}
+
+void
+ProcessGDBRemote::ClearThreadIDList ()
+{
+    Mutex::Locker locker(m_thread_list_real.GetMutex());
+    m_thread_ids.clear();
+}
+
+bool
+ProcessGDBRemote::UpdateThreadIDList ()
+{
+    Mutex::Locker locker(m_thread_list_real.GetMutex());
+    bool sequence_mutex_unavailable = false;
+    m_gdb_comm.GetCurrentThreadIDs (m_thread_ids, sequence_mutex_unavailable);
+    if (sequence_mutex_unavailable)
+    {
+        return false; // We just didn't get the list
+    }
+    return true;
+}
+
+bool
+ProcessGDBRemote::UpdateThreadList (ThreadList &old_thread_list, ThreadList &new_thread_list)
+{
+    // locker will keep a mutex locked until it goes out of scope
+    Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_THREAD));
+    if (log && log->GetMask().Test(GDBR_LOG_VERBOSE))
+        log->Printf ("ProcessGDBRemote::%s (pid = %" PRIu64 ")", __FUNCTION__, GetID());
+    
+    size_t num_thread_ids = m_thread_ids.size();
+    // The "m_thread_ids" thread ID list should always be updated after each stop
+    // reply packet, but in case it isn't, update it here.
+    if (num_thread_ids == 0)
+    {
+        if (!UpdateThreadIDList ())
+            return false;
+        num_thread_ids = m_thread_ids.size();
+    }
+
+    ThreadList old_thread_list_copy(old_thread_list);
+    if (num_thread_ids > 0)
+    {
+        for (size_t i=0; i<num_thread_ids; ++i)
+        {
+            tid_t tid = m_thread_ids[i];
+            ThreadSP thread_sp (old_thread_list_copy.RemoveThreadByProtocolID(tid, false));
+            if (!thread_sp)
+            {
+                thread_sp.reset (new ThreadGDBRemote (*this, tid));
+                if (log && log->GetMask().Test(GDBR_LOG_VERBOSE))
+                    log->Printf(
+                            "ProcessGDBRemote::%s Making new thread: %p for thread ID: 0x%" PRIx64 ".\n",
+                            __FUNCTION__,
+                            thread_sp.get(),
+                            thread_sp->GetID());
+            }
+            else
+            {
+                if (log && log->GetMask().Test(GDBR_LOG_VERBOSE))
+                    log->Printf(
+                           "ProcessGDBRemote::%s Found old thread: %p for thread ID: 0x%" PRIx64 ".\n",
+                           __FUNCTION__,
+                           thread_sp.get(),
+                           thread_sp->GetID());
+            }
+            new_thread_list.AddThread(thread_sp);
+        }
+    }
+    
+    // Whatever that is left in old_thread_list_copy are not
+    // present in new_thread_list. Remove non-existent threads from internal id table.
+    size_t old_num_thread_ids = old_thread_list_copy.GetSize(false);
+    for (size_t i=0; i<old_num_thread_ids; i++)
+    {
+        ThreadSP old_thread_sp(old_thread_list_copy.GetThreadAtIndex (i, false));
+        if (old_thread_sp)
+        {
+            lldb::tid_t old_thread_id = old_thread_sp->GetProtocolID();
+            m_thread_id_to_index_id_map.erase(old_thread_id);
+        }
+    }
+    
+    return true;
+}
+
+
+StateType
+ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet)
+{
+    stop_packet.SetFilePos (0);
+    const char stop_type = stop_packet.GetChar();
+    switch (stop_type)
+    {
+    case 'T':
+    case 'S':
+        {
+            // 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
+                if (GetID() == LLDB_INVALID_PROCESS_ID)
+                {
+                    lldb::pid_t pid = m_gdb_comm.GetCurrentProcessID ();
+                    if (pid != LLDB_INVALID_PROCESS_ID)
+                        SetID (pid);
+                }
+                BuildDynamicRegisterInfo (true);
+            }
+            // Stop with signal and thread info
+            const uint8_t signo = stop_packet.GetHexU8();
+            std::string name;
+            std::string value;
+            std::string thread_name;
+            std::string reason;
+            std::string description;
+            uint32_t exc_type = 0;
+            std::vector<addr_t> exc_data;
+            addr_t thread_dispatch_qaddr = LLDB_INVALID_ADDRESS;
+            ThreadSP thread_sp;
+            ThreadGDBRemote *gdb_thread = NULL;
+
+            while (stop_packet.GetNameColonValue(name, value))
+            {
+                if (name.compare("metype") == 0)
+                {
+                    // exception type in big endian hex
+                    exc_type = Args::StringToUInt32 (value.c_str(), 0, 16);
+                }
+                else if (name.compare("medata") == 0)
+                {
+                    // exception data in big endian hex
+                    exc_data.push_back(Args::StringToUInt64 (value.c_str(), 0, 16));
+                }
+                else if (name.compare("thread") == 0)
+                {
+                    // thread in big endian hex
+                    lldb::tid_t tid = Args::StringToUInt64 (value.c_str(), LLDB_INVALID_THREAD_ID, 16);
+                    // m_thread_list_real does have its own mutex, but we need to
+                    // hold onto the mutex between the call to m_thread_list_real.FindThreadByID(...)
+                    // and the m_thread_list_real.AddThread(...) so it doesn't change on us
+                    Mutex::Locker locker (m_thread_list_real.GetMutex ());
+                    thread_sp = m_thread_list_real.FindThreadByProtocolID(tid, false);
+
+                    if (!thread_sp)
+                    {
+                        // Create the thread if we need to
+                        thread_sp.reset (new ThreadGDBRemote (*this, tid));
+                        Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_THREAD));
+                        if (log && log->GetMask().Test(GDBR_LOG_VERBOSE))
+                            log->Printf ("ProcessGDBRemote::%s Adding new thread: %p for thread ID: 0x%" PRIx64 ".\n",
+                                         __FUNCTION__,
+                                         thread_sp.get(),
+                                         thread_sp->GetID());
+                                         
+                        m_thread_list_real.AddThread(thread_sp);
+                    }
+                    gdb_thread = static_cast<ThreadGDBRemote *> (thread_sp.get());
+
+                }
+                else if (name.compare("threads") == 0)
+                {
+                    Mutex::Locker locker(m_thread_list_real.GetMutex());
+                    m_thread_ids.clear();
+                    // A comma separated list of all threads in the current
+                    // process that includes the thread for this stop reply
+                    // packet
+                    size_t comma_pos;
+                    lldb::tid_t tid;
+                    while ((comma_pos = value.find(',')) != std::string::npos)
+                    {
+                        value[comma_pos] = '\0';
+                        // thread in big endian hex
+                        tid = Args::StringToUInt64 (value.c_str(), LLDB_INVALID_THREAD_ID, 16);
+                        if (tid != LLDB_INVALID_THREAD_ID)
+                            m_thread_ids.push_back (tid);
+                        value.erase(0, comma_pos + 1);
+                            
+                    }
+                    tid = Args::StringToUInt64 (value.c_str(), LLDB_INVALID_THREAD_ID, 16);
+                    if (tid != LLDB_INVALID_THREAD_ID)
+                        m_thread_ids.push_back (tid);
+                }
+                else if (name.compare("hexname") == 0)
+                {
+                    StringExtractor name_extractor;
+                    // Swap "value" over into "name_extractor"
+                    name_extractor.GetStringRef().swap(value);
+                    // Now convert the HEX bytes into a string value
+                    name_extractor.GetHexByteString (value);
+                    thread_name.swap (value);
+                }
+                else if (name.compare("name") == 0)
+                {
+                    thread_name.swap (value);
+                }
+                else if (name.compare("qaddr") == 0)
+                {
+                    thread_dispatch_qaddr = Args::StringToUInt64 (value.c_str(), 0, 16);
+                }
+                else if (name.compare("reason") == 0)
+                {
+                    reason.swap(value);
+                }
+                else if (name.compare("description") == 0)
+                {
+                    StringExtractor desc_extractor;
+                    // Swap "value" over into "name_extractor"
+                    desc_extractor.GetStringRef().swap(value);
+                    // Now convert the HEX bytes into a string value
+                    desc_extractor.GetHexByteString (thread_name);
+                }
+                else if (name.size() == 2 && ::isxdigit(name[0]) && ::isxdigit(name[1]))
+                {
+                    // We have a register number that contains an expedited
+                    // register value. Lets supply this register to our thread
+                    // so it won't have to go and read it.
+                    if (gdb_thread)
+                    {
+                        uint32_t reg = Args::StringToUInt32 (name.c_str(), UINT32_MAX, 16);
+
+                        if (reg != UINT32_MAX)
+                        {
+                            StringExtractor reg_value_extractor;
+                            // Swap "value" over into "reg_value_extractor"
+                            reg_value_extractor.GetStringRef().swap(value);
+                            if (!gdb_thread->PrivateSetRegisterValue (reg, reg_value_extractor))
+                            {
+                                Host::SetCrashDescriptionWithFormat("Setting thread register '%s' (decoded to %u (0x%x)) with value '%s' for stop packet: '%s'", 
+                                                                    name.c_str(), 
+                                                                    reg, 
+                                                                    reg, 
+                                                                    reg_value_extractor.GetStringRef().c_str(), 
+                                                                    stop_packet.GetStringRef().c_str());
+                            }
+                        }
+                    }
+                }
+            }
+
+            if (thread_sp)
+            {
+                // Clear the stop info just in case we don't set it to anything
+                thread_sp->SetStopInfo (StopInfoSP());
+
+                gdb_thread->SetThreadDispatchQAddr (thread_dispatch_qaddr);
+                gdb_thread->SetName (thread_name.empty() ? NULL : thread_name.c_str());
+                if (exc_type != 0)
+                {
+                    const size_t exc_data_size = exc_data.size();
+
+                    thread_sp->SetStopInfo (StopInfoMachException::CreateStopReasonWithMachException (*thread_sp,
+                                                                                                      exc_type,
+                                                                                                      exc_data_size,
+                                                                                                      exc_data_size >= 1 ? exc_data[0] : 0,
+                                                                                                      exc_data_size >= 2 ? exc_data[1] : 0,
+                                                                                                      exc_data_size >= 3 ? exc_data[2] : 0));
+                }
+                else
+                {
+                    bool handled = false;
+                    bool did_exec = false;
+                    if (!reason.empty())
+                    {
+                        if (reason.compare("trace") == 0)
+                        {
+                            thread_sp->SetStopInfo (StopInfo::CreateStopReasonToTrace (*thread_sp));
+                            handled = true;
+                        }
+                        else if (reason.compare("breakpoint") == 0)
+                        {
+                            addr_t pc = thread_sp->GetRegisterContext()->GetPC();
+                            lldb::BreakpointSiteSP bp_site_sp = thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress(pc);
+                            if (bp_site_sp)
+                            {
+                                // If the breakpoint is for this thread, then we'll report the hit, but if it is for another thread,
+                                // we can just report no reason.  We don't need to worry about stepping over the breakpoint here, that
+                                // will be taken care of when the thread resumes and notices that there's a breakpoint under the pc.
+                                handled = true;
+                                if (bp_site_sp->ValidForThisThread (thread_sp.get()))
+                                {
+                                    thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID (*thread_sp, bp_site_sp->GetID()));
+                                }
+                                else
+                                {
+                                    StopInfoSP invalid_stop_info_sp;
+                                    thread_sp->SetStopInfo (invalid_stop_info_sp);
+                                }
+                            }
+                            
+                        }
+                        else if (reason.compare("trap") == 0)
+                        {
+                            // Let the trap just use the standard signal stop reason below...
+                        }
+                        else if (reason.compare("watchpoint") == 0)
+                        {
+                            break_id_t watch_id = LLDB_INVALID_WATCH_ID;
+                            // TODO: locate the watchpoint somehow...
+                            thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithWatchpointID (*thread_sp, watch_id));
+                            handled = true;
+                        }
+                        else if (reason.compare("exception") == 0)
+                        {
+                            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 && did_exec == false)
+                    {
+                        if (signo == SIGTRAP)
+                        {
+                            // Currently we are going to assume SIGTRAP means we are either
+                            // hitting a breakpoint or hardware single stepping. 
+                            handled = true;
+                            addr_t pc = thread_sp->GetRegisterContext()->GetPC();
+                            lldb::BreakpointSiteSP bp_site_sp = thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress(pc);
+                            
+                            if (bp_site_sp)
+                            {
+                                // If the breakpoint is for this thread, then we'll report the hit, but if it is for another thread,
+                                // we can just report no reason.  We don't need to worry about stepping over the breakpoint here, that
+                                // will be taken care of when the thread resumes and notices that there's a breakpoint under the pc.
+                                if (bp_site_sp->ValidForThisThread (thread_sp.get()))
+                                {
+                                    thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID (*thread_sp, bp_site_sp->GetID()));
+                                }
+                                else
+                                {
+                                    StopInfoSP invalid_stop_info_sp;
+                                    thread_sp->SetStopInfo (invalid_stop_info_sp);
+                                }
+                            }
+                            else
+                            {
+                                // If we were stepping then assume the stop was the result of the trace.  If we were
+                                // not stepping then report the SIGTRAP.
+                                // FIXME: We are still missing the case where we single step over a trap instruction.
+                                if (thread_sp->GetTemporaryResumeState() == eStateStepping)
+                                    thread_sp->SetStopInfo (StopInfo::CreateStopReasonToTrace (*thread_sp));
+                                else
+                                    thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithSignal(*thread_sp, signo));
+                            }
+                        }
+                        if (!handled)
+                            thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithSignal (*thread_sp, signo));
+                    }
+                    
+                    if (!description.empty())
+                    {
+                        lldb::StopInfoSP stop_info_sp (thread_sp->GetStopInfo ());
+                        if (stop_info_sp)
+                        {
+                            stop_info_sp->SetDescription (description.c_str());
+                        }
+                        else
+                        {
+                            thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithException (*thread_sp, description.c_str()));
+                        }
+                    }
+                }
+            }
+            return eStateStopped;
+        }
+        break;
+
+    case 'W':
+        // process exited
+        return eStateExited;
+
+    default:
+        break;
+    }
+    return eStateInvalid;
+}
+
+void
+ProcessGDBRemote::RefreshStateAfterStop ()
+{
+    Mutex::Locker locker(m_thread_list_real.GetMutex());
+    m_thread_ids.clear();
+    // Set the thread stop info. It might have a "threads" key whose value is
+    // a list of all thread IDs in the current process, so m_thread_ids might
+    // get set.
+    SetThreadStopInfo (m_last_stop_packet);
+    // Check to see if SetThreadStopInfo() filled in m_thread_ids?
+    if (m_thread_ids.empty())
+    {
+        // No, we need to fetch the thread list manually
+        UpdateThreadIDList();
+    }
+
+    // Let all threads recover from stopping and do any clean up based
+    // on the previous thread state (if any).
+    m_thread_list_real.RefreshStateAfterStop();
+    
+}
+
+Error
+ProcessGDBRemote::DoHalt (bool &caused_stop)
+{
+    Error error;
+
+    bool timed_out = false;
+    Mutex::Locker locker;
+    
+    if (m_public_state.GetValue() == eStateAttaching)
+    {
+        // We are being asked to halt during an attach. We need to just close
+        // our file handle and debugserver will go away, and we can be done...
+        m_gdb_comm.Disconnect();
+    }
+    else
+    {
+        if (!m_gdb_comm.SendInterrupt (locker, 2, timed_out))
+        {
+            if (timed_out)
+                error.SetErrorString("timed out sending interrupt packet");
+            else
+                error.SetErrorString("unknown error sending interrupt packet");
+        }
+        
+        caused_stop = m_gdb_comm.GetInterruptWasSent ();
+    }
+    return error;
+}
+
+Error
+ProcessGDBRemote::DoDetach(bool keep_stopped)
+{
+    Error error;
+    Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
+    if (log)
+        log->Printf ("ProcessGDBRemote::DoDetach(keep_stopped: %i)", keep_stopped);
+ 
+    DisableAllBreakpointSites ();
+
+    m_thread_list.DiscardThreadPlans();
+
+    error = m_gdb_comm.Detach (keep_stopped);
+    if (log)
+    {
+        if (error.Success())
+            log->PutCString ("ProcessGDBRemote::DoDetach() detach packet sent successfully");
+        else
+            log->Printf ("ProcessGDBRemote::DoDetach() detach packet send failed: %s", error.AsCString() ? error.AsCString() : "<unknown error>");
+    }
+    
+    if (!error.Success())
+        return error;
+
+    // Sleep for one second to let the process get all detached...
+    StopAsyncThread ();
+
+    SetPrivateState (eStateDetached);
+    ResumePrivateStateThread();
+
+    //KillDebugserverProcess ();
+    return error;
+}
+
+
+Error
+ProcessGDBRemote::DoDestroy ()
+{
+    Error error;
+    Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
+    if (log)
+        log->Printf ("ProcessGDBRemote::DoDestroy()");
+
+    // There is a bug in older iOS debugservers where they don't shut down the process
+    // they are debugging properly.  If the process is sitting at a breakpoint or an exception,
+    // this can cause problems with restarting.  So we check to see if any of our threads are stopped
+    // at a breakpoint, and if so we remove all the breakpoints, resume the process, and THEN
+    // destroy it again.
+    //
+    // Note, we don't have a good way to test the version of debugserver, but I happen to know that
+    // the set of all the iOS debugservers which don't support GetThreadSuffixSupported() and that of
+    // the debugservers with this bug are equal.  There really should be a better way to test this!
+    //
+    // We also use m_destroy_tried_resuming to make sure we only do this once, if we resume and then halt and
+    // get called here to destroy again and we're still at a breakpoint or exception, then we should
+    // just do the straight-forward kill.
+    //
+    // And of course, if we weren't able to stop the process by the time we get here, it isn't
+    // necessary (or helpful) to do any of this.
+
+    if (!m_gdb_comm.GetThreadSuffixSupported() && m_public_state.GetValue() != eStateRunning)
+    {
+        PlatformSP platform_sp = GetTarget().GetPlatform();
+        
+        // FIXME: These should be ConstStrings so we aren't doing strcmp'ing.
+        if (platform_sp
+            && platform_sp->GetName()
+            && platform_sp->GetName() == PlatformRemoteiOS::GetPluginNameStatic())
+        {
+            if (m_destroy_tried_resuming)
+            {
+                if (log)
+                    log->PutCString ("ProcessGDBRemote::DoDestroy()Tried resuming to destroy once already, not doing it again.");
+            }
+            else
+            {            
+                // At present, the plans are discarded and the breakpoints disabled Process::Destroy,
+                // but we really need it to happen here and it doesn't matter if we do it twice.
+                m_thread_list.DiscardThreadPlans();
+                DisableAllBreakpointSites();
+                
+                bool stop_looks_like_crash = false;
+                ThreadList &threads = GetThreadList();
+                
+                {
+                    Mutex::Locker locker(threads.GetMutex());
+                    
+                    size_t num_threads = threads.GetSize();
+                    for (size_t i = 0; i < num_threads; i++)
+                    {
+                        ThreadSP thread_sp = threads.GetThreadAtIndex(i);
+                        StopInfoSP stop_info_sp = thread_sp->GetPrivateStopInfo();
+                        StopReason reason = eStopReasonInvalid;
+                        if (stop_info_sp)
+                            reason = stop_info_sp->GetStopReason();
+                        if (reason == eStopReasonBreakpoint
+                            || reason == eStopReasonException)
+                        {
+                            if (log)
+                                log->Printf ("ProcessGDBRemote::DoDestroy() - thread: 0x%4.4" PRIx64 " stopped with reason: %s.",
+                                             thread_sp->GetProtocolID(),
+                                             stop_info_sp->GetDescription());
+                            stop_looks_like_crash = true;
+                            break;
+                        }
+                    }
+                }
+                
+                if (stop_looks_like_crash)
+                {
+                    if (log)
+                        log->PutCString ("ProcessGDBRemote::DoDestroy() - Stopped at a breakpoint, continue and then kill.");
+                    m_destroy_tried_resuming = true;
+                    
+                    // If we are going to run again before killing, it would be good to suspend all the threads 
+                    // before resuming so they won't get into more trouble.  Sadly, for the threads stopped with
+                    // the breakpoint or exception, the exception doesn't get cleared if it is suspended, so we do
+                    // have to run the risk of letting those threads proceed a bit.
+    
+                    {
+                        Mutex::Locker locker(threads.GetMutex());
+                        
+                        size_t num_threads = threads.GetSize();
+                        for (size_t i = 0; i < num_threads; i++)
+                        {
+                            ThreadSP thread_sp = threads.GetThreadAtIndex(i);
+                            StopInfoSP stop_info_sp = thread_sp->GetPrivateStopInfo();
+                            StopReason reason = eStopReasonInvalid;
+                            if (stop_info_sp)
+                                reason = stop_info_sp->GetStopReason();
+                            if (reason != eStopReasonBreakpoint
+                                && reason != eStopReasonException)
+                            {
+                                if (log)
+                                    log->Printf ("ProcessGDBRemote::DoDestroy() - Suspending thread: 0x%4.4" PRIx64 " before running.",
+                                                 thread_sp->GetProtocolID());
+                                thread_sp->SetResumeState(eStateSuspended);
+                            }
+                        }
+                    }
+                    Resume ();
+                    return Destroy();
+                }
+            }
+        }
+    }
+    
+    // Interrupt if our inferior is running...
+    int exit_status = SIGABRT;
+    std::string exit_string;
+
+    if (m_gdb_comm.IsConnected())
+    {
+        if (m_public_state.GetValue() != eStateAttaching)
+        {
+
+            StringExtractorGDBRemote response;
+            bool send_async = true;
+            const uint32_t old_packet_timeout = m_gdb_comm.SetPacketTimeout (3);
+
+            if (m_gdb_comm.SendPacketAndWaitForResponse("k", 1, response, send_async))
+            {
+                char packet_cmd = response.GetChar(0);
+
+                if (packet_cmd == 'W' || packet_cmd == 'X')
+                {
+                    SetLastStopPacket (response);
+                    ClearThreadIDList ();
+                    exit_status = response.GetHexU8();
+                }
+                else
+                {
+                    if (log)
+                        log->Printf ("ProcessGDBRemote::DoDestroy - got unexpected response to k packet: %s", response.GetStringRef().c_str());
+                    exit_string.assign("got unexpected response to k packet: ");
+                    exit_string.append(response.GetStringRef());
+                }
+            }
+            else
+            {
+                if (log)
+                    log->Printf ("ProcessGDBRemote::DoDestroy - failed to send k packet");
+                exit_string.assign("failed to send the k packet");
+            }
+
+            m_gdb_comm.SetPacketTimeout(old_packet_timeout);
+        }
+        else
+        {
+            if (log)
+                log->Printf ("ProcessGDBRemote::DoDestroy - failed to send k packet");
+            exit_string.assign ("killed or interrupted while attaching.");
+        }
+    }
+    else
+    {
+        // If we missed setting the exit status on the way out, do it here.
+        // NB set exit status can be called multiple times, the first one sets the status.
+        exit_string.assign("destroying when not connected to debugserver");
+    }
+
+    SetExitStatus(exit_status, exit_string.c_str());
+
+    StopAsyncThread ();
+    KillDebugserverProcess ();
+    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
+//------------------------------------------------------------------
+
+bool
+ProcessGDBRemote::IsAlive ()
+{
+    return m_gdb_comm.IsConnected() && m_private_state.GetValue() != eStateExited;
+}
+
+addr_t
+ProcessGDBRemote::GetImageInfoAddress()
+{
+    return m_gdb_comm.GetShlibInfoAddr();
+}
+
+//------------------------------------------------------------------
+// Process Memory
+//------------------------------------------------------------------
+size_t
+ProcessGDBRemote::DoReadMemory (addr_t addr, void *buf, size_t size, Error &error)
+{
+    if (size > m_max_memory_size)
+    {
+        // Keep memory read sizes down to a sane limit. This function will be
+        // called multiple times in order to complete the task by 
+        // lldb_private::Process so it is ok to do this.
+        size = m_max_memory_size;
+    }
+
+    char packet[64];
+    const int packet_len = ::snprintf (packet, sizeof(packet), "m%" PRIx64 ",%" PRIx64, (uint64_t)addr, (uint64_t)size);
+    assert (packet_len + 1 < (int)sizeof(packet));
+    StringExtractorGDBRemote response;
+    if (m_gdb_comm.SendPacketAndWaitForResponse(packet, packet_len, response, true))
+    {
+        if (response.IsNormalResponse())
+        {
+            error.Clear();
+            return response.GetHexBytes(buf, size, '\xdd');
+        }
+        else if (response.IsErrorResponse())
+            error.SetErrorStringWithFormat("memory read failed for 0x%" PRIx64, addr);
+        else if (response.IsUnsupportedResponse())
+            error.SetErrorStringWithFormat("GDB server does not support reading memory");
+        else
+            error.SetErrorStringWithFormat("unexpected response to GDB server memory read packet '%s': '%s'", packet, response.GetStringRef().c_str());
+    }
+    else
+    {
+        error.SetErrorStringWithFormat("failed to send packet: '%s'", packet);
+    }
+    return 0;
+}
+
+size_t
+ProcessGDBRemote::DoWriteMemory (addr_t addr, const void *buf, size_t size, Error &error)
+{
+    if (size > m_max_memory_size)
+    {
+        // Keep memory read sizes down to a sane limit. This function will be
+        // called multiple times in order to complete the task by 
+        // lldb_private::Process so it is ok to do this.
+        size = m_max_memory_size;
+    }
+
+    StreamString packet;
+    packet.Printf("M%" PRIx64 ",%" PRIx64 ":", addr, (uint64_t)size);
+    packet.PutBytesAsRawHex8(buf, size, lldb::endian::InlHostByteOrder(), lldb::endian::InlHostByteOrder());
+    StringExtractorGDBRemote response;
+    if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetData(), packet.GetSize(), response, true))
+    {
+        if (response.IsOKResponse())
+        {
+            error.Clear();
+            return size;
+        }
+        else if (response.IsErrorResponse())
+            error.SetErrorStringWithFormat("memory write failed for 0x%" PRIx64, addr);
+        else if (response.IsUnsupportedResponse())
+            error.SetErrorStringWithFormat("GDB server does not support writing memory");
+        else
+            error.SetErrorStringWithFormat("unexpected response to GDB server memory write packet '%s': '%s'", packet.GetString().c_str(), response.GetStringRef().c_str());
+    }
+    else
+    {
+        error.SetErrorStringWithFormat("failed to send packet: '%s'", packet.GetString().c_str());
+    }
+    return 0;
+}
+
+lldb::addr_t
+ProcessGDBRemote::DoAllocateMemory (size_t size, uint32_t permissions, Error &error)
+{
+    addr_t allocated_addr = LLDB_INVALID_ADDRESS;
+    
+    LazyBool supported = m_gdb_comm.SupportsAllocDeallocMemory();
+    switch (supported)
+    {
+        case eLazyBoolCalculate:
+        case eLazyBoolYes:
+            allocated_addr = m_gdb_comm.AllocateMemory (size, permissions);
+            if (allocated_addr != LLDB_INVALID_ADDRESS || supported == eLazyBoolYes)
+                return allocated_addr;
+
+        case eLazyBoolNo:
+            // Call mmap() to create memory in the inferior..
+            unsigned prot = 0;
+            if (permissions & lldb::ePermissionsReadable)
+                prot |= eMmapProtRead;
+            if (permissions & lldb::ePermissionsWritable)
+                prot |= eMmapProtWrite;
+            if (permissions & lldb::ePermissionsExecutable)
+                prot |= eMmapProtExec;
+
+            if (InferiorCallMmap(this, allocated_addr, 0, size, prot,
+                                 eMmapFlagsAnon | eMmapFlagsPrivate, -1, 0))
+                m_addr_to_mmap_size[allocated_addr] = size;
+            else
+                allocated_addr = LLDB_INVALID_ADDRESS;
+            break;
+    }
+    
+    if (allocated_addr == LLDB_INVALID_ADDRESS)
+        error.SetErrorStringWithFormat("unable to allocate %" PRIu64 " bytes of memory with permissions %s", (uint64_t)size, GetPermissionsAsCString (permissions));
+    else
+        error.Clear();
+    return allocated_addr;
+}
+
+Error
+ProcessGDBRemote::GetMemoryRegionInfo (addr_t load_addr, 
+                                       MemoryRegionInfo &region_info)
+{
+    
+    Error error (m_gdb_comm.GetMemoryRegionInfo (load_addr, region_info));
+    return error;
+}
+
+Error
+ProcessGDBRemote::GetWatchpointSupportInfo (uint32_t &num)
+{
+    
+    Error error (m_gdb_comm.GetWatchpointSupportInfo (num));
+    return error;
+}
+
+Error
+ProcessGDBRemote::GetWatchpointSupportInfo (uint32_t &num, bool& after)
+{
+    Error error (m_gdb_comm.GetWatchpointSupportInfo (num, after));
+    return error;
+}
+
+Error
+ProcessGDBRemote::DoDeallocateMemory (lldb::addr_t addr)
+{
+    Error error; 
+    LazyBool supported = m_gdb_comm.SupportsAllocDeallocMemory();
+
+    switch (supported)
+    {
+        case eLazyBoolCalculate:
+            // We should never be deallocating memory without allocating memory 
+            // first so we should never get eLazyBoolCalculate
+            error.SetErrorString ("tried to deallocate memory without ever allocating memory");
+            break;
+
+        case eLazyBoolYes:
+            if (!m_gdb_comm.DeallocateMemory (addr))
+                error.SetErrorStringWithFormat("unable to deallocate memory at 0x%" PRIx64, addr);
+            break;
+            
+        case eLazyBoolNo:
+            // Call munmap() to deallocate memory in the inferior..
+            {
+                MMapMap::iterator pos = m_addr_to_mmap_size.find(addr);
+                if (pos != m_addr_to_mmap_size.end() &&
+                    InferiorCallMunmap(this, addr, pos->second))
+                    m_addr_to_mmap_size.erase (pos);
+                else
+                    error.SetErrorStringWithFormat("unable to deallocate memory at 0x%" PRIx64, addr);
+            }
+            break;
+    }
+
+    return error;
+}
+
+
+//------------------------------------------------------------------
+// Process STDIO
+//------------------------------------------------------------------
+size_t
+ProcessGDBRemote::PutSTDIN (const char *src, size_t src_len, Error &error)
+{
+    if (m_stdio_communication.IsConnected())
+    {
+        ConnectionStatus status;
+        m_stdio_communication.Write(src, src_len, status, NULL);
+    }
+    return 0;
+}
+
+Error
+ProcessGDBRemote::EnableBreakpointSite (BreakpointSite *bp_site)
+{
+    Error error;
+    assert (bp_site != NULL);
+
+    Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_BREAKPOINTS));
+    user_id_t site_id = bp_site->GetID();
+    const addr_t addr = bp_site->GetLoadAddress();
+    if (log)
+        log->Printf ("ProcessGDBRemote::EnableBreakpointSite (size_id = %" PRIu64 ") address = 0x%" PRIx64, site_id, (uint64_t)addr);
+
+    if (bp_site->IsEnabled())
+    {
+        if (log)
+            log->Printf ("ProcessGDBRemote::EnableBreakpointSite (size_id = %" PRIu64 ") address = 0x%" PRIx64 " -- SUCCESS (already enabled)", site_id, (uint64_t)addr);
+        return error;
+    }
+    else
+    {
+        const size_t bp_op_size = GetSoftwareBreakpointTrapOpcode (bp_site);
+
+        if (bp_site->HardwarePreferred())
+        {
+            // Try and set hardware breakpoint, and if that fails, fall through
+            // and set a software breakpoint?
+            if (m_gdb_comm.SupportsGDBStoppointPacket (eBreakpointHardware))
+            {
+                if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointHardware, true, addr, bp_op_size) == 0)
+                {
+                    bp_site->SetEnabled(true);
+                    bp_site->SetType (BreakpointSite::eHardware);
+                    return error;
+                }
+            }
+        }
+
+        if (m_gdb_comm.SupportsGDBStoppointPacket (eBreakpointSoftware))
+        {
+            if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointSoftware, true, addr, bp_op_size) == 0)
+            {
+                bp_site->SetEnabled(true);
+                bp_site->SetType (BreakpointSite::eExternal);
+                return error;
+            }
+        }
+
+        return EnableSoftwareBreakpoint (bp_site);
+    }
+
+    if (log)
+    {
+        const char *err_string = error.AsCString();
+        log->Printf ("ProcessGDBRemote::EnableBreakpointSite () error for breakpoint at 0x%8.8" PRIx64 ": %s",
+                     bp_site->GetLoadAddress(),
+                     err_string ? err_string : "NULL");
+    }
+    // We shouldn't reach here on a successful breakpoint enable...
+    if (error.Success())
+        error.SetErrorToGenericError();
+    return error;
+}
+
+Error
+ProcessGDBRemote::DisableBreakpointSite (BreakpointSite *bp_site)
+{
+    Error error;
+    assert (bp_site != NULL);
+    addr_t addr = bp_site->GetLoadAddress();
+    user_id_t site_id = bp_site->GetID();
+    Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_BREAKPOINTS));
+    if (log)
+        log->Printf ("ProcessGDBRemote::DisableBreakpointSite (site_id = %" PRIu64 ") addr = 0x%8.8" PRIx64, site_id, (uint64_t)addr);
+
+    if (bp_site->IsEnabled())
+    {
+        const size_t bp_op_size = GetSoftwareBreakpointTrapOpcode (bp_site);
+
+        BreakpointSite::Type bp_type = bp_site->GetType();
+        switch (bp_type)
+        {
+        case BreakpointSite::eSoftware:
+            error = DisableSoftwareBreakpoint (bp_site);
+            break;
+
+        case BreakpointSite::eHardware:
+            if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointSoftware, false, addr, bp_op_size))
+                error.SetErrorToGenericError();
+            break;
+
+        case BreakpointSite::eExternal:
+            if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointSoftware, false, addr, bp_op_size))
+                error.SetErrorToGenericError();
+            break;
+        }
+        if (error.Success())
+            bp_site->SetEnabled(false);
+    }
+    else
+    {
+        if (log)
+            log->Printf ("ProcessGDBRemote::DisableBreakpointSite (site_id = %" PRIu64 ") addr = 0x%8.8" PRIx64 " -- SUCCESS (already disabled)", site_id, (uint64_t)addr);
+        return error;
+    }
+
+    if (error.Success())
+        error.SetErrorToGenericError();
+    return error;
+}
+
+// Pre-requisite: wp != NULL.
+static GDBStoppointType
+GetGDBStoppointType (Watchpoint *wp)
+{
+    assert(wp);
+    bool watch_read = wp->WatchpointRead();
+    bool watch_write = wp->WatchpointWrite();
+
+    // watch_read and watch_write cannot both be false.
+    assert(watch_read || watch_write);
+    if (watch_read && watch_write)
+        return eWatchpointReadWrite;
+    else if (watch_read)
+        return eWatchpointRead;
+    else // Must be watch_write, then.
+        return eWatchpointWrite;
+}
+
+Error
+ProcessGDBRemote::EnableWatchpoint (Watchpoint *wp, bool notify)
+{
+    Error error;
+    if (wp)
+    {
+        user_id_t watchID = wp->GetID();
+        addr_t addr = wp->GetLoadAddress();
+        Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_WATCHPOINTS));
+        if (log)
+            log->Printf ("ProcessGDBRemote::EnableWatchpoint(watchID = %" PRIu64 ")", watchID);
+        if (wp->IsEnabled())
+        {
+            if (log)
+                log->Printf("ProcessGDBRemote::EnableWatchpoint(watchID = %" PRIu64 ") addr = 0x%8.8" PRIx64 ": watchpoint already enabled.", watchID, (uint64_t)addr);
+            return error;
+        }
+
+        GDBStoppointType type = GetGDBStoppointType(wp);
+        // Pass down an appropriate z/Z packet...
+        if (m_gdb_comm.SupportsGDBStoppointPacket (type))
+        {
+            if (m_gdb_comm.SendGDBStoppointTypePacket(type, true, addr, wp->GetByteSize()) == 0)
+            {
+                wp->SetEnabled(true, notify);
+                return error;
+            }
+            else
+                error.SetErrorString("sending gdb watchpoint packet failed");
+        }
+        else
+            error.SetErrorString("watchpoints not supported");
+    }
+    else
+    {
+        error.SetErrorString("Watchpoint argument was NULL.");
+    }
+    if (error.Success())
+        error.SetErrorToGenericError();
+    return error;
+}
+
+Error
+ProcessGDBRemote::DisableWatchpoint (Watchpoint *wp, bool notify)
+{
+    Error error;
+    if (wp)
+    {
+        user_id_t watchID = wp->GetID();
+
+        Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_WATCHPOINTS));
+
+        addr_t addr = wp->GetLoadAddress();
+
+        if (log)
+            log->Printf ("ProcessGDBRemote::DisableWatchpoint (watchID = %" PRIu64 ") addr = 0x%8.8" PRIx64, watchID, (uint64_t)addr);
+
+        if (!wp->IsEnabled())
+        {
+            if (log)
+                log->Printf ("ProcessGDBRemote::DisableWatchpoint (watchID = %" PRIu64 ") addr = 0x%8.8" PRIx64 " -- SUCCESS (already disabled)", watchID, (uint64_t)addr);
+            // See also 'class WatchpointSentry' within StopInfo.cpp.
+            // This disabling attempt might come from the user-supplied actions, we'll route it in order for
+            // the watchpoint object to intelligently process this action.
+            wp->SetEnabled(false, notify);
+            return error;
+        }
+        
+        if (wp->IsHardware())
+        {
+            GDBStoppointType type = GetGDBStoppointType(wp);
+            // Pass down an appropriate z/Z packet...
+            if (m_gdb_comm.SendGDBStoppointTypePacket(type, false, addr, wp->GetByteSize()) == 0)
+            {
+                wp->SetEnabled(false, notify);
+                return error;
+            }
+            else
+                error.SetErrorString("sending gdb watchpoint packet failed"); 
+        }
+        // TODO: clear software watchpoints if we implement them
+    }
+    else
+    {
+        error.SetErrorString("Watchpoint argument was NULL.");
+    }
+    if (error.Success())
+        error.SetErrorToGenericError();
+    return error;
+}
+
+void
+ProcessGDBRemote::Clear()
+{
+    m_flags = 0;
+    m_thread_list_real.Clear();
+    m_thread_list.Clear();
+}
+
+Error
+ProcessGDBRemote::DoSignal (int signo)
+{
+    Error error;
+    Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
+    if (log)
+        log->Printf ("ProcessGDBRemote::DoSignal (signal = %d)", signo);
+
+    if (!m_gdb_comm.SendAsyncSignal (signo))
+        error.SetErrorStringWithFormat("failed to send signal %i", signo);
+    return error;
+}
+
+Error
+ProcessGDBRemote::StartDebugserverProcess (const char *debugserver_url)
+{
+    ProcessLaunchInfo launch_info;
+    return StartDebugserverProcess(debugserver_url, launch_info);
+}
+
+Error
+ProcessGDBRemote::StartDebugserverProcess (const char *debugserver_url, const ProcessInfo &process_info)    // The connection string to use in the spawned debugserver ("localhost:1234" or "/dev/tty...")
+{
+    Error error;
+    if (m_debugserver_pid == LLDB_INVALID_PROCESS_ID)
+    {
+        // If we locate debugserver, keep that located version around
+        static FileSpec g_debugserver_file_spec;
+
+        ProcessLaunchInfo debugserver_launch_info;
+        char debugserver_path[PATH_MAX];
+        FileSpec &debugserver_file_spec = debugserver_launch_info.GetExecutableFile();
+
+        // Always check to see if we have an environment override for the path
+        // to the debugserver to use and use it if we do.
+        const char *env_debugserver_path = getenv("LLDB_DEBUGSERVER_PATH");
+        if (env_debugserver_path)
+            debugserver_file_spec.SetFile (env_debugserver_path, false);
+        else
+            debugserver_file_spec = g_debugserver_file_spec;
+        bool debugserver_exists = debugserver_file_spec.Exists();
+        if (!debugserver_exists)
+        {
+            // The debugserver binary is in the LLDB.framework/Resources
+            // directory. 
+            if (Host::GetLLDBPath (ePathTypeSupportExecutableDir, debugserver_file_spec))
+            {
+                debugserver_file_spec.GetFilename().SetCString(DEBUGSERVER_BASENAME);
+                debugserver_exists = debugserver_file_spec.Exists();
+                if (debugserver_exists)
+                {
+                    g_debugserver_file_spec = debugserver_file_spec;
+                }
+                else
+                {
+                    g_debugserver_file_spec.Clear();
+                    debugserver_file_spec.Clear();
+                }
+            }
+        }
+
+        if (debugserver_exists)
+        {
+            debugserver_file_spec.GetPath (debugserver_path, sizeof(debugserver_path));
+
+            m_stdio_communication.Clear();
+
+            Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
+
+            Args &debugserver_args = debugserver_launch_info.GetArguments();
+            char arg_cstr[PATH_MAX];
+
+            // Start args with "debugserver /file/path -r --"
+            debugserver_args.AppendArgument(debugserver_path);
+            debugserver_args.AppendArgument(debugserver_url);
+            // use native registers, not the GDB registers
+            debugserver_args.AppendArgument("--native-regs");   
+            // make debugserver run in its own session so signals generated by 
+            // special terminal key sequences (^C) don't affect debugserver
+            debugserver_args.AppendArgument("--setsid");
+
+            const char *env_debugserver_log_file = getenv("LLDB_DEBUGSERVER_LOG_FILE");
+            if (env_debugserver_log_file)
+            {
+                ::snprintf (arg_cstr, sizeof(arg_cstr), "--log-file=%s", env_debugserver_log_file);
+                debugserver_args.AppendArgument(arg_cstr);
+            }
+
+            const char *env_debugserver_log_flags = getenv("LLDB_DEBUGSERVER_LOG_FLAGS");
+            if (env_debugserver_log_flags)
+            {
+                ::snprintf (arg_cstr, sizeof(arg_cstr), "--log-flags=%s", env_debugserver_log_flags);
+                debugserver_args.AppendArgument(arg_cstr);
+            }
+//            debugserver_args.AppendArgument("--log-file=/tmp/debugserver.txt");
+//            debugserver_args.AppendArgument("--log-flags=0x802e0e");
+
+            // We currently send down all arguments, attach pids, or attach 
+            // process names in dedicated GDB server packets, so we don't need
+            // to pass them as arguments. This is currently because of all the
+            // things we need to setup prior to launching: the environment,
+            // current working dir, file actions, etc.
+#if 0
+            // Now append the program arguments
+            if (inferior_argv)
+            {
+                // Terminate the debugserver args so we can now append the inferior args
+                debugserver_args.AppendArgument("--");
+
+                for (int i = 0; inferior_argv[i] != NULL; ++i)
+                    debugserver_args.AppendArgument (inferior_argv[i]);
+            }
+            else if (attach_pid != LLDB_INVALID_PROCESS_ID)
+            {
+                ::snprintf (arg_cstr, sizeof(arg_cstr), "--attach=%u", attach_pid);
+                debugserver_args.AppendArgument (arg_cstr);
+            }
+            else if (attach_name && attach_name[0])
+            {
+                if (wait_for_launch)
+                    debugserver_args.AppendArgument ("--waitfor");
+                else
+                    debugserver_args.AppendArgument ("--attach");
+                debugserver_args.AppendArgument (attach_name);
+            }
+#endif
+            
+            ProcessLaunchInfo::FileAction file_action;
+            
+            // Close STDIN, STDOUT and STDERR. We might need to redirect them
+            // to "/dev/null" if we run into any problems.
+            file_action.Close (STDIN_FILENO);
+            debugserver_launch_info.AppendFileAction (file_action);
+            file_action.Close (STDOUT_FILENO);
+            debugserver_launch_info.AppendFileAction (file_action);
+            file_action.Close (STDERR_FILENO);
+            debugserver_launch_info.AppendFileAction (file_action);
+
+            if (log)
+            {
+                StreamString strm;
+                debugserver_args.Dump (&strm);
+                log->Printf("%s arguments:\n%s", debugserver_args.GetArgumentAtIndex(0), strm.GetData());
+            }
+
+            debugserver_launch_info.SetMonitorProcessCallback (MonitorDebugserverProcess, this, false);
+            debugserver_launch_info.SetUserID(process_info.GetUserID());
+
+            error = Host::LaunchProcess(debugserver_launch_info);
+
+            if (error.Success ())
+                m_debugserver_pid = debugserver_launch_info.GetProcessID();
+            else
+                m_debugserver_pid = LLDB_INVALID_PROCESS_ID;
+
+            if (error.Fail() || log)
+                error.PutToLog(log, "Host::LaunchProcess (launch_info) => pid=%" PRIu64 ", path='%s'", m_debugserver_pid, debugserver_path);
+        }
+        else
+        {
+            error.SetErrorStringWithFormat ("unable to locate " DEBUGSERVER_BASENAME);
+        }
+
+        if (m_debugserver_pid != LLDB_INVALID_PROCESS_ID)
+            StartAsyncThread ();
+    }
+    return error;
+}
+
+bool
+ProcessGDBRemote::MonitorDebugserverProcess
+(
+    void *callback_baton,
+    lldb::pid_t debugserver_pid,
+    bool exited,        // True if the process did exit
+    int signo,          // Zero for no signal
+    int exit_status     // Exit value of process if signal is zero
+)
+{
+    // The baton is a "ProcessGDBRemote *". Now this class might be gone
+    // and might not exist anymore, so we need to carefully try to get the
+    // target for this process first since we have a race condition when
+    // we are done running between getting the notice that the inferior 
+    // process has died and the debugserver that was debugging this process.
+    // In our test suite, we are also continually running process after
+    // process, so we must be very careful to make sure:
+    // 1 - process object hasn't been deleted already
+    // 2 - that a new process object hasn't been recreated in its place
+
+    // "debugserver_pid" argument passed in is the process ID for
+    // debugserver that we are tracking...
+    Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
+
+    ProcessGDBRemote *process = (ProcessGDBRemote *)callback_baton;
+
+    // Get a shared pointer to the target that has a matching process pointer.
+    // This target could be gone, or the target could already have a new process
+    // object inside of it
+    TargetSP target_sp (Debugger::FindTargetWithProcess(process));
+
+    if (log)
+        log->Printf ("ProcessGDBRemote::MonitorDebugserverProcess (baton=%p, pid=%" PRIu64 ", signo=%i (0x%x), exit_status=%i)", callback_baton, debugserver_pid, signo, signo, exit_status);
+
+    if (target_sp)
+    {
+        // We found a process in a target that matches, but another thread
+        // might be in the process of launching a new process that will
+        // soon replace it, so get a shared pointer to the process so we
+        // can keep it alive.
+        ProcessSP process_sp (target_sp->GetProcessSP());
+        // Now we have a shared pointer to the process that can't go away on us
+        // so we now make sure it was the same as the one passed in, and also make
+        // sure that our previous "process *" didn't get deleted and have a new 
+        // "process *" created in its place with the same pointer. To verify this
+        // we make sure the process has our debugserver process ID. If we pass all
+        // of these tests, then we are sure that this process is the one we were
+        // looking for.
+        if (process_sp && process == process_sp.get() && process->m_debugserver_pid == debugserver_pid)
+        {
+            // Sleep for a half a second to make sure our inferior process has
+            // time to set its exit status before we set it incorrectly when
+            // both the debugserver and the inferior process shut down.
+            usleep (500000);
+            // If our process hasn't yet exited, debugserver might have died.
+            // If the process did exit, the we are reaping it.
+            const StateType state = process->GetState();
+            
+            if (process->m_debugserver_pid != LLDB_INVALID_PROCESS_ID &&
+                state != eStateInvalid &&
+                state != eStateUnloaded &&
+                state != eStateExited &&
+                state != eStateDetached)
+            {
+                char error_str[1024];
+                if (signo)
+                {
+                    const char *signal_cstr = process->GetUnixSignals().GetSignalAsCString (signo);
+                    if (signal_cstr)
+                        ::snprintf (error_str, sizeof (error_str), DEBUGSERVER_BASENAME " died with signal %s", signal_cstr);
+                    else
+                        ::snprintf (error_str, sizeof (error_str), DEBUGSERVER_BASENAME " died with signal %i", signo);
+                }
+                else
+                {
+                    ::snprintf (error_str, sizeof (error_str), DEBUGSERVER_BASENAME " died with an exit status of 0x%8.8x", exit_status);
+                }
+
+                process->SetExitStatus (-1, error_str);
+            }
+            // Debugserver has exited we need to let our ProcessGDBRemote
+            // know that it no longer has a debugserver instance
+            process->m_debugserver_pid = LLDB_INVALID_PROCESS_ID;
+        }
+    }
+    return true;
+}
+
+void
+ProcessGDBRemote::KillDebugserverProcess ()
+{
+    if (m_debugserver_pid != LLDB_INVALID_PROCESS_ID)
+    {
+        ::kill (m_debugserver_pid, SIGINT);
+        m_debugserver_pid = LLDB_INVALID_PROCESS_ID;
+    }
+}
+
+void
+ProcessGDBRemote::Initialize()
+{
+    static bool g_initialized = false;
+
+    if (g_initialized == false)
+    {
+        g_initialized = true;
+        PluginManager::RegisterPlugin (GetPluginNameStatic(),
+                                       GetPluginDescriptionStatic(),
+                                       CreateInstance,
+                                       DebuggerInitialize);
+
+        Log::Callbacks log_callbacks = {
+            ProcessGDBRemoteLog::DisableLog,
+            ProcessGDBRemoteLog::EnableLog,
+            ProcessGDBRemoteLog::ListLogCategories
+        };
+
+        Log::RegisterLogChannel (ProcessGDBRemote::GetPluginNameStatic(), log_callbacks);
+    }
+}
+
+void
+ProcessGDBRemote::DebuggerInitialize (lldb_private::Debugger &debugger)
+{
+    if (!PluginManager::GetSettingForProcessPlugin(debugger, PluginProperties::GetSettingName()))
+    {
+        const bool is_global_setting = true;
+        PluginManager::CreateSettingForProcessPlugin (debugger,
+                                                      GetGlobalPluginProperties()->GetValueProperties(),
+                                                      ConstString ("Properties for the gdb-remote process plug-in."),
+                                                      is_global_setting);
+    }
+}
+
+bool
+ProcessGDBRemote::StartAsyncThread ()
+{
+    Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
+
+    if (log)
+        log->Printf ("ProcessGDBRemote::%s ()", __FUNCTION__);
+    
+    Mutex::Locker start_locker(m_async_thread_state_mutex);
+    if (m_async_thread_state == eAsyncThreadNotStarted)
+    {
+        // Create a thread that watches our internal state and controls which
+        // events make it to clients (into the DCProcess event queue).
+        m_async_thread = Host::ThreadCreate ("<lldb.process.gdb-remote.async>", ProcessGDBRemote::AsyncThread, this, NULL);
+        if (IS_VALID_LLDB_HOST_THREAD(m_async_thread))
+        {
+            m_async_thread_state = eAsyncThreadRunning;
+            return true;
+        }
+        else
+            return false;
+    }
+    else
+    {
+        // Somebody tried to start the async thread while it was either being started or stopped.  If the former, and
+        // it started up successfully, then say all's well.  Otherwise it is an error, since we aren't going to restart it.
+        if (log)
+            log->Printf ("ProcessGDBRemote::%s () - Called when Async thread was in state: %d.", __FUNCTION__, m_async_thread_state);
+        if (m_async_thread_state == eAsyncThreadRunning)
+            return true;
+        else
+            return false;
+    }
+}
+
+void
+ProcessGDBRemote::StopAsyncThread ()
+{
+    Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
+
+    if (log)
+        log->Printf ("ProcessGDBRemote::%s ()", __FUNCTION__);
+
+    Mutex::Locker start_locker(m_async_thread_state_mutex);
+    if (m_async_thread_state == eAsyncThreadRunning)
+    {
+        m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncThreadShouldExit);
+        
+        //  This will shut down the async thread.
+        m_gdb_comm.Disconnect();    // Disconnect from the debug server.
+
+        // Stop the stdio thread
+        if (IS_VALID_LLDB_HOST_THREAD(m_async_thread))
+        {
+            Host::ThreadJoin (m_async_thread, NULL, NULL);
+        }
+        m_async_thread_state = eAsyncThreadDone;
+    }
+    else
+    {
+        if (log)
+            log->Printf ("ProcessGDBRemote::%s () - Called when Async thread was in state: %d.", __FUNCTION__, m_async_thread_state);
+    }
+}
+
+
+void *
+ProcessGDBRemote::AsyncThread (void *arg)
+{
+    ProcessGDBRemote *process = (ProcessGDBRemote*) arg;
+
+    Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
+    if (log)
+        log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") thread starting...", __FUNCTION__, arg, process->GetID());
+
+    Listener listener ("ProcessGDBRemote::AsyncThread");
+    EventSP event_sp;
+    const uint32_t desired_event_mask = eBroadcastBitAsyncContinue |
+                                        eBroadcastBitAsyncThreadShouldExit;
+
+    if (listener.StartListeningForEvents (&process->m_async_broadcaster, desired_event_mask) == desired_event_mask)
+    {
+        listener.StartListeningForEvents (&process->m_gdb_comm, Communication::eBroadcastBitReadThreadDidExit);
+    
+        bool done = false;
+        while (!done)
+        {
+            if (log)
+                log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") listener.WaitForEvent (NULL, event_sp)...", __FUNCTION__, arg, process->GetID());
+            if (listener.WaitForEvent (NULL, event_sp))
+            {
+                const uint32_t event_type = event_sp->GetType();
+                if (event_sp->BroadcasterIs (&process->m_async_broadcaster))
+                {
+                    if (log)
+                        log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") Got an event of type: %d...", __FUNCTION__, arg, process->GetID(), event_type);
+
+                    switch (event_type)
+                    {
+                        case eBroadcastBitAsyncContinue:
+                            {
+                                const EventDataBytes *continue_packet = EventDataBytes::GetEventDataFromEvent(event_sp.get());
+
+                                if (continue_packet)
+                                {
+                                    const char *continue_cstr = (const char *)continue_packet->GetBytes ();
+                                    const size_t continue_cstr_len = continue_packet->GetByteSize ();
+                                    if (log)
+                                        log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") got eBroadcastBitAsyncContinue: %s", __FUNCTION__, arg, process->GetID(), continue_cstr);
+
+                                    if (::strstr (continue_cstr, "vAttach") == NULL)
+                                        process->SetPrivateState(eStateRunning);
+                                    StringExtractorGDBRemote response;
+                                    StateType stop_state = process->GetGDBRemote().SendContinuePacketAndWaitForResponse (process, continue_cstr, continue_cstr_len, response);
+
+                                    // We need to immediately clear the thread ID list so we are sure to get a valid list of threads.
+                                    // The thread ID list might be contained within the "response", or the stop reply packet that
+                                    // caused the stop. So clear it now before we give the stop reply packet to the process
+                                    // using the process->SetLastStopPacket()...
+                                    process->ClearThreadIDList ();
+
+                                    switch (stop_state)
+                                    {
+                                    case eStateStopped:
+                                    case eStateCrashed:
+                                    case eStateSuspended:
+                                        process->SetLastStopPacket (response);
+                                        process->SetPrivateState (stop_state);
+                                        break;
+
+                                    case eStateExited:
+                                        process->SetLastStopPacket (response);
+                                        process->ClearThreadIDList();
+                                        response.SetFilePos(1);
+                                        process->SetExitStatus(response.GetHexU8(), NULL);
+                                        done = true;
+                                        break;
+
+                                    case eStateInvalid:
+                                        process->SetExitStatus(-1, "lost connection");
+                                        break;
+
+                                    default:
+                                        process->SetPrivateState (stop_state);
+                                        break;
+                                    }
+                                }
+                            }
+                            break;
+
+                        case eBroadcastBitAsyncThreadShouldExit:
+                            if (log)
+                                log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") got eBroadcastBitAsyncThreadShouldExit...", __FUNCTION__, arg, process->GetID());
+                            done = true;
+                            break;
+
+                        default:
+                            if (log)
+                                log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") got unknown event 0x%8.8x", __FUNCTION__, arg, process->GetID(), event_type);
+                            done = true;
+                            break;
+                    }
+                }
+                else if (event_sp->BroadcasterIs (&process->m_gdb_comm))
+                {
+                    if (event_type & Communication::eBroadcastBitReadThreadDidExit)
+                    {
+                        process->SetExitStatus (-1, "lost connection");
+                        done = true;
+                    }
+                }
+            }
+            else
+            {
+                if (log)
+                    log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") listener.WaitForEvent (NULL, event_sp) => false", __FUNCTION__, arg, process->GetID());
+                done = true;
+            }
+        }
+    }
+
+    if (log)
+        log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") thread exiting...", __FUNCTION__, arg, process->GetID());
+
+    process->m_async_thread = LLDB_INVALID_HOST_THREAD;
+    return NULL;
+}
+
+const char *
+ProcessGDBRemote::GetDispatchQueueNameForThread
+(
+    addr_t thread_dispatch_qaddr,
+    std::string &dispatch_queue_name
+)
+{
+    dispatch_queue_name.clear();
+    if (thread_dispatch_qaddr != 0 && thread_dispatch_qaddr != LLDB_INVALID_ADDRESS)
+    {
+        // Cache the dispatch_queue_offsets_addr value so we don't always have
+        // to look it up
+        if (m_dispatch_queue_offsets_addr == LLDB_INVALID_ADDRESS)
+        {
+            static ConstString g_dispatch_queue_offsets_symbol_name ("dispatch_queue_offsets");
+            const Symbol *dispatch_queue_offsets_symbol = NULL;
+            ModuleSpec libSystem_module_spec (FileSpec("libSystem.B.dylib", false));
+            ModuleSP module_sp(GetTarget().GetImages().FindFirstModule (libSystem_module_spec));
+            if (module_sp)
+                dispatch_queue_offsets_symbol = module_sp->FindFirstSymbolWithNameAndType (g_dispatch_queue_offsets_symbol_name, eSymbolTypeData);
+            
+            if (dispatch_queue_offsets_symbol == NULL)
+            {
+                ModuleSpec libdispatch_module_spec (FileSpec("libdispatch.dylib", false));
+                module_sp = GetTarget().GetImages().FindFirstModule (libdispatch_module_spec);
+                if (module_sp)
+                    dispatch_queue_offsets_symbol = module_sp->FindFirstSymbolWithNameAndType (g_dispatch_queue_offsets_symbol_name, eSymbolTypeData);
+            }
+            if (dispatch_queue_offsets_symbol)
+                m_dispatch_queue_offsets_addr = dispatch_queue_offsets_symbol->GetAddress().GetLoadAddress(&m_target);
+
+            if (m_dispatch_queue_offsets_addr == LLDB_INVALID_ADDRESS)
+                return NULL;
+        }
+
+        uint8_t memory_buffer[8];
+        DataExtractor data (memory_buffer, 
+                            sizeof(memory_buffer), 
+                            m_target.GetArchitecture().GetByteOrder(), 
+                            m_target.GetArchitecture().GetAddressByteSize());
+
+        // Excerpt from src/queue_private.h
+        struct dispatch_queue_offsets_s
+        {
+            uint16_t dqo_version;
+            uint16_t dqo_label;      // in version 1-3, offset to string; in version 4+, offset to a pointer to a string
+            uint16_t dqo_label_size; // in version 1-3, length of string; in version 4+, size of a (void*) in this process
+        } dispatch_queue_offsets;
+
+
+        Error error;
+        if (ReadMemory (m_dispatch_queue_offsets_addr, memory_buffer, sizeof(dispatch_queue_offsets), error) == sizeof(dispatch_queue_offsets))
+        {
+            lldb::offset_t data_offset = 0;
+            if (data.GetU16(&data_offset, &dispatch_queue_offsets.dqo_version, sizeof(dispatch_queue_offsets)/sizeof(uint16_t)))
+            {
+                if (ReadMemory (thread_dispatch_qaddr, &memory_buffer, data.GetAddressByteSize(), error) == data.GetAddressByteSize())
+                {
+                    data_offset = 0;
+                    lldb::addr_t queue_addr = data.GetAddress(&data_offset);
+                    if (dispatch_queue_offsets.dqo_version >= 4)
+                    {
+                        // libdispatch versions 4+, pointer to dispatch name is in the 
+                        // queue structure.
+                        lldb::addr_t pointer_to_label_address = queue_addr + dispatch_queue_offsets.dqo_label;
+                        if (ReadMemory (pointer_to_label_address, &memory_buffer, data.GetAddressByteSize(), error) == data.GetAddressByteSize())
+                        {
+                            data_offset = 0;
+                            lldb::addr_t label_addr = data.GetAddress(&data_offset);
+                            ReadCStringFromMemory (label_addr, dispatch_queue_name, error);
+                        }
+                    }
+                    else
+                    {
+                        // libdispatch versions 1-3, dispatch name is a fixed width char array
+                        // in the queue structure.
+                        lldb::addr_t label_addr = queue_addr + dispatch_queue_offsets.dqo_label;
+                        dispatch_queue_name.resize(dispatch_queue_offsets.dqo_label_size, '\0');
+                        size_t bytes_read = ReadMemory (label_addr, &dispatch_queue_name[0], dispatch_queue_offsets.dqo_label_size, error);
+                        if (bytes_read < dispatch_queue_offsets.dqo_label_size)
+                            dispatch_queue_name.erase (bytes_read);
+                    }
+                }
+            }
+        }
+    }
+    if (dispatch_queue_name.empty())
+        return NULL;
+    return dispatch_queue_name.c_str();
+}
+
+//uint32_t
+//ProcessGDBRemote::ListProcessesMatchingName (const char *name, StringList &matches, std::vector<lldb::pid_t> &pids)
+//{
+//    // If we are planning to launch the debugserver remotely, then we need to fire up a debugserver
+//    // process and ask it for the list of processes. But if we are local, we can let the Host do it.
+//    if (m_local_debugserver)
+//    {
+//        return Host::ListProcessesMatchingName (name, matches, pids);
+//    }
+//    else 
+//    {
+//        // FIXME: Implement talking to the remote debugserver.
+//        return 0;
+//    }
+//
+//}
+//
+bool
+ProcessGDBRemote::NewThreadNotifyBreakpointHit (void *baton,
+                             lldb_private::StoppointCallbackContext *context,
+                             lldb::user_id_t break_id,
+                             lldb::user_id_t break_loc_id)
+{
+    // I don't think I have to do anything here, just make sure I notice the new thread when it starts to 
+    // run so I can stop it if that's what I want to do.
+    Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
+    if (log)
+        log->Printf("Hit New Thread Notification breakpoint.");
+    return false;
+}
+
+
+bool
+ProcessGDBRemote::StartNoticingNewThreads()
+{
+    Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
+    if (m_thread_create_bp_sp)
+    {
+        if (log && log->GetVerbose())
+            log->Printf("Enabled noticing new thread breakpoint.");
+        m_thread_create_bp_sp->SetEnabled(true);
+    }
+    else
+    {
+        PlatformSP platform_sp (m_target.GetPlatform());
+        if (platform_sp)
+        {
+            m_thread_create_bp_sp = platform_sp->SetThreadCreationBreakpoint(m_target);
+            if (m_thread_create_bp_sp)
+            {
+                if (log && log->GetVerbose())
+                    log->Printf("Successfully created new thread notification breakpoint %i", m_thread_create_bp_sp->GetID());
+                m_thread_create_bp_sp->SetCallback (ProcessGDBRemote::NewThreadNotifyBreakpointHit, this, true);
+            }
+            else
+            {
+                if (log)
+                    log->Printf("Failed to create new thread notification breakpoint.");
+            }
+        }
+    }
+    return m_thread_create_bp_sp.get() != NULL;
+}
+
+bool
+ProcessGDBRemote::StopNoticingNewThreads()
+{   
+    Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
+    if (log && log->GetVerbose())
+        log->Printf ("Disabling new thread notification breakpoint.");
+
+    if (m_thread_create_bp_sp)
+        m_thread_create_bp_sp->SetEnabled(false);
+
+    return true;
+}
+    
+lldb_private::DynamicLoader *
+ProcessGDBRemote::GetDynamicLoader ()
+{
+    if (m_dyld_ap.get() == NULL)
+        m_dyld_ap.reset (DynamicLoader::FindPlugin(this, NULL));
+    return m_dyld_ap.get();
+}
+
+
+class CommandObjectProcessGDBRemotePacketHistory : public CommandObjectParsed
+{
+private:
+    
+public:
+    CommandObjectProcessGDBRemotePacketHistory(CommandInterpreter &interpreter) :
+    CommandObjectParsed (interpreter,
+                         "process plugin packet history",
+                         "Dumps the packet history buffer. ",
+                         NULL)
+    {
+    }
+    
+    ~CommandObjectProcessGDBRemotePacketHistory ()
+    {
+    }
+    
+    bool
+    DoExecute (Args& command, CommandReturnObject &result)
+    {
+        const size_t argc = command.GetArgumentCount();
+        if (argc == 0)
+        {
+            ProcessGDBRemote *process = (ProcessGDBRemote *)m_interpreter.GetExecutionContext().GetProcessPtr();
+            if (process)
+            {
+                process->GetGDBRemote().DumpHistory(result.GetOutputStream());
+                result.SetStatus (eReturnStatusSuccessFinishResult);
+                return true;
+            }
+        }
+        else
+        {
+            result.AppendErrorWithFormat ("'%s' takes no arguments", m_cmd_name.c_str());
+        }
+        result.SetStatus (eReturnStatusFailed);
+        return false;
+    }
+};
+
+class CommandObjectProcessGDBRemotePacketSend : public CommandObjectParsed
+{
+private:
+    
+public:
+    CommandObjectProcessGDBRemotePacketSend(CommandInterpreter &interpreter) :
+        CommandObjectParsed (interpreter,
+                             "process plugin packet send",
+                             "Send a custom packet through the GDB remote protocol and print the answer. "
+                             "The packet header and footer will automatically be added to the packet prior to sending and stripped from the result.",
+                             NULL)
+    {
+    }
+    
+    ~CommandObjectProcessGDBRemotePacketSend ()
+    {
+    }
+    
+    bool
+    DoExecute (Args& command, CommandReturnObject &result)
+    {
+        const size_t argc = command.GetArgumentCount();
+        if (argc == 0)
+        {
+            result.AppendErrorWithFormat ("'%s' takes a one or more packet content arguments", m_cmd_name.c_str());
+            result.SetStatus (eReturnStatusFailed);
+            return false;
+        }
+        
+        ProcessGDBRemote *process = (ProcessGDBRemote *)m_interpreter.GetExecutionContext().GetProcessPtr();
+        if (process)
+        {
+            for (size_t i=0; i<argc; ++ i)
+            {
+                const char *packet_cstr = command.GetArgumentAtIndex(0);
+                bool send_async = true;
+                StringExtractorGDBRemote response;
+                process->GetGDBRemote().SendPacketAndWaitForResponse(packet_cstr, response, send_async);
+                result.SetStatus (eReturnStatusSuccessFinishResult);
+                Stream &output_strm = result.GetOutputStream();
+                output_strm.Printf ("  packet: %s\n", packet_cstr);
+                std::string &response_str = response.GetStringRef();
+                
+                if (strstr(packet_cstr, "qGetProfileData") != NULL)
+                {
+                    response_str = process->GetGDBRemote().HarmonizeThreadIdsForProfileData(process, response);
+                }
+
+                if (response_str.empty())
+                    output_strm.PutCString ("response: \nerror: UNIMPLEMENTED\n");
+                else
+                    output_strm.Printf ("response: %s\n", response.GetStringRef().c_str());
+            }
+        }
+        return true;
+    }
+};
+
+class CommandObjectProcessGDBRemotePacketMonitor : public CommandObjectRaw
+{
+private:
+    
+public:
+    CommandObjectProcessGDBRemotePacketMonitor(CommandInterpreter &interpreter) :
+        CommandObjectRaw (interpreter,
+                         "process plugin packet monitor",
+                         "Send a qRcmd packet through the GDB remote protocol and print the response."
+                         "The argument passed to this command will be hex encoded into a valid 'qRcmd' packet, sent and the response will be printed.",
+                         NULL)
+    {
+    }
+    
+    ~CommandObjectProcessGDBRemotePacketMonitor ()
+    {
+    }
+    
+    bool
+    DoExecute (const char *command, CommandReturnObject &result)
+    {
+        if (command == NULL || command[0] == '\0')
+        {
+            result.AppendErrorWithFormat ("'%s' takes a command string argument", m_cmd_name.c_str());
+            result.SetStatus (eReturnStatusFailed);
+            return false;
+        }
+        
+        ProcessGDBRemote *process = (ProcessGDBRemote *)m_interpreter.GetExecutionContext().GetProcessPtr();
+        if (process)
+        {
+            StreamString packet;
+            packet.PutCString("qRcmd,");
+            packet.PutBytesAsRawHex8(command, strlen(command));
+            const char *packet_cstr = packet.GetString().c_str();
+            
+            bool send_async = true;
+            StringExtractorGDBRemote response;
+            process->GetGDBRemote().SendPacketAndWaitForResponse(packet_cstr, response, send_async);
+            result.SetStatus (eReturnStatusSuccessFinishResult);
+            Stream &output_strm = result.GetOutputStream();
+            output_strm.Printf ("  packet: %s\n", packet_cstr);
+            const std::string &response_str = response.GetStringRef();
+            
+            if (response_str.empty())
+                output_strm.PutCString ("response: \nerror: UNIMPLEMENTED\n");
+            else
+                output_strm.Printf ("response: %s\n", response.GetStringRef().c_str());
+        }
+        return true;
+    }
+};
+
+class CommandObjectProcessGDBRemotePacket : public CommandObjectMultiword
+{
+private:
+    
+public:
+    CommandObjectProcessGDBRemotePacket(CommandInterpreter &interpreter) :
+        CommandObjectMultiword (interpreter,
+                                "process plugin packet",
+                                "Commands that deal with GDB remote packets.",
+                                NULL)
+    {
+        LoadSubCommand ("history", CommandObjectSP (new CommandObjectProcessGDBRemotePacketHistory (interpreter)));
+        LoadSubCommand ("send", CommandObjectSP (new CommandObjectProcessGDBRemotePacketSend (interpreter)));
+        LoadSubCommand ("monitor", CommandObjectSP (new CommandObjectProcessGDBRemotePacketMonitor (interpreter)));
+    }
+    
+    ~CommandObjectProcessGDBRemotePacket ()
+    {
+    }    
+};
+
+class CommandObjectMultiwordProcessGDBRemote : public CommandObjectMultiword
+{
+public:
+    CommandObjectMultiwordProcessGDBRemote (CommandInterpreter &interpreter) :
+        CommandObjectMultiword (interpreter,
+                                "process plugin",
+                                "A set of commands for operating on a ProcessGDBRemote process.",
+                                "process plugin <subcommand> [<subcommand-options>]")
+    {
+        LoadSubCommand ("packet", CommandObjectSP (new CommandObjectProcessGDBRemotePacket    (interpreter)));
+    }
+
+    ~CommandObjectMultiwordProcessGDBRemote ()
+    {
+    }
+};
+
+CommandObject *
+ProcessGDBRemote::GetPluginCommandObject()
+{
+    if (!m_command_sp)
+        m_command_sp.reset (new CommandObjectMultiwordProcessGDBRemote (GetTarget().GetDebugger().GetCommandInterpreter()));
+    return m_command_sp.get();
+}
diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
new file mode 100644
index 000000000000..e104b7191eab
--- /dev/null
+++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
@@ -0,0 +1,396 @@
+//===-- ProcessGDBRemote.h --------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ProcessGDBRemote_h_
+#define liblldb_ProcessGDBRemote_h_
+
+// C Includes
+
+// C++ Includes
+#include <list>
+#include <vector>
+
+// Other libraries and framework includes
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/Broadcaster.h"
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/InputReader.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Core/StringList.h"
+#include "lldb/Core/ThreadSafeValue.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Thread.h"
+
+#include "GDBRemoteCommunicationClient.h"
+#include "Utility/StringExtractor.h"
+#include "GDBRemoteRegisterContext.h"
+
+class ThreadGDBRemote;
+
+class ProcessGDBRemote : public lldb_private::Process
+{
+public:
+    //------------------------------------------------------------------
+    // Constructors and Destructors
+    //------------------------------------------------------------------
+    static lldb::ProcessSP
+    CreateInstance (lldb_private::Target& target, 
+                    lldb_private::Listener &listener,
+                    const lldb_private::FileSpec *crash_file_path);
+
+    static void
+    Initialize();
+
+    static void
+    DebuggerInitialize (lldb_private::Debugger &debugger);
+
+    static void
+    Terminate();
+
+    static lldb_private::ConstString
+    GetPluginNameStatic();
+
+    static const char *
+    GetPluginDescriptionStatic();
+
+    //------------------------------------------------------------------
+    // Constructors and Destructors
+    //------------------------------------------------------------------
+    ProcessGDBRemote(lldb_private::Target& target, lldb_private::Listener &listener);
+
+    virtual
+    ~ProcessGDBRemote();
+
+    //------------------------------------------------------------------
+    // Check if a given Process
+    //------------------------------------------------------------------
+    virtual bool
+    CanDebug (lldb_private::Target &target,
+              bool plugin_specified_by_name);
+
+    virtual lldb_private::CommandObject *
+    GetPluginCommandObject();
+
+    //------------------------------------------------------------------
+    // Creating a new process, or attaching to an existing one
+    //------------------------------------------------------------------
+    virtual lldb_private::Error
+    WillLaunch (lldb_private::Module* module);
+
+    virtual lldb_private::Error
+    DoLaunch (lldb_private::Module *exe_module, 
+              const lldb_private::ProcessLaunchInfo &launch_info);
+
+    virtual void
+    DidLaunch ();
+
+    virtual lldb_private::Error
+    WillAttachToProcessWithID (lldb::pid_t pid);
+
+    virtual lldb_private::Error
+    WillAttachToProcessWithName (const char *process_name, bool wait_for_launch);
+
+    virtual lldb_private::Error
+    DoConnectRemote (lldb_private::Stream *strm, const char *remote_url);
+    
+    lldb_private::Error
+    WillLaunchOrAttach ();
+
+    virtual lldb_private::Error
+    DoAttachToProcessWithID (lldb::pid_t pid);
+    
+    virtual lldb_private::Error
+    DoAttachToProcessWithID (lldb::pid_t pid, const lldb_private::ProcessAttachInfo &attach_info);
+    
+    virtual lldb_private::Error
+    DoAttachToProcessWithName (const char *process_name,
+                               bool wait_for_launch,
+                               const lldb_private::ProcessAttachInfo &attach_info);
+
+    virtual void
+    DidAttach ();
+
+    //------------------------------------------------------------------
+    // PluginInterface protocol
+    //------------------------------------------------------------------
+    virtual lldb_private::ConstString
+    GetPluginName();
+
+    virtual uint32_t
+    GetPluginVersion();
+
+    //------------------------------------------------------------------
+    // Process Control
+    //------------------------------------------------------------------
+    virtual lldb_private::Error
+    WillResume ();
+
+    virtual lldb_private::Error
+    DoResume ();
+
+    virtual lldb_private::Error
+    DoHalt (bool &caused_stop);
+
+    virtual lldb_private::Error
+    DoDetach (bool keep_stopped);
+    
+    virtual bool
+    DetachRequiresHalt() { return true; }
+
+    virtual lldb_private::Error
+    DoSignal (int signal);
+
+    virtual lldb_private::Error
+    DoDestroy ();
+
+    virtual void
+    RefreshStateAfterStop();
+
+    //------------------------------------------------------------------
+    // Process Queries
+    //------------------------------------------------------------------
+    virtual bool
+    IsAlive ();
+
+    virtual lldb::addr_t
+    GetImageInfoAddress();
+
+    //------------------------------------------------------------------
+    // Process Memory
+    //------------------------------------------------------------------
+    virtual size_t
+    DoReadMemory (lldb::addr_t addr, void *buf, size_t size, lldb_private::Error &error);
+
+    virtual size_t
+    DoWriteMemory (lldb::addr_t addr, const void *buf, size_t size, lldb_private::Error &error);
+
+    virtual lldb::addr_t
+    DoAllocateMemory (size_t size, uint32_t permissions, lldb_private::Error &error);
+
+    virtual lldb_private::Error
+    GetMemoryRegionInfo (lldb::addr_t load_addr, 
+                         lldb_private::MemoryRegionInfo &region_info);
+    
+    virtual lldb_private::Error
+    DoDeallocateMemory (lldb::addr_t ptr);
+
+    //------------------------------------------------------------------
+    // Process STDIO
+    //------------------------------------------------------------------
+    virtual size_t
+    PutSTDIN (const char *buf, size_t buf_size, lldb_private::Error &error);
+
+    //----------------------------------------------------------------------
+    // Process Breakpoints
+    //----------------------------------------------------------------------
+    virtual lldb_private::Error
+    EnableBreakpointSite (lldb_private::BreakpointSite *bp_site);
+
+    virtual lldb_private::Error
+    DisableBreakpointSite (lldb_private::BreakpointSite *bp_site);
+
+    //----------------------------------------------------------------------
+    // Process Watchpoints
+    //----------------------------------------------------------------------
+    virtual lldb_private::Error
+    EnableWatchpoint (lldb_private::Watchpoint *wp, bool notify = true);
+
+    virtual lldb_private::Error
+    DisableWatchpoint (lldb_private::Watchpoint *wp, bool notify = true);
+
+    virtual lldb_private::Error
+    GetWatchpointSupportInfo (uint32_t &num);
+    
+    virtual lldb_private::Error
+    GetWatchpointSupportInfo (uint32_t &num, bool& after);
+    
+    virtual bool
+    StartNoticingNewThreads();    
+
+    virtual bool
+    StopNoticingNewThreads();    
+
+    GDBRemoteCommunicationClient &
+    GetGDBRemote()
+    {
+        return m_gdb_comm;
+    }
+
+protected:
+    friend class ThreadGDBRemote;
+    friend class GDBRemoteCommunicationClient;
+    friend class GDBRemoteRegisterContext;
+
+    //----------------------------------------------------------------------
+    // Accessors
+    //----------------------------------------------------------------------
+    bool
+    IsRunning ( lldb::StateType state )
+    {
+        return    state == lldb::eStateRunning || IsStepping(state);
+    }
+
+    bool
+    IsStepping ( lldb::StateType state)
+    {
+        return    state == lldb::eStateStepping;
+    }
+    bool
+    CanResume ( lldb::StateType state)
+    {
+        return state == lldb::eStateStopped;
+    }
+
+    bool
+    HasExited (lldb::StateType state)
+    {
+        return state == lldb::eStateExited;
+    }
+
+    bool
+    ProcessIDIsValid ( ) const;
+
+    void
+    Clear ( );
+
+    lldb_private::Flags &
+    GetFlags ()
+    {
+        return m_flags;
+    }
+
+    const lldb_private::Flags &
+    GetFlags () const
+    {
+        return m_flags;
+    }
+
+    virtual bool
+    UpdateThreadList (lldb_private::ThreadList &old_thread_list, 
+                      lldb_private::ThreadList &new_thread_list);
+
+    lldb_private::Error
+    StartDebugserverProcess (const char *debugserver_url);
+    
+    lldb_private::Error
+    StartDebugserverProcess (const char *debugserver_url, const lldb_private::ProcessInfo &process_info);
+
+    void
+    KillDebugserverProcess ();
+
+    void
+    BuildDynamicRegisterInfo (bool force);
+
+    void
+    SetLastStopPacket (const StringExtractorGDBRemote &response);
+
+    //------------------------------------------------------------------
+    /// Broadcaster event bits definitions.
+    //------------------------------------------------------------------
+    enum
+    {
+        eBroadcastBitAsyncContinue                  = (1 << 0),
+        eBroadcastBitAsyncThreadShouldExit          = (1 << 1),
+        eBroadcastBitAsyncThreadDidExit             = (1 << 2)
+    };
+
+    typedef enum AsyncThreadState
+    {
+        eAsyncThreadNotStarted,
+        eAsyncThreadRunning,
+        eAsyncThreadDone
+    } AsyncThreadState;
+    
+    lldb_private::Flags m_flags;            // Process specific flags (see eFlags enums)
+    GDBRemoteCommunicationClient m_gdb_comm;
+    lldb::pid_t m_debugserver_pid;
+    StringExtractorGDBRemote m_last_stop_packet;
+    lldb_private::Mutex m_last_stop_packet_mutex;
+    GDBRemoteDynamicRegisterInfo m_register_info;
+    lldb_private::Broadcaster m_async_broadcaster;
+    lldb::thread_t m_async_thread;
+    AsyncThreadState m_async_thread_state;
+    lldb_private::Mutex m_async_thread_state_mutex;
+    typedef std::vector<lldb::tid_t> tid_collection;
+    typedef std::vector< std::pair<lldb::tid_t,int> > tid_sig_collection;
+    typedef std::map<lldb::addr_t, lldb::addr_t> MMapMap;
+    tid_collection m_thread_ids; // Thread IDs for all threads. This list gets updated after stopping
+    tid_collection m_continue_c_tids;                  // 'c' for continue
+    tid_sig_collection m_continue_C_tids; // 'C' for continue with signal
+    tid_collection m_continue_s_tids;                  // 's' for step
+    tid_sig_collection m_continue_S_tids; // 'S' for step with signal
+    lldb::addr_t m_dispatch_queue_offsets_addr;
+    size_t m_max_memory_size;       // The maximum number of bytes to read/write when reading and writing memory
+    MMapMap m_addr_to_mmap_size;
+    lldb::BreakpointSP m_thread_create_bp_sp;
+    bool m_waiting_for_attach;
+    bool m_destroy_tried_resuming;
+    lldb::CommandObjectSP m_command_sp;
+    
+    bool
+    StartAsyncThread ();
+
+    void
+    StopAsyncThread ();
+
+    static void *
+    AsyncThread (void *arg);
+
+    static bool
+    MonitorDebugserverProcess (void *callback_baton,
+                               lldb::pid_t pid,
+                               bool exited,
+                               int signo,
+                               int exit_status);
+
+    lldb::StateType
+    SetThreadStopInfo (StringExtractor& stop_packet);
+
+    void
+    ClearThreadIDList ();
+
+    bool
+    UpdateThreadIDList ();
+
+    void
+    DidLaunchOrAttach ();
+
+    lldb_private::Error
+    ConnectToDebugserver (const char *host_port);
+
+    const char *
+    GetDispatchQueueNameForThread (lldb::addr_t thread_dispatch_qaddr,
+                                   std::string &dispatch_queue_name);
+
+    static size_t
+    AttachInputReaderCallback (void *baton, 
+                               lldb_private::InputReader *reader, 
+                               lldb::InputReaderAction notification,
+                               const char *bytes, 
+                               size_t bytes_len);
+
+    lldb_private::DynamicLoader *
+    GetDynamicLoader ();
+
+private:
+    //------------------------------------------------------------------
+    // For ProcessGDBRemote only
+    //------------------------------------------------------------------
+    static bool
+    NewThreadNotifyBreakpointHit (void *baton,
+                         lldb_private::StoppointCallbackContext *context,
+                         lldb::user_id_t break_id,
+                         lldb::user_id_t break_loc_id);
+
+    DISALLOW_COPY_AND_ASSIGN (ProcessGDBRemote);
+
+};
+
+#endif  // liblldb_ProcessGDBRemote_h_
diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.cpp b/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.cpp
new file mode 100644
index 000000000000..15b861feaa82
--- /dev/null
+++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.cpp
@@ -0,0 +1,196 @@
+//===-- ProcessGDBRemoteLog.cpp ---------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ProcessGDBRemoteLog.h"
+
+#include "lldb/Interpreter/Args.h"
+#include "lldb/Core/StreamFile.h"
+
+#include "ProcessGDBRemote.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+// We want to avoid global constructors where code needs to be run so here we
+// control access to our static g_log_sp by hiding it in a singleton function
+// that will construct the static g_lob_sp the first time this function is 
+// called.
+static bool g_log_enabled = false;
+static Log * g_log = NULL;
+static Log *
+GetLog ()
+{
+    if (!g_log_enabled)
+        return NULL;
+    return g_log;
+}
+
+
+Log *
+ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (uint32_t mask)
+{
+    Log *log(GetLog ());
+    if (log && mask)
+    {
+        uint32_t log_mask = log->GetMask().Get();
+        if ((log_mask & mask) != mask)
+            return NULL;
+    }
+    return log;
+}
+
+Log *
+ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (uint32_t mask)
+{
+    Log *log(GetLog ());
+    if (log && log->GetMask().Get() & mask)
+        return log;
+    return NULL;
+}
+
+void
+ProcessGDBRemoteLog::DisableLog (const char **categories, Stream *feedback_strm)
+{
+    Log *log (GetLog ());
+    if (log)
+    {
+        uint32_t flag_bits = 0;
+        
+        if (categories[0] != NULL)
+        {
+            flag_bits = log->GetMask().Get();
+            for (size_t i = 0; categories[i] != NULL; ++i)
+            {
+                const char *arg = categories[i];
+                
+
+                if      (::strcasecmp (arg, "all")        == 0 ) flag_bits &= ~GDBR_LOG_ALL;
+                else if (::strcasecmp (arg, "async")      == 0 ) flag_bits &= ~GDBR_LOG_ASYNC;
+                else if (::strncasecmp (arg, "break", 5)  == 0 ) flag_bits &= ~GDBR_LOG_BREAKPOINTS;
+                else if (::strncasecmp (arg, "comm", 4)   == 0 ) flag_bits &= ~GDBR_LOG_COMM;
+                else if (::strcasecmp (arg, "default")    == 0 ) flag_bits &= ~GDBR_LOG_DEFAULT;
+                else if (::strcasecmp (arg, "packets")    == 0 ) flag_bits &= ~GDBR_LOG_PACKETS;
+                else if (::strcasecmp (arg, "memory")     == 0 ) flag_bits &= ~GDBR_LOG_MEMORY;
+                else if (::strcasecmp (arg, "data-short") == 0 ) flag_bits &= ~GDBR_LOG_MEMORY_DATA_SHORT;
+                else if (::strcasecmp (arg, "data-long")  == 0 ) flag_bits &= ~GDBR_LOG_MEMORY_DATA_LONG;
+                else if (::strcasecmp (arg, "process")    == 0 ) flag_bits &= ~GDBR_LOG_PROCESS;
+                else if (::strcasecmp (arg, "step")       == 0 ) flag_bits &= ~GDBR_LOG_STEP;
+                else if (::strcasecmp (arg, "thread")     == 0 ) flag_bits &= ~GDBR_LOG_THREAD;
+                else if (::strcasecmp (arg, "verbose")    == 0 ) flag_bits &= ~GDBR_LOG_VERBOSE;
+                else if (::strncasecmp (arg, "watch", 5)  == 0 ) flag_bits &= ~GDBR_LOG_WATCHPOINTS;
+                else
+                {
+                    feedback_strm->Printf("error: unrecognized log category '%s'\n", arg);
+                    ListLogCategories (feedback_strm);
+                }
+                
+            }
+        }
+        
+        if (flag_bits == 0)
+            g_log_enabled = false;
+        else
+            log->GetMask().Reset (flag_bits);
+    }
+    
+    return;
+}
+
+Log *
+ProcessGDBRemoteLog::EnableLog (StreamSP &log_stream_sp, uint32_t log_options, const char **categories, Stream *feedback_strm)
+{
+    // Try see if there already is a log - that way we can reuse its settings.
+    // We could reuse the log in toto, but we don't know that the stream is the same.
+    uint32_t flag_bits = 0;
+    if (g_log)
+        flag_bits = g_log->GetMask().Get();
+
+    // Now make a new log with this stream if one was provided
+    if (log_stream_sp)
+    {
+        if (g_log)
+            g_log->SetStream(log_stream_sp);
+        else
+            g_log = new Log(log_stream_sp);
+    }
+
+    if (g_log)
+    {
+        bool got_unknown_category = false;
+        for (size_t i=0; categories[i] != NULL; ++i)
+        {
+            const char *arg = categories[i];
+
+            if      (::strcasecmp (arg, "all")        == 0 ) flag_bits |= GDBR_LOG_ALL;
+            else if (::strcasecmp (arg, "async")      == 0 ) flag_bits |= GDBR_LOG_ASYNC;
+            else if (::strncasecmp (arg, "break", 5)  == 0 ) flag_bits |= GDBR_LOG_BREAKPOINTS;
+            else if (::strncasecmp (arg, "comm", 4)   == 0 ) flag_bits |= GDBR_LOG_COMM;
+            else if (::strcasecmp (arg, "default")    == 0 ) flag_bits |= GDBR_LOG_DEFAULT;
+            else if (::strcasecmp (arg, "packets")    == 0 ) flag_bits |= GDBR_LOG_PACKETS;
+            else if (::strcasecmp (arg, "memory")     == 0 ) flag_bits |= GDBR_LOG_MEMORY;
+            else if (::strcasecmp (arg, "data-short") == 0 ) flag_bits |= GDBR_LOG_MEMORY_DATA_SHORT;
+            else if (::strcasecmp (arg, "data-long")  == 0 ) flag_bits |= GDBR_LOG_MEMORY_DATA_LONG;
+            else if (::strcasecmp (arg, "process")    == 0 ) flag_bits |= GDBR_LOG_PROCESS;
+            else if (::strcasecmp (arg, "step")       == 0 ) flag_bits |= GDBR_LOG_STEP;
+            else if (::strcasecmp (arg, "thread")     == 0 ) flag_bits |= GDBR_LOG_THREAD;
+            else if (::strcasecmp (arg, "verbose")    == 0 ) flag_bits |= GDBR_LOG_VERBOSE;
+            else if (::strncasecmp (arg, "watch", 5)  == 0 ) flag_bits |= GDBR_LOG_WATCHPOINTS;
+            else
+            {
+                feedback_strm->Printf("error: unrecognized log category '%s'\n", arg);
+                if (got_unknown_category == false)
+                {
+                    got_unknown_category = true;
+                    ListLogCategories (feedback_strm);
+                }
+            }
+        }
+        if (flag_bits == 0)
+            flag_bits = GDBR_LOG_DEFAULT;
+        g_log->GetMask().Reset(flag_bits);
+        g_log->GetOptions().Reset(log_options);
+    }
+    g_log_enabled = true;
+    return g_log;
+}
+
+void
+ProcessGDBRemoteLog::ListLogCategories (Stream *strm)
+{
+    strm->Printf ("Logging categories for '%s':\n"
+                  "  all - turn on all available logging categories\n"
+                  "  async - log asynchronous activity\n"
+                  "  break - log breakpoints\n"
+                  "  communication - log communication activity\n"
+                  "  default - enable the default set of logging categories for liblldb\n"
+                  "  packets - log gdb remote packets\n"
+                  "  memory - log memory reads and writes\n"
+                  "  data-short - log memory bytes for memory reads and writes for short transactions only\n"
+                  "  data-long - log memory bytes for memory reads and writes for all transactions\n"
+                  "  process - log process events and activities\n"
+                  "  thread - log thread events and activities\n"
+                  "  step - log step related activities\n"
+                  "  verbose - enable verbose logging\n"
+                  "  watch - log watchpoint related activities\n", ProcessGDBRemote::GetPluginNameStatic().GetCString());
+}
+
+
+void
+ProcessGDBRemoteLog::LogIf (uint32_t mask, const char *format, ...)
+{
+    Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (mask));
+    if (log)
+    {
+        va_list args;
+        va_start (args, format);
+        log->VAPrintf (format, args);
+        va_end (args);
+    }
+}
diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h b/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h
new file mode 100644
index 000000000000..93734067f133
--- /dev/null
+++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h
@@ -0,0 +1,57 @@
+//===-- ProcessGDBRemoteLog.h -----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ProcessGDBRemoteLog_h_
+#define liblldb_ProcessGDBRemoteLog_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+
+// Project includes
+#include "lldb/Core/Log.h"
+
+#define GDBR_LOG_VERBOSE                  (1u << 0)
+#define GDBR_LOG_PROCESS                  (1u << 1)
+#define GDBR_LOG_THREAD                   (1u << 2)
+#define GDBR_LOG_PACKETS                  (1u << 3)
+#define GDBR_LOG_MEMORY                   (1u << 4)    // Log memory reads/writes calls
+#define GDBR_LOG_MEMORY_DATA_SHORT        (1u << 5)    // Log short memory reads/writes bytes
+#define GDBR_LOG_MEMORY_DATA_LONG         (1u << 6)    // Log all memory reads/writes bytes
+#define GDBR_LOG_BREAKPOINTS              (1u << 7)
+#define GDBR_LOG_WATCHPOINTS              (1u << 8)
+#define GDBR_LOG_STEP                     (1u << 9)
+#define GDBR_LOG_COMM                     (1u << 10)
+#define GDBR_LOG_ASYNC                    (1u << 11)
+#define GDBR_LOG_ALL                      (UINT32_MAX)
+#define GDBR_LOG_DEFAULT                  GDBR_LOG_PACKETS
+
+class ProcessGDBRemoteLog
+{
+public:
+    static lldb_private::Log *
+    GetLogIfAllCategoriesSet(uint32_t mask = 0);
+    
+    static lldb_private::Log *
+    GetLogIfAnyCategoryIsSet (uint32_t mask);
+
+    static void
+    DisableLog (const char **categories, lldb_private::Stream *feedback_strm);
+
+    static lldb_private::Log *
+    EnableLog (lldb::StreamSP &log_stream_sp, uint32_t log_options, const char **categories, lldb_private::Stream *feedback_strm);
+
+    static void
+    ListLogCategories (lldb_private::Stream *strm);
+
+    static void
+    LogIf (uint32_t mask, const char *format, ...);
+};
+
+#endif  // liblldb_ProcessGDBRemoteLog_h_
diff --git a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
new file mode 100644
index 000000000000..38fb84d66ef3
--- /dev/null
+++ b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
@@ -0,0 +1,214 @@
+//===-- ThreadGDBRemote.cpp -------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+
+#include "ThreadGDBRemote.h"
+
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Core/State.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/StopInfo.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Unwind.h"
+#include "lldb/Breakpoint/Watchpoint.h"
+
+#include "ProcessGDBRemote.h"
+#include "ProcessGDBRemoteLog.h"
+#include "Utility/StringExtractorGDBRemote.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// Thread Registers
+//----------------------------------------------------------------------
+
+ThreadGDBRemote::ThreadGDBRemote (Process &process, lldb::tid_t tid) :
+    Thread(process, tid),
+    m_thread_name (),
+    m_dispatch_queue_name (),
+    m_thread_dispatch_qaddr (LLDB_INVALID_ADDRESS)
+{
+    ProcessGDBRemoteLog::LogIf(GDBR_LOG_THREAD, "%p: ThreadGDBRemote::ThreadGDBRemote (pid = %i, tid = 0x%4.4x)", 
+                               this, 
+                               process.GetID(),
+                               GetID());
+}
+
+ThreadGDBRemote::~ThreadGDBRemote ()
+{
+    ProcessSP process_sp(GetProcess());
+    ProcessGDBRemoteLog::LogIf(GDBR_LOG_THREAD, "%p: ThreadGDBRemote::~ThreadGDBRemote (pid = %i, tid = 0x%4.4x)", 
+                               this, 
+                               process_sp ? process_sp->GetID() : LLDB_INVALID_PROCESS_ID, 
+                               GetID());
+    DestroyThread();
+}
+
+const char *
+ThreadGDBRemote::GetName ()
+{
+    if (m_thread_name.empty())
+        return NULL;
+    return m_thread_name.c_str();
+}
+
+
+const char *
+ThreadGDBRemote::GetQueueName ()
+{
+    // Always re-fetch the dispatch queue name since it can change
+
+    if (m_thread_dispatch_qaddr != 0 || m_thread_dispatch_qaddr != LLDB_INVALID_ADDRESS)
+    {
+        ProcessSP process_sp (GetProcess());
+        if (process_sp)
+        {
+            ProcessGDBRemote *gdb_process = static_cast<ProcessGDBRemote *>(process_sp.get());
+            return gdb_process->GetDispatchQueueNameForThread (m_thread_dispatch_qaddr, m_dispatch_queue_name);
+        }
+    }
+    return NULL;
+}
+
+void
+ThreadGDBRemote::WillResume (StateType resume_state)
+{
+    int signo = GetResumeSignal();
+    const lldb::user_id_t tid = GetProtocolID();
+    Log *log(lldb_private::GetLogIfAnyCategoriesSet (GDBR_LOG_THREAD));
+    if (log)
+        log->Printf ("Resuming thread: %4.4" PRIx64 " with state: %s.", tid, StateAsCString(resume_state));
+
+    ProcessSP process_sp (GetProcess());
+    if (process_sp)
+    {
+        ProcessGDBRemote *gdb_process = static_cast<ProcessGDBRemote *>(process_sp.get());
+        switch (resume_state)
+        {
+        case eStateSuspended:
+        case eStateStopped:
+            // Don't append anything for threads that should stay stopped.
+            break;
+
+        case eStateRunning:
+            if (gdb_process->GetUnixSignals().SignalIsValid (signo))
+                gdb_process->m_continue_C_tids.push_back(std::make_pair(tid, signo));
+            else
+                gdb_process->m_continue_c_tids.push_back(tid);
+            break;
+
+        case eStateStepping:
+            if (gdb_process->GetUnixSignals().SignalIsValid (signo))
+                gdb_process->m_continue_S_tids.push_back(std::make_pair(tid, signo));
+            else
+                gdb_process->m_continue_s_tids.push_back(tid);
+            break;
+
+        default:
+            break;
+        }
+    }
+}
+
+void
+ThreadGDBRemote::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 GDBRemoteRegisterContext
+    // 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.
+    const bool force = false;
+    GetRegisterContext()->InvalidateIfNeeded (force);
+}
+
+bool
+ThreadGDBRemote::ThreadIDIsValid (lldb::tid_t thread)
+{
+    return thread != 0;
+}
+
+void
+ThreadGDBRemote::Dump(Log *log, uint32_t index)
+{
+}
+
+
+bool
+ThreadGDBRemote::ShouldStop (bool &step_more)
+{
+    return true;
+}
+lldb::RegisterContextSP
+ThreadGDBRemote::GetRegisterContext ()
+{
+    if (m_reg_context_sp.get() == NULL)
+        m_reg_context_sp = CreateRegisterContextForFrame (NULL);
+    return m_reg_context_sp;
+}
+
+lldb::RegisterContextSP
+ThreadGDBRemote::CreateRegisterContextForFrame (StackFrame *frame)
+{
+    lldb::RegisterContextSP reg_ctx_sp;
+    const bool read_all_registers_at_once = false;
+    uint32_t concrete_frame_idx = 0;
+    
+    if (frame)
+        concrete_frame_idx = frame->GetConcreteFrameIndex ();
+
+    
+    if (concrete_frame_idx == 0)
+    {
+        ProcessSP process_sp (GetProcess());
+        if (process_sp)
+        {
+            ProcessGDBRemote *gdb_process = static_cast<ProcessGDBRemote *>(process_sp.get());
+            reg_ctx_sp.reset (new GDBRemoteRegisterContext (*this, concrete_frame_idx, gdb_process->m_register_info, read_all_registers_at_once));
+        }
+    }
+    else
+    {
+        Unwind *unwinder = GetUnwinder ();
+        if (unwinder)
+            reg_ctx_sp = unwinder->CreateRegisterContextForFrame (frame);
+    }
+    return reg_ctx_sp;
+}
+
+bool
+ThreadGDBRemote::PrivateSetRegisterValue (uint32_t reg, StringExtractor &response)
+{
+    GDBRemoteRegisterContext *gdb_reg_ctx = static_cast<GDBRemoteRegisterContext *>(GetRegisterContext ().get());
+    assert (gdb_reg_ctx);
+    return gdb_reg_ctx->PrivateSetRegisterValue (reg, response);
+}
+
+bool
+ThreadGDBRemote::CalculateStopInfo ()
+{
+    ProcessSP process_sp (GetProcess());
+    if (process_sp)
+    {
+        StringExtractorGDBRemote stop_packet;
+        ProcessGDBRemote *gdb_process = static_cast<ProcessGDBRemote *>(process_sp.get());
+        if (gdb_process->GetGDBRemote().GetThreadStopInfo(GetProtocolID(), stop_packet))
+            return gdb_process->SetThreadStopInfo (stop_packet) == eStateStopped;
+    }
+    return false;
+}
+
+
diff --git a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h
new file mode 100644
index 000000000000..50a3f19c6505
--- /dev/null
+++ b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h
@@ -0,0 +1,107 @@
+//===-- ThreadGDBRemote.h ---------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_ThreadGDBRemote_h_
+#define liblldb_ThreadGDBRemote_h_
+
+#include <string>
+
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Thread.h"
+
+class StringExtractor;
+class ProcessGDBRemote;
+
+class ThreadGDBRemote : public lldb_private::Thread
+{
+public:
+    ThreadGDBRemote (lldb_private::Process &process, lldb::tid_t tid);
+
+    virtual
+    ~ThreadGDBRemote ();
+
+    virtual void
+    WillResume (lldb::StateType resume_state);
+
+    virtual void
+    RefreshStateAfterStop();
+
+    virtual const char *
+    GetName ();
+
+    virtual const char *
+    GetQueueName ();
+
+    virtual lldb::RegisterContextSP
+    GetRegisterContext ();
+
+    virtual lldb::RegisterContextSP
+    CreateRegisterContextForFrame (lldb_private::StackFrame *frame);
+
+    void
+    Dump (lldb_private::Log *log, uint32_t index);
+
+    static bool
+    ThreadIDIsValid (lldb::tid_t thread);
+
+    bool
+    ShouldStop (bool &step_more);
+
+    const char *
+    GetBasicInfoAsString ();
+
+    void
+    SetName (const char *name)
+    {
+        if (name && name[0])
+            m_thread_name.assign (name);
+        else
+            m_thread_name.clear();
+    }
+
+    lldb::addr_t
+    GetThreadDispatchQAddr ()
+    {
+        return m_thread_dispatch_qaddr;
+    }
+
+    void
+    SetThreadDispatchQAddr (lldb::addr_t thread_dispatch_qaddr)
+    {
+        m_thread_dispatch_qaddr = thread_dispatch_qaddr;
+    }
+
+protected:
+    
+    friend class ProcessGDBRemote;
+
+    bool
+    PrivateSetRegisterValue (uint32_t reg, 
+                             StringExtractor &response);
+                             
+    //------------------------------------------------------------------
+    // Member variables.
+    //------------------------------------------------------------------
+    std::string m_thread_name;
+    std::string m_dispatch_queue_name;
+    lldb::addr_t m_thread_dispatch_qaddr;
+    //------------------------------------------------------------------
+    // Member variables.
+    //------------------------------------------------------------------
+
+    void
+    SetStopInfoFromPacket (StringExtractor &stop_packet, uint32_t stop_id);
+
+    virtual bool
+    CalculateStopInfo ();
+
+
+};
+
+#endif  // liblldb_ThreadGDBRemote_h_
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp b/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp
new file mode 100644
index 000000000000..06e87eab33ce
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.cpp
@@ -0,0 +1,211 @@
+//===-- DWARFAbbreviationDeclaration.cpp ------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFAbbreviationDeclaration.h"
+
+#include "lldb/Core/dwarf.h"
+
+#include "DWARFFormValue.h"
+
+using namespace lldb_private;
+
+DWARFAbbreviationDeclaration::DWARFAbbreviationDeclaration() :
+    m_code  (InvalidCode),
+    m_tag   (0),
+    m_has_children (0),
+    m_attributes()
+{
+}
+
+DWARFAbbreviationDeclaration::DWARFAbbreviationDeclaration(dw_tag_t tag, uint8_t has_children) :
+    m_code  (InvalidCode),
+    m_tag   (tag),
+    m_has_children (has_children),
+    m_attributes()
+{
+}
+
+bool
+DWARFAbbreviationDeclaration::Extract(const DataExtractor& data, lldb::offset_t* offset_ptr)
+{
+    return Extract(data, offset_ptr, data.GetULEB128(offset_ptr));
+}
+
+bool
+DWARFAbbreviationDeclaration::Extract(const DataExtractor& data, lldb::offset_t *offset_ptr, dw_uleb128_t code)
+{
+    m_code = code;
+    m_attributes.clear();
+    if (m_code)
+    {
+        m_tag = data.GetULEB128(offset_ptr);
+        m_has_children = data.GetU8(offset_ptr);
+
+        while (data.ValidOffset(*offset_ptr))
+        {
+            dw_attr_t attr = data.GetULEB128(offset_ptr);
+            dw_form_t form = data.GetULEB128(offset_ptr);
+
+            if (attr && form)
+                m_attributes.push_back(DWARFAttribute(attr, form));
+            else
+                break;
+        }
+
+        return m_tag != 0;
+    }
+    else
+    {
+        m_tag = 0;
+        m_has_children = 0;
+    }
+
+    return false;
+}
+
+
+void
+DWARFAbbreviationDeclaration::Dump(Stream *s)  const
+{
+//  *ostrm_ptr << std::setfill(' ') << std::dec << '[' << std::setw(3) << std::right << m_code << ']' << ' ' << std::setw(30) << std::left << DW_TAG_value_to_name(m_tag) << DW_CHILDREN_value_to_name(m_has_children) << std::endl;
+//
+//  DWARFAttribute::const_iterator pos;
+//
+//  for (pos = m_attributes.begin(); pos != m_attributes.end(); ++pos)
+//      *ostrm_ptr << "      " << std::setw(29) << std::left << DW_AT_value_to_name(pos->attr()) << ' ' << DW_FORM_value_to_name(pos->form()) << std::endl;
+//
+//  *ostrm_ptr << std::endl;
+}
+
+
+
+bool
+DWARFAbbreviationDeclaration::IsValid()
+{
+    return m_code != 0 && m_tag != 0;
+}
+
+
+void
+DWARFAbbreviationDeclaration::CopyExcludingAddressAttributes(const DWARFAbbreviationDeclaration& abbr_decl, const uint32_t idx)
+{
+    m_code = abbr_decl.Code();  // Invalidate the code since that can't be copied safely.
+    m_tag = abbr_decl.Tag();
+    m_has_children = abbr_decl.HasChildren();
+
+    const DWARFAttribute::collection& attributes = abbr_decl.Attributes();
+    const uint32_t num_abbr_decl_attributes = attributes.size();
+
+    dw_attr_t attr;
+    dw_form_t form;
+    uint32_t i;
+
+    for (i = 0; i < num_abbr_decl_attributes; ++i)
+    {
+        attributes[i].get(attr, form);
+        switch (attr)
+        {
+        case DW_AT_location:
+        case DW_AT_frame_base:
+            // Only add these if they are location expressions (have a single
+            // value) and not location lists (have a lists of location
+            // expressions which are only valid over specific address ranges)
+            if (DWARFFormValue::IsBlockForm(form))
+                m_attributes.push_back(DWARFAttribute(attr, form));
+            break;
+
+        case DW_AT_low_pc:
+        case DW_AT_high_pc:
+        case DW_AT_ranges:
+        case DW_AT_entry_pc:
+            // Don't add these attributes
+            if (i >= idx)
+                break;
+            // Fall through and add attribute
+        default:
+            // Add anything that isn't address related
+            m_attributes.push_back(DWARFAttribute(attr, form));
+            break;
+        }
+    }
+}
+
+void
+DWARFAbbreviationDeclaration::CopyChangingStringToStrp(
+    const DWARFAbbreviationDeclaration& abbr_decl,
+    const DataExtractor& debug_info_data,
+    dw_offset_t debug_info_offset,
+    const DWARFCompileUnit* cu,
+    const uint32_t strp_min_len
+)
+{
+    m_code = InvalidCode;
+    m_tag = abbr_decl.Tag();
+    m_has_children = abbr_decl.HasChildren();
+
+    const DWARFAttribute::collection& attributes = abbr_decl.Attributes();
+    const uint32_t num_abbr_decl_attributes = attributes.size();
+
+    dw_attr_t attr;
+    dw_form_t form;
+    uint32_t i;
+    lldb::offset_t offset = debug_info_offset;
+
+    for (i = 0; i < num_abbr_decl_attributes; ++i)
+    {
+        attributes[i].get(attr, form);
+        dw_offset_t attr_offset = offset;
+        DWARFFormValue::SkipValue(form, debug_info_data, &offset, cu);
+
+        if (form == DW_FORM_string && ((offset - attr_offset) >= strp_min_len))
+            m_attributes.push_back(DWARFAttribute(attr, DW_FORM_strp));
+        else
+            m_attributes.push_back(DWARFAttribute(attr, form));
+    }
+}
+
+
+uint32_t
+DWARFAbbreviationDeclaration::FindAttributeIndex(dw_attr_t attr) const
+{
+    uint32_t i;
+    const uint32_t kNumAttributes = m_attributes.size();
+    for (i = 0; i < kNumAttributes; ++i)
+    {
+        if (m_attributes[i].get_attr() == attr)
+            return i;
+    }
+    return DW_INVALID_INDEX;
+}
+
+
+bool
+DWARFAbbreviationDeclaration::operator == (const DWARFAbbreviationDeclaration& rhs) const
+{
+    return Tag()            == rhs.Tag()
+        && HasChildren()    == rhs.HasChildren()
+        && Attributes()     == rhs.Attributes();
+}
+
+#if 0
+DWARFAbbreviationDeclaration::Append(BinaryStreamBuf& out_buff) const
+{
+    out_buff.Append32_as_ULEB128(Code());
+    out_buff.Append32_as_ULEB128(Tag());
+    out_buff.Append8(HasChildren());
+    const uint32_t kNumAttributes = m_attributes.size();
+    for (uint32_t i = 0; i < kNumAttributes; ++i)
+    {
+        out_buff.Append32_as_ULEB128(m_attributes[i].attr());
+        out_buff.Append32_as_ULEB128(m_attributes[i].form());
+    }
+    out_buff.Append8(0);    // Output a zero for attr (faster than using Append32_as_ULEB128)
+    out_buff.Append8(0);    // Output a zero for attr (faster than using Append32_as_ULEB128)
+}
+#endif  // 0
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.h b/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.h
new file mode 100644
index 000000000000..f462b7fc108d
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.h
@@ -0,0 +1,81 @@
+//===-- DWARFAbbreviationDeclaration.h --------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_DWARFAbbreviationDeclaration_h_
+#define liblldb_DWARFAbbreviationDeclaration_h_
+
+#include "SymbolFileDWARF.h"
+#include "DWARFAttribute.h"
+
+class DWARFCompileUnit;
+
+class DWARFAbbreviationDeclaration
+{
+public:
+    enum { InvalidCode = 0 };
+                    DWARFAbbreviationDeclaration();
+
+                    // For hand crafting an abbreviation declaration
+                    DWARFAbbreviationDeclaration(dw_tag_t tag, uint8_t has_children);
+    void            AddAttribute(const DWARFAttribute& attr)
+                    {
+                        m_attributes.push_back(attr);
+                    }
+
+    dw_uleb128_t    Code() const { return m_code; }
+    void            SetCode(dw_uleb128_t code) { m_code = code; }
+    dw_tag_t        Tag() const { return m_tag; }
+    bool            HasChildren() const { return m_has_children; }
+    size_t          NumAttributes() const { return m_attributes.size(); }
+    dw_attr_t       GetAttrByIndex(uint32_t idx) const { return m_attributes.size() > idx ? m_attributes[idx].get_attr() : 0; }
+    dw_form_t       GetFormByIndex(uint32_t idx) const { return m_attributes.size() > idx ? m_attributes[idx].get_form() : 0; }
+    bool            GetAttrAndFormByIndex(uint32_t idx, dw_attr_t& attr, dw_form_t& form) const
+                    {
+                        if (m_attributes.size() > idx)
+                        {
+                            m_attributes[idx].get(attr, form);
+                            return true;
+                        }
+                        attr = form = 0;
+                        return false;
+                    }
+
+                    // idx is assumed to be valid when calling GetAttrAndFormByIndexUnchecked()
+    void            GetAttrAndFormByIndexUnchecked(uint32_t idx, dw_attr_t& attr, dw_form_t& form) const
+                    {
+                        m_attributes[idx].get(attr, form);
+                    }
+    dw_form_t       GetFormByIndexUnchecked (uint32_t idx) const
+                    {
+                        return m_attributes[idx].get_form();
+                    }
+    void            CopyExcludingAddressAttributes(const DWARFAbbreviationDeclaration& abbr_decl, const uint32_t idx);
+    void            CopyChangingStringToStrp(
+                        const DWARFAbbreviationDeclaration& abbr_decl,
+                        const lldb_private::DataExtractor& debug_info_data,
+                        dw_offset_t debug_info_offset,
+                        const DWARFCompileUnit* cu,
+                        const uint32_t strp_min_len);
+    uint32_t        FindAttributeIndex(dw_attr_t attr) const;
+    bool            Extract(const lldb_private::DataExtractor& data, lldb::offset_t *offset_ptr);
+    bool            Extract(const lldb_private::DataExtractor& data, lldb::offset_t *offset_ptr, dw_uleb128_t code);
+//  void            Append(BinaryStreamBuf& out_buff) const;
+    bool            IsValid();
+    void            Dump(lldb_private::Stream *s) const;
+    bool            operator == (const DWARFAbbreviationDeclaration& rhs) const;
+//  DWARFAttribute::collection& Attributes() { return m_attributes; }
+    const DWARFAttribute::collection& Attributes() const { return m_attributes; }
+protected:
+    dw_uleb128_t        m_code;
+    dw_tag_t            m_tag;
+    uint8_t             m_has_children;
+    DWARFAttribute::collection m_attributes;
+};
+
+#endif  // liblldb_DWARFAbbreviationDeclaration_h_
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h b/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h
new file mode 100644
index 000000000000..8310b1dda5f1
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFAttribute.h
@@ -0,0 +1,45 @@
+//===-- DWARFAttribute.h ----------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SymbolFileDWARF_DWARFAttribute_h_
+#define SymbolFileDWARF_DWARFAttribute_h_
+
+#include "DWARFDefines.h"
+#include <vector>
+
+class DWARFAttribute
+{
+public:
+    DWARFAttribute(dw_attr_t attr, dw_form_t form) :
+        m_attr_form ( attr << 16 | form )
+    {
+    }
+
+    void        set(dw_attr_t attr, dw_form_t form) { m_attr_form = (attr << 16) | form; }
+    void        set_attr(dw_attr_t attr) { m_attr_form = (m_attr_form & 0x0000ffffu) | (attr << 16); }
+    void        set_form(dw_form_t form) { m_attr_form = (m_attr_form & 0xffff0000u) | form; }
+    dw_attr_t   get_attr() const { return m_attr_form >> 16; }
+    dw_form_t   get_form() const { return (dw_form_t)m_attr_form; }
+    void        get(dw_attr_t& attr, dw_form_t& form)  const
+    {
+        register uint32_t attr_form = m_attr_form;
+        attr = attr_form >> 16;
+        form = (dw_form_t)attr_form;
+    }
+    bool        operator == (const DWARFAttribute& rhs) const { return m_attr_form == rhs.m_attr_form; }
+    typedef std::vector<DWARFAttribute> collection;
+    typedef collection::iterator iterator;
+    typedef collection::const_iterator const_iterator;
+
+protected:
+    uint32_t    m_attr_form;    // Upper 16 bits is attribute, lower 16 bits is form
+};
+
+
+#endif  // SymbolFileDWARF_DWARFAttribute_h_
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
new file mode 100644
index 000000000000..493b3af6ecd1
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp
@@ -0,0 +1,1027 @@
+//===-- DWARFCompileUnit.cpp ------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFCompileUnit.h"
+
+#include "lldb/Core/Mangled.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/Timer.h"
+#include "lldb/Symbol/CompileUnit.h"
+#include "lldb/Symbol/LineTable.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Target/ObjCLanguageRuntime.h"
+
+#include "DWARFDebugAbbrev.h"
+#include "DWARFDebugAranges.h"
+#include "DWARFDebugInfo.h"
+#include "DWARFDIECollection.h"
+#include "DWARFFormValue.h"
+#include "LogChannelDWARF.h"
+#include "NameToDIE.h"
+#include "SymbolFileDWARF.h"
+#include "SymbolFileDWARFDebugMap.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace std;
+
+
+extern int g_verbose;
+
+DWARFCompileUnit::DWARFCompileUnit(SymbolFileDWARF* dwarf2Data) :
+    m_dwarf2Data    (dwarf2Data),
+    m_abbrevs       (NULL),
+    m_user_data     (NULL),
+    m_die_array     (),
+    m_func_aranges_ap (),
+    m_base_addr     (0),
+    m_offset        (DW_INVALID_OFFSET),
+    m_length        (0),
+    m_version       (0),
+    m_addr_size     (DWARFCompileUnit::GetDefaultAddressSize()),
+    m_producer      (eProducerInvalid),
+    m_producer_version_major (0),
+    m_producer_version_minor (0),
+    m_producer_version_update (0)
+{
+}
+
+void
+DWARFCompileUnit::Clear()
+{
+    m_offset        = DW_INVALID_OFFSET;
+    m_length        = 0;
+    m_version       = 0;
+    m_abbrevs       = NULL;
+    m_addr_size     = DWARFCompileUnit::GetDefaultAddressSize();
+    m_base_addr     = 0;
+    m_die_array.clear();
+    m_func_aranges_ap.reset();
+    m_user_data     = NULL;
+    m_producer      = eProducerInvalid;
+}
+
+bool
+DWARFCompileUnit::Extract(const DataExtractor &debug_info, lldb::offset_t *offset_ptr)
+{
+    Clear();
+
+    m_offset = *offset_ptr;
+
+    if (debug_info.ValidOffset(*offset_ptr))
+    {
+        dw_offset_t abbr_offset;
+        const DWARFDebugAbbrev *abbr = m_dwarf2Data->DebugAbbrev();
+        m_length        = debug_info.GetU32(offset_ptr);
+        m_version       = debug_info.GetU16(offset_ptr);
+        abbr_offset     = debug_info.GetU32(offset_ptr);
+        m_addr_size     = debug_info.GetU8 (offset_ptr);
+
+        bool length_OK = debug_info.ValidOffset(GetNextCompileUnitOffset()-1);
+        bool version_OK = SymbolFileDWARF::SupportedVersion(m_version);
+        bool abbr_offset_OK = m_dwarf2Data->get_debug_abbrev_data().ValidOffset(abbr_offset);
+        bool addr_size_OK = ((m_addr_size == 4) || (m_addr_size == 8));
+
+        if (length_OK && version_OK && addr_size_OK && abbr_offset_OK && abbr != NULL)
+        {
+            m_abbrevs = abbr->GetAbbreviationDeclarationSet(abbr_offset);
+            return true;
+        }
+
+        // reset the offset to where we tried to parse from if anything went wrong
+        *offset_ptr = m_offset;
+    }
+
+    return false;
+}
+
+
+dw_offset_t
+DWARFCompileUnit::Extract(lldb::offset_t offset, const DataExtractor& debug_info_data, const DWARFAbbreviationDeclarationSet* abbrevs)
+{
+    Clear();
+
+    m_offset = offset;
+
+    if (debug_info_data.ValidOffset(offset))
+    {
+        m_length        = debug_info_data.GetU32(&offset);
+        m_version       = debug_info_data.GetU16(&offset);
+        bool abbrevs_OK = debug_info_data.GetU32(&offset) == abbrevs->GetOffset();
+        m_abbrevs       = abbrevs;
+        m_addr_size     = debug_info_data.GetU8 (&offset);
+
+        bool version_OK = SymbolFileDWARF::SupportedVersion(m_version);
+        bool addr_size_OK = ((m_addr_size == 4) || (m_addr_size == 8));
+
+        if (version_OK && addr_size_OK && abbrevs_OK && debug_info_data.ValidOffset(offset))
+            return offset;
+    }
+    return DW_INVALID_OFFSET;
+}
+
+void
+DWARFCompileUnit::ClearDIEs(bool keep_compile_unit_die)
+{
+    if (m_die_array.size() > 1)
+    {
+        // std::vectors never get any smaller when resized to a smaller size,
+        // or when clear() or erase() are called, the size will report that it
+        // is smaller, but the memory allocated remains intact (call capacity()
+        // to see this). So we need to create a temporary vector and swap the
+        // contents which will cause just the internal pointers to be swapped
+        // so that when "tmp_array" goes out of scope, it will destroy the
+        // contents.
+
+        // Save at least the compile unit DIE
+        DWARFDebugInfoEntry::collection tmp_array;
+        m_die_array.swap(tmp_array);
+        if (keep_compile_unit_die)
+            m_die_array.push_back(tmp_array.front());
+    }
+}
+
+//----------------------------------------------------------------------
+// ParseCompileUnitDIEsIfNeeded
+//
+// Parses a compile unit and indexes its DIEs if it hasn't already been
+// done.
+//----------------------------------------------------------------------
+size_t
+DWARFCompileUnit::ExtractDIEsIfNeeded (bool cu_die_only)
+{
+    const size_t initial_die_array_size = m_die_array.size();
+    if ((cu_die_only && initial_die_array_size > 0) || initial_die_array_size > 1)
+        return 0; // Already parsed
+
+    Timer scoped_timer (__PRETTY_FUNCTION__,
+                        "%8.8x: DWARFCompileUnit::ExtractDIEsIfNeeded( cu_die_only = %i )",
+                        m_offset,
+                        cu_die_only);
+
+    // Set the offset to that of the first DIE and calculate the start of the
+    // next compilation unit header.
+    lldb::offset_t offset = GetFirstDIEOffset();
+    lldb::offset_t next_cu_offset = GetNextCompileUnitOffset();
+
+    DWARFDebugInfoEntry die;
+        // Keep a flat array of the DIE for binary lookup by DIE offset
+    if (!cu_die_only)
+    {
+        Log *log (LogChannelDWARF::GetLogIfAny(DWARF_LOG_DEBUG_INFO | DWARF_LOG_LOOKUPS));
+        if (log)
+        {
+            m_dwarf2Data->GetObjectFile()->GetModule()->LogMessageVerboseBacktrace (log,
+                                                                                    "DWARFCompileUnit::ExtractDIEsIfNeeded () for compile unit at .debug_info[0x%8.8x]",
+                                                                                    GetOffset());
+        }
+    }
+
+    uint32_t depth = 0;
+    // We are in our compile unit, parse starting at the offset
+    // we were told to parse
+    const DataExtractor& debug_info_data = m_dwarf2Data->get_debug_info_data();
+    std::vector<uint32_t> die_index_stack;
+    die_index_stack.reserve(32);
+    die_index_stack.push_back(0);
+    bool prev_die_had_children = false;
+    const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (GetAddressByteSize());
+    while (offset < next_cu_offset &&
+           die.FastExtract (debug_info_data, this, fixed_form_sizes, &offset))
+    {
+//        if (log)
+//            log->Printf("0x%8.8x: %*.*s%s%s",
+//                        die.GetOffset(),
+//                        depth * 2, depth * 2, "",
+//                        DW_TAG_value_to_name (die.Tag()),
+//                        die.HasChildren() ? " *" : "");
+
+        const bool null_die = die.IsNULL();
+        if (depth == 0)
+        {
+            uint64_t base_addr = die.GetAttributeValueAsUnsigned(m_dwarf2Data, this, DW_AT_low_pc, LLDB_INVALID_ADDRESS);
+            if (base_addr == LLDB_INVALID_ADDRESS)
+                base_addr = die.GetAttributeValueAsUnsigned(m_dwarf2Data, this, DW_AT_entry_pc, 0);
+            SetBaseAddress (base_addr);
+            if (initial_die_array_size == 0)
+                AddDIE (die);
+            if (cu_die_only)
+                return 1;
+        }
+        else
+        {
+            if (null_die)
+            {
+                if (prev_die_had_children)
+                {
+                    // This will only happen if a DIE says is has children
+                    // but all it contains is a NULL tag. Since we are removing
+                    // the NULL DIEs from the list (saves up to 25% in C++ code),
+                    // we need a way to let the DIE know that it actually doesn't
+                    // have children.
+                    if (!m_die_array.empty())
+                        m_die_array.back().SetEmptyChildren(true);
+                }
+            }
+            else
+            {
+                die.SetParentIndex(m_die_array.size() - die_index_stack[depth-1]);
+
+                if (die_index_stack.back())
+                    m_die_array[die_index_stack.back()].SetSiblingIndex(m_die_array.size()-die_index_stack.back());
+                
+                // Only push the DIE if it isn't a NULL DIE
+                    m_die_array.push_back(die);
+            }
+        }
+
+        if (null_die)
+        {
+            // NULL DIE.
+            if (!die_index_stack.empty())
+                die_index_stack.pop_back();
+
+            if (depth > 0)
+                --depth;
+            if (depth == 0)
+                break;  // We are done with this compile unit!
+
+            prev_die_had_children = false;
+        }
+        else
+        {
+            die_index_stack.back() = m_die_array.size() - 1;
+            // Normal DIE
+            const bool die_has_children = die.HasChildren();
+            if (die_has_children)
+            {
+                die_index_stack.push_back(0);
+                ++depth;
+            }
+            prev_die_had_children = die_has_children;
+        }
+    }
+
+    // Give a little bit of info if we encounter corrupt DWARF (our offset
+    // should always terminate at or before the start of the next compilation
+    // unit header).
+    if (offset > next_cu_offset)
+    {
+        m_dwarf2Data->GetObjectFile()->GetModule()->ReportWarning ("DWARF compile unit extends beyond its bounds cu 0x%8.8x at 0x%8.8" PRIx64 "\n",
+                                                                   GetOffset(), 
+                                                                   offset);
+    }
+
+    // Since std::vector objects will double their size, we really need to
+    // make a new array with the perfect size so we don't end up wasting
+    // space. So here we copy and swap to make sure we don't have any extra
+    // memory taken up.
+    
+    if (m_die_array.size () < m_die_array.capacity())
+    {
+        DWARFDebugInfoEntry::collection exact_size_die_array (m_die_array.begin(), m_die_array.end());
+        exact_size_die_array.swap (m_die_array);
+    }
+    Log *log (LogChannelDWARF::GetLogIfAll (DWARF_LOG_DEBUG_INFO | DWARF_LOG_VERBOSE));
+    if (log)
+    {
+        StreamString strm;
+        DWARFDebugInfoEntry::DumpDIECollection (strm, m_die_array);
+        log->PutCString (strm.GetString().c_str());
+    }
+
+    return m_die_array.size();
+}
+
+
+dw_offset_t
+DWARFCompileUnit::GetAbbrevOffset() const
+{
+    return m_abbrevs ? m_abbrevs->GetOffset() : DW_INVALID_OFFSET;
+}
+
+
+
+bool
+DWARFCompileUnit::Verify(Stream *s) const
+{
+    const DataExtractor& debug_info = m_dwarf2Data->get_debug_info_data();
+    bool valid_offset = debug_info.ValidOffset(m_offset);
+    bool length_OK = debug_info.ValidOffset(GetNextCompileUnitOffset()-1);
+    bool version_OK = SymbolFileDWARF::SupportedVersion(m_version);
+    bool abbr_offset_OK = m_dwarf2Data->get_debug_abbrev_data().ValidOffset(GetAbbrevOffset());
+    bool addr_size_OK = ((m_addr_size == 4) || (m_addr_size == 8));
+    bool verbose = s->GetVerbose();
+    if (valid_offset && length_OK && version_OK && addr_size_OK && abbr_offset_OK)
+    {
+        if (verbose)
+            s->Printf("    0x%8.8x: OK\n", m_offset);
+        return true;
+    }
+    else
+    {
+        s->Printf("    0x%8.8x: ", m_offset);
+
+        m_dwarf2Data->get_debug_info_data().Dump (s, m_offset, lldb::eFormatHex, 1, Size(), 32, LLDB_INVALID_ADDRESS, 0, 0);
+        s->EOL();
+        if (valid_offset)
+        {
+            if (!length_OK)
+                s->Printf("        The length (0x%8.8x) for this compile unit is too large for the .debug_info provided.\n", m_length);
+            if (!version_OK)
+                s->Printf("        The 16 bit compile unit header version is not supported.\n");
+            if (!abbr_offset_OK)
+                s->Printf("        The offset into the .debug_abbrev section (0x%8.8x) is not valid.\n", GetAbbrevOffset());
+            if (!addr_size_OK)
+                s->Printf("        The address size is unsupported: 0x%2.2x\n", m_addr_size);
+        }
+        else
+            s->Printf("        The start offset of the compile unit header in the .debug_info is invalid.\n");
+    }
+    return false;
+}
+
+
+void
+DWARFCompileUnit::Dump(Stream *s) const
+{
+    s->Printf("0x%8.8x: Compile Unit: length = 0x%8.8x, version = 0x%4.4x, abbr_offset = 0x%8.8x, addr_size = 0x%2.2x (next CU at {0x%8.8x})\n",
+                m_offset, m_length, m_version, GetAbbrevOffset(), m_addr_size, GetNextCompileUnitOffset());
+}
+
+
+static uint8_t g_default_addr_size = 4;
+
+uint8_t
+DWARFCompileUnit::GetAddressByteSize(const DWARFCompileUnit* cu)
+{
+    if (cu)
+        return cu->GetAddressByteSize();
+    return DWARFCompileUnit::GetDefaultAddressSize();
+}
+
+uint8_t
+DWARFCompileUnit::GetDefaultAddressSize()
+{
+    return g_default_addr_size;
+}
+
+void
+DWARFCompileUnit::SetDefaultAddressSize(uint8_t addr_size)
+{
+    g_default_addr_size = addr_size;
+}
+
+void
+DWARFCompileUnit::BuildAddressRangeTable (SymbolFileDWARF* dwarf2Data,
+                                          DWARFDebugAranges* debug_aranges,
+                                          bool clear_dies_if_already_not_parsed)
+{
+    // This function is usually called if there in no .debug_aranges section
+    // in order to produce a compile unit level set of address ranges that
+    // is accurate. If the DIEs weren't parsed, then we don't want all dies for
+    // all compile units to stay loaded when they weren't needed. So we can end
+    // up parsing the DWARF and then throwing them all away to keep memory usage
+    // down.
+    const bool clear_dies = ExtractDIEsIfNeeded (false) > 1;
+    
+    const DWARFDebugInfoEntry* die = DIE();
+    if (die)
+        die->BuildAddressRangeTable(dwarf2Data, this, debug_aranges);
+    
+    if (debug_aranges->IsEmpty())
+    {
+        // We got nothing from the functions, maybe we have a line tables only
+        // situation. Check the line tables and build the arange table from this.
+        SymbolContext sc;
+        sc.comp_unit = dwarf2Data->GetCompUnitForDWARFCompUnit(this);
+        if (sc.comp_unit)
+        {
+            SymbolFileDWARFDebugMap *debug_map_sym_file = m_dwarf2Data->GetDebugMapSymfile();
+            if (debug_map_sym_file == NULL)
+            {
+                LineTable *line_table = sc.comp_unit->GetLineTable();
+
+                if (line_table)
+                {
+                    LineTable::FileAddressRanges file_ranges;
+                    const bool append = true;
+                    const size_t num_ranges = line_table->GetContiguousFileAddressRanges (file_ranges, append);
+                    for (uint32_t idx=0; idx<num_ranges; ++idx)
+                    {
+                        const LineTable::FileAddressRanges::Entry &range = file_ranges.GetEntryRef(idx);
+                        debug_aranges->AppendRange(GetOffset(), range.GetRangeBase(), range.GetRangeEnd());
+                        printf ("0x%8.8x: [0x%16.16" PRIx64 " - 0x%16.16" PRIx64 ")\n", GetOffset(), range.GetRangeBase(), range.GetRangeEnd());
+                    }
+                }
+            }
+            else
+                debug_map_sym_file->AddOSOARanges(dwarf2Data,debug_aranges);
+        }
+    }
+    
+    // Keep memory down by clearing DIEs if this generate function
+    // caused them to be parsed
+    if (clear_dies)
+        ClearDIEs (true);
+
+}
+
+
+const DWARFDebugAranges &
+DWARFCompileUnit::GetFunctionAranges ()
+{
+    if (m_func_aranges_ap.get() == NULL)
+    {
+        m_func_aranges_ap.reset (new DWARFDebugAranges());
+        Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_ARANGES));
+
+        if (log)
+        {
+            m_dwarf2Data->GetObjectFile()->GetModule()->LogMessage (log,
+                                                                    "DWARFCompileUnit::GetFunctionAranges() for compile unit at .debug_info[0x%8.8x]",
+                                                                    GetOffset());
+        }
+        const DWARFDebugInfoEntry* die = DIE();
+        if (die)
+            die->BuildFunctionAddressRangeTable (m_dwarf2Data, this, m_func_aranges_ap.get());
+        const bool minimize = false;
+        m_func_aranges_ap->Sort(minimize);
+    }
+    return *m_func_aranges_ap.get();
+}
+
+bool
+DWARFCompileUnit::LookupAddress
+(
+    const dw_addr_t address,
+    DWARFDebugInfoEntry** function_die_handle,
+    DWARFDebugInfoEntry** block_die_handle
+)
+{
+    bool success = false;
+
+    if (function_die_handle != NULL && DIE())
+    {
+
+        const DWARFDebugAranges &func_aranges = GetFunctionAranges ();
+
+        // Re-check the aranges auto pointer contents in case it was created above
+        if (!func_aranges.IsEmpty())
+        {
+            *function_die_handle = GetDIEPtr(func_aranges.FindAddress(address));
+            if (*function_die_handle != NULL)
+            {
+                success = true;
+                if (block_die_handle != NULL)
+                {
+                    DWARFDebugInfoEntry* child = (*function_die_handle)->GetFirstChild();
+                    while (child)
+                    {
+                        if (child->LookupAddress(address, m_dwarf2Data, this, NULL, block_die_handle))
+                            break;
+                        child = child->GetSibling();
+                    }
+                }
+            }
+        }
+    }
+    return success;
+}
+
+//----------------------------------------------------------------------
+// Compare function DWARFDebugAranges::Range structures
+//----------------------------------------------------------------------
+static bool CompareDIEOffset (const DWARFDebugInfoEntry& die1, const DWARFDebugInfoEntry& die2)
+{
+    return die1.GetOffset() < die2.GetOffset();
+}
+
+//----------------------------------------------------------------------
+// GetDIEPtr()
+//
+// Get the DIE (Debug Information Entry) with the specified offset.
+//----------------------------------------------------------------------
+DWARFDebugInfoEntry*
+DWARFCompileUnit::GetDIEPtr(dw_offset_t die_offset)
+{
+    if (die_offset != DW_INVALID_OFFSET)
+    {
+        ExtractDIEsIfNeeded (false);
+        DWARFDebugInfoEntry compare_die;
+        compare_die.SetOffset(die_offset);
+        DWARFDebugInfoEntry::iterator end = m_die_array.end();
+        DWARFDebugInfoEntry::iterator pos = lower_bound(m_die_array.begin(), end, compare_die, CompareDIEOffset);
+        if (pos != end)
+        {
+            if (die_offset == (*pos).GetOffset())
+                return &(*pos);
+        }
+    }
+    return NULL;    // Not found in any compile units
+}
+
+//----------------------------------------------------------------------
+// GetDIEPtrContainingOffset()
+//
+// Get the DIE (Debug Information Entry) that contains the specified
+// .debug_info offset.
+//----------------------------------------------------------------------
+const DWARFDebugInfoEntry*
+DWARFCompileUnit::GetDIEPtrContainingOffset(dw_offset_t die_offset)
+{
+    if (die_offset != DW_INVALID_OFFSET)
+    {
+        ExtractDIEsIfNeeded (false);
+        DWARFDebugInfoEntry compare_die;
+        compare_die.SetOffset(die_offset);
+        DWARFDebugInfoEntry::iterator end = m_die_array.end();
+        DWARFDebugInfoEntry::iterator pos = lower_bound(m_die_array.begin(), end, compare_die, CompareDIEOffset);
+        if (pos != end)
+        {
+            if (die_offset >= (*pos).GetOffset())
+            {
+                DWARFDebugInfoEntry::iterator next = pos + 1;
+                if (next != end)
+                {
+                    if (die_offset < (*next).GetOffset())
+                        return &(*pos);
+                }
+            }
+        }
+    }
+    return NULL;    // Not found in any compile units
+}
+
+
+
+size_t
+DWARFCompileUnit::AppendDIEsWithTag (const dw_tag_t tag, DWARFDIECollection& dies, uint32_t depth) const
+{
+    size_t old_size = dies.Size();
+    DWARFDebugInfoEntry::const_iterator pos;
+    DWARFDebugInfoEntry::const_iterator end = m_die_array.end();
+    for (pos = m_die_array.begin(); pos != end; ++pos)
+    {
+        if (pos->Tag() == tag)
+            dies.Append (&(*pos));
+    }
+
+    // Return the number of DIEs added to the collection
+    return dies.Size() - old_size;
+}
+
+//void
+//DWARFCompileUnit::AddGlobalDIEByIndex (uint32_t die_idx)
+//{
+//    m_global_die_indexes.push_back (die_idx);
+//}
+//
+//
+//void
+//DWARFCompileUnit::AddGlobal (const DWARFDebugInfoEntry* die)
+//{
+//    // Indexes to all file level global and static variables
+//    m_global_die_indexes;
+//    
+//    if (m_die_array.empty())
+//        return;
+//    
+//    const DWARFDebugInfoEntry* first_die = &m_die_array[0];
+//    const DWARFDebugInfoEntry* end = first_die + m_die_array.size();
+//    if (first_die <= die && die < end)
+//        m_global_die_indexes.push_back (die - first_die);
+//}
+
+
+void
+DWARFCompileUnit::Index (const uint32_t cu_idx,
+                         NameToDIE& func_basenames,
+                         NameToDIE& func_fullnames,
+                         NameToDIE& func_methods,
+                         NameToDIE& func_selectors,
+                         NameToDIE& objc_class_selectors,
+                         NameToDIE& globals,
+                         NameToDIE& types,
+                         NameToDIE& namespaces)
+{
+    const DataExtractor* debug_str = &m_dwarf2Data->get_debug_str_data();
+
+    const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (GetAddressByteSize());
+
+    Log *log (LogChannelDWARF::GetLogIfAll (DWARF_LOG_LOOKUPS));
+    
+    if (log)
+    {
+        m_dwarf2Data->GetObjectFile()->GetModule()->LogMessage (log, 
+                                                                "DWARFCompileUnit::Index() for compile unit at .debug_info[0x%8.8x]",
+                                                                GetOffset());
+    }
+
+    DWARFDebugInfoEntry::const_iterator pos;
+    DWARFDebugInfoEntry::const_iterator begin = m_die_array.begin();
+    DWARFDebugInfoEntry::const_iterator end = m_die_array.end();
+    for (pos = begin; pos != end; ++pos)
+    {
+        const DWARFDebugInfoEntry &die = *pos;
+        
+        const dw_tag_t tag = die.Tag();
+    
+        switch (tag)
+        {
+        case DW_TAG_subprogram:
+        case DW_TAG_inlined_subroutine:
+        case DW_TAG_base_type:
+        case DW_TAG_class_type:
+        case DW_TAG_constant:
+        case DW_TAG_enumeration_type:
+        case DW_TAG_string_type:
+        case DW_TAG_subroutine_type:
+        case DW_TAG_structure_type:
+        case DW_TAG_union_type:
+        case DW_TAG_typedef:
+        case DW_TAG_namespace:
+        case DW_TAG_variable:
+        case DW_TAG_unspecified_type:
+            break;
+            
+        default:
+            continue;
+        }
+
+        DWARFDebugInfoEntry::Attributes attributes;
+        const char *name = NULL;
+        const char *mangled_cstr = NULL;
+        bool is_declaration = false;
+        //bool is_artificial = false;
+        bool has_address = false;
+        bool has_location = false;
+        bool is_global_or_static_variable = false;
+        
+        dw_offset_t specification_die_offset = DW_INVALID_OFFSET;
+        const size_t num_attributes = die.GetAttributes(m_dwarf2Data, this, fixed_form_sizes, attributes);
+        if (num_attributes > 0)
+        {
+            for (uint32_t i=0; i<num_attributes; ++i)
+            {
+                dw_attr_t attr = attributes.AttributeAtIndex(i);
+                DWARFFormValue form_value;
+                switch (attr)
+                {
+                case DW_AT_name:
+                    if (attributes.ExtractFormValueAtIndex(m_dwarf2Data, i, form_value))
+                        name = form_value.AsCString(debug_str);
+                    break;
+
+                case DW_AT_declaration:
+                    if (attributes.ExtractFormValueAtIndex(m_dwarf2Data, i, form_value))
+                        is_declaration = form_value.Unsigned() != 0;
+                    break;
+
+//                case DW_AT_artificial:
+//                    if (attributes.ExtractFormValueAtIndex(m_dwarf2Data, i, form_value))
+//                        is_artificial = form_value.Unsigned() != 0;
+//                    break;
+
+                case DW_AT_MIPS_linkage_name:
+                case DW_AT_linkage_name:
+                    if (attributes.ExtractFormValueAtIndex(m_dwarf2Data, i, form_value))
+                        mangled_cstr = form_value.AsCString(debug_str);                        
+                    break;
+
+                case DW_AT_low_pc:
+                case DW_AT_high_pc:
+                case DW_AT_ranges:
+                    has_address = true;
+                    break;
+
+                case DW_AT_entry_pc:
+                    has_address = true;
+                    break;
+
+                case DW_AT_location:
+                    has_location = true;
+                    if (tag == DW_TAG_variable)
+                    {
+                        const DWARFDebugInfoEntry* parent_die = die.GetParent();
+                        while ( parent_die != NULL )
+                        {
+                            switch (parent_die->Tag())
+                            {
+                            case DW_TAG_subprogram:
+                            case DW_TAG_lexical_block:
+                            case DW_TAG_inlined_subroutine:
+                                // Even if this is a function level static, we don't add it. We could theoretically
+                                // add these if we wanted to by introspecting into the DW_AT_location and seeing
+                                // if the location describes a hard coded address, but we dont want the performance
+                                // penalty of that right now.
+                                is_global_or_static_variable = false;
+//                              if (attributes.ExtractFormValueAtIndex(dwarf2Data, i, form_value))
+//                              {
+//                                  // If we have valid block data, then we have location expression bytes
+//                                  // that are fixed (not a location list).
+//                                  const uint8_t *block_data = form_value.BlockData();
+//                                  if (block_data)
+//                                  {
+//                                      uint32_t block_length = form_value.Unsigned();
+//                                      if (block_length == 1 + attributes.CompileUnitAtIndex(i)->GetAddressByteSize())
+//                                      {
+//                                          if (block_data[0] == DW_OP_addr)
+//                                              add_die = true;
+//                                      }
+//                                  }
+//                              }
+                                parent_die = NULL;  // Terminate the while loop.
+                                break;
+
+                            case DW_TAG_compile_unit:
+                                is_global_or_static_variable = true;
+                                parent_die = NULL;  // Terminate the while loop.
+                                break;
+
+                            default:
+                                parent_die = parent_die->GetParent();   // Keep going in the while loop.
+                                break;
+                            }
+                        }
+                    }
+                    break;
+                    
+                case DW_AT_specification:
+                    if (attributes.ExtractFormValueAtIndex(m_dwarf2Data, i, form_value))
+                        specification_die_offset = form_value.Reference(this);
+                    break;
+                }
+            }
+        }
+
+        switch (tag)
+        {
+        case DW_TAG_subprogram:
+            if (has_address)
+            {
+                if (name)
+                {
+                    // Note, this check is also done in ParseMethodName, but since this is a hot loop, we do the
+                    // simple inlined check outside the call.
+                    ObjCLanguageRuntime::MethodName objc_method(name, true);
+                    if (objc_method.IsValid(true))
+                    {
+                        ConstString objc_class_name_with_category (objc_method.GetClassNameWithCategory());
+                        ConstString objc_selector_name (objc_method.GetSelector());
+                        ConstString objc_fullname_no_category_name (objc_method.GetFullNameWithoutCategory(true));
+                        ConstString objc_class_name_no_category (objc_method.GetClassName());
+                        func_fullnames.Insert (ConstString(name), die.GetOffset());
+                        if (objc_class_name_with_category)
+                            objc_class_selectors.Insert(objc_class_name_with_category, die.GetOffset());
+                        if (objc_class_name_no_category && objc_class_name_no_category != objc_class_name_with_category)
+                            objc_class_selectors.Insert(objc_class_name_no_category, die.GetOffset());
+                        if (objc_selector_name)
+                            func_selectors.Insert (objc_selector_name, die.GetOffset());
+                        if (objc_fullname_no_category_name)
+                            func_fullnames.Insert (objc_fullname_no_category_name, die.GetOffset());
+                    }
+                    // If we have a mangled name, then the DW_AT_name attribute
+                    // is usually the method name without the class or any parameters
+                    const DWARFDebugInfoEntry *parent = die.GetParent();
+                    bool is_method = false;
+                    if (parent)
+                    {
+                        dw_tag_t parent_tag = parent->Tag();
+                        if (parent_tag == DW_TAG_class_type || parent_tag == DW_TAG_structure_type)
+                        {
+                            is_method = true;
+                        }
+                        else
+                        {
+                            if (specification_die_offset != DW_INVALID_OFFSET)
+                            {
+                                const DWARFDebugInfoEntry *specification_die = m_dwarf2Data->DebugInfo()->GetDIEPtr (specification_die_offset, NULL);
+                                if (specification_die)
+                                {
+                                    parent = specification_die->GetParent();
+                                    if (parent)
+                                    {
+                                        parent_tag = parent->Tag();
+                                    
+                                        if (parent_tag == DW_TAG_class_type || parent_tag == DW_TAG_structure_type)
+                                            is_method = true;
+                                    }
+                                }
+                            }
+                        }
+                    }
+
+
+                    if (is_method)
+                        func_methods.Insert (ConstString(name), die.GetOffset());
+                    else
+                        func_basenames.Insert (ConstString(name), die.GetOffset());
+
+                    if (!is_method && !mangled_cstr && !objc_method.IsValid(true))
+                        func_fullnames.Insert (ConstString(name), die.GetOffset());
+                }
+                if (mangled_cstr)
+                {
+                    // Make sure our mangled name isn't the same string table entry
+                    // as our name. If it starts with '_', then it is ok, else compare
+                    // the string to make sure it isn't the same and we don't end up
+                    // with duplicate entries
+                    if (name != mangled_cstr && ((mangled_cstr[0] == '_') || (name && ::strcmp(name, mangled_cstr) != 0)))
+                    {
+                        Mangled mangled (ConstString(mangled_cstr), true);
+                        func_fullnames.Insert (mangled.GetMangledName(), die.GetOffset());
+                        if (mangled.GetDemangledName())
+                            func_fullnames.Insert (mangled.GetDemangledName(), die.GetOffset());
+                    }
+                }
+            }
+            break;
+
+        case DW_TAG_inlined_subroutine:
+            if (has_address)
+            {
+                if (name)
+                    func_basenames.Insert (ConstString(name), die.GetOffset());
+                if (mangled_cstr)
+                {
+                    // Make sure our mangled name isn't the same string table entry
+                    // as our name. If it starts with '_', then it is ok, else compare
+                    // the string to make sure it isn't the same and we don't end up
+                    // with duplicate entries
+                    if (name != mangled_cstr && ((mangled_cstr[0] == '_') || (::strcmp(name, mangled_cstr) != 0)))
+                    {
+                        Mangled mangled (ConstString(mangled_cstr), true);
+                        func_fullnames.Insert (mangled.GetMangledName(), die.GetOffset());
+                        if (mangled.GetDemangledName())
+                            func_fullnames.Insert (mangled.GetDemangledName(), die.GetOffset());
+                    }
+                }
+                else
+                    func_fullnames.Insert (ConstString(name), die.GetOffset());
+            }
+            break;
+        
+        case DW_TAG_base_type:
+        case DW_TAG_class_type:
+        case DW_TAG_constant:
+        case DW_TAG_enumeration_type:
+        case DW_TAG_string_type:
+        case DW_TAG_subroutine_type:
+        case DW_TAG_structure_type:
+        case DW_TAG_union_type:
+        case DW_TAG_typedef:
+        case DW_TAG_unspecified_type:
+            if (name && is_declaration == false)
+            {
+                types.Insert (ConstString(name), die.GetOffset());
+            }
+            break;
+
+        case DW_TAG_namespace:
+            if (name)
+                namespaces.Insert (ConstString(name), die.GetOffset());
+            break;
+
+        case DW_TAG_variable:
+            if (name && has_location && is_global_or_static_variable)
+            {
+                globals.Insert (ConstString(name), die.GetOffset());
+                // Be sure to include variables by their mangled and demangled
+                // names if they have any since a variable can have a basename
+                // "i", a mangled named "_ZN12_GLOBAL__N_11iE" and a demangled 
+                // mangled name "(anonymous namespace)::i"...
+                
+                // Make sure our mangled name isn't the same string table entry
+                // as our name. If it starts with '_', then it is ok, else compare
+                // the string to make sure it isn't the same and we don't end up
+                // with duplicate entries
+                if (mangled_cstr && name != mangled_cstr && ((mangled_cstr[0] == '_') || (::strcmp(name, mangled_cstr) != 0)))
+                {
+                    Mangled mangled (ConstString(mangled_cstr), true);
+                    globals.Insert (mangled.GetMangledName(), die.GetOffset());
+                    if (mangled.GetDemangledName())
+                        globals.Insert (mangled.GetDemangledName(), die.GetOffset());
+                }
+            }
+            break;
+            
+        default:
+            continue;
+        }
+    }
+}
+
+bool
+DWARFCompileUnit::Supports_unnamed_objc_bitfields ()
+{
+    if (GetProducer() == eProducerClang)
+    {
+        const uint32_t major_version = GetProducerVersionMajor();
+        if (major_version > 425 || (major_version == 425 && GetProducerVersionUpdate() >= 13))
+            return true;
+        else
+            return false;
+    }
+    return true; // Assume all other compilers didn't have incorrect ObjC bitfield info
+}
+
+bool
+DWARFCompileUnit::Supports_DW_AT_APPLE_objc_complete_type ()
+{
+    if (GetProducer() == eProducerLLVMGCC)
+        return false;
+    return true;
+}
+
+bool
+DWARFCompileUnit::DW_AT_decl_file_attributes_are_invalid()
+{
+    // llvm-gcc makes completely invalid decl file attributes and won't ever
+    // be fixed, so we need to know to ignore these.
+    return GetProducer() == eProducerLLVMGCC;
+}
+
+void
+DWARFCompileUnit::ParseProducerInfo ()
+{
+    m_producer_version_major = UINT32_MAX;
+    m_producer_version_minor = UINT32_MAX;
+    m_producer_version_update = UINT32_MAX;
+
+    const DWARFDebugInfoEntry *die = GetCompileUnitDIEOnly();
+    if (die)
+    {
+
+        const char *producer_cstr = die->GetAttributeValueAsString(m_dwarf2Data, this, DW_AT_producer, NULL);
+        if (producer_cstr)
+        {
+            RegularExpression llvm_gcc_regex("^4\\.[012]\\.[01] \\(Based on Apple Inc\\. build [0-9]+\\) \\(LLVM build [\\.0-9]+\\)$");
+            if (llvm_gcc_regex.Execute (producer_cstr))
+            {
+                m_producer = eProducerLLVMGCC;
+            }
+            else if (strstr(producer_cstr, "clang"))
+            {
+                static RegularExpression g_clang_version_regex("clang-([0-9]+)\\.([0-9]+)\\.([0-9]+)");
+                RegularExpression::Match regex_match(3);
+                if (g_clang_version_regex.Execute (producer_cstr, &regex_match))
+                {
+                    std::string str;
+                    if (regex_match.GetMatchAtIndex (producer_cstr, 1, str))
+                        m_producer_version_major = Args::StringToUInt32(str.c_str(), UINT32_MAX, 10);
+                    if (regex_match.GetMatchAtIndex (producer_cstr, 2, str))
+                        m_producer_version_minor = Args::StringToUInt32(str.c_str(), UINT32_MAX, 10);
+                    if (regex_match.GetMatchAtIndex (producer_cstr, 3, str))
+                        m_producer_version_update = Args::StringToUInt32(str.c_str(), UINT32_MAX, 10);
+                }
+                m_producer = eProducerClang;
+            }
+            else if (strstr(producer_cstr, "GNU"))
+                m_producer = eProducerGCC;
+        }
+    }
+    if (m_producer == eProducerInvalid)
+        m_producer = eProcucerOther;
+}
+
+DWARFCompileUnit::Producer
+DWARFCompileUnit::GetProducer ()
+{
+    if (m_producer == eProducerInvalid)
+        ParseProducerInfo ();
+    return m_producer;
+}
+
+
+uint32_t
+DWARFCompileUnit::GetProducerVersionMajor()
+{
+    if (m_producer_version_major == 0)
+        ParseProducerInfo ();
+    return m_producer_version_major;
+}
+
+uint32_t
+DWARFCompileUnit::GetProducerVersionMinor()
+{
+    if (m_producer_version_minor == 0)
+        ParseProducerInfo ();
+    return m_producer_version_minor;
+}
+
+uint32_t
+DWARFCompileUnit::GetProducerVersionUpdate()
+{
+    if (m_producer_version_update == 0)
+        ParseProducerInfo ();
+    return m_producer_version_update;
+}
+
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h
new file mode 100644
index 000000000000..9fee0a2d2236
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.h
@@ -0,0 +1,210 @@
+//===-- DWARFCompileUnit.h --------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SymbolFileDWARF_DWARFCompileUnit_h_
+#define SymbolFileDWARF_DWARFCompileUnit_h_
+
+#include "DWARFDebugInfoEntry.h"
+#include "SymbolFileDWARF.h"
+
+class NameToDIE;
+
+class DWARFCompileUnit
+{
+public:
+    enum Producer 
+    {
+        eProducerInvalid = 0,
+        eProducerClang,
+        eProducerGCC,
+        eProducerLLVMGCC,
+        eProcucerOther
+    };
+
+    DWARFCompileUnit(SymbolFileDWARF* dwarf2Data);
+
+    bool        Extract(const lldb_private::DataExtractor &debug_info, lldb::offset_t *offset_ptr);
+    dw_offset_t Extract(lldb::offset_t offset, const lldb_private::DataExtractor& debug_info_data, const DWARFAbbreviationDeclarationSet* abbrevs);
+    size_t      ExtractDIEsIfNeeded (bool cu_die_only);
+    bool        LookupAddress(
+                    const dw_addr_t address,
+                    DWARFDebugInfoEntry** function_die,
+                    DWARFDebugInfoEntry** block_die);
+
+    size_t      AppendDIEsWithTag (const dw_tag_t tag, DWARFDIECollection& matching_dies, uint32_t depth = UINT32_MAX) const;
+    void        Clear();
+    bool        Verify(lldb_private::Stream *s) const;
+    void        Dump(lldb_private::Stream *s) const;
+    dw_offset_t GetOffset() const { return m_offset; }
+    uint32_t    Size() const { return 11; /* Size in bytes of the compile unit header */ }
+    bool        ContainsDIEOffset(dw_offset_t die_offset) const { return die_offset >= GetFirstDIEOffset() && die_offset < GetNextCompileUnitOffset(); }
+    dw_offset_t GetFirstDIEOffset() const { return m_offset + Size(); }
+    dw_offset_t GetNextCompileUnitOffset() const { return m_offset + m_length + 4; }
+    size_t      GetDebugInfoSize() const { return m_length + 4 - Size(); /* Size in bytes of the .debug_info data associated with this compile unit. */ }
+    uint32_t    GetLength() const { return m_length; }
+    uint16_t    GetVersion() const { return m_version; }
+    const DWARFAbbreviationDeclarationSet*  GetAbbreviations() const { return m_abbrevs; }
+    dw_offset_t GetAbbrevOffset() const;
+    uint8_t     GetAddressByteSize() const { return m_addr_size; }
+    dw_addr_t   GetBaseAddress() const { return m_base_addr; }
+    void        ClearDIEs(bool keep_compile_unit_die);
+    void        BuildAddressRangeTable (SymbolFileDWARF* dwarf2Data,
+                                        DWARFDebugAranges* debug_aranges,
+                                        bool clear_dies_if_already_not_parsed);
+
+    void
+    SetBaseAddress(dw_addr_t base_addr)
+    {
+        m_base_addr = base_addr;
+    }
+
+    const DWARFDebugInfoEntry*
+    GetCompileUnitDIEOnly()
+    {
+        ExtractDIEsIfNeeded (true);
+        if (m_die_array.empty())
+            return NULL;
+        return &m_die_array[0];
+    }
+
+    const DWARFDebugInfoEntry*
+    DIE()
+    {
+        ExtractDIEsIfNeeded (false);
+        if (m_die_array.empty())
+            return NULL;
+        return &m_die_array[0];
+    }
+
+    void
+    AddDIE (DWARFDebugInfoEntry& die)
+    {
+        // The average bytes per DIE entry has been seen to be
+        // around 14-20 so lets pre-reserve half of that since
+        // we are now stripping the NULL tags. 
+
+        // Only reserve the memory if we are adding children of
+        // the main compile unit DIE. The compile unit DIE is always
+        // the first entry, so if our size is 1, then we are adding
+        // the first compile unit child DIE and should reserve
+        // the memory.
+        if (m_die_array.empty())
+            m_die_array.reserve(GetDebugInfoSize() / 24);
+        m_die_array.push_back(die);
+    }
+
+    bool
+    HasDIEsParsed () const
+    {
+        return m_die_array.size() > 1;
+    }
+
+    DWARFDebugInfoEntry*
+    GetDIEAtIndexUnchecked (uint32_t idx)
+    {
+        return &m_die_array[idx];
+    }
+
+    DWARFDebugInfoEntry*
+    GetDIEPtr (dw_offset_t die_offset);
+
+    const DWARFDebugInfoEntry*
+    GetDIEPtrContainingOffset (dw_offset_t die_offset);
+
+    static uint8_t
+    GetAddressByteSize(const DWARFCompileUnit* cu);
+
+    static uint8_t
+    GetDefaultAddressSize();
+
+    static void
+    SetDefaultAddressSize(uint8_t addr_size);
+
+    void *
+    GetUserData() const
+    {
+        return m_user_data;
+    }
+
+    void
+    SetUserData(void *d)
+    {
+        m_user_data = d;
+    }
+
+    bool
+    Supports_DW_AT_APPLE_objc_complete_type ();
+
+    bool
+    DW_AT_decl_file_attributes_are_invalid();
+
+    bool
+    Supports_unnamed_objc_bitfields ();
+
+//    void
+//    AddGlobalDIEByIndex (uint32_t die_idx);
+//
+//    void
+//    AddGlobal (const DWARFDebugInfoEntry* die);
+//
+    void
+    Index (const uint32_t cu_idx,
+           NameToDIE& func_basenames,
+           NameToDIE& func_fullnames,
+           NameToDIE& func_methods,
+           NameToDIE& func_selectors,
+           NameToDIE& objc_class_selectors,
+           NameToDIE& globals,
+           NameToDIE& types,
+           NameToDIE& namespaces);
+
+    const DWARFDebugAranges &
+    GetFunctionAranges ();
+
+    SymbolFileDWARF*
+    GetSymbolFileDWARF () const
+    {
+        return m_dwarf2Data;
+    }
+    
+    Producer
+    GetProducer ();
+    
+    uint32_t
+    GetProducerVersionMajor();
+
+    uint32_t
+    GetProducerVersionMinor();
+    
+    uint32_t
+    GetProducerVersionUpdate();
+
+protected:
+    SymbolFileDWARF*    m_dwarf2Data;
+    const DWARFAbbreviationDeclarationSet *m_abbrevs;
+    void *              m_user_data;
+    DWARFDebugInfoEntry::collection m_die_array;    // The compile unit debug information entry item
+    std::unique_ptr<DWARFDebugAranges> m_func_aranges_ap;   // A table similar to the .debug_aranges table, but this one points to the exact DW_TAG_subprogram DIEs
+    dw_addr_t           m_base_addr;
+    dw_offset_t         m_offset;
+    uint32_t            m_length;
+    uint16_t            m_version;
+    uint8_t             m_addr_size;
+    Producer            m_producer;
+    uint32_t            m_producer_version_major;
+    uint32_t            m_producer_version_minor;
+    uint32_t            m_producer_version_update;
+    
+    void
+    ParseProducerInfo ();
+private:
+    DISALLOW_COPY_AND_ASSIGN (DWARFCompileUnit);
+};
+
+#endif  // SymbolFileDWARF_DWARFCompileUnit_h_
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDIECollection.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDIECollection.cpp
new file mode 100644
index 000000000000..1beb75d33642
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDIECollection.cpp
@@ -0,0 +1,62 @@
+//===-- DWARFDIECollection.cpp ----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFDIECollection.h"
+
+#include <algorithm>
+
+#include "lldb/Core/Stream.h"
+
+#include "DWARFDebugInfoEntry.h"
+
+using namespace lldb_private;
+using namespace std;
+
+bool
+DWARFDIECollection::Insert(const DWARFDebugInfoEntry *die)
+{
+    iterator end_pos = m_dies.end();
+    iterator insert_pos = upper_bound(m_dies.begin(), end_pos, die);
+    if (insert_pos != end_pos && (*insert_pos == die))
+        return false;
+    m_dies.insert(insert_pos, die);
+    return true;
+}
+
+void
+DWARFDIECollection::Append (const DWARFDebugInfoEntry *die)
+{
+    m_dies.push_back (die);
+}
+
+const DWARFDebugInfoEntry *
+DWARFDIECollection::GetDIEPtrAtIndex(uint32_t idx) const
+{
+    if (idx < m_dies.size())
+        return m_dies[idx];
+    return NULL;
+}
+
+
+size_t
+DWARFDIECollection::Size() const
+{
+    return m_dies.size();
+}
+
+void
+DWARFDIECollection::Dump(Stream *s, const char* title) const
+{
+    if (title && title[0] != '\0')
+        s->Printf( "%s\n", title);
+    const_iterator end_pos = m_dies.end();
+    const_iterator pos;
+    for (pos = m_dies.begin(); pos != end_pos; ++pos)
+        s->Printf( "0x%8.8x\n", (*pos)->GetOffset());
+}
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDIECollection.h b/source/Plugins/SymbolFile/DWARF/DWARFDIECollection.h
new file mode 100644
index 000000000000..173d0a5604d0
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDIECollection.h
@@ -0,0 +1,51 @@
+//===-- DWARFDIECollection.h ------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SymbolFileDWARF_DWARFDIECollection_h_
+#define SymbolFileDWARF_DWARFDIECollection_h_
+
+#include "SymbolFileDWARF.h"
+#include <vector>
+
+class DWARFDIECollection
+{
+public:
+    DWARFDIECollection() :
+        m_dies()
+    {
+    }
+    ~DWARFDIECollection()
+    {
+    }
+
+    void
+    Append (const DWARFDebugInfoEntry *die);
+
+    void
+    Dump(lldb_private::Stream *s, const char* title) const;
+
+    const DWARFDebugInfoEntry*
+    GetDIEPtrAtIndex(uint32_t idx) const;
+
+    bool
+    Insert(const DWARFDebugInfoEntry *die);
+
+    size_t
+    Size() const;
+
+protected:
+    typedef std::vector<const DWARFDebugInfoEntry *>    collection;
+    typedef collection::iterator                iterator;
+    typedef collection::const_iterator          const_iterator;
+
+    collection m_dies;  // Ordered list of die offsets
+};
+
+
+#endif  // SymbolFileDWARF_DWARFDIECollection_h_
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.cpp
new file mode 100644
index 000000000000..47657d5089b2
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.cpp
@@ -0,0 +1,202 @@
+//===-- DWARFDebugAbbrev.cpp ------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFDebugAbbrev.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Stream.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace std;
+
+//----------------------------------------------------------------------
+// DWARFAbbreviationDeclarationSet::Clear()
+//----------------------------------------------------------------------
+void
+DWARFAbbreviationDeclarationSet::Clear()
+{
+    m_idx_offset = 0;
+    m_decls.clear();
+}
+
+
+//----------------------------------------------------------------------
+// DWARFAbbreviationDeclarationSet::Extract()
+//----------------------------------------------------------------------
+bool
+DWARFAbbreviationDeclarationSet::Extract(const DataExtractor& data, lldb::offset_t *offset_ptr)
+{
+    const lldb::offset_t begin_offset = *offset_ptr;
+    m_offset = begin_offset;
+    Clear();
+    DWARFAbbreviationDeclaration abbrevDeclaration;
+    dw_uleb128_t prev_abbr_code = 0;
+    while (abbrevDeclaration.Extract(data, offset_ptr))
+    {
+        m_decls.push_back(abbrevDeclaration);
+        if (m_idx_offset == 0)
+            m_idx_offset = abbrevDeclaration.Code();
+        else
+        {
+            if (prev_abbr_code + 1 != abbrevDeclaration.Code())
+                m_idx_offset = UINT32_MAX;    // Out of order indexes, we can't do O(1) lookups...
+        }
+        prev_abbr_code = abbrevDeclaration.Code();
+    }
+    return begin_offset != *offset_ptr;
+}
+
+
+//----------------------------------------------------------------------
+// DWARFAbbreviationDeclarationSet::Dump()
+//----------------------------------------------------------------------
+void
+DWARFAbbreviationDeclarationSet::Dump(Stream *s) const
+{
+    std::for_each (m_decls.begin(), m_decls.end(), bind2nd(std::mem_fun_ref(&DWARFAbbreviationDeclaration::Dump),s));
+}
+
+
+//----------------------------------------------------------------------
+// DWARFAbbreviationDeclarationSet::GetAbbreviationDeclaration()
+//----------------------------------------------------------------------
+const DWARFAbbreviationDeclaration*
+DWARFAbbreviationDeclarationSet::GetAbbreviationDeclaration(dw_uleb128_t abbrCode) const
+{
+    if (m_idx_offset == UINT32_MAX)
+    {
+        DWARFAbbreviationDeclarationCollConstIter pos;
+        DWARFAbbreviationDeclarationCollConstIter end = m_decls.end();
+        for (pos = m_decls.begin(); pos != end; ++pos)
+        {
+            if (pos->Code() == abbrCode)
+                return &(*pos);
+        }
+    }
+    else
+    {
+        uint32_t idx = abbrCode - m_idx_offset;
+        if (idx < m_decls.size())
+            return &m_decls[idx];
+    }
+    return NULL;
+}
+
+//----------------------------------------------------------------------
+// DWARFAbbreviationDeclarationSet::AppendAbbrevDeclSequential()
+//
+// Append an abbreviation declaration with a sequential code for O(n)
+// lookups. Handy when creating an DWARFAbbreviationDeclarationSet.
+//----------------------------------------------------------------------
+dw_uleb128_t
+DWARFAbbreviationDeclarationSet::AppendAbbrevDeclSequential(const DWARFAbbreviationDeclaration& abbrevDecl)
+{
+    // Get the next abbreviation code based on our current array size
+    dw_uleb128_t code = m_decls.size()+1;
+
+    // Push the new declaration on the back
+    m_decls.push_back(abbrevDecl);
+
+    // Update the code for this new declaration
+    m_decls.back().SetCode(code);
+
+    return code;    // return the new abbreviation code!
+}
+
+
+//----------------------------------------------------------------------
+// Encode
+//
+// Encode the abbreviation table onto the end of the buffer provided
+// into a byte representation as would be found in a ".debug_abbrev"
+// debug information section.
+//----------------------------------------------------------------------
+//void
+//DWARFAbbreviationDeclarationSet::Encode(BinaryStreamBuf& debug_abbrev_buf) const
+//{
+//  DWARFAbbreviationDeclarationCollConstIter pos;
+//  DWARFAbbreviationDeclarationCollConstIter end = m_decls.end();
+//  for (pos = m_decls.begin(); pos != end; ++pos)
+//      pos->Append(debug_abbrev_buf);
+//  debug_abbrev_buf.Append8(0);
+//}
+
+
+//----------------------------------------------------------------------
+// DWARFDebugAbbrev constructor
+//----------------------------------------------------------------------
+DWARFDebugAbbrev::DWARFDebugAbbrev() :
+    m_abbrevCollMap(),
+    m_prev_abbr_offset_pos(m_abbrevCollMap.end())
+{
+}
+
+
+//----------------------------------------------------------------------
+// DWARFDebugAbbrev::Parse()
+//----------------------------------------------------------------------
+void
+DWARFDebugAbbrev::Parse(const DataExtractor& data)
+{
+    lldb::offset_t offset = 0;
+
+    while (data.ValidOffset(offset))
+    {
+        uint32_t initial_cu_offset = offset;
+        DWARFAbbreviationDeclarationSet abbrevDeclSet;
+
+        if (abbrevDeclSet.Extract(data, &offset))
+            m_abbrevCollMap[initial_cu_offset] = abbrevDeclSet;
+        else
+            break;
+    }
+    m_prev_abbr_offset_pos = m_abbrevCollMap.end();
+}
+
+//----------------------------------------------------------------------
+// DWARFDebugAbbrev::Dump()
+//----------------------------------------------------------------------
+void
+DWARFDebugAbbrev::Dump(Stream *s) const
+{
+    if (m_abbrevCollMap.empty())
+    {
+        s->PutCString("< EMPTY >\n");
+        return;
+    }
+
+    DWARFAbbreviationDeclarationCollMapConstIter pos;
+    for (pos = m_abbrevCollMap.begin(); pos != m_abbrevCollMap.end(); ++pos)
+    {
+        s->Printf("Abbrev table for offset: 0x%8.8x\n", pos->first);
+        pos->second.Dump(s);
+    }
+}
+
+
+//----------------------------------------------------------------------
+// DWARFDebugAbbrev::GetAbbreviationDeclarationSet()
+//----------------------------------------------------------------------
+const DWARFAbbreviationDeclarationSet*
+DWARFDebugAbbrev::GetAbbreviationDeclarationSet(dw_offset_t cu_abbr_offset) const
+{
+    DWARFAbbreviationDeclarationCollMapConstIter end = m_abbrevCollMap.end();
+    DWARFAbbreviationDeclarationCollMapConstIter pos;
+    if (m_prev_abbr_offset_pos != end && m_prev_abbr_offset_pos->first == cu_abbr_offset)
+        return &(m_prev_abbr_offset_pos->second);
+    else
+    {
+        pos = m_abbrevCollMap.find(cu_abbr_offset);
+        m_prev_abbr_offset_pos = pos;
+    }
+
+    if (pos != m_abbrevCollMap.end())
+        return &(pos->second);
+    return NULL;
+}
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.h
new file mode 100644
index 000000000000..eba439928a2c
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugAbbrev.h
@@ -0,0 +1,74 @@
+//===-- DWARFDebugAbbrev.h --------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SymbolFileDWARF_DWARFDebugAbbrev_h_
+#define SymbolFileDWARF_DWARFDebugAbbrev_h_
+
+#include <list>
+#include <map>
+
+#include "lldb/lldb-private.h"
+
+#include "DWARFDefines.h"
+#include "DWARFAbbreviationDeclaration.h"
+
+typedef std::vector<DWARFAbbreviationDeclaration>               DWARFAbbreviationDeclarationColl;
+typedef DWARFAbbreviationDeclarationColl::iterator              DWARFAbbreviationDeclarationCollIter;
+typedef DWARFAbbreviationDeclarationColl::const_iterator        DWARFAbbreviationDeclarationCollConstIter;
+
+
+class DWARFAbbreviationDeclarationSet
+{
+public:
+    DWARFAbbreviationDeclarationSet() :
+        m_offset(DW_INVALID_OFFSET),
+        m_idx_offset(0),
+        m_decls()
+        {
+        }
+
+    DWARFAbbreviationDeclarationSet(dw_offset_t offset, uint32_t idx_offset) :
+        m_offset(offset),
+        m_idx_offset(idx_offset),
+        m_decls()
+        {
+        }
+
+    void Clear();
+    dw_offset_t GetOffset() const { return m_offset; }
+    void Dump(lldb_private::Stream *s) const;
+    bool Extract(const lldb_private::DataExtractor& data, lldb::offset_t *offset_ptr);
+    //void Encode(BinaryStreamBuf& debug_abbrev_buf) const;
+    dw_uleb128_t AppendAbbrevDeclSequential(const DWARFAbbreviationDeclaration& abbrevDecl);
+
+    const DWARFAbbreviationDeclaration* GetAbbreviationDeclaration(dw_uleb128_t abbrCode) const;
+private:
+    dw_offset_t m_offset;
+    uint32_t m_idx_offset;
+    std::vector<DWARFAbbreviationDeclaration> m_decls;
+};
+
+typedef std::map<dw_offset_t, DWARFAbbreviationDeclarationSet> DWARFAbbreviationDeclarationCollMap;
+typedef DWARFAbbreviationDeclarationCollMap::iterator DWARFAbbreviationDeclarationCollMapIter;
+typedef DWARFAbbreviationDeclarationCollMap::const_iterator DWARFAbbreviationDeclarationCollMapConstIter;
+
+
+class DWARFDebugAbbrev
+{
+public:
+    DWARFDebugAbbrev();
+    const DWARFAbbreviationDeclarationSet*  GetAbbreviationDeclarationSet(dw_offset_t cu_abbr_offset) const;
+    void Dump(lldb_private::Stream *s) const;
+    void Parse(const lldb_private::DataExtractor& data);
+protected:
+    DWARFAbbreviationDeclarationCollMap m_abbrevCollMap;
+    mutable DWARFAbbreviationDeclarationCollMapConstIter m_prev_abbr_offset_pos;
+};
+
+#endif  // SymbolFileDWARF_DWARFDebugAbbrev_h_
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.cpp
new file mode 100644
index 000000000000..b1eb27299efb
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.cpp
@@ -0,0 +1,274 @@
+//===-- DWARFDebugArangeSet.cpp ---------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFDebugArangeSet.h"
+
+#include <assert.h>
+#include "lldb/Core/Stream.h"
+#include "SymbolFileDWARF.h"
+
+using namespace lldb_private;
+
+DWARFDebugArangeSet::DWARFDebugArangeSet() :
+    m_offset(DW_INVALID_OFFSET),
+    m_header(),
+    m_arange_descriptors()
+{
+    m_header.length     = 0;
+    m_header.version    = 0;
+    m_header.cu_offset  = 0;
+    m_header.addr_size  = 0;
+    m_header.seg_size   = 0;
+}
+
+void
+DWARFDebugArangeSet::Clear()
+{
+    m_offset = DW_INVALID_OFFSET;
+    m_header.length     = 0;
+    m_header.version    = 0;
+    m_header.cu_offset  = 0;
+    m_header.addr_size  = 0;
+    m_header.seg_size   = 0;
+    m_arange_descriptors.clear();
+}
+
+void
+DWARFDebugArangeSet::SetHeader
+(
+    uint16_t version,
+    uint32_t cu_offset,
+    uint8_t addr_size,
+    uint8_t seg_size
+)
+{
+    m_header.version    = version;
+    m_header.cu_offset  = cu_offset;
+    m_header.addr_size  = addr_size;
+    m_header.seg_size   = seg_size;
+}
+
+void
+DWARFDebugArangeSet::Compact()
+{
+    if (m_arange_descriptors.empty())
+        return;
+
+    // Iterate through all arange descriptors and combine any ranges that
+    // overlap or have matching boundaries. The m_arange_descriptors are assumed
+    // to be in ascending order after being built by adding descriptors
+    // using the AddDescriptor method.
+    uint32_t i = 0;
+    while (i + 1 < m_arange_descriptors.size())
+    {
+        if (m_arange_descriptors[i].end_address() >= m_arange_descriptors[i+1].address)
+        {
+            // The current range ends at or exceeds the start of the next address range.
+            // Compute the max end address between the two and use that to make the new
+            // length.
+            const dw_addr_t max_end_addr = std::max(m_arange_descriptors[i].end_address(), m_arange_descriptors[i+1].end_address());
+            m_arange_descriptors[i].length = max_end_addr - m_arange_descriptors[i].address;
+            // Now remove the next entry as it was just combined with the previous one.
+            m_arange_descriptors.erase(m_arange_descriptors.begin()+i+1);
+        }
+        else
+        {
+            // Discontiguous address range, just proceed to the next one.
+            ++i;
+        }
+    }
+}
+//----------------------------------------------------------------------
+// Compare function DWARFDebugArangeSet::Descriptor structures
+//----------------------------------------------------------------------
+static bool DescriptorLessThan (const DWARFDebugArangeSet::Descriptor& range1, const DWARFDebugArangeSet::Descriptor& range2)
+{
+    return range1.address < range2.address;
+}
+
+//----------------------------------------------------------------------
+// Add a range descriptor and keep things sorted so we can easily
+// compact the ranges before being saved or used.
+//----------------------------------------------------------------------
+void
+DWARFDebugArangeSet::AddDescriptor(const DWARFDebugArangeSet::Descriptor& range)
+{
+    if (m_arange_descriptors.empty())
+    {
+        m_arange_descriptors.push_back(range);
+        return;
+    }
+
+    DescriptorIter end = m_arange_descriptors.end();
+    DescriptorIter pos = lower_bound(m_arange_descriptors.begin(), end, range, DescriptorLessThan);
+    const dw_addr_t range_end_addr = range.end_address();
+    if (pos != end)
+    {
+        const dw_addr_t found_end_addr = pos->end_address();
+        if (range.address < pos->address)
+        {
+            if (range_end_addr < pos->address)
+            {
+                // Non-contiguous entries, add this one before the found entry
+                m_arange_descriptors.insert(pos, range);
+            }
+            else if (range_end_addr == pos->address)
+            {
+                // The top end of 'range' is the lower end of the entry
+                // pointed to by 'pos'. We can combine range with the
+                // entry we found by setting the starting address and
+                // increasing the length since they don't overlap.
+                pos->address = range.address;
+                pos->length += range.length;
+            }
+            else
+            {
+                // We can combine these two and make sure the largest end
+                // address is used to make end address.
+                pos->address = range.address;
+                pos->length = std::max(found_end_addr, range_end_addr) - pos->address;
+            }
+        }
+        else if (range.address == pos->address)
+        {
+            pos->length = std::max(pos->length, range.length);
+        }
+    }
+    else
+    {
+        // NOTE: 'pos' points to entry past the end which is ok for insert,
+        // don't use otherwise!!!
+        const dw_addr_t max_addr = m_arange_descriptors.back().end_address();
+        if (max_addr < range.address)
+        {
+            // Non-contiguous entries, add this one before the found entry
+            m_arange_descriptors.insert(pos, range);
+        }
+        else if (max_addr == range.address)
+        {
+            m_arange_descriptors.back().length += range.length;
+        }
+        else
+        {
+            m_arange_descriptors.back().length = std::max(max_addr, range_end_addr) - m_arange_descriptors.back().address;
+        }
+    }
+}
+
+bool
+DWARFDebugArangeSet::Extract(const DataExtractor &data, lldb::offset_t *offset_ptr)
+{
+    if (data.ValidOffset(*offset_ptr))
+    {
+        m_arange_descriptors.clear();
+        m_offset = *offset_ptr;
+
+        // 7.20 Address Range Table
+        //
+        // Each set of entries in the table of address ranges contained in
+        // the .debug_aranges section begins with a header consisting of: a
+        // 4-byte length containing the length of the set of entries for this
+        // compilation unit, not including the length field itself; a 2-byte
+        // version identifier containing the value 2 for DWARF Version 2; a
+        // 4-byte offset into the.debug_infosection; a 1-byte unsigned integer
+        // containing the size in bytes of an address (or the offset portion of
+        // an address for segmented addressing) on the target system; and a
+        // 1-byte unsigned integer containing the size in bytes of a segment
+        // descriptor on the target system. This header is followed by a series
+        // of tuples. Each tuple consists of an address and a length, each in
+        // the size appropriate for an address on the target architecture.
+        m_header.length     = data.GetU32(offset_ptr);
+        m_header.version    = data.GetU16(offset_ptr);
+        m_header.cu_offset  = data.GetU32(offset_ptr);
+        m_header.addr_size  = data.GetU8(offset_ptr);
+        m_header.seg_size   = data.GetU8(offset_ptr);
+
+
+        // The first tuple following the header in each set begins at an offset
+        // that is a multiple of the size of a single tuple (that is, twice the
+        // size of an address). The header is padded, if necessary, to the
+        // appropriate boundary.
+        const uint32_t header_size = *offset_ptr - m_offset;
+        const uint32_t tuple_size = m_header.addr_size << 1;
+        uint32_t first_tuple_offset = 0;
+        while (first_tuple_offset < header_size)
+            first_tuple_offset += tuple_size;
+
+        *offset_ptr = m_offset + first_tuple_offset;
+
+        Descriptor arangeDescriptor;
+
+        assert(sizeof(arangeDescriptor.address) == sizeof(arangeDescriptor.length));
+        assert(sizeof(arangeDescriptor.address) >= m_header.addr_size);
+
+        while (data.ValidOffset(*offset_ptr))
+        {
+            arangeDescriptor.address    = data.GetMaxU64(offset_ptr, m_header.addr_size);
+            arangeDescriptor.length     = data.GetMaxU64(offset_ptr, m_header.addr_size);
+
+            // Each set of tuples is terminated by a 0 for the address and 0
+            // for the length.
+            if (arangeDescriptor.address || arangeDescriptor.length)
+                m_arange_descriptors.push_back(arangeDescriptor);
+            else
+                break;  // We are done if we get a zero address and length
+        }
+
+        return !m_arange_descriptors.empty();
+    }
+    return false;
+}
+
+
+dw_offset_t
+DWARFDebugArangeSet::GetOffsetOfNextEntry() const
+{
+    return m_offset + m_header.length + 4;
+}
+
+
+void
+DWARFDebugArangeSet::Dump(Stream *s) const
+{
+    s->Printf("Address Range Header: length = 0x%8.8x, version = 0x%4.4x, cu_offset = 0x%8.8x, addr_size = 0x%2.2x, seg_size = 0x%2.2x\n",
+        m_header.length ,m_header.version, m_header.cu_offset, m_header.addr_size, m_header.seg_size);
+
+    const uint32_t hex_width = m_header.addr_size * 2;
+    DescriptorConstIter pos;
+    DescriptorConstIter end = m_arange_descriptors.end();
+    for (pos = m_arange_descriptors.begin(); pos != end; ++pos)
+        s->Printf("[0x%*.*" PRIx64 " - 0x%*.*" PRIx64 ")\n",
+            hex_width, hex_width, pos->address,
+            hex_width, hex_width, pos->end_address());
+}
+
+
+class DescriptorContainsAddress
+{
+public:
+    DescriptorContainsAddress (dw_addr_t address) : m_address(address) {}
+    bool operator() (const DWARFDebugArangeSet::Descriptor& desc) const
+    {
+        return (m_address >= desc.address) && (m_address < (desc.address + desc.length));
+    }
+ private:
+   const dw_addr_t m_address;
+};
+
+dw_offset_t
+DWARFDebugArangeSet::FindAddress(dw_addr_t address) const
+{
+    DescriptorConstIter end = m_arange_descriptors.end();
+    DescriptorConstIter pos = std::find_if( m_arange_descriptors.begin(), end,  // Range
+                                            DescriptorContainsAddress(address));// Predicate
+    if (pos != end)
+        return m_header.cu_offset;
+
+    return DW_INVALID_OFFSET;
+}
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.h
new file mode 100644
index 000000000000..19ec8d042e72
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.h
@@ -0,0 +1,76 @@
+//===-- DWARFDebugArangeSet.h -----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SymbolFileDWARF_DWARFDebugArangeSet_h_
+#define SymbolFileDWARF_DWARFDebugArangeSet_h_
+
+#include "SymbolFileDWARF.h"
+#include <vector>
+
+class SymbolFileDWARF;
+
+class DWARFDebugArangeSet
+{
+public:
+    struct Header
+    {
+        uint32_t    length;     // The total length of the entries for that set, not including the length field itself.
+        uint16_t    version;    // The DWARF version number
+        uint32_t    cu_offset;  // The offset from the beginning of the .debug_info section of the compilation unit entry referenced by the table.
+        uint8_t     addr_size;  // The size in bytes of an address on the target architecture. For segmented addressing, this is the size of the offset portion of the address
+        uint8_t     seg_size;   // The size in bytes of a segment descriptor on the target architecture. If the target system uses a flat address space, this value is 0.
+    };
+
+    struct Descriptor
+    {
+        dw_addr_t   address;
+        dw_addr_t   length;
+        dw_addr_t end_address() const { return address + length; }
+    };
+
+
+                    DWARFDebugArangeSet();
+        void        Clear();
+        void        SetOffset(uint32_t offset) { m_offset = offset; }
+        void        SetHeader(uint16_t version, uint32_t cu_offset, uint8_t addr_size, uint8_t seg_size);
+        void        AddDescriptor(const DWARFDebugArangeSet::Descriptor& range);
+        void        Compact();
+        bool        Extract(const lldb_private::DataExtractor &data, lldb::offset_t *offset_ptr);
+        void        Dump(lldb_private::Stream *s) const;
+        dw_offset_t GetCompileUnitDIEOffset() const { return m_header.cu_offset; }
+        dw_offset_t GetOffsetOfNextEntry() const;
+        dw_offset_t FindAddress(dw_addr_t address) const;
+        size_t      NumDescriptors() const { return m_arange_descriptors.size(); }
+        const Header&       GetHeader() const { return m_header; }
+        const Descriptor*   GetDescriptor(uint32_t i) const
+        {
+            if (i < m_arange_descriptors.size())
+                return &m_arange_descriptors[i];
+            return NULL;
+        }
+
+        const Descriptor &  
+        GetDescriptorRef (uint32_t i) const
+        {
+            return m_arange_descriptors[i];
+        }
+
+
+protected:
+    typedef std::vector<Descriptor>         DescriptorColl;
+    typedef DescriptorColl::iterator        DescriptorIter;
+    typedef DescriptorColl::const_iterator  DescriptorConstIter;
+
+
+    uint32_t        m_offset;
+    Header          m_header;
+    DescriptorColl  m_arange_descriptors;
+};
+
+#endif  // SymbolFileDWARF_DWARFDebugArangeSet_h_
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp
new file mode 100644
index 000000000000..3b004c4b3890
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp
@@ -0,0 +1,177 @@
+//===-- DWARFDebugAranges.cpp -----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFDebugAranges.h"
+
+#include <assert.h>
+#include <stdio.h>
+
+#include <algorithm>
+
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/Timer.h"
+
+#include "LogChannelDWARF.h"
+#include "SymbolFileDWARF.h"
+#include "DWARFDebugInfo.h"
+#include "DWARFCompileUnit.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// Constructor
+//----------------------------------------------------------------------
+DWARFDebugAranges::DWARFDebugAranges() :
+    m_aranges()
+{
+}
+
+//----------------------------------------------------------------------
+// CountArangeDescriptors
+//----------------------------------------------------------------------
+class CountArangeDescriptors
+{
+public:
+    CountArangeDescriptors (uint32_t& count_ref) : count(count_ref)
+    {
+//      printf("constructor CountArangeDescriptors()\n");
+    }
+    void operator() (const DWARFDebugArangeSet& set)
+    {
+        count += set.NumDescriptors();
+    }
+    uint32_t& count;
+};
+
+
+//----------------------------------------------------------------------
+// Extract
+//----------------------------------------------------------------------
+bool
+DWARFDebugAranges::Extract(const DataExtractor &debug_aranges_data)
+{
+    if (debug_aranges_data.ValidOffset(0))
+    {
+        lldb::offset_t offset = 0;
+
+        DWARFDebugArangeSet set;
+        Range range;
+        while (set.Extract(debug_aranges_data, &offset))
+        {
+            const uint32_t num_descriptors = set.NumDescriptors();
+            if (num_descriptors > 0)
+            {
+                const dw_offset_t cu_offset = set.GetCompileUnitDIEOffset();
+                
+                for (uint32_t i=0; i<num_descriptors; ++i)
+                {
+                    const DWARFDebugArangeSet::Descriptor &descriptor = set.GetDescriptorRef(i);
+                    m_aranges.Append(RangeToDIE::Entry (descriptor.address, descriptor.length, cu_offset));
+                }
+            }
+            set.Clear();
+        }
+    }
+    return false;
+}
+
+//----------------------------------------------------------------------
+// Generate
+//----------------------------------------------------------------------
+bool
+DWARFDebugAranges::Generate(SymbolFileDWARF* dwarf2Data)
+{
+    Clear();
+    DWARFDebugInfo* debug_info = dwarf2Data->DebugInfo();
+    if (debug_info)
+    {
+        const bool clear_dies_if_already_not_parsed = true;
+        uint32_t cu_idx = 0;
+        const uint32_t num_compile_units = dwarf2Data->GetNumCompileUnits();
+        for (cu_idx = 0; cu_idx < num_compile_units; ++cu_idx)
+        {
+            DWARFCompileUnit* cu = debug_info->GetCompileUnitAtIndex(cu_idx);
+            if (cu)
+                cu->BuildAddressRangeTable(dwarf2Data, this, clear_dies_if_already_not_parsed);
+        }
+    }
+    return !IsEmpty();
+}
+
+
+void
+DWARFDebugAranges::Dump (Log *log) const
+{
+    if (log == NULL)
+        return;
+    
+    const size_t num_entries = m_aranges.GetSize();
+    for (size_t i=0; i<num_entries; ++i)
+    {
+        const RangeToDIE::Entry *entry = m_aranges.GetEntryAtIndex(i);
+        if (entry)
+            log->Printf ("0x%8.8x: [0x%" PRIx64 " - 0x%" PRIx64 ")",
+                         entry->data,
+                         entry->GetRangeBase(),
+                         entry->GetRangeEnd());
+    }
+}
+
+void
+DWARFDebugAranges::AppendRange (dw_offset_t offset, dw_addr_t low_pc, dw_addr_t high_pc)
+{
+    if (high_pc > low_pc)
+        m_aranges.Append(RangeToDIE::Entry (low_pc, high_pc - low_pc, offset));
+}
+
+void
+DWARFDebugAranges::Sort (bool minimize)
+{    
+    Timer scoped_timer(__PRETTY_FUNCTION__, "%s this = %p",
+                       __PRETTY_FUNCTION__, this);
+
+    Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_ARANGES));
+    size_t orig_arange_size = 0;
+    if (log)
+    {
+        orig_arange_size = m_aranges.GetSize();
+        log->Printf ("DWARFDebugAranges::Sort(minimize = %u) with %" PRIu64 " entries", minimize, (uint64_t)orig_arange_size);
+    }
+
+    m_aranges.Sort();
+    m_aranges.CombineConsecutiveEntriesWithEqualData();
+
+    if (log)
+    {
+        if (minimize)
+        {
+            const size_t new_arange_size = m_aranges.GetSize();
+            const size_t delta = orig_arange_size - new_arange_size;
+            log->Printf ("DWARFDebugAranges::Sort() %" PRIu64 " entries after minimizing (%" PRIu64 " entries combined for %" PRIu64 " bytes saved)",
+                         (uint64_t)new_arange_size,
+                         (uint64_t)delta,
+                         (uint64_t)delta * sizeof(Range));
+        }
+        Dump (log);
+    }
+}
+
+//----------------------------------------------------------------------
+// FindAddress
+//----------------------------------------------------------------------
+dw_offset_t
+DWARFDebugAranges::FindAddress(dw_addr_t address) const
+{
+    const RangeToDIE::Entry *entry = m_aranges.FindEntryThatContains(address);
+    if (entry)
+        return entry->data;
+    return DW_INVALID_OFFSET;
+}
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.h
new file mode 100644
index 000000000000..88db929226ab
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.h
@@ -0,0 +1,94 @@
+//===-- DWARFDebugAranges.h -------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SymbolFileDWARF_DWARFDebugAranges_h_
+#define SymbolFileDWARF_DWARFDebugAranges_h_
+
+#include "DWARFDebugArangeSet.h"
+#include <list>
+
+#include "lldb/Core/RangeMap.h"
+
+class SymbolFileDWARF;
+
+class DWARFDebugAranges
+{
+protected:
+    typedef lldb_private::RangeDataArray<dw_addr_t, uint32_t, dw_offset_t, 1> RangeToDIE;
+
+public:
+    typedef RangeToDIE::Entry Range;
+    typedef std::vector<RangeToDIE::Entry> RangeColl;
+
+    DWARFDebugAranges();
+
+    void
+    Clear() 
+    {
+        m_aranges.Clear(); 
+    }
+
+    bool
+    Extract(const lldb_private::DataExtractor &debug_aranges_data);
+
+    bool
+    Generate(SymbolFileDWARF* dwarf2Data);
+    
+                // Use append range multiple times and then call sort
+    void
+    AppendRange (dw_offset_t cu_offset, 
+                 dw_addr_t low_pc, 
+                 dw_addr_t high_pc);
+
+    void 
+    Sort (bool minimize);
+
+    const Range* 
+    RangeAtIndex(uint32_t idx) const
+    {
+        return m_aranges.GetEntryAtIndex (idx);
+    }
+    
+    void
+    Dump (lldb_private::Log *log) const;
+    
+    dw_offset_t
+    FindAddress(dw_addr_t address) const;
+
+    bool
+    IsEmpty() const 
+    {
+        return m_aranges.IsEmpty(); 
+    }
+    size_t
+    GetNumRanges() const
+    {
+        return m_aranges.GetSize();
+    }
+
+    dw_offset_t 
+    OffsetAtIndex(uint32_t idx) const
+    {
+        const Range *range = m_aranges.GetEntryAtIndex (idx);
+        if (range)
+            return range->data;
+        return DW_INVALID_OFFSET;
+    }
+
+    static void 
+    Dump(SymbolFileDWARF* dwarf2Data, lldb_private::Stream *s);
+    
+protected:
+
+
+    RangeToDIE m_aranges;
+};
+
+
+#endif  // SymbolFileDWARF_DWARFDebugAranges_h_
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
new file mode 100644
index 000000000000..4c76eed8166f
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
@@ -0,0 +1,797 @@
+//===-- DWARFDebugInfo.cpp --------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SymbolFileDWARF.h"
+
+#include <algorithm>
+#include <set>
+
+#include "lldb/Core/RegularExpression.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Symbol/ObjectFile.h"
+
+#include "DWARFDebugAranges.h"
+#include "DWARFDebugInfo.h"
+#include "DWARFCompileUnit.h"
+#include "DWARFDebugAranges.h"
+#include "DWARFDebugInfoEntry.h"
+#include "DWARFFormValue.h"
+#include "LogChannelDWARF.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace std;
+
+//----------------------------------------------------------------------
+// Constructor
+//----------------------------------------------------------------------
+DWARFDebugInfo::DWARFDebugInfo() :
+    m_dwarf2Data(NULL),
+    m_compile_units(),
+    m_cu_aranges_ap ()
+{
+}
+
+//----------------------------------------------------------------------
+// SetDwarfData
+//----------------------------------------------------------------------
+void
+DWARFDebugInfo::SetDwarfData(SymbolFileDWARF* dwarf2Data)
+{
+    m_dwarf2Data = dwarf2Data;
+    m_compile_units.clear();
+}
+
+
+DWARFDebugAranges &
+DWARFDebugInfo::GetCompileUnitAranges ()
+{
+    if (m_cu_aranges_ap.get() == NULL && m_dwarf2Data)
+    {
+        Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_ARANGES));
+
+        m_cu_aranges_ap.reset (new DWARFDebugAranges());
+        const DataExtractor &debug_aranges_data = m_dwarf2Data->get_debug_aranges_data();
+        if (debug_aranges_data.GetByteSize() > 0)
+        {
+            if (log)
+                log->Printf ("DWARFDebugInfo::GetCompileUnitAranges() for \"%s\" from .debug_aranges",
+                             m_dwarf2Data->GetObjectFile()->GetFileSpec().GetPath().c_str());
+            m_cu_aranges_ap->Extract (debug_aranges_data);
+            
+        }
+        else
+        {
+            if (log)
+                log->Printf ("DWARFDebugInfo::GetCompileUnitAranges() for \"%s\" by parsing", 
+                             m_dwarf2Data->GetObjectFile()->GetFileSpec().GetPath().c_str());
+            const size_t num_compile_units = GetNumCompileUnits();
+            const bool clear_dies_if_already_not_parsed = true;
+            for (size_t idx = 0; idx < num_compile_units; ++idx)
+            {
+                DWARFCompileUnit* cu = GetCompileUnitAtIndex(idx);
+                if (cu)
+                    cu->BuildAddressRangeTable (m_dwarf2Data, m_cu_aranges_ap.get(), clear_dies_if_already_not_parsed);
+            }
+        }
+
+        const bool minimize = true;
+        m_cu_aranges_ap->Sort (minimize);
+    }
+    return *m_cu_aranges_ap.get();
+}
+
+
+//----------------------------------------------------------------------
+// LookupAddress
+//----------------------------------------------------------------------
+bool
+DWARFDebugInfo::LookupAddress
+(
+    const dw_addr_t address,
+    const dw_offset_t hint_die_offset,
+    DWARFCompileUnitSP& cu_sp,
+    DWARFDebugInfoEntry** function_die,
+    DWARFDebugInfoEntry** block_die
+)
+{
+
+    if (hint_die_offset != DW_INVALID_OFFSET)
+        cu_sp = GetCompileUnit(hint_die_offset);
+    else
+    {
+        DWARFDebugAranges &cu_aranges = GetCompileUnitAranges ();
+        const dw_offset_t cu_offset = cu_aranges.FindAddress (address);
+        cu_sp = GetCompileUnit(cu_offset);
+    }
+
+    if (cu_sp.get())
+    {
+        if (cu_sp->LookupAddress(address, function_die, block_die))
+            return true;
+        cu_sp.reset();
+    }
+    else
+    {
+        // The hint_die_offset may have been a pointer to the actual item that
+        // we are looking for
+        DWARFDebugInfoEntry* die_ptr = GetDIEPtr(hint_die_offset, &cu_sp);
+        if (die_ptr)
+        {
+            if (cu_sp.get())
+            {
+                if (function_die || block_die)
+                    return die_ptr->LookupAddress(address, m_dwarf2Data, cu_sp.get(), function_die, block_die);
+
+                // We only wanted the compile unit that contained this address
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+
+void
+DWARFDebugInfo::ParseCompileUnitHeadersIfNeeded()
+{
+    if (m_compile_units.empty())
+    {
+        if (m_dwarf2Data != NULL)
+        {
+            lldb::offset_t offset = 0;
+            const DataExtractor &debug_info_data = m_dwarf2Data->get_debug_info_data();
+            while (debug_info_data.ValidOffset(offset))
+            {
+                DWARFCompileUnitSP cu_sp(new DWARFCompileUnit(m_dwarf2Data));
+                // Out of memory?
+                if (cu_sp.get() == NULL)
+                    break;
+
+                if (cu_sp->Extract(debug_info_data, &offset) == false)
+                    break;
+
+                m_compile_units.push_back(cu_sp);
+
+                offset = cu_sp->GetNextCompileUnitOffset();
+            }
+        }
+    }
+}
+
+size_t
+DWARFDebugInfo::GetNumCompileUnits()
+{
+    ParseCompileUnitHeadersIfNeeded();
+    return m_compile_units.size();
+}
+
+DWARFCompileUnit*
+DWARFDebugInfo::GetCompileUnitAtIndex(uint32_t idx)
+{
+    DWARFCompileUnit* cu = NULL;
+    if (idx < GetNumCompileUnits())
+        cu = m_compile_units[idx].get();
+    return cu;
+}
+
+bool
+DWARFDebugInfo::ContainsCompileUnit (const DWARFCompileUnit *cu) const
+{
+    // Not a verify efficient function, but it is handy for use in assertions
+    // to make sure that a compile unit comes from a debug information file.
+    CompileUnitColl::const_iterator end_pos = m_compile_units.end();
+    CompileUnitColl::const_iterator pos;
+    
+    for (pos = m_compile_units.begin(); pos != end_pos; ++pos)
+    {
+        if (pos->get() == cu)
+            return true;
+    }
+    return false;
+}
+
+
+static bool CompileUnitOffsetLessThan (const DWARFCompileUnitSP& a, const DWARFCompileUnitSP& b)
+{
+    return a->GetOffset() < b->GetOffset();
+}
+
+
+static int
+CompareDWARFCompileUnitSPOffset (const void *key, const void *arrmem)
+{
+    const dw_offset_t key_cu_offset = *(dw_offset_t*) key;
+    const dw_offset_t cu_offset = ((DWARFCompileUnitSP *)arrmem)->get()->GetOffset();
+    if (key_cu_offset < cu_offset)
+        return -1;
+    if (key_cu_offset > cu_offset)
+        return 1;
+    return 0;
+}
+
+DWARFCompileUnitSP
+DWARFDebugInfo::GetCompileUnit(dw_offset_t cu_offset, uint32_t* idx_ptr)
+{
+    DWARFCompileUnitSP cu_sp;
+    uint32_t cu_idx = DW_INVALID_INDEX;
+    if (cu_offset != DW_INVALID_OFFSET)
+    {
+        ParseCompileUnitHeadersIfNeeded();
+
+        DWARFCompileUnitSP* match = (DWARFCompileUnitSP*)bsearch(&cu_offset, &m_compile_units[0], m_compile_units.size(), sizeof(DWARFCompileUnitSP), CompareDWARFCompileUnitSPOffset);
+        if (match)
+        {
+            cu_sp = *match;
+            cu_idx = match - &m_compile_units[0];
+        }
+    }
+    if (idx_ptr)
+        *idx_ptr = cu_idx;
+    return cu_sp;
+}
+
+DWARFCompileUnitSP
+DWARFDebugInfo::GetCompileUnitContainingDIE(dw_offset_t die_offset)
+{
+    DWARFCompileUnitSP cu_sp;
+    if (die_offset != DW_INVALID_OFFSET)
+    {
+        ParseCompileUnitHeadersIfNeeded();
+
+        CompileUnitColl::const_iterator end_pos = m_compile_units.end();
+        CompileUnitColl::const_iterator pos;
+
+        for (pos = m_compile_units.begin(); pos != end_pos; ++pos)
+        {
+            dw_offset_t cu_start_offset = (*pos)->GetOffset();
+            dw_offset_t cu_end_offset = (*pos)->GetNextCompileUnitOffset();
+            if (cu_start_offset <= die_offset && die_offset < cu_end_offset)
+            {
+                cu_sp = *pos;
+                break;
+            }
+        }
+    }
+    return cu_sp;
+}
+
+//----------------------------------------------------------------------
+// Compare function DWARFDebugAranges::Range structures
+//----------------------------------------------------------------------
+static bool CompareDIEOffset (const DWARFDebugInfoEntry& die1, const DWARFDebugInfoEntry& die2)
+{
+    return die1.GetOffset() < die2.GetOffset();
+}
+
+
+//----------------------------------------------------------------------
+// GetDIE()
+//
+// Get the DIE (Debug Information Entry) with the specified offset.
+//----------------------------------------------------------------------
+DWARFDebugInfoEntry*
+DWARFDebugInfo::GetDIEPtr(dw_offset_t die_offset, DWARFCompileUnitSP* cu_sp_ptr)
+{
+    DWARFCompileUnitSP cu_sp(GetCompileUnitContainingDIE(die_offset));
+    if (cu_sp_ptr)
+        *cu_sp_ptr = cu_sp;
+    if (cu_sp.get())
+        return cu_sp->GetDIEPtr(die_offset);
+    return NULL;    // Not found in any compile units
+}
+
+DWARFDebugInfoEntry*
+DWARFDebugInfo::GetDIEPtrWithCompileUnitHint (dw_offset_t die_offset, DWARFCompileUnit**cu_handle)
+{
+    assert (cu_handle);
+    DWARFDebugInfoEntry* die = NULL;
+    if (*cu_handle)
+        die = (*cu_handle)->GetDIEPtr(die_offset);
+
+    if (die == NULL)
+    {
+        DWARFCompileUnitSP cu_sp (GetCompileUnitContainingDIE(die_offset));
+        if (cu_sp.get())
+        {
+            *cu_handle = cu_sp.get();
+            die = cu_sp->GetDIEPtr(die_offset);
+        }
+    }
+    if (die == NULL)
+        *cu_handle = NULL;
+    return die;
+}
+
+
+const DWARFDebugInfoEntry*
+DWARFDebugInfo::GetDIEPtrContainingOffset(dw_offset_t die_offset, DWARFCompileUnitSP* cu_sp_ptr)
+{
+    DWARFCompileUnitSP cu_sp(GetCompileUnitContainingDIE(die_offset));
+    if (cu_sp_ptr)
+        *cu_sp_ptr = cu_sp;
+    if (cu_sp.get())
+        return cu_sp->GetDIEPtrContainingOffset(die_offset);
+
+    return NULL;    // Not found in any compile units
+
+}
+
+//----------------------------------------------------------------------
+// DWARFDebugInfo_ParseCallback
+//
+// A callback function for the static DWARFDebugInfo::Parse() function
+// that gets parses all compile units and DIE's into an internate
+// representation for further modification.
+//----------------------------------------------------------------------
+
+static dw_offset_t
+DWARFDebugInfo_ParseCallback
+(
+    SymbolFileDWARF* dwarf2Data,
+    DWARFCompileUnitSP& cu_sp,
+    DWARFDebugInfoEntry* die,
+    const dw_offset_t next_offset,
+    const uint32_t curr_depth,
+    void* userData
+)
+{
+    DWARFDebugInfo* debug_info = (DWARFDebugInfo*)userData;
+    DWARFCompileUnit* cu = cu_sp.get();
+    if (die)
+    {
+        cu->AddDIE(*die);
+    }
+    else if (cu)
+    {
+        debug_info->AddCompileUnit(cu_sp);
+    }
+
+    // Just return the current offset to parse the next CU or DIE entry
+    return next_offset;
+}
+
+//----------------------------------------------------------------------
+// AddCompileUnit
+//----------------------------------------------------------------------
+void
+DWARFDebugInfo::AddCompileUnit(DWARFCompileUnitSP& cu)
+{
+    m_compile_units.push_back(cu);
+}
+
+/*
+void
+DWARFDebugInfo::AddDIE(DWARFDebugInfoEntry& die)
+{
+    m_die_array.push_back(die);
+}
+*/
+
+
+
+
+//----------------------------------------------------------------------
+// Parse
+//
+// Parses the .debug_info section and uses the .debug_abbrev section
+// and various other sections in the SymbolFileDWARF class and calls the
+// supplied callback function each time a compile unit header, or debug
+// information entry is successfully parsed. This function can be used
+// for different tasks such as parsing the file contents into a
+// structured data, dumping, verifying and much more.
+//----------------------------------------------------------------------
+void
+DWARFDebugInfo::Parse(SymbolFileDWARF* dwarf2Data, Callback callback, void* userData)
+{
+    if (dwarf2Data)
+    {
+        lldb::offset_t offset = 0;
+        uint32_t depth = 0;
+        DWARFCompileUnitSP cu(new DWARFCompileUnit(dwarf2Data));
+        if (cu.get() == NULL)
+            return;
+        DWARFDebugInfoEntry die;
+
+        while (cu->Extract(dwarf2Data->get_debug_info_data(), &offset))
+        {
+            const dw_offset_t next_cu_offset = cu->GetNextCompileUnitOffset();
+
+            depth = 0;
+            // Call the callback function with no DIE pointer for the compile unit
+            // and get the offset that we are to continue to parse from
+            offset = callback(dwarf2Data, cu, NULL, offset, depth, userData);
+
+            // Make sure we are within our compile unit
+            if (offset < next_cu_offset)
+            {
+                // We are in our compile unit, parse starting at the offset
+                // we were told to parse
+                bool done = false;
+                while (!done && die.Extract(dwarf2Data, cu.get(), &offset))
+                {
+                    // Call the callback function with DIE pointer that falls within the compile unit
+                    offset = callback(dwarf2Data, cu, &die, offset, depth, userData);
+
+                    if (die.IsNULL())
+                    {
+                        if (depth)
+                            --depth;
+                        else
+                            done = true;    // We are done with this compile unit!
+                    }
+                    else if (die.HasChildren())
+                        ++depth;
+                }
+            }
+
+            // Make sure the offset returned is valid, and if not stop parsing.
+            // Returning DW_INVALID_OFFSET from this callback is a good way to end
+            // all parsing
+            if (!dwarf2Data->get_debug_info_data().ValidOffset(offset))
+                break;
+
+            // See if during the callback anyone retained a copy of the compile
+            // unit other than ourselves and if so, let whomever did own the object
+            // and create a new one for our own use!
+            if (!cu.unique())
+                cu.reset(new DWARFCompileUnit(dwarf2Data));
+
+
+            // Make sure we start on a proper
+            offset = next_cu_offset;
+        }
+    }
+}
+
+typedef struct DumpInfo
+{
+    DumpInfo(Stream* init_strm, uint32_t off, uint32_t depth) :
+        strm(init_strm),
+        die_offset(off),
+        recurse_depth(depth),
+        found_depth(UINT32_MAX),
+        found_die(false),
+        ancestors()
+    {
+    }
+    Stream* strm;
+    const uint32_t die_offset;
+    const uint32_t recurse_depth;
+    uint32_t found_depth;
+    bool found_die;
+    std::vector<DWARFDebugInfoEntry> ancestors;
+
+    DISALLOW_COPY_AND_ASSIGN(DumpInfo);
+} DumpInfo;
+
+//----------------------------------------------------------------------
+// DumpCallback
+//
+// A callback function for the static DWARFDebugInfo::Parse() function
+// that gets called each time a compile unit header or debug information
+// entry is successfully parsed.
+//
+// This function dump DWARF information and obey recurse depth and
+// whether a single DIE is to be dumped (or all of the data).
+//----------------------------------------------------------------------
+static dw_offset_t DumpCallback
+(
+    SymbolFileDWARF* dwarf2Data,
+    DWARFCompileUnitSP& cu_sp,
+    DWARFDebugInfoEntry* die,
+    const dw_offset_t next_offset,
+    const uint32_t curr_depth,
+    void* userData
+)
+{
+    DumpInfo* dumpInfo = (DumpInfo*)userData;
+
+    const DWARFCompileUnit* cu = cu_sp.get();
+
+    Stream *s = dumpInfo->strm;
+    bool show_parents = s->GetFlags().Test(DWARFDebugInfo::eDumpFlag_ShowAncestors);
+
+    if (die)
+    {
+        // Are we dumping everything?
+        if (dumpInfo->die_offset == DW_INVALID_OFFSET)
+        {
+            // Yes we are dumping everything. Obey our recurse level though
+            if (curr_depth < dumpInfo->recurse_depth)
+                die->Dump(dwarf2Data, cu, *s, 0);
+        }
+        else
+        {
+            // We are dumping a specific DIE entry by offset
+            if (dumpInfo->die_offset == die->GetOffset())
+            {
+                // We found the DIE we were looking for, dump it!
+                if (show_parents)
+                {
+                    s->SetIndentLevel(0);
+                    const uint32_t num_ancestors = dumpInfo->ancestors.size();
+                    if (num_ancestors > 0)
+                    {
+                        for (uint32_t i=0; i<num_ancestors-1; ++i)
+                        {
+                            dumpInfo->ancestors[i].Dump(dwarf2Data, cu, *s, 0);
+                            s->IndentMore();
+                        }
+                    }
+                }
+
+                dumpInfo->found_depth = curr_depth;
+
+                die->Dump(dwarf2Data, cu, *s, 0);
+
+                // Note that we found the DIE we were looking for
+                dumpInfo->found_die = true;
+
+                // Since we are dumping a single DIE, if there are no children we are done!
+                if (!die->HasChildren() || dumpInfo->recurse_depth == 0)
+                    return DW_INVALID_OFFSET;   // Return an invalid address to end parsing
+            }
+            else if (dumpInfo->found_die)
+            {
+                // Are we done with all the children?
+                if (curr_depth <= dumpInfo->found_depth)
+                    return DW_INVALID_OFFSET;
+
+                // We have already found our DIE and are printing it's children. Obey
+                // our recurse depth and return an invalid offset if we get done
+                // dumping all the the children
+                if (dumpInfo->recurse_depth == UINT32_MAX || curr_depth <= dumpInfo->found_depth + dumpInfo->recurse_depth)
+                    die->Dump(dwarf2Data, cu, *s, 0);
+            }
+            else if (dumpInfo->die_offset > die->GetOffset())
+            {
+                if (show_parents)
+                    dumpInfo->ancestors.back() = *die;
+            }
+        }
+
+        // Keep up with our indent level
+        if (die->IsNULL())
+        {
+            if (show_parents)
+                dumpInfo->ancestors.pop_back();
+
+            if (curr_depth <= 1)
+                return cu->GetNextCompileUnitOffset();
+            else
+                s->IndentLess();
+        }
+        else if (die->HasChildren())
+        {
+            if (show_parents)
+            {
+                DWARFDebugInfoEntry null_die;
+                dumpInfo->ancestors.push_back(null_die);
+            }
+            s->IndentMore();
+        }
+    }
+    else
+    {
+        if (cu == NULL)
+            s->PutCString("NULL - cu");
+        // We have a compile unit, reset our indent level to zero just in case
+        s->SetIndentLevel(0);
+
+        // See if we are dumping everything?
+        if (dumpInfo->die_offset == DW_INVALID_OFFSET)
+        {
+            // We are dumping everything
+            cu->Dump(s);
+            return cu->GetFirstDIEOffset(); // Return true to parse all DIEs in this Compile Unit
+        }
+        else
+        {
+            if (show_parents)
+            {
+                dumpInfo->ancestors.clear();
+                dumpInfo->ancestors.resize(1);
+            }
+
+            // We are dumping only a single DIE possibly with it's children and
+            // we must find it's compile unit before we can dump it properly
+            if (dumpInfo->die_offset < cu->GetFirstDIEOffset())
+            {
+                // Not found, maybe the DIE offset provided wasn't correct?
+            //  *ostrm_ptr << "DIE at offset " << HEX32 << dumpInfo->die_offset << " was not found." << endl;
+                return DW_INVALID_OFFSET;
+            }
+            else
+            {
+                // See if the DIE is in this compile unit?
+                if (dumpInfo->die_offset < cu->GetNextCompileUnitOffset())
+                {
+                    // This DIE is in this compile unit!
+                    if (s->GetVerbose())
+                        cu->Dump(s); // Dump the compile unit for the DIE in verbose mode
+
+                    return next_offset;
+                //  // We found our compile unit that contains our DIE, just skip to dumping the requested DIE...
+                //  return dumpInfo->die_offset;
+                }
+                else
+                {
+                    // Skip to the next compile unit as the DIE isn't in the current one!
+                    return cu->GetNextCompileUnitOffset();
+                }
+            }
+        }
+    }
+
+    // Just return the current offset to parse the next CU or DIE entry
+    return next_offset;
+}
+
+//----------------------------------------------------------------------
+// Dump
+//
+// Dump the information in the .debug_info section to the specified
+// ostream. If die_offset is valid, a single DIE will be dumped. If the
+// die_offset is invalid, all the DWARF information will be dumped. Both
+// cases will obey a "recurse_depth" or how deep to traverse into the
+// children of each DIE entry. A recurse_depth of zero will dump all
+// compile unit headers. A recurse_depth of 1 will dump all compile unit
+// headers and the DW_TAG_compile unit tags. A depth of 2 will also
+// dump all types and functions.
+//----------------------------------------------------------------------
+void
+DWARFDebugInfo::Dump
+(
+    Stream *s,
+    SymbolFileDWARF* dwarf2Data,
+    const uint32_t die_offset,
+    const uint32_t recurse_depth
+)
+{
+    DumpInfo dumpInfo(s, die_offset, recurse_depth);
+    s->PutCString(".debug_info contents");
+    if (dwarf2Data->get_debug_info_data().GetByteSize() > 0)
+    {
+        if (die_offset == DW_INVALID_OFFSET)
+            s->PutCString(":\n");
+        else
+        {
+            s->Printf(" for DIE entry at .debug_info[0x%8.8x]", die_offset);
+            if (recurse_depth != UINT32_MAX)
+                s->Printf(" recursing %u levels deep.", recurse_depth);
+            s->EOL();
+        }
+    }
+    else
+    {
+        s->PutCString(": < EMPTY >\n");
+        return;
+    }
+    DWARFDebugInfo::Parse(dwarf2Data, DumpCallback, &dumpInfo);
+}
+
+
+//----------------------------------------------------------------------
+// Dump
+//
+// Dump the contents of this DWARFDebugInfo object as has been parsed
+// and/or modified after it has been parsed.
+//----------------------------------------------------------------------
+void
+DWARFDebugInfo::Dump (Stream *s, const uint32_t die_offset, const uint32_t recurse_depth)
+{
+    DumpInfo dumpInfo(s, die_offset, recurse_depth);
+
+    s->PutCString("Dumping .debug_info section from internal representation\n");
+
+    CompileUnitColl::const_iterator pos;
+    uint32_t curr_depth = 0;
+    ParseCompileUnitHeadersIfNeeded();
+    for (pos = m_compile_units.begin(); pos != m_compile_units.end(); ++pos)
+    {
+        const DWARFCompileUnitSP& cu_sp = *pos;
+        DumpCallback(m_dwarf2Data, (DWARFCompileUnitSP&)cu_sp, NULL, 0, curr_depth, &dumpInfo);
+        
+        const DWARFDebugInfoEntry* die = cu_sp->DIE();
+        if (die)
+            die->Dump(m_dwarf2Data, cu_sp.get(), *s, recurse_depth);
+    }
+}
+
+
+//----------------------------------------------------------------------
+// FindCallbackString
+//
+// A callback function for the static DWARFDebugInfo::Parse() function
+// that gets called each time a compile unit header or debug information
+// entry is successfully parsed.
+//
+// This function will find the die_offset of any items whose DW_AT_name
+// matches the given string
+//----------------------------------------------------------------------
+typedef struct FindCallbackStringInfoTag
+{
+    const char* name;
+    bool ignore_case;
+    RegularExpression* regex;
+    vector<dw_offset_t>& die_offsets;
+} FindCallbackStringInfo;
+
+static dw_offset_t FindCallbackString
+(
+    SymbolFileDWARF* dwarf2Data,
+    DWARFCompileUnitSP& cu_sp,
+    DWARFDebugInfoEntry* die,
+    const dw_offset_t next_offset,
+    const uint32_t curr_depth,
+    void* userData
+)
+{
+    FindCallbackStringInfo* info = (FindCallbackStringInfo*)userData;
+    const DWARFCompileUnit* cu = cu_sp.get();
+
+    if (die)
+    {
+        const char* die_name = die->GetName(dwarf2Data, cu);
+        if (die_name)
+        {
+            if (info->regex)
+            {
+                if (info->regex->Execute(die_name))
+                    info->die_offsets.push_back(die->GetOffset());
+            }
+            else
+            {
+                if ((info->ignore_case ? strcasecmp(die_name, info->name) : strcmp(die_name, info->name)) == 0)
+                    info->die_offsets.push_back(die->GetOffset());
+            }
+        }
+    }
+
+    // Just return the current offset to parse the next CU or DIE entry
+    return next_offset;
+}
+
+//----------------------------------------------------------------------
+// Find
+//
+// Finds all DIE that have a specific DW_AT_name attribute by manually
+// searching through the debug information (not using the
+// .debug_pubnames section). The string must match the entire name
+// and case sensitive searches are an option.
+//----------------------------------------------------------------------
+bool
+DWARFDebugInfo::Find(const char* name, bool ignore_case, vector<dw_offset_t>& die_offsets) const
+{
+    die_offsets.clear();
+    if (name && name[0])
+    {
+        FindCallbackStringInfo info = { name, ignore_case, NULL, die_offsets };
+        DWARFDebugInfo::Parse(m_dwarf2Data, FindCallbackString, &info);
+    }
+    return !die_offsets.empty();
+}
+
+//----------------------------------------------------------------------
+// Find
+//
+// Finds all DIE that have a specific DW_AT_name attribute by manually
+// searching through the debug information (not using the
+// .debug_pubnames section). The string must match the supplied regular
+// expression.
+//----------------------------------------------------------------------
+bool
+DWARFDebugInfo::Find(RegularExpression& re, vector<dw_offset_t>& die_offsets) const
+{
+    die_offsets.clear();
+    FindCallbackStringInfo info = { NULL, false, &re, die_offsets };
+    DWARFDebugInfo::Parse(m_dwarf2Data, FindCallbackString, &info);
+    return !die_offsets.empty();
+}
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h
new file mode 100644
index 000000000000..50a7ae76921f
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.h
@@ -0,0 +1,89 @@
+//===-- DWARFDebugInfo.h ----------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SymbolFileDWARF_DWARFDebugInfo_h_
+#define SymbolFileDWARF_DWARFDebugInfo_h_
+
+#include <vector>
+#include <map>
+
+#include "lldb/lldb-private.h"
+#include "lldb/lldb-private.h"
+#include "SymbolFileDWARF.h"
+
+typedef std::multimap<const char*, dw_offset_t, CStringCompareFunctionObject> CStringToDIEMap;
+typedef CStringToDIEMap::iterator CStringToDIEMapIter;
+typedef CStringToDIEMap::const_iterator CStringToDIEMapConstIter;
+
+typedef std::shared_ptr<DWARFCompileUnit> DWARFCompileUnitSP;
+
+class DWARFDebugInfo
+{
+public:
+    typedef dw_offset_t (*Callback)(
+        SymbolFileDWARF* dwarf2Data,
+        DWARFCompileUnitSP& cu_shared_ptr,
+        DWARFDebugInfoEntry* die,
+        const dw_offset_t next_offset,
+        const uint32_t depth,
+        void* userData);
+
+    DWARFDebugInfo();
+    void SetDwarfData(SymbolFileDWARF* dwarf2Data);
+
+    bool LookupAddress(
+            const dw_addr_t address,
+            const dw_offset_t cu_offset,    // Can be valid (find in .debug_aranges), or DW_INVALID_OFFSET if we need to search manually
+            DWARFCompileUnitSP& cu_shared_ptr,
+            DWARFDebugInfoEntry** function_die,
+            DWARFDebugInfoEntry** block_die);
+
+    void AddCompileUnit(DWARFCompileUnitSP& cu);
+    size_t GetNumCompileUnits();
+    bool ContainsCompileUnit (const DWARFCompileUnit *cu) const;
+    DWARFCompileUnit* GetCompileUnitAtIndex(uint32_t idx);
+    DWARFCompileUnitSP GetCompileUnit(dw_offset_t cu_offset, uint32_t* idx_ptr = NULL);
+    DWARFCompileUnitSP GetCompileUnitContainingDIE(dw_offset_t die_offset);
+
+    DWARFDebugInfoEntry* GetDIEPtr(dw_offset_t die_offset, DWARFCompileUnitSP* cu_sp_ptr);
+    DWARFDebugInfoEntry* GetDIEPtrWithCompileUnitHint (dw_offset_t die_offset, DWARFCompileUnit**cu_handle);
+
+    const DWARFDebugInfoEntry* GetDIEPtrContainingOffset(dw_offset_t die_offset, DWARFCompileUnitSP* cu_sp_ptr);
+
+    void Dump(lldb_private::Stream *s, const uint32_t die_offset, const uint32_t recurse_depth);
+    static void Parse(SymbolFileDWARF* parser, Callback callback, void* userData);
+    static void Verify(lldb_private::Stream *s, SymbolFileDWARF* dwarf2Data);
+    static void Dump(lldb_private::Stream *s, SymbolFileDWARF* dwarf2Data, const uint32_t die_offset, const uint32_t recurse_depth);
+    bool Find(const char* name, bool ignore_case, std::vector<dw_offset_t>& die_offsets) const;
+    bool Find(lldb_private::RegularExpression& re, std::vector<dw_offset_t>& die_offsets) const;
+
+    enum
+    {
+        eDumpFlag_Verbose               = (1<<0),   // Verbose dumping
+        eDumpFlag_ShowForm              = (1<<1),   // Show the DW_form type
+        eDumpFlag_ShowAncestors         = (1<<2)    // Show all parent DIEs when dumping single DIEs
+    };
+
+    DWARFDebugAranges &
+    GetCompileUnitAranges ();
+
+protected:
+    SymbolFileDWARF* m_dwarf2Data;
+    typedef std::vector<DWARFCompileUnitSP>     CompileUnitColl;
+    CompileUnitColl m_compile_units;
+    std::unique_ptr<DWARFDebugAranges> m_cu_aranges_ap; // A quick address to compile unit table
+
+private:
+    // All parsing needs to be done partially any managed by this class as accessors are called.
+    void ParseCompileUnitHeadersIfNeeded();
+
+    DISALLOW_COPY_AND_ASSIGN (DWARFDebugInfo);
+};
+
+#endif  // SymbolFileDWARF_DWARFDebugInfo_h_
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
new file mode 100644
index 000000000000..03c12e366f92
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
@@ -0,0 +1,2317 @@
+//===-- DWARFDebugInfoEntry.cpp ---------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFDebugInfoEntry.h"
+
+#include <assert.h>
+
+#include <algorithm>
+
+#include "lldb/Core/Module.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Expression/DWARFExpression.h"
+#include "lldb/Symbol/ObjectFile.h"
+
+#include "DWARFCompileUnit.h"
+#include "SymbolFileDWARF.h"
+#include "DWARFDebugAbbrev.h"
+#include "DWARFDebugAranges.h"
+#include "DWARFDebugInfo.h"
+#include "DWARFDeclContext.h"
+#include "DWARFDIECollection.h"
+#include "DWARFFormValue.h"
+#include "DWARFLocationDescription.h"
+#include "DWARFLocationList.h"
+#include "DWARFDebugRanges.h"
+
+using namespace lldb_private;
+using namespace std;
+extern int g_verbose;
+
+
+
+DWARFDebugInfoEntry::Attributes::Attributes() :
+    m_infos()
+{
+}
+
+DWARFDebugInfoEntry::Attributes::~Attributes()
+{
+}
+
+
+uint32_t
+DWARFDebugInfoEntry::Attributes::FindAttributeIndex(dw_attr_t attr) const
+{
+    collection::const_iterator end = m_infos.end();
+    collection::const_iterator beg = m_infos.begin();
+    collection::const_iterator pos;
+    for (pos = beg; pos != end; ++pos)
+    {
+        if (pos->attr == attr)
+            return std::distance(beg, pos);
+    }
+    return UINT32_MAX;
+}
+
+void
+DWARFDebugInfoEntry::Attributes::Append(const DWARFCompileUnit *cu, dw_offset_t attr_die_offset, dw_attr_t attr, dw_form_t form)
+{
+    Info info = { cu, attr_die_offset, attr, form };
+    m_infos.push_back(info);
+}
+
+bool
+DWARFDebugInfoEntry::Attributes::ContainsAttribute(dw_attr_t attr) const
+{
+    return FindAttributeIndex(attr) != UINT32_MAX;
+}
+
+bool
+DWARFDebugInfoEntry::Attributes::RemoveAttribute(dw_attr_t attr)
+{
+    uint32_t attr_index = FindAttributeIndex(attr);
+    if (attr_index != UINT32_MAX)
+    {
+        m_infos.erase(m_infos.begin() + attr_index);
+        return true;
+    }
+    return false;
+}
+
+bool
+DWARFDebugInfoEntry::Attributes::ExtractFormValueAtIndex (SymbolFileDWARF* dwarf2Data, uint32_t i, DWARFFormValue &form_value) const
+{
+    form_value.SetForm(FormAtIndex(i));
+    lldb::offset_t offset = DIEOffsetAtIndex(i);
+    return form_value.ExtractValue(dwarf2Data->get_debug_info_data(), &offset, CompileUnitAtIndex(i));
+}
+
+uint64_t
+DWARFDebugInfoEntry::Attributes::FormValueAsUnsigned (SymbolFileDWARF* dwarf2Data, dw_attr_t attr, uint64_t fail_value) const
+{
+    const uint32_t attr_idx = FindAttributeIndex (attr);
+    if (attr_idx != UINT32_MAX)
+        return FormValueAsUnsignedAtIndex (dwarf2Data, attr_idx, fail_value);
+    return fail_value;
+}
+
+uint64_t
+DWARFDebugInfoEntry::Attributes::FormValueAsUnsignedAtIndex(SymbolFileDWARF* dwarf2Data, uint32_t i, uint64_t fail_value) const
+{
+    DWARFFormValue form_value;
+    if (ExtractFormValueAtIndex(dwarf2Data, i, form_value))
+        return form_value.Reference(CompileUnitAtIndex(i));
+    return fail_value;
+}
+
+
+
+bool
+DWARFDebugInfoEntry::FastExtract
+(
+    const DataExtractor& debug_info_data,
+    const DWARFCompileUnit* cu,
+    const uint8_t *fixed_form_sizes,
+    lldb::offset_t *offset_ptr
+)
+{
+    m_offset = *offset_ptr;
+    m_parent_idx = 0;
+    m_sibling_idx = 0;
+    m_empty_children = false;
+    const uint64_t abbr_idx = debug_info_data.GetULEB128 (offset_ptr);
+    assert (abbr_idx < (1 << DIE_ABBR_IDX_BITSIZE));
+    m_abbr_idx = abbr_idx;
+    
+    //assert (fixed_form_sizes);  // For best performance this should be specified!
+    
+    if (m_abbr_idx)
+    {
+        lldb::offset_t offset = *offset_ptr;
+
+        const DWARFAbbreviationDeclaration *abbrevDecl = cu->GetAbbreviations()->GetAbbreviationDeclaration(m_abbr_idx);
+        
+        if (abbrevDecl == NULL)
+        {
+            cu->GetSymbolFileDWARF()->GetObjectFile()->GetModule()->ReportError ("{0x%8.8x}: invalid abbreviation code %u, please file a bug and attach the file at the start of this error message", 
+                                                                                 m_offset, 
+                                                                                 (unsigned)abbr_idx);
+            // WE can't parse anymore if the DWARF is borked...
+            *offset_ptr = UINT32_MAX;
+            return false;
+        }
+        m_tag = abbrevDecl->Tag();
+        m_has_children = abbrevDecl->HasChildren();
+        // Skip all data in the .debug_info for the attributes
+        const uint32_t numAttributes = abbrevDecl->NumAttributes();
+        register uint32_t i;
+        register dw_form_t form;
+        for (i=0; i<numAttributes; ++i)
+        {
+            form = abbrevDecl->GetFormByIndexUnchecked(i);
+
+            const uint8_t fixed_skip_size = fixed_form_sizes [form];
+            if (fixed_skip_size)
+                offset += fixed_skip_size;
+            else
+            {
+                bool form_is_indirect = false;
+                do
+                {
+                    form_is_indirect = false;
+                    register uint32_t form_size = 0;
+                    switch (form)
+                    {
+                    // Blocks if inlined data that have a length field and the data bytes
+                    // inlined in the .debug_info
+                    case DW_FORM_exprloc     :
+                    case DW_FORM_block       : form_size = debug_info_data.GetULEB128 (&offset);      break;
+                    case DW_FORM_block1      : form_size = debug_info_data.GetU8_unchecked (&offset); break;
+                    case DW_FORM_block2      : form_size = debug_info_data.GetU16_unchecked (&offset);break;
+                    case DW_FORM_block4      : form_size = debug_info_data.GetU32_unchecked (&offset);break;
+
+                    // Inlined NULL terminated C-strings
+                    case DW_FORM_string      :
+                        debug_info_data.GetCStr (&offset);
+                        break;
+
+                    // Compile unit address sized values
+                    case DW_FORM_addr        :
+                        form_size = cu->GetAddressByteSize();
+                        break;
+                    case DW_FORM_ref_addr    :
+                        if (cu->GetVersion() <= 2)
+                            form_size = cu->GetAddressByteSize();
+                        else
+                            form_size = 4; // 4 bytes for DWARF 32, 8 bytes for DWARF 64, but we don't support DWARF64 yet
+                        break;
+
+                    // 0 sized form
+                    case DW_FORM_flag_present:
+                        form_size = 0;
+                        break;
+
+                    // 1 byte values
+                    case DW_FORM_data1       :
+                    case DW_FORM_flag        :
+                    case DW_FORM_ref1        :
+                        form_size = 1;
+                        break;
+
+                    // 2 byte values
+                    case DW_FORM_data2       :
+                    case DW_FORM_ref2        :
+                        form_size = 2;
+                        break;
+
+                    // 4 byte values
+                    case DW_FORM_strp        :
+                    case DW_FORM_data4       :
+                    case DW_FORM_ref4        :
+                        form_size = 4;
+                        break;
+
+                    // 8 byte values
+                    case DW_FORM_data8       :
+                    case DW_FORM_ref8        :
+                    case DW_FORM_ref_sig8    :
+                        form_size = 8;
+                        break;
+
+                    // signed or unsigned LEB 128 values
+                    case DW_FORM_sdata       :
+                    case DW_FORM_udata       :
+                    case DW_FORM_ref_udata   :
+                        debug_info_data.Skip_LEB128 (&offset);
+                        break;
+
+                    case DW_FORM_indirect    :
+                        form_is_indirect = true;
+                        form = debug_info_data.GetULEB128 (&offset);
+                        break;
+
+                    case DW_FORM_sec_offset  :
+                        if (cu->GetAddressByteSize () == 4)
+                            debug_info_data.GetU32 (offset_ptr);
+                        else
+                            debug_info_data.GetU64 (offset_ptr);
+                        break;
+
+                    default:
+                        *offset_ptr = m_offset;
+                        return false;
+                    }
+                    offset += form_size;
+
+                } while (form_is_indirect);
+            }
+        }
+        *offset_ptr = offset;
+        return true;
+    }
+    else
+    {
+        m_tag = 0;
+        m_has_children = false;
+        return true;    // NULL debug tag entry
+    }
+
+    return false;
+}
+
+//----------------------------------------------------------------------
+// Extract
+//
+// Extract a debug info entry for a given compile unit from the
+// .debug_info and .debug_abbrev data within the SymbolFileDWARF class
+// starting at the given offset
+//----------------------------------------------------------------------
+bool
+DWARFDebugInfoEntry::Extract
+(
+    SymbolFileDWARF* dwarf2Data,
+    const DWARFCompileUnit* cu,
+    lldb::offset_t *offset_ptr
+)
+{
+    const DataExtractor& debug_info_data = dwarf2Data->get_debug_info_data();
+//    const DataExtractor& debug_str_data = dwarf2Data->get_debug_str_data();
+    const uint32_t cu_end_offset = cu->GetNextCompileUnitOffset();
+    const uint8_t cu_addr_size = cu->GetAddressByteSize();
+    lldb::offset_t offset = *offset_ptr;
+//  if (offset >= cu_end_offset)
+//      Log::Error("DIE at offset 0x%8.8x is beyond the end of the current compile unit (0x%8.8x)", m_offset, cu_end_offset);
+    if ((offset < cu_end_offset) && debug_info_data.ValidOffset(offset))
+    {
+        m_offset = offset;
+
+        const uint64_t abbr_idx = debug_info_data.GetULEB128(&offset);
+        assert (abbr_idx < (1 << DIE_ABBR_IDX_BITSIZE));
+        m_abbr_idx = abbr_idx;
+        if (abbr_idx)
+        {
+            const DWARFAbbreviationDeclaration *abbrevDecl = cu->GetAbbreviations()->GetAbbreviationDeclaration(abbr_idx);
+
+            if (abbrevDecl)
+            {
+                m_tag = abbrevDecl->Tag();
+                m_has_children = abbrevDecl->HasChildren();
+
+                bool isCompileUnitTag = m_tag == DW_TAG_compile_unit;
+                if (cu && isCompileUnitTag)
+                    ((DWARFCompileUnit*)cu)->SetBaseAddress(0);
+
+                // Skip all data in the .debug_info for the attributes
+                const uint32_t numAttributes = abbrevDecl->NumAttributes();
+                uint32_t i;
+                dw_attr_t attr;
+                dw_form_t form;
+                for (i=0; i<numAttributes; ++i)
+                {
+                    abbrevDecl->GetAttrAndFormByIndexUnchecked(i, attr, form);
+
+                    if (isCompileUnitTag && ((attr == DW_AT_entry_pc) || (attr == DW_AT_low_pc)))
+                    {
+                        DWARFFormValue form_value(form);
+                        if (form_value.ExtractValue(debug_info_data, &offset, cu))
+                        {
+                            if (attr == DW_AT_low_pc || attr == DW_AT_entry_pc)
+                                ((DWARFCompileUnit*)cu)->SetBaseAddress(form_value.Unsigned());
+                        }
+                    }
+                    else
+                    {
+                        bool form_is_indirect = false;
+                        do
+                        {
+                            form_is_indirect = false;
+                            register uint32_t form_size = 0;
+                            switch (form)
+                            {
+                            // Blocks if inlined data that have a length field and the data bytes
+                            // inlined in the .debug_info
+                            case DW_FORM_exprloc     :
+                            case DW_FORM_block       : form_size = debug_info_data.GetULEB128(&offset);  break;
+                            case DW_FORM_block1      : form_size = debug_info_data.GetU8(&offset);       break;
+                            case DW_FORM_block2      : form_size = debug_info_data.GetU16(&offset);      break;
+                            case DW_FORM_block4      : form_size = debug_info_data.GetU32(&offset);      break;
+
+                            // Inlined NULL terminated C-strings
+                            case DW_FORM_string      : debug_info_data.GetCStr(&offset);                 break;
+
+                            // Compile unit address sized values
+                            case DW_FORM_addr        :
+                                form_size = cu_addr_size;
+                                break;
+                            case DW_FORM_ref_addr    :
+                                if (cu->GetVersion() <= 2)
+                                    form_size = cu_addr_size;
+                                else
+                                    form_size = 4; // 4 bytes for DWARF 32, 8 bytes for DWARF 64, but we don't support DWARF64 yet
+                                break;
+
+                            // 0 sized form
+                            case DW_FORM_flag_present:
+                                form_size = 0;
+                                break;
+
+                            // 1 byte values
+                            case DW_FORM_data1       :
+                            case DW_FORM_flag        :
+                            case DW_FORM_ref1        :
+                                form_size = 1;
+                                break;
+
+                            // 2 byte values
+                            case DW_FORM_data2       :
+                            case DW_FORM_ref2        :
+                                form_size = 2;
+                                break;
+
+                            // 4 byte values
+                            case DW_FORM_strp        :
+                                form_size = 4;
+                                break;
+
+                            case DW_FORM_data4       :
+                            case DW_FORM_ref4        :
+                                form_size = 4;
+                                break;
+
+                            // 8 byte values
+                            case DW_FORM_data8       :
+                            case DW_FORM_ref8        :
+                            case DW_FORM_ref_sig8    :
+                                form_size = 8;
+                                break;
+
+                            // signed or unsigned LEB 128 values
+                            case DW_FORM_sdata       :
+                            case DW_FORM_udata       :
+                            case DW_FORM_ref_udata   :
+                                debug_info_data.Skip_LEB128(&offset);
+                                break;
+
+                            case DW_FORM_indirect    :
+                                form = debug_info_data.GetULEB128(&offset);
+                                form_is_indirect = true;
+                                break;
+
+                            case DW_FORM_sec_offset  :
+                                if (cu->GetAddressByteSize () == 4)
+                                    debug_info_data.GetU32 (offset_ptr);
+                                else
+                                    debug_info_data.GetU64 (offset_ptr);
+                                break;
+
+                            default:
+                                *offset_ptr = offset;
+                                return false;
+                            }
+
+                            offset += form_size;
+                        } while (form_is_indirect);
+                    }
+                }
+                *offset_ptr = offset;
+                return true;
+            }
+        }
+        else
+        {
+            m_tag = 0;
+            m_has_children = false;
+            *offset_ptr = offset;
+            return true;    // NULL debug tag entry
+        }
+    }
+
+    return false;
+}
+
+//----------------------------------------------------------------------
+// DumpAncestry
+//
+// Dumps all of a debug information entries parents up until oldest and
+// all of it's attributes to the specified stream.
+//----------------------------------------------------------------------
+void
+DWARFDebugInfoEntry::DumpAncestry
+(
+    SymbolFileDWARF* dwarf2Data,
+    const DWARFCompileUnit* cu,
+    const DWARFDebugInfoEntry* oldest,
+    Stream &s,
+    uint32_t recurse_depth
+) const
+{
+    const DWARFDebugInfoEntry* parent = GetParent();
+    if (parent && parent != oldest)
+        parent->DumpAncestry(dwarf2Data, cu, oldest, s, 0);
+    Dump(dwarf2Data, cu, s, recurse_depth);
+}
+
+//----------------------------------------------------------------------
+// Compare two DIE by comparing all their attributes values, and
+// following all DW_FORM_ref attributes and comparing their contents as
+// well (except for DW_AT_sibling attributes.
+//
+//  DWARFDebugInfoEntry::CompareState compare_state;
+//  int result = DWARFDebugInfoEntry::Compare(this, 0x00017ccb, 0x0001eb2b, compare_state, false, true);
+//----------------------------------------------------------------------
+//int
+//DWARFDebugInfoEntry::Compare
+//(
+//    SymbolFileDWARF* dwarf2Data,
+//    dw_offset_t a_die_offset,
+//    dw_offset_t b_die_offset,
+//    CompareState &compare_state,
+//    bool compare_siblings,
+//    bool compare_children
+//)
+//{
+//    if (a_die_offset == b_die_offset)
+//        return 0;
+//
+//    DWARFCompileUnitSP a_cu_sp;
+//    DWARFCompileUnitSP b_cu_sp;
+//    const DWARFDebugInfoEntry* a_die = dwarf2Data->DebugInfo()->GetDIEPtr(a_die_offset, &a_cu_sp);
+//    const DWARFDebugInfoEntry* b_die = dwarf2Data->DebugInfo()->GetDIEPtr(b_die_offset, &b_cu_sp);
+//
+//    return Compare(dwarf2Data, a_cu_sp.get(), a_die, b_cu_sp.get(), b_die, compare_state, compare_siblings, compare_children);
+//}
+//
+//int
+//DWARFDebugInfoEntry::Compare
+//(
+//    SymbolFileDWARF* dwarf2Data,
+//    DWARFCompileUnit* a_cu, const DWARFDebugInfoEntry* a_die,
+//    DWARFCompileUnit* b_cu, const DWARFDebugInfoEntry* b_die,
+//    CompareState &compare_state,
+//    bool compare_siblings,
+//    bool compare_children
+//)
+//{
+//    if (a_die == b_die)
+//        return 0;
+//
+//    if (!compare_state.AddTypePair(a_die->GetOffset(), b_die->GetOffset()))
+//    {
+//        // We are already comparing both of these types, so let
+//        // compares complete for the real result
+//        return 0;
+//    }
+//
+//    //printf("DWARFDebugInfoEntry::Compare(0x%8.8x, 0x%8.8x)\n", a_die->GetOffset(), b_die->GetOffset());
+//
+//    // Do we have two valid DIEs?
+//    if (a_die && b_die)
+//    {
+//        // Both DIE are valid
+//        int result = 0;
+//
+//        const dw_tag_t a_tag = a_die->Tag();
+//        const dw_tag_t b_tag = b_die->Tag();
+//        if (a_tag == 0 && b_tag == 0)
+//            return 0;
+//
+//        //printf("    comparing tags: %s and %s\n", DW_TAG_value_to_name(a_tag), DW_TAG_value_to_name(b_tag));
+//
+//        if (a_tag < b_tag)
+//            return -1;
+//        else if (a_tag > b_tag)
+//            return 1;
+//
+//        DWARFDebugInfoEntry::Attributes a_attrs;
+//        DWARFDebugInfoEntry::Attributes b_attrs;
+//        size_t a_attr_count = a_die->GetAttributes(dwarf2Data, a_cu, a_attrs);
+//        size_t b_attr_count = b_die->GetAttributes(dwarf2Data, b_cu, b_attrs);
+//        if (a_attr_count != b_attr_count)
+//        {
+//            a_attrs.RemoveAttribute(DW_AT_sibling);
+//            b_attrs.RemoveAttribute(DW_AT_sibling);
+//        }
+//
+//        a_attr_count = a_attrs.Size();
+//        b_attr_count = b_attrs.Size();
+//
+//        DWARFFormValue a_form_value;
+//        DWARFFormValue b_form_value;
+//
+//        if (a_attr_count != b_attr_count)
+//        {
+//            uint32_t is_decl_index = a_attrs.FindAttributeIndex(DW_AT_declaration);
+//            uint32_t a_name_index = UINT32_MAX;
+//            uint32_t b_name_index = UINT32_MAX;
+//            if (is_decl_index != UINT32_MAX)
+//            {
+//                if (a_attr_count == 2)
+//                {
+//                    a_name_index = a_attrs.FindAttributeIndex(DW_AT_name);
+//                    b_name_index = b_attrs.FindAttributeIndex(DW_AT_name);
+//                }
+//            }
+//            else
+//            {
+//                is_decl_index = b_attrs.FindAttributeIndex(DW_AT_declaration);
+//                if (is_decl_index != UINT32_MAX && a_attr_count == 2)
+//                {
+//                    a_name_index = a_attrs.FindAttributeIndex(DW_AT_name);
+//                    b_name_index = b_attrs.FindAttributeIndex(DW_AT_name);
+//                }
+//            }
+//            if (a_name_index != UINT32_MAX && b_name_index != UINT32_MAX)
+//            {
+//                if (a_attrs.ExtractFormValueAtIndex(dwarf2Data, a_name_index, a_form_value) &&
+//                    b_attrs.ExtractFormValueAtIndex(dwarf2Data, b_name_index, b_form_value))
+//                {
+//                    result = DWARFFormValue::Compare (a_form_value, b_form_value, a_cu, b_cu, &dwarf2Data->get_debug_str_data());
+//                    if (result == 0)
+//                    {
+//                        a_attr_count = b_attr_count = 0;
+//                        compare_children = false;
+//                    }
+//                }
+//            }
+//        }
+//
+//        if (a_attr_count < b_attr_count)
+//            return -1;
+//        if (a_attr_count > b_attr_count)
+//            return 1;
+//
+//
+//        // The number of attributes are the same...
+//        if (a_attr_count > 0)
+//        {
+//            const DataExtractor* debug_str_data_ptr = &dwarf2Data->get_debug_str_data();
+//
+//            uint32_t i;
+//            for (i=0; i<a_attr_count; ++i)
+//            {
+//                const dw_attr_t a_attr = a_attrs.AttributeAtIndex(i);
+//                const dw_attr_t b_attr = b_attrs.AttributeAtIndex(i);
+//                //printf("    comparing attributes\n\t\t0x%8.8x: %s %s\t\t0x%8.8x: %s %s\n",
+//                //                a_attrs.DIEOffsetAtIndex(i), DW_FORM_value_to_name(a_attrs.FormAtIndex(i)), DW_AT_value_to_name(a_attr),
+//                //                b_attrs.DIEOffsetAtIndex(i), DW_FORM_value_to_name(b_attrs.FormAtIndex(i)), DW_AT_value_to_name(b_attr));
+//
+//                if (a_attr < b_attr)
+//                    return -1;
+//                else if (a_attr > b_attr)
+//                    return 1;
+//
+//                switch (a_attr)
+//                {
+//                // Since we call a form of GetAttributes which inlines the
+//                // attributes from DW_AT_abstract_origin and DW_AT_specification
+//                // we don't care if their values mismatch...
+//                case DW_AT_abstract_origin:
+//                case DW_AT_specification:
+//                case DW_AT_sibling:
+//                case DW_AT_containing_type:
+//                    //printf("        action = IGNORE\n");
+//                    result = 0;
+//                    break;  // ignore
+//
+//                default:
+//                    if (a_attrs.ExtractFormValueAtIndex(dwarf2Data, i, a_form_value) &&
+//                        b_attrs.ExtractFormValueAtIndex(dwarf2Data, i, b_form_value))
+//                        result = DWARFFormValue::Compare (a_form_value, b_form_value, a_cu, b_cu, debug_str_data_ptr);
+//                    break;
+//                }
+//
+//                //printf("\t  result = %i\n", result);
+//
+//                if (result != 0)
+//                {
+//                    // Attributes weren't equal, lets see if we care?
+//                    switch (a_attr)
+//                    {
+//                    case DW_AT_decl_file:
+//                        // TODO: add the ability to compare files in two different compile units
+//                        if (a_cu == b_cu)
+//                        {
+//                            //printf("        action = RETURN RESULT\n");
+//                            return result;  // Only return the compare results when the compile units are the same and the decl_file attributes can be compared
+//                        }
+//                        else
+//                        {
+//                            result = 0;
+//                            //printf("        action = IGNORE\n");
+//                        }
+//                        break;
+//
+//                    default:
+//                        switch (a_attrs.FormAtIndex(i))
+//                        {
+//                        case DW_FORM_ref1:
+//                        case DW_FORM_ref2:
+//                        case DW_FORM_ref4:
+//                        case DW_FORM_ref8:
+//                        case DW_FORM_ref_udata:
+//                        case DW_FORM_ref_addr:
+//                            //printf("    action = COMPARE DIEs 0x%8.8x 0x%8.8x\n", (dw_offset_t)a_form_value.Reference(a_cu), (dw_offset_t)b_form_value.Reference(b_cu));
+//                            // These attribute values refer to other DIEs, so lets compare those instead of their DIE offsets...
+//                            result = Compare(dwarf2Data, a_form_value.Reference(a_cu), b_form_value.Reference(b_cu), compare_state, false, true);
+//                            if (result != 0)
+//                                return result;
+//                            break;
+//
+//                        default:
+//                            // We do care that they were different, return this result...
+//                            //printf("        action = RETURN RESULT\n");
+//                            return result;
+//                        }
+//                    }
+//                }
+//            }
+//        }
+//        //printf("    SUCCESS\n\t\t0x%8.8x: %s\n\t\t0x%8.8x: %s\n", a_die->GetOffset(), DW_TAG_value_to_name(a_tag), b_die->GetOffset(), DW_TAG_value_to_name(b_tag));
+//
+//        if (compare_children)
+//        {
+//            bool a_has_children = a_die->HasChildren();
+//            bool b_has_children = b_die->HasChildren();
+//            if (a_has_children == b_has_children)
+//            {
+//                // Both either have kids or don't
+//                if (a_has_children)
+//                    result = Compare(   dwarf2Data,
+//                                        a_cu, a_die->GetFirstChild(),
+//                                        b_cu, b_die->GetFirstChild(),
+//                                        compare_state, true, compare_children);
+//                else
+//                    result = 0;
+//            }
+//            else if (!a_has_children)
+//                result = -1;    // A doesn't have kids, but B does
+//            else
+//                result = 1; // A has kids, but B doesn't
+//        }
+//
+//        if (compare_siblings)
+//        {
+//            result = Compare(   dwarf2Data,
+//                                a_cu, a_die->GetSibling(),
+//                                b_cu, b_die->GetSibling(),
+//                                compare_state, true, compare_children);
+//        }
+//
+//        return result;
+//    }
+//
+//    if (a_die == NULL)
+//        return -1;  // a_die is NULL, yet b_die is non-NULL
+//    else
+//        return 1;   // a_die is non-NULL, yet b_die is NULL
+//
+//}
+//
+//
+//int
+//DWARFDebugInfoEntry::Compare
+//(
+//  SymbolFileDWARF* dwarf2Data,
+//  const DWARFCompileUnit* cu_a,
+//  const DWARFDebugInfoEntry* die_a,
+//  const DWARFCompileUnit* cu_a,
+//  const DWARFDebugInfoEntry* die_b,
+//  CompareState &compare_state
+//)
+//{
+//}
+
+//----------------------------------------------------------------------
+// GetDIENamesAndRanges
+//
+// Gets the valid address ranges for a given DIE by looking for a
+// DW_AT_low_pc/DW_AT_high_pc pair, DW_AT_entry_pc, or DW_AT_ranges
+// attributes.
+//----------------------------------------------------------------------
+bool
+DWARFDebugInfoEntry::GetDIENamesAndRanges
+(
+    SymbolFileDWARF* dwarf2Data,
+    const DWARFCompileUnit* cu,
+    const char * &name,
+    const char * &mangled,
+    DWARFDebugRanges::RangeList& ranges,
+    int& decl_file,
+    int& decl_line,
+    int& decl_column,
+    int& call_file,
+    int& call_line,
+    int& call_column,
+    DWARFExpression *frame_base
+) const
+{
+    if (dwarf2Data == NULL)
+        return false;
+
+    dw_addr_t lo_pc = LLDB_INVALID_ADDRESS;
+    dw_addr_t hi_pc = LLDB_INVALID_ADDRESS;
+    std::vector<dw_offset_t> die_offsets;
+    bool set_frame_base_loclist_addr = false;
+    
+    lldb::offset_t offset;
+    const DWARFAbbreviationDeclaration* abbrevDecl = GetAbbreviationDeclarationPtr(dwarf2Data, cu, offset);
+
+    if (abbrevDecl)
+    {
+        const DataExtractor& debug_info_data = dwarf2Data->get_debug_info_data();
+
+        if (!debug_info_data.ValidOffset(offset))
+            return false;
+
+        const uint32_t numAttributes = abbrevDecl->NumAttributes();
+        uint32_t i;
+        dw_attr_t attr;
+        dw_form_t form;
+        bool do_offset = false;
+
+        for (i=0; i<numAttributes; ++i)
+        {
+            abbrevDecl->GetAttrAndFormByIndexUnchecked(i, attr, form);
+            DWARFFormValue form_value(form);
+            if (form_value.ExtractValue(debug_info_data, &offset, cu))
+            {
+                switch (attr)
+                {
+                case DW_AT_low_pc:
+                    lo_pc = form_value.Unsigned();
+
+                    if (do_offset)
+                        hi_pc += lo_pc;
+                    do_offset = false;
+                    break;
+
+                case DW_AT_entry_pc:
+                    lo_pc = form_value.Unsigned();
+                    break;
+
+                case DW_AT_high_pc:
+                    hi_pc = form_value.Unsigned();
+                    if (form_value.Form() != DW_FORM_addr)
+                    {
+                        if (lo_pc == LLDB_INVALID_ADDRESS)
+                            do_offset = hi_pc != LLDB_INVALID_ADDRESS;
+                        else
+                            hi_pc += lo_pc; // DWARF 4 introduces <offset-from-lo-pc> to save on relocations
+                    }
+                    break;
+
+                case DW_AT_ranges:
+                    {
+                        const DWARFDebugRanges* debug_ranges = dwarf2Data->DebugRanges();
+                        debug_ranges->FindRanges(form_value.Unsigned(), ranges);
+                        // All DW_AT_ranges are relative to the base address of the
+                        // compile unit. We add the compile unit base address to make
+                        // sure all the addresses are properly fixed up.
+                        ranges.Slide(cu->GetBaseAddress());
+                    }
+                    break;
+
+                case DW_AT_name:
+                    if (name == NULL)
+                        name = form_value.AsCString(&dwarf2Data->get_debug_str_data());
+                    break;
+
+                case DW_AT_MIPS_linkage_name:
+                case DW_AT_linkage_name:
+                    if (mangled == NULL)
+                        mangled = form_value.AsCString(&dwarf2Data->get_debug_str_data());
+                    break;
+
+                case DW_AT_abstract_origin:
+                    die_offsets.push_back(form_value.Reference(cu));
+                    break;
+
+                case DW_AT_specification:
+                    die_offsets.push_back(form_value.Reference(cu));
+                    break;
+
+                case DW_AT_decl_file:
+                    if (decl_file == 0)
+                        decl_file = form_value.Unsigned();
+                    break;
+
+                case DW_AT_decl_line:
+                    if (decl_line == 0)
+                        decl_line = form_value.Unsigned();
+                    break;
+
+                case DW_AT_decl_column:
+                    if (decl_column == 0)
+                        decl_column = form_value.Unsigned();
+                    break;
+
+                case DW_AT_call_file:
+                    if (call_file == 0)
+                        call_file = form_value.Unsigned();
+                    break;
+
+                case DW_AT_call_line:
+                    if (call_line == 0)
+                        call_line = form_value.Unsigned();
+                    break;
+
+                case DW_AT_call_column:
+                    if (call_column == 0)
+                        call_column = form_value.Unsigned();
+                    break;
+
+                case DW_AT_frame_base:
+                    if (frame_base)
+                    {
+                        if (form_value.BlockData())
+                        {
+                            uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart();
+                            uint32_t block_length = form_value.Unsigned();
+                            frame_base->SetOpcodeData(debug_info_data, block_offset, block_length);
+                        }
+                        else
+                        {
+                            const DataExtractor &debug_loc_data = dwarf2Data->get_debug_loc_data();
+                            const dw_offset_t debug_loc_offset = form_value.Unsigned();
+
+                            size_t loc_list_length = DWARFLocationList::Size(debug_loc_data, debug_loc_offset);
+                            if (loc_list_length > 0)
+                            {
+                                frame_base->SetOpcodeData(debug_loc_data, debug_loc_offset, loc_list_length);
+                                if (lo_pc != LLDB_INVALID_ADDRESS)
+                                {
+                                    assert (lo_pc >= cu->GetBaseAddress());
+                                    frame_base->SetLocationListSlide(lo_pc - cu->GetBaseAddress());
+                                }
+                                else
+                                {
+                                    set_frame_base_loclist_addr = true;
+                                }
+                            }
+                        }
+                    }
+                    break;
+
+                default:
+                    break;
+                }
+            }
+        }
+    }
+
+    if (ranges.IsEmpty())
+    {
+        if (lo_pc != LLDB_INVALID_ADDRESS)
+        {
+            if (hi_pc != LLDB_INVALID_ADDRESS && hi_pc > lo_pc)
+                ranges.Append(DWARFDebugRanges::Range (lo_pc, hi_pc - lo_pc));
+            else
+                ranges.Append(DWARFDebugRanges::Range (lo_pc, 0));
+        }
+    }
+    
+    if (set_frame_base_loclist_addr)
+    {
+        dw_addr_t lowest_range_pc = ranges.GetMinRangeBase(0);
+        assert (lowest_range_pc >= cu->GetBaseAddress());
+        frame_base->SetLocationListSlide (lowest_range_pc - cu->GetBaseAddress());
+    }
+
+    if (ranges.IsEmpty() || name == NULL || mangled == NULL)
+    {
+        std::vector<dw_offset_t>::const_iterator pos;
+        std::vector<dw_offset_t>::const_iterator end = die_offsets.end();
+        for (pos = die_offsets.begin(); pos != end; ++pos)
+        {
+            DWARFCompileUnitSP cu_sp_ptr;
+            const DWARFDebugInfoEntry* die = NULL;
+            dw_offset_t die_offset = *pos;
+            if (die_offset != DW_INVALID_OFFSET)
+            {
+                die = dwarf2Data->DebugInfo()->GetDIEPtr(die_offset, &cu_sp_ptr);
+                if (die)
+                    die->GetDIENamesAndRanges(dwarf2Data, cu_sp_ptr.get(), name, mangled, ranges, decl_file, decl_line, decl_column, call_file, call_line, call_column);
+            }
+        }
+    }
+    return !ranges.IsEmpty();
+}
+
+//----------------------------------------------------------------------
+// Dump
+//
+// Dumps a debug information entry and all of it's attributes to the
+// specified stream.
+//----------------------------------------------------------------------
+void
+DWARFDebugInfoEntry::Dump
+(
+    SymbolFileDWARF* dwarf2Data,
+    const DWARFCompileUnit* cu,
+    Stream &s,
+    uint32_t recurse_depth
+) const
+{
+    const DataExtractor& debug_info_data = dwarf2Data->get_debug_info_data();
+    lldb::offset_t offset = m_offset;
+
+    if (debug_info_data.ValidOffset(offset))
+    {
+        dw_uleb128_t abbrCode = debug_info_data.GetULEB128(&offset);
+
+        s.Printf("\n0x%8.8x: ", m_offset);
+        s.Indent();
+        if (abbrCode != m_abbr_idx)
+        {
+            s.Printf( "error: DWARF has been modified\n");
+        }
+        else if (abbrCode)
+        {
+            const DWARFAbbreviationDeclaration* abbrevDecl = cu->GetAbbreviations()->GetAbbreviationDeclaration (abbrCode);
+
+            if (abbrevDecl)
+            {
+                s.PutCString(DW_TAG_value_to_name(abbrevDecl->Tag()));
+                s.Printf( " [%u] %c\n", abbrCode, abbrevDecl->HasChildren() ? '*':' ');
+
+                // Dump all data in the .debug_info for the attributes
+                const uint32_t numAttributes = abbrevDecl->NumAttributes();
+                uint32_t i;
+                dw_attr_t attr;
+                dw_form_t form;
+                for (i=0; i<numAttributes; ++i)
+                {
+                    abbrevDecl->GetAttrAndFormByIndexUnchecked(i, attr, form);
+
+                    DumpAttribute(dwarf2Data, cu, debug_info_data, &offset, s, attr, form);
+                }
+
+                const DWARFDebugInfoEntry* child = GetFirstChild();
+                if (recurse_depth > 0 && child)
+                {
+                    s.IndentMore();
+
+                    while (child)
+                    {
+                        child->Dump(dwarf2Data, cu, s, recurse_depth-1);
+                        child = child->GetSibling();
+                    }
+                    s.IndentLess();
+                }
+            }
+            else
+                s.Printf( "Abbreviation code note found in 'debug_abbrev' class for code: %u\n", abbrCode);
+        }
+        else
+        {
+            s.Printf( "NULL\n");
+        }
+    }
+}
+
+void
+DWARFDebugInfoEntry::DumpLocation
+(
+    SymbolFileDWARF* dwarf2Data,
+    DWARFCompileUnit* cu,
+    Stream &s
+) const
+{
+    const DWARFDebugInfoEntry *cu_die = cu->GetCompileUnitDIEOnly();
+    const char *cu_name = NULL;
+    if (cu_die != NULL)
+        cu_name = cu_die->GetName (dwarf2Data, cu);
+    const char *obj_file_name = NULL;
+    ObjectFile *obj_file = dwarf2Data->GetObjectFile();
+    if (obj_file)
+        obj_file_name = obj_file->GetFileSpec().GetFilename().AsCString();
+    const char *die_name = GetName (dwarf2Data, cu);
+    s.Printf ("0x%8.8x/0x%8.8x: %-30s (from %s in %s)", 
+              cu->GetOffset(),
+              GetOffset(),
+              die_name ? die_name : "", 
+              cu_name ? cu_name : "<NULL>",
+              obj_file_name ? obj_file_name : "<NULL>");
+}
+
+//----------------------------------------------------------------------
+// DumpAttribute
+//
+// Dumps a debug information entry attribute along with it's form. Any
+// special display of attributes is done (disassemble location lists,
+// show enumeration values for attributes, etc).
+//----------------------------------------------------------------------
+void
+DWARFDebugInfoEntry::DumpAttribute
+(
+    SymbolFileDWARF* dwarf2Data,
+    const DWARFCompileUnit* cu,
+    const DataExtractor& debug_info_data,
+    lldb::offset_t *offset_ptr,
+    Stream &s,
+    dw_attr_t attr,
+    dw_form_t form
+)
+{
+    bool verbose    = s.GetVerbose();
+    bool show_form  = s.GetFlags().Test(DWARFDebugInfo::eDumpFlag_ShowForm);
+    
+    const DataExtractor* debug_str_data = dwarf2Data ? &dwarf2Data->get_debug_str_data() : NULL;
+    if (verbose)
+        s.Offset (*offset_ptr);
+    else
+        s.Printf ("            ");
+    s.Indent(DW_AT_value_to_name(attr));
+
+    if (show_form)
+    {
+        s.Printf( "[%s", DW_FORM_value_to_name(form));
+    }
+
+    DWARFFormValue form_value(form);
+
+    if (!form_value.ExtractValue(debug_info_data, offset_ptr, cu))
+        return;
+
+    if (show_form)
+    {
+        if (form == DW_FORM_indirect)
+        {
+            s.Printf( " [%s]", DW_FORM_value_to_name(form_value.Form()));
+        }
+
+        s.PutCString("] ");
+    }
+
+    s.PutCString("( ");
+
+    // Always dump form value if verbose is enabled
+    if (verbose)
+    {
+        form_value.Dump(s, debug_str_data, cu);
+    }
+
+
+    // Check to see if we have any special attribute formatters
+    switch (attr)
+    {
+    case DW_AT_stmt_list:
+        if ( verbose ) s.PutCString(" ( ");
+        s.Printf( "0x%8.8" PRIx64, form_value.Unsigned());
+        if ( verbose ) s.PutCString(" )");
+        break;
+
+    case DW_AT_language:
+        if ( verbose ) s.PutCString(" ( ");
+        s.PutCString(DW_LANG_value_to_name(form_value.Unsigned()));
+        if ( verbose ) s.PutCString(" )");
+        break;
+
+    case DW_AT_encoding:
+        if ( verbose ) s.PutCString(" ( ");
+        s.PutCString(DW_ATE_value_to_name(form_value.Unsigned()));
+        if ( verbose ) s.PutCString(" )");
+        break;
+
+    case DW_AT_frame_base:
+    case DW_AT_location:
+    case DW_AT_data_member_location:
+        {
+            const uint8_t* blockData = form_value.BlockData();
+            if (blockData)
+            {
+                if (!verbose)
+                    form_value.Dump(s, debug_str_data, cu);
+
+                // Location description is inlined in data in the form value
+                DataExtractor locationData(debug_info_data, (*offset_ptr) - form_value.Unsigned(), form_value.Unsigned());
+                if ( verbose ) s.PutCString(" ( ");
+                print_dwarf_expression (s, locationData, DWARFCompileUnit::GetAddressByteSize(cu), 4, false);
+                if ( verbose ) s.PutCString(" )");
+            }
+            else
+            {
+                // We have a location list offset as the value that is
+                // the offset into the .debug_loc section that describes
+                // the value over it's lifetime
+                uint64_t debug_loc_offset = form_value.Unsigned();
+                if (dwarf2Data)
+                {
+                    if ( !verbose )
+                        form_value.Dump(s, debug_str_data, cu);
+                    DWARFLocationList::Dump(s, cu, dwarf2Data->get_debug_loc_data(), debug_loc_offset);
+                }
+                else
+                {
+                    if ( !verbose )
+                        form_value.Dump(s, NULL, cu);
+                }
+            }
+        }
+        break;
+
+    case DW_AT_abstract_origin:
+    case DW_AT_specification:
+        {
+            uint64_t abstract_die_offset = form_value.Reference(cu);
+            form_value.Dump(s, debug_str_data, cu);
+        //  *ostrm_ptr << HEX32 << abstract_die_offset << " ( ";
+            if ( verbose ) s.PutCString(" ( ");
+            GetName(dwarf2Data, cu, abstract_die_offset, s);
+            if ( verbose ) s.PutCString(" )");
+        }
+        break;
+
+    case DW_AT_type:
+        {
+            uint64_t type_die_offset = form_value.Reference(cu);
+            if (!verbose)
+                form_value.Dump(s, debug_str_data, cu);
+            s.PutCString(" ( ");
+            AppendTypeName(dwarf2Data, cu, type_die_offset, s);
+            s.PutCString(" )");
+        }
+        break;
+
+    case DW_AT_ranges:
+        {
+            if ( !verbose )
+                form_value.Dump(s, debug_str_data, cu);
+            lldb::offset_t ranges_offset = form_value.Unsigned();
+            dw_addr_t base_addr = cu ? cu->GetBaseAddress() : 0;
+            if (dwarf2Data)
+                DWARFDebugRanges::Dump(s, dwarf2Data->get_debug_ranges_data(), &ranges_offset, base_addr);
+        }
+        break;
+
+    default:
+        if ( !verbose )
+            form_value.Dump(s, debug_str_data, cu);
+        break;
+    }
+
+    s.PutCString(" )\n");
+}
+
+//----------------------------------------------------------------------
+// Get all attribute values for a given DIE, including following any
+// specification or abstract origin attributes and including those in
+// the results. Any duplicate attributes will have the first instance
+// take precedence (this can happen for declaration attributes).
+//----------------------------------------------------------------------
+size_t
+DWARFDebugInfoEntry::GetAttributes
+(
+    SymbolFileDWARF* dwarf2Data,
+    const DWARFCompileUnit* cu,
+    const uint8_t *fixed_form_sizes,
+    DWARFDebugInfoEntry::Attributes& attributes,
+    uint32_t curr_depth
+) const
+{
+    lldb::offset_t offset;
+    const DWARFAbbreviationDeclaration* abbrevDecl = GetAbbreviationDeclarationPtr(dwarf2Data, cu, offset);
+
+    if (abbrevDecl)
+    {
+        const DataExtractor& debug_info_data = dwarf2Data->get_debug_info_data();
+
+        if (fixed_form_sizes == NULL)
+            fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize(cu->GetAddressByteSize());
+
+        const uint32_t num_attributes = abbrevDecl->NumAttributes();
+        uint32_t i;
+        dw_attr_t attr;
+        dw_form_t form;
+        DWARFFormValue form_value;
+        for (i=0; i<num_attributes; ++i)
+        {
+            abbrevDecl->GetAttrAndFormByIndexUnchecked (i, attr, form);
+            
+            // If we are tracking down DW_AT_specification or DW_AT_abstract_origin
+            // attributes, the depth will be non-zero. We need to omit certain
+            // attributes that don't make sense.
+            switch (attr)
+            {
+            case DW_AT_sibling:
+            case DW_AT_declaration:
+                if (curr_depth > 0)
+                {
+                    // This attribute doesn't make sense when combined with
+                    // the DIE that references this DIE. We know a DIE is 
+                    // referencing this DIE because curr_depth is not zero
+                    break;  
+                }
+                // Fall through...
+            default:
+                attributes.Append(cu, offset, attr, form);
+                break;
+            }
+
+            if ((attr == DW_AT_specification) || (attr == DW_AT_abstract_origin))
+            {
+                form_value.SetForm(form);
+                if (form_value.ExtractValue(debug_info_data, &offset, cu))
+                {
+                    const DWARFDebugInfoEntry* die = NULL;
+                    dw_offset_t die_offset = form_value.Reference(cu);
+                    if (cu->ContainsDIEOffset(die_offset))
+                    {
+                        die = const_cast<DWARFCompileUnit*>(cu)->GetDIEPtr(die_offset);
+                        if (die)
+                            die->GetAttributes(dwarf2Data, cu, fixed_form_sizes, attributes, curr_depth + 1);
+                    }
+                    else
+                    {
+                        DWARFCompileUnitSP cu_sp_ptr;
+                        die = const_cast<SymbolFileDWARF*>(dwarf2Data)->DebugInfo()->GetDIEPtr(die_offset, &cu_sp_ptr);
+                        if (die)
+                            die->GetAttributes(dwarf2Data, cu_sp_ptr.get(), fixed_form_sizes, attributes, curr_depth + 1);
+                    }
+                }
+            }
+            else
+            {
+                const uint8_t fixed_skip_size = fixed_form_sizes [form];
+                if (fixed_skip_size)
+                    offset += fixed_skip_size;
+                else
+                    DWARFFormValue::SkipValue(form, debug_info_data, &offset, cu);
+            }
+        }
+    }
+    else
+    {
+        attributes.Clear();
+    }
+    return attributes.Size();
+
+}
+
+//----------------------------------------------------------------------
+// GetAttributeValue
+//
+// Get the value of an attribute and return the .debug_info offset of the
+// attribute if it was properly extracted into form_value, or zero
+// if we fail since an offset of zero is invalid for an attribute (it
+// would be a compile unit header).
+//----------------------------------------------------------------------
+dw_offset_t
+DWARFDebugInfoEntry::GetAttributeValue
+(
+    SymbolFileDWARF* dwarf2Data,
+    const DWARFCompileUnit* cu,
+    const dw_attr_t attr,
+    DWARFFormValue& form_value,
+    dw_offset_t* end_attr_offset_ptr
+) const
+{
+    lldb::offset_t offset;
+    const DWARFAbbreviationDeclaration* abbrevDecl = GetAbbreviationDeclarationPtr(dwarf2Data, cu, offset);
+
+    if (abbrevDecl)
+    {
+        uint32_t attr_idx = abbrevDecl->FindAttributeIndex(attr);
+
+        if (attr_idx != DW_INVALID_INDEX)
+        {
+            const DataExtractor& debug_info_data = dwarf2Data->get_debug_info_data();
+
+            uint32_t idx=0;
+            while (idx<attr_idx)
+                DWARFFormValue::SkipValue(abbrevDecl->GetFormByIndex(idx++), debug_info_data, &offset, cu);
+
+            const dw_offset_t attr_offset = offset;
+            form_value.SetForm(abbrevDecl->GetFormByIndex(idx));
+            if (form_value.ExtractValue(debug_info_data, &offset, cu))
+            {
+                if (end_attr_offset_ptr)
+                    *end_attr_offset_ptr = offset;
+                return attr_offset;
+            }
+        }
+    }
+
+    return 0;
+}
+
+//----------------------------------------------------------------------
+// GetAttributeValueAsString
+//
+// Get the value of an attribute as a string return it. The resulting
+// pointer to the string data exists within the supplied SymbolFileDWARF
+// and will only be available as long as the SymbolFileDWARF is still around
+// and it's content doesn't change.
+//----------------------------------------------------------------------
+const char*
+DWARFDebugInfoEntry::GetAttributeValueAsString
+(
+    SymbolFileDWARF* dwarf2Data,
+    const DWARFCompileUnit* cu,
+    const dw_attr_t attr,
+    const char* fail_value) const
+{
+    DWARFFormValue form_value;
+    if (GetAttributeValue(dwarf2Data, cu, attr, form_value))
+        return form_value.AsCString(&dwarf2Data->get_debug_str_data());
+    return fail_value;
+}
+
+//----------------------------------------------------------------------
+// GetAttributeValueAsUnsigned
+//
+// Get the value of an attribute as unsigned and return it.
+//----------------------------------------------------------------------
+uint64_t
+DWARFDebugInfoEntry::GetAttributeValueAsUnsigned
+(
+    SymbolFileDWARF* dwarf2Data,
+    const DWARFCompileUnit* cu,
+    const dw_attr_t attr,
+    uint64_t fail_value
+) const
+{
+    DWARFFormValue form_value;
+    if (GetAttributeValue(dwarf2Data, cu, attr, form_value))
+        return form_value.Unsigned();
+    return fail_value;
+}
+
+//----------------------------------------------------------------------
+// GetAttributeValueAsSigned
+//
+// Get the value of an attribute a signed value and return it.
+//----------------------------------------------------------------------
+int64_t
+DWARFDebugInfoEntry::GetAttributeValueAsSigned
+(
+    SymbolFileDWARF* dwarf2Data,
+    const DWARFCompileUnit* cu,
+    const dw_attr_t attr,
+    int64_t fail_value
+) const
+{
+    DWARFFormValue form_value;
+    if (GetAttributeValue(dwarf2Data, cu, attr, form_value))
+        return form_value.Signed();
+    return fail_value;
+}
+
+//----------------------------------------------------------------------
+// GetAttributeValueAsReference
+//
+// Get the value of an attribute as reference and fix up and compile
+// unit relative offsets as needed.
+//----------------------------------------------------------------------
+uint64_t
+DWARFDebugInfoEntry::GetAttributeValueAsReference
+(
+    SymbolFileDWARF* dwarf2Data,
+    const DWARFCompileUnit* cu,
+    const dw_attr_t attr,
+    uint64_t fail_value
+) const
+{
+    DWARFFormValue form_value;
+    if (GetAttributeValue(dwarf2Data, cu, attr, form_value))
+        return form_value.Reference(cu);
+    return fail_value;
+}
+
+//----------------------------------------------------------------------
+// GetAttributeHighPC
+//
+// Get the hi_pc, adding hi_pc to lo_pc when specified
+// as an <offset-from-low-pc>.
+//
+// Returns the hi_pc or fail_value.
+//----------------------------------------------------------------------
+dw_addr_t
+DWARFDebugInfoEntry::GetAttributeHighPC
+(
+    SymbolFileDWARF* dwarf2Data,
+    const DWARFCompileUnit* cu,
+    dw_addr_t lo_pc,
+    uint64_t fail_value
+) const
+{
+    DWARFFormValue form_value;
+
+    if (GetAttributeValue(dwarf2Data, cu, DW_AT_high_pc, form_value))
+    {
+        dw_addr_t hi_pc = form_value.Unsigned();
+        if (form_value.Form() != DW_FORM_addr)
+            hi_pc += lo_pc; // DWARF4 can specify the hi_pc as an <offset-from-lowpc>
+        return hi_pc; 
+    }
+    return fail_value;
+}
+
+//----------------------------------------------------------------------
+// GetAttributeAddressRange
+//
+// Get the lo_pc and hi_pc, adding hi_pc to lo_pc when specified
+// as an <offset-from-low-pc>.
+//
+// Returns true or sets lo_pc and hi_pc to fail_value.
+//----------------------------------------------------------------------
+bool
+DWARFDebugInfoEntry::GetAttributeAddressRange
+(
+    SymbolFileDWARF* dwarf2Data,
+    const DWARFCompileUnit* cu,
+    dw_addr_t& lo_pc,
+    dw_addr_t& hi_pc,
+    uint64_t fail_value
+) const
+{
+    lo_pc = GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_low_pc, fail_value);
+    if (lo_pc != fail_value)
+    {
+        hi_pc = GetAttributeHighPC(dwarf2Data, cu, lo_pc, fail_value);
+        if (hi_pc != fail_value)
+          return true;
+    }
+    lo_pc = fail_value;
+    hi_pc = fail_value;
+    return false;
+}
+//----------------------------------------------------------------------
+// GetAttributeValueAsLocation
+//
+// Get the value of an attribute as reference and fix up and compile
+// unit relative offsets as needed.
+//----------------------------------------------------------------------
+dw_offset_t
+DWARFDebugInfoEntry::GetAttributeValueAsLocation
+(
+    SymbolFileDWARF* dwarf2Data,
+    const DWARFCompileUnit* cu,
+    const dw_attr_t attr,
+    DataExtractor& location_data,
+    uint32_t &block_size
+) const
+{
+    block_size = 0;
+    DWARFFormValue form_value;
+
+    // Empty out data in case we don't find anything
+    location_data.Clear();
+    dw_offset_t end_addr_offset = DW_INVALID_OFFSET;
+    const dw_offset_t attr_offset = GetAttributeValue(dwarf2Data, cu, attr, form_value, &end_addr_offset);
+    if (attr_offset)
+    {
+        const uint8_t* blockData = form_value.BlockData();
+        if (blockData)
+        {
+            // We have an inlined location list in the .debug_info section
+            const DataExtractor& debug_info = dwarf2Data->get_debug_info_data();
+            dw_offset_t block_offset = blockData - debug_info.GetDataStart();
+            block_size = (end_addr_offset - attr_offset) - form_value.Unsigned();
+            location_data.SetData(debug_info, block_offset, block_size);
+        }
+        else
+        {
+            // We have a location list offset as the value that is
+            // the offset into the .debug_loc section that describes
+            // the value over it's lifetime
+            lldb::offset_t debug_loc_offset = form_value.Unsigned();
+            if (dwarf2Data)
+            {
+                assert(dwarf2Data->get_debug_loc_data().GetAddressByteSize() == cu->GetAddressByteSize());
+                return DWARFLocationList::Extract(dwarf2Data->get_debug_loc_data(), &debug_loc_offset, location_data);
+            }
+        }
+    }
+    return attr_offset;
+}
+
+//----------------------------------------------------------------------
+// GetName
+//
+// Get value of the DW_AT_name attribute and return it if one exists,
+// else return NULL.
+//----------------------------------------------------------------------
+const char*
+DWARFDebugInfoEntry::GetName
+(
+    SymbolFileDWARF* dwarf2Data,
+    const DWARFCompileUnit* cu
+) const
+{
+    DWARFFormValue form_value;
+    if (GetAttributeValue(dwarf2Data, cu, DW_AT_name, form_value))
+        return form_value.AsCString(&dwarf2Data->get_debug_str_data());
+    else
+    {
+        if (GetAttributeValue(dwarf2Data, cu, DW_AT_specification, form_value))
+        {
+            DWARFCompileUnitSP cu_sp_ptr;
+            const DWARFDebugInfoEntry* die = const_cast<SymbolFileDWARF*>(dwarf2Data)->DebugInfo()->GetDIEPtr(form_value.Reference(cu), &cu_sp_ptr);
+            if (die)
+                return die->GetName(dwarf2Data, cu_sp_ptr.get());
+        }
+    }
+    return NULL;
+}
+
+
+//----------------------------------------------------------------------
+// GetMangledName
+//
+// Get value of the DW_AT_MIPS_linkage_name attribute and return it if
+// one exists, else return the value of the DW_AT_name attribute
+//----------------------------------------------------------------------
+const char*
+DWARFDebugInfoEntry::GetMangledName
+(
+    SymbolFileDWARF* dwarf2Data,
+    const DWARFCompileUnit* cu,
+    bool substitute_name_allowed
+) const
+{
+    const char* name = NULL;
+    DWARFFormValue form_value;
+
+    if (GetAttributeValue(dwarf2Data, cu, DW_AT_MIPS_linkage_name, form_value))
+        name = form_value.AsCString(&dwarf2Data->get_debug_str_data());
+
+    if (GetAttributeValue(dwarf2Data, cu, DW_AT_linkage_name, form_value))
+        name = form_value.AsCString(&dwarf2Data->get_debug_str_data());
+
+    if (substitute_name_allowed && name == NULL)
+    {
+        if (GetAttributeValue(dwarf2Data, cu, DW_AT_name, form_value))
+            name = form_value.AsCString(&dwarf2Data->get_debug_str_data());
+    }
+    return name;
+}
+
+
+//----------------------------------------------------------------------
+// GetPubname
+//
+// Get value the name for a DIE as it should appear for a
+// .debug_pubnames or .debug_pubtypes section.
+//----------------------------------------------------------------------
+const char*
+DWARFDebugInfoEntry::GetPubname
+(
+    SymbolFileDWARF* dwarf2Data,
+    const DWARFCompileUnit* cu
+) const
+{
+    const char* name = NULL;
+    if (!dwarf2Data)
+        return name;
+    
+    DWARFFormValue form_value;
+
+    if (GetAttributeValue(dwarf2Data, cu, DW_AT_MIPS_linkage_name, form_value))
+        name = form_value.AsCString(&dwarf2Data->get_debug_str_data());
+    else if (GetAttributeValue(dwarf2Data, cu, DW_AT_linkage_name, form_value))
+        name = form_value.AsCString(&dwarf2Data->get_debug_str_data());
+    else if (GetAttributeValue(dwarf2Data, cu, DW_AT_name, form_value))
+        name = form_value.AsCString(&dwarf2Data->get_debug_str_data());
+    else if (GetAttributeValue(dwarf2Data, cu, DW_AT_specification, form_value))
+    {
+        // The specification DIE may be in another compile unit so we need
+        // to get a die and its compile unit.
+        DWARFCompileUnitSP cu_sp_ptr;
+        const DWARFDebugInfoEntry* die = const_cast<SymbolFileDWARF*>(dwarf2Data)->DebugInfo()->GetDIEPtr(form_value.Reference(cu), &cu_sp_ptr);
+        if (die)
+            return die->GetPubname(dwarf2Data, cu_sp_ptr.get());
+    }
+    return name;
+}
+
+
+//----------------------------------------------------------------------
+// GetName
+//
+// Get value of the DW_AT_name attribute for a debug information entry
+// that exists at offset "die_offset" and place that value into the
+// supplied stream object. If the DIE is a NULL object "NULL" is placed
+// into the stream, and if no DW_AT_name attribute exists for the DIE
+// then nothing is printed.
+//----------------------------------------------------------------------
+bool
+DWARFDebugInfoEntry::GetName
+(
+    SymbolFileDWARF* dwarf2Data,
+    const DWARFCompileUnit* cu,
+    const dw_offset_t die_offset,
+    Stream &s
+)
+{
+    if (dwarf2Data == NULL)
+    {
+        s.PutCString("NULL");
+        return false;
+    }
+    
+    DWARFDebugInfoEntry die;
+    lldb::offset_t offset = die_offset;
+    if (die.Extract(dwarf2Data, cu, &offset))
+    {
+        if (die.IsNULL())
+        {
+            s.PutCString("NULL");
+            return true;
+        }
+        else
+        {
+            DWARFFormValue form_value;
+            if (die.GetAttributeValue(dwarf2Data, cu, DW_AT_name, form_value))
+            {
+                const char* name = form_value.AsCString(&dwarf2Data->get_debug_str_data());
+                if (name)
+                {
+                    s.PutCString(name);
+                    return true;
+                }
+            }
+        }
+    }
+    return false;
+}
+
+//----------------------------------------------------------------------
+// AppendTypeName
+//
+// Follows the type name definition down through all needed tags to
+// end up with a fully qualified type name and dump the results to
+// the supplied stream. This is used to show the name of types given
+// a type identifier.
+//----------------------------------------------------------------------
+bool
+DWARFDebugInfoEntry::AppendTypeName
+(
+    SymbolFileDWARF* dwarf2Data,
+    const DWARFCompileUnit* cu,
+    const dw_offset_t die_offset,
+    Stream &s
+)
+{
+    if (dwarf2Data == NULL)
+    {
+        s.PutCString("NULL");
+        return false;
+    }
+    
+    DWARFDebugInfoEntry die;
+    lldb::offset_t offset = die_offset;
+    if (die.Extract(dwarf2Data, cu, &offset))
+    {
+        if (die.IsNULL())
+        {
+            s.PutCString("NULL");
+            return true;
+        }
+        else
+        {
+            const char* name = die.GetPubname(dwarf2Data, cu);
+        //  if (die.GetAttributeValue(dwarf2Data, cu, DW_AT_name, form_value))
+        //      name = form_value.AsCString(&dwarf2Data->get_debug_str_data());
+            if (name)
+                s.PutCString(name);
+            else
+            {
+                bool result = true;
+                const DWARFAbbreviationDeclaration* abbrevDecl = die.GetAbbreviationDeclarationPtr(dwarf2Data, cu, offset);
+                
+                if (abbrevDecl == NULL)
+                    return false;
+
+                switch (abbrevDecl->Tag())
+                {
+                case DW_TAG_array_type:         break;  // print out a "[]" after printing the full type of the element below
+                case DW_TAG_base_type:          s.PutCString("base ");         break;
+                case DW_TAG_class_type:         s.PutCString("class ");            break;
+                case DW_TAG_const_type:         s.PutCString("const ");            break;
+                case DW_TAG_enumeration_type:   s.PutCString("enum ");         break;
+                case DW_TAG_file_type:          s.PutCString("file ");         break;
+                case DW_TAG_interface_type:     s.PutCString("interface ");        break;
+                case DW_TAG_packed_type:        s.PutCString("packed ");       break;
+                case DW_TAG_pointer_type:       break;  // print out a '*' after printing the full type below
+                case DW_TAG_ptr_to_member_type: break;  // print out a '*' after printing the full type below
+                case DW_TAG_reference_type:     break;  // print out a '&' after printing the full type below
+                case DW_TAG_restrict_type:      s.PutCString("restrict ");     break;
+                case DW_TAG_set_type:           s.PutCString("set ");          break;
+                case DW_TAG_shared_type:        s.PutCString("shared ");       break;
+                case DW_TAG_string_type:        s.PutCString("string ");       break;
+                case DW_TAG_structure_type:     s.PutCString("struct ");       break;
+                case DW_TAG_subrange_type:      s.PutCString("subrange ");     break;
+                case DW_TAG_subroutine_type:    s.PutCString("function ");     break;
+                case DW_TAG_thrown_type:        s.PutCString("thrown ");       break;
+                case DW_TAG_union_type:         s.PutCString("union ");            break;
+                case DW_TAG_unspecified_type:   s.PutCString("unspecified ");  break;
+                case DW_TAG_volatile_type:      s.PutCString("volatile ");     break;
+                default:
+                    return false;
+                }
+
+                // Follow the DW_AT_type if possible
+                DWARFFormValue form_value;
+                if (die.GetAttributeValue(dwarf2Data, cu, DW_AT_type, form_value))
+                {
+                    uint64_t next_die_offset = form_value.Reference(cu);
+                    result = AppendTypeName(dwarf2Data, cu, next_die_offset, s);
+                }
+
+                switch (abbrevDecl->Tag())
+                {
+                case DW_TAG_array_type:         s.PutCString("[]");    break;
+                case DW_TAG_pointer_type:       s.PutChar('*');    break;
+                case DW_TAG_ptr_to_member_type: s.PutChar('*');    break;
+                case DW_TAG_reference_type:     s.PutChar('&');    break;
+                default:
+                    break;
+                }
+                return result;
+            }
+        }
+    }
+    return false;
+}
+
+bool
+DWARFDebugInfoEntry::Contains (const DWARFDebugInfoEntry *die) const
+{
+    if (die)
+    {
+        const dw_offset_t die_offset = die->GetOffset();
+        if (die_offset > GetOffset())
+        {
+            const DWARFDebugInfoEntry *sibling = GetSibling();
+            assert (sibling); // TODO: take this out
+            if (sibling)
+                return die_offset < sibling->GetOffset();
+        }
+    }
+    return false;
+}
+
+//----------------------------------------------------------------------
+// BuildAddressRangeTable
+//----------------------------------------------------------------------
+void
+DWARFDebugInfoEntry::BuildAddressRangeTable
+(
+    SymbolFileDWARF* dwarf2Data,
+    const DWARFCompileUnit* cu,
+    DWARFDebugAranges* debug_aranges
+) const
+{
+    if (m_tag)
+    {
+        if (m_tag == DW_TAG_subprogram)
+        {
+            dw_addr_t lo_pc = LLDB_INVALID_ADDRESS;
+            dw_addr_t hi_pc = LLDB_INVALID_ADDRESS;
+            if (GetAttributeAddressRange(dwarf2Data, cu, lo_pc, hi_pc, LLDB_INVALID_ADDRESS))
+            {
+                /// printf("BuildAddressRangeTable() 0x%8.8x: %30s: [0x%8.8x - 0x%8.8x)\n", m_offset, DW_TAG_value_to_name(tag), lo_pc, hi_pc);
+                debug_aranges->AppendRange (cu->GetOffset(), lo_pc, hi_pc);
+            }
+        }
+
+
+        const DWARFDebugInfoEntry* child = GetFirstChild();
+        while (child)
+        {
+            child->BuildAddressRangeTable(dwarf2Data, cu, debug_aranges);
+            child = child->GetSibling();
+        }
+    }
+}
+
+//----------------------------------------------------------------------
+// BuildFunctionAddressRangeTable
+//
+// This function is very similar to the BuildAddressRangeTable function
+// except that the actual DIE offset for the function is placed in the
+// table instead of the compile unit offset (which is the way the
+// standard .debug_aranges section does it).
+//----------------------------------------------------------------------
+void
+DWARFDebugInfoEntry::BuildFunctionAddressRangeTable
+(
+    SymbolFileDWARF* dwarf2Data,
+    const DWARFCompileUnit* cu,
+    DWARFDebugAranges* debug_aranges
+) const
+{
+    if (m_tag)
+    {
+        if (m_tag == DW_TAG_subprogram)
+        {
+            dw_addr_t lo_pc = LLDB_INVALID_ADDRESS;
+            dw_addr_t hi_pc = LLDB_INVALID_ADDRESS;
+            if (GetAttributeAddressRange(dwarf2Data, cu, lo_pc, hi_pc, LLDB_INVALID_ADDRESS))
+            {
+            //  printf("BuildAddressRangeTable() 0x%8.8x: [0x%16.16" PRIx64 " - 0x%16.16" PRIx64 ")\n", m_offset, lo_pc, hi_pc); // DEBUG ONLY
+                debug_aranges->AppendRange (GetOffset(), lo_pc, hi_pc);
+            }
+        }
+
+        const DWARFDebugInfoEntry* child = GetFirstChild();
+        while (child)
+        {
+            child->BuildFunctionAddressRangeTable(dwarf2Data, cu, debug_aranges);
+            child = child->GetSibling();
+        }
+    }
+}
+
+void
+DWARFDebugInfoEntry::GetDeclContextDIEs (SymbolFileDWARF* dwarf2Data, 
+                                         DWARFCompileUnit* cu,
+                                         DWARFDIECollection &decl_context_dies) const
+{
+    const DWARFDebugInfoEntry *parent_decl_ctx_die = GetParentDeclContextDIE (dwarf2Data, cu);
+    if (parent_decl_ctx_die && parent_decl_ctx_die != this)
+    {
+        decl_context_dies.Append(parent_decl_ctx_die);
+        parent_decl_ctx_die->GetDeclContextDIEs (dwarf2Data, cu, decl_context_dies);
+    }
+}
+
+void
+DWARFDebugInfoEntry::GetDWARFDeclContext (SymbolFileDWARF* dwarf2Data,
+                                          DWARFCompileUnit* cu,
+                                          DWARFDeclContext &dwarf_decl_ctx) const
+{
+    const dw_tag_t tag = Tag();
+    if (tag != DW_TAG_compile_unit)
+    {
+        dwarf_decl_ctx.AppendDeclContext(tag, GetName(dwarf2Data, cu));
+        const DWARFDebugInfoEntry *parent_decl_ctx_die = GetParentDeclContextDIE (dwarf2Data, cu);
+        if (parent_decl_ctx_die && parent_decl_ctx_die != this)
+        {
+            if (parent_decl_ctx_die->Tag() != DW_TAG_compile_unit)
+                parent_decl_ctx_die->GetDWARFDeclContext (dwarf2Data, cu, dwarf_decl_ctx);
+        }
+    }
+}
+
+
+bool
+DWARFDebugInfoEntry::MatchesDWARFDeclContext (SymbolFileDWARF* dwarf2Data,
+                                              DWARFCompileUnit* cu,
+                                              const DWARFDeclContext &dwarf_decl_ctx) const
+{
+    
+    DWARFDeclContext this_dwarf_decl_ctx;
+    GetDWARFDeclContext (dwarf2Data, cu, this_dwarf_decl_ctx);
+    return this_dwarf_decl_ctx == dwarf_decl_ctx;
+}
+
+const DWARFDebugInfoEntry *
+DWARFDebugInfoEntry::GetParentDeclContextDIE (SymbolFileDWARF* dwarf2Data, 
+											  DWARFCompileUnit* cu) const
+{
+	DWARFDebugInfoEntry::Attributes attributes;
+	GetAttributes(dwarf2Data, cu, NULL, attributes);
+	return GetParentDeclContextDIE (dwarf2Data, cu, attributes);
+}
+
+const DWARFDebugInfoEntry *
+DWARFDebugInfoEntry::GetParentDeclContextDIE (SymbolFileDWARF* dwarf2Data, 
+											  DWARFCompileUnit* cu,
+											  const DWARFDebugInfoEntry::Attributes& attributes) const
+{
+	const DWARFDebugInfoEntry * die = this;
+	
+	while (die != NULL)
+	{
+		// If this is the original DIE that we are searching for a declaration 
+		// for, then don't look in the cache as we don't want our own decl 
+		// context to be our decl context...
+		if (die != this)
+		{            
+			switch (die->Tag())
+			{
+				case DW_TAG_compile_unit:
+				case DW_TAG_namespace:
+				case DW_TAG_structure_type:
+				case DW_TAG_union_type:
+				case DW_TAG_class_type:
+					return die;
+					
+				default:
+					break;
+			}
+		}
+		
+		dw_offset_t die_offset;
+        
+		die_offset = attributes.FormValueAsUnsigned(dwarf2Data, DW_AT_specification, DW_INVALID_OFFSET);
+		if (die_offset != DW_INVALID_OFFSET)
+		{
+			const DWARFDebugInfoEntry *spec_die = cu->GetDIEPtr (die_offset);
+			if (spec_die)
+			{
+				const DWARFDebugInfoEntry *spec_die_decl_ctx_die = spec_die->GetParentDeclContextDIE (dwarf2Data, cu);
+				if (spec_die_decl_ctx_die)
+					return spec_die_decl_ctx_die;
+			}
+		}
+		
+        die_offset = attributes.FormValueAsUnsigned(dwarf2Data, DW_AT_abstract_origin, DW_INVALID_OFFSET);
+		if (die_offset != DW_INVALID_OFFSET)
+		{
+			const DWARFDebugInfoEntry *abs_die = cu->GetDIEPtr (die_offset);
+			if (abs_die)
+			{
+				const DWARFDebugInfoEntry *abs_die_decl_ctx_die = abs_die->GetParentDeclContextDIE (dwarf2Data, cu);
+				if (abs_die_decl_ctx_die)
+					return abs_die_decl_ctx_die;
+			}
+		}
+		
+		die = die->GetParent();
+	}
+    return NULL;
+}
+
+
+const char *
+DWARFDebugInfoEntry::GetQualifiedName (SymbolFileDWARF* dwarf2Data, 
+									   DWARFCompileUnit* cu,
+									   std::string &storage) const
+{
+	DWARFDebugInfoEntry::Attributes attributes;
+	GetAttributes(dwarf2Data, cu, NULL, attributes);
+	return GetQualifiedName (dwarf2Data, cu, attributes, storage);
+}
+
+const char*
+DWARFDebugInfoEntry::GetQualifiedName (SymbolFileDWARF* dwarf2Data, 
+									   DWARFCompileUnit* cu,
+									   const DWARFDebugInfoEntry::Attributes& attributes,
+									   std::string &storage) const
+{
+	
+	const char *name = GetName (dwarf2Data, cu);
+	
+	if (name)
+	{
+		const DWARFDebugInfoEntry *parent_decl_ctx_die = GetParentDeclContextDIE (dwarf2Data, cu);
+		storage.clear();
+		// TODO: change this to get the correct decl context parent....
+		while (parent_decl_ctx_die)
+		{
+			const dw_tag_t parent_tag = parent_decl_ctx_die->Tag();
+			switch (parent_tag)
+			{
+                case DW_TAG_namespace:
+				{
+					const char *namespace_name = parent_decl_ctx_die->GetName (dwarf2Data, cu);
+					if (namespace_name)
+					{
+						storage.insert (0, "::");
+						storage.insert (0, namespace_name);
+					}
+					else
+					{
+						storage.insert (0, "(anonymous namespace)::");
+					}
+					parent_decl_ctx_die = parent_decl_ctx_die->GetParentDeclContextDIE(dwarf2Data, cu);
+				}
+                    break;
+					
+                case DW_TAG_class_type:
+                case DW_TAG_structure_type:
+                case DW_TAG_union_type:
+				{
+					const char *class_union_struct_name = parent_decl_ctx_die->GetName (dwarf2Data, cu);
+                    
+					if (class_union_struct_name)
+					{
+						storage.insert (0, "::");
+						storage.insert (0, class_union_struct_name);
+					}
+					parent_decl_ctx_die = parent_decl_ctx_die->GetParentDeclContextDIE(dwarf2Data, cu);
+				}
+                    break;
+                    
+                default:
+                    parent_decl_ctx_die = NULL;
+                    break;
+			}
+		}
+		
+		if (storage.empty())
+			storage.append ("::");
+        
+		storage.append (name);
+	}
+	if (storage.empty())
+		return NULL;
+	return storage.c_str();
+}
+
+
+//----------------------------------------------------------------------
+// LookupAddress
+//----------------------------------------------------------------------
+bool
+DWARFDebugInfoEntry::LookupAddress
+(
+    const dw_addr_t address,
+    SymbolFileDWARF* dwarf2Data,
+    const DWARFCompileUnit* cu,
+    DWARFDebugInfoEntry** function_die,
+    DWARFDebugInfoEntry** block_die
+)
+{
+    bool found_address = false;
+    if (m_tag)
+    {
+        bool check_children = false;
+        bool match_addr_range = false;
+    //  printf("0x%8.8x: %30s: address = 0x%8.8x - ", m_offset, DW_TAG_value_to_name(tag), address);
+        switch (m_tag)
+        {
+        case DW_TAG_array_type                 : break;
+        case DW_TAG_class_type                 : check_children = true; break;
+        case DW_TAG_entry_point                : break;
+        case DW_TAG_enumeration_type           : break;
+        case DW_TAG_formal_parameter           : break;
+        case DW_TAG_imported_declaration       : break;
+        case DW_TAG_label                      : break;
+        case DW_TAG_lexical_block              : check_children = true; match_addr_range = true; break;
+        case DW_TAG_member                     : break;
+        case DW_TAG_pointer_type               : break;
+        case DW_TAG_reference_type             : break;
+        case DW_TAG_compile_unit               : match_addr_range = true; break;
+        case DW_TAG_string_type                : break;
+        case DW_TAG_structure_type             : check_children = true; break;
+        case DW_TAG_subroutine_type            : break;
+        case DW_TAG_typedef                    : break;
+        case DW_TAG_union_type                 : break;
+        case DW_TAG_unspecified_parameters     : break;
+        case DW_TAG_variant                    : break;
+        case DW_TAG_common_block               : check_children = true; break;
+        case DW_TAG_common_inclusion           : break;
+        case DW_TAG_inheritance                : break;
+        case DW_TAG_inlined_subroutine         : check_children = true; match_addr_range = true; break;
+        case DW_TAG_module                     : match_addr_range = true; break;
+        case DW_TAG_ptr_to_member_type         : break;
+        case DW_TAG_set_type                   : break;
+        case DW_TAG_subrange_type              : break;
+        case DW_TAG_with_stmt                  : break;
+        case DW_TAG_access_declaration         : break;
+        case DW_TAG_base_type                  : break;
+        case DW_TAG_catch_block                : match_addr_range = true; break;
+        case DW_TAG_const_type                 : break;
+        case DW_TAG_constant                   : break;
+        case DW_TAG_enumerator                 : break;
+        case DW_TAG_file_type                  : break;
+        case DW_TAG_friend                     : break;
+        case DW_TAG_namelist                   : break;
+        case DW_TAG_namelist_item              : break;
+        case DW_TAG_packed_type                : break;
+        case DW_TAG_subprogram                 : match_addr_range = true; break;
+        case DW_TAG_template_type_parameter    : break;
+        case DW_TAG_template_value_parameter   : break;
+        case DW_TAG_thrown_type                : break;
+        case DW_TAG_try_block                  : match_addr_range = true; break;
+        case DW_TAG_variant_part               : break;
+        case DW_TAG_variable                   : break;
+        case DW_TAG_volatile_type              : break;
+        case DW_TAG_dwarf_procedure            : break;
+        case DW_TAG_restrict_type              : break;
+        case DW_TAG_interface_type             : break;
+        case DW_TAG_namespace                  : check_children = true; break;
+        case DW_TAG_imported_module            : break;
+        case DW_TAG_unspecified_type           : break;
+        case DW_TAG_partial_unit               : break;
+        case DW_TAG_imported_unit              : break;
+        case DW_TAG_shared_type                : break;
+        default: break;
+        }
+
+        if (match_addr_range)
+        {
+            dw_addr_t lo_pc = GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_low_pc, LLDB_INVALID_ADDRESS);
+            if (lo_pc != LLDB_INVALID_ADDRESS)
+            {
+                dw_addr_t hi_pc = GetAttributeHighPC(dwarf2Data, cu, lo_pc, LLDB_INVALID_ADDRESS);
+                if (hi_pc != LLDB_INVALID_ADDRESS)
+                {
+                    //  printf("\n0x%8.8x: %30s: address = 0x%8.8x  [0x%8.8x - 0x%8.8x) ", m_offset, DW_TAG_value_to_name(tag), address, lo_pc, hi_pc);
+                    if ((lo_pc <= address) && (address < hi_pc))
+                    {
+                        found_address = true;
+                    //  puts("***MATCH***");
+                        switch (m_tag)
+                        {
+                        case DW_TAG_compile_unit:       // File
+                            check_children = ((function_die != NULL) || (block_die != NULL));
+                            break;
+
+                        case DW_TAG_subprogram:         // Function
+                            if (function_die)
+                                *function_die = this;
+                            check_children = (block_die != NULL);
+                            break;
+
+                        case DW_TAG_inlined_subroutine: // Inlined Function
+                        case DW_TAG_lexical_block:      // Block { } in code
+                            if (block_die)
+                            {
+                                *block_die = this;
+                                check_children = true;
+                            }
+                            break;
+
+                        default:
+                            check_children = true;
+                            break;
+                        }
+                    }
+                }
+                else
+                {   // compile units may not have a valid high/low pc when there
+                    // are address gaps in subroutines so we must always search
+                    // if there is no valid high and low PC
+                    check_children = (m_tag == DW_TAG_compile_unit) && ((function_die != NULL) || (block_die != NULL));
+                }
+            }
+            else
+            {
+                dw_offset_t debug_ranges_offset = GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_ranges, DW_INVALID_OFFSET);
+                if (debug_ranges_offset != DW_INVALID_OFFSET)
+                {
+                    DWARFDebugRanges::RangeList ranges;
+                    DWARFDebugRanges* debug_ranges = dwarf2Data->DebugRanges();
+                    debug_ranges->FindRanges(debug_ranges_offset, ranges);
+                    // All DW_AT_ranges are relative to the base address of the
+                    // compile unit. We add the compile unit base address to make
+                    // sure all the addresses are properly fixed up.
+                    ranges.Slide (cu->GetBaseAddress());
+                    if (ranges.FindEntryThatContains(address))
+                    {
+                        found_address = true;
+                    //  puts("***MATCH***");
+                        switch (m_tag)
+                        {
+                        case DW_TAG_compile_unit:       // File
+                            check_children = ((function_die != NULL) || (block_die != NULL));
+                            break;
+
+                        case DW_TAG_subprogram:         // Function
+                            if (function_die)
+                                *function_die = this;
+                            check_children = (block_die != NULL);
+                            break;
+
+                        case DW_TAG_inlined_subroutine: // Inlined Function
+                        case DW_TAG_lexical_block:      // Block { } in code
+                            if (block_die)
+                            {
+                                *block_die = this;
+                                check_children = true;
+                            }
+                            break;
+
+                        default:
+                            check_children = true;
+                            break;
+                        }
+                    }
+                    else
+                    {
+                        check_children = false;
+                    }
+                }
+            }
+        }
+
+
+        if (check_children)
+        {
+        //  printf("checking children\n");
+            DWARFDebugInfoEntry* child = GetFirstChild();
+            while (child)
+            {
+                if (child->LookupAddress(address, dwarf2Data, cu, function_die, block_die))
+                    return true;
+                child = child->GetSibling();
+            }
+        }
+    }
+    return found_address;
+}
+
+const DWARFAbbreviationDeclaration* 
+DWARFDebugInfoEntry::GetAbbreviationDeclarationPtr (SymbolFileDWARF* dwarf2Data,
+                                                    const DWARFCompileUnit *cu,
+                                                    lldb::offset_t &offset) const
+{
+    if (dwarf2Data)
+    {
+        offset = GetOffset();
+        
+        const DWARFAbbreviationDeclaration* abbrev_decl = cu->GetAbbreviations()->GetAbbreviationDeclaration (m_abbr_idx);
+        if (abbrev_decl)
+        {
+            // Make sure the abbreviation code still matches. If it doesn't and
+            // the DWARF data was mmap'ed, the backing file might have been modified
+            // which is bad news.
+            const uint64_t abbrev_code = dwarf2Data->get_debug_info_data().GetULEB128 (&offset);
+        
+            if (abbrev_decl->Code() == abbrev_code)
+                return abbrev_decl;
+            
+            dwarf2Data->GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("0x%8.8x: the DWARF debug information has been modified (abbrev code was %u, and is now %u)", 
+                                                                                   GetOffset(),
+                                                                                   (uint32_t)abbrev_decl->Code(),
+                                                                                   (uint32_t)abbrev_code);
+        }
+    }
+    offset = DW_INVALID_OFFSET;
+    return NULL;
+}
+
+
+bool
+DWARFDebugInfoEntry::OffsetLessThan (const DWARFDebugInfoEntry& a, const DWARFDebugInfoEntry& b)
+{
+    return a.GetOffset() < b.GetOffset();
+}
+
+void
+DWARFDebugInfoEntry::DumpDIECollection (Stream &strm, DWARFDebugInfoEntry::collection &die_collection)
+{
+    DWARFDebugInfoEntry::const_iterator pos;
+    DWARFDebugInfoEntry::const_iterator end = die_collection.end();
+    strm.PutCString("\noffset    parent   sibling  child\n");
+    strm.PutCString("--------  -------- -------- --------\n");
+    for (pos = die_collection.begin(); pos != end; ++pos)
+    {
+        const DWARFDebugInfoEntry& die_ref = *pos;
+        const DWARFDebugInfoEntry* p = die_ref.GetParent();
+        const DWARFDebugInfoEntry* s = die_ref.GetSibling();
+        const DWARFDebugInfoEntry* c = die_ref.GetFirstChild();
+        strm.Printf("%.8x: %.8x %.8x %.8x 0x%4.4x %s%s\n", 
+                    die_ref.GetOffset(),
+                    p ? p->GetOffset() : 0,
+                    s ? s->GetOffset() : 0,
+                    c ? c->GetOffset() : 0,
+                    die_ref.Tag(), 
+                    DW_TAG_value_to_name(die_ref.Tag()),
+                    die_ref.HasChildren() ? " *" : "");
+    }
+}
+
+
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h
new file mode 100644
index 000000000000..85f4109ae01a
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h
@@ -0,0 +1,457 @@
+//===-- DWARFDebugInfoEntry.h -----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SymbolFileDWARF_DWARFDebugInfoEntry_h_
+#define SymbolFileDWARF_DWARFDebugInfoEntry_h_
+
+#include "SymbolFileDWARF.h"
+#include "llvm/ADT/SmallVector.h"
+
+#include "DWARFDebugAbbrev.h"
+#include "DWARFAbbreviationDeclaration.h"
+#include "DWARFDebugRanges.h"
+#include <vector>
+#include <map>
+#include <set>
+
+typedef std::map<const DWARFDebugInfoEntry*, dw_addr_t>     DIEToAddressMap;
+typedef DIEToAddressMap::iterator                           DIEToAddressMapIter;
+typedef DIEToAddressMap::const_iterator                     DIEToAddressMapConstIter;
+
+typedef std::map<dw_addr_t, const DWARFDebugInfoEntry*>     AddressToDIEMap;
+typedef AddressToDIEMap::iterator                           AddressToDIEMapIter;
+typedef AddressToDIEMap::const_iterator                     AddressToDIEMapConstIter;
+
+
+typedef std::map<dw_offset_t, dw_offset_t>                  DIEToDIEMap;
+typedef DIEToDIEMap::iterator                               DIEToDIEMapIter;
+typedef DIEToDIEMap::const_iterator                         DIEToDIEMapConstIter;
+
+typedef std::map<uint32_t, const DWARFDebugInfoEntry*>      UInt32ToDIEMap;
+typedef UInt32ToDIEMap::iterator                            UInt32ToDIEMapIter;
+typedef UInt32ToDIEMap::const_iterator                      UInt32ToDIEMapConstIter;
+
+typedef std::multimap<uint32_t, const DWARFDebugInfoEntry*> UInt32ToDIEMMap;
+typedef UInt32ToDIEMMap::iterator                           UInt32ToDIEMMapIter;
+typedef UInt32ToDIEMMap::const_iterator                     UInt32ToDIEMMapConstIter;
+
+class DWARFDeclContext;
+
+#define DIE_SIBLING_IDX_BITSIZE 31
+#define DIE_ABBR_IDX_BITSIZE 15
+
+class DWARFDebugInfoEntry
+{
+public:
+    typedef std::vector<DWARFDebugInfoEntry>    collection;
+    typedef collection::iterator                iterator;
+    typedef collection::const_iterator          const_iterator;
+
+    typedef std::vector<dw_offset_t>            offset_collection;
+    typedef offset_collection::iterator         offset_collection_iterator;
+    typedef offset_collection::const_iterator   offset_collection_const_iterator;
+
+    class Attributes
+    {
+    public:
+        Attributes();
+        ~Attributes();
+
+        void Append(const DWARFCompileUnit *cu, dw_offset_t attr_die_offset, dw_attr_t attr, dw_form_t form);
+        const DWARFCompileUnit * CompileUnitAtIndex(uint32_t i) const { return m_infos[i].cu; }
+        dw_offset_t DIEOffsetAtIndex(uint32_t i) const { return m_infos[i].die_offset; }
+        dw_attr_t AttributeAtIndex(uint32_t i) const { return m_infos[i].attr; }
+        dw_attr_t FormAtIndex(uint32_t i) const { return m_infos[i].form; }
+        bool ExtractFormValueAtIndex (SymbolFileDWARF* dwarf2Data, uint32_t i, DWARFFormValue &form_value) const;
+        uint64_t FormValueAsUnsignedAtIndex (SymbolFileDWARF* dwarf2Data, uint32_t i, uint64_t fail_value) const;
+        uint64_t FormValueAsUnsigned (SymbolFileDWARF* dwarf2Data, dw_attr_t attr, uint64_t fail_value) const;
+        uint32_t FindAttributeIndex(dw_attr_t attr) const;
+        bool ContainsAttribute(dw_attr_t attr) const;
+        bool RemoveAttribute(dw_attr_t attr);
+        void Clear() { m_infos.clear(); }
+        size_t Size() const { return m_infos.size(); }
+
+    protected:
+        struct Info
+        {
+            const DWARFCompileUnit *cu; // Keep the compile unit with each attribute in case we have DW_FORM_ref_addr values
+            dw_offset_t die_offset;
+            dw_attr_t attr;
+            dw_form_t form;
+        };
+
+        typedef llvm::SmallVector<Info, 32> collection;
+        collection m_infos;
+    };
+
+    struct CompareState
+    {
+        CompareState() :
+            die_offset_pairs()
+        {
+            assert(sizeof(dw_offset_t)*2 == sizeof(uint64_t));
+        }
+
+        bool AddTypePair(dw_offset_t a, dw_offset_t b)
+        {
+            uint64_t a_b_offsets = (uint64_t)a << 32 | (uint64_t)b;
+            // Return true if this type was inserted, false otherwise
+            return die_offset_pairs.insert(a_b_offsets).second;
+        }
+        std::set< uint64_t > die_offset_pairs;
+    };
+
+                DWARFDebugInfoEntry():
+                    m_offset        (DW_INVALID_OFFSET),
+                    m_parent_idx    (0),
+                    m_sibling_idx   (0),
+                    m_empty_children(false),
+                    m_abbr_idx      (0),
+                    m_has_children  (false),
+                    m_tag           (0)
+                {
+                }
+
+    void        Clear ()
+                {
+                    m_offset         = DW_INVALID_OFFSET;
+                    m_parent_idx     = 0;
+                    m_sibling_idx    = 0;
+                    m_empty_children = false;
+                    m_abbr_idx       = 0;
+                    m_has_children   = false;
+                    m_tag            = 0;
+                }
+
+    bool        Contains (const DWARFDebugInfoEntry *die) const;
+
+    void        BuildAddressRangeTable(
+                    SymbolFileDWARF* dwarf2Data,
+                    const DWARFCompileUnit* cu,
+                    DWARFDebugAranges* debug_aranges) const;
+
+    void        BuildFunctionAddressRangeTable(
+                    SymbolFileDWARF* dwarf2Data,
+                    const DWARFCompileUnit* cu,
+                    DWARFDebugAranges* debug_aranges) const;
+
+    bool        FastExtract(
+                    const lldb_private::DataExtractor& debug_info_data,
+                    const DWARFCompileUnit* cu,
+                    const uint8_t *fixed_form_sizes,
+                    lldb::offset_t* offset_ptr);
+
+    bool        Extract(
+                    SymbolFileDWARF* dwarf2Data,
+                    const DWARFCompileUnit* cu,
+                    lldb::offset_t* offset_ptr);
+
+    bool        LookupAddress(
+                    const dw_addr_t address,
+                    SymbolFileDWARF* dwarf2Data,
+                    const DWARFCompileUnit* cu,
+                    DWARFDebugInfoEntry** function_die,
+                    DWARFDebugInfoEntry** block_die);
+
+    size_t      GetAttributes(
+                    SymbolFileDWARF* dwarf2Data,
+                    const DWARFCompileUnit* cu,
+                    const uint8_t *fixed_form_sizes,
+                    DWARFDebugInfoEntry::Attributes& attrs,
+                    uint32_t curr_depth = 0) const; // "curr_depth" for internal use only, don't set this yourself!!!
+
+    dw_offset_t GetAttributeValue(
+                    SymbolFileDWARF* dwarf2Data,
+                    const DWARFCompileUnit* cu,
+                    const dw_attr_t attr,
+                    DWARFFormValue& formValue,
+                    dw_offset_t* end_attr_offset_ptr = NULL) const;
+
+    const char* GetAttributeValueAsString(
+                    SymbolFileDWARF* dwarf2Data,
+                    const DWARFCompileUnit* cu,
+                    const dw_attr_t attr,
+                    const char* fail_value) const;
+
+    uint64_t    GetAttributeValueAsUnsigned(
+                    SymbolFileDWARF* dwarf2Data,
+                    const DWARFCompileUnit* cu,
+                    const dw_attr_t attr,
+                    uint64_t fail_value) const;
+
+    uint64_t    GetAttributeValueAsReference(
+                    SymbolFileDWARF* dwarf2Data,
+                    const DWARFCompileUnit* cu,
+                    const dw_attr_t attr,
+                    uint64_t fail_value) const;
+
+    int64_t     GetAttributeValueAsSigned(
+                    SymbolFileDWARF* dwarf2Data,
+                    const DWARFCompileUnit* cu,
+                    const dw_attr_t attr,
+                    int64_t fail_value) const;
+
+    dw_addr_t   GetAttributeHighPC(
+                    SymbolFileDWARF* dwarf2Data,
+                    const DWARFCompileUnit* cu,
+                    dw_addr_t lo_pc,
+                    uint64_t fail_value) const;
+
+    bool        GetAttributeAddressRange(
+                    SymbolFileDWARF* dwarf2Data,
+                    const DWARFCompileUnit* cu,
+                    dw_addr_t& lo_pc,
+                    dw_addr_t& hi_pc,
+                    uint64_t fail_value) const;
+
+    dw_offset_t GetAttributeValueAsLocation(
+                    SymbolFileDWARF* dwarf2Data,
+                    const DWARFCompileUnit* cu,
+                    const dw_attr_t attr,
+                    lldb_private::DataExtractor& data,
+                    uint32_t &block_size) const;
+
+    const char* GetName(
+                    SymbolFileDWARF* dwarf2Data,
+                    const DWARFCompileUnit* cu) const;
+
+    const char* GetMangledName(
+                    SymbolFileDWARF* dwarf2Data,
+                    const DWARFCompileUnit* cu,
+                    bool substitute_name_allowed = true) const;
+
+    const char* GetPubname(
+                    SymbolFileDWARF* dwarf2Data,
+                    const DWARFCompileUnit* cu) const;
+
+    static bool GetName(
+                    SymbolFileDWARF* dwarf2Data,
+                    const DWARFCompileUnit* cu,
+                    const dw_offset_t die_offset,
+                    lldb_private::Stream &s);
+
+    static bool AppendTypeName(
+                    SymbolFileDWARF* dwarf2Data,
+                    const DWARFCompileUnit* cu,
+                    const dw_offset_t die_offset,
+                    lldb_private::Stream &s);
+
+    const char * GetQualifiedName (
+                    SymbolFileDWARF* dwarf2Data, 
+                    DWARFCompileUnit* cu,
+                    std::string &storage) const;
+    
+    const char * GetQualifiedName (
+                    SymbolFileDWARF* dwarf2Data, 
+                    DWARFCompileUnit* cu,
+                    const DWARFDebugInfoEntry::Attributes& attributes,
+                    std::string &storage) const;
+
+//    static int  Compare(
+//                    SymbolFileDWARF* dwarf2Data,
+//                    dw_offset_t a_die_offset,
+//                    dw_offset_t b_die_offset,
+//                    CompareState &compare_state,
+//                    bool compare_siblings,
+//                    bool compare_children);
+//
+//    static int Compare(
+//                    SymbolFileDWARF* dwarf2Data,
+//                    DWARFCompileUnit* a_cu, const DWARFDebugInfoEntry* a_die,
+//                    DWARFCompileUnit* b_cu, const DWARFDebugInfoEntry* b_die,
+//                    CompareState &compare_state,
+//                    bool compare_siblings,
+//                    bool compare_children);
+
+    static bool OffsetLessThan (
+                    const DWARFDebugInfoEntry& a,
+                    const DWARFDebugInfoEntry& b);
+
+    void        Dump(
+                    SymbolFileDWARF* dwarf2Data,
+                    const DWARFCompileUnit* cu,
+                    lldb_private::Stream &s,
+                    uint32_t recurse_depth) const;
+
+    void        DumpAncestry(
+                    SymbolFileDWARF* dwarf2Data,
+                    const DWARFCompileUnit* cu,
+                    const DWARFDebugInfoEntry* oldest,
+                    lldb_private::Stream &s,
+                    uint32_t recurse_depth) const;
+
+    static void DumpAttribute(
+                    SymbolFileDWARF* dwarf2Data,
+                    const DWARFCompileUnit* cu,
+                    const lldb_private::DataExtractor& debug_info_data,
+                    lldb::offset_t *offset_ptr,
+                    lldb_private::Stream &s,
+                    dw_attr_t attr,
+                    dw_form_t form);
+    // This one dumps the comp unit name, objfile name and die offset for this die so the stream S.
+    void          DumpLocation(
+                    SymbolFileDWARF* dwarf2Data,
+                    DWARFCompileUnit* cu,
+                    lldb_private::Stream &s) const;
+                    
+    bool        GetDIENamesAndRanges(
+                    SymbolFileDWARF* dwarf2Data,
+                    const DWARFCompileUnit* cu,
+                    const char * &name,
+                    const char * &mangled,
+                    DWARFDebugRanges::RangeList& rangeList,
+                    int& decl_file,
+                    int& decl_line,
+                    int& decl_column,
+                    int& call_file,
+                    int& call_line,
+                    int& call_column,
+                    lldb_private::DWARFExpression *frame_base = NULL) const;
+
+    const DWARFAbbreviationDeclaration* 
+    GetAbbreviationDeclarationPtr (SymbolFileDWARF* dwarf2Data,
+                                   const DWARFCompileUnit *cu,
+                                   lldb::offset_t &offset) const;
+
+    dw_tag_t
+    Tag () const 
+    {
+        return m_tag;
+    }
+
+    bool
+    IsNULL() const 
+    {
+        return m_abbr_idx == 0; 
+    }
+
+    dw_offset_t
+    GetOffset () const 
+    { 
+        return m_offset; 
+    }
+
+    void
+    SetOffset (dw_offset_t offset)
+    { 
+        m_offset = offset; 
+    }
+
+    bool
+    HasChildren () const 
+    { 
+        return m_has_children;
+    }
+    
+    void
+    SetHasChildren (bool b)
+    {
+        m_has_children = b;
+    }
+
+            // We know we are kept in a vector of contiguous entries, so we know
+            // our parent will be some index behind "this".
+            DWARFDebugInfoEntry*    GetParent()             { return m_parent_idx > 0 ? this - m_parent_idx : NULL;  }
+    const   DWARFDebugInfoEntry*    GetParent()     const   { return m_parent_idx > 0 ? this - m_parent_idx : NULL;  }
+            // We know we are kept in a vector of contiguous entries, so we know
+            // our sibling will be some index after "this".
+            DWARFDebugInfoEntry*    GetSibling()            { return m_sibling_idx > 0 ? this + m_sibling_idx : NULL;  }
+    const   DWARFDebugInfoEntry*    GetSibling()    const   { return m_sibling_idx > 0 ? this + m_sibling_idx : NULL;  }
+            // We know we are kept in a vector of contiguous entries, so we know
+            // we don't need to store our child pointer, if we have a child it will
+            // be the next entry in the list...
+            DWARFDebugInfoEntry*    GetFirstChild()         { return (HasChildren() && !m_empty_children) ? this + 1 : NULL; }
+    const   DWARFDebugInfoEntry*    GetFirstChild() const   { return (HasChildren() && !m_empty_children) ? this + 1 : NULL; }
+
+    
+    void                            GetDeclContextDIEs (SymbolFileDWARF* dwarf2Data, 
+                                                        DWARFCompileUnit* cu,
+                                                        DWARFDIECollection &decl_context_dies) const;
+
+    void                            GetDWARFDeclContext (SymbolFileDWARF* dwarf2Data,
+                                                         DWARFCompileUnit* cu,
+                                                         DWARFDeclContext &dwarf_decl_ctx) const;
+
+
+    bool                            MatchesDWARFDeclContext(SymbolFileDWARF* dwarf2Data,
+                                                            DWARFCompileUnit* cu,
+                                                            const DWARFDeclContext &dwarf_decl_ctx) const;
+
+    const   DWARFDebugInfoEntry*    GetParentDeclContextDIE (SymbolFileDWARF* dwarf2Data, 
+                                                             DWARFCompileUnit* cu) const;
+    const   DWARFDebugInfoEntry*    GetParentDeclContextDIE (SymbolFileDWARF* dwarf2Data, 
+                                                             DWARFCompileUnit* cu, 
+                                                             const DWARFDebugInfoEntry::Attributes& attributes) const;
+
+    void        
+    SetParent (DWARFDebugInfoEntry* parent)     
+    {
+        if (parent)
+        {
+            // We know we are kept in a vector of contiguous entries, so we know
+            // our parent will be some index behind "this".
+            m_parent_idx = this - parent;
+        }
+        else        
+            m_parent_idx = 0;
+    }
+    void
+    SetSibling (DWARFDebugInfoEntry* sibling)
+    {
+        if (sibling)
+        {
+            // We know we are kept in a vector of contiguous entries, so we know
+            // our sibling will be some index after "this".
+            m_sibling_idx = sibling - this;
+            sibling->SetParent(GetParent()); 
+        }
+        else        
+            m_sibling_idx = 0;
+    }
+
+    void
+    SetSiblingIndex (uint32_t idx)
+    {
+        m_sibling_idx = idx;
+    }
+    
+    void
+    SetParentIndex (uint32_t idx)
+    {
+        m_parent_idx = idx;
+    }
+
+    bool
+    GetEmptyChildren () const
+    {
+        return m_empty_children;
+    }
+
+    void
+    SetEmptyChildren (bool b)
+    {
+        m_empty_children = b;
+    }
+
+    static void
+    DumpDIECollection (lldb_private::Stream &strm,
+                       DWARFDebugInfoEntry::collection &die_collection);
+
+protected:
+    dw_offset_t m_offset;           // Offset within the .debug_info of the start of this entry
+    uint32_t    m_parent_idx;       // How many to subtract from "this" to get the parent. If zero this die has no parent
+    uint32_t    m_sibling_idx:31,   // How many to add to "this" to get the sibling.
+                m_empty_children:1; // If a DIE says it had children, yet it just contained a NULL tag, this will be set.
+    uint32_t    m_abbr_idx:DIE_ABBR_IDX_BITSIZE,
+                m_has_children:1,   // Set to 1 if this DIE has children
+                m_tag:16;           // A copy of the DW_TAG value so we don't have to go through the compile unit abbrev table
+                
+};
+
+#endif  // SymbolFileDWARF_DWARFDebugInfoEntry_h_
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp
new file mode 100644
index 000000000000..6c9336a08426
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.cpp
@@ -0,0 +1,1436 @@
+//===-- DWARFDebugLine.cpp --------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFDebugLine.h"
+
+//#define ENABLE_DEBUG_PRINTF   // DO NOT LEAVE THIS DEFINED: DEBUG ONLY!!!
+#include <assert.h>
+
+#include "lldb/Core/FileSpecList.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/Timer.h"
+#include "lldb/Host/Host.h"
+
+#include "SymbolFileDWARF.h"
+#include "LogChannelDWARF.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace std;
+
+//----------------------------------------------------------------------
+// Parse
+//
+// Parse all information in the debug_line_data into an internal
+// representation.
+//----------------------------------------------------------------------
+void
+DWARFDebugLine::Parse(const DataExtractor& debug_line_data)
+{
+    m_lineTableMap.clear();
+    lldb::offset_t offset = 0;
+    LineTable::shared_ptr line_table_sp(new LineTable);
+    while (debug_line_data.ValidOffset(offset))
+    {
+        const lldb::offset_t debug_line_offset = offset;
+
+        if (line_table_sp.get() == NULL)
+            break;
+
+        if (ParseStatementTable(debug_line_data, &offset, line_table_sp.get()))
+        {
+            // Make sure we don't don't loop infinitely
+            if (offset <= debug_line_offset)
+                break;
+            //DEBUG_PRINTF("m_lineTableMap[0x%8.8x] = line_table_sp\n", debug_line_offset);
+            m_lineTableMap[debug_line_offset] = line_table_sp;
+            line_table_sp.reset(new LineTable);
+        }
+        else
+            ++offset;   // Try next byte in line table
+    }
+}
+
+void
+DWARFDebugLine::ParseIfNeeded(const DataExtractor& debug_line_data)
+{
+    if (m_lineTableMap.empty())
+        Parse(debug_line_data);
+}
+
+
+//----------------------------------------------------------------------
+// DWARFDebugLine::GetLineTable
+//----------------------------------------------------------------------
+DWARFDebugLine::LineTable::shared_ptr
+DWARFDebugLine::GetLineTable(const dw_offset_t offset) const
+{
+    DWARFDebugLine::LineTable::shared_ptr line_table_shared_ptr;
+    LineTableConstIter pos = m_lineTableMap.find(offset);
+    if (pos != m_lineTableMap.end())
+        line_table_shared_ptr = pos->second;
+    return line_table_shared_ptr;
+}
+
+
+//----------------------------------------------------------------------
+// DumpStateToFile
+//----------------------------------------------------------------------
+static void
+DumpStateToFile (dw_offset_t offset, const DWARFDebugLine::State& state, void* userData)
+{
+    Log *log = (Log *)userData;
+    if (state.row == DWARFDebugLine::State::StartParsingLineTable)
+    {
+        // If the row is zero we are being called with the prologue only
+        state.prologue->Dump (log);
+        log->PutCString ("Address            Line   Column File");
+        log->PutCString ("------------------ ------ ------ ------");
+    }
+    else if (state.row == DWARFDebugLine::State::DoneParsingLineTable)
+    {
+        // Done parsing line table
+    }
+    else
+    {
+        log->Printf( "0x%16.16" PRIx64 " %6u %6u %6u%s\n", state.address, state.line, state.column, state.file, state.end_sequence ? " END" : "");
+    }
+}
+
+//----------------------------------------------------------------------
+// DWARFDebugLine::DumpLineTableRows
+//----------------------------------------------------------------------
+bool
+DWARFDebugLine::DumpLineTableRows(Log *log, SymbolFileDWARF* dwarf2Data, dw_offset_t debug_line_offset)
+{
+    const DataExtractor& debug_line_data = dwarf2Data->get_debug_line_data();
+
+    if (debug_line_offset == DW_INVALID_OFFSET)
+    {
+        // Dump line table to a single file only
+        debug_line_offset = 0;
+        while (debug_line_data.ValidOffset(debug_line_offset))
+            debug_line_offset = DumpStatementTable (log, debug_line_data, debug_line_offset);
+    }
+    else
+    {
+        // Dump line table to a single file only
+        DumpStatementTable (log, debug_line_data, debug_line_offset);
+    }
+    return false;
+}
+
+//----------------------------------------------------------------------
+// DWARFDebugLine::DumpStatementTable
+//----------------------------------------------------------------------
+dw_offset_t
+DWARFDebugLine::DumpStatementTable(Log *log, const DataExtractor& debug_line_data, const dw_offset_t debug_line_offset)
+{
+    if (debug_line_data.ValidOffset(debug_line_offset))
+    {
+        lldb::offset_t offset = debug_line_offset;
+        log->Printf(  "----------------------------------------------------------------------\n"
+                    "debug_line[0x%8.8x]\n"
+                    "----------------------------------------------------------------------\n", debug_line_offset);
+
+        if (ParseStatementTable(debug_line_data, &offset, DumpStateToFile, log))
+            return offset;
+        else
+            return debug_line_offset + 1;   // Skip to next byte in .debug_line section
+    }
+
+    return DW_INVALID_OFFSET;
+}
+
+
+//----------------------------------------------------------------------
+// DumpOpcodes
+//----------------------------------------------------------------------
+bool
+DWARFDebugLine::DumpOpcodes(Log *log, SymbolFileDWARF* dwarf2Data, dw_offset_t debug_line_offset, uint32_t dump_flags)
+{
+    const DataExtractor& debug_line_data = dwarf2Data->get_debug_line_data();
+
+    if (debug_line_data.GetByteSize() == 0)
+    {
+        log->Printf( "< EMPTY >\n");
+        return false;
+    }
+
+    if (debug_line_offset == DW_INVALID_OFFSET)
+    {
+        // Dump line table to a single file only
+        debug_line_offset = 0;
+        while (debug_line_data.ValidOffset(debug_line_offset))
+            debug_line_offset = DumpStatementOpcodes (log, debug_line_data, debug_line_offset, dump_flags);
+    }
+    else
+    {
+        // Dump line table to a single file only
+        DumpStatementOpcodes (log, debug_line_data, debug_line_offset, dump_flags);
+    }
+    return false;
+}
+
+//----------------------------------------------------------------------
+// DumpStatementOpcodes
+//----------------------------------------------------------------------
+dw_offset_t
+DWARFDebugLine::DumpStatementOpcodes(Log *log, const DataExtractor& debug_line_data, const dw_offset_t debug_line_offset, uint32_t flags)
+{
+    lldb::offset_t offset = debug_line_offset;
+    if (debug_line_data.ValidOffset(offset))
+    {
+        Prologue prologue;
+
+        if (ParsePrologue(debug_line_data, &offset, &prologue))
+        {
+            log->PutCString ("----------------------------------------------------------------------");
+            log->Printf     ("debug_line[0x%8.8x]", debug_line_offset);
+            log->PutCString ("----------------------------------------------------------------------\n");
+            prologue.Dump (log);
+        }
+        else
+        {
+            offset = debug_line_offset;
+            log->Printf( "0x%8.8" PRIx64 ": skipping pad byte %2.2x", offset, debug_line_data.GetU8(&offset));
+            return offset;
+        }
+
+        Row row(prologue.default_is_stmt);
+        const dw_offset_t end_offset = debug_line_offset + prologue.total_length + sizeof(prologue.total_length);
+
+        assert(debug_line_data.ValidOffset(end_offset-1));
+
+        while (offset < end_offset)
+        {
+            const uint32_t op_offset = offset;
+            uint8_t opcode = debug_line_data.GetU8(&offset);
+            switch (opcode)
+            {
+            case 0: // Extended Opcodes always start with a zero opcode followed by
+                {   // a uleb128 length so you can skip ones you don't know about
+
+                    dw_offset_t ext_offset = offset;
+                    dw_uleb128_t len = debug_line_data.GetULEB128(&offset);
+                    dw_offset_t arg_size = len - (offset - ext_offset);
+                    uint8_t sub_opcode = debug_line_data.GetU8(&offset);
+//                    if (verbose)
+//                        log->Printf( "Extended: <%u> %2.2x ", len, sub_opcode);
+
+                    switch (sub_opcode)
+                    {
+                    case DW_LNE_end_sequence    :
+                        log->Printf( "0x%8.8x: DW_LNE_end_sequence", op_offset);
+                        row.Dump(log);
+                        row.Reset(prologue.default_is_stmt);
+                        break;
+
+                    case DW_LNE_set_address     :
+                        {
+                            row.address = debug_line_data.GetMaxU64(&offset, arg_size);
+                            log->Printf( "0x%8.8x: DW_LNE_set_address (0x%" PRIx64 ")", op_offset, row.address);
+                        }
+                        break;
+
+                    case DW_LNE_define_file:
+                        {
+                            FileNameEntry fileEntry;
+                            fileEntry.name      = debug_line_data.GetCStr(&offset);
+                            fileEntry.dir_idx   = debug_line_data.GetULEB128(&offset);
+                            fileEntry.mod_time  = debug_line_data.GetULEB128(&offset);
+                            fileEntry.length    = debug_line_data.GetULEB128(&offset);
+                            log->Printf( "0x%8.8x: DW_LNE_define_file('%s', dir=%i, mod_time=0x%8.8x, length=%i )",
+                                    op_offset,
+                                    fileEntry.name.c_str(),
+                                    fileEntry.dir_idx,
+                                    fileEntry.mod_time,
+                                    fileEntry.length);
+                            prologue.file_names.push_back(fileEntry);
+                        }
+                        break;
+
+                    default:
+                        log->Printf( "0x%8.8x: DW_LNE_??? (%2.2x) - Skipping unknown upcode", op_offset, opcode);
+                        // Length doesn't include the zero opcode byte or the length itself, but
+                        // it does include the sub_opcode, so we have to adjust for that below
+                        offset += arg_size;
+                        break;
+                    }
+                }
+                break;
+
+            // Standard Opcodes
+            case DW_LNS_copy:
+                log->Printf( "0x%8.8x: DW_LNS_copy", op_offset);
+                row.Dump (log);
+                break;
+
+            case DW_LNS_advance_pc:
+                {
+                    dw_uleb128_t addr_offset_n = debug_line_data.GetULEB128(&offset);
+                    dw_uleb128_t addr_offset = addr_offset_n * prologue.min_inst_length;
+                    log->Printf( "0x%8.8x: DW_LNS_advance_pc (0x%x)", op_offset, addr_offset);
+                    row.address += addr_offset;
+                }
+                break;
+
+            case DW_LNS_advance_line:
+                {
+                    dw_sleb128_t line_offset = debug_line_data.GetSLEB128(&offset);
+                    log->Printf( "0x%8.8x: DW_LNS_advance_line (%i)", op_offset, line_offset);
+                    row.line += line_offset;
+                }
+                break;
+
+            case DW_LNS_set_file:
+                row.file = debug_line_data.GetULEB128(&offset);
+                log->Printf( "0x%8.8x: DW_LNS_set_file (%u)", op_offset, row.file);
+                break;
+
+            case DW_LNS_set_column:
+                row.column = debug_line_data.GetULEB128(&offset);
+                log->Printf( "0x%8.8x: DW_LNS_set_column (%u)", op_offset, row.column);
+                break;
+
+            case DW_LNS_negate_stmt:
+                row.is_stmt = !row.is_stmt;
+                log->Printf( "0x%8.8x: DW_LNS_negate_stmt", op_offset);
+                break;
+
+            case DW_LNS_set_basic_block:
+                row.basic_block = true;
+                log->Printf( "0x%8.8x: DW_LNS_set_basic_block", op_offset);
+                break;
+
+            case DW_LNS_const_add_pc:
+                {
+                    uint8_t adjust_opcode = 255 - prologue.opcode_base;
+                    dw_addr_t addr_offset = (adjust_opcode / prologue.line_range) * prologue.min_inst_length;
+                    log->Printf( "0x%8.8x: DW_LNS_const_add_pc (0x%8.8" PRIx64 ")", op_offset, addr_offset);
+                    row.address += addr_offset;
+                }
+                break;
+
+            case DW_LNS_fixed_advance_pc:
+                {
+                    uint16_t pc_offset = debug_line_data.GetU16(&offset);
+                    log->Printf( "0x%8.8x: DW_LNS_fixed_advance_pc (0x%4.4x)", op_offset, pc_offset);
+                    row.address += pc_offset;
+                }
+                break;
+
+            case DW_LNS_set_prologue_end:
+                row.prologue_end = true;
+                log->Printf( "0x%8.8x: DW_LNS_set_prologue_end", op_offset);
+                break;
+
+            case DW_LNS_set_epilogue_begin:
+                row.epilogue_begin = true;
+                log->Printf( "0x%8.8x: DW_LNS_set_epilogue_begin", op_offset);
+                break;
+
+            case DW_LNS_set_isa:
+                row.isa = debug_line_data.GetULEB128(&offset);
+                log->Printf( "0x%8.8x: DW_LNS_set_isa (%u)", op_offset, row.isa);
+                break;
+
+            // Special Opcodes
+            default:
+                if (opcode < prologue.opcode_base)
+                {
+                    // We have an opcode that this parser doesn't know about, skip
+                    // the number of ULEB128 numbers that is says to skip in the
+                    // prologue's standard_opcode_lengths array
+                    uint8_t n = prologue.standard_opcode_lengths[opcode-1];
+                    log->Printf( "0x%8.8x: Special : Unknown skipping %u ULEB128 values.", op_offset, n);
+                    while (n > 0)
+                    {
+                        debug_line_data.GetULEB128(&offset);
+                        --n;
+                    }
+                }
+                else
+                {
+                    uint8_t adjust_opcode = opcode - prologue.opcode_base;
+                    dw_addr_t addr_offset = (adjust_opcode / prologue.line_range) * prologue.min_inst_length;
+                    int32_t line_offset = prologue.line_base + (adjust_opcode % prologue.line_range);
+                    log->Printf("0x%8.8x: address += 0x%" PRIx64 ",  line += %i\n", op_offset, (uint64_t)addr_offset, line_offset);
+                    row.address += addr_offset;
+                    row.line += line_offset;
+                    row.Dump (log);
+                }
+                break;
+            }
+        }
+        return end_offset;
+    }
+    return DW_INVALID_OFFSET;
+}
+
+
+
+
+//----------------------------------------------------------------------
+// Parse
+//
+// Parse the entire line table contents calling callback each time a
+// new prologue is parsed and every time a new row is to be added to
+// the line table.
+//----------------------------------------------------------------------
+void
+DWARFDebugLine::Parse(const DataExtractor& debug_line_data, DWARFDebugLine::State::Callback callback, void* userData)
+{
+    lldb::offset_t offset = 0;
+    if (debug_line_data.ValidOffset(offset))
+    {
+        if (!ParseStatementTable(debug_line_data, &offset, callback, userData))
+            ++offset;   // Skip to next byte in .debug_line section
+    }
+}
+
+
+//----------------------------------------------------------------------
+// DWARFDebugLine::ParsePrologue
+//----------------------------------------------------------------------
+bool
+DWARFDebugLine::ParsePrologue(const DataExtractor& debug_line_data, lldb::offset_t* offset_ptr, Prologue* prologue)
+{
+    const lldb::offset_t prologue_offset = *offset_ptr;
+
+    //DEBUG_PRINTF("0x%8.8x: ParsePrologue()\n", *offset_ptr);
+
+    prologue->Clear();
+    uint32_t i;
+    const char * s;
+    prologue->total_length      = debug_line_data.GetU32(offset_ptr);
+    prologue->version           = debug_line_data.GetU16(offset_ptr);
+    if (prologue->version != 2)
+      return false;
+
+    prologue->prologue_length   = debug_line_data.GetU32(offset_ptr);
+    const lldb::offset_t end_prologue_offset = prologue->prologue_length + *offset_ptr;
+    prologue->min_inst_length   = debug_line_data.GetU8(offset_ptr);
+    prologue->default_is_stmt   = debug_line_data.GetU8(offset_ptr);
+    prologue->line_base         = debug_line_data.GetU8(offset_ptr);
+    prologue->line_range        = debug_line_data.GetU8(offset_ptr);
+    prologue->opcode_base       = debug_line_data.GetU8(offset_ptr);
+
+    prologue->standard_opcode_lengths.reserve(prologue->opcode_base-1);
+
+    for (i=1; i<prologue->opcode_base; ++i)
+    {
+        uint8_t op_len = debug_line_data.GetU8(offset_ptr);
+        prologue->standard_opcode_lengths.push_back(op_len);
+    }
+
+    while (*offset_ptr < end_prologue_offset)
+    {
+        s = debug_line_data.GetCStr(offset_ptr);
+        if (s && s[0])
+            prologue->include_directories.push_back(s);
+        else
+            break;
+    }
+
+    while (*offset_ptr < end_prologue_offset)
+    {
+        const char* name = debug_line_data.GetCStr( offset_ptr );
+        if (name && name[0])
+        {
+            FileNameEntry fileEntry;
+            fileEntry.name      = name;
+            fileEntry.dir_idx   = debug_line_data.GetULEB128( offset_ptr );
+            fileEntry.mod_time  = debug_line_data.GetULEB128( offset_ptr );
+            fileEntry.length    = debug_line_data.GetULEB128( offset_ptr );
+            prologue->file_names.push_back(fileEntry);
+        }
+        else
+            break;
+    }
+
+    if (*offset_ptr != end_prologue_offset)
+    {
+        Host::SystemLog (Host::eSystemLogWarning, 
+                         "warning: parsing line table prologue at 0x%8.8" PRIx64 " should have ended at 0x%8.8" PRIx64 " but it ended ad 0x%8.8" PRIx64 "\n",
+                         prologue_offset,
+                         end_prologue_offset, 
+                         *offset_ptr);
+    }
+    return end_prologue_offset;
+}
+
+bool
+DWARFDebugLine::ParseSupportFiles (const lldb::ModuleSP &module_sp,
+                                   const DataExtractor& debug_line_data,
+                                   const char *cu_comp_dir,
+                                   dw_offset_t stmt_list,
+                                   FileSpecList &support_files)
+{
+    lldb::offset_t offset = stmt_list + 4;    // Skip the total length
+    const char * s;
+    uint32_t version = debug_line_data.GetU16(&offset);
+    if (version != 2)
+      return false;
+
+    const dw_offset_t end_prologue_offset = debug_line_data.GetU32(&offset) + offset;
+    // Skip instruction length, default is stmt, line base, line range and
+    // opcode base, and all opcode lengths
+    offset += 4;
+    const uint8_t opcode_base = debug_line_data.GetU8(&offset);
+    offset += opcode_base - 1;
+    std::vector<std::string> include_directories;
+    include_directories.push_back("");  // Directory at index zero doesn't exist
+    while (offset < end_prologue_offset)
+    {
+        s = debug_line_data.GetCStr(&offset);
+        if (s && s[0])
+            include_directories.push_back(s);
+        else
+            break;
+    }
+    std::string fullpath;
+    std::string remapped_fullpath;
+    while (offset < end_prologue_offset)
+    {
+        const char* path = debug_line_data.GetCStr( &offset );
+        if (path && path[0])
+        {
+            uint32_t dir_idx    = debug_line_data.GetULEB128( &offset );
+            debug_line_data.Skip_LEB128(&offset); // Skip mod_time
+            debug_line_data.Skip_LEB128(&offset); // Skip length
+
+            if (path[0] == '/')
+            {
+                // The path starts with a directory delimiter, so we are done.
+                if (module_sp->RemapSourceFile (path, fullpath))
+                    support_files.Append(FileSpec (fullpath.c_str(), false));
+                else
+                    support_files.Append(FileSpec (path, false));
+            }
+            else
+            {
+                if (dir_idx > 0 && dir_idx < include_directories.size())
+                {
+                    if (cu_comp_dir && include_directories[dir_idx][0] != '/')
+                    {
+                        fullpath = cu_comp_dir;
+
+                        if (*fullpath.rbegin() != '/')
+                            fullpath += '/';
+                        fullpath += include_directories[dir_idx];
+
+                    }
+                    else
+                        fullpath = include_directories[dir_idx];
+                }
+                else if (cu_comp_dir && cu_comp_dir[0])
+                {
+                    fullpath = cu_comp_dir;
+                }
+
+                if (!fullpath.empty())
+                {
+                   if (*fullpath.rbegin() != '/')
+                        fullpath += '/';
+                }
+                fullpath += path;
+                if (module_sp->RemapSourceFile (fullpath.c_str(), remapped_fullpath))
+                    support_files.Append(FileSpec (remapped_fullpath.c_str(), false));
+                else
+                    support_files.Append(FileSpec (fullpath.c_str(), false));
+            }
+            
+        }
+    }
+
+    if (offset != end_prologue_offset)
+    {
+        Host::SystemLog (Host::eSystemLogError, 
+                         "warning: parsing line table prologue at 0x%8.8x should have ended at 0x%8.8x but it ended ad 0x%8.8" PRIx64 "\n",
+                         stmt_list, 
+                         end_prologue_offset, 
+                         offset);
+    }
+    return end_prologue_offset;
+}
+
+//----------------------------------------------------------------------
+// ParseStatementTable
+//
+// Parse a single line table (prologue and all rows) and call the
+// callback function once for the prologue (row in state will be zero)
+// and each time a row is to be added to the line table.
+//----------------------------------------------------------------------
+bool
+DWARFDebugLine::ParseStatementTable
+(
+    const DataExtractor& debug_line_data,
+    lldb::offset_t* offset_ptr,
+    DWARFDebugLine::State::Callback callback,
+    void* userData
+)
+{
+    Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_LINE));
+    Prologue::shared_ptr prologue(new Prologue());
+
+
+    const dw_offset_t debug_line_offset = *offset_ptr;
+
+    Timer scoped_timer (__PRETTY_FUNCTION__,
+                        "DWARFDebugLine::ParseStatementTable (.debug_line[0x%8.8x])",
+                        debug_line_offset);
+
+    if (!ParsePrologue(debug_line_data, offset_ptr, prologue.get()))
+    {
+        if (log)
+            log->Error ("failed to parse DWARF line table prologue");
+        // Restore our offset and return false to indicate failure!
+        *offset_ptr = debug_line_offset;
+        return false;
+    }
+
+    if (log)
+        prologue->Dump (log);
+
+    const dw_offset_t end_offset = debug_line_offset + prologue->total_length + sizeof(prologue->total_length);
+
+    State state(prologue, log, callback, userData);
+
+    while (*offset_ptr < end_offset)
+    {
+        //DEBUG_PRINTF("0x%8.8x: ", *offset_ptr);
+        uint8_t opcode = debug_line_data.GetU8(offset_ptr);
+
+        if (opcode == 0)
+        {
+            // Extended Opcodes always start with a zero opcode followed by
+            // a uleb128 length so you can skip ones you don't know about
+            lldb::offset_t ext_offset = *offset_ptr;
+            dw_uleb128_t len = debug_line_data.GetULEB128(offset_ptr);
+            dw_offset_t arg_size = len - (*offset_ptr - ext_offset);
+
+            //DEBUG_PRINTF("Extended: <%2u> ", len);
+            uint8_t sub_opcode = debug_line_data.GetU8(offset_ptr);
+            switch (sub_opcode)
+            {
+            case DW_LNE_end_sequence:
+                // Set the end_sequence register of the state machine to true and
+                // append a row to the matrix using the current values of the
+                // state-machine registers. Then reset the registers to the initial
+                // values specified above. Every statement program sequence must end
+                // with a DW_LNE_end_sequence instruction which creates a row whose
+                // address is that of the byte after the last target machine instruction
+                // of the sequence.
+                state.end_sequence = true;
+                state.AppendRowToMatrix(*offset_ptr);
+                state.Reset();
+                break;
+
+            case DW_LNE_set_address:
+                // Takes a single relocatable address as an operand. The size of the
+                // operand is the size appropriate to hold an address on the target
+                // machine. Set the address register to the value given by the
+                // relocatable address. All of the other statement program opcodes
+                // that affect the address register add a delta to it. This instruction
+                // stores a relocatable value into it instead.
+                state.address = debug_line_data.GetAddress(offset_ptr);
+                break;
+
+            case DW_LNE_define_file:
+                // Takes 4 arguments. The first is a null terminated string containing
+                // a source file name. The second is an unsigned LEB128 number representing
+                // the directory index of the directory in which the file was found. The
+                // third is an unsigned LEB128 number representing the time of last
+                // modification of the file. The fourth is an unsigned LEB128 number
+                // representing the length in bytes of the file. The time and length
+                // fields may contain LEB128(0) if the information is not available.
+                //
+                // The directory index represents an entry in the include_directories
+                // section of the statement program prologue. The index is LEB128(0)
+                // if the file was found in the current directory of the compilation,
+                // LEB128(1) if it was found in the first directory in the
+                // include_directories section, and so on. The directory index is
+                // ignored for file names that represent full path names.
+                //
+                // The files are numbered, starting at 1, in the order in which they
+                // appear; the names in the prologue come before names defined by
+                // the DW_LNE_define_file instruction. These numbers are used in the
+                // the file register of the state machine.
+                {
+                    FileNameEntry fileEntry;
+                    fileEntry.name      = debug_line_data.GetCStr(offset_ptr);
+                    fileEntry.dir_idx   = debug_line_data.GetULEB128(offset_ptr);
+                    fileEntry.mod_time  = debug_line_data.GetULEB128(offset_ptr);
+                    fileEntry.length    = debug_line_data.GetULEB128(offset_ptr);
+                    state.prologue->file_names.push_back(fileEntry);
+                }
+                break;
+
+            default:
+                // Length doesn't include the zero opcode byte or the length itself, but
+                // it does include the sub_opcode, so we have to adjust for that below
+                (*offset_ptr) += arg_size;
+                break;
+            }
+        }
+        else if (opcode < prologue->opcode_base)
+        {
+            switch (opcode)
+            {
+            // Standard Opcodes
+            case DW_LNS_copy:
+                // Takes no arguments. Append a row to the matrix using the
+                // current values of the state-machine registers. Then set
+                // the basic_block register to false.
+                state.AppendRowToMatrix(*offset_ptr);
+                break;
+
+            case DW_LNS_advance_pc:
+                // Takes a single unsigned LEB128 operand, multiplies it by the
+                // min_inst_length field of the prologue, and adds the
+                // result to the address register of the state machine.
+                state.address += debug_line_data.GetULEB128(offset_ptr) * prologue->min_inst_length;
+                break;
+
+            case DW_LNS_advance_line:
+                // Takes a single signed LEB128 operand and adds that value to
+                // the line register of the state machine.
+                state.line += debug_line_data.GetSLEB128(offset_ptr);
+                break;
+
+            case DW_LNS_set_file:
+                // Takes a single unsigned LEB128 operand and stores it in the file
+                // register of the state machine.
+                state.file = debug_line_data.GetULEB128(offset_ptr);
+                break;
+
+            case DW_LNS_set_column:
+                // Takes a single unsigned LEB128 operand and stores it in the
+                // column register of the state machine.
+                state.column = debug_line_data.GetULEB128(offset_ptr);
+                break;
+
+            case DW_LNS_negate_stmt:
+                // Takes no arguments. Set the is_stmt register of the state
+                // machine to the logical negation of its current value.
+                state.is_stmt = !state.is_stmt;
+                break;
+
+            case DW_LNS_set_basic_block:
+                // Takes no arguments. Set the basic_block register of the
+                // state machine to true
+                state.basic_block = true;
+                break;
+
+            case DW_LNS_const_add_pc:
+                // Takes no arguments. Add to the address register of the state
+                // machine the address increment value corresponding to special
+                // opcode 255. The motivation for DW_LNS_const_add_pc is this:
+                // when the statement program needs to advance the address by a
+                // small amount, it can use a single special opcode, which occupies
+                // a single byte. When it needs to advance the address by up to
+                // twice the range of the last special opcode, it can use
+                // DW_LNS_const_add_pc followed by a special opcode, for a total
+                // of two bytes. Only if it needs to advance the address by more
+                // than twice that range will it need to use both DW_LNS_advance_pc
+                // and a special opcode, requiring three or more bytes.
+                {
+                    uint8_t adjust_opcode = 255 - prologue->opcode_base;
+                    dw_addr_t addr_offset = (adjust_opcode / prologue->line_range) * prologue->min_inst_length;
+                    state.address += addr_offset;
+                }
+                break;
+
+            case DW_LNS_fixed_advance_pc:
+                // Takes a single uhalf operand. Add to the address register of
+                // the state machine the value of the (unencoded) operand. This
+                // is the only extended opcode that takes an argument that is not
+                // a variable length number. The motivation for DW_LNS_fixed_advance_pc
+                // is this: existing assemblers cannot emit DW_LNS_advance_pc or
+                // special opcodes because they cannot encode LEB128 numbers or
+                // judge when the computation of a special opcode overflows and
+                // requires the use of DW_LNS_advance_pc. Such assemblers, however,
+                // can use DW_LNS_fixed_advance_pc instead, sacrificing compression.
+                state.address += debug_line_data.GetU16(offset_ptr);
+                break;
+
+            case DW_LNS_set_prologue_end:
+                // Takes no arguments. Set the prologue_end register of the
+                // state machine to true
+                state.prologue_end = true;
+                break;
+
+            case DW_LNS_set_epilogue_begin:
+                // Takes no arguments. Set the basic_block register of the
+                // state machine to true
+                state.epilogue_begin = true;
+                break;
+
+            case DW_LNS_set_isa:
+                // Takes a single unsigned LEB128 operand and stores it in the
+                // column register of the state machine.
+                state.isa = debug_line_data.GetULEB128(offset_ptr);
+                break;
+
+            default:
+                // Handle any unknown standard opcodes here. We know the lengths
+                // of such opcodes because they are specified in the prologue
+                // as a multiple of LEB128 operands for each opcode.
+                {
+                    uint8_t i;
+                    assert (opcode - 1 < prologue->standard_opcode_lengths.size());
+                    const uint8_t opcode_length = prologue->standard_opcode_lengths[opcode - 1];
+                    for (i=0; i<opcode_length; ++i)
+                        debug_line_data.Skip_LEB128(offset_ptr);
+                }
+                break;
+            }
+        }
+        else
+        {
+            // Special Opcodes
+
+            // A special opcode value is chosen based on the amount that needs
+            // to be added to the line and address registers. The maximum line
+            // increment for a special opcode is the value of the line_base
+            // field in the header, plus the value of the line_range field,
+            // minus 1 (line base + line range - 1). If the desired line
+            // increment is greater than the maximum line increment, a standard
+            // opcode must be used instead of a special opcode. The "address
+            // advance" is calculated by dividing the desired address increment
+            // by the minimum_instruction_length field from the header. The
+            // special opcode is then calculated using the following formula:
+            //
+            //  opcode = (desired line increment - line_base) + (line_range * address advance) + opcode_base
+            //
+            // If the resulting opcode is greater than 255, a standard opcode
+            // must be used instead.
+            //
+            // To decode a special opcode, subtract the opcode_base from the
+            // opcode itself to give the adjusted opcode. The amount to
+            // increment the address register is the result of the adjusted
+            // opcode divided by the line_range multiplied by the
+            // minimum_instruction_length field from the header. That is:
+            //
+            //  address increment = (adjusted opcode / line_range) * minimum_instruction_length
+            //
+            // The amount to increment the line register is the line_base plus
+            // the result of the adjusted opcode modulo the line_range. That is:
+            //
+            // line increment = line_base + (adjusted opcode % line_range)
+
+            uint8_t adjust_opcode = opcode - prologue->opcode_base;
+            dw_addr_t addr_offset = (adjust_opcode / prologue->line_range) * prologue->min_inst_length;
+            int32_t line_offset = prologue->line_base + (adjust_opcode % prologue->line_range);
+            state.line += line_offset;
+            state.address += addr_offset;
+            state.AppendRowToMatrix(*offset_ptr);
+        }
+    }
+
+    state.Finalize( *offset_ptr );
+
+    return end_offset;
+}
+
+
+//----------------------------------------------------------------------
+// ParseStatementTableCallback
+//----------------------------------------------------------------------
+static void
+ParseStatementTableCallback(dw_offset_t offset, const DWARFDebugLine::State& state, void* userData)
+{
+    DWARFDebugLine::LineTable* line_table = (DWARFDebugLine::LineTable*)userData;
+    if (state.row == DWARFDebugLine::State::StartParsingLineTable)
+    {
+        // Just started parsing the line table, so lets keep a reference to
+        // the prologue using the supplied shared pointer
+        line_table->prologue = state.prologue;
+    }
+    else if (state.row == DWARFDebugLine::State::DoneParsingLineTable)
+    {
+        // Done parsing line table, nothing to do for the cleanup
+    }
+    else
+    {
+        // We have a new row, lets append it
+        line_table->AppendRow(state);
+    }
+}
+
+//----------------------------------------------------------------------
+// ParseStatementTable
+//
+// Parse a line table at offset and populate the LineTable class with
+// the prologue and all rows.
+//----------------------------------------------------------------------
+bool
+DWARFDebugLine::ParseStatementTable(const DataExtractor& debug_line_data, lldb::offset_t *offset_ptr, LineTable* line_table)
+{
+    return ParseStatementTable(debug_line_data, offset_ptr, ParseStatementTableCallback, line_table);
+}
+
+
+inline bool
+DWARFDebugLine::Prologue::IsValid() const
+{
+    return SymbolFileDWARF::SupportedVersion(version);
+}
+
+//----------------------------------------------------------------------
+// DWARFDebugLine::Prologue::Dump
+//----------------------------------------------------------------------
+void
+DWARFDebugLine::Prologue::Dump(Log *log)
+{
+    uint32_t i;
+
+    log->Printf( "Line table prologue:");
+    log->Printf( "   total_length: 0x%8.8x", total_length);
+    log->Printf( "        version: %u", version);
+    log->Printf( "prologue_length: 0x%8.8x", prologue_length);
+    log->Printf( "min_inst_length: %u", min_inst_length);
+    log->Printf( "default_is_stmt: %u", default_is_stmt);
+    log->Printf( "      line_base: %i", line_base);
+    log->Printf( "     line_range: %u", line_range);
+    log->Printf( "    opcode_base: %u", opcode_base);
+
+    for (i=0; i<standard_opcode_lengths.size(); ++i)
+    {
+        log->Printf( "standard_opcode_lengths[%s] = %u", DW_LNS_value_to_name(i+1), standard_opcode_lengths[i]);
+    }
+
+    if (!include_directories.empty())
+    {
+        for (i=0; i<include_directories.size(); ++i)
+        {
+            log->Printf( "include_directories[%3u] = '%s'", i+1, include_directories[i].c_str());
+        }
+    }
+
+    if (!file_names.empty())
+    {
+        log->PutCString ("                Dir  Mod Time   File Len   File Name");
+        log->PutCString ("                ---- ---------- ---------- ---------------------------");
+        for (i=0; i<file_names.size(); ++i)
+        {
+            const FileNameEntry& fileEntry = file_names[i];
+            log->Printf ("file_names[%3u] %4u 0x%8.8x 0x%8.8x %s",
+                i+1,
+                fileEntry.dir_idx,
+                fileEntry.mod_time,
+                fileEntry.length,
+                fileEntry.name.c_str());
+        }
+    }
+}
+
+
+//----------------------------------------------------------------------
+// DWARFDebugLine::ParsePrologue::Append
+//
+// Append the contents of the prologue to the binary stream buffer
+//----------------------------------------------------------------------
+//void
+//DWARFDebugLine::Prologue::Append(BinaryStreamBuf& buff) const
+//{
+//  uint32_t i;
+//
+//  buff.Append32(total_length);
+//  buff.Append16(version);
+//  buff.Append32(prologue_length);
+//  buff.Append8(min_inst_length);
+//  buff.Append8(default_is_stmt);
+//  buff.Append8(line_base);
+//  buff.Append8(line_range);
+//  buff.Append8(opcode_base);
+//
+//  for (i=0; i<standard_opcode_lengths.size(); ++i)
+//      buff.Append8(standard_opcode_lengths[i]);
+//
+//  for (i=0; i<include_directories.size(); ++i)
+//      buff.AppendCStr(include_directories[i].c_str());
+//  buff.Append8(0);    // Terminate the include directory section with empty string
+//
+//  for (i=0; i<file_names.size(); ++i)
+//  {
+//      buff.AppendCStr(file_names[i].name.c_str());
+//      buff.Append32_as_ULEB128(file_names[i].dir_idx);
+//      buff.Append32_as_ULEB128(file_names[i].mod_time);
+//      buff.Append32_as_ULEB128(file_names[i].length);
+//  }
+//  buff.Append8(0);    // Terminate the file names section with empty string
+//}
+
+
+bool DWARFDebugLine::Prologue::GetFile(uint32_t file_idx, std::string& path, std::string& directory) const
+{
+    uint32_t idx = file_idx - 1;    // File indexes are 1 based...
+    if (idx < file_names.size())
+    {
+        path = file_names[idx].name;
+        uint32_t dir_idx = file_names[idx].dir_idx - 1;
+        if (dir_idx < include_directories.size())
+            directory = include_directories[dir_idx];
+        else
+            directory.clear();
+        return true;
+    }
+    return false;
+}
+
+//----------------------------------------------------------------------
+// DWARFDebugLine::LineTable::Dump
+//----------------------------------------------------------------------
+void
+DWARFDebugLine::LineTable::Dump(Log *log) const
+{
+    if (prologue.get())
+        prologue->Dump (log);
+
+    if (!rows.empty())
+    {
+        log->PutCString ("Address            Line   Column File   ISA Flags");
+        log->PutCString ("------------------ ------ ------ ------ --- -------------");
+        Row::const_iterator pos = rows.begin();
+        Row::const_iterator end = rows.end();
+        while (pos != end)
+        {
+            (*pos).Dump (log);
+            ++pos;
+        }
+    }
+}
+
+
+void
+DWARFDebugLine::LineTable::AppendRow(const DWARFDebugLine::Row& state)
+{
+    rows.push_back(state);
+}
+
+
+
+//----------------------------------------------------------------------
+// Compare function for the binary search in DWARFDebugLine::LineTable::LookupAddress()
+//----------------------------------------------------------------------
+static bool FindMatchingAddress (const DWARFDebugLine::Row& row1, const DWARFDebugLine::Row& row2)
+{
+    return row1.address < row2.address;
+}
+
+
+//----------------------------------------------------------------------
+// DWARFDebugLine::LineTable::LookupAddress
+//----------------------------------------------------------------------
+uint32_t
+DWARFDebugLine::LineTable::LookupAddress(dw_addr_t address, dw_addr_t cu_high_pc) const
+{
+    uint32_t index = UINT32_MAX;
+    if (!rows.empty())
+    {
+        // Use the lower_bound algorithm to perform a binary search since we know
+        // that our line table data is ordered by address.
+        DWARFDebugLine::Row row;
+        row.address = address;
+        Row::const_iterator begin_pos = rows.begin();
+        Row::const_iterator end_pos = rows.end();
+        Row::const_iterator pos = lower_bound(begin_pos, end_pos, row, FindMatchingAddress);
+        if (pos == end_pos)
+        {
+            if (address < cu_high_pc)
+                return rows.size()-1;
+        }
+        else
+        {
+            // Rely on fact that we are using a std::vector and we can do
+            // pointer arithmetic to find the row index (which will be one less
+            // that what we found since it will find the first position after
+            // the current address) since std::vector iterators are just
+            // pointers to the container type.
+            index = pos - begin_pos;
+            if (pos->address > address)
+            {
+                if (index > 0)
+                    --index;
+                else
+                    index = UINT32_MAX;
+            }
+        }
+    }
+    return index;   // Failed to find address
+}
+
+
+//----------------------------------------------------------------------
+// DWARFDebugLine::Row::Row
+//----------------------------------------------------------------------
+DWARFDebugLine::Row::Row(bool default_is_stmt) :
+    address(0),
+    line(1),
+    column(0),
+    file(1),
+    is_stmt(default_is_stmt),
+    basic_block(false),
+    end_sequence(false),
+    prologue_end(false),
+    epilogue_begin(false),
+    isa(0)
+{
+}
+
+//----------------------------------------------------------------------
+// Called after a row is appended to the matrix
+//----------------------------------------------------------------------
+void
+DWARFDebugLine::Row::PostAppend()
+{
+    basic_block = false;
+    prologue_end = false;
+    epilogue_begin = false;
+}
+
+
+//----------------------------------------------------------------------
+// DWARFDebugLine::Row::Reset
+//----------------------------------------------------------------------
+void
+DWARFDebugLine::Row::Reset(bool default_is_stmt)
+{
+    address = 0;
+    line = 1;
+    column = 0;
+    file = 1;
+    is_stmt = default_is_stmt;
+    basic_block = false;
+    end_sequence = false;
+    prologue_end = false;
+    epilogue_begin = false;
+    isa = 0;
+}
+//----------------------------------------------------------------------
+// DWARFDebugLine::Row::Dump
+//----------------------------------------------------------------------
+void
+DWARFDebugLine::Row::Dump(Log *log) const
+{
+    log->Printf( "0x%16.16" PRIx64 " %6u %6u %6u %3u %s%s%s%s%s",
+                address,
+                line,
+                column,
+                file,
+                isa,
+                is_stmt ? " is_stmt" : "",
+                basic_block ? " basic_block" : "",
+                prologue_end ? " prologue_end" : "",
+                epilogue_begin ? " epilogue_begin" : "",
+                end_sequence ? " end_sequence" : "");
+}
+
+//----------------------------------------------------------------------
+// Compare function LineTable structures
+//----------------------------------------------------------------------
+static bool AddressLessThan (const DWARFDebugLine::Row& a, const DWARFDebugLine::Row& b)
+{
+    return a.address < b.address;
+}
+
+
+
+// Insert a row at the correct address if the addresses can be out of
+// order which can only happen when we are linking a line table that
+// may have had it's contents rearranged.
+void
+DWARFDebugLine::Row::Insert(Row::collection& state_coll, const Row& state)
+{
+    // If we don't have anything yet, or if the address of the last state in our
+    // line table is less than the current one, just append the current state
+    if (state_coll.empty() || AddressLessThan(state_coll.back(), state))
+    {
+        state_coll.push_back(state);
+    }
+    else
+    {
+        // Do a binary search for the correct entry
+        pair<Row::iterator, Row::iterator> range(equal_range(state_coll.begin(), state_coll.end(), state, AddressLessThan));
+
+        // If the addresses are equal, we can safely replace the previous entry
+        // with the current one if the one it is replacing is an end_sequence entry.
+        // We currently always place an extra end sequence when ever we exit a valid
+        // address range for a function in case the functions get rearranged by
+        // optimizations or by order specifications. These extra end sequences will
+        // disappear by getting replaced with valid consecutive entries within a
+        // compile unit if there are no gaps.
+        if (range.first == range.second)
+        {
+            state_coll.insert(range.first, state);
+        }
+        else
+        {
+            if ((distance(range.first, range.second) == 1) && range.first->end_sequence == true)
+            {
+                *range.first = state;
+            }
+            else
+            {
+                state_coll.insert(range.second, state);
+            }
+        }
+    }
+}
+
+void
+DWARFDebugLine::Row::Dump(Log *log, const Row::collection& state_coll)
+{
+    std::for_each (state_coll.begin(), state_coll.end(), bind2nd(std::mem_fun_ref(&Row::Dump),log));
+}
+
+
+//----------------------------------------------------------------------
+// DWARFDebugLine::State::State
+//----------------------------------------------------------------------
+DWARFDebugLine::State::State(Prologue::shared_ptr& p, Log *l, DWARFDebugLine::State::Callback cb, void* userData) :
+    Row (p->default_is_stmt),
+    prologue (p),
+    log (l),
+    callback (cb),
+    callbackUserData (userData),
+    row (StartParsingLineTable)
+{
+    // Call the callback with the initial row state of zero for the prologue
+    if (callback)
+        callback(0, *this, callbackUserData);
+}
+
+//----------------------------------------------------------------------
+// DWARFDebugLine::State::Reset
+//----------------------------------------------------------------------
+void
+DWARFDebugLine::State::Reset()
+{
+    Row::Reset(prologue->default_is_stmt);
+}
+
+//----------------------------------------------------------------------
+// DWARFDebugLine::State::AppendRowToMatrix
+//----------------------------------------------------------------------
+void
+DWARFDebugLine::State::AppendRowToMatrix(dw_offset_t offset)
+{
+    // Each time we are to add an entry into the line table matrix
+    // call the callback function so that someone can do something with
+    // the current state of the state machine (like build a line table
+    // or dump the line table!)
+    if (log)
+    {
+        if (row == 0)
+        {
+            log->PutCString ("Address            Line   Column File   ISA Flags");
+            log->PutCString ("------------------ ------ ------ ------ --- -------------");
+        }
+        Dump (log);
+    }
+
+    ++row;  // Increase the row number before we call our callback for a real row
+    if (callback)
+        callback(offset, *this, callbackUserData);
+    PostAppend();
+}
+
+//----------------------------------------------------------------------
+// DWARFDebugLine::State::Finalize
+//----------------------------------------------------------------------
+void
+DWARFDebugLine::State::Finalize(dw_offset_t offset)
+{
+    // Call the callback with a special row state when we are done parsing a
+    // line table
+    row = DoneParsingLineTable;
+    if (callback)
+        callback(offset, *this, callbackUserData);
+}
+
+//void
+//DWARFDebugLine::AppendLineTableData
+//(
+//  const DWARFDebugLine::Prologue* prologue,
+//  const DWARFDebugLine::Row::collection& state_coll,
+//  const uint32_t addr_size,
+//  BinaryStreamBuf &debug_line_data
+//)
+//{
+//  if (state_coll.empty())
+//  {
+//      // We have no entries, just make an empty line table
+//      debug_line_data.Append8(0);
+//      debug_line_data.Append8(1);
+//      debug_line_data.Append8(DW_LNE_end_sequence);
+//  }
+//  else
+//  {
+//      DWARFDebugLine::Row::const_iterator pos;
+//      Row::const_iterator end = state_coll.end();
+//      bool default_is_stmt = prologue->default_is_stmt;
+//      const DWARFDebugLine::Row reset_state(default_is_stmt);
+//      const DWARFDebugLine::Row* prev_state = &reset_state;
+//      const int32_t max_line_increment_for_special_opcode = prologue->MaxLineIncrementForSpecialOpcode();
+//      for (pos = state_coll.begin(); pos != end; ++pos)
+//      {
+//          const DWARFDebugLine::Row& curr_state = *pos;
+//          int32_t line_increment  = 0;
+//          dw_addr_t addr_offset   = curr_state.address - prev_state->address;
+//          dw_addr_t addr_advance  = (addr_offset) / prologue->min_inst_length;
+//          line_increment = (int32_t)(curr_state.line - prev_state->line);
+//
+//          // If our previous state was the reset state, then let's emit the
+//          // address to keep GDB's DWARF parser happy. If we don't start each
+//          // sequence with a DW_LNE_set_address opcode, the line table won't
+//          // get slid properly in GDB.
+//
+//          if (prev_state == &reset_state)
+//          {
+//              debug_line_data.Append8(0); // Extended opcode
+//              debug_line_data.Append32_as_ULEB128(addr_size + 1); // Length of opcode bytes
+//              debug_line_data.Append8(DW_LNE_set_address);
+//              debug_line_data.AppendMax64(curr_state.address, addr_size);
+//              addr_advance = 0;
+//          }
+//
+//          if (prev_state->file != curr_state.file)
+//          {
+//              debug_line_data.Append8(DW_LNS_set_file);
+//              debug_line_data.Append32_as_ULEB128(curr_state.file);
+//          }
+//
+//          if (prev_state->column != curr_state.column)
+//          {
+//              debug_line_data.Append8(DW_LNS_set_column);
+//              debug_line_data.Append32_as_ULEB128(curr_state.column);
+//          }
+//
+//          // Don't do anything fancy if we are at the end of a sequence
+//          // as we don't want to push any extra rows since the DW_LNE_end_sequence
+//          // will push a row itself!
+//          if (curr_state.end_sequence)
+//          {
+//              if (line_increment != 0)
+//              {
+//                  debug_line_data.Append8(DW_LNS_advance_line);
+//                  debug_line_data.Append32_as_SLEB128(line_increment);
+//              }
+//
+//              if (addr_advance > 0)
+//              {
+//                  debug_line_data.Append8(DW_LNS_advance_pc);
+//                  debug_line_data.Append32_as_ULEB128(addr_advance);
+//              }
+//
+//              // Now push the end sequence on!
+//              debug_line_data.Append8(0);
+//              debug_line_data.Append8(1);
+//              debug_line_data.Append8(DW_LNE_end_sequence);
+//
+//              prev_state = &reset_state;
+//          }
+//          else
+//          {
+//              if (line_increment || addr_advance)
+//              {
+//                  if (line_increment > max_line_increment_for_special_opcode)
+//                  {
+//                      debug_line_data.Append8(DW_LNS_advance_line);
+//                      debug_line_data.Append32_as_SLEB128(line_increment);
+//                      line_increment = 0;
+//                  }
+//
+//                  uint32_t special_opcode = (line_increment >= prologue->line_base) ? ((line_increment - prologue->line_base) + (prologue->line_range * addr_advance) + prologue->opcode_base) : 256;
+//                  if (special_opcode > 255)
+//                  {
+//                      // Both the address and line won't fit in one special opcode
+//                      // check to see if just the line advance will?
+//                      uint32_t special_opcode_line = ((line_increment >= prologue->line_base) && (line_increment != 0)) ?
+//                              ((line_increment - prologue->line_base) + prologue->opcode_base) : 256;
+//
+//
+//                      if (special_opcode_line > 255)
+//                      {
+//                          // Nope, the line advance won't fit by itself, check the address increment by itself
+//                          uint32_t special_opcode_addr = addr_advance ?
+//                              ((0 - prologue->line_base) + (prologue->line_range * addr_advance) + prologue->opcode_base) : 256;
+//
+//                          if (special_opcode_addr > 255)
+//                          {
+//                              // Neither the address nor the line will fit in a
+//                              // special opcode, we must manually enter both then
+//                              // do a DW_LNS_copy to push a row (special opcode
+//                              // automatically imply a new row is pushed)
+//                              if (line_increment != 0)
+//                              {
+//                                  debug_line_data.Append8(DW_LNS_advance_line);
+//                                  debug_line_data.Append32_as_SLEB128(line_increment);
+//                              }
+//
+//                              if (addr_advance > 0)
+//                              {
+//                                  debug_line_data.Append8(DW_LNS_advance_pc);
+//                                  debug_line_data.Append32_as_ULEB128(addr_advance);
+//                              }
+//
+//                              // Now push a row onto the line table manually
+//                              debug_line_data.Append8(DW_LNS_copy);
+//
+//                          }
+//                          else
+//                          {
+//                              // The address increment alone will fit into a special opcode
+//                              // so modify our line change, then issue a special opcode
+//                              // for the address increment and it will push a row into the
+//                              // line table
+//                              if (line_increment != 0)
+//                              {
+//                                  debug_line_data.Append8(DW_LNS_advance_line);
+//                                  debug_line_data.Append32_as_SLEB128(line_increment);
+//                              }
+//
+//                              // Advance of line and address will fit into a single byte special opcode
+//                              // and this will also push a row onto the line table
+//                              debug_line_data.Append8(special_opcode_addr);
+//                          }
+//                      }
+//                      else
+//                      {
+//                          // The line change alone will fit into a special opcode
+//                          // so modify our address increment first, then issue a
+//                          // special opcode for the line change and it will push
+//                          // a row into the line table
+//                          if (addr_advance > 0)
+//                          {
+//                              debug_line_data.Append8(DW_LNS_advance_pc);
+//                              debug_line_data.Append32_as_ULEB128(addr_advance);
+//                          }
+//
+//                          // Advance of line and address will fit into a single byte special opcode
+//                          // and this will also push a row onto the line table
+//                          debug_line_data.Append8(special_opcode_line);
+//                      }
+//                  }
+//                  else
+//                  {
+//                      // Advance of line and address will fit into a single byte special opcode
+//                      // and this will also push a row onto the line table
+//                      debug_line_data.Append8(special_opcode);
+//                  }
+//              }
+//              prev_state = &curr_state;
+//          }
+//      }
+//  }
+//}
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h
new file mode 100644
index 000000000000..cfa8654ed9ba
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugLine.h
@@ -0,0 +1,225 @@
+//===-- DWARFDebugLine.h ----------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SymbolFileDWARF_DWARFDebugLine_h_
+#define SymbolFileDWARF_DWARFDebugLine_h_
+
+#include <map>
+#include <vector>
+#include <string>
+
+#include "lldb/lldb-private.h"
+
+#include "DWARFDefines.h"
+
+class SymbolFileDWARF;
+class DWARFDebugInfoEntry;
+
+//----------------------------------------------------------------------
+// DWARFDebugLine
+//----------------------------------------------------------------------
+class DWARFDebugLine
+{
+public:
+    //------------------------------------------------------------------
+    // FileNameEntry
+    //------------------------------------------------------------------
+    struct FileNameEntry
+    {
+        FileNameEntry() :
+            name(),
+            dir_idx(0),
+            mod_time(0),
+            length(0)
+        {
+        }
+
+        std::string     name;
+        dw_sleb128_t    dir_idx;
+        dw_sleb128_t    mod_time;
+        dw_sleb128_t    length;
+
+    };
+
+    //------------------------------------------------------------------
+    // Prologue
+    //------------------------------------------------------------------
+    struct Prologue
+    {
+
+        Prologue() :
+            total_length(0),
+            version(0),
+            prologue_length(0),
+            min_inst_length(0),
+            default_is_stmt(0),
+            line_base(0),
+            line_range(0),
+            opcode_base(0),
+            standard_opcode_lengths(),
+            include_directories(),
+            file_names()
+        {
+        }
+
+        typedef std::shared_ptr<Prologue> shared_ptr;
+
+        uint32_t    total_length;   // The size in bytes of the statement information for this compilation unit (not including the total_length field itself).
+        uint16_t    version;        // Version identifier for the statement information format.
+        uint32_t    prologue_length;// The number of bytes following the prologue_length field to the beginning of the first byte of the statement program itself.
+        uint8_t     min_inst_length;// The size in bytes of the smallest target machine instruction. Statement program opcodes that alter the address register first multiply their operands by this value.
+        uint8_t     default_is_stmt;// The initial value of theis_stmtregister.
+        int8_t      line_base;      // This parameter affects the meaning of the special opcodes. See below.
+        uint8_t     line_range;     // This parameter affects the meaning of the special opcodes. See below.
+        uint8_t     opcode_base;    // The number assigned to the first special opcode.
+        std::vector<uint8_t>            standard_opcode_lengths;
+        std::vector<std::string>        include_directories;
+        std::vector<FileNameEntry>      file_names;
+
+        // Length of the prologue in bytes
+        uint32_t Length() const { return prologue_length + sizeof(total_length) + sizeof(version) + sizeof(prologue_length); }
+        // Length of the line table data in bytes (not including the prologue)
+        uint32_t StatementTableLength() const { return total_length + sizeof(total_length) - Length(); }
+        int32_t MaxLineIncrementForSpecialOpcode() const { return line_base + (int8_t)line_range - 1; }
+        bool IsValid() const;
+//      void Append(BinaryStreamBuf& buff) const;
+        void Dump (lldb_private::Log *log);
+        void Clear()
+        {
+            total_length = version = prologue_length = min_inst_length = line_base = line_range = opcode_base = 0;
+            line_base = 0;
+            standard_opcode_lengths.clear();
+            include_directories.clear();
+            file_names.clear();
+        }
+        bool GetFile(uint32_t file_idx, std::string& file, std::string& dir) const;
+
+    };
+
+    // Standard .debug_line state machine structure
+    struct Row
+    {
+        typedef std::vector<Row>            collection;
+        typedef collection::iterator        iterator;
+        typedef collection::const_iterator  const_iterator;
+
+        Row(bool default_is_stmt = false);
+        virtual ~Row() {}
+        void PostAppend ();
+        void Reset(bool default_is_stmt);
+        void Dump(lldb_private::Log *log) const;
+        static void Insert(Row::collection& state_coll, const Row& state);
+        static void Dump(lldb_private::Log *log, const Row::collection& state_coll);
+
+        dw_addr_t   address;        // The program-counter value corresponding to a machine instruction generated by the compiler.
+        uint32_t    line;           // An unsigned integer indicating a source line number. Lines are numbered beginning at 1. The compiler may emit the value 0 in cases where an instruction cannot be attributed to any source line.
+        uint16_t    column;         // An unsigned integer indicating a column number within a source line. Columns are numbered beginning at 1. The value 0 is reserved to indicate that a statement begins at the 'left edge' of the line.
+        uint16_t    file;           // An unsigned integer indicating the identity of the source file corresponding to a machine instruction.
+        uint8_t     is_stmt:1,      // A boolean indicating that the current instruction is the beginning of a statement.
+                    basic_block:1,  // A boolean indicating that the current instruction is the beginning of a basic block.
+                    end_sequence:1, // A boolean indicating that the current address is that of the first byte after the end of a sequence of target machine instructions.
+                    prologue_end:1, // A boolean indicating that the current address is one (of possibly many) where execution should be suspended for an entry breakpoint of a function.
+                    epilogue_begin:1;// A boolean indicating that the current address is one (of possibly many) where execution should be suspended for an exit breakpoint of a function.
+        uint32_t    isa;            // An unsigned integer whose value encodes the applicable instruction set architecture for the current instruction.
+    };
+
+
+    //------------------------------------------------------------------
+    // LineTable
+    //------------------------------------------------------------------
+    struct LineTable
+    {
+        typedef std::shared_ptr<LineTable> shared_ptr;
+
+        LineTable() :
+            prologue(),
+            rows()
+        {
+        }
+
+        void AppendRow(const DWARFDebugLine::Row& state);
+        void Clear()
+        {
+            prologue.reset();
+            rows.clear();
+        }
+
+        uint32_t LookupAddress(dw_addr_t address, dw_addr_t cu_high_pc) const;
+        void Dump(lldb_private::Log *log) const;
+
+        Prologue::shared_ptr prologue;
+        Row::collection rows;
+    };
+
+    //------------------------------------------------------------------
+    // State
+    //------------------------------------------------------------------
+    struct State : public Row
+    {
+        typedef void (*Callback)(dw_offset_t offset, const State& state, void* userData);
+
+        // Special row codes used when calling the callback
+        enum
+        {
+            StartParsingLineTable = 0,
+            DoneParsingLineTable = -1
+        };
+
+        State (Prologue::shared_ptr& prologue_sp,
+               lldb_private::Log *log,
+               Callback callback,
+               void* userData);
+
+        void
+        AppendRowToMatrix (dw_offset_t offset);
+
+        void
+        Finalize (dw_offset_t offset);
+
+        void
+        Reset ();
+
+        Prologue::shared_ptr prologue;
+        lldb_private::Log *log;
+        Callback callback; // Callback function that gets called each time an entry is to be added to the matrix
+        void* callbackUserData;
+        int row; // The row number that starts at zero for the prologue, and increases for each row added to the matrix
+    private:
+        DISALLOW_COPY_AND_ASSIGN (State);
+    };
+
+    static bool DumpOpcodes(lldb_private::Log *log, SymbolFileDWARF* dwarf2Data, dw_offset_t line_offset = DW_INVALID_OFFSET, uint32_t dump_flags = 0);   // If line_offset is invalid, dump everything
+    static bool DumpLineTableRows(lldb_private::Log *log, SymbolFileDWARF* dwarf2Data, dw_offset_t line_offset = DW_INVALID_OFFSET);  // If line_offset is invalid, dump everything
+    static bool ParseSupportFiles(const lldb::ModuleSP &module_sp, const lldb_private::DataExtractor& debug_line_data, const char *cu_comp_dir, dw_offset_t stmt_list, lldb_private::FileSpecList &support_files);
+    static bool ParsePrologue(const lldb_private::DataExtractor& debug_line_data, lldb::offset_t* offset_ptr, Prologue* prologue);
+    static bool ParseStatementTable(const lldb_private::DataExtractor& debug_line_data, lldb::offset_t* offset_ptr, State::Callback callback, void* userData);
+    static dw_offset_t DumpStatementTable(lldb_private::Log *log, const lldb_private::DataExtractor& debug_line_data, const dw_offset_t line_offset);
+    static dw_offset_t DumpStatementOpcodes(lldb_private::Log *log, const lldb_private::DataExtractor& debug_line_data, const dw_offset_t line_offset, uint32_t flags);
+    static bool ParseStatementTable(const lldb_private::DataExtractor& debug_line_data, lldb::offset_t *offset_ptr, LineTable* line_table);
+    static void Parse(const lldb_private::DataExtractor& debug_line_data, DWARFDebugLine::State::Callback callback, void* userData);
+//  static void AppendLineTableData(const DWARFDebugLine::Prologue* prologue, const DWARFDebugLine::Row::collection& state_coll, const uint32_t addr_size, BinaryStreamBuf &debug_line_data);
+
+    DWARFDebugLine() :
+        m_lineTableMap()
+    {
+    }
+
+    void Parse(const lldb_private::DataExtractor& debug_line_data);
+    void ParseIfNeeded(const lldb_private::DataExtractor& debug_line_data);
+    LineTable::shared_ptr GetLineTable(const dw_offset_t offset) const;
+
+protected:
+    typedef std::map<dw_offset_t, LineTable::shared_ptr> LineTableMap;
+    typedef LineTableMap::iterator LineTableIter;
+    typedef LineTableMap::const_iterator LineTableConstIter;
+
+    LineTableMap m_lineTableMap;
+};
+
+#endif  // SymbolFileDWARF_DWARFDebugLine_h_
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfo.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfo.cpp
new file mode 100644
index 000000000000..60ace9e82290
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfo.cpp
@@ -0,0 +1,48 @@
+//===-- DWARFDebugMacinfo.cpp -----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFDebugMacinfo.h"
+
+#include "DWARFDebugMacinfoEntry.h"
+#include "SymbolFileDWARF.h"
+
+#include "lldb/Core/Stream.h"
+
+using namespace lldb_private;
+using namespace std;
+
+DWARFDebugMacinfo::DWARFDebugMacinfo()
+{
+}
+
+DWARFDebugMacinfo::~DWARFDebugMacinfo()
+{
+}
+
+void
+DWARFDebugMacinfo::Dump(Stream *s, const DataExtractor& macinfo_data, lldb::offset_t offset)
+{
+    DWARFDebugMacinfoEntry maninfo_entry;
+    if (macinfo_data.GetByteSize() == 0)
+    {
+        s->PutCString("< EMPTY >\n");
+        return;
+    }
+    if (offset == LLDB_INVALID_OFFSET)
+    {
+        offset = 0;
+        while (maninfo_entry.Extract(macinfo_data, &offset))
+            maninfo_entry.Dump(s);
+    }
+    else
+    {
+        if (maninfo_entry.Extract(macinfo_data, &offset))
+            maninfo_entry.Dump(s);
+    }
+}
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfo.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfo.h
new file mode 100644
index 000000000000..5f3b437d964f
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfo.h
@@ -0,0 +1,29 @@
+//===-- DWARFDebugMacinfo.h -------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SymbolFileDWARF_DWARFDebugMacinfo_h_
+#define SymbolFileDWARF_DWARFDebugMacinfo_h_
+
+#include "SymbolFileDWARF.h"
+
+class DWARFDebugMacinfo
+{
+public:
+    DWARFDebugMacinfo();
+
+    ~DWARFDebugMacinfo();
+
+    static void
+    Dump (lldb_private::Stream *s,
+          const lldb_private::DataExtractor& macinfo_data,
+          lldb::offset_t offset = LLDB_INVALID_OFFSET);
+};
+
+
+#endif  // SymbolFileDWARF_DWARFDebugMacinfo_h_
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfoEntry.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfoEntry.cpp
new file mode 100644
index 000000000000..5cd9cb6be474
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfoEntry.cpp
@@ -0,0 +1,132 @@
+//===-- DWARFDebugMacinfoEntry.cpp ------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFDebugMacinfoEntry.h"
+
+#include "lldb/Core/Stream.h"
+
+using namespace lldb_private;
+using namespace std;
+
+DWARFDebugMacinfoEntry::DWARFDebugMacinfoEntry() :
+    m_type_code(0),
+    m_line(0),
+    m_op2()
+{
+    m_op2.cstr = NULL;
+}
+
+DWARFDebugMacinfoEntry::~DWARFDebugMacinfoEntry()
+{
+}
+
+const char*
+DWARFDebugMacinfoEntry::GetCString() const
+{
+    switch (m_type_code)
+    {
+    case 0:
+    case DW_MACINFO_start_file:
+    case DW_MACINFO_end_file:
+        return NULL;
+    default:
+        break;
+    }
+    return m_op2.cstr;
+}
+
+
+
+void
+DWARFDebugMacinfoEntry::Dump(Stream *s) const
+{
+    if (m_type_code)
+    {
+        s->PutCString(DW_MACINFO_value_to_name(m_type_code));
+
+        switch (m_type_code)
+        {
+        case DW_MACINFO_define:
+            s->Printf(" line:%u  #define %s\n", (uint32_t)m_line, m_op2.cstr);
+            break;
+
+        case DW_MACINFO_undef:
+            s->Printf(" line:%u  #undef %s\n", (uint32_t)m_line, m_op2.cstr);
+            break;
+
+        default:
+            s->Printf(" line:%u  str: '%s'\n", (uint32_t)m_line, m_op2.cstr);
+            break;
+
+        case DW_MACINFO_start_file:
+            s->Printf(" line:%u  file index: '%u'\n", (uint32_t)m_line, (uint32_t)m_op2.file_idx);
+            break;
+
+        case DW_MACINFO_end_file:
+            break;
+        }
+    }
+    else
+    {
+        s->PutCString(" END\n");
+    }
+}
+
+
+bool
+DWARFDebugMacinfoEntry::Extract(const DataExtractor& mac_info_data, lldb::offset_t* offset_ptr)
+{
+    if (mac_info_data.ValidOffset(*offset_ptr))
+    {
+        m_type_code = mac_info_data.GetU8(offset_ptr);
+
+        switch (m_type_code)
+        {
+
+        case DW_MACINFO_define:
+        case DW_MACINFO_undef:
+            // 2 operands:
+            // Arg 1: operand encodes the line number of the source line on which
+            //      the relevant defining or undefining pre-processor directives
+            //      appeared.
+            m_line  = mac_info_data.GetULEB128(offset_ptr);
+            // Arg 2: define string
+            m_op2.cstr  = mac_info_data.GetCStr(offset_ptr);
+            break;
+
+        case DW_MACINFO_start_file:
+            // 2 operands:
+            // Op 1: line number of the source line on which the inclusion
+            //      pre-processor directive occurred.
+            m_line  = mac_info_data.GetULEB128(offset_ptr);
+            // Op 2: a source file name index to a file number in the statement
+            //      information table for the relevant compilation unit.
+            m_op2.file_idx  = mac_info_data.GetULEB128(offset_ptr);
+            break;
+
+        case 0: // End of list
+        case DW_MACINFO_end_file:
+            // No operands
+            m_line = DW_INVALID_OFFSET;
+            m_op2.cstr = NULL;
+            break;
+        default:
+            // Vendor specific entries always have a ULEB128 and a string
+            m_line      = mac_info_data.GetULEB128(offset_ptr);
+            m_op2.cstr  = mac_info_data.GetCStr(offset_ptr);
+            break;
+        }
+        return true;
+    }
+    else
+        m_type_code = 0;
+
+    return false;
+}
+
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfoEntry.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfoEntry.h
new file mode 100644
index 000000000000..46fd44a22a63
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugMacinfoEntry.h
@@ -0,0 +1,57 @@
+//===-- DWARFDebugMacinfoEntry.h --------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SymbolFileDWARF_DWARFDebugMacinfoEntry_h_
+#define SymbolFileDWARF_DWARFDebugMacinfoEntry_h_
+
+#include "SymbolFileDWARF.h"
+
+class DWARFDebugMacinfoEntry
+{
+public:
+    DWARFDebugMacinfoEntry();
+
+    ~DWARFDebugMacinfoEntry();
+
+    uint8_t
+    TypeCode() const
+    {
+        return m_type_code;
+    }
+
+    uint8_t
+    GetLineNumber() const
+    {
+        return m_line;
+    }
+
+    void
+    Dump(lldb_private::Stream *s) const;
+
+    const char*
+    GetCString() const;
+
+    bool
+    Extract(const lldb_private::DataExtractor& mac_info_data,
+            lldb::offset_t* offset_ptr);
+
+protected:
+
+private:
+    uint8_t m_type_code;
+    dw_uleb128_t m_line;
+    union
+    {
+        dw_uleb128_t file_idx;
+        const char* cstr;
+    } m_op2;
+};
+
+
+#endif  // SymbolFileDWARF_DWARFDebugMacinfoEntry_h_
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp
new file mode 100644
index 000000000000..3e511007a1ec
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp
@@ -0,0 +1,296 @@
+//===-- DWARFDebugPubnames.cpp ----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFDebugPubnames.h"
+
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/Timer.h"
+
+#include "DWARFDebugInfo.h"
+#include "DWARFDIECollection.h"
+#include "DWARFFormValue.h"
+#include "DWARFCompileUnit.h"
+#include "LogChannelDWARF.h"
+#include "SymbolFileDWARF.h"
+
+
+using namespace lldb;
+using namespace lldb_private;
+
+DWARFDebugPubnames::DWARFDebugPubnames() :
+    m_sets()
+{
+}
+
+bool
+DWARFDebugPubnames::Extract(const DataExtractor& data)
+{
+    Timer scoped_timer (__PRETTY_FUNCTION__,
+                        "DWARFDebugPubnames::Extract (byte_size = %" PRIu64 ")",
+                        (uint64_t)data.GetByteSize());
+    Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_PUBNAMES));
+    if (log)
+        log->Printf("DWARFDebugPubnames::Extract (byte_size = %" PRIu64 ")", (uint64_t)data.GetByteSize());
+
+    if (data.ValidOffset(0))
+    {
+        lldb::offset_t offset = 0;
+
+        DWARFDebugPubnamesSet set;
+        while (data.ValidOffset(offset))
+        {
+            if (set.Extract(data, &offset))
+            {
+                m_sets.push_back(set);
+                offset = set.GetOffsetOfNextEntry();
+            }
+            else
+                break;
+        }
+        if (log)
+            Dump (log);
+        return true;
+    }
+    return false;
+}
+
+
+bool
+DWARFDebugPubnames::GeneratePubnames(SymbolFileDWARF* dwarf2Data)
+{
+    Timer scoped_timer (__PRETTY_FUNCTION__,
+                        "DWARFDebugPubnames::GeneratePubnames (data = %p)",
+                        dwarf2Data);
+
+    Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_PUBNAMES));
+    if (log)
+        log->Printf("DWARFDebugPubnames::GeneratePubnames (data = %p)", dwarf2Data);
+
+    m_sets.clear();
+    DWARFDebugInfo* debug_info = dwarf2Data->DebugInfo();
+    if (debug_info)
+    {
+
+        const DataExtractor* debug_str = &dwarf2Data->get_debug_str_data();
+
+        uint32_t cu_idx = 0;
+        const uint32_t num_compile_units = dwarf2Data->GetNumCompileUnits();
+        for (cu_idx = 0; cu_idx < num_compile_units; ++cu_idx)
+        {
+
+            DWARFCompileUnit* cu = debug_info->GetCompileUnitAtIndex(cu_idx);
+
+            const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (cu->GetAddressByteSize());
+
+            bool clear_dies = cu->ExtractDIEsIfNeeded (false) > 1;
+
+            DWARFDIECollection dies;
+            const size_t die_count = cu->AppendDIEsWithTag (DW_TAG_subprogram, dies) +
+                                     cu->AppendDIEsWithTag (DW_TAG_variable, dies);
+
+            dw_offset_t cu_offset = cu->GetOffset();
+            DWARFDebugPubnamesSet pubnames_set(DW_INVALID_OFFSET, cu_offset, cu->GetNextCompileUnitOffset() - cu_offset);
+
+            size_t die_idx;
+            for (die_idx = 0; die_idx < die_count; ++die_idx)
+            {
+                const DWARFDebugInfoEntry *die = dies.GetDIEPtrAtIndex(die_idx);
+                DWARFDebugInfoEntry::Attributes attributes;
+                const char *name = NULL;
+                const char *mangled = NULL;
+                bool add_die = false;
+                const size_t num_attributes = die->GetAttributes(dwarf2Data, cu, fixed_form_sizes, attributes);
+                if (num_attributes > 0)
+                {
+                    uint32_t i;
+
+                    dw_tag_t tag = die->Tag();
+                    
+                    for (i=0; i<num_attributes; ++i)
+                    {
+                        dw_attr_t attr = attributes.AttributeAtIndex(i);
+                        DWARFFormValue form_value;
+                        switch (attr)
+                        {
+                        case DW_AT_name:
+                            if (attributes.ExtractFormValueAtIndex(dwarf2Data, i, form_value))
+                                name = form_value.AsCString(debug_str);
+                            break;
+
+                        case DW_AT_MIPS_linkage_name:
+                        case DW_AT_linkage_name:
+                            if (attributes.ExtractFormValueAtIndex(dwarf2Data, i, form_value))
+                                mangled = form_value.AsCString(debug_str);
+                            break;
+
+                        case DW_AT_low_pc:
+                        case DW_AT_ranges:
+                        case DW_AT_entry_pc:
+                            if (tag == DW_TAG_subprogram)
+                                add_die = true;
+                            break;
+
+                        case DW_AT_location:
+                            if (tag == DW_TAG_variable)
+                            {
+                                const DWARFDebugInfoEntry* parent_die = die->GetParent();
+                                while ( parent_die != NULL )
+                                {
+                                    switch (parent_die->Tag())
+                                    {
+                                    case DW_TAG_subprogram:
+                                    case DW_TAG_lexical_block:
+                                    case DW_TAG_inlined_subroutine:
+                                        // Even if this is a function level static, we don't add it. We could theoretically
+                                        // add these if we wanted to by introspecting into the DW_AT_location and seeing
+                                        // if the location describes a hard coded address, but we don't want the performance
+                                        // penalty of that right now.
+                                        add_die = false;
+//                                      if (attributes.ExtractFormValueAtIndex(dwarf2Data, i, form_value))
+//                                      {
+//                                          // If we have valid block data, then we have location expression bytes
+//                                          // that are fixed (not a location list).
+//                                          const uint8_t *block_data = form_value.BlockData();
+//                                          if (block_data)
+//                                          {
+//                                              uint32_t block_length = form_value.Unsigned();
+//                                              if (block_length == 1 + attributes.CompileUnitAtIndex(i)->GetAddressByteSize())
+//                                              {
+//                                                  if (block_data[0] == DW_OP_addr)
+//                                                      add_die = true;
+//                                              }
+//                                          }
+//                                      }
+                                        parent_die = NULL;  // Terminate the while loop.
+                                        break;
+
+                                    case DW_TAG_compile_unit:
+                                        add_die = true;
+                                        parent_die = NULL;  // Terminate the while loop.
+                                        break;
+
+                                    default:
+                                        parent_die = parent_die->GetParent();   // Keep going in the while loop.
+                                        break;
+                                    }
+                                }
+                            }
+                            break;
+                        }
+                    }
+                }
+
+                if (add_die && (name || mangled))
+                {
+                    pubnames_set.AddDescriptor(die->GetOffset() - cu_offset, mangled ? mangled : name);
+                }
+            }
+
+            if (pubnames_set.NumDescriptors() > 0)
+            {
+                m_sets.push_back(pubnames_set);
+            }
+            
+            // Keep memory down by clearing DIEs if this generate function
+            // caused them to be parsed
+            if (clear_dies)
+                cu->ClearDIEs (true);
+        }
+    }
+    if (m_sets.empty())
+        return false;
+    if (log)
+        Dump (log);
+    return true;
+}
+
+bool
+DWARFDebugPubnames::GeneratePubBaseTypes(SymbolFileDWARF* dwarf2Data)
+{
+    m_sets.clear();
+    DWARFDebugInfo* debug_info = dwarf2Data->DebugInfo();
+    if (debug_info)
+    {
+        uint32_t cu_idx = 0;
+        const uint32_t num_compile_units = dwarf2Data->GetNumCompileUnits();
+        for (cu_idx = 0; cu_idx < num_compile_units; ++cu_idx)
+        {
+            DWARFCompileUnit* cu = debug_info->GetCompileUnitAtIndex(cu_idx);
+            DWARFDIECollection dies;
+            const size_t die_count = cu->AppendDIEsWithTag (DW_TAG_base_type, dies);
+            dw_offset_t cu_offset = cu->GetOffset();
+            DWARFDebugPubnamesSet pubnames_set(DW_INVALID_OFFSET, cu_offset, cu->GetNextCompileUnitOffset() - cu_offset);
+
+            size_t die_idx;
+            for (die_idx = 0; die_idx < die_count; ++die_idx)
+            {
+                const DWARFDebugInfoEntry *die = dies.GetDIEPtrAtIndex(die_idx);
+                const char *name = die->GetAttributeValueAsString(dwarf2Data, cu, DW_AT_name, NULL);
+
+                if (name)
+                {
+                    pubnames_set.AddDescriptor(die->GetOffset() - cu_offset, name);
+                }
+            }
+
+            if (pubnames_set.NumDescriptors() > 0)
+            {
+                m_sets.push_back(pubnames_set);
+            }
+        }
+    }
+    return !m_sets.empty();
+}
+
+void
+DWARFDebugPubnames::Dump(Log *s) const
+{
+    if (m_sets.empty())
+        s->PutCString("< EMPTY >\n");
+    else
+    {
+        const_iterator pos;
+        const_iterator end = m_sets.end();
+
+        for (pos = m_sets.begin(); pos != end; ++pos)
+            (*pos).Dump(s);
+    }
+}
+
+bool
+DWARFDebugPubnames::Find(const char* name, bool ignore_case, std::vector<dw_offset_t>& die_offsets) const
+{
+    const_iterator pos;
+    const_iterator end = m_sets.end();
+
+    die_offsets.clear();
+
+    for (pos = m_sets.begin(); pos != end; ++pos)
+    {
+        (*pos).Find(name, ignore_case, die_offsets);
+    }
+
+    return !die_offsets.empty();
+}
+
+bool
+DWARFDebugPubnames::Find(const RegularExpression& regex, std::vector<dw_offset_t>& die_offsets) const
+{
+    const_iterator pos;
+    const_iterator end = m_sets.end();
+
+    die_offsets.clear();
+
+    for (pos = m_sets.begin(); pos != end; ++pos)
+    {
+        (*pos).Find(regex, die_offsets);
+    }
+
+    return !die_offsets.empty();
+}
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.h
new file mode 100644
index 000000000000..09eb80ab3006
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.h
@@ -0,0 +1,38 @@
+//===-- DWARFDebugPubnames.h ------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SymbolFileDWARF_DWARFDebugPubnames_h_
+#define SymbolFileDWARF_DWARFDebugPubnames_h_
+
+#include "SymbolFileDWARF.h"
+
+#include <list>
+
+#include "DWARFDebugPubnamesSet.h"
+
+class DWARFDebugPubnames
+{
+public:
+            DWARFDebugPubnames();
+    bool    Extract(const lldb_private::DataExtractor& data);
+    bool    GeneratePubnames(SymbolFileDWARF* dwarf2Data);
+    bool    GeneratePubBaseTypes(SymbolFileDWARF* dwarf2Data);
+
+    void    Dump(lldb_private::Log *s) const;
+    bool    Find(const char* name, bool ignore_case, std::vector<dw_offset_t>& die_offset_coll) const;
+    bool    Find(const lldb_private::RegularExpression& regex, std::vector<dw_offset_t>& die_offsets) const;
+protected:
+    typedef std::list<DWARFDebugPubnamesSet>    collection;
+    typedef collection::iterator                iterator;
+    typedef collection::const_iterator          const_iterator;
+
+    collection m_sets;
+};
+
+#endif  // SymbolFileDWARF_DWARFDebugPubnames_h_
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnamesSet.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnamesSet.cpp
new file mode 100644
index 000000000000..2df8d525f03f
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnamesSet.cpp
@@ -0,0 +1,166 @@
+//===-- DWARFDebugPubnamesSet.cpp -------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFDebugPubnamesSet.h"
+
+#include "lldb/Core/RegularExpression.h"
+#include "lldb/Core/Log.h"
+
+#include "SymbolFileDWARF.h"
+
+using namespace lldb_private;
+
+DWARFDebugPubnamesSet::DWARFDebugPubnamesSet() :
+    m_offset(DW_INVALID_OFFSET),
+    m_header(),
+    m_descriptors(),
+    m_name_to_descriptor_index()
+{
+}
+
+DWARFDebugPubnamesSet::DWARFDebugPubnamesSet(dw_offset_t debug_aranges_offset, dw_offset_t cu_die_offset, dw_offset_t cu_die_length) :
+    m_offset(debug_aranges_offset),
+    m_header(),
+    m_descriptors(),
+    m_name_to_descriptor_index()
+{
+    m_header.length = 10;               // set the length to only include the header right for now
+    m_header.version = 2;               // The DWARF version number
+    m_header.die_offset = cu_die_offset;// compile unit .debug_info offset
+    m_header.die_length = cu_die_length;// compile unit .debug_info length
+}
+
+void
+DWARFDebugPubnamesSet::AddDescriptor(dw_offset_t cu_rel_offset, const char* name)
+{
+    if (name && name[0])
+    {
+        // Adjust our header length
+        m_header.length += strlen(name) + 1 + sizeof(dw_offset_t);
+        Descriptor pubnameDesc(cu_rel_offset, name);
+        m_descriptors.push_back(pubnameDesc);
+    }
+}
+
+void
+DWARFDebugPubnamesSet::Clear()
+{
+    m_offset = DW_INVALID_OFFSET;
+    m_header.length = 10;
+    m_header.version = 2;
+    m_header.die_offset = DW_INVALID_OFFSET;
+    m_header.die_length = 0;
+    m_descriptors.clear();
+}
+
+
+//----------------------------------------------------------------------
+// InitNameIndexes
+//----------------------------------------------------------------------
+void
+DWARFDebugPubnamesSet::InitNameIndexes() const
+{
+    // Create the name index vector to be able to quickly search by name
+    const size_t count = m_descriptors.size();
+    for (uint32_t idx = 0; idx < count; ++idx)
+    {
+        const char* name = m_descriptors[idx].name.c_str();
+        if (name && name[0])
+            m_name_to_descriptor_index.insert(cstr_to_index_mmap::value_type(name, idx));
+    }
+}
+
+
+bool
+DWARFDebugPubnamesSet::Extract(const DataExtractor& data, lldb::offset_t *offset_ptr)
+{
+    if (data.ValidOffset(*offset_ptr))
+    {
+        m_descriptors.clear();
+        m_offset = *offset_ptr;
+        m_header.length     = data.GetU32(offset_ptr);
+        m_header.version    = data.GetU16(offset_ptr);
+        m_header.die_offset = data.GetU32(offset_ptr);
+        m_header.die_length = data.GetU32(offset_ptr);
+
+        Descriptor pubnameDesc;
+        while (data.ValidOffset(*offset_ptr))
+        {
+            pubnameDesc.offset  = data.GetU32(offset_ptr);
+
+            if (pubnameDesc.offset)
+            {
+                const char* name = data.GetCStr(offset_ptr);
+                if (name && name[0])
+                {
+                    pubnameDesc.name = name;
+                    m_descriptors.push_back(pubnameDesc);
+                }
+            }
+            else
+                break;  // We are done if we get a zero 4 byte offset
+        }
+
+        return !m_descriptors.empty();
+    }
+    return false;
+}
+
+dw_offset_t
+DWARFDebugPubnamesSet::GetOffsetOfNextEntry() const
+{
+    return m_offset + m_header.length + 4;
+}
+
+void
+DWARFDebugPubnamesSet::Dump(Log *log) const
+{
+    log->Printf("Pubnames Header: length = 0x%8.8x, version = 0x%4.4x, die_offset = 0x%8.8x, die_length = 0x%8.8x",
+        m_header.length,
+        m_header.version,
+        m_header.die_offset,
+        m_header.die_length);
+
+    bool verbose = log->GetVerbose();
+
+    DescriptorConstIter pos;
+    DescriptorConstIter end = m_descriptors.end();
+    for (pos = m_descriptors.begin(); pos != end; ++pos)
+    {
+        if (verbose)
+            log->Printf("0x%8.8x + 0x%8.8x = 0x%8.8x: %s", pos->offset, m_header.die_offset, pos->offset + m_header.die_offset, pos->name.c_str());
+        else
+            log->Printf("0x%8.8x: %s", pos->offset + m_header.die_offset, pos->name.c_str());
+    }
+}
+
+
+void
+DWARFDebugPubnamesSet::Find(const char* name, bool ignore_case, std::vector<dw_offset_t>& die_offset_coll) const
+{
+    if (!m_descriptors.empty() && m_name_to_descriptor_index.empty())
+        InitNameIndexes();
+
+    std::pair<cstr_to_index_mmap::const_iterator, cstr_to_index_mmap::const_iterator> range(m_name_to_descriptor_index.equal_range(name));
+    for (cstr_to_index_mmap::const_iterator pos = range.first; pos != range.second; ++pos)
+        die_offset_coll.push_back(m_header.die_offset + m_descriptors[(*pos).second].offset);
+}
+
+void
+DWARFDebugPubnamesSet::Find(const RegularExpression& regex, std::vector<dw_offset_t>& die_offset_coll) const
+{
+    DescriptorConstIter pos;
+    DescriptorConstIter end = m_descriptors.end();
+    for (pos = m_descriptors.begin(); pos != end; ++pos)
+    {
+        if ( regex.Execute(pos->name.c_str()) )
+            die_offset_coll.push_back(m_header.die_offset + pos->offset);
+    }
+}
+
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnamesSet.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnamesSet.h
new file mode 100644
index 000000000000..941c83e58a44
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnamesSet.h
@@ -0,0 +1,99 @@
+//===-- DWARFDebugPubnamesSet.h ---------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SymbolFileDWARF_DWARFDebugPubnamesSet_h_
+#define SymbolFileDWARF_DWARFDebugPubnamesSet_h_
+
+#include "SymbolFileDWARF.h"
+#include <string>
+#include <vector>
+#if __cplusplus >= 201103L
+#include <unordered_map>
+#else
+#include <ext/hash_map>
+#endif
+
+class DWARFDebugPubnamesSet
+{
+public:
+    struct Header
+    {
+        uint32_t    length;     // length of the set of entries for this compilation unit, not including the length field itself
+        uint16_t    version;    // The DWARF version number
+        uint32_t    die_offset; // compile unit .debug_info offset
+        uint32_t    die_length; // compile unit .debug_info length
+        Header() :
+            length(10),
+            version(2),
+            die_offset(DW_INVALID_OFFSET),
+            die_length(0)
+        {
+        }
+    };
+
+    struct Descriptor
+    {
+        Descriptor() :
+            offset(),
+            name()
+        {
+        }
+
+        Descriptor(dw_offset_t the_offset, const char *the_name) :
+            offset(the_offset),
+            name(the_name ? the_name : "")
+        {
+        }
+
+        dw_offset_t offset;
+        std::string name;
+    };
+
+                DWARFDebugPubnamesSet();
+                DWARFDebugPubnamesSet(dw_offset_t debug_aranges_offset, dw_offset_t cu_die_offset, dw_offset_t die_length);
+    dw_offset_t GetOffset() const { return m_offset; }
+    void        SetOffset(dw_offset_t offset) { m_offset = offset; }
+    DWARFDebugPubnamesSet::Header& GetHeader() { return m_header; }
+    const DWARFDebugPubnamesSet::Header& GetHeader() const { return m_header; }
+    const DWARFDebugPubnamesSet::Descriptor* GetDescriptor(uint32_t i) const
+        {
+            if (i < m_descriptors.size())
+                return &m_descriptors[i];
+            return NULL;
+        }
+    uint32_t    NumDescriptors() const { return m_descriptors.size(); }
+    void        AddDescriptor(dw_offset_t cu_rel_offset, const char* name);
+    void        Clear();
+    bool        Extract(const lldb_private::DataExtractor& debug_pubnames_data, lldb::offset_t *offset_ptr);
+    void        Dump(lldb_private::Log *s) const;
+    void        InitNameIndexes() const;
+    void        Find(const char* name, bool ignore_case, std::vector<dw_offset_t>& die_offset_coll) const;
+    void        Find(const lldb_private::RegularExpression& regex, std::vector<dw_offset_t>& die_offsets) const;
+    dw_offset_t GetOffsetOfNextEntry() const;
+
+
+
+protected:
+    typedef std::vector<Descriptor>         DescriptorColl;
+    typedef DescriptorColl::iterator        DescriptorIter;
+    typedef DescriptorColl::const_iterator  DescriptorConstIter;
+
+
+    dw_offset_t     m_offset;
+    Header          m_header;
+#if __cplusplus >= 201103L
+    typedef std::unordered_multimap<const char*, uint32_t, std::hash<const char*>, CStringEqualBinaryPredicate> cstr_to_index_mmap;
+#else
+    typedef __gnu_cxx::hash_multimap<const char*, uint32_t, __gnu_cxx::hash<const char*>, CStringEqualBinaryPredicate> cstr_to_index_mmap;
+#endif
+    DescriptorColl  m_descriptors;
+    mutable cstr_to_index_mmap m_name_to_descriptor_index;
+};
+
+#endif  // SymbolFileDWARF_DWARFDebugPubnamesSet_h_
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp
new file mode 100644
index 000000000000..461b17fc3aba
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.cpp
@@ -0,0 +1,192 @@
+//===-- DWARFDebugRanges.cpp ------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFDebugRanges.h"
+#include "SymbolFileDWARF.h"
+#include "lldb/Core/Stream.h"
+#include <assert.h>
+
+using namespace lldb_private;
+using namespace std;
+
+DWARFDebugRanges::DWARFDebugRanges() :
+    m_range_map()
+{
+}
+
+DWARFDebugRanges::~DWARFDebugRanges()
+{
+}
+
+void
+DWARFDebugRanges::Extract(SymbolFileDWARF* dwarf2Data)
+{
+    RangeList range_list;
+    lldb::offset_t offset = 0;
+    dw_offset_t debug_ranges_offset = offset;
+    while (Extract(dwarf2Data, &offset, range_list))
+    {
+        m_range_map[debug_ranges_offset] = range_list;
+        debug_ranges_offset = offset;
+    }
+}
+
+//void
+//DWARFDebugRanges::RangeList::AddOffset(dw_addr_t offset)
+//{
+//    if (!ranges.empty())
+//    {
+//        Range::iterator pos = ranges.begin();
+//        Range::iterator end_pos = ranges.end();
+//        for (pos = ranges.begin(); pos != end_pos; ++pos)
+//        {
+//            // assert for unsigned overflows
+//            assert (~pos->begin_offset >= offset);
+//            assert (~pos->end_offset >= offset);
+//            pos->begin_offset += offset;
+//            pos->end_offset += offset;
+//        }
+//    }
+//}
+//
+//void
+//DWARFDebugRanges::RangeList::SubtractOffset(dw_addr_t offset)
+//{
+//    if (!ranges.empty())
+//    {
+//        Range::iterator pos = ranges.begin();
+//        Range::iterator end_pos = ranges.end();
+//        for (pos = ranges.begin(); pos != end_pos; ++pos)
+//        {
+//            assert (pos->begin_offset >= offset);
+//            assert (pos->end_offset >= offset);
+//            pos->begin_offset -= offset;
+//            pos->end_offset -= offset;
+//        }
+//    }
+//}
+//
+//
+//const DWARFDebugRanges::Range*
+//DWARFDebugRanges::RangeList::RangeAtIndex(size_t i) const
+//{
+//    if (i < ranges.size())
+//        return &ranges[i];
+//    return NULL;
+//}
+
+bool
+DWARFDebugRanges::Extract(SymbolFileDWARF* dwarf2Data, lldb::offset_t *offset_ptr, RangeList &range_list)
+{
+    range_list.Clear();
+
+    lldb::offset_t range_offset = *offset_ptr;
+    const DataExtractor& debug_ranges_data = dwarf2Data->get_debug_ranges_data();
+    uint32_t addr_size = debug_ranges_data.GetAddressByteSize();
+
+    while (debug_ranges_data.ValidOffsetForDataOfSize(*offset_ptr, 2 * addr_size))
+    {
+        dw_addr_t begin = debug_ranges_data.GetMaxU64(offset_ptr, addr_size);
+        dw_addr_t end   = debug_ranges_data.GetMaxU64(offset_ptr, addr_size);
+        if (!begin && !end)
+        {
+            // End of range list
+            break;
+        }
+        // Extend 4 byte addresses that consists of 32 bits of 1's to be 64 bits
+        // of ones
+        switch (addr_size)
+        {
+        case 2:
+            if (begin == 0xFFFFull)
+                begin = LLDB_INVALID_ADDRESS;
+            break;
+
+        case 4:
+            if (begin == 0xFFFFFFFFull)
+                begin = LLDB_INVALID_ADDRESS;
+            break;
+
+        case 8:
+            break;
+
+        default:
+            assert(!"DWARFDebugRanges::RangeList::Extract() unsupported address size.");
+            break;
+        }
+
+        // Filter out empty ranges
+        if (begin < end)
+            range_list.Append(Range(begin, end - begin));
+    }
+
+    // Make sure we consumed at least something
+    return range_offset != *offset_ptr;
+}
+
+
+void
+DWARFDebugRanges::Dump(Stream &s, const DataExtractor& debug_ranges_data, lldb::offset_t *offset_ptr, dw_addr_t cu_base_addr)
+{
+    uint32_t addr_size = s.GetAddressByteSize();
+    bool verbose = s.GetVerbose();
+
+    dw_addr_t base_addr = cu_base_addr;
+    while (debug_ranges_data.ValidOffsetForDataOfSize(*offset_ptr, 2 * addr_size))
+    {
+        dw_addr_t begin = debug_ranges_data.GetMaxU64(offset_ptr, addr_size);
+        dw_addr_t end   = debug_ranges_data.GetMaxU64(offset_ptr, addr_size);
+        // Extend 4 byte addresses that consits of 32 bits of 1's to be 64 bits
+        // of ones
+        if (begin == 0xFFFFFFFFull && addr_size == 4)
+            begin = LLDB_INVALID_ADDRESS;
+
+        s.Indent();
+        if (verbose)
+        {
+            s.AddressRange(begin, end, sizeof (dw_addr_t), " offsets = ");
+        }
+
+
+        if (begin == 0 && end == 0)
+        {
+            s.PutCString(" End");
+            break;
+        }
+        else if (begin == LLDB_INVALID_ADDRESS)
+        {
+            // A base address selection entry
+            base_addr = end;
+            s.Address(base_addr, sizeof (dw_addr_t), " Base address = ");
+        }
+        else
+        {
+            // Convert from offset to an address
+            dw_addr_t begin_addr = begin + base_addr;
+            dw_addr_t end_addr = end + base_addr;
+
+            s.AddressRange(begin_addr, end_addr, sizeof (dw_addr_t), verbose ? " ==> addrs = " : NULL);
+        }
+    }
+}
+
+bool
+DWARFDebugRanges::FindRanges(dw_offset_t debug_ranges_offset, RangeList& range_list) const
+{
+    range_map_const_iterator pos = m_range_map.find(debug_ranges_offset);
+    if (pos != m_range_map.end())
+    {
+        range_list = pos->second;
+        return true;
+    }
+    return false;
+}
+
+
+
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h b/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h
new file mode 100644
index 000000000000..40899abe9c25
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDebugRanges.h
@@ -0,0 +1,46 @@
+//===-- DWARFDebugRanges.h --------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SymbolFileDWARF_DWARFDebugRanges_h_
+#define SymbolFileDWARF_DWARFDebugRanges_h_
+
+#include "SymbolFileDWARF.h"
+
+#include <map>
+#include <vector>
+
+#include "lldb/Core/RangeMap.h"
+
+class DWARFDebugRanges
+{
+public:
+    typedef lldb_private::RangeArray<dw_addr_t, dw_addr_t, 2> RangeList;
+    typedef RangeList::Entry Range;
+
+    DWARFDebugRanges();
+    ~DWARFDebugRanges();
+    void Extract(SymbolFileDWARF* dwarf2Data);
+    static void Dump(lldb_private::Stream &s, const lldb_private::DataExtractor& debug_ranges_data, lldb::offset_t *offset_ptr, dw_addr_t cu_base_addr);
+    bool FindRanges(dw_offset_t debug_ranges_offset, DWARFDebugRanges::RangeList& range_list) const;
+
+protected:
+
+    bool
+    Extract (SymbolFileDWARF* dwarf2Data, 
+             lldb::offset_t *offset_ptr, 
+             RangeList &range_list);
+
+    typedef std::map<dw_offset_t, RangeList>    range_map;
+    typedef range_map::iterator                 range_map_iterator;
+    typedef range_map::const_iterator           range_map_const_iterator;
+    range_map m_range_map;
+};
+
+
+#endif  // SymbolFileDWARF_DWARFDebugRanges_h_
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.cpp
new file mode 100644
index 000000000000..abf69190c93c
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.cpp
@@ -0,0 +1,104 @@
+//===-- DWARFDeclContext.cpp ------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFDeclContext.h"
+
+const char *
+DWARFDeclContext::GetQualifiedName () const
+{
+    if (m_qualified_name.empty())
+    {
+        // The declaration context array for a class named "foo" in namespace
+        // "a::b::c" will be something like:
+        //  [0] DW_TAG_class_type "foo"
+        //  [1] DW_TAG_namespace "c"
+        //  [2] DW_TAG_namespace "b"
+        //  [3] DW_TAG_namespace "a"
+        if (!m_entries.empty())
+        {
+            if (m_entries.size() == 1)
+            {
+                if (m_entries[0].name)
+                {
+                    m_qualified_name.append("::");
+                    m_qualified_name.append(m_entries[0].name);
+                }
+            }
+            else
+            {
+                collection::const_reverse_iterator pos;
+                collection::const_reverse_iterator begin = m_entries.rbegin();
+                collection::const_reverse_iterator end = m_entries.rend();
+                for (pos = begin; pos != end; ++pos)
+                {
+                    if (pos != begin)
+                        m_qualified_name.append("::");
+                    if (pos->name == NULL)
+                    {
+                        if (pos->tag == DW_TAG_namespace)
+                            m_qualified_name.append ("(anonymous namespace)");
+                        else if (pos->tag == DW_TAG_class_type)
+                            m_qualified_name.append ("(anonymous class)");
+                        else if (pos->tag == DW_TAG_structure_type)
+                            m_qualified_name.append ("(anonymous struct)");
+                        else if (pos->tag == DW_TAG_union_type)
+                            m_qualified_name.append ("(anonymous union)");
+                        else
+                            m_qualified_name.append ("(anonymous)");
+                    }
+                    else
+                        m_qualified_name.append(pos->name);
+                }
+            }
+        }
+    }
+    if (m_qualified_name.empty())
+        return NULL;
+    return m_qualified_name.c_str();
+}
+
+
+bool
+DWARFDeclContext::operator==(const DWARFDeclContext& rhs) const
+{
+    if (m_entries.size() != rhs.m_entries.size())
+        return false;
+    
+    collection::const_iterator pos;
+    collection::const_iterator begin = m_entries.begin();
+    collection::const_iterator end = m_entries.end();
+
+    collection::const_iterator rhs_pos;
+    collection::const_iterator rhs_begin = rhs.m_entries.begin();
+    // The two entry arrays have the same size
+    
+    // First compare the tags before we do expensize name compares
+    for (pos = begin, rhs_pos = rhs_begin; pos != end; ++pos, ++rhs_pos)
+    {
+        if (pos->tag != rhs_pos->tag)
+        {
+            // Check for DW_TAG_structure_type and DW_TAG_class_type as they are often
+            // used interchangeably in GCC
+            if (pos->tag == DW_TAG_structure_type && rhs_pos->tag == DW_TAG_class_type)
+                continue;
+            if (pos->tag == DW_TAG_class_type && rhs_pos->tag == DW_TAG_structure_type)
+                continue;
+            return false;
+        }
+    }
+    // The tags all match, now compare the names
+    for (pos = begin, rhs_pos = rhs_begin; pos != end; ++pos, ++rhs_pos)
+    {
+        if (!pos->NameMatches (*rhs_pos))
+            return false;
+    }
+    // All tags and names match
+    return true;
+}
+
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h b/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h
new file mode 100644
index 000000000000..accd3446317a
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.h
@@ -0,0 +1,109 @@
+//===-- DWARFDeclContext.h --------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SymbolFileDWARF_DWARFDeclContext_h_
+#define SymbolFileDWARF_DWARFDeclContext_h_
+
+// C Includes
+// C++ Includes
+#include <string>
+#include <vector>
+// Other libraries and framework includes
+#include "lldb/Core/ConstString.h"
+// Project includes
+#include "DWARFDefines.h"
+
+//----------------------------------------------------------------------
+// DWARFDeclContext
+//
+// A class that represents a declaration context all the way down to a
+// DIE. This is useful when trying to find a DIE in one DWARF to a DIE
+// in another DWARF file.
+//----------------------------------------------------------------------
+
+class DWARFDeclContext
+{
+public:
+    struct Entry
+    {
+        Entry () :
+            tag(0),
+            name(NULL)
+        {
+        }
+        Entry (dw_tag_t t, const char *n) :
+            tag(t),
+            name(n)
+        {
+        }
+
+        bool
+        NameMatches (const Entry& rhs) const
+        {
+            if (name == rhs.name)
+                return true;
+            else if (name && rhs.name)
+                return strcmp(name, rhs.name) == 0;
+            return false;
+        }
+
+        // Test operator
+        operator bool() const
+        {
+            return tag != 0;
+        }
+
+        dw_tag_t tag;
+        const char *name;
+    };
+
+    DWARFDeclContext () :
+        m_entries()
+    {
+    }
+
+    void
+    AppendDeclContext (dw_tag_t tag, const char *name)
+    {
+        m_entries.push_back(Entry(tag, name));
+    }
+
+    bool
+    operator ==(const DWARFDeclContext& rhs) const;
+
+    uint32_t
+    GetSize() const
+    {
+        return m_entries.size();
+    }
+
+    Entry &
+    operator[] (uint32_t idx)
+    {
+        // "idx" must be valid
+        return m_entries[idx];
+    }
+
+    const Entry &
+    operator[] (uint32_t idx) const
+    {
+        // "idx" must be valid
+        return m_entries[idx];
+    }
+
+    const char *
+    GetQualifiedName () const;
+
+protected:
+    typedef std::vector<Entry> collection;
+    collection m_entries;
+    mutable std::string m_qualified_name;
+};
+
+#endif  // SymbolFileDWARF_DWARFDeclContext_h_
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDefines.cpp b/source/Plugins/SymbolFile/DWARF/DWARFDefines.cpp
new file mode 100644
index 000000000000..fe4093bc130e
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDefines.cpp
@@ -0,0 +1,497 @@
+//===-- DWARFDefines.c ------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFDefines.h"
+#include <cstdio>
+#include <cstring>
+#include <string>
+#include "lldb/Core/ConstString.h"
+
+namespace lldb_private {
+
+const char *
+DW_TAG_value_to_name (uint32_t val)
+{
+  static char invalid[100];
+
+  if (val == 0)
+      return "NULL";
+
+  const char *llvmstr = llvm::dwarf::TagString (val);
+  if (llvmstr == NULL)
+  {
+      snprintf (invalid, sizeof (invalid), "Unknown DW_TAG constant: 0x%x", val);
+      return invalid;
+  }
+  return llvmstr;
+}   
+
+const char *
+DW_CHILDREN_value_to_name (uint8_t val)
+{
+  static char invalid[100];
+  const char *llvmstr = llvm::dwarf::ChildrenString (val);
+  if (llvmstr == NULL)
+  {
+       snprintf (invalid, sizeof (invalid), "Unknown DW_CHILDREN constant: 0x%x", val);
+       return invalid;
+  }
+  return llvmstr;
+}
+
+const char *
+DW_AT_value_to_name (uint32_t val)
+{
+  static char invalid[100];
+  const char *llvmstr = llvm::dwarf::AttributeString (val);
+  if (llvmstr == NULL)
+  {
+      snprintf (invalid, sizeof (invalid), "Unknown DW_AT constant: 0x%x", val);
+      return invalid;
+  }
+  return llvmstr;
+}
+
+const char *
+DW_FORM_value_to_name (uint32_t val)
+{
+  static char invalid[100];
+  const char *llvmstr = llvm::dwarf::FormEncodingString (val);
+  if (llvmstr == NULL)
+  {
+      snprintf (invalid, sizeof (invalid), "Unknown DW_FORM constant: 0x%x", val);
+      return invalid;
+  }
+  return llvmstr;
+}
+
+const char *
+DW_OP_value_to_name (uint32_t val)
+{
+  static char invalid[100];
+  const char *llvmstr = llvm::dwarf::OperationEncodingString (val);
+  if (llvmstr == NULL)
+  {
+      snprintf (invalid, sizeof (invalid), "Unknown DW_OP constant: 0x%x", val);
+      return invalid;
+  }
+  return llvmstr;
+}
+
+DRC_class
+DW_OP_value_to_class (uint32_t val)
+{
+  switch (val) {
+    case 0x03: return DRC_ONEOPERAND;
+    case 0x06: return DRC_ZEROOPERANDS;
+    case 0x08: return DRC_ONEOPERAND;
+    case 0x09: return DRC_ONEOPERAND;
+    case 0x0a: return DRC_ONEOPERAND;
+    case 0x0b: return DRC_ONEOPERAND;
+    case 0x0c: return DRC_ONEOPERAND;
+    case 0x0d: return DRC_ONEOPERAND;
+    case 0x0e: return DRC_ONEOPERAND;
+    case 0x0f: return DRC_ONEOPERAND;
+    case 0x10: return DRC_ONEOPERAND;
+    case 0x11: return DRC_ONEOPERAND;
+    case 0x12: return DRC_ZEROOPERANDS;
+    case 0x13: return DRC_ZEROOPERANDS;
+    case 0x14: return DRC_ZEROOPERANDS;
+    case 0x15: return DRC_ONEOPERAND;
+    case 0x16: return DRC_ZEROOPERANDS;
+    case 0x17: return DRC_ZEROOPERANDS;
+    case 0x18: return DRC_ZEROOPERANDS;
+    case 0x19: return DRC_ZEROOPERANDS;
+    case 0x1a: return DRC_ZEROOPERANDS;
+    case 0x1b: return DRC_ZEROOPERANDS;
+    case 0x1c: return DRC_ZEROOPERANDS;
+    case 0x1d: return DRC_ZEROOPERANDS;
+    case 0x1e: return DRC_ZEROOPERANDS;
+    case 0x1f: return DRC_ZEROOPERANDS;
+    case 0x20: return DRC_ZEROOPERANDS;
+    case 0x21: return DRC_ZEROOPERANDS;
+    case 0x22: return DRC_ZEROOPERANDS;
+    case 0x23: return DRC_ONEOPERAND;
+    case 0x24: return DRC_ZEROOPERANDS;
+    case 0x25: return DRC_ZEROOPERANDS;
+    case 0x26: return DRC_ZEROOPERANDS;
+    case 0x27: return DRC_ZEROOPERANDS;
+    case 0x2f: return DRC_ONEOPERAND;
+    case 0x28: return DRC_ONEOPERAND;
+    case 0x29: return DRC_ZEROOPERANDS;
+    case 0x2a: return DRC_ZEROOPERANDS;
+    case 0x2b: return DRC_ZEROOPERANDS;
+    case 0x2c: return DRC_ZEROOPERANDS;
+    case 0x2d: return DRC_ZEROOPERANDS;
+    case 0x2e: return DRC_ZEROOPERANDS;
+    case 0x30: return DRC_ZEROOPERANDS;
+    case 0x31: return DRC_ZEROOPERANDS;
+    case 0x32: return DRC_ZEROOPERANDS;
+    case 0x33: return DRC_ZEROOPERANDS;
+    case 0x34: return DRC_ZEROOPERANDS;
+    case 0x35: return DRC_ZEROOPERANDS;
+    case 0x36: return DRC_ZEROOPERANDS;
+    case 0x37: return DRC_ZEROOPERANDS;
+    case 0x38: return DRC_ZEROOPERANDS;
+    case 0x39: return DRC_ZEROOPERANDS;
+    case 0x3a: return DRC_ZEROOPERANDS;
+    case 0x3b: return DRC_ZEROOPERANDS;
+    case 0x3c: return DRC_ZEROOPERANDS;
+    case 0x3d: return DRC_ZEROOPERANDS;
+    case 0x3e: return DRC_ZEROOPERANDS;
+    case 0x3f: return DRC_ZEROOPERANDS;
+    case 0x40: return DRC_ZEROOPERANDS;
+    case 0x41: return DRC_ZEROOPERANDS;
+    case 0x42: return DRC_ZEROOPERANDS;
+    case 0x43: return DRC_ZEROOPERANDS;
+    case 0x44: return DRC_ZEROOPERANDS;
+    case 0x45: return DRC_ZEROOPERANDS;
+    case 0x46: return DRC_ZEROOPERANDS;
+    case 0x47: return DRC_ZEROOPERANDS;
+    case 0x48: return DRC_ZEROOPERANDS;
+    case 0x49: return DRC_ZEROOPERANDS;
+    case 0x4a: return DRC_ZEROOPERANDS;
+    case 0x4b: return DRC_ZEROOPERANDS;
+    case 0x4c: return DRC_ZEROOPERANDS;
+    case 0x4d: return DRC_ZEROOPERANDS;
+    case 0x4e: return DRC_ZEROOPERANDS;
+    case 0x4f: return DRC_ZEROOPERANDS;
+    case 0x50: return DRC_ZEROOPERANDS;
+    case 0x51: return DRC_ZEROOPERANDS;
+    case 0x52: return DRC_ZEROOPERANDS;
+    case 0x53: return DRC_ZEROOPERANDS;
+    case 0x54: return DRC_ZEROOPERANDS;
+    case 0x55: return DRC_ZEROOPERANDS;
+    case 0x56: return DRC_ZEROOPERANDS;
+    case 0x57: return DRC_ZEROOPERANDS;
+    case 0x58: return DRC_ZEROOPERANDS;
+    case 0x59: return DRC_ZEROOPERANDS;
+    case 0x5a: return DRC_ZEROOPERANDS;
+    case 0x5b: return DRC_ZEROOPERANDS;
+    case 0x5c: return DRC_ZEROOPERANDS;
+    case 0x5d: return DRC_ZEROOPERANDS;
+    case 0x5e: return DRC_ZEROOPERANDS;
+    case 0x5f: return DRC_ZEROOPERANDS;
+    case 0x60: return DRC_ZEROOPERANDS;
+    case 0x61: return DRC_ZEROOPERANDS;
+    case 0x62: return DRC_ZEROOPERANDS;
+    case 0x63: return DRC_ZEROOPERANDS;
+    case 0x64: return DRC_ZEROOPERANDS;
+    case 0x65: return DRC_ZEROOPERANDS;
+    case 0x66: return DRC_ZEROOPERANDS;
+    case 0x67: return DRC_ZEROOPERANDS;
+    case 0x68: return DRC_ZEROOPERANDS;
+    case 0x69: return DRC_ZEROOPERANDS;
+    case 0x6a: return DRC_ZEROOPERANDS;
+    case 0x6b: return DRC_ZEROOPERANDS;
+    case 0x6c: return DRC_ZEROOPERANDS;
+    case 0x6d: return DRC_ZEROOPERANDS;
+    case 0x6e: return DRC_ZEROOPERANDS;
+    case 0x6f: return DRC_ZEROOPERANDS;
+    case 0x70: return DRC_ONEOPERAND;
+    case 0x71: return DRC_ONEOPERAND;
+    case 0x72: return DRC_ONEOPERAND;
+    case 0x73: return DRC_ONEOPERAND;
+    case 0x74: return DRC_ONEOPERAND;
+    case 0x75: return DRC_ONEOPERAND;
+    case 0x76: return DRC_ONEOPERAND;
+    case 0x77: return DRC_ONEOPERAND;
+    case 0x78: return DRC_ONEOPERAND;
+    case 0x79: return DRC_ONEOPERAND;
+    case 0x7a: return DRC_ONEOPERAND;
+    case 0x7b: return DRC_ONEOPERAND;
+    case 0x7c: return DRC_ONEOPERAND;
+    case 0x7d: return DRC_ONEOPERAND;
+    case 0x7e: return DRC_ONEOPERAND;
+    case 0x7f: return DRC_ONEOPERAND;
+    case 0x80: return DRC_ONEOPERAND;
+    case 0x81: return DRC_ONEOPERAND;
+    case 0x82: return DRC_ONEOPERAND;
+    case 0x83: return DRC_ONEOPERAND;
+    case 0x84: return DRC_ONEOPERAND;
+    case 0x85: return DRC_ONEOPERAND;
+    case 0x86: return DRC_ONEOPERAND;
+    case 0x87: return DRC_ONEOPERAND;
+    case 0x88: return DRC_ONEOPERAND;
+    case 0x89: return DRC_ONEOPERAND;
+    case 0x8a: return DRC_ONEOPERAND;
+    case 0x8b: return DRC_ONEOPERAND;
+    case 0x8c: return DRC_ONEOPERAND;
+    case 0x8d: return DRC_ONEOPERAND;
+    case 0x8e: return DRC_ONEOPERAND;
+    case 0x8f: return DRC_ONEOPERAND;
+    case 0x90: return DRC_ONEOPERAND;
+    case 0x91: return DRC_ONEOPERAND;
+    case 0x92: return DRC_TWOOPERANDS;
+    case 0x93: return DRC_ONEOPERAND;
+    case 0x94: return DRC_ONEOPERAND;
+    case 0x95: return DRC_ONEOPERAND;
+    case 0x96: return DRC_ZEROOPERANDS;
+    case 0x97: return DRC_DWARFv3 | DRC_ZEROOPERANDS;
+    case 0x98: return DRC_DWARFv3 | DRC_ONEOPERAND;
+    case 0x99: return DRC_DWARFv3 | DRC_ONEOPERAND;
+    case 0x9a: return DRC_DWARFv3 | DRC_ONEOPERAND;
+    case 0xf0: return DRC_ZEROOPERANDS; /* DW_OP_APPLE_uninit */
+    case 0xe0: return 0;
+    case 0xff: return 0;
+    default: return 0;
+  }
+}
+
+const char *
+DW_ATE_value_to_name (uint32_t val)
+{
+  static char invalid[100];
+  const char *llvmstr = llvm::dwarf::AttributeEncodingString (val);
+  if (llvmstr == NULL)
+  {
+      snprintf (invalid, sizeof (invalid), "Unknown DW_ATE constant: 0x%x", val);
+      return invalid;
+  }
+  return llvmstr;
+}
+
+const char *
+DW_ACCESS_value_to_name (uint32_t val)
+{
+  static char invalid[100];
+
+  const char *llvmstr = llvm::dwarf::AccessibilityString (val);
+  if (llvmstr == NULL)
+  {
+      snprintf (invalid, sizeof (invalid), "Unknown DW_ACCESS constant: 0x%x", val);
+      return invalid;
+  }
+  return llvmstr;
+}
+
+const char *
+DW_VIS_value_to_name (uint32_t val)
+{
+  static char invalid[100];
+  const char *llvmstr = llvm::dwarf::VisibilityString (val);
+  if (llvmstr == NULL)
+  {
+      snprintf (invalid, sizeof (invalid), "Unknown DW_VIS constant: 0x%x", val);
+      return invalid;
+  }
+  return llvmstr;
+}
+
+const char *
+DW_VIRTUALITY_value_to_name (uint32_t val)
+{
+  static char invalid[100];
+  const char *llvmstr = llvm::dwarf::VirtualityString (val);
+  if (llvmstr == NULL)
+  {
+      snprintf (invalid, sizeof (invalid), "Unknown DW_VIRTUALITY constant: 0x%x", val);
+      return invalid;
+  }
+  return llvmstr;
+}
+
+const char *
+DW_LANG_value_to_name (uint32_t val)
+{
+  static char invalid[100];
+  const char *llvmstr = llvm::dwarf::LanguageString (val);
+  if (llvmstr == NULL)
+  {
+      snprintf (invalid, sizeof (invalid), "Unknown DW_LANG constant: 0x%x", val);
+      return invalid;
+  }
+  return llvmstr;
+}
+
+const char *
+DW_ID_value_to_name (uint32_t val)
+{
+  static char invalid[100];
+  const char *llvmstr = llvm::dwarf::CaseString (val);
+  if (llvmstr == NULL)
+  {
+      snprintf (invalid, sizeof (invalid), "Unknown DW_ID constant: 0x%x", val);
+      return invalid;
+  }
+  return llvmstr;
+}
+
+const char *
+DW_CC_value_to_name (uint32_t val)
+{
+  static char invalid[100];
+  const char *llvmstr = llvm::dwarf::ConventionString (val);
+  if (llvmstr == NULL)
+  {
+      snprintf (invalid, sizeof (invalid), "Unknown DW_CC constant: 0x%x", val);
+      return invalid;
+  }
+  return llvmstr;
+}
+
+const char *
+DW_INL_value_to_name (uint32_t val)
+{
+  static char invalid[100];
+  const char *llvmstr = llvm::dwarf::InlineCodeString (val);
+  if (llvmstr == NULL)
+  {
+      snprintf (invalid, sizeof (invalid), "Unknown DW_INL constant: 0x%x", val);
+      return invalid;
+  }
+  return llvmstr;
+}
+
+const char *
+DW_ORD_value_to_name (uint32_t val)
+{
+  static char invalid[100];
+  const char *llvmstr = llvm::dwarf::ArrayOrderString (val);
+  if (llvmstr == NULL)
+  {
+      snprintf (invalid, sizeof (invalid), "Unknown DW_ORD constant: 0x%x", val);
+      return invalid;
+  }
+  return llvmstr;
+}
+
+const char *
+DW_DSC_value_to_name (uint32_t val)
+{
+  static char invalid[100];
+  const char *llvmstr = llvm::dwarf::DiscriminantString (val);
+  if (llvmstr == NULL)
+  {
+      snprintf (invalid, sizeof (invalid), "Unknown DW_DSC constant: 0x%x", val);
+      return invalid;
+  }
+  return llvmstr;
+}
+
+const char *
+DW_LNS_value_to_name (uint32_t val)
+{
+  static char invalid[100];
+  const char *llvmstr = llvm::dwarf::LNStandardString (val);
+  if (llvmstr == NULL)
+  {
+      snprintf (invalid, sizeof (invalid), "Unknown DW_LNS constant: 0x%x", val);
+      return invalid;
+  }
+  return llvmstr;
+}
+
+const char *
+DW_LNE_value_to_name (uint32_t val)
+{
+  static char invalid[100];
+  const char *llvmstr = llvm::dwarf::LNExtendedString (val);
+  if (llvmstr == NULL)
+  {
+      snprintf (invalid, sizeof (invalid), "Unknown DW_LNE constant: 0x%x", val);
+      return invalid;
+  }
+  return llvmstr;
+}
+
+const char *
+DW_MACINFO_value_to_name (uint32_t val)
+{
+  static char invalid[100];
+  const char *llvmstr = llvm::dwarf::MacinfoString (val);
+  if (llvmstr == NULL)
+  {
+      snprintf (invalid, sizeof (invalid), "Unknown DW_MACINFO constant: 0x%x", val);
+      return invalid;
+  }
+  return llvmstr;
+}
+
+const char *
+DW_CFA_value_to_name (uint32_t val)
+{
+  static char invalid[100];
+  const char *llvmstr = llvm::dwarf::CallFrameString (val);
+  if (llvmstr == NULL)
+  {
+      snprintf (invalid, sizeof (invalid), "Unknown DW_CFA constant: 0x%x", val);
+      return invalid;
+  }
+  return llvmstr;
+}
+
+DW_TAG_CategoryEnum
+get_tag_category (uint16_t tag)
+{
+  switch (tag)
+    {
+      case DW_TAG_array_type                 : return TagCategoryType;
+      case DW_TAG_class_type                 : return TagCategoryType;
+      case DW_TAG_entry_point                : return TagCategoryProgram;
+      case DW_TAG_enumeration_type           : return TagCategoryType;
+      case DW_TAG_formal_parameter           : return TagCategoryVariable;
+      case DW_TAG_imported_declaration       : return TagCategoryProgram;
+      case DW_TAG_label                      : return TagCategoryProgram;
+      case DW_TAG_lexical_block              : return TagCategoryProgram;
+      case DW_TAG_member                     : return TagCategoryType;
+      case DW_TAG_pointer_type               : return TagCategoryType;
+      case DW_TAG_reference_type             : return TagCategoryType;
+      case DW_TAG_compile_unit               : return TagCategoryProgram;
+      case DW_TAG_string_type                : return TagCategoryType;
+      case DW_TAG_structure_type             : return TagCategoryType;
+      case DW_TAG_subroutine_type            : return TagCategoryType;
+      case DW_TAG_typedef                    : return TagCategoryType;
+      case DW_TAG_union_type                 : return TagCategoryType;
+      case DW_TAG_unspecified_parameters     : return TagCategoryVariable;
+      case DW_TAG_variant                    : return TagCategoryType;
+      case DW_TAG_common_block               : return TagCategoryProgram;
+      case DW_TAG_common_inclusion           : return TagCategoryProgram;
+      case DW_TAG_inheritance                : return TagCategoryType;
+      case DW_TAG_inlined_subroutine         : return TagCategoryProgram;
+      case DW_TAG_module                     : return TagCategoryProgram;
+      case DW_TAG_ptr_to_member_type         : return TagCategoryType;
+      case DW_TAG_set_type                   : return TagCategoryType;
+      case DW_TAG_subrange_type              : return TagCategoryType;
+      case DW_TAG_with_stmt                  : return TagCategoryProgram;
+      case DW_TAG_access_declaration         : return TagCategoryProgram;
+      case DW_TAG_base_type                  : return TagCategoryType;
+      case DW_TAG_catch_block                : return TagCategoryProgram;
+      case DW_TAG_const_type                 : return TagCategoryType;
+      case DW_TAG_constant                   : return TagCategoryVariable;
+      case DW_TAG_enumerator                 : return TagCategoryType;
+      case DW_TAG_file_type                  : return TagCategoryType;
+      case DW_TAG_friend                     : return TagCategoryType;
+      case DW_TAG_namelist                   : return TagCategoryVariable;
+      case DW_TAG_namelist_item              : return TagCategoryVariable;
+      case DW_TAG_packed_type                : return TagCategoryType;
+      case DW_TAG_subprogram                 : return TagCategoryProgram;
+      case DW_TAG_template_type_parameter    : return TagCategoryType;
+      case DW_TAG_template_value_parameter   : return TagCategoryType;
+      case DW_TAG_thrown_type                : return TagCategoryType;
+      case DW_TAG_try_block                  : return TagCategoryProgram;
+      case DW_TAG_variant_part               : return TagCategoryType;
+      case DW_TAG_variable                   : return TagCategoryVariable;
+      case DW_TAG_volatile_type              : return TagCategoryType;
+      case DW_TAG_dwarf_procedure            : return TagCategoryProgram;
+      case DW_TAG_restrict_type              : return TagCategoryType;
+      case DW_TAG_interface_type             : return TagCategoryType;
+      case DW_TAG_namespace                  : return TagCategoryProgram;
+      case DW_TAG_imported_module            : return TagCategoryProgram;
+      case DW_TAG_unspecified_type           : return TagCategoryType;
+      case DW_TAG_partial_unit               : return TagCategoryProgram;
+      case DW_TAG_imported_unit              : return TagCategoryProgram;
+      case DW_TAG_shared_type                : return TagCategoryType;
+      default: break;
+    }
+    return TagCategoryProgram;
+}
+
+} // namespace lldb_private
+
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFDefines.h b/source/Plugins/SymbolFile/DWARF/DWARFDefines.h
new file mode 100644
index 000000000000..e37aefb27a72
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFDefines.h
@@ -0,0 +1,116 @@
+//===-- DWARFDefines.h ------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SymbolFileDWARF_DWARFDefines_h_
+#define SymbolFileDWARF_DWARFDefines_h_
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "lldb/Core/dwarf.h"
+
+namespace lldb_private {
+
+typedef uint32_t DRC_class;          // Holds DRC_* class bitfields
+
+enum DW_TAG_Category
+{
+    TagCategoryVariable,
+    TagCategoryType,
+    TagCategoryProgram,
+    kNumTagCategories
+};
+
+typedef enum DW_TAG_Category DW_TAG_CategoryEnum;
+
+const char *DW_TAG_value_to_name (uint32_t val);
+
+DW_TAG_CategoryEnum get_tag_category (uint16_t tag);
+
+const char *DW_CHILDREN_value_to_name (uint8_t val);
+
+const char *DW_AT_value_to_name (uint32_t val);
+
+const char *DW_FORM_value_to_name (uint32_t val);
+
+const char *DW_OP_value_to_name (uint32_t val);
+
+DRC_class DW_OP_value_to_class (uint32_t val);
+
+const char *DW_ATE_value_to_name (uint32_t val);
+
+const char *DW_ACCESS_value_to_name (uint32_t val);
+
+const char *DW_VIS_value_to_name (uint32_t val);
+
+const char *DW_VIRTUALITY_value_to_name (uint32_t val);
+
+const char *DW_LANG_value_to_name (uint32_t val);
+
+const char *DW_ID_value_to_name (uint32_t val);
+
+const char *DW_CC_value_to_name (uint32_t val);
+
+const char *DW_INL_value_to_name (uint32_t val);
+
+const char *DW_ORD_value_to_name (uint32_t val);
+
+const char *DW_DSC_value_to_name (uint32_t val);
+
+const char *DW_LNS_value_to_name (uint32_t val);
+
+const char *DW_LNE_value_to_name (uint32_t val);
+
+const char *DW_MACINFO_value_to_name (uint32_t val);
+
+const char *DW_CFA_value_to_name (uint32_t val);
+
+const char *DW_GNU_EH_PE_value_to_name (uint32_t val);
+
+/* These DRC are entirely our own construction,
+    although they are derived from various comments in the DWARF standard.
+    Most of these are not useful to the parser, but the DW_AT and DW_FORM
+    classes should prove to be usable in some fashion.  */
+
+#define DRC_0x65                               0x1
+#define DRC_ADDRESS                            0x2
+#define DRC_BLOCK                              0x4
+#define DRC_CONSTANT                           0x8
+#define DRC_DWARFv3                           0x10
+#define DRC_FLAG                              0x20
+#define DRC_INDIRECT_SPECIAL                  0x40
+#define DRC_LINEPTR                           0x80
+#define DRC_LOCEXPR                          0x100
+#define DRC_LOCLISTPTR                       0x200
+#define DRC_MACPTR                           0x400
+#define DRC_ONEOPERAND                       0x800
+#define DRC_OPERANDONE_1BYTE_DELTA          0x1000
+#define DRC_OPERANDONE_2BYTE_DELTA          0x2000
+#define DRC_OPERANDONE_4BYTE_DELTA          0x4000
+#define DRC_OPERANDONE_ADDRESS              0x8000
+#define DRC_OPERANDONE_BLOCK               0x10000
+#define DRC_OPERANDONE_SLEB128_OFFSET      0x20000
+#define DRC_OPERANDONE_ULEB128_OFFSET      0x40000
+#define DRC_OPERANDONE_ULEB128_REGISTER    0x80000
+#define DRC_OPERANDTWO_BLOCK              0x100000
+#define DRC_OPERANDTWO_SLEB128_OFFSET     0x200000
+#define DRC_OPERANDTWO_ULEB128_OFFSET     0x400000
+#define DRC_OPERANDTWO_ULEB128_REGISTER   0x800000
+#define DRC_OPERNADONE_ULEB128_REGISTER  0x1000000
+#define DRC_RANGELISTPTR                 0x2000000
+#define DRC_REFERENCE                    0x4000000
+#define DRC_STRING                       0x8000000
+#define DRC_TWOOPERANDS                 0x10000000
+#define DRC_VENDOR_GNU                  0x20000000
+#define DRC_VENDOR_MIPS                 0x40000000
+#define DRC_ZEROOPERANDS                0x80000000
+
+} // namespace lldb_private
+
+
+#endif  // SymbolFileDWARF_DWARFDefines_h_
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp b/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
new file mode 100644
index 000000000000..6113a146c93d
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp
@@ -0,0 +1,599 @@
+//===-- DWARFFormValue.cpp --------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <assert.h>
+
+#include "lldb/Core/dwarf.h"
+#include "lldb/Core/Stream.h"
+
+#include "DWARFFormValue.h"
+#include "DWARFCompileUnit.h"
+
+class DWARFCompileUnit;
+
+using namespace lldb_private;
+
+
+static uint8_t g_form_sizes_addr4[] = 
+{
+    0, // 0x00 unused
+    4, // 0x01 DW_FORM_addr
+    0, // 0x02 unused
+    0, // 0x03 DW_FORM_block2
+    0, // 0x04 DW_FORM_block4
+    2, // 0x05 DW_FORM_data2
+    4, // 0x06 DW_FORM_data4
+    8, // 0x07 DW_FORM_data8
+    0, // 0x08 DW_FORM_string
+    0, // 0x09 DW_FORM_block
+    0, // 0x0a DW_FORM_block1
+    1, // 0x0b DW_FORM_data1
+    1, // 0x0c DW_FORM_flag
+    0, // 0x0d DW_FORM_sdata
+    4, // 0x0e DW_FORM_strp
+    0, // 0x0f DW_FORM_udata
+    0, // 0x10 DW_FORM_ref_addr (addr size for DWARF2 and earlier, 4 bytes for DWARF32, 8 bytes for DWARF32 in DWARF 3 and later
+    1, // 0x11 DW_FORM_ref1
+    2, // 0x12 DW_FORM_ref2
+    4, // 0x13 DW_FORM_ref4
+    8, // 0x14 DW_FORM_ref8
+    0, // 0x15 DW_FORM_ref_udata
+    0, // 0x16 DW_FORM_indirect
+    4, // 0x17 DW_FORM_sec_offset
+    0, // 0x18 DW_FORM_exprloc
+    0, // 0x19 DW_FORM_flag_present
+    0, // 0x1a
+    0, // 0x1b
+    0, // 0x1c
+    0, // 0x1d
+    0, // 0x1e
+    0, // 0x1f
+    8, // 0x20 DW_FORM_ref_sig8
+
+};
+
+static uint8_t
+g_form_sizes_addr8[] = 
+{
+    0, // 0x00 unused
+    8, // 0x01 DW_FORM_addr
+    0, // 0x02 unused
+    0, // 0x03 DW_FORM_block2
+    0, // 0x04 DW_FORM_block4
+    2, // 0x05 DW_FORM_data2
+    4, // 0x06 DW_FORM_data4
+    8, // 0x07 DW_FORM_data8
+    0, // 0x08 DW_FORM_string
+    0, // 0x09 DW_FORM_block
+    0, // 0x0a DW_FORM_block1
+    1, // 0x0b DW_FORM_data1
+    1, // 0x0c DW_FORM_flag
+    0, // 0x0d DW_FORM_sdata
+    4, // 0x0e DW_FORM_strp
+    0, // 0x0f DW_FORM_udata
+    0, // 0x10 DW_FORM_ref_addr (addr size for DWARF2 and earlier, 4 bytes for DWARF32, 8 bytes for DWARF32 in DWARF 3 and later
+    1, // 0x11 DW_FORM_ref1
+    2, // 0x12 DW_FORM_ref2
+    4, // 0x13 DW_FORM_ref4
+    8, // 0x14 DW_FORM_ref8
+    0, // 0x15 DW_FORM_ref_udata
+    0, // 0x16 DW_FORM_indirect
+    4, // 0x17 DW_FORM_sec_offset
+    0, // 0x18 DW_FORM_exprloc
+    0, // 0x19 DW_FORM_flag_present
+    0, // 0x1a
+    0, // 0x1b
+    0, // 0x1c
+    0, // 0x1d
+    0, // 0x1e
+    0, // 0x1f
+    8, // 0x20 DW_FORM_ref_sig8
+};
+
+const uint8_t * 
+DWARFFormValue::GetFixedFormSizesForAddressSize (uint8_t addr_size)
+{
+    switch (addr_size)
+    {
+    case 4: return g_form_sizes_addr4;
+    case 8: return g_form_sizes_addr8;
+    }
+    return NULL;
+}
+
+DWARFFormValue::DWARFFormValue(dw_form_t form) :
+    m_form(form),
+    m_value()
+{
+}
+
+bool
+DWARFFormValue::ExtractValue(const DataExtractor& data, lldb::offset_t* offset_ptr, const DWARFCompileUnit* cu)
+{
+    bool indirect = false;
+    bool is_block = false;
+    m_value.data = NULL;
+    // Read the value for the form into value and follow and DW_FORM_indirect instances we run into
+    do
+    {
+        indirect = false;
+        switch (m_form)
+        {
+        case DW_FORM_addr:      m_value.value.uval = data.GetMaxU64(offset_ptr, DWARFCompileUnit::GetAddressByteSize(cu));  break;
+        case DW_FORM_block2:    m_value.value.uval = data.GetU16(offset_ptr); is_block = true;          break;
+        case DW_FORM_block4:    m_value.value.uval = data.GetU32(offset_ptr); is_block = true;          break;
+        case DW_FORM_data2:     m_value.value.uval = data.GetU16(offset_ptr);                           break;
+        case DW_FORM_data4:     m_value.value.uval = data.GetU32(offset_ptr);                           break;
+        case DW_FORM_data8:     m_value.value.uval = data.GetU64(offset_ptr);                           break;
+        case DW_FORM_string:    m_value.value.cstr = data.GetCStr(offset_ptr);
+                                // Set the string value to also be the data for inlined cstr form values only
+                                // so we can tell the differnence between DW_FORM_string and DW_FORM_strp form
+                                // values;
+                                m_value.data = (uint8_t*)m_value.value.cstr;                            break;
+        case DW_FORM_exprloc:
+        case DW_FORM_block:     m_value.value.uval = data.GetULEB128(offset_ptr); is_block = true;      break;
+        case DW_FORM_block1:    m_value.value.uval = data.GetU8(offset_ptr); is_block = true;           break;
+        case DW_FORM_data1:     m_value.value.uval = data.GetU8(offset_ptr);                            break;
+        case DW_FORM_flag:      m_value.value.uval = data.GetU8(offset_ptr);                            break;
+        case DW_FORM_sdata:     m_value.value.sval = data.GetSLEB128(offset_ptr);                       break;
+        case DW_FORM_strp:      m_value.value.uval = data.GetU32(offset_ptr);                           break;
+    //  case DW_FORM_APPLE_db_str:
+        case DW_FORM_udata:     m_value.value.uval = data.GetULEB128(offset_ptr);                       break;
+        case DW_FORM_ref_addr:
+            if (cu->GetVersion() <= 2)
+                m_value.value.uval = data.GetMaxU64(offset_ptr, DWARFCompileUnit::GetAddressByteSize(cu));
+            else
+                m_value.value.uval = data.GetU32(offset_ptr); // 4 for DWARF32, 8 for DWARF64, but we don't support DWARF64 yet
+            break;
+        case DW_FORM_ref1:      m_value.value.uval = data.GetU8(offset_ptr);                            break;
+        case DW_FORM_ref2:      m_value.value.uval = data.GetU16(offset_ptr);                           break;
+        case DW_FORM_ref4:      m_value.value.uval = data.GetU32(offset_ptr);                           break;
+        case DW_FORM_ref8:      m_value.value.uval = data.GetU64(offset_ptr);                           break;
+        case DW_FORM_ref_udata: m_value.value.uval = data.GetULEB128(offset_ptr);                       break;
+        case DW_FORM_indirect:
+            m_form = data.GetULEB128(offset_ptr);
+            indirect = true;
+            break;
+
+        case DW_FORM_sec_offset:    m_value.value.uval = data.GetU32(offset_ptr);                       break;
+        case DW_FORM_flag_present:  m_value.value.uval = 1;                                             break;
+        case DW_FORM_ref_sig8:      m_value.value.uval = data.GetU64(offset_ptr);                       break;
+        default:
+            return false;
+            break;
+        }
+    } while (indirect);
+
+    if (is_block)
+    {
+        m_value.data = data.PeekData(*offset_ptr, m_value.value.uval);
+        if (m_value.data != NULL)
+        {
+            *offset_ptr += m_value.value.uval;
+        }
+    }
+
+    return true;
+}
+
+bool
+DWARFFormValue::SkipValue(const DataExtractor& debug_info_data, lldb::offset_t *offset_ptr, const DWARFCompileUnit* cu) const
+{
+    return DWARFFormValue::SkipValue(m_form, debug_info_data, offset_ptr, cu);
+}
+
+bool
+DWARFFormValue::SkipValue(dw_form_t form, const DataExtractor& debug_info_data, lldb::offset_t *offset_ptr, const DWARFCompileUnit* cu)
+{
+    switch (form)
+    {
+    // Blocks if inlined data that have a length field and the data bytes
+    // inlined in the .debug_info
+    case DW_FORM_exprloc:
+    case DW_FORM_block:  { dw_uleb128_t size = debug_info_data.GetULEB128(offset_ptr); *offset_ptr += size; } return true;
+    case DW_FORM_block1: { dw_uleb128_t size = debug_info_data.GetU8(offset_ptr);      *offset_ptr += size; } return true;
+    case DW_FORM_block2: { dw_uleb128_t size = debug_info_data.GetU16(offset_ptr);     *offset_ptr += size; } return true;
+    case DW_FORM_block4: { dw_uleb128_t size = debug_info_data.GetU32(offset_ptr);     *offset_ptr += size; } return true;
+
+    // Inlined NULL terminated C-strings
+    case DW_FORM_string:
+        debug_info_data.GetCStr(offset_ptr);
+        return true;
+
+    // Compile unit address sized values
+    case DW_FORM_addr:
+        *offset_ptr += DWARFCompileUnit::GetAddressByteSize(cu);
+        return true;
+
+    case DW_FORM_ref_addr:
+        if (cu->GetVersion() <= 2)
+            *offset_ptr += DWARFCompileUnit::GetAddressByteSize(cu);
+        else
+            *offset_ptr += 4;// 4 for DWARF32, 8 for DWARF64, but we don't support DWARF64 yet
+        return true;
+
+    // 0 bytes values (implied from DW_FORM)
+    case DW_FORM_flag_present:
+        return true;
+
+    // 1 byte values
+    case DW_FORM_data1:
+    case DW_FORM_flag:
+    case DW_FORM_ref1:
+        *offset_ptr += 1;
+        return true;
+
+    // 2 byte values
+    case DW_FORM_data2:
+    case DW_FORM_ref2:
+        *offset_ptr += 2;
+        return true;
+
+    // 32 bit for DWARF 32, 64 for DWARF 64
+    case DW_FORM_sec_offset:
+        *offset_ptr += 4;
+        return true;
+
+    // 4 byte values
+    case DW_FORM_strp:
+    case DW_FORM_data4:
+    case DW_FORM_ref4:
+        *offset_ptr += 4;
+        return true;
+
+    // 8 byte values
+    case DW_FORM_data8:
+    case DW_FORM_ref8:
+    case DW_FORM_ref_sig8:
+        *offset_ptr += 8;
+        return true;
+
+    // signed or unsigned LEB 128 values
+    case DW_FORM_sdata:
+    case DW_FORM_udata:
+    case DW_FORM_ref_udata:
+        debug_info_data.Skip_LEB128(offset_ptr);
+        return true;
+
+    case DW_FORM_indirect:
+        {
+            dw_form_t indirect_form = debug_info_data.GetULEB128(offset_ptr);
+            return DWARFFormValue::SkipValue (indirect_form,
+                                              debug_info_data,
+                                              offset_ptr,
+                                              cu);
+        }
+
+    default:
+        break;
+    }
+    return false;
+}
+
+
+void
+DWARFFormValue::Dump(Stream &s, const DataExtractor* debug_str_data, const DWARFCompileUnit* cu) const
+{
+    uint64_t uvalue = Unsigned();
+    bool cu_relative_offset = false;
+
+    bool verbose = s.GetVerbose();
+
+    switch (m_form)
+    {
+    case DW_FORM_addr:      s.Address(uvalue, sizeof (uint64_t)); break;
+    case DW_FORM_flag:
+    case DW_FORM_data1:     s.PutHex8(uvalue);     break;
+    case DW_FORM_data2:     s.PutHex16(uvalue);        break;
+    case DW_FORM_sec_offset:
+    case DW_FORM_data4:     s.PutHex32(uvalue);        break;
+    case DW_FORM_ref_sig8:
+    case DW_FORM_data8:     s.PutHex64(uvalue);        break;
+    case DW_FORM_string:    s.QuotedCString(AsCString(NULL));          break;
+    case DW_FORM_exprloc:
+    case DW_FORM_block:
+    case DW_FORM_block1:
+    case DW_FORM_block2:
+    case DW_FORM_block4:
+        if (uvalue > 0)
+        {
+            switch (m_form)
+            {
+            case DW_FORM_exprloc:
+            case DW_FORM_block:  s.Printf("<0x%" PRIx64 "> ", uvalue);                break;
+            case DW_FORM_block1: s.Printf("<0x%2.2x> ", (uint8_t)uvalue);      break;
+            case DW_FORM_block2: s.Printf("<0x%4.4x> ", (uint16_t)uvalue);     break;
+            case DW_FORM_block4: s.Printf("<0x%8.8x> ", (uint32_t)uvalue);     break;
+            default:                                                            break;
+            }
+
+            const uint8_t* data_ptr = m_value.data;
+            if (data_ptr)
+            {
+                const uint8_t* end_data_ptr = data_ptr + uvalue;    // uvalue contains size of block
+                while (data_ptr < end_data_ptr)
+                {
+                    s.Printf("%2.2x ", *data_ptr);
+                    ++data_ptr;
+                }
+            }
+            else
+                s.PutCString("NULL");
+        }
+        break;
+
+    case DW_FORM_sdata:     s.PutSLEB128(uvalue); break;
+    case DW_FORM_udata:     s.PutULEB128(uvalue); break;
+    case DW_FORM_strp:
+        if (debug_str_data)
+        {
+            if (verbose)
+                s.Printf(" .debug_str[0x%8.8x] = ", (uint32_t)uvalue);
+
+            const char* dbg_str = AsCString(debug_str_data);
+            if (dbg_str)
+                s.QuotedCString(dbg_str);
+        }
+        else
+        {
+            s.PutHex32(uvalue);
+        }
+        break;
+
+    case DW_FORM_ref_addr:
+    {
+        if (cu->GetVersion() <= 2)
+            s.Address(uvalue, sizeof (uint64_t) * 2);
+        else
+            s.Address(uvalue, 4 * 2);// 4 for DWARF32, 8 for DWARF64, but we don't support DWARF64 yet
+        break;
+    }
+    case DW_FORM_ref1:      cu_relative_offset = true;  if (verbose) s.Printf("cu + 0x%2.2x", (uint8_t)uvalue); break;
+    case DW_FORM_ref2:      cu_relative_offset = true;  if (verbose) s.Printf("cu + 0x%4.4x", (uint16_t)uvalue); break;
+    case DW_FORM_ref4:      cu_relative_offset = true;  if (verbose) s.Printf("cu + 0x%4.4x", (uint32_t)uvalue); break;
+    case DW_FORM_ref8:      cu_relative_offset = true;  if (verbose) s.Printf("cu + 0x%8.8" PRIx64, uvalue); break;
+    case DW_FORM_ref_udata: cu_relative_offset = true;  if (verbose) s.Printf("cu + 0x%" PRIx64, uvalue); break;
+
+    // All DW_FORM_indirect attributes should be resolved prior to calling this function
+    case DW_FORM_indirect:  s.PutCString("DW_FORM_indirect"); break;
+    case DW_FORM_flag_present: break;
+    default:
+        s.Printf("DW_FORM(0x%4.4x)", m_form);
+        break;
+    }
+
+    if (cu_relative_offset)
+    {
+        if (verbose)
+            s.PutCString(" => ");
+
+        s.Printf("{0x%8.8" PRIx64 "}", (uvalue + (cu ? cu->GetOffset() : 0)));
+    }
+}
+
+const char*
+DWARFFormValue::AsCString(const DataExtractor* debug_str_data_ptr) const
+{
+    if (IsInlinedCStr())
+        return m_value.value.cstr;
+    else if (debug_str_data_ptr)
+        return debug_str_data_ptr->PeekCStr(m_value.value.uval);
+    return NULL;
+}
+
+uint64_t
+DWARFFormValue::Reference(const DWARFCompileUnit* cu) const
+{
+    uint64_t die_offset = m_value.value.uval;
+    switch (m_form)
+    {
+    case DW_FORM_ref1:
+    case DW_FORM_ref2:
+    case DW_FORM_ref4:
+    case DW_FORM_ref8:
+    case DW_FORM_ref_udata:
+        die_offset += (cu ? cu->GetOffset() : 0);
+        break;
+
+    default:
+        break;
+    }
+
+    return die_offset;
+}
+
+uint64_t
+DWARFFormValue::Reference (dw_offset_t base_offset) const
+{
+    uint64_t die_offset = m_value.value.uval;
+    switch (m_form)
+    {
+        case DW_FORM_ref1:
+        case DW_FORM_ref2:
+        case DW_FORM_ref4:
+        case DW_FORM_ref8:
+        case DW_FORM_ref_udata:
+            die_offset += base_offset;
+            break;
+            
+        default:
+            break;
+    }
+    
+    return die_offset;
+}
+
+//----------------------------------------------------------------------
+// Resolve any compile unit specific references so that we don't need
+// the compile unit at a later time in order to work with the form
+// value.
+//----------------------------------------------------------------------
+bool
+DWARFFormValue::ResolveCompileUnitReferences(const DWARFCompileUnit* cu)
+{
+    switch (m_form)
+    {
+    case DW_FORM_ref1:
+    case DW_FORM_ref2:
+    case DW_FORM_ref4:
+    case DW_FORM_ref8:
+    case DW_FORM_ref_udata:
+        m_value.value.uval += cu->GetOffset();
+        m_form = DW_FORM_ref_addr;
+        return true;
+        break;
+
+    default:
+        break;
+    }
+
+    return false;
+}
+
+const uint8_t*
+DWARFFormValue::BlockData() const
+{
+    if (!IsInlinedCStr())
+        return m_value.data;
+    return NULL;
+}
+
+
+bool
+DWARFFormValue::IsBlockForm(const dw_form_t form)
+{
+    switch (form)
+    {
+    case DW_FORM_block:
+    case DW_FORM_block1:
+    case DW_FORM_block2:
+    case DW_FORM_block4:
+        return true;
+    }
+    return false;
+}
+
+bool
+DWARFFormValue::IsDataForm(const dw_form_t form)
+{
+    switch (form)
+    {
+    case DW_FORM_sdata:
+    case DW_FORM_udata:
+    case DW_FORM_data1:
+    case DW_FORM_data2:
+    case DW_FORM_data4:
+    case DW_FORM_data8:
+        return true;
+    }
+    return false;
+}
+
+int
+DWARFFormValue::Compare (const DWARFFormValue& a_value, const DWARFFormValue& b_value, const DWARFCompileUnit* a_cu, const DWARFCompileUnit* b_cu, const DataExtractor* debug_str_data_ptr)
+{
+    dw_form_t a_form = a_value.Form();
+    dw_form_t b_form = b_value.Form();
+    if (a_form < b_form)
+        return -1;
+    if (a_form > b_form)
+        return 1;
+    switch (a_form)
+    {
+    case DW_FORM_addr:
+    case DW_FORM_flag:
+    case DW_FORM_data1:
+    case DW_FORM_data2:
+    case DW_FORM_data4:
+    case DW_FORM_data8:
+    case DW_FORM_udata:
+    case DW_FORM_ref_addr:
+    case DW_FORM_sec_offset:
+    case DW_FORM_flag_present:
+    case DW_FORM_ref_sig8:
+        {
+            uint64_t a = a_value.Unsigned();
+            uint64_t b = b_value.Unsigned();
+            if (a < b)
+                return -1;
+            if (a > b)
+                return 1;
+            return 0;
+        }
+
+    case DW_FORM_sdata:
+        {
+            int64_t a = a_value.Signed();
+            int64_t b = b_value.Signed();
+            if (a < b)
+                return -1;
+            if (a > b)
+                return 1;
+            return 0;
+        }
+
+    case DW_FORM_string:
+    case DW_FORM_strp:
+        {
+            const char *a_string = a_value.AsCString(debug_str_data_ptr);
+            const char *b_string = b_value.AsCString(debug_str_data_ptr);
+            if (a_string == b_string)
+                return 0;
+            else if (a_string && b_string)
+                return strcmp(a_string, b_string);
+            else if (a_string == NULL)
+                return -1;  // A string is NULL, and B is valid
+            else
+                return 1;   // A string valid, and B is NULL
+        }
+
+
+    case DW_FORM_block:
+    case DW_FORM_block1:
+    case DW_FORM_block2:
+    case DW_FORM_block4:
+    case DW_FORM_exprloc:
+        {
+            uint64_t a_len = a_value.Unsigned();
+            uint64_t b_len = b_value.Unsigned();
+            if (a_len < b_len)
+                return -1;
+            if (a_len > b_len)
+                return 1;
+            // The block lengths are the same
+            return memcmp(a_value.BlockData(), b_value.BlockData(), a_value.Unsigned());
+        }
+        break;
+
+    case DW_FORM_ref1:
+    case DW_FORM_ref2:
+    case DW_FORM_ref4:
+    case DW_FORM_ref8:
+    case DW_FORM_ref_udata:
+        {
+            uint64_t a = a_value.Reference(a_cu);
+            uint64_t b = b_value.Reference(b_cu);
+            if (a < b)
+                return -1;
+            if (a > b)
+                return 1;
+            return 0;
+        }
+
+    case DW_FORM_indirect:
+        assert(!"This shouldn't happen after the form has been extracted...");
+        break;
+
+    default:
+        assert(!"Unhandled DW_FORM");
+        break;
+    }
+    return -1;
+}
+
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h b/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h
new file mode 100644
index 000000000000..4c400b2df58e
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h
@@ -0,0 +1,81 @@
+//===-- DWARFFormValue.h ----------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SymbolFileDWARF_DWARFFormValue_h_
+#define SymbolFileDWARF_DWARFFormValue_h_
+
+#include <stddef.h> // for NULL
+
+class DWARFCompileUnit;
+
+class DWARFFormValue
+{
+public:
+    typedef struct ValueTypeTag
+    {
+        ValueTypeTag() :
+            value(),
+            data(NULL)
+        {
+            value.uval = 0;
+        }
+
+        union
+        {
+            uint64_t uval;
+            int64_t sval;
+            const char* cstr;
+        } value;
+        const uint8_t* data;
+    } ValueType;
+
+    enum
+    {
+        eValueTypeInvalid = 0,
+        eValueTypeUnsigned,
+        eValueTypeSigned,
+        eValueTypeCStr,
+        eValueTypeBlock
+    };
+
+    DWARFFormValue(dw_form_t form = 0);
+    dw_form_t           Form()  const { return m_form; }
+    void                SetForm(dw_form_t form) { m_form = form; }
+    const ValueType&    Value() const { return m_value; }
+    void                Dump(lldb_private::Stream &s, const lldb_private::DataExtractor* debug_str_data, const DWARFCompileUnit* cu) const;
+    bool                ExtractValue(const lldb_private::DataExtractor& data,
+                                     lldb::offset_t* offset_ptr,
+                                     const DWARFCompileUnit* cu);
+    bool                IsInlinedCStr() const { return (m_value.data != NULL) && m_value.data == (uint8_t*)m_value.value.cstr; }
+    const uint8_t*      BlockData() const;
+    uint64_t            Reference(const DWARFCompileUnit* cu) const;
+    uint64_t            Reference (dw_offset_t offset) const;
+    bool                ResolveCompileUnitReferences(const DWARFCompileUnit* cu);
+    bool                Boolean() const { return m_value.value.uval != 0; }
+    uint64_t            Unsigned() const { return m_value.value.uval; }
+    void                SetUnsigned(uint64_t uval) { m_value.value.uval = uval; }
+    int64_t             Signed() const { return m_value.value.sval; }
+    void                SetSigned(int64_t sval) { m_value.value.sval = sval; }
+    const char*         AsCString(const lldb_private::DataExtractor* debug_str_data_ptr) const;
+    bool                SkipValue(const lldb_private::DataExtractor& debug_info_data, lldb::offset_t *offset_ptr, const DWARFCompileUnit* cu) const;
+    static bool         SkipValue(const dw_form_t form, const lldb_private::DataExtractor& debug_info_data, lldb::offset_t *offset_ptr, const DWARFCompileUnit* cu);
+//  static bool         TransferValue(dw_form_t form, const lldb_private::DataExtractor& debug_info_data, lldb::offset_t *offset_ptr, const DWARFCompileUnit* cu, BinaryStreamBuf& out_buff);
+//  static bool         TransferValue(const DWARFFormValue& formValue, const DWARFCompileUnit* cu, BinaryStreamBuf& out_buff);
+//  static bool         PutUnsigned(dw_form_t form, dw_offset_t offset, uint64_t value, BinaryStreamBuf& out_buff, const DWARFCompileUnit* cu, bool fixup_cu_relative_refs);
+    static bool         IsBlockForm(const dw_form_t form);
+    static bool         IsDataForm(const dw_form_t form);
+    static const uint8_t * GetFixedFormSizesForAddressSize (uint8_t addr_size);
+    static int          Compare (const DWARFFormValue& a, const DWARFFormValue& b, const DWARFCompileUnit* a_cu, const DWARFCompileUnit* b_cu, const lldb_private::DataExtractor* debug_str_data_ptr);
+protected:
+    dw_form_t   m_form;     // Form for this value
+    ValueType   m_value;    // Contains all data for the form
+};
+
+
+#endif  // SymbolFileDWARF_DWARFFormValue_h_
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFLocationDescription.cpp b/source/Plugins/SymbolFile/DWARF/DWARFLocationDescription.cpp
new file mode 100644
index 000000000000..fdc07836b88d
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFLocationDescription.cpp
@@ -0,0 +1,172 @@
+//===-- DWARFLocationDescription.cpp ----------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFLocationDescription.h"
+#include "DWARFDefines.h"
+#include "lldb/lldb-private.h"
+#include "lldb/Core/Stream.h"
+
+
+using namespace lldb_private;
+
+static int print_dwarf_exp_op (Stream &s, const DataExtractor& data, lldb::offset_t *offset_ptr, int address_size, int dwarf_ref_size);
+
+int
+print_dwarf_expression (Stream &s,
+                        const DataExtractor& data,
+                        int address_size,
+                        int dwarf_ref_size,
+                        bool location_expression)
+{
+    int op_count = 0;
+    lldb::offset_t offset = 0;
+    while (data.ValidOffset(offset))
+    {
+        if (location_expression && op_count > 0)
+        {
+            //  err (baton, "Dwarf location expressions may only have one operand!");
+            return 1;
+        }
+        if (op_count > 0)
+        {
+            s.PutCString(", ");
+        }
+        if (print_dwarf_exp_op (s, data, &offset, address_size, dwarf_ref_size) == 1)
+            return 1;
+        op_count++;
+    }
+
+    return 0;
+}
+
+static int
+print_dwarf_exp_op (Stream &s,
+                    const DataExtractor& data,
+                    lldb::offset_t *offset_ptr,
+                    int address_size,
+                    int dwarf_ref_size)
+{
+    uint8_t opcode = data.GetU8(offset_ptr);
+    DRC_class opcode_class;
+    uint64_t  uint;
+    int64_t   sint;
+
+    int size;
+
+    opcode_class = DW_OP_value_to_class (opcode) & (~DRC_DWARFv3);
+
+    s.Printf("%s ", DW_OP_value_to_name (opcode));
+
+    /* Does this take zero parameters?  If so we can shortcut this function.  */
+    if (opcode_class == DRC_ZEROOPERANDS)
+        return 0;
+
+    if (opcode_class == DRC_TWOOPERANDS && opcode == DW_OP_bregx)
+    {
+        uint = data.GetULEB128(offset_ptr);
+        sint = data.GetSLEB128(offset_ptr);
+        s.Printf("%" PRIu64 " %" PRIi64, uint, sint);
+        return 0;
+    }
+    if (opcode_class != DRC_ONEOPERAND)
+    {
+        s.Printf("UNKNOWN OP %u", opcode);
+        return 1;
+    }
+
+    switch (opcode)
+    {
+        case DW_OP_addr:    size = address_size;    break;
+        case DW_OP_const1u: size = 1;               break;
+        case DW_OP_const1s: size = -1;              break;
+        case DW_OP_const2u: size = 2;               break;
+        case DW_OP_const2s: size = -2;              break;
+        case DW_OP_const4u: size = 4;               break;
+        case DW_OP_const4s: size = -4;              break;
+        case DW_OP_const8u: size = 8;               break;
+        case DW_OP_const8s: size = -8;              break;
+        case DW_OP_constu:  size = 128;             break;
+        case DW_OP_consts:  size = -128;            break;
+        case DW_OP_fbreg:   size = -128;            break;
+        case DW_OP_breg0:
+        case DW_OP_breg1:
+        case DW_OP_breg2:
+        case DW_OP_breg3:
+        case DW_OP_breg4:
+        case DW_OP_breg5:
+        case DW_OP_breg6:
+        case DW_OP_breg7:
+        case DW_OP_breg8:
+        case DW_OP_breg9:
+        case DW_OP_breg10:
+        case DW_OP_breg11:
+        case DW_OP_breg12:
+        case DW_OP_breg13:
+        case DW_OP_breg14:
+        case DW_OP_breg15:
+        case DW_OP_breg16:
+        case DW_OP_breg17:
+        case DW_OP_breg18:
+        case DW_OP_breg19:
+        case DW_OP_breg20:
+        case DW_OP_breg21:
+        case DW_OP_breg22:
+        case DW_OP_breg23:
+        case DW_OP_breg24:
+        case DW_OP_breg25:
+        case DW_OP_breg26:
+        case DW_OP_breg27:
+        case DW_OP_breg28:
+        case DW_OP_breg29:
+        case DW_OP_breg30:
+        case DW_OP_breg31:
+            size = -128; break;
+        case DW_OP_pick:
+            size = 1;       break;
+        case DW_OP_deref_size:
+            size = 1;       break;
+        case DW_OP_xderef_size:
+            size = 1;       break;
+        case DW_OP_plus_uconst:
+            size = 128;     break;
+        case DW_OP_skip:
+            size = -2;      break;
+        case DW_OP_bra:
+            size = -2;      break;
+        case DW_OP_call2:
+            size = 2;       break;
+        case DW_OP_call4:
+            size = 4;       break;
+        case DW_OP_call_ref:
+            size = dwarf_ref_size;  break;
+        case DW_OP_piece:
+            size = 128; break;
+        case DW_OP_regx:
+            size = 128; break;
+        default:
+            s.Printf("UNKNOWN ONE-OPERAND OPCODE, #%u", opcode);
+            return 1;
+    }
+
+    switch (size)
+    {
+    case -1:    sint = (int8_t)     data.GetU8(offset_ptr);     s.Printf("%+" PRIi64, sint); break;
+    case -2:    sint = (int16_t)    data.GetU16(offset_ptr);    s.Printf("%+" PRIi64, sint); break;
+    case -4:    sint = (int32_t)    data.GetU32(offset_ptr);    s.Printf("%+" PRIi64, sint); break;
+    case -8:    sint = (int64_t)    data.GetU64(offset_ptr);    s.Printf("%+" PRIi64, sint); break;
+    case -128:  sint = data.GetSLEB128(offset_ptr);             s.Printf("%+" PRIi64, sint); break;
+    case 1:     uint = data.GetU8(offset_ptr);                  s.Printf("0x%2.2" PRIx64, uint); break;
+    case 2:     uint = data.GetU16(offset_ptr);                 s.Printf("0x%4.4" PRIx64, uint); break;
+    case 4:     uint = data.GetU32(offset_ptr);                 s.Printf("0x%8.8" PRIx64, uint); break;
+    case 8:     uint = data.GetU64(offset_ptr);                 s.Printf("0x%16.16" PRIx64, uint); break;
+    case 128:   uint = data.GetULEB128(offset_ptr);             s.Printf("0x%" PRIx64, uint); break;
+    }
+
+    return 0;
+}
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFLocationDescription.h b/source/Plugins/SymbolFile/DWARF/DWARFLocationDescription.h
new file mode 100644
index 000000000000..ff7c907e921c
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFLocationDescription.h
@@ -0,0 +1,24 @@
+//===-- DWARFLocationDescription.h ------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SymbolFileDWARF_DWARFLocationDescription_h_
+#define SymbolFileDWARF_DWARFLocationDescription_h_
+
+#include "SymbolFileDWARF.h"
+
+int
+print_dwarf_expression (lldb_private::Stream &s,
+                        const lldb_private::DataExtractor& data,
+                        int address_size,
+                        int dwarf_ref_size,
+                        bool location_expression);
+
+
+
+#endif  // SymbolFileDWARF_DWARFLocationDescription_h_
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFLocationList.cpp b/source/Plugins/SymbolFile/DWARF/DWARFLocationList.cpp
new file mode 100644
index 000000000000..dad5691267df
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFLocationList.cpp
@@ -0,0 +1,94 @@
+//===-- DWARFLocationList.cpp -----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFLocationList.h"
+
+#include "lldb/Core/Stream.h"
+
+#include "DWARFCompileUnit.h"
+#include "DWARFDebugInfo.h"
+#include "DWARFLocationDescription.h"
+
+using namespace lldb_private;
+
+dw_offset_t
+DWARFLocationList::Dump(Stream &s, const DWARFCompileUnit* cu, const DataExtractor& debug_loc_data, lldb::offset_t offset)
+{
+    uint64_t start_addr, end_addr;
+    uint32_t addr_size = DWARFCompileUnit::GetAddressByteSize(cu);
+    s.SetAddressByteSize(DWARFCompileUnit::GetAddressByteSize(cu));
+    dw_addr_t base_addr = cu ? cu->GetBaseAddress() : 0;
+    while (debug_loc_data.ValidOffset(offset))
+    {
+        start_addr = debug_loc_data.GetMaxU64(&offset,addr_size);
+        end_addr = debug_loc_data.GetMaxU64(&offset,addr_size);
+
+        if (start_addr == 0 && end_addr == 0)
+            break;
+
+        s.PutCString("\n            ");
+        s.Indent();
+        if (cu)
+            s.AddressRange (start_addr + base_addr, 
+                            end_addr + base_addr, 
+                            cu->GetAddressByteSize(), 
+                            NULL,
+                            ": ");
+        uint32_t loc_length = debug_loc_data.GetU16(&offset);
+
+        DataExtractor locationData(debug_loc_data, offset, loc_length);
+    //  if ( dump_flags & DWARFDebugInfo::eDumpFlag_Verbose ) *ostrm_ptr << " ( ";
+        print_dwarf_expression (s, locationData, addr_size, 4, false);
+        offset += loc_length;
+    }
+
+    return offset;
+}
+
+bool
+DWARFLocationList::Extract(const DataExtractor& debug_loc_data, lldb::offset_t* offset_ptr, DataExtractor& location_list_data)
+{
+    // Initialize with no data just in case we don't find anything
+    location_list_data.Clear();
+
+    size_t loc_list_length = Size(debug_loc_data, *offset_ptr);
+    if (loc_list_length > 0)
+    {
+        location_list_data.SetData(debug_loc_data, *offset_ptr, loc_list_length);
+        *offset_ptr += loc_list_length;
+        return true;
+    }
+
+    return false;
+}
+
+size_t
+DWARFLocationList::Size(const DataExtractor& debug_loc_data, lldb::offset_t offset)
+{
+    const dw_offset_t debug_loc_offset = offset;
+
+    while (debug_loc_data.ValidOffset(offset))
+    {
+        dw_addr_t start_addr = debug_loc_data.GetAddress(&offset);
+        dw_addr_t end_addr = debug_loc_data.GetAddress(&offset);
+
+        if (start_addr == 0 && end_addr == 0)
+            break;
+
+        uint16_t loc_length = debug_loc_data.GetU16(&offset);
+        offset += loc_length;
+    }
+
+    if (offset > debug_loc_offset)
+        return offset - debug_loc_offset;
+    return 0;
+}
+
+
+
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFLocationList.h b/source/Plugins/SymbolFile/DWARF/DWARFLocationList.h
new file mode 100644
index 000000000000..85e11d90b36b
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/DWARFLocationList.h
@@ -0,0 +1,34 @@
+//===-- DWARFLocationList.h -------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SymbolFileDWARF_DWARFLocationList_h_
+#define SymbolFileDWARF_DWARFLocationList_h_
+
+#include "SymbolFileDWARF.h"
+
+class DWARFLocationList
+{
+public:
+    static dw_offset_t
+    Dump (lldb_private::Stream &s,
+          const DWARFCompileUnit* cu,
+          const lldb_private::DataExtractor& debug_loc_data,
+          lldb::offset_t offset);
+
+    static bool
+    Extract (const lldb_private::DataExtractor& debug_loc_data,
+             lldb::offset_t* offset_ptr,
+             lldb_private::DataExtractor& location_list_data);
+
+    static size_t
+    Size (const lldb_private::DataExtractor& debug_loc_data,
+          lldb::offset_t offset);
+
+};
+#endif  // SymbolFileDWARF_DWARFLocationList_h_
diff --git a/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h b/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h
new file mode 100644
index 000000000000..c31cbaf3ca20
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h
@@ -0,0 +1,933 @@
+//===-- HashedNameToDIE.h ---------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SymbolFileDWARF_HashedNameToDIE_h_
+#define SymbolFileDWARF_HashedNameToDIE_h_
+
+#include <vector>
+
+#include "DWARFDefines.h"
+#include "DWARFFormValue.h"
+
+#include "lldb/lldb-defines.h"
+#include "lldb/Core/dwarf.h"
+#include "lldb/Core/RegularExpression.h"
+#include "lldb/Core/MappedHash.h"
+
+
+class SymbolFileDWARF;
+class DWARFCompileUnit;
+class DWARFDebugInfoEntry;
+
+struct DWARFMappedHash
+{
+    struct DIEInfo
+    {
+        dw_offset_t offset;  // The DIE offset
+        dw_tag_t tag;
+        uint32_t type_flags; // Any flags for this DIEInfo
+        uint32_t qualified_name_hash; // A 32 bit hash of the fully qualified name
+
+        DIEInfo () :
+            offset (DW_INVALID_OFFSET),
+            tag (0),
+            type_flags (0),
+            qualified_name_hash (0)
+        {
+        }
+
+        DIEInfo (dw_offset_t o, dw_tag_t t, uint32_t f, uint32_t h) :
+            offset(o),
+            tag (t),
+            type_flags (f),
+            qualified_name_hash (h)
+        {
+        }
+        
+        void
+        Clear()
+        {
+            offset = DW_INVALID_OFFSET;
+            tag = 0;
+            type_flags = 0;
+            qualified_name_hash = 0;
+        }            
+    };
+    
+    typedef std::vector<DIEInfo> DIEInfoArray;
+    typedef std::vector<uint32_t> DIEArray;
+    
+    static void
+    ExtractDIEArray (const DIEInfoArray &die_info_array,
+                     DIEArray &die_offsets)
+    {
+        const size_t count = die_info_array.size();
+        for (size_t i=0; i<count; ++i)
+        {
+            die_offsets.push_back (die_info_array[i].offset);
+        }
+    }
+
+    static void
+    ExtractDIEArray (const DIEInfoArray &die_info_array,
+                     const dw_tag_t tag,
+                     DIEArray &die_offsets)
+    {
+        if (tag == 0)
+        {
+            ExtractDIEArray (die_info_array, die_offsets);
+        }
+        else
+        {
+            const size_t count = die_info_array.size();
+            for (size_t i=0; i<count; ++i)
+            {
+                const dw_tag_t die_tag = die_info_array[i].tag;
+                bool tag_matches = die_tag == 0 || tag == die_tag;
+                if (!tag_matches)
+                {
+                    if (die_tag == DW_TAG_class_type || die_tag == DW_TAG_structure_type)
+                        tag_matches = tag == DW_TAG_structure_type || tag == DW_TAG_class_type;
+                }
+                if (tag_matches)
+                    die_offsets.push_back (die_info_array[i].offset);
+            }
+        }
+    }
+
+    static void
+    ExtractDIEArray (const DIEInfoArray &die_info_array,
+                     const dw_tag_t tag,
+                     const uint32_t qualified_name_hash,
+                     DIEArray &die_offsets)
+    {
+        if (tag == 0)
+        {
+            ExtractDIEArray (die_info_array, die_offsets);
+        }
+        else
+        {
+            const size_t count = die_info_array.size();
+            for (size_t i=0; i<count; ++i)
+            {
+                if (qualified_name_hash != die_info_array[i].qualified_name_hash)
+                    continue;
+                const dw_tag_t die_tag = die_info_array[i].tag;
+                bool tag_matches = die_tag == 0 || tag == die_tag;
+                if (!tag_matches)
+                {
+                    if (die_tag == DW_TAG_class_type || die_tag == DW_TAG_structure_type)
+                        tag_matches = tag == DW_TAG_structure_type || tag == DW_TAG_class_type;
+                }
+                if (tag_matches)
+                    die_offsets.push_back (die_info_array[i].offset);
+            }
+        }
+    }
+
+    enum AtomType
+    {
+        eAtomTypeNULL       = 0u,
+        eAtomTypeDIEOffset  = 1u,   // DIE offset, check form for encoding
+        eAtomTypeCUOffset   = 2u,   // DIE offset of the compiler unit header that contains the item in question
+        eAtomTypeTag        = 3u,   // DW_TAG_xxx value, should be encoded as DW_FORM_data1 (if no tags exceed 255) or DW_FORM_data2
+        eAtomTypeNameFlags  = 4u,   // Flags from enum NameFlags
+        eAtomTypeTypeFlags  = 5u,   // Flags from enum TypeFlags,
+        eAtomTypeQualNameHash = 6u  // A 32 bit hash of the full qualified name (since all hash entries are basename only)
+                                    // For example a type like "std::vector<int>::iterator" would have a name of "iterator"
+                                    // and a 32 bit hash for "std::vector<int>::iterator" to allow us to not have to pull
+                                    // in debug info for a type when we know the fully qualified name.
+    };
+    
+    // Bit definitions for the eAtomTypeTypeFlags flags
+    enum TypeFlags
+    {
+        // Always set for C++, only set for ObjC if this is the 
+        // @implementation for class
+        eTypeFlagClassIsImplementation  = ( 1u << 1 )
+    };
+    
+
+    static void
+    ExtractClassOrStructDIEArray (const DIEInfoArray &die_info_array,
+                                  bool return_implementation_only_if_available,
+                                  DIEArray &die_offsets)
+    {
+        const size_t count = die_info_array.size();
+        for (size_t i=0; i<count; ++i)
+        {
+            const dw_tag_t die_tag = die_info_array[i].tag;
+            if (die_tag == 0 || die_tag == DW_TAG_class_type || die_tag == DW_TAG_structure_type)
+            {
+                if (die_info_array[i].type_flags & eTypeFlagClassIsImplementation)
+                {
+                    if (return_implementation_only_if_available)
+                    {
+                        // We found the one true definiton for this class, so
+                        // only return that
+                        die_offsets.clear();                        
+                        die_offsets.push_back (die_info_array[i].offset);
+                        return;
+                    }
+                    else
+                    {
+                        // Put the one true definition as the first entry so it
+                        // matches first
+                        die_offsets.insert (die_offsets.begin(), die_info_array[i].offset);
+                    }
+                }
+                else
+                {
+                    die_offsets.push_back (die_info_array[i].offset);
+                }
+            }
+        }
+    }
+
+    static void
+    ExtractTypesFromDIEArray (const DIEInfoArray &die_info_array,
+                              uint32_t type_flag_mask,
+                              uint32_t type_flag_value,
+                              DIEArray &die_offsets)
+    {
+        const size_t count = die_info_array.size();
+        for (size_t i=0; i<count; ++i)
+        {
+            if ((die_info_array[i].type_flags & type_flag_mask) == type_flag_value)
+                die_offsets.push_back (die_info_array[i].offset);
+        }
+    }
+
+    struct Atom
+    {
+        uint16_t type;
+        dw_form_t form;
+        
+        Atom (uint16_t t = eAtomTypeNULL, dw_form_t f = 0) :
+            type (t),
+            form (f)
+        {
+        }
+    };
+    
+    typedef std::vector<Atom> AtomArray;
+    
+    static uint32_t 
+    GetTypeFlags (SymbolFileDWARF *dwarf2Data,
+                  const DWARFCompileUnit* cu,
+                  const DWARFDebugInfoEntry* die);
+    
+
+    static const char *
+    GetAtomTypeName (uint16_t atom)
+    {
+        switch (atom)
+        {
+            case eAtomTypeNULL:         return "NULL";
+            case eAtomTypeDIEOffset:    return "die-offset";
+            case eAtomTypeCUOffset:     return "cu-offset";
+            case eAtomTypeTag:          return "die-tag";
+            case eAtomTypeNameFlags:    return "name-flags";
+            case eAtomTypeTypeFlags:    return "type-flags";
+            case eAtomTypeQualNameHash: return "qualified-name-hash";
+        }
+        return "<invalid>";
+    }
+    struct Prologue
+    {
+        // DIE offset base so die offsets in hash_data can be CU relative
+        dw_offset_t die_base_offset;
+        AtomArray atoms;
+        uint32_t atom_mask;
+        size_t min_hash_data_byte_size;
+        bool hash_data_has_fixed_byte_size;
+        
+        Prologue (dw_offset_t _die_base_offset = 0) :
+            die_base_offset (_die_base_offset),
+            atoms(),
+            atom_mask (0),
+            min_hash_data_byte_size(0),
+            hash_data_has_fixed_byte_size(true)
+        {
+            // Define an array of DIE offsets by first defining an array, 
+            // and then define the atom type for the array, in this case
+            // we have an array of DIE offsets
+            AppendAtom (eAtomTypeDIEOffset, DW_FORM_data4);
+        }
+        
+        virtual ~Prologue()
+        {
+        }
+
+        void
+        ClearAtoms ()
+        {
+            hash_data_has_fixed_byte_size = true;
+            min_hash_data_byte_size = 0;
+            atom_mask = 0;
+            atoms.clear();
+        }
+
+        bool
+        ContainsAtom (AtomType atom_type) const
+        {
+            return (atom_mask & (1u << atom_type)) != 0;
+        }
+
+        virtual void
+        Clear ()
+        {
+            die_base_offset = 0;
+            ClearAtoms ();
+        }
+        
+        void
+        AppendAtom (AtomType type, dw_form_t form)
+        {
+            atoms.push_back (Atom(type, form));
+            atom_mask |= 1u << type;
+            switch (form)
+            {
+                case DW_FORM_indirect:
+                case DW_FORM_exprloc:
+                case DW_FORM_flag_present:
+                case DW_FORM_ref_sig8:
+                    assert (!"Unhandled atom form");
+                    break;
+
+                case DW_FORM_string:
+                case DW_FORM_block:
+                case DW_FORM_block1:
+                case DW_FORM_sdata:
+                case DW_FORM_udata:
+                case DW_FORM_ref_udata:
+                    hash_data_has_fixed_byte_size = false;
+                    // Fall through to the cases below...
+                case DW_FORM_flag:
+                case DW_FORM_data1:
+                case DW_FORM_ref1:
+                case DW_FORM_sec_offset:
+                    min_hash_data_byte_size += 1; 
+                    break;
+
+                case DW_FORM_block2:
+                    hash_data_has_fixed_byte_size = false;
+                    // Fall through to the cases below...
+                case DW_FORM_data2: 
+                case DW_FORM_ref2:
+                    min_hash_data_byte_size += 2; 
+                    break;
+
+                case DW_FORM_block4: 
+                    hash_data_has_fixed_byte_size = false;
+                    // Fall through to the cases below...
+                case DW_FORM_data4:
+                case DW_FORM_ref4:
+                case DW_FORM_addr:
+                case DW_FORM_ref_addr:
+                case DW_FORM_strp:
+                    min_hash_data_byte_size += 4; 
+                    break;
+
+                case DW_FORM_data8:
+                case DW_FORM_ref8:
+                    min_hash_data_byte_size += 8; 
+                    break;
+                    
+            }
+        }
+        
+//        void
+//        Dump (std::ostream* ostrm_ptr);        
+        
+        lldb::offset_t
+        Read (const lldb_private::DataExtractor &data,
+              lldb::offset_t offset)
+        {
+            ClearAtoms ();
+            
+            die_base_offset = data.GetU32 (&offset);
+            
+            const uint32_t atom_count = data.GetU32 (&offset);
+            if (atom_count == 0x00060003u)
+            {
+                // Old format, deal with contents of old pre-release format
+                while (data.GetU32(&offset))
+                    /* do nothing */;
+
+                // Hardcode to the only known value for now.
+                AppendAtom (eAtomTypeDIEOffset, DW_FORM_data4);
+            }
+            else
+            {
+                for (uint32_t i=0; i<atom_count; ++i)
+                {
+                    AtomType type = (AtomType)data.GetU16 (&offset);
+                    dw_form_t form = (dw_form_t)data.GetU16 (&offset);                    
+                    AppendAtom (type, form);
+                }
+            }
+            return offset;
+        }
+        
+//        virtual void
+//        Write (BinaryStreamBuf &s);
+        
+        size_t
+        GetByteSize () const
+        {
+            // Add an extra count to the atoms size for the zero termination Atom that gets
+            // written to disk
+            return sizeof(die_base_offset) + sizeof(uint32_t) + atoms.size() * sizeof(Atom);
+        }
+        
+        size_t
+        GetMinumumHashDataByteSize () const
+        {
+            return min_hash_data_byte_size;
+        }
+
+        bool
+        HashDataHasFixedByteSize() const
+        {
+            return hash_data_has_fixed_byte_size;
+        }
+    };
+    
+    struct Header : public MappedHash::Header<Prologue>
+    {
+        Header (dw_offset_t _die_base_offset = 0)
+        {
+        }
+        
+        virtual 
+        ~Header()
+        {
+        }
+
+        virtual size_t
+        GetByteSize (const HeaderData &header_data)
+        {
+            return header_data.GetByteSize();
+        }
+
+        //        virtual void
+        //        Dump (std::ostream* ostrm_ptr);        
+        //        
+        virtual lldb::offset_t
+        Read (lldb_private::DataExtractor &data, lldb::offset_t offset)
+        {
+            offset = MappedHash::Header<Prologue>::Read (data, offset);
+            if (offset != UINT32_MAX)
+            {
+                offset = header_data.Read (data, offset);
+            }
+            return offset;
+        }
+        
+        bool
+        Read (const lldb_private::DataExtractor &data, 
+              lldb::offset_t *offset_ptr, 
+              DIEInfo &hash_data) const
+        {
+            const size_t num_atoms = header_data.atoms.size();
+            if (num_atoms == 0)
+                return false;
+            
+            for (size_t i=0; i<num_atoms; ++i)
+            {
+                DWARFFormValue form_value (header_data.atoms[i].form);
+                
+                if (!form_value.ExtractValue(data, offset_ptr, NULL))
+                    return false;
+                
+                switch (header_data.atoms[i].type)
+                {
+                    case eAtomTypeDIEOffset:    // DIE offset, check form for encoding
+                        hash_data.offset = (dw_offset_t)form_value.Reference (header_data.die_base_offset);
+                        break;
+
+                    case eAtomTypeTag:          // DW_TAG value for the DIE
+                        hash_data.tag = (dw_tag_t)form_value.Unsigned ();
+                        
+                    case eAtomTypeTypeFlags:    // Flags from enum TypeFlags
+                        hash_data.type_flags = (uint32_t)form_value.Unsigned ();
+                        break;
+
+                    case eAtomTypeQualNameHash:    // Flags from enum TypeFlags
+                        hash_data.qualified_name_hash = form_value.Unsigned ();
+                        break;
+
+                    default:
+                        // We can always skip atomes we don't know about
+                        break;
+                }
+            }
+            return true;
+        }
+        
+        void
+        Dump (lldb_private::Stream& strm, const DIEInfo &hash_data) const
+        {
+            const size_t num_atoms = header_data.atoms.size();
+            for (size_t i=0; i<num_atoms; ++i)
+            {
+                if (i > 0)
+                    strm.PutCString (", ");
+                
+                DWARFFormValue form_value (header_data.atoms[i].form);
+                switch (header_data.atoms[i].type)
+                {
+                    case eAtomTypeDIEOffset:    // DIE offset, check form for encoding
+                        strm.Printf ("{0x%8.8x}", hash_data.offset);
+                        break;
+
+                    case eAtomTypeTag:          // DW_TAG value for the DIE
+                        {
+                            const char *tag_cstr = lldb_private::DW_TAG_value_to_name (hash_data.tag);
+                            if (tag_cstr)
+                                strm.PutCString (tag_cstr);
+                            else
+                                strm.Printf ("DW_TAG_(0x%4.4x)", hash_data.tag);
+                        }
+                        break;
+
+                    case eAtomTypeTypeFlags:    // Flags from enum TypeFlags
+                        strm.Printf ("0x%2.2x", hash_data.type_flags);
+                        if (hash_data.type_flags)
+                        {
+                            strm.PutCString (" (");
+                            if (hash_data.type_flags & eTypeFlagClassIsImplementation)
+                                strm.PutCString (" implementation");
+                            strm.PutCString (" )");
+                        }
+                        break;
+
+                    case eAtomTypeQualNameHash:    // Flags from enum TypeFlags
+                        strm.Printf ("0x%8.8x", hash_data.qualified_name_hash);
+                        break;
+
+                    default:
+                        strm.Printf ("AtomType(0x%x)", header_data.atoms[i].type);
+                        break;
+                }
+            }
+        }
+    };
+    
+//    class ExportTable
+//    {
+//    public:
+//        ExportTable ();
+//        
+//        void
+//        AppendNames (DWARFDebugPubnamesSet &pubnames_set,
+//                     StringTable &string_table);
+//        
+//        void
+//        AppendNamesEntry (SymbolFileDWARF *dwarf2Data,
+//                          const DWARFCompileUnit* cu,
+//                          const DWARFDebugInfoEntry* die,
+//                          StringTable &string_table);
+//        
+//        void
+//        AppendTypesEntry (DWARFData *dwarf2Data,
+//                          const DWARFCompileUnit* cu,
+//                          const DWARFDebugInfoEntry* die,
+//                          StringTable &string_table);
+//        
+//        size_t
+//        Save (BinaryStreamBuf &names_data, const StringTable &string_table);
+//        
+//        void
+//        AppendName (const char *name, 
+//                    uint32_t die_offset, 
+//                    StringTable &string_table,
+//                    dw_offset_t name_debug_str_offset = DW_INVALID_OFFSET); // If "name" has already been looked up, then it can be supplied
+//        void
+//        AppendType (const char *name, 
+//                    uint32_t die_offset, 
+//                    StringTable &string_table);
+//        
+//        
+//    protected:
+//        struct Entry
+//        {
+//            uint32_t hash;
+//            uint32_t str_offset;
+//            uint32_t die_offset;
+//        };
+//        
+//        // Map uniqued .debug_str offset to the corresponding DIE offsets
+//        typedef std::map<uint32_t, DIEInfoArray> NameInfo;
+//        // Map a name hash to one or more name infos
+//        typedef std::map<uint32_t, NameInfo> BucketEntry;
+//        
+//        static uint32_t
+//        GetByteSize (const NameInfo &name_info);
+//        
+//        typedef std::vector<BucketEntry> BucketEntryColl;
+//        typedef std::vector<Entry> EntryColl;
+//        EntryColl m_entries;
+//        
+//    };
+    
+    
+    // A class for reading and using a saved hash table from a block of data
+    // in memory
+    class MemoryTable : public MappedHash::MemoryTable<uint32_t, DWARFMappedHash::Header, DIEInfoArray>
+    {
+    public:
+        
+        MemoryTable (lldb_private::DataExtractor &table_data, 
+                     const lldb_private::DataExtractor &string_table,
+                     const char *name) :
+            MappedHash::MemoryTable<uint32_t, Header, DIEInfoArray> (table_data),
+            m_data (table_data),
+            m_string_table (string_table),
+            m_name (name)
+        {
+        }
+    
+        virtual 
+        ~MemoryTable ()
+        {
+        }
+
+        virtual const char *
+        GetStringForKeyType (KeyType key) const
+        {
+            // The key in the DWARF table is the .debug_str offset for the string
+            return m_string_table.PeekCStr (key);
+        }
+        
+        virtual bool
+        ReadHashData (uint32_t hash_data_offset,
+                      HashData &hash_data) const
+        {
+            lldb::offset_t offset = hash_data_offset;
+            offset += 4; // Skip string table offset that contains offset of hash name in .debug_str
+            const uint32_t count = m_data.GetU32 (&offset);
+            if (count > 0)
+            {
+                hash_data.resize(count);
+                for (uint32_t i=0; i<count; ++i)
+                {
+                    if (!m_header.Read(m_data, &offset, hash_data[i]))
+                        return false;
+                }
+            }
+            else
+                hash_data.clear();
+            return true;
+        }
+
+        virtual Result
+        GetHashDataForName (const char *name,
+                            lldb::offset_t* hash_data_offset_ptr,
+                            Pair &pair) const
+        {
+            pair.key = m_data.GetU32 (hash_data_offset_ptr);
+            pair.value.clear();
+
+            // If the key is zero, this terminates our chain of HashData objects
+            // for this hash value.
+            if (pair.key == 0)
+                return eResultEndOfHashData;
+
+            // There definitely should be a string for this string offset, if
+            // there isn't, there is something wrong, return and error
+            const char *strp_cstr = m_string_table.PeekCStr (pair.key);
+            if (strp_cstr == NULL)
+            {
+                *hash_data_offset_ptr = UINT32_MAX;
+                return eResultError;
+            }
+
+            const uint32_t count = m_data.GetU32 (hash_data_offset_ptr);
+            const size_t min_total_hash_data_size = count * m_header.header_data.GetMinumumHashDataByteSize();
+            if (count > 0 && m_data.ValidOffsetForDataOfSize (*hash_data_offset_ptr, min_total_hash_data_size))
+            {
+                // We have at least one HashData entry, and we have enough
+                // data to parse at leats "count" HashData enties.
+                
+                // First make sure the entire C string matches...
+                const bool match = strcmp (name, strp_cstr) == 0;
+                
+                if (!match && m_header.header_data.HashDataHasFixedByteSize())
+                {
+                    // If the string doesn't match and we have fixed size data,
+                    // we can just add the total byte size of all HashData objects
+                    // to the hash data offset and be done...
+                    *hash_data_offset_ptr += min_total_hash_data_size;
+                }
+                else
+                {
+                    // If the string does match, or we don't have fixed size data
+                    // then we need to read the hash data as a stream. If the
+                    // string matches we also append all HashData objects to the
+                    // value array.
+                    for (uint32_t i=0; i<count; ++i)
+                    {
+                        DIEInfo die_info;
+                        if (m_header.Read(m_data, hash_data_offset_ptr, die_info))
+                        {
+                            // Only happend the HashData if the string matched...
+                            if (match)
+                                pair.value.push_back (die_info);
+                        }
+                        else
+                        {
+                            // Something went wrong while reading the data
+                            *hash_data_offset_ptr = UINT32_MAX;
+                            return eResultError;
+                        }
+                    }
+                }
+                // Return the correct response depending on if the string matched
+                // or not...
+                if (match)
+                    return eResultKeyMatch;     // The key (cstring) matches and we have lookup results!
+                else
+                    return eResultKeyMismatch;  // The key doesn't match, this function will get called 
+                                                // again for the next key/value or the key terminator
+                                                // which in our case is a zero .debug_str offset.
+            }
+            else
+            {
+                *hash_data_offset_ptr = UINT32_MAX;
+                return eResultError;
+            }
+        }
+
+        virtual Result
+        AppendHashDataForRegularExpression (const lldb_private::RegularExpression& regex,
+                                            lldb::offset_t* hash_data_offset_ptr, 
+                                            Pair &pair) const
+        {
+            pair.key = m_data.GetU32 (hash_data_offset_ptr);
+            // If the key is zero, this terminates our chain of HashData objects
+            // for this hash value.
+            if (pair.key == 0)
+                return eResultEndOfHashData;
+            
+            // There definitely should be a string for this string offset, if
+            // there isn't, there is something wrong, return and error
+            const char *strp_cstr = m_string_table.PeekCStr (pair.key);
+            if (strp_cstr == NULL)
+                return eResultError;
+            
+            const uint32_t count = m_data.GetU32 (hash_data_offset_ptr);
+            const size_t min_total_hash_data_size = count * m_header.header_data.GetMinumumHashDataByteSize();
+            if (count > 0 && m_data.ValidOffsetForDataOfSize (*hash_data_offset_ptr, min_total_hash_data_size))
+            {
+                const bool match = regex.Execute(strp_cstr);
+                
+                if (!match && m_header.header_data.HashDataHasFixedByteSize())
+                {
+                    // If the regex doesn't match and we have fixed size data,
+                    // we can just add the total byte size of all HashData objects
+                    // to the hash data offset and be done...
+                    *hash_data_offset_ptr += min_total_hash_data_size;
+                }
+                else
+                {
+                    // If the string does match, or we don't have fixed size data
+                    // then we need to read the hash data as a stream. If the
+                    // string matches we also append all HashData objects to the
+                    // value array.
+                    for (uint32_t i=0; i<count; ++i)
+                    {
+                        DIEInfo die_info;
+                        if (m_header.Read(m_data, hash_data_offset_ptr, die_info))
+                        {
+                            // Only happend the HashData if the string matched...
+                            if (match)
+                                pair.value.push_back (die_info);
+                        }
+                        else
+                        {
+                            // Something went wrong while reading the data
+                            *hash_data_offset_ptr = UINT32_MAX;
+                            return eResultError;
+                        }
+                    }
+                }
+                // Return the correct response depending on if the string matched
+                // or not...
+                if (match)
+                    return eResultKeyMatch;     // The key (cstring) matches and we have lookup results!
+                else
+                    return eResultKeyMismatch;  // The key doesn't match, this function will get called 
+                                                // again for the next key/value or the key terminator
+                                                // which in our case is a zero .debug_str offset.
+            }
+            else
+            {
+                *hash_data_offset_ptr = UINT32_MAX;
+                return eResultError;
+            }
+        }
+
+        size_t
+        AppendAllDIEsThatMatchingRegex (const lldb_private::RegularExpression& regex, 
+                                        DIEInfoArray &die_info_array) const
+        {
+            const uint32_t hash_count = m_header.hashes_count;
+            Pair pair;
+            for (uint32_t offset_idx=0; offset_idx<hash_count; ++offset_idx)
+            {
+                lldb::offset_t hash_data_offset = GetHashDataOffset (offset_idx);
+                while (hash_data_offset != UINT32_MAX)
+                {
+                    const lldb::offset_t prev_hash_data_offset = hash_data_offset;
+                    Result hash_result = AppendHashDataForRegularExpression (regex, &hash_data_offset, pair);
+                    if (prev_hash_data_offset == hash_data_offset)
+                        break;
+
+                    // Check the result of getting our hash data
+                    switch (hash_result)
+                    {
+                        case eResultKeyMatch:
+                        case eResultKeyMismatch:
+                            // Whether we matches or not, it doesn't matter, we
+                            // keep looking.
+                            break;
+                            
+                        case eResultEndOfHashData:
+                        case eResultError:
+                            hash_data_offset = UINT32_MAX;
+                            break;
+                    }
+                }
+            }
+            die_info_array.swap (pair.value);
+            return die_info_array.size();
+        }
+        
+        size_t
+        AppendAllDIEsInRange (const uint32_t die_offset_start, 
+                              const uint32_t die_offset_end, 
+                              DIEInfoArray &die_info_array) const
+        {
+            const uint32_t hash_count = m_header.hashes_count;
+            for (uint32_t offset_idx=0; offset_idx<hash_count; ++offset_idx)
+            {
+                bool done = false;
+                lldb::offset_t hash_data_offset = GetHashDataOffset (offset_idx);
+                while (!done && hash_data_offset != UINT32_MAX)
+                {
+                    KeyType key = m_data.GetU32 (&hash_data_offset);
+                    // If the key is zero, this terminates our chain of HashData objects
+                    // for this hash value.
+                    if (key == 0)
+                        break;
+                    
+                    const uint32_t count = m_data.GetU32 (&hash_data_offset);
+                    for (uint32_t i=0; i<count; ++i)
+                    {
+                        DIEInfo die_info;
+                        if (m_header.Read(m_data, &hash_data_offset, die_info))
+                        {
+                            if (die_info.offset == 0)
+                                done = true;
+                            if (die_offset_start <= die_info.offset && die_info.offset < die_offset_end)
+                                die_info_array.push_back(die_info);
+                        }
+                    }
+                }
+            }
+            return die_info_array.size();
+        }
+
+        size_t
+        FindByName (const char *name, DIEArray &die_offsets)
+        {
+            DIEInfoArray die_info_array;
+            if (FindByName(name, die_info_array))
+                DWARFMappedHash::ExtractDIEArray (die_info_array, die_offsets);
+            return die_info_array.size();
+        }
+
+        size_t
+        FindByNameAndTag (const char *name, 
+                          const dw_tag_t tag, 
+                          DIEArray &die_offsets)
+        {
+            DIEInfoArray die_info_array;
+            if (FindByName(name, die_info_array))
+                DWARFMappedHash::ExtractDIEArray (die_info_array, tag, die_offsets);
+            return die_info_array.size();
+        }
+
+        size_t
+        FindByNameAndTagAndQualifiedNameHash (const char *name,
+                                              const dw_tag_t tag,
+                                              const uint32_t qualified_name_hash,
+                                              DIEArray &die_offsets)
+        {
+            DIEInfoArray die_info_array;
+            if (FindByName(name, die_info_array))
+                DWARFMappedHash::ExtractDIEArray (die_info_array, tag, qualified_name_hash, die_offsets);
+            return die_info_array.size();
+        }
+
+        size_t
+        FindCompleteObjCClassByName (const char *name, DIEArray &die_offsets, bool must_be_implementation)
+        {
+            DIEInfoArray die_info_array;
+            if (FindByName(name, die_info_array))
+            {
+                if (must_be_implementation && GetHeader().header_data.ContainsAtom (eAtomTypeTypeFlags))
+                {
+                    // If we have two atoms, then we have the DIE offset and
+                    // the type flags so we can find the objective C class
+                    // efficiently.
+                    DWARFMappedHash::ExtractTypesFromDIEArray (die_info_array, 
+                                                               UINT32_MAX,
+                                                               eTypeFlagClassIsImplementation,
+                                                               die_offsets);
+                }
+                else
+                {
+                    // We don't only want the one true definition, so try and see
+                    // what we can find, and only return class or struct DIEs.
+                    // If we do have the full implementation, then return it alone,
+                    // else return all possible matches.
+                    const bool return_implementation_only_if_available = true;
+                    DWARFMappedHash::ExtractClassOrStructDIEArray (die_info_array, 
+                                                                   return_implementation_only_if_available,
+                                                                   die_offsets);
+                }
+            }
+            return die_offsets.size();
+        }
+
+        size_t 
+        FindByName (const char *name, DIEInfoArray &die_info_array)
+        {
+            Pair kv_pair;
+            size_t old_size = die_info_array.size();
+            if (Find (name, kv_pair))
+            {
+                die_info_array.swap(kv_pair.value);
+                return die_info_array.size() - old_size;
+            }
+            return 0;
+        }
+        
+    protected:
+        const lldb_private::DataExtractor &m_data;
+        const lldb_private::DataExtractor &m_string_table;
+        std::string m_name;
+    };
+};
+
+
+#endif  // SymbolFileDWARF_HashedNameToDIE_h_
diff --git a/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.cpp b/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.cpp
new file mode 100644
index 000000000000..27fa261813bb
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.cpp
@@ -0,0 +1,232 @@
+//===-- LogChannelDWARF.cpp ------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "LogChannelDWARF.h"
+
+#include "lldb/Interpreter/Args.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/StreamFile.h"
+#include "SymbolFileDWARF.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+// when the one and only logging channel is abled, then this will be non NULL.
+static LogChannelDWARF* g_log_channel = NULL;
+
+LogChannelDWARF::LogChannelDWARF () :
+    LogChannel ()
+{
+}
+
+LogChannelDWARF::~LogChannelDWARF ()
+{
+}
+
+
+void
+LogChannelDWARF::Initialize()
+{
+    PluginManager::RegisterPlugin (GetPluginNameStatic(),
+                                   GetPluginDescriptionStatic(),
+                                   LogChannelDWARF::CreateInstance);
+}
+
+void
+LogChannelDWARF::Terminate()
+{
+    PluginManager::UnregisterPlugin (LogChannelDWARF::CreateInstance);
+}
+
+LogChannel*
+LogChannelDWARF::CreateInstance ()
+{
+    return new LogChannelDWARF ();
+}
+
+lldb_private::ConstString
+LogChannelDWARF::GetPluginNameStatic()
+{
+    return SymbolFileDWARF::GetPluginNameStatic();
+}
+
+const char *
+LogChannelDWARF::GetPluginDescriptionStatic()
+{
+    return "DWARF log channel for debugging plug-in issues.";
+}
+
+lldb_private::ConstString
+LogChannelDWARF::GetPluginName()
+{
+    return GetPluginNameStatic();
+}
+
+uint32_t
+LogChannelDWARF::GetPluginVersion()
+{
+    return 1;
+}
+
+
+void
+LogChannelDWARF::Delete ()
+{
+    g_log_channel = NULL;
+}
+
+
+void
+LogChannelDWARF::Disable (const char **categories, Stream *feedback_strm)
+{
+    if (m_log_ap.get() == NULL)
+        return;
+
+    uint32_t flag_bits = m_log_ap->GetMask().Get();
+    for (size_t i = 0; categories[i] != NULL; ++i)
+    {
+         const char *arg = categories[i];
+
+        if      (::strcasecmp (arg, "all")        == 0) flag_bits &= ~DWARF_LOG_ALL;
+        else if (::strcasecmp (arg, "info")       == 0) flag_bits &= ~DWARF_LOG_DEBUG_INFO;
+        else if (::strcasecmp (arg, "line")       == 0) flag_bits &= ~DWARF_LOG_DEBUG_LINE;
+        else if (::strcasecmp (arg, "pubnames")   == 0) flag_bits &= ~DWARF_LOG_DEBUG_PUBNAMES;
+        else if (::strcasecmp (arg, "pubtypes")   == 0) flag_bits &= ~DWARF_LOG_DEBUG_PUBTYPES;
+        else if (::strcasecmp (arg, "aranges")    == 0) flag_bits &= ~DWARF_LOG_DEBUG_ARANGES;
+        else if (::strcasecmp (arg, "lookups")    == 0) flag_bits &= ~DWARF_LOG_LOOKUPS;
+        else if (::strcasecmp (arg, "map")        == 0) flag_bits &= ~DWARF_LOG_DEBUG_MAP;
+        else if (::strcasecmp (arg, "default")    == 0) flag_bits &= ~DWARF_LOG_DEFAULT;
+        else if (::strncasecmp(arg, "comp", 4)    == 0) flag_bits &= ~DWARF_LOG_TYPE_COMPLETION;
+        else
+        {
+            feedback_strm->Printf("error: unrecognized log category '%s'\n", arg);
+            ListCategories (feedback_strm);
+        }
+   }
+    
+    if (flag_bits == 0)
+        Delete ();
+    else
+        m_log_ap->GetMask().Reset (flag_bits);
+
+    return;
+}
+
+bool
+LogChannelDWARF::Enable
+(
+    StreamSP &log_stream_sp,
+    uint32_t log_options,
+    Stream *feedback_strm,  // Feedback stream for argument errors etc
+    const char **categories  // The categories to enable within this logging stream, if empty, enable default set
+)
+{
+    Delete ();
+
+    if (m_log_ap)
+        m_log_ap->SetStream(log_stream_sp);
+    else
+        m_log_ap.reset(new Log (log_stream_sp));
+    
+    g_log_channel = this;
+    uint32_t flag_bits = 0;
+    bool got_unknown_category = false;
+    for (size_t i = 0; categories[i] != NULL; ++i)
+    {
+        const char *arg = categories[i];
+
+        if      (::strcasecmp (arg, "all")        == 0) flag_bits |= DWARF_LOG_ALL;
+        else if (::strcasecmp (arg, "info")       == 0) flag_bits |= DWARF_LOG_DEBUG_INFO;
+        else if (::strcasecmp (arg, "line")       == 0) flag_bits |= DWARF_LOG_DEBUG_LINE;
+        else if (::strcasecmp (arg, "pubnames")   == 0) flag_bits |= DWARF_LOG_DEBUG_PUBNAMES;
+        else if (::strcasecmp (arg, "pubtypes")   == 0) flag_bits |= DWARF_LOG_DEBUG_PUBTYPES;
+        else if (::strcasecmp (arg, "aranges")    == 0) flag_bits |= DWARF_LOG_DEBUG_ARANGES;
+        else if (::strcasecmp (arg, "lookups")    == 0) flag_bits |= DWARF_LOG_LOOKUPS;
+        else if (::strcasecmp (arg, "map")        == 0) flag_bits |= DWARF_LOG_DEBUG_MAP;
+        else if (::strcasecmp (arg, "default")    == 0) flag_bits |= DWARF_LOG_DEFAULT;
+        else if (::strncasecmp(arg, "comp", 4)    == 0) flag_bits |= DWARF_LOG_TYPE_COMPLETION;
+        else
+        {
+            feedback_strm->Printf("error: unrecognized log category '%s'\n", arg);
+            if (got_unknown_category == false)
+            {
+                got_unknown_category = true;
+                ListCategories (feedback_strm);
+            }
+        }
+    }
+    if (flag_bits == 0)
+        flag_bits = DWARF_LOG_DEFAULT;
+    m_log_ap->GetMask().Reset(flag_bits);
+    m_log_ap->GetOptions().Reset(log_options);
+    return m_log_ap.get() != NULL;
+}
+
+void
+LogChannelDWARF::ListCategories (Stream *strm)
+{
+    strm->Printf ("Logging categories for '%s':\n"
+                  "  all - turn on all available logging categories\n"
+                  "  info - log the parsing if .debug_info\n"
+                  "  line - log the parsing if .debug_line\n"
+                  "  pubnames - log the parsing if .debug_pubnames\n"
+                  "  pubtypes - log the parsing if .debug_pubtypes\n"
+                  "  lookups - log any lookups that happen by name, regex, or address\n"
+                  "  completion - log struct/unions/class type completions\n"
+                  "  map - log insertions of object files into DWARF debug maps\n",
+                  SymbolFileDWARF::GetPluginNameStatic().GetCString());
+}
+
+Log *
+LogChannelDWARF::GetLog ()
+{
+    if (g_log_channel)
+        return g_log_channel->m_log_ap.get();
+
+    return NULL;
+}
+
+Log *
+LogChannelDWARF::GetLogIfAll (uint32_t mask)
+{
+    if (g_log_channel && g_log_channel->m_log_ap.get())
+    {
+        if (g_log_channel->m_log_ap->GetMask().AllSet(mask))
+            return g_log_channel->m_log_ap.get();
+    }
+    return NULL;
+}
+
+Log *
+LogChannelDWARF::GetLogIfAny (uint32_t mask)
+{
+    if (g_log_channel && g_log_channel->m_log_ap.get())
+    {
+        if (g_log_channel->m_log_ap->GetMask().AnySet(mask))
+            return g_log_channel->m_log_ap.get();
+    }
+    return NULL;
+}
+
+void
+LogChannelDWARF::LogIf (uint32_t mask, const char *format, ...)
+{
+    if (g_log_channel)
+    {
+        Log *log = g_log_channel->m_log_ap.get();
+        if (log && log->GetMask().AnySet(mask))
+        {
+            va_list args;
+            va_start (args, format);
+            log->VAPrintf (format, args);
+            va_end (args);
+        }
+    }
+}
diff --git a/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h b/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h
new file mode 100644
index 000000000000..2091a8414f58
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/LogChannelDWARF.h
@@ -0,0 +1,89 @@
+//===-- LogChannelDWARF.h --------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SymbolFileDWARF_LogChannelDWARF_h_
+#define SymbolFileDWARF_LogChannelDWARF_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+
+// Project includes
+#include "lldb/Core/Log.h"
+
+#define DWARF_LOG_VERBOSE           (1u << 0)
+#define DWARF_LOG_DEBUG_INFO        (1u << 1)
+#define DWARF_LOG_DEBUG_LINE        (1u << 2)
+#define DWARF_LOG_DEBUG_PUBNAMES    (1u << 3)
+#define DWARF_LOG_DEBUG_PUBTYPES    (1u << 4)
+#define DWARF_LOG_DEBUG_ARANGES     (1u << 5)
+#define DWARF_LOG_LOOKUPS           (1u << 6)
+#define DWARF_LOG_TYPE_COMPLETION   (1u << 7)
+#define DWARF_LOG_DEBUG_MAP         (1u << 8)
+#define DWARF_LOG_ALL               (UINT32_MAX)
+#define DWARF_LOG_DEFAULT           (DWARF_LOG_DEBUG_INFO)
+
+class LogChannelDWARF : public lldb_private::LogChannel
+{
+public:
+    LogChannelDWARF ();
+
+    virtual
+    ~LogChannelDWARF ();
+
+    static void
+    Initialize();
+
+    static void
+    Terminate();
+
+    static lldb_private::ConstString
+    GetPluginNameStatic();
+
+    static const char *
+    GetPluginDescriptionStatic();
+
+    static lldb_private::LogChannel *
+    CreateInstance ();
+
+    virtual lldb_private::ConstString
+    GetPluginName();
+
+    virtual uint32_t
+    GetPluginVersion();
+
+    virtual void
+    Disable (const char** categories, lldb_private::Stream *feedback_strm);
+
+    void
+    Delete ();
+
+    virtual bool
+    Enable (lldb::StreamSP &log_stream_sp,
+            uint32_t log_options,
+            lldb_private::Stream *feedback_strm,      // Feedback stream for argument errors etc
+            const char **categories);    // The categories to enable within this logging stream, if empty, enable default set
+
+    virtual void
+    ListCategories (lldb_private::Stream *strm);
+
+    static lldb_private::Log *
+    GetLog ();
+
+    static lldb_private::Log *
+    GetLogIfAll (uint32_t mask);
+    
+    static lldb_private::Log *
+    GetLogIfAny (uint32_t mask);
+    
+    static void
+    LogIf (uint32_t mask, const char *format, ...);
+};
+
+#endif  // SymbolFileDWARF_LogChannelDWARF_h_
diff --git a/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp b/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp
new file mode 100644
index 000000000000..5514469d0758
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp
@@ -0,0 +1,87 @@
+//===-- NameToDIE.cpp -------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "NameToDIE.h"
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Core/RegularExpression.h"
+#include "lldb/Symbol/ObjectFile.h"
+
+#include "DWARFCompileUnit.h"
+#include "DWARFDebugInfo.h"
+#include "DWARFDebugInfoEntry.h"
+#include "SymbolFileDWARF.h"
+using namespace lldb;
+using namespace lldb_private;
+
+void
+NameToDIE::Finalize()
+{
+    m_map.Sort ();
+    m_map.SizeToFit ();
+}
+
+void
+NameToDIE::Insert (const ConstString& name, uint32_t die_offset)
+{
+    m_map.Append(name.GetCString(), die_offset);
+}
+
+size_t
+NameToDIE::Find (const ConstString &name, DIEArray &info_array) const
+{
+    return m_map.GetValues (name.GetCString(), info_array);
+}
+
+size_t
+NameToDIE::Find (const RegularExpression& regex, DIEArray &info_array) const
+{
+    return m_map.GetValues (regex, info_array);
+}
+
+size_t
+NameToDIE::FindAllEntriesForCompileUnit (uint32_t cu_offset, 
+                                         uint32_t cu_end_offset, 
+                                         DIEArray &info_array) const
+{
+    const size_t initial_size = info_array.size();
+    const uint32_t size = m_map.GetSize();
+    for (uint32_t i=0; i<size; ++i)
+    {
+        const uint32_t die_offset = m_map.GetValueAtIndexUnchecked(i);
+        if (cu_offset < die_offset && die_offset < cu_end_offset)
+            info_array.push_back (die_offset);
+    }
+    return info_array.size() - initial_size;
+}
+
+void
+NameToDIE::Dump (Stream *s)
+{
+    const uint32_t size = m_map.GetSize();
+    for (uint32_t i=0; i<size; ++i)
+    {
+        const char *cstr = m_map.GetCStringAtIndex(i);
+        s->Printf("%p: {0x%8.8x} \"%s\"\n", cstr, m_map.GetValueAtIndexUnchecked(i), cstr);
+    }
+}
+
+void
+NameToDIE::ForEach (std::function <bool(const char *name, uint32_t die_offset)> const &callback) const
+{
+    const uint32_t size = m_map.GetSize();
+    for (uint32_t i=0; i<size; ++i)
+    {
+        if (!callback(m_map.GetCStringAtIndexUnchecked(i),
+                      m_map.GetValueAtIndexUnchecked (i)))
+            break;
+    }
+}
diff --git a/source/Plugins/SymbolFile/DWARF/NameToDIE.h b/source/Plugins/SymbolFile/DWARF/NameToDIE.h
new file mode 100644
index 000000000000..f9a12736bf9e
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/NameToDIE.h
@@ -0,0 +1,65 @@
+//===-- NameToDIE.h ---------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SymbolFileDWARF_NameToDIE_h_
+#define SymbolFileDWARF_NameToDIE_h_
+
+#include "lldb/Core/UniqueCStringMap.h"
+
+#include <functional>
+
+#include "lldb/lldb-defines.h"
+
+class SymbolFileDWARF;
+
+typedef std::vector<uint32_t> DIEArray;
+
+class NameToDIE
+{
+public:
+    NameToDIE () :   
+        m_map()
+    {
+    }
+    
+    ~NameToDIE ()
+    {
+    }
+    
+    void
+    Dump (lldb_private::Stream *s);
+
+    void
+    Insert (const lldb_private::ConstString& name, uint32_t die_offset);
+
+    void
+    Finalize();
+
+    size_t
+    Find (const lldb_private::ConstString &name, 
+          DIEArray &info_array) const;
+    
+    size_t
+    Find (const lldb_private::RegularExpression& regex, 
+          DIEArray &info_array) const;
+
+    size_t
+    FindAllEntriesForCompileUnit (uint32_t cu_offset, 
+                                  uint32_t cu_end_offset, 
+                                  DIEArray &info_array) const;
+
+    void
+    ForEach (std::function <bool(const char *name, uint32_t die_offset)> const &callback) const;
+
+protected:
+    lldb_private::UniqueCStringMap<uint32_t> m_map;
+
+};
+
+#endif  // SymbolFileDWARF_NameToDIE_h_
diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
new file mode 100644
index 000000000000..f265af837eef
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -0,0 +1,7973 @@
+//===-- SymbolFileDWARF.cpp ------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SymbolFileDWARF.h"
+
+// Other libraries and framework includes
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclGroup.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/Basic/Builtins.h"
+#include "clang/Basic/IdentifierTable.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/Specifiers.h"
+#include "clang/Sema/DeclSpec.h"
+
+#include "llvm/Support/Casting.h"
+
+#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/RegularExpression.h"
+#include "lldb/Core/Scalar.h"
+#include "lldb/Core/Section.h"
+#include "lldb/Core/StreamFile.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Core/Timer.h"
+#include "lldb/Core/Value.h"
+
+#include "lldb/Host/Host.h"
+
+#include "lldb/Symbol/Block.h"
+#include "lldb/Symbol/ClangExternalASTSourceCallbacks.h"
+#include "lldb/Symbol/CompileUnit.h"
+#include "lldb/Symbol/LineTable.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/SymbolVendor.h"
+#include "lldb/Symbol/VariableList.h"
+
+#include "lldb/Target/ObjCLanguageRuntime.h"
+#include "lldb/Target/CPPLanguageRuntime.h"
+
+#include "DWARFCompileUnit.h"
+#include "DWARFDebugAbbrev.h"
+#include "DWARFDebugAranges.h"
+#include "DWARFDebugInfo.h"
+#include "DWARFDebugInfoEntry.h"
+#include "DWARFDebugLine.h"
+#include "DWARFDebugPubnames.h"
+#include "DWARFDebugRanges.h"
+#include "DWARFDeclContext.h"
+#include "DWARFDIECollection.h"
+#include "DWARFFormValue.h"
+#include "DWARFLocationList.h"
+#include "LogChannelDWARF.h"
+#include "SymbolFileDWARFDebugMap.h"
+
+#include <map>
+
+//#define ENABLE_DEBUG_PRINTF // COMMENT OUT THIS LINE PRIOR TO CHECKIN
+
+#ifdef ENABLE_DEBUG_PRINTF
+#include <stdio.h>
+#define DEBUG_PRINTF(fmt, ...) printf(fmt, ## __VA_ARGS__)
+#else
+#define DEBUG_PRINTF(fmt, ...)
+#endif
+
+#define DIE_IS_BEING_PARSED ((lldb_private::Type*)1)
+
+using namespace lldb;
+using namespace lldb_private;
+
+//static inline bool
+//child_requires_parent_class_union_or_struct_to_be_completed (dw_tag_t tag)
+//{
+//    switch (tag)
+//    {
+//    default:
+//        break;
+//    case DW_TAG_subprogram:
+//    case DW_TAG_inlined_subroutine:
+//    case DW_TAG_class_type:
+//    case DW_TAG_structure_type:
+//    case DW_TAG_union_type:
+//        return true;
+//    }
+//    return false;
+//}
+//
+static AccessType
+DW_ACCESS_to_AccessType (uint32_t dwarf_accessibility)
+{
+    switch (dwarf_accessibility)
+    {
+        case DW_ACCESS_public:      return eAccessPublic;
+        case DW_ACCESS_private:     return eAccessPrivate;
+        case DW_ACCESS_protected:   return eAccessProtected;
+        default:                    break;
+    }
+    return eAccessNone;
+}
+
+#if defined(LLDB_CONFIGURATION_DEBUG) or defined(LLDB_CONFIGURATION_RELEASE)
+
+class DIEStack
+{
+public:
+    
+    void Push (DWARFCompileUnit *cu, const DWARFDebugInfoEntry *die)
+    {
+        m_dies.push_back (DIEInfo(cu, die));
+    }
+
+    
+    void LogDIEs (Log *log, SymbolFileDWARF *dwarf)
+    {
+        StreamString log_strm;
+        const size_t n = m_dies.size();
+        log_strm.Printf("DIEStack[%" PRIu64 "]:\n", (uint64_t)n);
+        for (size_t i=0; i<n; i++)
+        {
+            DWARFCompileUnit *cu = m_dies[i].cu;
+            const DWARFDebugInfoEntry *die = m_dies[i].die;
+            std::string qualified_name;
+            die->GetQualifiedName(dwarf, cu, qualified_name);
+            log_strm.Printf ("[%" PRIu64 "] 0x%8.8x: %s name='%s'\n",
+                             (uint64_t)i,
+                             die->GetOffset(), 
+                             DW_TAG_value_to_name(die->Tag()), 
+                             qualified_name.c_str());
+        }
+        log->PutCString(log_strm.GetData());
+    }
+    void Pop ()
+    {
+        m_dies.pop_back();
+    }
+    
+    class ScopedPopper
+    {
+    public:
+        ScopedPopper (DIEStack &die_stack) :
+            m_die_stack (die_stack),
+            m_valid (false)
+        {
+        }
+        
+        void
+        Push (DWARFCompileUnit *cu, const DWARFDebugInfoEntry *die)
+        {
+            m_valid = true;
+            m_die_stack.Push (cu, die);
+        }
+        
+        ~ScopedPopper ()
+        {
+            if (m_valid)
+                m_die_stack.Pop();
+        }
+        
+        
+        
+    protected:
+        DIEStack &m_die_stack;
+        bool m_valid;
+    };
+
+protected:
+    struct DIEInfo {
+        DIEInfo (DWARFCompileUnit *c, const DWARFDebugInfoEntry *d) :
+            cu(c),
+            die(d)
+        {
+        }
+        DWARFCompileUnit *cu;
+        const DWARFDebugInfoEntry *die;
+    };
+    typedef std::vector<DIEInfo> Stack;
+    Stack m_dies;
+};
+#endif
+
+void
+SymbolFileDWARF::Initialize()
+{
+    LogChannelDWARF::Initialize();
+    PluginManager::RegisterPlugin (GetPluginNameStatic(),
+                                   GetPluginDescriptionStatic(),
+                                   CreateInstance);
+}
+
+void
+SymbolFileDWARF::Terminate()
+{
+    PluginManager::UnregisterPlugin (CreateInstance);
+    LogChannelDWARF::Initialize();
+}
+
+
+lldb_private::ConstString
+SymbolFileDWARF::GetPluginNameStatic()
+{
+    static ConstString g_name("dwarf");
+    return g_name;
+}
+
+const char *
+SymbolFileDWARF::GetPluginDescriptionStatic()
+{
+    return "DWARF and DWARF3 debug symbol file reader.";
+}
+
+
+SymbolFile*
+SymbolFileDWARF::CreateInstance (ObjectFile* obj_file)
+{
+    return new SymbolFileDWARF(obj_file);
+}
+
+TypeList *          
+SymbolFileDWARF::GetTypeList ()
+{
+    if (GetDebugMapSymfile ())
+        return m_debug_map_symfile->GetTypeList();
+    return m_obj_file->GetModule()->GetTypeList();
+
+}
+void
+SymbolFileDWARF::GetTypes (DWARFCompileUnit* cu,
+                           const DWARFDebugInfoEntry *die,
+                           dw_offset_t min_die_offset,
+                           dw_offset_t max_die_offset,
+                           uint32_t type_mask,
+                           TypeSet &type_set)
+{
+    if (cu)
+    {
+        if (die)
+        {
+            const dw_offset_t die_offset = die->GetOffset();
+            
+            if (die_offset >= max_die_offset)
+                return;
+            
+            if (die_offset >= min_die_offset)
+            {
+                const dw_tag_t tag = die->Tag();
+                
+                bool add_type = false;
+
+                switch (tag)
+                {
+                    case DW_TAG_array_type:         add_type = (type_mask & eTypeClassArray         ) != 0; break;
+                    case DW_TAG_unspecified_type:
+                    case DW_TAG_base_type:          add_type = (type_mask & eTypeClassBuiltin       ) != 0; break;
+                    case DW_TAG_class_type:         add_type = (type_mask & eTypeClassClass         ) != 0; break;
+                    case DW_TAG_structure_type:     add_type = (type_mask & eTypeClassStruct        ) != 0; break;
+                    case DW_TAG_union_type:         add_type = (type_mask & eTypeClassUnion         ) != 0; break;
+                    case DW_TAG_enumeration_type:   add_type = (type_mask & eTypeClassEnumeration   ) != 0; break;
+                    case DW_TAG_subroutine_type:
+                    case DW_TAG_subprogram:
+                    case DW_TAG_inlined_subroutine: add_type = (type_mask & eTypeClassFunction      ) != 0; break;
+                    case DW_TAG_pointer_type:       add_type = (type_mask & eTypeClassPointer       ) != 0; break;
+                    case DW_TAG_rvalue_reference_type:
+                    case DW_TAG_reference_type:     add_type = (type_mask & eTypeClassReference     ) != 0; break;
+                    case DW_TAG_typedef:            add_type = (type_mask & eTypeClassTypedef       ) != 0; break;
+                    case DW_TAG_ptr_to_member_type: add_type = (type_mask & eTypeClassMemberPointer ) != 0; break;
+                }
+
+                if (add_type)
+                {
+                    const bool assert_not_being_parsed = true;
+                    Type *type = ResolveTypeUID (cu, die, assert_not_being_parsed);
+                    if (type)
+                    {
+                        if (type_set.find(type) == type_set.end())
+                            type_set.insert(type);
+                    }
+                }
+            }
+            
+            for (const DWARFDebugInfoEntry *child_die = die->GetFirstChild();
+                 child_die != NULL;
+                 child_die = child_die->GetSibling())
+            {
+                GetTypes (cu, child_die, min_die_offset, max_die_offset, type_mask, type_set);
+            }
+        }
+    }
+}
+
+size_t
+SymbolFileDWARF::GetTypes (SymbolContextScope *sc_scope,
+                           uint32_t type_mask,
+                           TypeList &type_list)
+
+{
+    TypeSet type_set;
+    
+    CompileUnit *comp_unit = NULL;
+    DWARFCompileUnit* dwarf_cu = NULL;
+    if (sc_scope)
+        comp_unit = sc_scope->CalculateSymbolContextCompileUnit();
+
+    if (comp_unit)
+    {
+        dwarf_cu = GetDWARFCompileUnit(comp_unit);
+        if (dwarf_cu == 0)
+            return 0;
+        GetTypes (dwarf_cu,
+                  dwarf_cu->DIE(),
+                  dwarf_cu->GetOffset(),
+                  dwarf_cu->GetNextCompileUnitOffset(),
+                  type_mask,
+                  type_set);
+    }
+    else
+    {
+        DWARFDebugInfo* info = DebugInfo();
+        if (info)
+        {
+            const size_t num_cus = info->GetNumCompileUnits();
+            for (size_t cu_idx=0; cu_idx<num_cus; ++cu_idx)
+            {
+                dwarf_cu = info->GetCompileUnitAtIndex(cu_idx);
+                if (dwarf_cu)
+                {
+                    GetTypes (dwarf_cu,
+                              dwarf_cu->DIE(),
+                              0,
+                              UINT32_MAX,
+                              type_mask,
+                              type_set);
+                }
+            }
+        }
+    }
+//    if (m_using_apple_tables)
+//    {
+//        DWARFMappedHash::MemoryTable *apple_types = m_apple_types_ap.get();
+//        if (apple_types)
+//        {
+//            apple_types->ForEach([this, &type_set, apple_types, type_mask](const DWARFMappedHash::DIEInfoArray &die_info_array) -> bool {
+//
+//                for (auto die_info: die_info_array)
+//                {
+//                    bool add_type = TagMatchesTypeMask (type_mask, 0);
+//                    if (!add_type)
+//                    {
+//                        dw_tag_t tag = die_info.tag;
+//                        if (tag == 0)
+//                        {
+//                            const DWARFDebugInfoEntry *die = DebugInfo()->GetDIEPtr(die_info.offset, NULL);
+//                            tag = die->Tag();
+//                        }
+//                        add_type = TagMatchesTypeMask (type_mask, tag);
+//                    }
+//                    if (add_type)
+//                    {
+//                        Type *type = ResolveTypeUID(die_info.offset);
+//                        
+//                        if (type_set.find(type) == type_set.end())
+//                            type_set.insert(type);
+//                    }
+//                }
+//                return true; // Keep iterating
+//            });
+//        }
+//    }
+//    else
+//    {
+//        if (!m_indexed)
+//            Index ();
+//        
+//        m_type_index.ForEach([this, &type_set, type_mask](const char *name, uint32_t die_offset) -> bool {
+//            
+//            bool add_type = TagMatchesTypeMask (type_mask, 0);
+//
+//            if (!add_type)
+//            {
+//                const DWARFDebugInfoEntry *die = DebugInfo()->GetDIEPtr(die_offset, NULL);
+//                if (die)
+//                {
+//                    const dw_tag_t tag = die->Tag();
+//                    add_type = TagMatchesTypeMask (type_mask, tag);
+//                }
+//            }
+//            
+//            if (add_type)
+//            {
+//                Type *type = ResolveTypeUID(die_offset);
+//                
+//                if (type_set.find(type) == type_set.end())
+//                    type_set.insert(type);
+//            }
+//            return true; // Keep iterating
+//        });
+//    }
+    
+    std::set<ClangASTType> clang_type_set;
+    size_t num_types_added = 0;
+    for (Type *type : type_set)
+    {
+        ClangASTType clang_type = type->GetClangForwardType();
+        if (clang_type_set.find(clang_type) == clang_type_set.end())
+        {
+            clang_type_set.insert(clang_type);
+            type_list.Insert (type->shared_from_this());
+            ++num_types_added;
+        }
+    }
+    return num_types_added;
+}
+
+
+//----------------------------------------------------------------------
+// Gets the first parent that is a lexical block, function or inlined
+// subroutine, or compile unit.
+//----------------------------------------------------------------------
+static const DWARFDebugInfoEntry *
+GetParentSymbolContextDIE(const DWARFDebugInfoEntry *child_die)
+{
+    const DWARFDebugInfoEntry *die;
+    for (die = child_die->GetParent(); die != NULL; die = die->GetParent())
+    {
+        dw_tag_t tag = die->Tag();
+
+        switch (tag)
+        {
+        case DW_TAG_compile_unit:
+        case DW_TAG_subprogram:
+        case DW_TAG_inlined_subroutine:
+        case DW_TAG_lexical_block:
+            return die;
+        }
+    }
+    return NULL;
+}
+
+
+SymbolFileDWARF::SymbolFileDWARF(ObjectFile* objfile) :
+    SymbolFile (objfile),
+    UserID (0),  // Used by SymbolFileDWARFDebugMap to when this class parses .o files to contain the .o file index/ID
+    m_debug_map_module_wp (),
+    m_debug_map_symfile (NULL),
+    m_clang_tu_decl (NULL),
+    m_flags(),
+    m_data_debug_abbrev (),
+    m_data_debug_aranges (),
+    m_data_debug_frame (),
+    m_data_debug_info (),
+    m_data_debug_line (),
+    m_data_debug_loc (),
+    m_data_debug_ranges (),
+    m_data_debug_str (),
+    m_data_apple_names (),
+    m_data_apple_types (),
+    m_data_apple_namespaces (),
+    m_abbr(),
+    m_info(),
+    m_line(),
+    m_apple_names_ap (),
+    m_apple_types_ap (),
+    m_apple_namespaces_ap (),
+    m_apple_objc_ap (),
+    m_function_basename_index(),
+    m_function_fullname_index(),
+    m_function_method_index(),
+    m_function_selector_index(),
+    m_objc_class_selectors_index(),
+    m_global_index(),
+    m_type_index(),
+    m_namespace_index(),
+    m_indexed (false),
+    m_is_external_ast_source (false),
+    m_using_apple_tables (false),
+    m_supports_DW_AT_APPLE_objc_complete_type (eLazyBoolCalculate),
+    m_ranges(),
+    m_unique_ast_type_map ()
+{
+}
+
+SymbolFileDWARF::~SymbolFileDWARF()
+{
+    if (m_is_external_ast_source)
+    {
+        ModuleSP module_sp (m_obj_file->GetModule());
+        if (module_sp)
+            module_sp->GetClangASTContext().RemoveExternalSource ();
+    }
+}
+
+static const ConstString &
+GetDWARFMachOSegmentName ()
+{
+    static ConstString g_dwarf_section_name ("__DWARF");
+    return g_dwarf_section_name;
+}
+
+UniqueDWARFASTTypeMap &
+SymbolFileDWARF::GetUniqueDWARFASTTypeMap ()
+{
+    if (GetDebugMapSymfile ())
+        return m_debug_map_symfile->GetUniqueDWARFASTTypeMap ();
+    return m_unique_ast_type_map;
+}
+
+ClangASTContext &       
+SymbolFileDWARF::GetClangASTContext ()
+{
+    if (GetDebugMapSymfile ())
+        return m_debug_map_symfile->GetClangASTContext ();
+
+    ClangASTContext &ast = m_obj_file->GetModule()->GetClangASTContext();
+    if (!m_is_external_ast_source)
+    {
+        m_is_external_ast_source = true;
+        llvm::OwningPtr<clang::ExternalASTSource> ast_source_ap (
+            new ClangExternalASTSourceCallbacks (SymbolFileDWARF::CompleteTagDecl,
+                                                 SymbolFileDWARF::CompleteObjCInterfaceDecl,
+                                                 SymbolFileDWARF::FindExternalVisibleDeclsByName,
+                                                 SymbolFileDWARF::LayoutRecordType,
+                                                 this));
+        ast.SetExternalSource (ast_source_ap);
+    }
+    return ast;
+}
+
+void
+SymbolFileDWARF::InitializeObject()
+{
+    // Install our external AST source callbacks so we can complete Clang types.
+    ModuleSP module_sp (m_obj_file->GetModule());
+    if (module_sp)
+    {
+        const SectionList *section_list = module_sp->GetSectionList();
+
+        const Section* section = section_list->FindSectionByName(GetDWARFMachOSegmentName ()).get();
+
+        // Memory map the DWARF mach-o segment so we have everything mmap'ed
+        // to keep our heap memory usage down.
+        if (section)
+            m_obj_file->MemoryMapSectionData(section, m_dwarf_data);
+    }
+    get_apple_names_data();
+    if (m_data_apple_names.GetByteSize() > 0)
+    {
+        m_apple_names_ap.reset (new DWARFMappedHash::MemoryTable (m_data_apple_names, get_debug_str_data(), ".apple_names"));
+        if (m_apple_names_ap->IsValid())
+            m_using_apple_tables = true;
+        else
+            m_apple_names_ap.reset();
+    }
+    get_apple_types_data();
+    if (m_data_apple_types.GetByteSize() > 0)
+    {
+        m_apple_types_ap.reset (new DWARFMappedHash::MemoryTable (m_data_apple_types, get_debug_str_data(), ".apple_types"));
+        if (m_apple_types_ap->IsValid())
+            m_using_apple_tables = true;
+        else
+            m_apple_types_ap.reset();
+    }
+
+    get_apple_namespaces_data();
+    if (m_data_apple_namespaces.GetByteSize() > 0)
+    {
+        m_apple_namespaces_ap.reset (new DWARFMappedHash::MemoryTable (m_data_apple_namespaces, get_debug_str_data(), ".apple_namespaces"));
+        if (m_apple_namespaces_ap->IsValid())
+            m_using_apple_tables = true;
+        else
+            m_apple_namespaces_ap.reset();
+    }
+
+    get_apple_objc_data();
+    if (m_data_apple_objc.GetByteSize() > 0)
+    {
+        m_apple_objc_ap.reset (new DWARFMappedHash::MemoryTable (m_data_apple_objc, get_debug_str_data(), ".apple_objc"));
+        if (m_apple_objc_ap->IsValid())
+            m_using_apple_tables = true;
+        else
+            m_apple_objc_ap.reset();
+    }
+}
+
+bool
+SymbolFileDWARF::SupportedVersion(uint16_t version)
+{
+    return version == 2 || version == 3 || version == 4;
+}
+
+uint32_t
+SymbolFileDWARF::CalculateAbilities ()
+{
+    uint32_t abilities = 0;
+    if (m_obj_file != NULL)
+    {
+        const Section* section = NULL;
+        const SectionList *section_list = m_obj_file->GetSectionList();
+        if (section_list == NULL)
+            return 0;
+
+        uint64_t debug_abbrev_file_size = 0;
+        uint64_t debug_info_file_size = 0;
+        uint64_t debug_line_file_size = 0;
+
+        section = section_list->FindSectionByName(GetDWARFMachOSegmentName ()).get();
+        
+        if (section)
+            section_list = &section->GetChildren ();
+        
+        section = section_list->FindSectionByType (eSectionTypeDWARFDebugInfo, true).get();
+        if (section != NULL)
+        {
+            debug_info_file_size = section->GetFileSize();
+
+            section = section_list->FindSectionByType (eSectionTypeDWARFDebugAbbrev, true).get();
+            if (section)
+                debug_abbrev_file_size = section->GetFileSize();
+            else
+                m_flags.Set (flagsGotDebugAbbrevData);
+
+            section = section_list->FindSectionByType (eSectionTypeDWARFDebugAranges, true).get();
+            if (!section)
+                m_flags.Set (flagsGotDebugArangesData);
+
+            section = section_list->FindSectionByType (eSectionTypeDWARFDebugFrame, true).get();
+            if (!section)
+                m_flags.Set (flagsGotDebugFrameData);
+
+            section = section_list->FindSectionByType (eSectionTypeDWARFDebugLine, true).get();
+            if (section)
+                debug_line_file_size = section->GetFileSize();
+            else
+                m_flags.Set (flagsGotDebugLineData);
+
+            section = section_list->FindSectionByType (eSectionTypeDWARFDebugLoc, true).get();
+            if (!section)
+                m_flags.Set (flagsGotDebugLocData);
+
+            section = section_list->FindSectionByType (eSectionTypeDWARFDebugMacInfo, true).get();
+            if (!section)
+                m_flags.Set (flagsGotDebugMacInfoData);
+
+            section = section_list->FindSectionByType (eSectionTypeDWARFDebugPubNames, true).get();
+            if (!section)
+                m_flags.Set (flagsGotDebugPubNamesData);
+
+            section = section_list->FindSectionByType (eSectionTypeDWARFDebugPubTypes, true).get();
+            if (!section)
+                m_flags.Set (flagsGotDebugPubTypesData);
+
+            section = section_list->FindSectionByType (eSectionTypeDWARFDebugRanges, true).get();
+            if (!section)
+                m_flags.Set (flagsGotDebugRangesData);
+
+            section = section_list->FindSectionByType (eSectionTypeDWARFDebugStr, true).get();
+            if (!section)
+                m_flags.Set (flagsGotDebugStrData);
+        }
+        else
+        {
+            const char *symfile_dir_cstr = m_obj_file->GetFileSpec().GetDirectory().GetCString();
+            if (symfile_dir_cstr)
+            {
+                if (strcasestr(symfile_dir_cstr, ".dsym"))
+                {
+                    if (m_obj_file->GetType() == ObjectFile::eTypeDebugInfo)
+                    {
+                        // We have a dSYM file that didn't have a any debug info.
+                        // If the string table has a size of 1, then it was made from
+                        // an executable with no debug info, or from an executable that
+                        // was stripped.
+                        section = section_list->FindSectionByType (eSectionTypeDWARFDebugStr, true).get();
+                        if (section && section->GetFileSize() == 1)
+                        {
+                            m_obj_file->GetModule()->ReportWarning ("empty dSYM file detected, dSYM was created with an executable with no debug info.");
+                        }
+                    }
+                }
+            }
+        }
+
+        if (debug_abbrev_file_size > 0 && debug_info_file_size > 0)
+            abilities |= CompileUnits | Functions | Blocks | GlobalVariables | LocalVariables | VariableTypes;
+
+        if (debug_line_file_size > 0)
+            abilities |= LineTables;
+    }
+    return abilities;
+}
+
+const DataExtractor&
+SymbolFileDWARF::GetCachedSectionData (uint32_t got_flag, SectionType sect_type, DataExtractor &data)
+{
+    if (m_flags.IsClear (got_flag))
+    {
+        ModuleSP module_sp (m_obj_file->GetModule());
+        m_flags.Set (got_flag);
+        const SectionList *section_list = module_sp->GetSectionList();
+        if (section_list)
+        {
+            SectionSP section_sp (section_list->FindSectionByType(sect_type, true));
+            if (section_sp)
+            {
+                // See if we memory mapped the DWARF segment?
+                if (m_dwarf_data.GetByteSize())
+                {
+                    data.SetData(m_dwarf_data, section_sp->GetOffset (), section_sp->GetFileSize());
+                }
+                else
+                {
+                    if (m_obj_file->ReadSectionData (section_sp.get(), data) == 0)
+                        data.Clear();
+                }
+            }
+        }
+    }
+    return data;
+}
+
+const DataExtractor&
+SymbolFileDWARF::get_debug_abbrev_data()
+{
+    return GetCachedSectionData (flagsGotDebugAbbrevData, eSectionTypeDWARFDebugAbbrev, m_data_debug_abbrev);
+}
+
+const DataExtractor&
+SymbolFileDWARF::get_debug_aranges_data()
+{
+    return GetCachedSectionData (flagsGotDebugArangesData, eSectionTypeDWARFDebugAranges, m_data_debug_aranges);
+}
+
+const DataExtractor&
+SymbolFileDWARF::get_debug_frame_data()
+{
+    return GetCachedSectionData (flagsGotDebugFrameData, eSectionTypeDWARFDebugFrame, m_data_debug_frame);
+}
+
+const DataExtractor&
+SymbolFileDWARF::get_debug_info_data()
+{
+    return GetCachedSectionData (flagsGotDebugInfoData, eSectionTypeDWARFDebugInfo, m_data_debug_info);
+}
+
+const DataExtractor&
+SymbolFileDWARF::get_debug_line_data()
+{
+    return GetCachedSectionData (flagsGotDebugLineData, eSectionTypeDWARFDebugLine, m_data_debug_line);
+}
+
+const DataExtractor&
+SymbolFileDWARF::get_debug_loc_data()
+{
+    return GetCachedSectionData (flagsGotDebugLocData, eSectionTypeDWARFDebugLoc, m_data_debug_loc);
+}
+
+const DataExtractor&
+SymbolFileDWARF::get_debug_ranges_data()
+{
+    return GetCachedSectionData (flagsGotDebugRangesData, eSectionTypeDWARFDebugRanges, m_data_debug_ranges);
+}
+
+const DataExtractor&
+SymbolFileDWARF::get_debug_str_data()
+{
+    return GetCachedSectionData (flagsGotDebugStrData, eSectionTypeDWARFDebugStr, m_data_debug_str);
+}
+
+const DataExtractor&
+SymbolFileDWARF::get_apple_names_data()
+{
+    return GetCachedSectionData (flagsGotAppleNamesData, eSectionTypeDWARFAppleNames, m_data_apple_names);
+}
+
+const DataExtractor&
+SymbolFileDWARF::get_apple_types_data()
+{
+    return GetCachedSectionData (flagsGotAppleTypesData, eSectionTypeDWARFAppleTypes, m_data_apple_types);
+}
+
+const DataExtractor&
+SymbolFileDWARF::get_apple_namespaces_data()
+{
+    return GetCachedSectionData (flagsGotAppleNamespacesData, eSectionTypeDWARFAppleNamespaces, m_data_apple_namespaces);
+}
+
+const DataExtractor&
+SymbolFileDWARF::get_apple_objc_data()
+{
+    return GetCachedSectionData (flagsGotAppleObjCData, eSectionTypeDWARFAppleObjC, m_data_apple_objc);
+}
+
+
+DWARFDebugAbbrev*
+SymbolFileDWARF::DebugAbbrev()
+{
+    if (m_abbr.get() == NULL)
+    {
+        const DataExtractor &debug_abbrev_data = get_debug_abbrev_data();
+        if (debug_abbrev_data.GetByteSize() > 0)
+        {
+            m_abbr.reset(new DWARFDebugAbbrev());
+            if (m_abbr.get())
+                m_abbr->Parse(debug_abbrev_data);
+        }
+    }
+    return m_abbr.get();
+}
+
+const DWARFDebugAbbrev*
+SymbolFileDWARF::DebugAbbrev() const
+{
+    return m_abbr.get();
+}
+
+
+DWARFDebugInfo*
+SymbolFileDWARF::DebugInfo()
+{
+    if (m_info.get() == NULL)
+    {
+        Timer scoped_timer(__PRETTY_FUNCTION__, "%s this = %p", __PRETTY_FUNCTION__, this);
+        if (get_debug_info_data().GetByteSize() > 0)
+        {
+            m_info.reset(new DWARFDebugInfo());
+            if (m_info.get())
+            {
+                m_info->SetDwarfData(this);
+            }
+        }
+    }
+    return m_info.get();
+}
+
+const DWARFDebugInfo*
+SymbolFileDWARF::DebugInfo() const
+{
+    return m_info.get();
+}
+
+DWARFCompileUnit*
+SymbolFileDWARF::GetDWARFCompileUnit(lldb_private::CompileUnit *comp_unit)
+{
+    DWARFDebugInfo* info = DebugInfo();
+    if (info)
+    {
+        if (GetDebugMapSymfile ())
+        {
+            // The debug map symbol file made the compile units for this DWARF
+            // file which is .o file with DWARF in it, and we should have
+            // only 1 compile unit which is at offset zero in the DWARF.
+            // TODO: modify to support LTO .o files where each .o file might
+            // have multiple DW_TAG_compile_unit tags.
+            return info->GetCompileUnit(0).get();
+        }
+        else
+        {
+            // Just a normal DWARF file whose user ID for the compile unit is
+            // the DWARF offset itself
+            return info->GetCompileUnit((dw_offset_t)comp_unit->GetID()).get();
+        }
+    }
+    return NULL;
+}
+
+
+DWARFDebugRanges*
+SymbolFileDWARF::DebugRanges()
+{
+    if (m_ranges.get() == NULL)
+    {
+        Timer scoped_timer(__PRETTY_FUNCTION__, "%s this = %p", __PRETTY_FUNCTION__, this);
+        if (get_debug_ranges_data().GetByteSize() > 0)
+        {
+            m_ranges.reset(new DWARFDebugRanges());
+            if (m_ranges.get())
+                m_ranges->Extract(this);
+        }
+    }
+    return m_ranges.get();
+}
+
+const DWARFDebugRanges*
+SymbolFileDWARF::DebugRanges() const
+{
+    return m_ranges.get();
+}
+
+lldb::CompUnitSP
+SymbolFileDWARF::ParseCompileUnit (DWARFCompileUnit* dwarf_cu, uint32_t cu_idx)
+{
+    CompUnitSP cu_sp;
+    if (dwarf_cu)
+    {
+        CompileUnit *comp_unit = (CompileUnit*)dwarf_cu->GetUserData();
+        if (comp_unit)
+        {
+            // We already parsed this compile unit, had out a shared pointer to it
+            cu_sp = comp_unit->shared_from_this();
+        }
+        else
+        {
+            if (GetDebugMapSymfile ())
+            {
+                // Let the debug map create the compile unit
+                cu_sp = m_debug_map_symfile->GetCompileUnit(this);
+                dwarf_cu->SetUserData(cu_sp.get());
+            }
+            else
+            {
+                ModuleSP module_sp (m_obj_file->GetModule());
+                if (module_sp)
+                {
+                    const DWARFDebugInfoEntry * cu_die = dwarf_cu->GetCompileUnitDIEOnly ();
+                    if (cu_die)
+                    {
+                        const char * cu_die_name = cu_die->GetName(this, dwarf_cu);
+                        const char * cu_comp_dir = cu_die->GetAttributeValueAsString(this, dwarf_cu, DW_AT_comp_dir, NULL);
+                        LanguageType cu_language = (LanguageType)cu_die->GetAttributeValueAsUnsigned(this, dwarf_cu, DW_AT_language, 0);
+                        if (cu_die_name)
+                        {
+                            std::string ramapped_file;
+                            FileSpec cu_file_spec;
+
+                            if (cu_die_name[0] == '/' || cu_comp_dir == NULL || cu_comp_dir[0] == '\0')
+                            {
+                                // If we have a full path to the compile unit, we don't need to resolve
+                                // the file.  This can be expensive e.g. when the source files are NFS mounted.
+                                if (module_sp->RemapSourceFile(cu_die_name, ramapped_file))
+                                    cu_file_spec.SetFile (ramapped_file.c_str(), false);
+                                else
+                                    cu_file_spec.SetFile (cu_die_name, false);
+                            }
+                            else
+                            {
+                                std::string fullpath(cu_comp_dir);
+                                if (*fullpath.rbegin() != '/')
+                                    fullpath += '/';
+                                fullpath += cu_die_name;
+                                if (module_sp->RemapSourceFile (fullpath.c_str(), ramapped_file))
+                                    cu_file_spec.SetFile (ramapped_file.c_str(), false);
+                                else
+                                    cu_file_spec.SetFile (fullpath.c_str(), false);
+                            }
+
+                            cu_sp.reset(new CompileUnit (module_sp,
+                                                         dwarf_cu,
+                                                         cu_file_spec, 
+                                                         MakeUserID(dwarf_cu->GetOffset()),
+                                                         cu_language));
+                            if (cu_sp)
+                            {
+                                dwarf_cu->SetUserData(cu_sp.get());
+                                
+                                // Figure out the compile unit index if we weren't given one
+                                if (cu_idx == UINT32_MAX)
+                                    DebugInfo()->GetCompileUnit(dwarf_cu->GetOffset(), &cu_idx);
+                                
+                                m_obj_file->GetModule()->GetSymbolVendor()->SetCompileUnitAtIndex(cu_idx, cu_sp);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    return cu_sp;
+}
+
+uint32_t
+SymbolFileDWARF::GetNumCompileUnits()
+{
+    DWARFDebugInfo* info = DebugInfo();
+    if (info)
+        return info->GetNumCompileUnits();
+    return 0;
+}
+
+CompUnitSP
+SymbolFileDWARF::ParseCompileUnitAtIndex(uint32_t cu_idx)
+{
+    CompUnitSP cu_sp;
+    DWARFDebugInfo* info = DebugInfo();
+    if (info)
+    {
+        DWARFCompileUnit* dwarf_cu = info->GetCompileUnitAtIndex(cu_idx);
+        if (dwarf_cu)
+            cu_sp = ParseCompileUnit(dwarf_cu, cu_idx);
+    }
+    return cu_sp;
+}
+
+static void
+AddRangesToBlock (Block& block,
+                  DWARFDebugRanges::RangeList& ranges,
+                  addr_t block_base_addr)
+{
+    const size_t num_ranges = ranges.GetSize();
+    for (size_t i = 0; i<num_ranges; ++i)
+    {
+        const DWARFDebugRanges::Range &range = ranges.GetEntryRef (i);
+        const addr_t range_base = range.GetRangeBase();
+        assert (range_base >= block_base_addr);
+        block.AddRange(Block::Range (range_base - block_base_addr, range.GetByteSize()));;
+    }
+    block.FinalizeRanges ();
+}
+
+
+Function *
+SymbolFileDWARF::ParseCompileUnitFunction (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry *die)
+{
+    DWARFDebugRanges::RangeList func_ranges;
+    const char *name = NULL;
+    const char *mangled = NULL;
+    int decl_file = 0;
+    int decl_line = 0;
+    int decl_column = 0;
+    int call_file = 0;
+    int call_line = 0;
+    int call_column = 0;
+    DWARFExpression frame_base;
+
+    assert (die->Tag() == DW_TAG_subprogram);
+    
+    if (die->Tag() != DW_TAG_subprogram)
+        return NULL;
+
+    if (die->GetDIENamesAndRanges (this, 
+                                   dwarf_cu, 
+                                   name, 
+                                   mangled, 
+                                   func_ranges, 
+                                   decl_file, 
+                                   decl_line, 
+                                   decl_column, 
+                                   call_file, 
+                                   call_line, 
+                                   call_column, 
+                                   &frame_base))
+    {
+        // Union of all ranges in the function DIE (if the function is discontiguous)
+        AddressRange func_range;
+        lldb::addr_t lowest_func_addr = func_ranges.GetMinRangeBase (0);
+        lldb::addr_t highest_func_addr = func_ranges.GetMaxRangeEnd (0);
+        if (lowest_func_addr != LLDB_INVALID_ADDRESS && lowest_func_addr <= highest_func_addr)
+        {
+            ModuleSP module_sp (m_obj_file->GetModule());
+            func_range.GetBaseAddress().ResolveAddressUsingFileSections (lowest_func_addr, module_sp->GetSectionList());
+            if (func_range.GetBaseAddress().IsValid())
+                func_range.SetByteSize(highest_func_addr - lowest_func_addr);
+        }
+
+        if (func_range.GetBaseAddress().IsValid())
+        {
+            Mangled func_name;
+            if (mangled)
+                func_name.SetValue(ConstString(mangled), true);
+            else if (name)
+                func_name.SetValue(ConstString(name), false);
+
+            FunctionSP func_sp;
+            std::unique_ptr<Declaration> decl_ap;
+            if (decl_file != 0 || decl_line != 0 || decl_column != 0)
+                decl_ap.reset(new Declaration (sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(decl_file), 
+                                               decl_line, 
+                                               decl_column));
+
+            // Supply the type _only_ if it has already been parsed
+            Type *func_type = m_die_to_type.lookup (die);
+
+            assert(func_type == NULL || func_type != DIE_IS_BEING_PARSED);
+
+            if (FixupAddress (func_range.GetBaseAddress()))
+            {
+                const user_id_t func_user_id = MakeUserID(die->GetOffset());
+                func_sp.reset(new Function (sc.comp_unit,
+                                            MakeUserID(func_user_id),       // UserID is the DIE offset
+                                            MakeUserID(func_user_id),
+                                            func_name,
+                                            func_type,
+                                            func_range));           // first address range
+
+                if (func_sp.get() != NULL)
+                {
+                    if (frame_base.IsValid())
+                        func_sp->GetFrameBaseExpression() = frame_base;
+                    sc.comp_unit->AddFunction(func_sp);
+                    return func_sp.get();
+                }
+            }
+        }
+    }
+    return NULL;
+}
+
+bool
+SymbolFileDWARF::FixupAddress (Address &addr)
+{
+    SymbolFileDWARFDebugMap * debug_map_symfile = GetDebugMapSymfile ();
+    if (debug_map_symfile)
+    {
+        return debug_map_symfile->LinkOSOAddress(addr);
+    }
+    // This is a normal DWARF file, no address fixups need to happen
+    return true;
+}
+lldb::LanguageType
+SymbolFileDWARF::ParseCompileUnitLanguage (const SymbolContext& sc)
+{
+    assert (sc.comp_unit);
+    DWARFCompileUnit* dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
+    if (dwarf_cu)
+    {
+        const DWARFDebugInfoEntry *die = dwarf_cu->GetCompileUnitDIEOnly();
+        if (die)
+        {
+            const uint32_t language = die->GetAttributeValueAsUnsigned(this, dwarf_cu, DW_AT_language, 0);
+            if (language)
+                return (lldb::LanguageType)language;
+        }
+    }
+    return eLanguageTypeUnknown;
+}
+
+size_t
+SymbolFileDWARF::ParseCompileUnitFunctions(const SymbolContext &sc)
+{
+    assert (sc.comp_unit);
+    size_t functions_added = 0;
+    DWARFCompileUnit* dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
+    if (dwarf_cu)
+    {
+        DWARFDIECollection function_dies;
+        const size_t num_functions = dwarf_cu->AppendDIEsWithTag (DW_TAG_subprogram, function_dies);
+        size_t func_idx;
+        for (func_idx = 0; func_idx < num_functions; ++func_idx)
+        {
+            const DWARFDebugInfoEntry *die = function_dies.GetDIEPtrAtIndex(func_idx);
+            if (sc.comp_unit->FindFunctionByUID (MakeUserID(die->GetOffset())).get() == NULL)
+            {
+                if (ParseCompileUnitFunction(sc, dwarf_cu, die))
+                    ++functions_added;
+            }
+        }
+        //FixupTypes();
+    }
+    return functions_added;
+}
+
+bool
+SymbolFileDWARF::ParseCompileUnitSupportFiles (const SymbolContext& sc, FileSpecList& support_files)
+{
+    assert (sc.comp_unit);
+    DWARFCompileUnit* dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
+    if (dwarf_cu)
+    {
+        const DWARFDebugInfoEntry * cu_die = dwarf_cu->GetCompileUnitDIEOnly();
+
+        if (cu_die)
+        {
+            const char * cu_comp_dir = cu_die->GetAttributeValueAsString(this, dwarf_cu, DW_AT_comp_dir, NULL);
+            dw_offset_t stmt_list = cu_die->GetAttributeValueAsUnsigned(this, dwarf_cu, DW_AT_stmt_list, DW_INVALID_OFFSET);
+
+            // All file indexes in DWARF are one based and a file of index zero is
+            // supposed to be the compile unit itself.
+            support_files.Append (*sc.comp_unit);
+
+            return DWARFDebugLine::ParseSupportFiles(sc.comp_unit->GetModule(), get_debug_line_data(), cu_comp_dir, stmt_list, support_files);
+        }
+    }
+    return false;
+}
+
+struct ParseDWARFLineTableCallbackInfo
+{
+    LineTable* line_table;
+    std::unique_ptr<LineSequence> sequence_ap;
+};
+
+//----------------------------------------------------------------------
+// ParseStatementTableCallback
+//----------------------------------------------------------------------
+static void
+ParseDWARFLineTableCallback(dw_offset_t offset, const DWARFDebugLine::State& state, void* userData)
+{
+    if (state.row == DWARFDebugLine::State::StartParsingLineTable)
+    {
+        // Just started parsing the line table
+    }
+    else if (state.row == DWARFDebugLine::State::DoneParsingLineTable)
+    {
+        // Done parsing line table, nothing to do for the cleanup
+    }
+    else
+    {
+        ParseDWARFLineTableCallbackInfo* info = (ParseDWARFLineTableCallbackInfo*)userData;
+        LineTable* line_table = info->line_table;
+
+        // If this is our first time here, we need to create a
+        // sequence container.
+        if (!info->sequence_ap.get())
+        {
+            info->sequence_ap.reset(line_table->CreateLineSequenceContainer());
+            assert(info->sequence_ap.get());
+        }
+        line_table->AppendLineEntryToSequence (info->sequence_ap.get(),
+                                               state.address,
+                                               state.line,
+                                               state.column,
+                                               state.file,
+                                               state.is_stmt,
+                                               state.basic_block,
+                                               state.prologue_end,
+                                               state.epilogue_begin,
+                                               state.end_sequence);
+        if (state.end_sequence)
+        {
+            // First, put the current sequence into the line table.
+            line_table->InsertSequence(info->sequence_ap.get());
+            // Then, empty it to prepare for the next sequence.
+            info->sequence_ap->Clear();
+        }
+    }
+}
+
+bool
+SymbolFileDWARF::ParseCompileUnitLineTable (const SymbolContext &sc)
+{
+    assert (sc.comp_unit);
+    if (sc.comp_unit->GetLineTable() != NULL)
+        return true;
+
+    DWARFCompileUnit* dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
+    if (dwarf_cu)
+    {
+        const DWARFDebugInfoEntry *dwarf_cu_die = dwarf_cu->GetCompileUnitDIEOnly();
+        if (dwarf_cu_die)
+        {
+            const dw_offset_t cu_line_offset = dwarf_cu_die->GetAttributeValueAsUnsigned(this, dwarf_cu, DW_AT_stmt_list, DW_INVALID_OFFSET);
+            if (cu_line_offset != DW_INVALID_OFFSET)
+            {
+                std::unique_ptr<LineTable> line_table_ap(new LineTable(sc.comp_unit));
+                if (line_table_ap.get())
+                {
+                    ParseDWARFLineTableCallbackInfo info;
+                    info.line_table = line_table_ap.get();
+                    lldb::offset_t offset = cu_line_offset;
+                    DWARFDebugLine::ParseStatementTable(get_debug_line_data(), &offset, ParseDWARFLineTableCallback, &info);
+                    if (m_debug_map_symfile)
+                    {
+                        // We have an object file that has a line table with addresses
+                        // that are not linked. We need to link the line table and convert
+                        // the addresses that are relative to the .o file into addresses
+                        // for the main executable.
+                        sc.comp_unit->SetLineTable (m_debug_map_symfile->LinkOSOLineTable (this, line_table_ap.get()));
+                    }
+                    else
+                    {
+                        sc.comp_unit->SetLineTable(line_table_ap.release());
+                        return true;
+                    }
+                }
+            }
+        }
+    }
+    return false;
+}
+
+size_t
+SymbolFileDWARF::ParseFunctionBlocks
+(
+    const SymbolContext& sc,
+    Block *parent_block,
+    DWARFCompileUnit* dwarf_cu,
+    const DWARFDebugInfoEntry *die,
+    addr_t subprogram_low_pc,
+    uint32_t depth
+)
+{
+    size_t blocks_added = 0;
+    while (die != NULL)
+    {
+        dw_tag_t tag = die->Tag();
+
+        switch (tag)
+        {
+        case DW_TAG_inlined_subroutine:
+        case DW_TAG_subprogram:
+        case DW_TAG_lexical_block:
+            {
+                Block *block = NULL;
+                if (tag == DW_TAG_subprogram)
+                {
+                    // Skip any DW_TAG_subprogram DIEs that are inside
+                    // of a normal or inlined functions. These will be 
+                    // parsed on their own as separate entities.
+
+                    if (depth > 0)
+                        break;
+
+                    block = parent_block;
+                }
+                else
+                {
+                    BlockSP block_sp(new Block (MakeUserID(die->GetOffset())));
+                    parent_block->AddChild(block_sp);
+                    block = block_sp.get();
+                }
+                DWARFDebugRanges::RangeList ranges;
+                const char *name = NULL;
+                const char *mangled_name = NULL;
+
+                int decl_file = 0;
+                int decl_line = 0;
+                int decl_column = 0;
+                int call_file = 0;
+                int call_line = 0;
+                int call_column = 0;
+                if (die->GetDIENamesAndRanges (this, 
+                                               dwarf_cu, 
+                                               name, 
+                                               mangled_name, 
+                                               ranges, 
+                                               decl_file, decl_line, decl_column,
+                                               call_file, call_line, call_column))
+                {
+                    if (tag == DW_TAG_subprogram)
+                    {
+                        assert (subprogram_low_pc == LLDB_INVALID_ADDRESS);
+                        subprogram_low_pc = ranges.GetMinRangeBase(0);
+                    }
+                    else if (tag == DW_TAG_inlined_subroutine)
+                    {
+                        // We get called here for inlined subroutines in two ways.  
+                        // The first time is when we are making the Function object 
+                        // for this inlined concrete instance.  Since we're creating a top level block at
+                        // here, the subprogram_low_pc will be LLDB_INVALID_ADDRESS.  So we need to 
+                        // adjust the containing address.
+                        // The second time is when we are parsing the blocks inside the function that contains
+                        // the inlined concrete instance.  Since these will be blocks inside the containing "real"
+                        // function the offset will be for that function.  
+                        if (subprogram_low_pc == LLDB_INVALID_ADDRESS)
+                        {
+                            subprogram_low_pc = ranges.GetMinRangeBase(0);
+                        }
+                    }
+                    
+                    AddRangesToBlock (*block, ranges, subprogram_low_pc);
+
+                    if (tag != DW_TAG_subprogram && (name != NULL || mangled_name != NULL))
+                    {
+                        std::unique_ptr<Declaration> decl_ap;
+                        if (decl_file != 0 || decl_line != 0 || decl_column != 0)
+                            decl_ap.reset(new Declaration(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(decl_file), 
+                                                          decl_line, decl_column));
+
+                        std::unique_ptr<Declaration> call_ap;
+                        if (call_file != 0 || call_line != 0 || call_column != 0)
+                            call_ap.reset(new Declaration(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(call_file), 
+                                                          call_line, call_column));
+
+                        block->SetInlinedFunctionInfo (name, mangled_name, decl_ap.get(), call_ap.get());
+                    }
+
+                    ++blocks_added;
+
+                    if (die->HasChildren())
+                    {
+                        blocks_added += ParseFunctionBlocks (sc, 
+                                                             block, 
+                                                             dwarf_cu, 
+                                                             die->GetFirstChild(), 
+                                                             subprogram_low_pc, 
+                                                             depth + 1);
+                    }
+                }
+            }
+            break;
+        default:
+            break;
+        }
+
+        // Only parse siblings of the block if we are not at depth zero. A depth
+        // of zero indicates we are currently parsing the top level 
+        // DW_TAG_subprogram DIE
+        
+        if (depth == 0)
+            die = NULL;
+        else
+            die = die->GetSibling();
+    }
+    return blocks_added;
+}
+
+bool
+SymbolFileDWARF::ParseTemplateDIE (DWARFCompileUnit* dwarf_cu,
+                                   const DWARFDebugInfoEntry *die,
+                                   ClangASTContext::TemplateParameterInfos &template_param_infos)
+{
+    const dw_tag_t tag = die->Tag();
+    
+    switch (tag)
+    {
+    case DW_TAG_template_type_parameter:
+    case DW_TAG_template_value_parameter:
+        {
+            const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize());
+
+            DWARFDebugInfoEntry::Attributes attributes;
+            const size_t num_attributes = die->GetAttributes (this, 
+                                                              dwarf_cu, 
+                                                              fixed_form_sizes, 
+                                                              attributes);
+            const char *name = NULL;
+            Type *lldb_type = NULL;
+            ClangASTType clang_type;
+            uint64_t uval64 = 0;
+            bool uval64_valid = false;
+            if (num_attributes > 0)
+            {
+                DWARFFormValue form_value;
+                for (size_t i=0; i<num_attributes; ++i)
+                {
+                    const dw_attr_t attr = attributes.AttributeAtIndex(i);
+                    
+                    switch (attr)
+                    {
+                        case DW_AT_name:
+                            if (attributes.ExtractFormValueAtIndex(this, i, form_value))
+                                name = form_value.AsCString(&get_debug_str_data());
+                            break;
+                            
+                        case DW_AT_type:
+                            if (attributes.ExtractFormValueAtIndex(this, i, form_value))
+                            {
+                                const dw_offset_t type_die_offset = form_value.Reference(dwarf_cu);
+                                lldb_type = ResolveTypeUID(type_die_offset);
+                                if (lldb_type)
+                                    clang_type = lldb_type->GetClangForwardType();
+                            }
+                            break;
+                            
+                        case DW_AT_const_value:
+                            if (attributes.ExtractFormValueAtIndex(this, i, form_value))
+                            {
+                                uval64_valid = true;
+                                uval64 = form_value.Unsigned();
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                }
+                
+                clang::ASTContext *ast = GetClangASTContext().getASTContext();
+                if (!clang_type)
+                    clang_type = GetClangASTContext().GetBasicType(eBasicTypeVoid);
+
+                if (clang_type)
+                {
+                    bool is_signed = false;
+                    if (name && name[0])
+                        template_param_infos.names.push_back(name);
+                    else
+                        template_param_infos.names.push_back(NULL);
+    
+                    if (tag == DW_TAG_template_value_parameter &&
+                        lldb_type != NULL &&
+                        clang_type.IsIntegerType (is_signed) &&
+                        uval64_valid)
+                    {
+                        llvm::APInt apint (lldb_type->GetByteSize() * 8, uval64, is_signed);
+                        template_param_infos.args.push_back (clang::TemplateArgument (*ast,
+                                                                                      llvm::APSInt(apint),
+                                                                                      clang_type.GetQualType()));
+                    }
+                    else
+                    {
+                        template_param_infos.args.push_back (clang::TemplateArgument (clang_type.GetQualType()));
+                    }
+                }
+                else
+                {
+                    return false;
+                }
+                
+            }
+        }
+        return true;
+
+    default:
+        break;
+    }
+    return false;
+}
+
+bool
+SymbolFileDWARF::ParseTemplateParameterInfos (DWARFCompileUnit* dwarf_cu,
+                                              const DWARFDebugInfoEntry *parent_die,
+                                              ClangASTContext::TemplateParameterInfos &template_param_infos)
+{
+
+    if (parent_die == NULL)
+        return false;
+    
+    Args template_parameter_names;
+    for (const DWARFDebugInfoEntry *die = parent_die->GetFirstChild(); 
+         die != NULL; 
+         die = die->GetSibling())
+    {
+        const dw_tag_t tag = die->Tag();
+        
+        switch (tag)
+        {
+            case DW_TAG_template_type_parameter:
+            case DW_TAG_template_value_parameter:
+                ParseTemplateDIE (dwarf_cu, die, template_param_infos);
+            break;
+                
+        default:
+            break;
+        }
+    }
+    if (template_param_infos.args.empty())
+        return false;
+    return template_param_infos.args.size() == template_param_infos.names.size();
+}
+
+clang::ClassTemplateDecl *
+SymbolFileDWARF::ParseClassTemplateDecl (clang::DeclContext *decl_ctx,
+                                         lldb::AccessType access_type,
+                                         const char *parent_name,
+                                         int tag_decl_kind,
+                                         const ClangASTContext::TemplateParameterInfos &template_param_infos)
+{
+    if (template_param_infos.IsValid())
+    {
+        std::string template_basename(parent_name);
+        template_basename.erase (template_basename.find('<'));
+        ClangASTContext &ast = GetClangASTContext();
+
+        return ast.CreateClassTemplateDecl (decl_ctx,
+                                            access_type,
+                                            template_basename.c_str(), 
+                                            tag_decl_kind, 
+                                            template_param_infos);
+    }
+    return NULL;
+}
+
+class SymbolFileDWARF::DelayedAddObjCClassProperty
+{
+public:
+    DelayedAddObjCClassProperty
+    (
+        const ClangASTType     &class_opaque_type,
+        const char             *property_name,
+        const ClangASTType     &property_opaque_type,  // The property type is only required if you don't have an ivar decl
+        clang::ObjCIvarDecl    *ivar_decl,   
+        const char             *property_setter_name,
+        const char             *property_getter_name,
+        uint32_t                property_attributes,
+        const ClangASTMetadata *metadata
+    ) :
+        m_class_opaque_type     (class_opaque_type),
+        m_property_name         (property_name),
+        m_property_opaque_type  (property_opaque_type),
+        m_ivar_decl             (ivar_decl),
+        m_property_setter_name  (property_setter_name),
+        m_property_getter_name  (property_getter_name),
+        m_property_attributes   (property_attributes)
+    {
+        if (metadata != NULL)
+        {
+            m_metadata_ap.reset(new ClangASTMetadata());
+            *m_metadata_ap = *metadata;
+        }
+    }
+    
+    DelayedAddObjCClassProperty (const DelayedAddObjCClassProperty &rhs)
+    {
+        *this = rhs;
+    }
+
+    DelayedAddObjCClassProperty& operator= (const DelayedAddObjCClassProperty &rhs)
+    {
+        m_class_opaque_type    = rhs.m_class_opaque_type;
+        m_property_name        = rhs.m_property_name;
+        m_property_opaque_type = rhs.m_property_opaque_type;
+        m_ivar_decl            = rhs.m_ivar_decl;
+        m_property_setter_name = rhs.m_property_setter_name;
+        m_property_getter_name = rhs.m_property_getter_name;
+        m_property_attributes  = rhs.m_property_attributes;
+        
+        if (rhs.m_metadata_ap.get())
+        {
+            m_metadata_ap.reset (new ClangASTMetadata());
+            *m_metadata_ap = *rhs.m_metadata_ap;
+        }
+        return *this;
+    }
+    
+    bool
+    Finalize()
+    {
+        return m_class_opaque_type.AddObjCClassProperty (m_property_name,
+                                                         m_property_opaque_type,
+                                                         m_ivar_decl,
+                                                         m_property_setter_name,
+                                                         m_property_getter_name,
+                                                         m_property_attributes,
+                                                         m_metadata_ap.get());
+    }
+private:
+    ClangASTType            m_class_opaque_type;
+    const char             *m_property_name;
+    ClangASTType            m_property_opaque_type;
+    clang::ObjCIvarDecl    *m_ivar_decl;
+    const char             *m_property_setter_name;
+    const char             *m_property_getter_name;
+    uint32_t                m_property_attributes;
+    std::unique_ptr<ClangASTMetadata> m_metadata_ap;
+};
+
+struct BitfieldInfo
+{
+    uint64_t bit_size;
+    uint64_t bit_offset;
+    
+    BitfieldInfo () :
+        bit_size (LLDB_INVALID_ADDRESS),
+        bit_offset (LLDB_INVALID_ADDRESS)
+    {
+    }
+    
+    bool IsValid ()
+    {
+        return (bit_size != LLDB_INVALID_ADDRESS) &&
+               (bit_offset != LLDB_INVALID_ADDRESS);
+    }
+};
+
+
+bool
+SymbolFileDWARF::ClassOrStructIsVirtual (DWARFCompileUnit* dwarf_cu,
+                                         const DWARFDebugInfoEntry *parent_die)
+{
+    if (parent_die)
+    {
+        for (const DWARFDebugInfoEntry *die = parent_die->GetFirstChild(); die != NULL; die = die->GetSibling())
+        {
+            dw_tag_t tag = die->Tag();
+            bool check_virtuality = false;
+            switch (tag)
+            {
+                case DW_TAG_inheritance:
+                case DW_TAG_subprogram:
+                    check_virtuality = true;
+                    break;
+                default:
+                    break;
+            }
+            if (check_virtuality)
+            {
+                if (die->GetAttributeValueAsUnsigned(this, dwarf_cu, DW_AT_virtuality, 0) != 0)
+                    return true;
+            }
+        }
+    }
+    return false;
+}
+
+size_t
+SymbolFileDWARF::ParseChildMembers
+(
+    const SymbolContext& sc,
+    DWARFCompileUnit* dwarf_cu,
+    const DWARFDebugInfoEntry *parent_die,
+    ClangASTType &class_clang_type,
+    const LanguageType class_language,
+    std::vector<clang::CXXBaseSpecifier *>& base_classes,
+    std::vector<int>& member_accessibilities,
+    DWARFDIECollection& member_function_dies,
+    DelayedPropertyList& delayed_properties,
+    AccessType& default_accessibility,
+    bool &is_a_class,
+    LayoutInfo &layout_info
+)
+{
+    if (parent_die == NULL)
+        return 0;
+
+    size_t count = 0;
+    const DWARFDebugInfoEntry *die;
+    const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize());
+    uint32_t member_idx = 0;
+    BitfieldInfo last_field_info;
+
+    for (die = parent_die->GetFirstChild(); die != NULL; die = die->GetSibling())
+    {
+        dw_tag_t tag = die->Tag();
+
+        switch (tag)
+        {
+        case DW_TAG_member:
+        case DW_TAG_APPLE_property:
+            {
+                DWARFDebugInfoEntry::Attributes attributes;
+                const size_t num_attributes = die->GetAttributes (this, 
+                                                                  dwarf_cu, 
+                                                                  fixed_form_sizes, 
+                                                                  attributes);
+                if (num_attributes > 0)
+                {
+                    Declaration decl;
+                    //DWARFExpression location;
+                    const char *name = NULL;
+                    const char *prop_name = NULL;
+                    const char *prop_getter_name = NULL;
+                    const char *prop_setter_name = NULL;
+                    uint32_t prop_attributes = 0;
+                    
+                    
+                    bool is_artificial = false;
+                    lldb::user_id_t encoding_uid = LLDB_INVALID_UID;
+                    AccessType accessibility = eAccessNone;
+                    uint32_t member_byte_offset = UINT32_MAX;
+                    size_t byte_size = 0;
+                    size_t bit_offset = 0;
+                    size_t bit_size = 0;
+                    bool is_external = false; // On DW_TAG_members, this means the member is static
+                    uint32_t i;
+                    for (i=0; i<num_attributes && !is_artificial; ++i)
+                    {
+                        const dw_attr_t attr = attributes.AttributeAtIndex(i);
+                        DWARFFormValue form_value;
+                        if (attributes.ExtractFormValueAtIndex(this, i, form_value))
+                        {
+                            switch (attr)
+                            {
+                            case DW_AT_decl_file:   decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
+                            case DW_AT_decl_line:   decl.SetLine(form_value.Unsigned()); break;
+                            case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
+                            case DW_AT_name:        name = form_value.AsCString(&get_debug_str_data()); break;
+                            case DW_AT_type:        encoding_uid = form_value.Reference(dwarf_cu); break;
+                            case DW_AT_bit_offset:  bit_offset = form_value.Unsigned(); break;
+                            case DW_AT_bit_size:    bit_size = form_value.Unsigned(); break;
+                            case DW_AT_byte_size:   byte_size = form_value.Unsigned(); break;
+                            case DW_AT_data_member_location:
+                                if (form_value.BlockData())
+                                {
+                                    Value initialValue(0);
+                                    Value memberOffset(0);
+                                    const DataExtractor& debug_info_data = get_debug_info_data();
+                                    uint32_t block_length = form_value.Unsigned();
+                                    uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart();
+                                    if (DWARFExpression::Evaluate(NULL, // ExecutionContext *
+                                                                  NULL, // ClangExpressionVariableList *
+                                                                  NULL, // ClangExpressionDeclMap *
+                                                                  NULL, // RegisterContext *
+                                                                  debug_info_data, 
+                                                                  block_offset, 
+                                                                  block_length, 
+                                                                  eRegisterKindDWARF, 
+                                                                  &initialValue, 
+                                                                  memberOffset, 
+                                                                  NULL))
+                                    {
+                                        member_byte_offset = memberOffset.ResolveValue(NULL).UInt();
+                                    }
+                                }
+                                else
+                                {
+                                    // With DWARF 3 and later, if the value is an integer constant,
+                                    // this form value is the offset in bytes from the beginning
+                                    // of the containing entity. 
+                                    member_byte_offset = form_value.Unsigned(); 
+                                }
+                                break;
+
+                            case DW_AT_accessibility: accessibility = DW_ACCESS_to_AccessType (form_value.Unsigned()); break;
+                            case DW_AT_artificial: is_artificial = form_value.Boolean(); break;
+                            case DW_AT_APPLE_property_name:      prop_name = form_value.AsCString(&get_debug_str_data()); break;
+                            case DW_AT_APPLE_property_getter:    prop_getter_name = form_value.AsCString(&get_debug_str_data()); break;
+                            case DW_AT_APPLE_property_setter:    prop_setter_name = form_value.AsCString(&get_debug_str_data()); break;
+                            case DW_AT_APPLE_property_attribute: prop_attributes = form_value.Unsigned(); break;
+                            case DW_AT_external:                 is_external = form_value.Boolean(); break;
+
+                            default:
+                            case DW_AT_declaration:
+                            case DW_AT_description:
+                            case DW_AT_mutable:
+                            case DW_AT_visibility:
+                            case DW_AT_sibling:
+                                break;
+                            }
+                        }
+                    }
+                                        
+                    if (prop_name)
+                    {
+                        ConstString fixed_getter;
+                        ConstString fixed_setter;
+
+                        // Check if the property getter/setter were provided as full
+                        // names.  We want basenames, so we extract them.
+                        
+                        if (prop_getter_name && prop_getter_name[0] == '-')
+                        {
+                            ObjCLanguageRuntime::MethodName prop_getter_method(prop_getter_name, true);
+                            prop_getter_name = prop_getter_method.GetSelector().GetCString();
+                        }
+                        
+                        if (prop_setter_name && prop_setter_name[0] == '-')
+                        {
+                            ObjCLanguageRuntime::MethodName prop_setter_method(prop_setter_name, true);
+                            prop_setter_name = prop_setter_method.GetSelector().GetCString();
+                        }
+                        
+                        // If the names haven't been provided, they need to be
+                        // filled in.
+                        
+                        if (!prop_getter_name)
+                        {
+                            prop_getter_name = prop_name;
+                        }
+                        if (!prop_setter_name && prop_name[0] && !(prop_attributes & DW_APPLE_PROPERTY_readonly))
+                        {
+                            StreamString ss;
+                            
+                            ss.Printf("set%c%s:",
+                                      toupper(prop_name[0]),
+                                      &prop_name[1]);
+                            
+                            fixed_setter.SetCString(ss.GetData());
+                            prop_setter_name = fixed_setter.GetCString();
+                        }
+                    }
+                    
+                    // Clang has a DWARF generation bug where sometimes it
+                    // represents fields that are references with bad byte size
+                    // and bit size/offset information such as:
+                    //
+                    //  DW_AT_byte_size( 0x00 )
+                    //  DW_AT_bit_size( 0x40 )
+                    //  DW_AT_bit_offset( 0xffffffffffffffc0 )
+                    //
+                    // So check the bit offset to make sure it is sane, and if 
+                    // the values are not sane, remove them. If we don't do this
+                    // then we will end up with a crash if we try to use this 
+                    // type in an expression when clang becomes unhappy with its
+                    // recycled debug info.
+                    
+                    if (bit_offset > 128)
+                    {
+                        bit_size = 0;
+                        bit_offset = 0;
+                    }
+
+                    // FIXME: Make Clang ignore Objective-C accessibility for expressions
+                    if (class_language == eLanguageTypeObjC ||
+                        class_language == eLanguageTypeObjC_plus_plus)
+                        accessibility = eAccessNone; 
+                    
+                    if (member_idx == 0 && !is_artificial && name && (strstr (name, "_vptr$") == name))
+                    {
+                        // Not all compilers will mark the vtable pointer
+                        // member as artificial (llvm-gcc). We can't have
+                        // the virtual members in our classes otherwise it
+                        // throws off all child offsets since we end up
+                        // having and extra pointer sized member in our 
+                        // class layouts.
+                        is_artificial = true;
+                    }
+
+                    // Handle static members
+                    if (is_external && member_byte_offset == UINT32_MAX)
+                    {
+                        Type *var_type = ResolveTypeUID(encoding_uid);
+
+                        if (var_type)
+                        {
+                            if (accessibility == eAccessNone)
+                                accessibility = eAccessPublic;
+                            class_clang_type.AddVariableToRecordType (name,
+                                                                      var_type->GetClangLayoutType(),
+                                                                      accessibility);
+                        }
+                        break;
+                    }
+
+                    if (is_artificial == false)
+                    {
+                        Type *member_type = ResolveTypeUID(encoding_uid);
+                        
+                        clang::FieldDecl *field_decl = NULL;
+                        if (tag == DW_TAG_member)
+                        {
+                            if (member_type)
+                            {
+                                if (accessibility == eAccessNone)
+                                    accessibility = default_accessibility;
+                                member_accessibilities.push_back(accessibility);
+                                
+                                BitfieldInfo this_field_info;
+                        
+                                this_field_info.bit_size = bit_size;
+                                
+                                if (member_byte_offset != UINT32_MAX || bit_size != 0)
+                                {
+                                    /////////////////////////////////////////////////////////////
+                                    // How to locate a field given the DWARF debug information
+                                    //
+                                    // AT_byte_size indicates the size of the word in which the
+                                    // bit offset must be interpreted.
+                                    //
+                                    // AT_data_member_location indicates the byte offset of the
+                                    // word from the base address of the structure.
+                                    //
+                                    // AT_bit_offset indicates how many bits into the word
+                                    // (according to the host endianness) the low-order bit of
+                                    // the field starts.  AT_bit_offset can be negative.
+                                    //
+                                    // AT_bit_size indicates the size of the field in bits.
+                                    /////////////////////////////////////////////////////////////
+                                    
+                                    this_field_info.bit_offset = 0;
+                                    
+                                    this_field_info.bit_offset += (member_byte_offset == UINT32_MAX ? 0 : (member_byte_offset * 8));
+                                    
+                                    if (GetObjectFile()->GetByteOrder() == eByteOrderLittle)
+                                    {
+                                        this_field_info.bit_offset += byte_size * 8;
+                                        this_field_info.bit_offset -= (bit_offset + bit_size);
+                                    }
+                                    else
+                                    {
+                                        this_field_info.bit_offset += bit_offset;
+                                    }
+                                }
+
+                                // If the member to be emitted did not start on a character boundary and there is
+                                // empty space between the last field and this one, then we need to emit an
+                                // anonymous member filling up the space up to its start.  There are three cases
+                                // here:
+                                //
+                                // 1 If the previous member ended on a character boundary, then we can emit an
+                                //   anonymous member starting at the most recent character boundary.
+                                //
+                                // 2 If the previous member did not end on a character boundary and the distance
+                                //   from the end of the previous member to the current member is less than a
+                                //   word width, then we can emit an anonymous member starting right after the
+                                //   previous member and right before this member.
+                                //
+                                // 3 If the previous member did not end on a character boundary and the distance
+                                //   from the end of the previous member to the current member is greater than
+                                //   or equal a word width, then we act as in Case 1.
+                                
+                                const uint64_t character_width = 8;
+                                const uint64_t word_width = 32;
+                                
+                                if (this_field_info.IsValid())
+                                {
+                                    // Objective-C has invalid DW_AT_bit_offset values in older versions
+                                    // of clang, so we have to be careful and only insert unnammed bitfields
+                                    // if we have a new enough clang.
+                                    bool detect_unnamed_bitfields = true;
+                                    
+                                    if (class_language == eLanguageTypeObjC || class_language == eLanguageTypeObjC_plus_plus)
+                                        detect_unnamed_bitfields = dwarf_cu->Supports_unnamed_objc_bitfields ();
+                                    
+                                    if (detect_unnamed_bitfields)
+                                    {
+                                        BitfieldInfo anon_field_info;
+                                        
+                                        if ((this_field_info.bit_offset % character_width) != 0) // not char aligned
+                                        {
+                                            uint64_t last_field_end = 0;
+                                            
+                                            if (last_field_info.IsValid())
+                                                last_field_end = last_field_info.bit_offset + last_field_info.bit_size;
+                                            
+                                            if (this_field_info.bit_offset != last_field_end)
+                                            {                                                
+                                                if (((last_field_end % character_width) == 0) ||                    // case 1
+                                                    (this_field_info.bit_offset - last_field_end >= word_width))    // case 3
+                                                {
+                                                    anon_field_info.bit_size = this_field_info.bit_offset % character_width;
+                                                    anon_field_info.bit_offset = this_field_info.bit_offset - anon_field_info.bit_size;
+                                                }
+                                                else                                                                // case 2
+                                                {
+                                                    anon_field_info.bit_size = this_field_info.bit_offset - last_field_end;
+                                                    anon_field_info.bit_offset = last_field_end;
+                                                }
+                                            }
+                                        }
+                                        
+                                        if (anon_field_info.IsValid())
+                                        {
+                                            clang::FieldDecl *unnamed_bitfield_decl = class_clang_type.AddFieldToRecordType (NULL,
+                                                                                                                             GetClangASTContext().GetBuiltinTypeForEncodingAndBitSize(eEncodingSint, word_width),
+                                                                                                                             accessibility,
+                                                                                                                             anon_field_info.bit_size);
+                                            
+                                            layout_info.field_offsets.insert(std::make_pair(unnamed_bitfield_decl, anon_field_info.bit_offset));
+                                        }
+                                    }
+                                }
+                                
+                                ClangASTType member_clang_type = member_type->GetClangLayoutType();
+                                
+                                {
+                                    // Older versions of clang emit array[0] and array[1] in the same way (<rdar://problem/12566646>).
+                                    // If the current field is at the end of the structure, then there is definitely no room for extra
+                                    // elements and we override the type to array[0].
+                                    
+                                    ClangASTType member_array_element_type;
+                                    uint64_t member_array_size;
+                                    bool member_array_is_incomplete;
+                                    
+                                    if (member_clang_type.IsArrayType(&member_array_element_type,
+                                                                      &member_array_size,
+                                                                      &member_array_is_incomplete) &&
+                                        !member_array_is_incomplete)
+                                    {
+                                        uint64_t parent_byte_size = parent_die->GetAttributeValueAsUnsigned(this, dwarf_cu, DW_AT_byte_size, UINT64_MAX);
+                                    
+                                        if (member_byte_offset >= parent_byte_size)
+                                        {
+                                            if (member_array_size != 1)
+                                            {
+                                                GetObjectFile()->GetModule()->ReportError ("0x%8.8" PRIx64 ": DW_TAG_member '%s' refers to type 0x%8.8" PRIx64 " which extends beyond the bounds of 0x%8.8" PRIx64,
+                                                                                           MakeUserID(die->GetOffset()),
+                                                                                           name,
+                                                                                           encoding_uid,
+                                                                                           MakeUserID(parent_die->GetOffset()));
+                                            }
+                                            
+                                            member_clang_type = GetClangASTContext().CreateArrayType(member_array_element_type, 0, false);
+                                        }
+                                    }
+                                }
+                                
+                                field_decl = class_clang_type.AddFieldToRecordType (name,
+                                                                                    member_clang_type,
+                                                                                    accessibility,
+                                                                                    bit_size);
+                                
+                                GetClangASTContext().SetMetadataAsUserID (field_decl, MakeUserID(die->GetOffset()));
+                                
+                                if (this_field_info.IsValid())
+                                {
+                                    layout_info.field_offsets.insert(std::make_pair(field_decl, this_field_info.bit_offset));
+                                    last_field_info = this_field_info;
+                                }
+                            }
+                            else
+                            {
+                                if (name)
+                                    GetObjectFile()->GetModule()->ReportError ("0x%8.8" PRIx64 ": DW_TAG_member '%s' refers to type 0x%8.8" PRIx64 " which was unable to be parsed",
+                                                                               MakeUserID(die->GetOffset()),
+                                                                               name,
+                                                                               encoding_uid);
+                                else
+                                    GetObjectFile()->GetModule()->ReportError ("0x%8.8" PRIx64 ": DW_TAG_member refers to type 0x%8.8" PRIx64 " which was unable to be parsed",
+                                                                               MakeUserID(die->GetOffset()),
+                                                                               encoding_uid);
+                            }
+                        }
+                        
+                        if (prop_name != NULL)
+                        {
+                            clang::ObjCIvarDecl *ivar_decl = NULL;
+                            
+                            if (field_decl)
+                            {
+                                ivar_decl = clang::dyn_cast<clang::ObjCIvarDecl>(field_decl);
+                                assert (ivar_decl != NULL);
+                            }
+                            
+                            ClangASTMetadata metadata;
+                            metadata.SetUserID (MakeUserID(die->GetOffset()));
+                            delayed_properties.push_back(DelayedAddObjCClassProperty(class_clang_type,
+                                                                                     prop_name,
+                                                                                     member_type->GetClangLayoutType(),
+                                                                                     ivar_decl,
+                                                                                     prop_setter_name,
+                                                                                     prop_getter_name,
+                                                                                     prop_attributes,
+                                                                                     &metadata));
+                            
+                            if (ivar_decl)
+                                GetClangASTContext().SetMetadataAsUserID (ivar_decl, MakeUserID(die->GetOffset()));
+                        }
+                    }
+                }
+                ++member_idx;
+            }
+            break;
+
+        case DW_TAG_subprogram:
+            // Let the type parsing code handle this one for us. 
+            member_function_dies.Append (die);
+            break;
+
+        case DW_TAG_inheritance:
+            {
+                is_a_class = true;
+                if (default_accessibility == eAccessNone)
+                    default_accessibility = eAccessPrivate;
+                // TODO: implement DW_TAG_inheritance type parsing
+                DWARFDebugInfoEntry::Attributes attributes;
+                const size_t num_attributes = die->GetAttributes (this, 
+                                                                  dwarf_cu, 
+                                                                  fixed_form_sizes, 
+                                                                  attributes);
+                if (num_attributes > 0)
+                {
+                    Declaration decl;
+                    DWARFExpression location;
+                    lldb::user_id_t encoding_uid = LLDB_INVALID_UID;
+                    AccessType accessibility = default_accessibility;
+                    bool is_virtual = false;
+                    bool is_base_of_class = true;
+                    off_t member_byte_offset = 0;
+                    uint32_t i;
+                    for (i=0; i<num_attributes; ++i)
+                    {
+                        const dw_attr_t attr = attributes.AttributeAtIndex(i);
+                        DWARFFormValue form_value;
+                        if (attributes.ExtractFormValueAtIndex(this, i, form_value))
+                        {
+                            switch (attr)
+                            {
+                            case DW_AT_decl_file:   decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
+                            case DW_AT_decl_line:   decl.SetLine(form_value.Unsigned()); break;
+                            case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
+                            case DW_AT_type:        encoding_uid = form_value.Reference(dwarf_cu); break;
+                            case DW_AT_data_member_location:
+                                if (form_value.BlockData())
+                                {
+                                    Value initialValue(0);
+                                    Value memberOffset(0);
+                                    const DataExtractor& debug_info_data = get_debug_info_data();
+                                    uint32_t block_length = form_value.Unsigned();
+                                    uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart();
+                                    if (DWARFExpression::Evaluate (NULL, 
+                                                                   NULL, 
+                                                                   NULL, 
+                                                                   NULL,
+                                                                   debug_info_data, 
+                                                                   block_offset, 
+                                                                   block_length, 
+                                                                   eRegisterKindDWARF, 
+                                                                   &initialValue, 
+                                                                   memberOffset, 
+                                                                   NULL))
+                                    {
+                                        member_byte_offset = memberOffset.ResolveValue(NULL).UInt();
+                                    }
+                                }
+                                else
+                                {
+                                    // With DWARF 3 and later, if the value is an integer constant,
+                                    // this form value is the offset in bytes from the beginning
+                                    // of the containing entity. 
+                                    member_byte_offset = form_value.Unsigned(); 
+                                }
+                                break;
+
+                            case DW_AT_accessibility:
+                                accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned());
+                                break;
+
+                            case DW_AT_virtuality:
+                                is_virtual = form_value.Boolean();
+                                break;
+                                                   
+                            case DW_AT_sibling:
+                                break;
+
+                            default:
+                                break;
+                            }
+                        }
+                    }
+
+                    Type *base_class_type = ResolveTypeUID(encoding_uid);
+                    assert(base_class_type);
+                    
+                    ClangASTType base_class_clang_type = base_class_type->GetClangFullType();
+                    assert (base_class_clang_type);
+                    if (class_language == eLanguageTypeObjC)
+                    {
+                        class_clang_type.SetObjCSuperClass(base_class_clang_type);
+                    }
+                    else
+                    {
+                        base_classes.push_back (base_class_clang_type.CreateBaseClassSpecifier (accessibility,
+                                                                                               is_virtual, 
+                                                                                               is_base_of_class));
+                        
+                        if (is_virtual)
+                        {
+                            layout_info.vbase_offsets.insert(std::make_pair(class_clang_type.GetAsCXXRecordDecl(),
+                                                                            clang::CharUnits::fromQuantity(member_byte_offset)));
+                        }
+                        else
+                        {
+                            layout_info.base_offsets.insert(std::make_pair(class_clang_type.GetAsCXXRecordDecl(),
+                                                                           clang::CharUnits::fromQuantity(member_byte_offset)));
+                        }
+                    }
+                }
+            }
+            break;
+
+        default:
+            break;
+        }
+    }
+    
+    return count;
+}
+
+
+clang::DeclContext*
+SymbolFileDWARF::GetClangDeclContextContainingTypeUID (lldb::user_id_t type_uid)
+{
+    DWARFDebugInfo* debug_info = DebugInfo();
+    if (debug_info && UserIDMatches(type_uid))
+    {
+        DWARFCompileUnitSP cu_sp;
+        const DWARFDebugInfoEntry* die = debug_info->GetDIEPtr(type_uid, &cu_sp);
+        if (die)
+            return GetClangDeclContextContainingDIE (cu_sp.get(), die, NULL);
+    }
+    return NULL;
+}
+
+clang::DeclContext*
+SymbolFileDWARF::GetClangDeclContextForTypeUID (const lldb_private::SymbolContext &sc, lldb::user_id_t type_uid)
+{
+    if (UserIDMatches(type_uid))
+        return GetClangDeclContextForDIEOffset (sc, type_uid);
+    return NULL;
+}
+
+Type*
+SymbolFileDWARF::ResolveTypeUID (lldb::user_id_t type_uid)
+{
+    if (UserIDMatches(type_uid))
+    {
+        DWARFDebugInfo* debug_info = DebugInfo();
+        if (debug_info)
+        {
+            DWARFCompileUnitSP cu_sp;
+            const DWARFDebugInfoEntry* type_die = debug_info->GetDIEPtr(type_uid, &cu_sp);
+            const bool assert_not_being_parsed = true;
+            return ResolveTypeUID (cu_sp.get(), type_die, assert_not_being_parsed);
+        }
+    }
+    return NULL;
+}
+
+Type*
+SymbolFileDWARF::ResolveTypeUID (DWARFCompileUnit* cu, const DWARFDebugInfoEntry* die, bool assert_not_being_parsed)
+{    
+    if (die != NULL)
+    {
+        Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO));
+        if (log)
+            GetObjectFile()->GetModule()->LogMessage (log,
+                                                      "SymbolFileDWARF::ResolveTypeUID (die = 0x%8.8x) %s '%s'", 
+                                                      die->GetOffset(), 
+                                                      DW_TAG_value_to_name(die->Tag()), 
+                                                      die->GetName(this, cu));
+
+        // We might be coming in in the middle of a type tree (a class
+        // withing a class, an enum within a class), so parse any needed
+        // parent DIEs before we get to this one...
+        const DWARFDebugInfoEntry *decl_ctx_die = GetDeclContextDIEContainingDIE (cu, die);
+        switch (decl_ctx_die->Tag())
+        {
+            case DW_TAG_structure_type:
+            case DW_TAG_union_type:
+            case DW_TAG_class_type:
+            {
+                // Get the type, which could be a forward declaration
+                if (log)
+                    GetObjectFile()->GetModule()->LogMessage (log,
+                                                              "SymbolFileDWARF::ResolveTypeUID (die = 0x%8.8x) %s '%s' resolve parent forward type for 0x%8.8x", 
+                                                              die->GetOffset(), 
+                                                              DW_TAG_value_to_name(die->Tag()), 
+                                                              die->GetName(this, cu), 
+                                                              decl_ctx_die->GetOffset());
+//
+//                Type *parent_type = ResolveTypeUID (cu, decl_ctx_die, assert_not_being_parsed);
+//                if (child_requires_parent_class_union_or_struct_to_be_completed(die->Tag()))
+//                {
+//                    if (log)
+//                        GetObjectFile()->GetModule()->LogMessage (log,
+//                                                                  "SymbolFileDWARF::ResolveTypeUID (die = 0x%8.8x) %s '%s' resolve parent full type for 0x%8.8x since die is a function", 
+//                                                                  die->GetOffset(), 
+//                                                                  DW_TAG_value_to_name(die->Tag()), 
+//                                                                  die->GetName(this, cu), 
+//                                                                  decl_ctx_die->GetOffset());
+//                    // Ask the type to complete itself if it already hasn't since if we
+//                    // want a function (method or static) from a class, the class must 
+//                    // create itself and add it's own methods and class functions.
+//                    if (parent_type)
+//                        parent_type->GetClangFullType();
+//                }
+            }
+            break;
+
+            default:
+                break;
+        }
+        return ResolveType (cu, die);
+    }
+    return NULL;
+}
+
+// This function is used when SymbolFileDWARFDebugMap owns a bunch of
+// SymbolFileDWARF objects to detect if this DWARF file is the one that
+// can resolve a clang_type.
+bool
+SymbolFileDWARF::HasForwardDeclForClangType (const ClangASTType &clang_type)
+{
+    ClangASTType clang_type_no_qualifiers = clang_type.RemoveFastQualifiers();
+    const DWARFDebugInfoEntry* die = m_forward_decl_clang_type_to_die.lookup (clang_type_no_qualifiers.GetOpaqueQualType());
+    return die != NULL;
+}
+
+
+bool
+SymbolFileDWARF::ResolveClangOpaqueTypeDefinition (ClangASTType &clang_type)
+{
+    // We have a struct/union/class/enum that needs to be fully resolved.
+    ClangASTType clang_type_no_qualifiers = clang_type.RemoveFastQualifiers();
+    const DWARFDebugInfoEntry* die = m_forward_decl_clang_type_to_die.lookup (clang_type_no_qualifiers.GetOpaqueQualType());
+    if (die == NULL)
+    {
+        // We have already resolved this type...
+        return true;
+    }
+    // Once we start resolving this type, remove it from the forward declaration
+    // map in case anyone child members or other types require this type to get resolved.
+    // The type will get resolved when all of the calls to SymbolFileDWARF::ResolveClangOpaqueTypeDefinition
+    // are done.
+    m_forward_decl_clang_type_to_die.erase (clang_type_no_qualifiers.GetOpaqueQualType());
+    
+
+    // Disable external storage for this type so we don't get anymore 
+    // clang::ExternalASTSource queries for this type.
+    clang_type.SetHasExternalStorage (false);
+
+    DWARFDebugInfo* debug_info = DebugInfo();
+
+    DWARFCompileUnit *dwarf_cu = debug_info->GetCompileUnitContainingDIE (die->GetOffset()).get();
+    Type *type = m_die_to_type.lookup (die);
+
+    const dw_tag_t tag = die->Tag();
+
+    Log *log (LogChannelDWARF::GetLogIfAny(DWARF_LOG_DEBUG_INFO|DWARF_LOG_TYPE_COMPLETION));
+    if (log)
+    {
+        GetObjectFile()->GetModule()->LogMessageVerboseBacktrace (log,
+                                                                  "0x%8.8" PRIx64 ": %s '%s' resolving forward declaration...",
+                                                                  MakeUserID(die->GetOffset()),
+                                                                  DW_TAG_value_to_name(tag),
+                                                                  type->GetName().AsCString());
+    
+    }
+    assert (clang_type);
+    DWARFDebugInfoEntry::Attributes attributes;
+
+    switch (tag)
+    {
+    case DW_TAG_structure_type:
+    case DW_TAG_union_type:
+    case DW_TAG_class_type:
+        {
+            LayoutInfo layout_info;
+            
+            {
+                if (die->HasChildren())
+                {
+                    
+                    LanguageType class_language = eLanguageTypeUnknown;
+                    if (clang_type.IsObjCObjectOrInterfaceType())
+                    {
+                        class_language = eLanguageTypeObjC;
+                        // For objective C we don't start the definition when
+                        // the class is created.
+                        clang_type.StartTagDeclarationDefinition ();
+                    }
+                    
+                    int tag_decl_kind = -1;
+                    AccessType default_accessibility = eAccessNone;
+                    if (tag == DW_TAG_structure_type)
+                    {
+                        tag_decl_kind = clang::TTK_Struct;
+                        default_accessibility = eAccessPublic;
+                    }
+                    else if (tag == DW_TAG_union_type)
+                    {
+                        tag_decl_kind = clang::TTK_Union;
+                        default_accessibility = eAccessPublic;
+                    }
+                    else if (tag == DW_TAG_class_type)
+                    {
+                        tag_decl_kind = clang::TTK_Class;
+                        default_accessibility = eAccessPrivate;
+                    }
+                    
+                    SymbolContext sc(GetCompUnitForDWARFCompUnit(dwarf_cu));
+                    std::vector<clang::CXXBaseSpecifier *> base_classes;
+                    std::vector<int> member_accessibilities;
+                    bool is_a_class = false;
+                    // Parse members and base classes first
+                    DWARFDIECollection member_function_dies;
+                                        
+                    DelayedPropertyList delayed_properties;
+                    ParseChildMembers (sc,
+                                       dwarf_cu,
+                                       die, 
+                                       clang_type,
+                                       class_language,
+                                       base_classes, 
+                                       member_accessibilities,
+                                       member_function_dies,
+                                       delayed_properties,
+                                       default_accessibility, 
+                                       is_a_class,
+                                       layout_info);
+                    
+                    // Now parse any methods if there were any...
+                    size_t num_functions = member_function_dies.Size();                
+                    if (num_functions > 0)
+                    {
+                        for (size_t i=0; i<num_functions; ++i)
+                        {
+                            ResolveType(dwarf_cu, member_function_dies.GetDIEPtrAtIndex(i));
+                        }
+                    }
+                    
+                    if (class_language == eLanguageTypeObjC)
+                    {
+                        std::string class_str (clang_type.GetTypeName());
+                        if (!class_str.empty())
+                        {
+                            
+                            DIEArray method_die_offsets;
+                            if (m_using_apple_tables)
+                            {
+                                if (m_apple_objc_ap.get())
+                                    m_apple_objc_ap->FindByName(class_str.c_str(), method_die_offsets);
+                            }
+                            else
+                            {
+                                if (!m_indexed)
+                                    Index ();
+                                
+                                ConstString class_name (class_str.c_str());
+                                m_objc_class_selectors_index.Find (class_name, method_die_offsets);
+                            }
+                            
+                            if (!method_die_offsets.empty())
+                            {
+                                DWARFDebugInfo* debug_info = DebugInfo();
+                                
+                                DWARFCompileUnit* method_cu = NULL;
+                                const size_t num_matches = method_die_offsets.size();
+                                for (size_t i=0; i<num_matches; ++i)
+                                {
+                                    const dw_offset_t die_offset = method_die_offsets[i];
+                                    DWARFDebugInfoEntry *method_die = debug_info->GetDIEPtrWithCompileUnitHint (die_offset, &method_cu);
+                                    
+                                    if (method_die)
+                                        ResolveType (method_cu, method_die);
+                                    else
+                                    {
+                                        if (m_using_apple_tables)
+                                        {
+                                            GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_objc accelerator table had bad die 0x%8.8x for '%s')\n",
+                                                                                                       die_offset, class_str.c_str());
+                                        }
+                                    }            
+                                }
+                            }
+                            
+                            for (DelayedPropertyList::iterator pi = delayed_properties.begin(), pe = delayed_properties.end();
+                                 pi != pe;
+                                 ++pi)
+                                pi->Finalize();
+                        }
+                    }
+                    
+                    // If we have a DW_TAG_structure_type instead of a DW_TAG_class_type we
+                    // need to tell the clang type it is actually a class.
+                    if (class_language != eLanguageTypeObjC)
+                    {
+                        if (is_a_class && tag_decl_kind != clang::TTK_Class)
+                            clang_type.SetTagTypeKind (clang::TTK_Class);
+                    }
+                    
+                    // Since DW_TAG_structure_type gets used for both classes
+                    // and structures, we may need to set any DW_TAG_member
+                    // fields to have a "private" access if none was specified.
+                    // When we parsed the child members we tracked that actual
+                    // accessibility value for each DW_TAG_member in the
+                    // "member_accessibilities" array. If the value for the
+                    // member is zero, then it was set to the "default_accessibility"
+                    // which for structs was "public". Below we correct this
+                    // by setting any fields to "private" that weren't correctly
+                    // set.
+                    if (is_a_class && !member_accessibilities.empty())
+                    {
+                        // This is a class and all members that didn't have
+                        // their access specified are private.
+                        clang_type.SetDefaultAccessForRecordFields (eAccessPrivate,
+                                                                    &member_accessibilities.front(),
+                                                                    member_accessibilities.size());
+                    }
+                    
+                    if (!base_classes.empty())
+                    {
+                        clang_type.SetBaseClassesForClassType (&base_classes.front(),
+                                                               base_classes.size());
+                        
+                        // Clang will copy each CXXBaseSpecifier in "base_classes"
+                        // so we have to free them all.
+                        ClangASTType::DeleteBaseClassSpecifiers (&base_classes.front(),
+                                                                 base_classes.size());
+                    }
+                }
+            }
+            
+            clang_type.BuildIndirectFields ();
+            clang_type.CompleteTagDeclarationDefinition ();
+            
+            if (!layout_info.field_offsets.empty() ||
+                !layout_info.base_offsets.empty()  ||
+                !layout_info.vbase_offsets.empty() )
+            {
+                if (type)
+                    layout_info.bit_size = type->GetByteSize() * 8;
+                if (layout_info.bit_size == 0)
+                    layout_info.bit_size = die->GetAttributeValueAsUnsigned(this, dwarf_cu, DW_AT_byte_size, 0) * 8;
+                
+                clang::CXXRecordDecl *record_decl = clang_type.GetAsCXXRecordDecl();
+                if (record_decl)
+                {
+                    if (log)
+                    {
+                        GetObjectFile()->GetModule()->LogMessage (log,
+                                                                  "SymbolFileDWARF::ResolveClangOpaqueTypeDefinition (clang_type = %p) caching layout info for record_decl = %p, bit_size = %" PRIu64 ", alignment = %" PRIu64 ", field_offsets[%u], base_offsets[%u], vbase_offsets[%u])",
+                                                                  clang_type.GetOpaqueQualType(),
+                                                                  record_decl,
+                                                                  layout_info.bit_size,
+                                                                  layout_info.alignment,
+                                                                  (uint32_t)layout_info.field_offsets.size(),
+                                                                  (uint32_t)layout_info.base_offsets.size(),
+                                                                  (uint32_t)layout_info.vbase_offsets.size());
+                        
+                        uint32_t idx;
+                        {
+                        llvm::DenseMap <const clang::FieldDecl *, uint64_t>::const_iterator pos, end = layout_info.field_offsets.end();
+                        for (idx = 0, pos = layout_info.field_offsets.begin(); pos != end; ++pos, ++idx)
+                        {
+                            GetObjectFile()->GetModule()->LogMessage (log,
+                                                                      "SymbolFileDWARF::ResolveClangOpaqueTypeDefinition (clang_type = %p) field[%u] = { bit_offset=%u, name='%s' }",
+                                                                      clang_type.GetOpaqueQualType(),
+                                                                      idx,
+                                                                      (uint32_t)pos->second,
+                                                                      pos->first->getNameAsString().c_str());
+                        }
+                        }
+                        
+                        {
+                        llvm::DenseMap <const clang::CXXRecordDecl *, clang::CharUnits>::const_iterator base_pos, base_end = layout_info.base_offsets.end();
+                        for (idx = 0, base_pos = layout_info.base_offsets.begin(); base_pos != base_end; ++base_pos, ++idx)
+                        {
+                            GetObjectFile()->GetModule()->LogMessage (log,
+                                                                      "SymbolFileDWARF::ResolveClangOpaqueTypeDefinition (clang_type = %p) base[%u] = { byte_offset=%u, name='%s' }",
+                                                                      clang_type.GetOpaqueQualType(),
+                                                                      idx,
+                                                                      (uint32_t)base_pos->second.getQuantity(),
+                                                                      base_pos->first->getNameAsString().c_str());
+                        }
+                        }
+                        {
+                        llvm::DenseMap <const clang::CXXRecordDecl *, clang::CharUnits>::const_iterator vbase_pos, vbase_end = layout_info.vbase_offsets.end();
+                        for (idx = 0, vbase_pos = layout_info.vbase_offsets.begin(); vbase_pos != vbase_end; ++vbase_pos, ++idx)
+                        {
+                            GetObjectFile()->GetModule()->LogMessage (log,
+                                                                      "SymbolFileDWARF::ResolveClangOpaqueTypeDefinition (clang_type = %p) vbase[%u] = { byte_offset=%u, name='%s' }",
+                                                                      clang_type.GetOpaqueQualType(),
+                                                                      idx,
+                                                                      (uint32_t)vbase_pos->second.getQuantity(),
+                                                                      vbase_pos->first->getNameAsString().c_str());
+                        }
+                        }
+                    }
+                    m_record_decl_to_layout_map.insert(std::make_pair(record_decl, layout_info));
+                }
+            }
+        }
+
+        return clang_type;
+
+    case DW_TAG_enumeration_type:
+        clang_type.StartTagDeclarationDefinition ();
+        if (die->HasChildren())
+        {
+            SymbolContext sc(GetCompUnitForDWARFCompUnit(dwarf_cu));
+            bool is_signed = false;
+            clang_type.IsIntegerType(is_signed);
+            ParseChildEnumerators(sc, clang_type, is_signed, type->GetByteSize(), dwarf_cu, die);
+        }
+        clang_type.CompleteTagDeclarationDefinition ();
+        return clang_type;
+
+    default:
+        assert(false && "not a forward clang type decl!");
+        break;
+    }
+    return false;
+}
+
+Type*
+SymbolFileDWARF::ResolveType (DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry* type_die, bool assert_not_being_parsed)
+{
+    if (type_die != NULL)
+    {
+        Type *type = m_die_to_type.lookup (type_die);
+
+        if (type == NULL)
+            type = GetTypeForDIE (dwarf_cu, type_die).get();
+
+        if (assert_not_being_parsed)
+        { 
+            if (type != DIE_IS_BEING_PARSED)
+                return type;
+            
+            GetObjectFile()->GetModule()->ReportError ("Parsing a die that is being parsed die: 0x%8.8x: %s %s",
+                                                       type_die->GetOffset(), 
+                                                       DW_TAG_value_to_name(type_die->Tag()), 
+                                                       type_die->GetName(this, dwarf_cu));
+
+        }
+        else
+            return type;
+    }
+    return NULL;
+}
+
+CompileUnit*
+SymbolFileDWARF::GetCompUnitForDWARFCompUnit (DWARFCompileUnit* dwarf_cu, uint32_t cu_idx)
+{
+    // Check if the symbol vendor already knows about this compile unit?
+    if (dwarf_cu->GetUserData() == NULL)
+    {
+        // The symbol vendor doesn't know about this compile unit, we
+        // need to parse and add it to the symbol vendor object.
+        return ParseCompileUnit(dwarf_cu, cu_idx).get();
+    }
+    return (CompileUnit*)dwarf_cu->GetUserData();
+}
+
+bool
+SymbolFileDWARF::GetFunction (DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry* func_die, SymbolContext& sc)
+{
+    sc.Clear(false);
+    // Check if the symbol vendor already knows about this compile unit?
+    sc.comp_unit = GetCompUnitForDWARFCompUnit(dwarf_cu, UINT32_MAX);
+
+    sc.function = sc.comp_unit->FindFunctionByUID (MakeUserID(func_die->GetOffset())).get();
+    if (sc.function == NULL)
+        sc.function = ParseCompileUnitFunction(sc, dwarf_cu, func_die);
+        
+    if (sc.function)
+    {        
+        sc.module_sp = sc.function->CalculateSymbolContextModule();
+        return true;
+    }
+    
+    return false;
+}
+
+uint32_t
+SymbolFileDWARF::ResolveSymbolContext (const Address& so_addr, uint32_t resolve_scope, SymbolContext& sc)
+{
+    Timer scoped_timer(__PRETTY_FUNCTION__,
+                       "SymbolFileDWARF::ResolveSymbolContext (so_addr = { section = %p, offset = 0x%" PRIx64 " }, resolve_scope = 0x%8.8x)",
+                       so_addr.GetSection().get(),
+                       so_addr.GetOffset(),
+                       resolve_scope);
+    uint32_t resolved = 0;
+    if (resolve_scope & (   eSymbolContextCompUnit |
+                            eSymbolContextFunction |
+                            eSymbolContextBlock |
+                            eSymbolContextLineEntry))
+    {
+        lldb::addr_t file_vm_addr = so_addr.GetFileAddress();
+
+        DWARFDebugInfo* debug_info = DebugInfo();
+        if (debug_info)
+        {
+            const dw_offset_t cu_offset = debug_info->GetCompileUnitAranges().FindAddress(file_vm_addr);
+            if (cu_offset != DW_INVALID_OFFSET)
+            {
+                uint32_t cu_idx = DW_INVALID_INDEX;
+                DWARFCompileUnit* dwarf_cu = debug_info->GetCompileUnit(cu_offset, &cu_idx).get();
+                if (dwarf_cu)
+                {
+                    sc.comp_unit = GetCompUnitForDWARFCompUnit(dwarf_cu, cu_idx);
+                    if (sc.comp_unit)
+                    {
+                        resolved |= eSymbolContextCompUnit;
+
+                        bool force_check_line_table = false;
+                        if (resolve_scope & (eSymbolContextFunction | eSymbolContextBlock))
+                        {
+                            DWARFDebugInfoEntry *function_die = NULL;
+                            DWARFDebugInfoEntry *block_die = NULL;
+                            if (resolve_scope & eSymbolContextBlock)
+                            {
+                                dwarf_cu->LookupAddress(file_vm_addr, &function_die, &block_die);
+                            }
+                            else
+                            {
+                                dwarf_cu->LookupAddress(file_vm_addr, &function_die, NULL);
+                            }
+
+                            if (function_die != NULL)
+                            {
+                                sc.function = sc.comp_unit->FindFunctionByUID (MakeUserID(function_die->GetOffset())).get();
+                                if (sc.function == NULL)
+                                    sc.function = ParseCompileUnitFunction(sc, dwarf_cu, function_die);
+                            }
+                            else
+                            {
+                                // We might have had a compile unit that had discontiguous
+                                // address ranges where the gaps are symbols that don't have
+                                // any debug info. Discontiguous compile unit address ranges
+                                // should only happen when there aren't other functions from
+                                // other compile units in these gaps. This helps keep the size
+                                // of the aranges down.
+                                force_check_line_table = true;
+                            }
+
+                            if (sc.function != NULL)
+                            {
+                                resolved |= eSymbolContextFunction;
+
+                                if (resolve_scope & eSymbolContextBlock)
+                                {
+                                    Block& block = sc.function->GetBlock (true);
+
+                                    if (block_die != NULL)
+                                        sc.block = block.FindBlockByID (MakeUserID(block_die->GetOffset()));
+                                    else
+                                        sc.block = block.FindBlockByID (MakeUserID(function_die->GetOffset()));
+                                    if (sc.block)
+                                        resolved |= eSymbolContextBlock;
+                                }
+                            }
+                        }
+                        
+                        if ((resolve_scope & eSymbolContextLineEntry) || force_check_line_table)
+                        {
+                            LineTable *line_table = sc.comp_unit->GetLineTable();
+                            if (line_table != NULL)
+                            {
+                                // And address that makes it into this function should be in terms
+                                // of this debug file if there is no debug map, or it will be an
+                                // address in the .o file which needs to be fixed up to be in terms
+                                // of the debug map executable. Either way, calling FixupAddress()
+                                // will work for us.
+                                Address exe_so_addr (so_addr);
+                                if (FixupAddress(exe_so_addr))
+                                {
+                                    if (line_table->FindLineEntryByAddress (exe_so_addr, sc.line_entry))
+                                    {
+                                        resolved |= eSymbolContextLineEntry;
+                                    }
+                                }
+                            }
+                        }
+                        
+                        if (force_check_line_table && !(resolved & eSymbolContextLineEntry))
+                        {
+                            // We might have had a compile unit that had discontiguous
+                            // address ranges where the gaps are symbols that don't have
+                            // any debug info. Discontiguous compile unit address ranges
+                            // should only happen when there aren't other functions from
+                            // other compile units in these gaps. This helps keep the size
+                            // of the aranges down.
+                            sc.comp_unit = NULL;
+                            resolved &= ~eSymbolContextCompUnit;
+                        }
+                    }
+                    else
+                    {
+                        GetObjectFile()->GetModule()->ReportWarning ("0x%8.8x: compile unit %u failed to create a valid lldb_private::CompileUnit class.",
+                                                                     cu_offset,
+                                                                     cu_idx);
+                    }
+                }
+            }
+        }
+    }
+    return resolved;
+}
+
+
+
+uint32_t
+SymbolFileDWARF::ResolveSymbolContext(const FileSpec& file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list)
+{
+    const uint32_t prev_size = sc_list.GetSize();
+    if (resolve_scope & eSymbolContextCompUnit)
+    {
+        DWARFDebugInfo* debug_info = DebugInfo();
+        if (debug_info)
+        {
+            uint32_t cu_idx;
+            DWARFCompileUnit* dwarf_cu = NULL;
+
+            for (cu_idx = 0; (dwarf_cu = debug_info->GetCompileUnitAtIndex(cu_idx)) != NULL; ++cu_idx)
+            {
+                CompileUnit *dc_cu = GetCompUnitForDWARFCompUnit(dwarf_cu, cu_idx);
+                const bool full_match = file_spec.GetDirectory();
+                bool file_spec_matches_cu_file_spec = dc_cu != NULL && FileSpec::Equal(file_spec, *dc_cu, full_match);
+                if (check_inlines || file_spec_matches_cu_file_spec)
+                {
+                    SymbolContext sc (m_obj_file->GetModule());
+                    sc.comp_unit = GetCompUnitForDWARFCompUnit(dwarf_cu, cu_idx);
+                    if (sc.comp_unit)
+                    {
+                        uint32_t file_idx = UINT32_MAX;
+
+                        // If we are looking for inline functions only and we don't
+                        // find it in the support files, we are done.
+                        if (check_inlines)
+                        {
+                            file_idx = sc.comp_unit->GetSupportFiles().FindFileIndex (1, file_spec, true);
+                            if (file_idx == UINT32_MAX)
+                                continue;
+                        }
+
+                        if (line != 0)
+                        {
+                            LineTable *line_table = sc.comp_unit->GetLineTable();
+
+                            if (line_table != NULL && line != 0)
+                            {
+                                // We will have already looked up the file index if
+                                // we are searching for inline entries.
+                                if (!check_inlines)
+                                    file_idx = sc.comp_unit->GetSupportFiles().FindFileIndex (1, file_spec, true);
+
+                                if (file_idx != UINT32_MAX)
+                                {
+                                    uint32_t found_line;
+                                    uint32_t line_idx = line_table->FindLineEntryIndexByFileIndex (0, file_idx, line, false, &sc.line_entry);
+                                    found_line = sc.line_entry.line;
+
+                                    while (line_idx != UINT32_MAX)
+                                    {
+                                        sc.function = NULL;
+                                        sc.block = NULL;
+                                        if (resolve_scope & (eSymbolContextFunction | eSymbolContextBlock))
+                                        {
+                                            const lldb::addr_t file_vm_addr = sc.line_entry.range.GetBaseAddress().GetFileAddress();
+                                            if (file_vm_addr != LLDB_INVALID_ADDRESS)
+                                            {
+                                                DWARFDebugInfoEntry *function_die = NULL;
+                                                DWARFDebugInfoEntry *block_die = NULL;
+                                                dwarf_cu->LookupAddress(file_vm_addr, &function_die, resolve_scope & eSymbolContextBlock ? &block_die : NULL);
+
+                                                if (function_die != NULL)
+                                                {
+                                                    sc.function = sc.comp_unit->FindFunctionByUID (MakeUserID(function_die->GetOffset())).get();
+                                                    if (sc.function == NULL)
+                                                        sc.function = ParseCompileUnitFunction(sc, dwarf_cu, function_die);
+                                                }
+
+                                                if (sc.function != NULL)
+                                                {
+                                                    Block& block = sc.function->GetBlock (true);
+
+                                                    if (block_die != NULL)
+                                                        sc.block = block.FindBlockByID (MakeUserID(block_die->GetOffset()));
+                                                    else
+                                                        sc.block = block.FindBlockByID (MakeUserID(function_die->GetOffset()));
+                                                }
+                                            }
+                                        }
+
+                                        sc_list.Append(sc);
+                                        line_idx = line_table->FindLineEntryIndexByFileIndex (line_idx + 1, file_idx, found_line, true, &sc.line_entry);
+                                    }
+                                }
+                            }
+                            else if (file_spec_matches_cu_file_spec && !check_inlines)
+                            {
+                                // only append the context if we aren't looking for inline call sites
+                                // by file and line and if the file spec matches that of the compile unit
+                                sc_list.Append(sc);
+                            }
+                        }
+                        else if (file_spec_matches_cu_file_spec && !check_inlines)
+                        {
+                            // only append the context if we aren't looking for inline call sites
+                            // by file and line and if the file spec matches that of the compile unit
+                            sc_list.Append(sc);
+                        }
+
+                        if (!check_inlines)
+                            break;
+                    }
+                }
+            }
+        }
+    }
+    return sc_list.GetSize() - prev_size;
+}
+
+void
+SymbolFileDWARF::Index ()
+{
+    if (m_indexed)
+        return;
+    m_indexed = true;
+    Timer scoped_timer (__PRETTY_FUNCTION__,
+                        "SymbolFileDWARF::Index (%s)",
+                        GetObjectFile()->GetFileSpec().GetFilename().AsCString());
+
+    DWARFDebugInfo* debug_info = DebugInfo();
+    if (debug_info)
+    {
+        uint32_t cu_idx = 0;
+        const uint32_t num_compile_units = GetNumCompileUnits();
+        for (cu_idx = 0; cu_idx < num_compile_units; ++cu_idx)
+        {
+            DWARFCompileUnit* dwarf_cu = debug_info->GetCompileUnitAtIndex(cu_idx);
+
+            bool clear_dies = dwarf_cu->ExtractDIEsIfNeeded (false) > 1;
+
+            dwarf_cu->Index (cu_idx,
+                             m_function_basename_index,
+                             m_function_fullname_index,
+                             m_function_method_index,
+                             m_function_selector_index,
+                             m_objc_class_selectors_index,
+                             m_global_index, 
+                             m_type_index,
+                             m_namespace_index);
+            
+            // Keep memory down by clearing DIEs if this generate function
+            // caused them to be parsed
+            if (clear_dies)
+                dwarf_cu->ClearDIEs (true);
+        }
+        
+        m_function_basename_index.Finalize();
+        m_function_fullname_index.Finalize();
+        m_function_method_index.Finalize();
+        m_function_selector_index.Finalize();
+        m_objc_class_selectors_index.Finalize();
+        m_global_index.Finalize(); 
+        m_type_index.Finalize();
+        m_namespace_index.Finalize();
+
+#if defined (ENABLE_DEBUG_PRINTF)
+        StreamFile s(stdout, false);
+        s.Printf ("DWARF index for '%s':",
+                  GetObjectFile()->GetFileSpec().GetPath().c_str());
+        s.Printf("\nFunction basenames:\n");    m_function_basename_index.Dump (&s);
+        s.Printf("\nFunction fullnames:\n");    m_function_fullname_index.Dump (&s);
+        s.Printf("\nFunction methods:\n");      m_function_method_index.Dump (&s);
+        s.Printf("\nFunction selectors:\n");    m_function_selector_index.Dump (&s);
+        s.Printf("\nObjective C class selectors:\n");    m_objc_class_selectors_index.Dump (&s);
+        s.Printf("\nGlobals and statics:\n");   m_global_index.Dump (&s); 
+        s.Printf("\nTypes:\n");                 m_type_index.Dump (&s);
+        s.Printf("\nNamepaces:\n");             m_namespace_index.Dump (&s);
+#endif
+    }
+}
+
+bool
+SymbolFileDWARF::NamespaceDeclMatchesThisSymbolFile (const ClangNamespaceDecl *namespace_decl)
+{
+    if (namespace_decl == NULL)
+    {
+        // Invalid namespace decl which means we aren't matching only things
+        // in this symbol file, so return true to indicate it matches this
+        // symbol file.
+        return true;
+    }
+    
+    clang::ASTContext *namespace_ast = namespace_decl->GetASTContext();
+
+    if (namespace_ast == NULL)
+        return true;    // No AST in the "namespace_decl", return true since it 
+                        // could then match any symbol file, including this one
+
+    if (namespace_ast == GetClangASTContext().getASTContext())
+        return true;    // The ASTs match, return true
+    
+    // The namespace AST was valid, and it does not match...
+    Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS));
+
+    if (log)
+        GetObjectFile()->GetModule()->LogMessage(log, "Valid namespace does not match symbol file");
+    
+    return false;
+}
+
+bool
+SymbolFileDWARF::DIEIsInNamespace (const ClangNamespaceDecl *namespace_decl, 
+                                   DWARFCompileUnit* cu, 
+                                   const DWARFDebugInfoEntry* die)
+{
+    // No namespace specified, so the answesr i
+    if (namespace_decl == NULL)
+        return true;
+    
+    Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS));
+
+    const DWARFDebugInfoEntry *decl_ctx_die = NULL;
+    clang::DeclContext *die_clang_decl_ctx = GetClangDeclContextContainingDIE (cu, die, &decl_ctx_die);
+    if (decl_ctx_die)
+    { 
+        clang::NamespaceDecl *clang_namespace_decl = namespace_decl->GetNamespaceDecl();
+
+        if (clang_namespace_decl)
+        {
+            if (decl_ctx_die->Tag() != DW_TAG_namespace)
+            {
+                if (log)
+                    GetObjectFile()->GetModule()->LogMessage(log, "Found a match, but its parent is not a namespace");
+                return false;
+            }
+                
+            if (clang_namespace_decl == die_clang_decl_ctx)
+                return true;
+            else
+                return false;
+        }
+        else
+        {
+            // We have a namespace_decl that was not NULL but it contained
+            // a NULL "clang::NamespaceDecl", so this means the global namespace
+            // So as long the the contained decl context DIE isn't a namespace
+            // we should be ok.
+            if (decl_ctx_die->Tag() != DW_TAG_namespace)
+                return true;
+        }
+    }
+    
+    if (log)
+        GetObjectFile()->GetModule()->LogMessage(log, "Found a match, but its parent doesn't exist");
+    
+    return false;
+}
+uint32_t
+SymbolFileDWARF::FindGlobalVariables (const ConstString &name, const lldb_private::ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, VariableList& variables)
+{
+    Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS));
+
+    if (log)
+    {
+        GetObjectFile()->GetModule()->LogMessage (log,
+                                                  "SymbolFileDWARF::FindGlobalVariables (name=\"%s\", namespace_decl=%p, append=%u, max_matches=%u, variables)", 
+                                                  name.GetCString(), 
+                                                  namespace_decl,
+                                                  append, 
+                                                  max_matches);
+    }
+    
+    if (!NamespaceDeclMatchesThisSymbolFile(namespace_decl))
+		return 0;
+    
+    DWARFDebugInfo* info = DebugInfo();
+    if (info == NULL)
+        return 0;
+
+    // If we aren't appending the results to this list, then clear the list
+    if (!append)
+        variables.Clear();
+
+    // Remember how many variables are in the list before we search in case
+    // we are appending the results to a variable list.
+    const uint32_t original_size = variables.GetSize();
+
+    DIEArray die_offsets;
+    
+    if (m_using_apple_tables)
+    {
+        if (m_apple_names_ap.get())
+        {
+            const char *name_cstr = name.GetCString();
+            const char *base_name_start;
+            const char *base_name_end = NULL;
+            
+            if (!CPPLanguageRuntime::StripNamespacesFromVariableName(name_cstr, base_name_start, base_name_end))
+                base_name_start = name_cstr;
+                
+            m_apple_names_ap->FindByName (base_name_start, die_offsets);
+        }
+    }
+    else
+    {
+        // Index the DWARF if we haven't already
+        if (!m_indexed)
+            Index ();
+
+        m_global_index.Find (name, die_offsets);
+    }
+    
+    const size_t num_die_matches = die_offsets.size();
+    if (num_die_matches)
+    {
+        SymbolContext sc;
+        sc.module_sp = m_obj_file->GetModule();
+        assert (sc.module_sp);
+        
+        DWARFDebugInfo* debug_info = DebugInfo();
+        DWARFCompileUnit* dwarf_cu = NULL;
+        const DWARFDebugInfoEntry* die = NULL;
+        bool done = false;
+        for (size_t i=0; i<num_die_matches && !done; ++i)
+        {
+            const dw_offset_t die_offset = die_offsets[i];
+            die = debug_info->GetDIEPtrWithCompileUnitHint (die_offset, &dwarf_cu);
+
+            if (die)
+            {
+                switch (die->Tag())
+                {
+                    default:
+                    case DW_TAG_subprogram:
+                    case DW_TAG_inlined_subroutine:
+                    case DW_TAG_try_block:
+                    case DW_TAG_catch_block:
+                        break;
+                        
+                    case DW_TAG_variable:
+                        {
+                            sc.comp_unit = GetCompUnitForDWARFCompUnit(dwarf_cu, UINT32_MAX);
+                    
+                            if (namespace_decl && !DIEIsInNamespace (namespace_decl, dwarf_cu, die))
+                                continue;
+
+                            ParseVariables(sc, dwarf_cu, LLDB_INVALID_ADDRESS, die, false, false, &variables);
+
+                            if (variables.GetSize() - original_size >= max_matches)
+                                done = true;
+                        }
+                        break;
+                }
+            }
+            else
+            {
+                if (m_using_apple_tables)
+                {
+                    GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_names accelerator table had bad die 0x%8.8x for '%s')\n",
+                                                                               die_offset, name.GetCString());
+                }
+            }
+        }
+    }
+
+    // Return the number of variable that were appended to the list
+    const uint32_t num_matches = variables.GetSize() - original_size;
+    if (log && num_matches > 0)
+    {
+        GetObjectFile()->GetModule()->LogMessage (log,
+                                                  "SymbolFileDWARF::FindGlobalVariables (name=\"%s\", namespace_decl=%p, append=%u, max_matches=%u, variables) => %u",
+                                                  name.GetCString(), 
+                                                  namespace_decl,
+                                                  append, 
+                                                  max_matches,
+                                                  num_matches);
+    }
+    return num_matches;
+}
+
+uint32_t
+SymbolFileDWARF::FindGlobalVariables(const RegularExpression& regex, bool append, uint32_t max_matches, VariableList& variables)
+{
+    Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS));
+    
+    if (log)
+    {
+        GetObjectFile()->GetModule()->LogMessage (log,
+                                                  "SymbolFileDWARF::FindGlobalVariables (regex=\"%s\", append=%u, max_matches=%u, variables)", 
+                                                  regex.GetText(), 
+                                                  append, 
+                                                  max_matches);
+    }
+
+    DWARFDebugInfo* info = DebugInfo();
+    if (info == NULL)
+        return 0;
+
+    // If we aren't appending the results to this list, then clear the list
+    if (!append)
+        variables.Clear();
+
+    // Remember how many variables are in the list before we search in case
+    // we are appending the results to a variable list.
+    const uint32_t original_size = variables.GetSize();
+
+    DIEArray die_offsets;
+    
+    if (m_using_apple_tables)
+    {
+        if (m_apple_names_ap.get())
+        {
+            DWARFMappedHash::DIEInfoArray hash_data_array;
+            if (m_apple_names_ap->AppendAllDIEsThatMatchingRegex (regex, hash_data_array))
+                DWARFMappedHash::ExtractDIEArray (hash_data_array, die_offsets);
+        }
+    }
+    else
+    {
+        // Index the DWARF if we haven't already
+        if (!m_indexed)
+            Index ();
+        
+        m_global_index.Find (regex, die_offsets);
+    }
+
+    SymbolContext sc;
+    sc.module_sp = m_obj_file->GetModule();
+    assert (sc.module_sp);
+    
+    DWARFCompileUnit* dwarf_cu = NULL;
+    const DWARFDebugInfoEntry* die = NULL;
+    const size_t num_matches = die_offsets.size();
+    if (num_matches)
+    {
+        DWARFDebugInfo* debug_info = DebugInfo();
+        for (size_t i=0; i<num_matches; ++i)
+        {
+            const dw_offset_t die_offset = die_offsets[i];
+            die = debug_info->GetDIEPtrWithCompileUnitHint (die_offset, &dwarf_cu);
+            
+            if (die)
+            {
+                sc.comp_unit = GetCompUnitForDWARFCompUnit(dwarf_cu, UINT32_MAX);
+
+                ParseVariables(sc, dwarf_cu, LLDB_INVALID_ADDRESS, die, false, false, &variables);
+
+                if (variables.GetSize() - original_size >= max_matches)
+                    break;
+            }
+            else
+            {
+                if (m_using_apple_tables)
+                {
+                    GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_names accelerator table had bad die 0x%8.8x for regex '%s')\n",
+                                                                               die_offset, regex.GetText());
+                }
+            }            
+        }
+    }
+
+    // Return the number of variable that were appended to the list
+    return variables.GetSize() - original_size;
+}
+
+
+bool
+SymbolFileDWARF::ResolveFunction (dw_offset_t die_offset,
+                                  DWARFCompileUnit *&dwarf_cu,
+                                  SymbolContextList& sc_list)
+{
+    const DWARFDebugInfoEntry *die = DebugInfo()->GetDIEPtrWithCompileUnitHint (die_offset, &dwarf_cu);
+    return ResolveFunction (dwarf_cu, die, sc_list);
+}
+    
+
+bool
+SymbolFileDWARF::ResolveFunction (DWARFCompileUnit *cu,
+                                  const DWARFDebugInfoEntry *die,
+                                  SymbolContextList& sc_list)
+{
+    SymbolContext sc;
+
+    if (die == NULL)
+        return false;
+
+    // If we were passed a die that is not a function, just return false...
+    if (die->Tag() != DW_TAG_subprogram && die->Tag() != DW_TAG_inlined_subroutine)
+        return false;
+    
+    const DWARFDebugInfoEntry* inlined_die = NULL;
+    if (die->Tag() == DW_TAG_inlined_subroutine)
+    {
+        inlined_die = die;
+        
+        while ((die = die->GetParent()) != NULL)
+        {
+            if (die->Tag() == DW_TAG_subprogram)
+                break;
+        }
+    }
+    assert (die->Tag() == DW_TAG_subprogram);
+    if (GetFunction (cu, die, sc))
+    {
+        Address addr;
+        // Parse all blocks if needed
+        if (inlined_die)
+        {
+            sc.block = sc.function->GetBlock (true).FindBlockByID (MakeUserID(inlined_die->GetOffset()));
+            assert (sc.block != NULL);
+            if (sc.block->GetStartAddress (addr) == false)
+                addr.Clear();
+        }
+        else 
+        {
+            sc.block = NULL;
+            addr = sc.function->GetAddressRange().GetBaseAddress();
+        }
+
+        if (addr.IsValid())
+        {
+            sc_list.Append(sc);
+            return true;
+        }
+    }
+    
+    return false;
+}
+
+void
+SymbolFileDWARF::FindFunctions (const ConstString &name, 
+                                const NameToDIE &name_to_die,
+                                SymbolContextList& sc_list)
+{
+    DIEArray die_offsets;
+    if (name_to_die.Find (name, die_offsets))
+    {
+        ParseFunctions (die_offsets, sc_list);
+    }
+}
+
+
+void
+SymbolFileDWARF::FindFunctions (const RegularExpression &regex, 
+                                const NameToDIE &name_to_die,
+                                SymbolContextList& sc_list)
+{
+    DIEArray die_offsets;
+    if (name_to_die.Find (regex, die_offsets))
+    {
+        ParseFunctions (die_offsets, sc_list);
+    }
+}
+
+
+void
+SymbolFileDWARF::FindFunctions (const RegularExpression &regex, 
+                                const DWARFMappedHash::MemoryTable &memory_table,
+                                SymbolContextList& sc_list)
+{
+    DIEArray die_offsets;
+    DWARFMappedHash::DIEInfoArray hash_data_array;
+    if (memory_table.AppendAllDIEsThatMatchingRegex (regex, hash_data_array))
+    {
+        DWARFMappedHash::ExtractDIEArray (hash_data_array, die_offsets);
+        ParseFunctions (die_offsets, sc_list);
+    }
+}
+
+void
+SymbolFileDWARF::ParseFunctions (const DIEArray &die_offsets,
+                                 SymbolContextList& sc_list)
+{
+    const size_t num_matches = die_offsets.size();
+    if (num_matches)
+    {
+        SymbolContext sc;
+
+        DWARFCompileUnit* dwarf_cu = NULL;
+        for (size_t i=0; i<num_matches; ++i)
+        {
+            const dw_offset_t die_offset = die_offsets[i];
+            ResolveFunction (die_offset, dwarf_cu, sc_list);
+        }
+    }
+}
+
+bool
+SymbolFileDWARF::FunctionDieMatchesPartialName (const DWARFDebugInfoEntry* die,
+                                                const DWARFCompileUnit *dwarf_cu,
+                                                uint32_t name_type_mask, 
+                                                const char *partial_name,
+                                                const char *base_name_start,
+                                                const char *base_name_end)
+{
+    // If we are looking only for methods, throw away all the ones that are or aren't in C++ classes:
+    if (name_type_mask == eFunctionNameTypeMethod || name_type_mask == eFunctionNameTypeBase)
+    {
+        clang::DeclContext *containing_decl_ctx = GetClangDeclContextContainingDIEOffset(die->GetOffset());
+        if (!containing_decl_ctx)
+            return false;
+        
+        bool is_cxx_method = DeclKindIsCXXClass(containing_decl_ctx->getDeclKind());
+        
+        if (name_type_mask == eFunctionNameTypeMethod)
+        {
+            if (is_cxx_method == false)
+                return false;
+        }
+        
+        if (name_type_mask == eFunctionNameTypeBase)
+        {
+            if (is_cxx_method == true)
+                return false;
+        }
+    }
+
+    // Now we need to check whether the name we got back for this type matches the extra specifications
+    // that were in the name we're looking up:
+    if (base_name_start != partial_name || *base_name_end != '\0')
+    {
+        // First see if the stuff to the left matches the full name.  To do that let's see if
+        // we can pull out the mips linkage name attribute:
+        
+        Mangled best_name;
+        DWARFDebugInfoEntry::Attributes attributes;
+        DWARFFormValue form_value;
+        die->GetAttributes(this, dwarf_cu, NULL, attributes);
+        uint32_t idx = attributes.FindAttributeIndex(DW_AT_MIPS_linkage_name);
+        if (idx == UINT32_MAX)
+            idx = attributes.FindAttributeIndex(DW_AT_linkage_name);
+        if (idx != UINT32_MAX)
+        {
+            if (attributes.ExtractFormValueAtIndex(this, idx, form_value))
+            {
+                const char *mangled_name = form_value.AsCString(&get_debug_str_data());
+                if (mangled_name)
+                    best_name.SetValue (ConstString(mangled_name), true);
+            }
+        }
+
+        if (!best_name)
+        {
+            idx = attributes.FindAttributeIndex(DW_AT_name);
+            if (idx != UINT32_MAX && attributes.ExtractFormValueAtIndex(this, idx, form_value))
+            {
+                const char *name = form_value.AsCString(&get_debug_str_data());
+                best_name.SetValue (ConstString(name), false);
+            }
+        }
+
+        if (best_name.GetDemangledName())
+        {
+            const char *demangled = best_name.GetDemangledName().GetCString();
+            if (demangled)
+            {
+                std::string name_no_parens(partial_name, base_name_end - partial_name);
+                const char *partial_in_demangled = strstr (demangled, name_no_parens.c_str());
+                if (partial_in_demangled == NULL)
+                    return false;
+                else
+                {
+                    // Sort out the case where our name is something like "Process::Destroy" and the match is
+                    // "SBProcess::Destroy" - that shouldn't be a match.  We should really always match on
+                    // namespace boundaries...
+                    
+                    if (partial_name[0] == ':'  && partial_name[1] == ':')
+                    {
+                        // The partial name was already on a namespace boundary so all matches are good.
+                        return true;
+                    }
+                    else if (partial_in_demangled == demangled)
+                    {
+                        // They both start the same, so this is an good match.
+                        return true;
+                    }
+                    else
+                    {
+                        if (partial_in_demangled - demangled == 1)
+                        {
+                            // Only one character difference, can't be a namespace boundary...
+                            return false;
+                        }
+                        else if (*(partial_in_demangled - 1) == ':' && *(partial_in_demangled - 2) == ':')
+                        {
+                            // We are on a namespace boundary, so this is also good.
+                            return true;
+                        }
+                        else
+                            return false;
+                    }
+                }
+            }
+        }
+    }
+    
+    return true;
+}
+
+uint32_t
+SymbolFileDWARF::FindFunctions (const ConstString &name, 
+                                const lldb_private::ClangNamespaceDecl *namespace_decl, 
+                                uint32_t name_type_mask,
+                                bool include_inlines,
+                                bool append, 
+                                SymbolContextList& sc_list)
+{
+    Timer scoped_timer (__PRETTY_FUNCTION__,
+                        "SymbolFileDWARF::FindFunctions (name = '%s')",
+                        name.AsCString());
+
+    // eFunctionNameTypeAuto should be pre-resolved by a call to Module::PrepareForFunctionNameLookup()
+    assert ((name_type_mask & eFunctionNameTypeAuto) == 0);
+
+    Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS));
+    
+    if (log)
+    {
+        GetObjectFile()->GetModule()->LogMessage (log,
+                                                  "SymbolFileDWARF::FindFunctions (name=\"%s\", name_type_mask=0x%x, append=%u, sc_list)", 
+                                                  name.GetCString(), 
+                                                  name_type_mask, 
+                                                  append);
+    }
+
+    // If we aren't appending the results to this list, then clear the list
+    if (!append)
+        sc_list.Clear();
+    
+    if (!NamespaceDeclMatchesThisSymbolFile(namespace_decl))
+		return 0;
+        
+    // If name is empty then we won't find anything.
+    if (name.IsEmpty())
+        return 0;
+
+    // Remember how many sc_list are in the list before we search in case
+    // we are appending the results to a variable list.
+
+    const char *name_cstr = name.GetCString();
+
+    const uint32_t original_size = sc_list.GetSize();
+   
+    DWARFDebugInfo* info = DebugInfo();
+    if (info == NULL)
+        return 0;
+
+    DWARFCompileUnit *dwarf_cu = NULL;
+    std::set<const DWARFDebugInfoEntry *> resolved_dies;
+    if (m_using_apple_tables)
+    {
+        if (m_apple_names_ap.get())
+        {
+
+            DIEArray die_offsets;
+
+            uint32_t num_matches = 0;
+                
+            if (name_type_mask & eFunctionNameTypeFull)
+            {
+                // If they asked for the full name, match what they typed.  At some point we may
+                // want to canonicalize this (strip double spaces, etc.  For now, we just add all the
+                // dies that we find by exact match.
+                num_matches = m_apple_names_ap->FindByName (name_cstr, die_offsets);
+                for (uint32_t i = 0; i < num_matches; i++)
+                {
+                    const dw_offset_t die_offset = die_offsets[i];
+                    const DWARFDebugInfoEntry *die = info->GetDIEPtrWithCompileUnitHint (die_offset, &dwarf_cu);
+                    if (die)
+                    {
+                        if (namespace_decl && !DIEIsInNamespace (namespace_decl, dwarf_cu, die))
+                            continue;
+                        
+                        if (!include_inlines && die->Tag() == DW_TAG_inlined_subroutine)
+                            continue;
+                        
+                        if (resolved_dies.find(die) == resolved_dies.end())
+                        {
+                            if (ResolveFunction (dwarf_cu, die, sc_list))
+                                resolved_dies.insert(die);
+                        }
+                    }
+                    else
+                    {
+                        GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_names accelerator table had bad die 0x%8.8x for '%s')", 
+                                                                                   die_offset, name_cstr);
+                    }                                    
+                }
+            }
+
+            if (name_type_mask & eFunctionNameTypeSelector)
+            {
+                if (namespace_decl && *namespace_decl)
+                    return 0; // no selectors in namespaces
+                    
+                num_matches = m_apple_names_ap->FindByName (name_cstr, die_offsets);
+                // Now make sure these are actually ObjC methods.  In this case we can simply look up the name,
+                // and if it is an ObjC method name, we're good.
+                
+                for (uint32_t i = 0; i < num_matches; i++)
+                {
+                    const dw_offset_t die_offset = die_offsets[i];
+                    const DWARFDebugInfoEntry* die = info->GetDIEPtrWithCompileUnitHint (die_offset, &dwarf_cu);
+                    if (die)
+                    {
+                        const char *die_name = die->GetName(this, dwarf_cu);
+                        if (ObjCLanguageRuntime::IsPossibleObjCMethodName(die_name))
+                        {
+                            if (!include_inlines && die->Tag() == DW_TAG_inlined_subroutine)
+                                continue;
+                            
+                            if (resolved_dies.find(die) == resolved_dies.end())
+                            {
+                                if (ResolveFunction (dwarf_cu, die, sc_list))
+                                    resolved_dies.insert(die);
+                            }
+                        }
+                    }
+                    else
+                    {
+                        GetObjectFile()->GetModule()->ReportError ("the DWARF debug information has been modified (.apple_names accelerator table had bad die 0x%8.8x for '%s')",
+                                                                   die_offset, name_cstr);
+                    }                                    
+                }
+                die_offsets.clear();
+            }
+            
+            if (((name_type_mask & eFunctionNameTypeMethod) && !namespace_decl) || name_type_mask & eFunctionNameTypeBase)
+            {
+                // The apple_names table stores just the "base name" of C++ methods in the table.  So we have to
+                // extract the base name, look that up, and if there is any other information in the name we were
+                // passed in we have to post-filter based on that.
+                
+                // FIXME: Arrange the logic above so that we don't calculate the base name twice:
+                num_matches = m_apple_names_ap->FindByName (name_cstr, die_offsets);
+                
+                for (uint32_t i = 0; i < num_matches; i++)
+                {
+                    const dw_offset_t die_offset = die_offsets[i];
+                    const DWARFDebugInfoEntry* die = info->GetDIEPtrWithCompileUnitHint (die_offset, &dwarf_cu);
+                    if (die)
+                    {
+                        if (!include_inlines && die->Tag() == DW_TAG_inlined_subroutine)
+                            continue;
+                        
+                        if (namespace_decl && !DIEIsInNamespace (namespace_decl, dwarf_cu, die))
+                            continue;
+
+                        // If we get to here, the die is good, and we should add it:
+                        if (resolved_dies.find(die) == resolved_dies.end())
+                        if (ResolveFunction (dwarf_cu, die, sc_list))
+                        {
+                            bool keep_die = true;
+                            if ((name_type_mask & (eFunctionNameTypeBase|eFunctionNameTypeMethod)) != (eFunctionNameTypeBase|eFunctionNameTypeMethod))
+                            {
+                                // We are looking for either basenames or methods, so we need to
+                                // trim out the ones we won't want by looking at the type
+                                SymbolContext sc;
+                                if (sc_list.GetLastContext(sc))
+                                {
+                                    if (sc.block)
+                                    {
+                                        // We have an inlined function
+                                    }
+                                    else if (sc.function)
+                                    {
+                                        Type *type = sc.function->GetType();
+                                        
+                                        clang::DeclContext* decl_ctx = GetClangDeclContextContainingTypeUID (type->GetID());
+                                        if (decl_ctx->isRecord())
+                                        {
+                                            if (name_type_mask & eFunctionNameTypeBase)
+                                            {
+                                                sc_list.RemoveContextAtIndex(sc_list.GetSize()-1);
+                                                keep_die = false;
+                                            }
+                                        }
+                                        else
+                                        {
+                                            if (name_type_mask & eFunctionNameTypeMethod)
+                                            {
+                                                sc_list.RemoveContextAtIndex(sc_list.GetSize()-1);
+                                                keep_die = false;
+                                            }
+                                        }
+                                    }
+                                }
+                            }
+                            if (keep_die)
+                                resolved_dies.insert(die);
+                        }
+                    }
+                    else
+                    {
+                        GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_names accelerator table had bad die 0x%8.8x for '%s')",
+                                                                                   die_offset, name_cstr);
+                    }                                    
+                }
+                die_offsets.clear();
+            }
+        }
+    }
+    else
+    {
+
+        // Index the DWARF if we haven't already
+        if (!m_indexed)
+            Index ();
+
+        if (name_type_mask & eFunctionNameTypeFull)
+        {
+            FindFunctions (name, m_function_fullname_index, sc_list);
+
+            // Temporary workaround for global/anonymous namespace functions on linux
+#if defined (__linux__)
+            // If we didn't find any functions in the global namespace try
+            // looking in the basename index but ignore any returned
+            // functions that have a namespace (ie. mangled names starting with 
+            // '_ZN') but keep functions which have an anonymous namespace
+            if (sc_list.GetSize() == 0)
+            {
+                SymbolContextList temp_sc_list;
+                FindFunctions (name, m_function_basename_index, temp_sc_list);
+                if (!namespace_decl)
+                {
+                    SymbolContext sc;
+                    for (uint32_t i = 0; i < temp_sc_list.GetSize(); i++)
+                    {
+                        if (temp_sc_list.GetContextAtIndex(i, sc))
+                        {
+                            ConstString mangled_name = sc.GetFunctionName(Mangled::ePreferMangled);
+                            ConstString demangled_name = sc.GetFunctionName(Mangled::ePreferDemangled);
+                            if (strncmp(mangled_name.GetCString(), "_ZN", 3) ||
+                                !strncmp(demangled_name.GetCString(), "(anonymous namespace)", 21))
+                            {
+                                sc_list.Append(sc);
+                            }
+                        }
+                    }
+                }
+            }
+#endif
+        }
+        DIEArray die_offsets;
+        DWARFCompileUnit *dwarf_cu = NULL;
+        
+        if (name_type_mask & eFunctionNameTypeBase)
+        {
+            uint32_t num_base = m_function_basename_index.Find(name, die_offsets);
+            for (uint32_t i = 0; i < num_base; i++)
+            {
+                const DWARFDebugInfoEntry* die = info->GetDIEPtrWithCompileUnitHint (die_offsets[i], &dwarf_cu);
+                if (die)
+                {
+                    if (!include_inlines && die->Tag() == DW_TAG_inlined_subroutine)
+                        continue;
+                    
+                    if (namespace_decl && !DIEIsInNamespace (namespace_decl, dwarf_cu, die))
+                        continue;
+                    
+                    // If we get to here, the die is good, and we should add it:
+                    if (resolved_dies.find(die) == resolved_dies.end())
+                    {
+                        if (ResolveFunction (dwarf_cu, die, sc_list))
+                            resolved_dies.insert(die);
+                    }
+                }
+            }
+            die_offsets.clear();
+        }
+        
+        if (name_type_mask & eFunctionNameTypeMethod)
+        {
+            if (namespace_decl && *namespace_decl)
+                return 0; // no methods in namespaces
+
+            uint32_t num_base = m_function_method_index.Find(name, die_offsets);
+            {
+                for (uint32_t i = 0; i < num_base; i++)
+                {
+                    const DWARFDebugInfoEntry* die = info->GetDIEPtrWithCompileUnitHint (die_offsets[i], &dwarf_cu);
+                    if (die)
+                    {
+                        if (!include_inlines && die->Tag() == DW_TAG_inlined_subroutine)
+                            continue;
+                        
+                        // If we get to here, the die is good, and we should add it:
+                        if (resolved_dies.find(die) == resolved_dies.end())
+                        {
+                            if (ResolveFunction (dwarf_cu, die, sc_list))
+                                resolved_dies.insert(die);
+                        }
+                    }
+                }
+            }
+            die_offsets.clear();
+        }
+
+        if ((name_type_mask & eFunctionNameTypeSelector) && (!namespace_decl || !*namespace_decl))
+        {
+            FindFunctions (name, m_function_selector_index, sc_list);
+        }
+        
+    }
+
+    // Return the number of variable that were appended to the list
+    const uint32_t num_matches = sc_list.GetSize() - original_size;
+    
+    if (log && num_matches > 0)
+    {
+        GetObjectFile()->GetModule()->LogMessage (log,
+                                                  "SymbolFileDWARF::FindFunctions (name=\"%s\", name_type_mask=0x%x, append=%u, sc_list) => %u",
+                                                  name.GetCString(), 
+                                                  name_type_mask, 
+                                                  append,
+                                                  num_matches);
+    }
+    return num_matches;
+}
+
+uint32_t
+SymbolFileDWARF::FindFunctions(const RegularExpression& regex, bool include_inlines, bool append, SymbolContextList& sc_list)
+{
+    Timer scoped_timer (__PRETTY_FUNCTION__,
+                        "SymbolFileDWARF::FindFunctions (regex = '%s')",
+                        regex.GetText());
+
+    Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS));
+    
+    if (log)
+    {
+        GetObjectFile()->GetModule()->LogMessage (log,
+                                                  "SymbolFileDWARF::FindFunctions (regex=\"%s\", append=%u, sc_list)", 
+                                                  regex.GetText(), 
+                                                  append);
+    }
+    
+
+    // If we aren't appending the results to this list, then clear the list
+    if (!append)
+        sc_list.Clear();
+
+    // Remember how many sc_list are in the list before we search in case
+    // we are appending the results to a variable list.
+    uint32_t original_size = sc_list.GetSize();
+
+    if (m_using_apple_tables)
+    {
+        if (m_apple_names_ap.get())
+            FindFunctions (regex, *m_apple_names_ap, sc_list);
+    }
+    else
+    {
+        // Index the DWARF if we haven't already
+        if (!m_indexed)
+            Index ();
+
+        FindFunctions (regex, m_function_basename_index, sc_list);
+
+        FindFunctions (regex, m_function_fullname_index, sc_list);
+    }
+
+    // Return the number of variable that were appended to the list
+    return sc_list.GetSize() - original_size;
+}
+
+uint32_t
+SymbolFileDWARF::FindTypes (const SymbolContext& sc, 
+                            const ConstString &name, 
+                            const lldb_private::ClangNamespaceDecl *namespace_decl, 
+                            bool append, 
+                            uint32_t max_matches, 
+                            TypeList& types)
+{
+    DWARFDebugInfo* info = DebugInfo();
+    if (info == NULL)
+        return 0;
+
+    Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS));
+    
+    if (log)
+    {
+        if (namespace_decl)
+        {
+            GetObjectFile()->GetModule()->LogMessage (log,
+                                                      "SymbolFileDWARF::FindTypes (sc, name=\"%s\", clang::NamespaceDecl(%p) \"%s\", append=%u, max_matches=%u, type_list)", 
+                                                      name.GetCString(),
+                                                      namespace_decl->GetNamespaceDecl(),
+                                                      namespace_decl->GetQualifiedName().c_str(),
+                                                      append, 
+                                                      max_matches);
+        }
+        else
+        {
+            GetObjectFile()->GetModule()->LogMessage (log,
+                                                      "SymbolFileDWARF::FindTypes (sc, name=\"%s\", clang::NamespaceDecl(NULL), append=%u, max_matches=%u, type_list)",
+                                                      name.GetCString(), 
+                                                      append, 
+                                                      max_matches);
+        }
+    }
+
+    // If we aren't appending the results to this list, then clear the list
+    if (!append)
+        types.Clear();
+    
+    if (!NamespaceDeclMatchesThisSymbolFile(namespace_decl))
+		return 0;
+
+    DIEArray die_offsets;
+    
+    if (m_using_apple_tables)
+    {
+        if (m_apple_types_ap.get())
+        {
+            const char *name_cstr = name.GetCString();
+            m_apple_types_ap->FindByName (name_cstr, die_offsets);
+        }
+    }
+    else
+    {
+        if (!m_indexed)
+            Index ();
+        
+        m_type_index.Find (name, die_offsets);
+    }
+    
+    const size_t num_die_matches = die_offsets.size();
+
+    if (num_die_matches)
+    {
+        const uint32_t initial_types_size = types.GetSize();
+        DWARFCompileUnit* dwarf_cu = NULL;
+        const DWARFDebugInfoEntry* die = NULL;
+        DWARFDebugInfo* debug_info = DebugInfo();
+        for (size_t i=0; i<num_die_matches; ++i)
+        {
+            const dw_offset_t die_offset = die_offsets[i];
+            die = debug_info->GetDIEPtrWithCompileUnitHint (die_offset, &dwarf_cu);
+
+            if (die)
+            {
+                if (namespace_decl && !DIEIsInNamespace (namespace_decl, dwarf_cu, die))
+                    continue;
+                
+                Type *matching_type = ResolveType (dwarf_cu, die);
+                if (matching_type)
+                {
+                    // We found a type pointer, now find the shared pointer form our type list
+                    types.InsertUnique (matching_type->shared_from_this());
+                    if (types.GetSize() >= max_matches)
+                        break;
+                }
+            }
+            else
+            {
+                if (m_using_apple_tables)
+                {
+                    GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_types accelerator table had bad die 0x%8.8x for '%s')\n",
+                                                                               die_offset, name.GetCString());
+                }
+            }            
+
+        }
+        const uint32_t num_matches = types.GetSize() - initial_types_size;
+        if (log && num_matches)
+        {
+            if (namespace_decl)
+            {
+                GetObjectFile()->GetModule()->LogMessage (log,
+                                                          "SymbolFileDWARF::FindTypes (sc, name=\"%s\", clang::NamespaceDecl(%p) \"%s\", append=%u, max_matches=%u, type_list) => %u", 
+                                                          name.GetCString(),
+                                                          namespace_decl->GetNamespaceDecl(),
+                                                          namespace_decl->GetQualifiedName().c_str(),
+                                                          append, 
+                                                          max_matches,
+                                                          num_matches);
+            }
+            else
+            {
+                GetObjectFile()->GetModule()->LogMessage (log,
+                                                          "SymbolFileDWARF::FindTypes (sc, name=\"%s\", clang::NamespaceDecl(NULL), append=%u, max_matches=%u, type_list) => %u",
+                                                          name.GetCString(), 
+                                                          append, 
+                                                          max_matches,
+                                                          num_matches);
+            }
+        }
+        return num_matches;
+    }
+    return 0;
+}
+
+
+ClangNamespaceDecl
+SymbolFileDWARF::FindNamespace (const SymbolContext& sc, 
+                                const ConstString &name,
+                                const lldb_private::ClangNamespaceDecl *parent_namespace_decl)
+{
+    Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS));
+    
+    if (log)
+    {
+        GetObjectFile()->GetModule()->LogMessage (log,
+                                                  "SymbolFileDWARF::FindNamespace (sc, name=\"%s\")", 
+                                                  name.GetCString());
+    }
+    
+    if (!NamespaceDeclMatchesThisSymbolFile(parent_namespace_decl))
+		return ClangNamespaceDecl();
+
+    ClangNamespaceDecl namespace_decl;
+    DWARFDebugInfo* info = DebugInfo();
+    if (info)
+    {
+        DIEArray die_offsets;
+
+        // Index if we already haven't to make sure the compile units
+        // get indexed and make their global DIE index list
+        if (m_using_apple_tables)
+        {
+            if (m_apple_namespaces_ap.get())
+            {
+                const char *name_cstr = name.GetCString();
+                m_apple_namespaces_ap->FindByName (name_cstr, die_offsets);
+            }
+        }
+        else
+        {
+            if (!m_indexed)
+                Index ();
+
+            m_namespace_index.Find (name, die_offsets);
+        }
+        
+        DWARFCompileUnit* dwarf_cu = NULL;
+        const DWARFDebugInfoEntry* die = NULL;
+        const size_t num_matches = die_offsets.size();
+        if (num_matches)
+        {
+            DWARFDebugInfo* debug_info = DebugInfo();
+            for (size_t i=0; i<num_matches; ++i)
+            {
+                const dw_offset_t die_offset = die_offsets[i];
+                die = debug_info->GetDIEPtrWithCompileUnitHint (die_offset, &dwarf_cu);
+                
+                if (die)
+                {
+                    if (parent_namespace_decl && !DIEIsInNamespace (parent_namespace_decl, dwarf_cu, die))
+                        continue;
+
+                    clang::NamespaceDecl *clang_namespace_decl = ResolveNamespaceDIE (dwarf_cu, die);
+                    if (clang_namespace_decl)
+                    {
+                        namespace_decl.SetASTContext (GetClangASTContext().getASTContext());
+                        namespace_decl.SetNamespaceDecl (clang_namespace_decl);
+                        break;
+                    }
+                }
+                else
+                {
+                    if (m_using_apple_tables)
+                    {
+                        GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_namespaces accelerator table had bad die 0x%8.8x for '%s')\n",
+                                                                   die_offset, name.GetCString());
+                    }
+                }            
+
+            }
+        }
+    }
+    if (log && namespace_decl.GetNamespaceDecl())
+    {
+        GetObjectFile()->GetModule()->LogMessage (log,
+                                                  "SymbolFileDWARF::FindNamespace (sc, name=\"%s\") => clang::NamespaceDecl(%p) \"%s\"",
+                                                  name.GetCString(),
+                                                  namespace_decl.GetNamespaceDecl(),
+                                                  namespace_decl.GetQualifiedName().c_str());
+    }
+
+    return namespace_decl;
+}
+
+uint32_t
+SymbolFileDWARF::FindTypes(std::vector<dw_offset_t> die_offsets, uint32_t max_matches, TypeList& types)
+{
+    // Remember how many sc_list are in the list before we search in case
+    // we are appending the results to a variable list.
+    uint32_t original_size = types.GetSize();
+
+    const uint32_t num_die_offsets = die_offsets.size();
+    // Parse all of the types we found from the pubtypes matches
+    uint32_t i;
+    uint32_t num_matches = 0;
+    for (i = 0; i < num_die_offsets; ++i)
+    {
+        Type *matching_type = ResolveTypeUID (die_offsets[i]);
+        if (matching_type)
+        {
+            // We found a type pointer, now find the shared pointer form our type list
+            types.InsertUnique (matching_type->shared_from_this());
+            ++num_matches;
+            if (num_matches >= max_matches)
+                break;
+        }
+    }
+
+    // Return the number of variable that were appended to the list
+    return types.GetSize() - original_size;
+}
+
+
+size_t
+SymbolFileDWARF::ParseChildParameters (const SymbolContext& sc,
+                                       clang::DeclContext *containing_decl_ctx,
+                                       DWARFCompileUnit* dwarf_cu,
+                                       const DWARFDebugInfoEntry *parent_die,
+                                       bool skip_artificial,
+                                       bool &is_static,
+                                       TypeList* type_list,
+                                       std::vector<ClangASTType>& function_param_types,
+                                       std::vector<clang::ParmVarDecl*>& function_param_decls,
+                                       unsigned &type_quals,
+                                       ClangASTContext::TemplateParameterInfos &template_param_infos)
+{
+    if (parent_die == NULL)
+        return 0;
+
+    const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize());
+
+    size_t arg_idx = 0;
+    const DWARFDebugInfoEntry *die;
+    for (die = parent_die->GetFirstChild(); die != NULL; die = die->GetSibling())
+    {
+        dw_tag_t tag = die->Tag();
+        switch (tag)
+        {
+        case DW_TAG_formal_parameter:
+            {
+                DWARFDebugInfoEntry::Attributes attributes;
+                const size_t num_attributes = die->GetAttributes(this, dwarf_cu, fixed_form_sizes, attributes);
+                if (num_attributes > 0)
+                {
+                    const char *name = NULL;
+                    Declaration decl;
+                    dw_offset_t param_type_die_offset = DW_INVALID_OFFSET;
+                    bool is_artificial = false;
+                    // one of None, Auto, Register, Extern, Static, PrivateExtern
+
+                    clang::StorageClass storage = clang::SC_None;
+                    uint32_t i;
+                    for (i=0; i<num_attributes; ++i)
+                    {
+                        const dw_attr_t attr = attributes.AttributeAtIndex(i);
+                        DWARFFormValue form_value;
+                        if (attributes.ExtractFormValueAtIndex(this, i, form_value))
+                        {
+                            switch (attr)
+                            {
+                            case DW_AT_decl_file:   decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
+                            case DW_AT_decl_line:   decl.SetLine(form_value.Unsigned()); break;
+                            case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
+                            case DW_AT_name:        name = form_value.AsCString(&get_debug_str_data()); break;
+                            case DW_AT_type:        param_type_die_offset = form_value.Reference(dwarf_cu); break;
+                            case DW_AT_artificial:  is_artificial = form_value.Boolean(); break;
+                            case DW_AT_location:
+    //                          if (form_value.BlockData())
+    //                          {
+    //                              const DataExtractor& debug_info_data = debug_info();
+    //                              uint32_t block_length = form_value.Unsigned();
+    //                              DataExtractor location(debug_info_data, form_value.BlockData() - debug_info_data.GetDataStart(), block_length);
+    //                          }
+    //                          else
+    //                          {
+    //                          }
+    //                          break;
+                            case DW_AT_const_value:
+                            case DW_AT_default_value:
+                            case DW_AT_description:
+                            case DW_AT_endianity:
+                            case DW_AT_is_optional:
+                            case DW_AT_segment:
+                            case DW_AT_variable_parameter:
+                            default:
+                            case DW_AT_abstract_origin:
+                            case DW_AT_sibling:
+                                break;
+                            }
+                        }
+                    }
+
+                    bool skip = false;
+                    if (skip_artificial)
+                    {
+                        if (is_artificial)
+                        {
+                            // In order to determine if a C++ member function is
+                            // "const" we have to look at the const-ness of "this"...
+                            // Ugly, but that
+                            if (arg_idx == 0)
+                            {
+                                if (DeclKindIsCXXClass(containing_decl_ctx->getDeclKind()))
+                                {                                    
+                                    // Often times compilers omit the "this" name for the
+                                    // specification DIEs, so we can't rely upon the name
+                                    // being in the formal parameter DIE...
+                                    if (name == NULL || ::strcmp(name, "this")==0)
+                                    {
+                                        Type *this_type = ResolveTypeUID (param_type_die_offset);
+                                        if (this_type)
+                                        {                              
+                                            uint32_t encoding_mask = this_type->GetEncodingMask();
+                                            if (encoding_mask & Type::eEncodingIsPointerUID)
+                                            {
+                                                is_static = false;
+                                                
+                                                if (encoding_mask & (1u << Type::eEncodingIsConstUID))
+                                                    type_quals |= clang::Qualifiers::Const;
+                                                if (encoding_mask & (1u << Type::eEncodingIsVolatileUID))
+                                                    type_quals |= clang::Qualifiers::Volatile;
+                                            }
+                                        }
+                                    }
+                                }
+                            }
+                            skip = true;
+                        }
+                        else
+                        {
+
+                            // HACK: Objective C formal parameters "self" and "_cmd" 
+                            // are not marked as artificial in the DWARF...
+                            CompileUnit *comp_unit = GetCompUnitForDWARFCompUnit(dwarf_cu, UINT32_MAX);
+                            if (comp_unit)
+                            {
+                                switch (comp_unit->GetLanguage())
+                                {
+                                    case eLanguageTypeObjC:
+                                    case eLanguageTypeObjC_plus_plus:
+                                        if (name && name[0] && (strcmp (name, "self") == 0 || strcmp (name, "_cmd") == 0))
+                                            skip = true;
+                                        break;
+                                    default:
+                                        break;
+                                }
+                            }
+                        }
+                    }
+
+                    if (!skip)
+                    {
+                        Type *type = ResolveTypeUID(param_type_die_offset);
+                        if (type)
+                        {
+                            function_param_types.push_back (type->GetClangForwardType());
+
+                            clang::ParmVarDecl *param_var_decl = GetClangASTContext().CreateParameterDeclaration (name, 
+                                                                                                                  type->GetClangForwardType(), 
+                                                                                                                  storage);
+                            assert(param_var_decl);
+                            function_param_decls.push_back(param_var_decl);
+                            
+                            GetClangASTContext().SetMetadataAsUserID (param_var_decl, MakeUserID(die->GetOffset()));
+                        }
+                    }
+                }
+                arg_idx++;
+            }
+            break;
+
+        case DW_TAG_template_type_parameter:
+        case DW_TAG_template_value_parameter:
+            ParseTemplateDIE (dwarf_cu, die,template_param_infos);
+            break;
+
+        default:
+            break;
+        }
+    }
+    return arg_idx;
+}
+
+size_t
+SymbolFileDWARF::ParseChildEnumerators
+(
+    const SymbolContext& sc,
+    lldb_private::ClangASTType &clang_type,
+    bool is_signed,
+    uint32_t enumerator_byte_size,
+    DWARFCompileUnit* dwarf_cu,
+    const DWARFDebugInfoEntry *parent_die
+)
+{
+    if (parent_die == NULL)
+        return 0;
+
+    size_t enumerators_added = 0;
+    const DWARFDebugInfoEntry *die;
+    const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize());
+
+    for (die = parent_die->GetFirstChild(); die != NULL; die = die->GetSibling())
+    {
+        const dw_tag_t tag = die->Tag();
+        if (tag == DW_TAG_enumerator)
+        {
+            DWARFDebugInfoEntry::Attributes attributes;
+            const size_t num_child_attributes = die->GetAttributes(this, dwarf_cu, fixed_form_sizes, attributes);
+            if (num_child_attributes > 0)
+            {
+                const char *name = NULL;
+                bool got_value = false;
+                int64_t enum_value = 0;
+                Declaration decl;
+
+                uint32_t i;
+                for (i=0; i<num_child_attributes; ++i)
+                {
+                    const dw_attr_t attr = attributes.AttributeAtIndex(i);
+                    DWARFFormValue form_value;
+                    if (attributes.ExtractFormValueAtIndex(this, i, form_value))
+                    {
+                        switch (attr)
+                        {
+                        case DW_AT_const_value:
+                            got_value = true;
+                            if (is_signed)
+                                enum_value = form_value.Signed();
+                            else
+                                enum_value = form_value.Unsigned();
+                            break;
+
+                        case DW_AT_name:
+                            name = form_value.AsCString(&get_debug_str_data());
+                            break;
+
+                        case DW_AT_description:
+                        default:
+                        case DW_AT_decl_file:   decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
+                        case DW_AT_decl_line:   decl.SetLine(form_value.Unsigned()); break;
+                        case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
+                        case DW_AT_sibling:
+                            break;
+                        }
+                    }
+                }
+
+                if (name && name[0] && got_value)
+                {
+                    clang_type.AddEnumerationValueToEnumerationType (clang_type.GetEnumerationIntegerType(),
+                                                                     decl,
+                                                                     name,
+                                                                     enum_value,
+                                                                     enumerator_byte_size * 8);
+                    ++enumerators_added;
+                }
+            }
+        }
+    }
+    return enumerators_added;
+}
+
+void
+SymbolFileDWARF::ParseChildArrayInfo
+(
+    const SymbolContext& sc,
+    DWARFCompileUnit* dwarf_cu,
+    const DWARFDebugInfoEntry *parent_die,
+    int64_t& first_index,
+    std::vector<uint64_t>& element_orders,
+    uint32_t& byte_stride,
+    uint32_t& bit_stride
+)
+{
+    if (parent_die == NULL)
+        return;
+
+    const DWARFDebugInfoEntry *die;
+    const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize());
+    for (die = parent_die->GetFirstChild(); die != NULL; die = die->GetSibling())
+    {
+        const dw_tag_t tag = die->Tag();
+        switch (tag)
+        {
+        case DW_TAG_subrange_type:
+            {
+                DWARFDebugInfoEntry::Attributes attributes;
+                const size_t num_child_attributes = die->GetAttributes(this, dwarf_cu, fixed_form_sizes, attributes);
+                if (num_child_attributes > 0)
+                {
+                    uint64_t num_elements = 0;
+                    uint64_t lower_bound = 0;
+                    uint64_t upper_bound = 0;
+                    bool upper_bound_valid = false;
+                    uint32_t i;
+                    for (i=0; i<num_child_attributes; ++i)
+                    {
+                        const dw_attr_t attr = attributes.AttributeAtIndex(i);
+                        DWARFFormValue form_value;
+                        if (attributes.ExtractFormValueAtIndex(this, i, form_value))
+                        {
+                            switch (attr)
+                            {
+                            case DW_AT_name:
+                                break;
+
+                            case DW_AT_count:
+                                num_elements = form_value.Unsigned();
+                                break;
+
+                            case DW_AT_bit_stride:
+                                bit_stride = form_value.Unsigned();
+                                break;
+
+                            case DW_AT_byte_stride:
+                                byte_stride = form_value.Unsigned();
+                                break;
+
+                            case DW_AT_lower_bound:
+                                lower_bound = form_value.Unsigned();
+                                break;
+
+                            case DW_AT_upper_bound:
+                                upper_bound_valid = true;
+                                upper_bound = form_value.Unsigned();
+                                break;
+
+                            default:
+                            case DW_AT_abstract_origin:
+                            case DW_AT_accessibility:
+                            case DW_AT_allocated:
+                            case DW_AT_associated:
+                            case DW_AT_data_location:
+                            case DW_AT_declaration:
+                            case DW_AT_description:
+                            case DW_AT_sibling:
+                            case DW_AT_threads_scaled:
+                            case DW_AT_type:
+                            case DW_AT_visibility:
+                                break;
+                            }
+                        }
+                    }
+
+                    if (num_elements == 0)
+                    {
+                        if (upper_bound_valid && upper_bound >= lower_bound)
+                            num_elements = upper_bound - lower_bound + 1;
+                    }
+
+                    element_orders.push_back (num_elements);
+                }
+            }
+            break;
+        }
+    }
+}
+
+TypeSP
+SymbolFileDWARF::GetTypeForDIE (DWARFCompileUnit *dwarf_cu, const DWARFDebugInfoEntry* die)
+{
+    TypeSP type_sp;
+    if (die != NULL)
+    {
+        assert(dwarf_cu != NULL);
+        Type *type_ptr = m_die_to_type.lookup (die);
+        if (type_ptr == NULL)
+        {
+            CompileUnit* lldb_cu = GetCompUnitForDWARFCompUnit(dwarf_cu);
+            assert (lldb_cu);
+            SymbolContext sc(lldb_cu);
+            type_sp = ParseType(sc, dwarf_cu, die, NULL);
+        }
+        else if (type_ptr != DIE_IS_BEING_PARSED)
+        {
+            // Grab the existing type from the master types lists
+            type_sp = type_ptr->shared_from_this();
+        }
+
+    }
+    return type_sp;
+}
+
+clang::DeclContext *
+SymbolFileDWARF::GetClangDeclContextContainingDIEOffset (dw_offset_t die_offset)
+{
+    if (die_offset != DW_INVALID_OFFSET)
+    {
+        DWARFCompileUnitSP cu_sp;
+        const DWARFDebugInfoEntry* die = DebugInfo()->GetDIEPtr(die_offset, &cu_sp);
+        return GetClangDeclContextContainingDIE (cu_sp.get(), die, NULL);
+    }
+    return NULL;
+}
+
+clang::DeclContext *
+SymbolFileDWARF::GetClangDeclContextForDIEOffset (const SymbolContext &sc, dw_offset_t die_offset)
+{
+    if (die_offset != DW_INVALID_OFFSET)
+    {
+        DWARFDebugInfo* debug_info = DebugInfo();
+        if (debug_info)
+        {
+            DWARFCompileUnitSP cu_sp;
+            const DWARFDebugInfoEntry* die = debug_info->GetDIEPtr(die_offset, &cu_sp);
+            if (die)
+                return GetClangDeclContextForDIE (sc, cu_sp.get(), die);
+        }
+    }
+    return NULL;
+}
+
+clang::NamespaceDecl *
+SymbolFileDWARF::ResolveNamespaceDIE (DWARFCompileUnit *dwarf_cu, const DWARFDebugInfoEntry *die)
+{
+    if (die && die->Tag() == DW_TAG_namespace)
+    {
+        // See if we already parsed this namespace DIE and associated it with a
+        // uniqued namespace declaration
+        clang::NamespaceDecl *namespace_decl = static_cast<clang::NamespaceDecl *>(m_die_to_decl_ctx[die]);
+        if (namespace_decl)
+            return namespace_decl;
+        else
+        {
+            const char *namespace_name = die->GetAttributeValueAsString(this, dwarf_cu, DW_AT_name, NULL);
+            clang::DeclContext *containing_decl_ctx = GetClangDeclContextContainingDIE (dwarf_cu, die, NULL);
+            namespace_decl = GetClangASTContext().GetUniqueNamespaceDeclaration (namespace_name, containing_decl_ctx);
+            Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO));
+            if (log)
+            {
+                if (namespace_name)
+                {
+                    GetObjectFile()->GetModule()->LogMessage (log,
+                                                              "ASTContext => %p: 0x%8.8" PRIx64 ": DW_TAG_namespace with DW_AT_name(\"%s\") => clang::NamespaceDecl *%p (original = %p)",
+                                                              GetClangASTContext().getASTContext(),
+                                                              MakeUserID(die->GetOffset()),
+                                                              namespace_name,
+                                                              namespace_decl,
+                                                              namespace_decl->getOriginalNamespace());
+                }
+                else
+                {
+                    GetObjectFile()->GetModule()->LogMessage (log,
+                                                              "ASTContext => %p: 0x%8.8" PRIx64 ": DW_TAG_namespace (anonymous) => clang::NamespaceDecl *%p (original = %p)",
+                                                              GetClangASTContext().getASTContext(),
+                                                              MakeUserID(die->GetOffset()),
+                                                              namespace_decl,
+                                                              namespace_decl->getOriginalNamespace());
+                }
+            }
+
+            if (namespace_decl)
+                LinkDeclContextToDIE((clang::DeclContext*)namespace_decl, die);
+            return namespace_decl;
+        }
+    }
+    return NULL;
+}
+
+clang::DeclContext *
+SymbolFileDWARF::GetClangDeclContextForDIE (const SymbolContext &sc, DWARFCompileUnit *cu, const DWARFDebugInfoEntry *die)
+{
+    clang::DeclContext *clang_decl_ctx = GetCachedClangDeclContextForDIE (die);
+    if (clang_decl_ctx)
+        return clang_decl_ctx;
+    // If this DIE has a specification, or an abstract origin, then trace to those.
+        
+    dw_offset_t die_offset = die->GetAttributeValueAsReference(this, cu, DW_AT_specification, DW_INVALID_OFFSET);
+    if (die_offset != DW_INVALID_OFFSET)
+        return GetClangDeclContextForDIEOffset (sc, die_offset);
+    
+    die_offset = die->GetAttributeValueAsReference(this, cu, DW_AT_abstract_origin, DW_INVALID_OFFSET);
+    if (die_offset != DW_INVALID_OFFSET)
+        return GetClangDeclContextForDIEOffset (sc, die_offset);
+    
+    Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO));
+    if (log)
+        GetObjectFile()->GetModule()->LogMessage(log, "SymbolFileDWARF::GetClangDeclContextForDIE (die = 0x%8.8x) %s '%s'", die->GetOffset(), DW_TAG_value_to_name(die->Tag()), die->GetName(this, cu));
+    // This is the DIE we want.  Parse it, then query our map.
+    bool assert_not_being_parsed = true;
+    ResolveTypeUID (cu, die, assert_not_being_parsed);    
+
+    clang_decl_ctx = GetCachedClangDeclContextForDIE (die);
+
+    return clang_decl_ctx;
+}
+
+clang::DeclContext *
+SymbolFileDWARF::GetClangDeclContextContainingDIE (DWARFCompileUnit *cu, const DWARFDebugInfoEntry *die, const DWARFDebugInfoEntry **decl_ctx_die_copy)
+{
+    if (m_clang_tu_decl == NULL)
+        m_clang_tu_decl = GetClangASTContext().getASTContext()->getTranslationUnitDecl();
+
+    const DWARFDebugInfoEntry *decl_ctx_die = GetDeclContextDIEContainingDIE (cu, die);
+
+    if (decl_ctx_die_copy)
+        *decl_ctx_die_copy = decl_ctx_die;
+    
+    if (decl_ctx_die)
+    {
+
+        DIEToDeclContextMap::iterator pos = m_die_to_decl_ctx.find (decl_ctx_die);
+        if (pos != m_die_to_decl_ctx.end())
+            return pos->second;
+
+        switch (decl_ctx_die->Tag())
+        {
+        case DW_TAG_compile_unit:
+            return m_clang_tu_decl;
+
+        case DW_TAG_namespace:
+            return ResolveNamespaceDIE (cu, decl_ctx_die);
+            break;
+
+        case DW_TAG_structure_type:
+        case DW_TAG_union_type:
+        case DW_TAG_class_type:
+            {
+                Type* type = ResolveType (cu, decl_ctx_die);
+                if (type)
+                {
+                    clang::DeclContext *decl_ctx = type->GetClangForwardType().GetDeclContextForType ();
+                    if (decl_ctx)
+                    {
+                        LinkDeclContextToDIE (decl_ctx, decl_ctx_die);
+                        if (decl_ctx)
+                            return decl_ctx;
+                    }
+                }
+            }
+            break;
+
+        default:
+            break;
+        }
+    }
+    return m_clang_tu_decl;
+}
+
+
+const DWARFDebugInfoEntry *
+SymbolFileDWARF::GetDeclContextDIEContainingDIE (DWARFCompileUnit *cu, const DWARFDebugInfoEntry *die)
+{
+    if (cu && die)
+    {
+        const DWARFDebugInfoEntry * const decl_die = die;
+    
+        while (die != NULL)
+        {
+            // If this is the original DIE that we are searching for a declaration 
+            // for, then don't look in the cache as we don't want our own decl 
+            // context to be our decl context...
+            if (decl_die != die)
+            {            
+                switch (die->Tag())
+                {
+                    case DW_TAG_compile_unit:
+                    case DW_TAG_namespace:
+                    case DW_TAG_structure_type:
+                    case DW_TAG_union_type:
+                    case DW_TAG_class_type:
+                        return die;
+                        
+                    default:
+                        break;
+                }
+            }
+            
+            dw_offset_t die_offset = die->GetAttributeValueAsReference(this, cu, DW_AT_specification, DW_INVALID_OFFSET);
+            if (die_offset != DW_INVALID_OFFSET)
+            {
+                DWARFCompileUnit *spec_cu = cu;
+                const DWARFDebugInfoEntry *spec_die = DebugInfo()->GetDIEPtrWithCompileUnitHint (die_offset, &spec_cu);
+                const DWARFDebugInfoEntry *spec_die_decl_ctx_die = GetDeclContextDIEContainingDIE (spec_cu, spec_die);
+                if (spec_die_decl_ctx_die)
+                    return spec_die_decl_ctx_die;
+            }
+            
+            die_offset = die->GetAttributeValueAsReference(this, cu, DW_AT_abstract_origin, DW_INVALID_OFFSET);
+            if (die_offset != DW_INVALID_OFFSET)
+            {
+                DWARFCompileUnit *abs_cu = cu;
+                const DWARFDebugInfoEntry *abs_die = DebugInfo()->GetDIEPtrWithCompileUnitHint (die_offset, &abs_cu);
+                const DWARFDebugInfoEntry *abs_die_decl_ctx_die = GetDeclContextDIEContainingDIE (abs_cu, abs_die);
+                if (abs_die_decl_ctx_die)
+                    return abs_die_decl_ctx_die;
+            }
+            
+            die = die->GetParent();
+        }
+    }
+    return NULL;
+}
+
+
+Symbol *
+SymbolFileDWARF::GetObjCClassSymbol (const ConstString &objc_class_name)
+{
+    Symbol *objc_class_symbol = NULL;
+    if (m_obj_file)
+    {
+        Symtab *symtab = m_obj_file->GetSymtab ();
+        if (symtab)
+        {
+            objc_class_symbol = symtab->FindFirstSymbolWithNameAndType (objc_class_name, 
+                                                                        eSymbolTypeObjCClass, 
+                                                                        Symtab::eDebugNo, 
+                                                                        Symtab::eVisibilityAny);
+        }
+    }
+    return objc_class_symbol;
+}
+
+// Some compilers don't emit the DW_AT_APPLE_objc_complete_type attribute. If they don't
+// then we can end up looking through all class types for a complete type and never find
+// the full definition. We need to know if this attribute is supported, so we determine
+// this here and cache th result. We also need to worry about the debug map DWARF file
+// if we are doing darwin DWARF in .o file debugging.
+bool
+SymbolFileDWARF::Supports_DW_AT_APPLE_objc_complete_type (DWARFCompileUnit *cu)
+{
+    if (m_supports_DW_AT_APPLE_objc_complete_type == eLazyBoolCalculate)
+    {
+        m_supports_DW_AT_APPLE_objc_complete_type = eLazyBoolNo;
+        if (cu && cu->Supports_DW_AT_APPLE_objc_complete_type())
+            m_supports_DW_AT_APPLE_objc_complete_type = eLazyBoolYes;
+        else
+        {
+            DWARFDebugInfo* debug_info = DebugInfo();
+            const uint32_t num_compile_units = GetNumCompileUnits();
+            for (uint32_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx)
+            {
+                DWARFCompileUnit* dwarf_cu = debug_info->GetCompileUnitAtIndex(cu_idx);
+                if (dwarf_cu != cu && dwarf_cu->Supports_DW_AT_APPLE_objc_complete_type())
+                {
+                    m_supports_DW_AT_APPLE_objc_complete_type = eLazyBoolYes;
+                    break;
+                }
+            }
+        }
+        if (m_supports_DW_AT_APPLE_objc_complete_type == eLazyBoolNo && GetDebugMapSymfile ())
+            return m_debug_map_symfile->Supports_DW_AT_APPLE_objc_complete_type (this);
+    }
+    return m_supports_DW_AT_APPLE_objc_complete_type == eLazyBoolYes;
+}
+
+// This function can be used when a DIE is found that is a forward declaration
+// DIE and we want to try and find a type that has the complete definition.
+TypeSP
+SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE (const DWARFDebugInfoEntry *die, 
+                                                       const ConstString &type_name,
+                                                       bool must_be_implementation)
+{
+    
+    TypeSP type_sp;
+    
+    if (!type_name || (must_be_implementation && !GetObjCClassSymbol (type_name)))
+        return type_sp;
+    
+    DIEArray die_offsets;
+    
+    if (m_using_apple_tables)
+    {
+        if (m_apple_types_ap.get())
+        {
+            const char *name_cstr = type_name.GetCString();
+            m_apple_types_ap->FindCompleteObjCClassByName (name_cstr, die_offsets, must_be_implementation);
+        }
+    }
+    else
+    {
+        if (!m_indexed)
+            Index ();
+        
+        m_type_index.Find (type_name, die_offsets);
+    }
+    
+    const size_t num_matches = die_offsets.size();
+    
+    DWARFCompileUnit* type_cu = NULL;
+    const DWARFDebugInfoEntry* type_die = NULL;
+    if (num_matches)
+    {
+        DWARFDebugInfo* debug_info = DebugInfo();
+        for (size_t i=0; i<num_matches; ++i)
+        {
+            const dw_offset_t die_offset = die_offsets[i];
+            type_die = debug_info->GetDIEPtrWithCompileUnitHint (die_offset, &type_cu);
+            
+            if (type_die)
+            {
+                bool try_resolving_type = false;
+                
+                // Don't try and resolve the DIE we are looking for with the DIE itself!
+                if (type_die != die)
+                {
+                    switch (type_die->Tag())
+                    {
+                        case DW_TAG_class_type:
+                        case DW_TAG_structure_type:
+                            try_resolving_type = true;
+                            break;
+                        default:
+                            break;
+                    }
+                }
+                
+                if (try_resolving_type)
+                {
+					if (must_be_implementation && type_cu->Supports_DW_AT_APPLE_objc_complete_type())
+	                    try_resolving_type = type_die->GetAttributeValueAsUnsigned (this, type_cu, DW_AT_APPLE_objc_complete_type, 0);
+                    
+                    if (try_resolving_type)
+                    {
+                        Type *resolved_type = ResolveType (type_cu, type_die, false);
+                        if (resolved_type && resolved_type != DIE_IS_BEING_PARSED)
+                        {
+                            DEBUG_PRINTF ("resolved 0x%8.8" PRIx64 " (cu 0x%8.8" PRIx64 ") from %s to 0x%8.8" PRIx64 " (cu 0x%8.8" PRIx64 ")\n",
+                                          MakeUserID(die->GetOffset()), 
+                                          MakeUserID(dwarf_cu->GetOffset()),
+                                          m_obj_file->GetFileSpec().GetFilename().AsCString(),
+                                          MakeUserID(type_die->GetOffset()), 
+                                          MakeUserID(type_cu->GetOffset()));
+                            
+                            if (die)
+                                m_die_to_type[die] = resolved_type;
+                            type_sp = resolved_type->shared_from_this();
+                            break;
+                        }
+                    }
+                }
+            }
+            else
+            {
+                if (m_using_apple_tables)
+                {
+                    GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_types accelerator table had bad die 0x%8.8x for '%s')\n",
+                                                               die_offset, type_name.GetCString());
+                }
+            }            
+            
+        }
+    }
+    return type_sp;
+}
+
+
+//----------------------------------------------------------------------
+// This function helps to ensure that the declaration contexts match for
+// two different DIEs. Often times debug information will refer to a 
+// forward declaration of a type (the equivalent of "struct my_struct;".
+// There will often be a declaration of that type elsewhere that has the
+// full definition. When we go looking for the full type "my_struct", we
+// will find one or more matches in the accelerator tables and we will
+// then need to make sure the type was in the same declaration context 
+// as the original DIE. This function can efficiently compare two DIEs
+// and will return true when the declaration context matches, and false
+// when they don't. 
+//----------------------------------------------------------------------
+bool
+SymbolFileDWARF::DIEDeclContextsMatch (DWARFCompileUnit* cu1, const DWARFDebugInfoEntry *die1,
+                                       DWARFCompileUnit* cu2, const DWARFDebugInfoEntry *die2)
+{
+    if (die1 == die2)
+        return true;
+
+#if defined (LLDB_CONFIGURATION_DEBUG)
+    // You can't and shouldn't call this function with a compile unit from
+    // two different SymbolFileDWARF instances.
+    assert (DebugInfo()->ContainsCompileUnit (cu1));
+    assert (DebugInfo()->ContainsCompileUnit (cu2));
+#endif
+
+    DWARFDIECollection decl_ctx_1;
+    DWARFDIECollection decl_ctx_2;
+    //The declaration DIE stack is a stack of the declaration context 
+    // DIEs all the way back to the compile unit. If a type "T" is
+    // declared inside a class "B", and class "B" is declared inside
+    // a class "A" and class "A" is in a namespace "lldb", and the
+    // namespace is in a compile unit, there will be a stack of DIEs:
+    //
+    //   [0] DW_TAG_class_type for "B"
+    //   [1] DW_TAG_class_type for "A"
+    //   [2] DW_TAG_namespace  for "lldb"
+    //   [3] DW_TAG_compile_unit for the source file.
+    // 
+    // We grab both contexts and make sure that everything matches 
+    // all the way back to the compiler unit.
+    
+    // First lets grab the decl contexts for both DIEs
+    die1->GetDeclContextDIEs (this, cu1, decl_ctx_1);
+    die2->GetDeclContextDIEs (this, cu2, decl_ctx_2);
+    // Make sure the context arrays have the same size, otherwise
+    // we are done
+    const size_t count1 = decl_ctx_1.Size();
+    const size_t count2 = decl_ctx_2.Size();
+    if (count1 != count2)
+        return false;
+    
+    // Make sure the DW_TAG values match all the way back up the the
+    // compile unit. If they don't, then we are done.
+    const DWARFDebugInfoEntry *decl_ctx_die1;
+    const DWARFDebugInfoEntry *decl_ctx_die2;
+    size_t i;
+    for (i=0; i<count1; i++)
+    {
+        decl_ctx_die1 = decl_ctx_1.GetDIEPtrAtIndex (i);
+        decl_ctx_die2 = decl_ctx_2.GetDIEPtrAtIndex (i);
+        if (decl_ctx_die1->Tag() != decl_ctx_die2->Tag())
+            return false;
+    }
+#if defined LLDB_CONFIGURATION_DEBUG
+
+    // Make sure the top item in the decl context die array is always 
+    // DW_TAG_compile_unit. If it isn't then something went wrong in
+    // the DWARFDebugInfoEntry::GetDeclContextDIEs() function...
+    assert (decl_ctx_1.GetDIEPtrAtIndex (count1 - 1)->Tag() == DW_TAG_compile_unit);
+
+#endif
+    // Always skip the compile unit when comparing by only iterating up to
+    // "count - 1". Here we compare the names as we go. 
+    for (i=0; i<count1 - 1; i++)
+    {
+        decl_ctx_die1 = decl_ctx_1.GetDIEPtrAtIndex (i);
+        decl_ctx_die2 = decl_ctx_2.GetDIEPtrAtIndex (i);
+        const char *name1 = decl_ctx_die1->GetName(this, cu1);
+        const char *name2 = decl_ctx_die2->GetName(this, cu2);
+        // If the string was from a DW_FORM_strp, then the pointer will often
+        // be the same!
+        if (name1 == name2)
+            continue;
+
+        // Name pointers are not equal, so only compare the strings
+        // if both are not NULL.
+        if (name1 && name2)
+        {
+            // If the strings don't compare, we are done...
+            if (strcmp(name1, name2) != 0)
+                return false;
+        }
+        else
+        {
+            // One name was NULL while the other wasn't
+            return false;
+        }
+    }
+    // We made it through all of the checks and the declaration contexts
+    // are equal.
+    return true;
+}
+                                          
+// This function can be used when a DIE is found that is a forward declaration
+// DIE and we want to try and find a type that has the complete definition.
+// "cu" and "die" must be from this SymbolFileDWARF
+TypeSP
+SymbolFileDWARF::FindDefinitionTypeForDIE (DWARFCompileUnit* cu,
+                                           const DWARFDebugInfoEntry *die, 
+                                           const ConstString &type_name)
+{
+    TypeSP type_sp;
+
+#if defined (LLDB_CONFIGURATION_DEBUG)
+    // You can't and shouldn't call this function with a compile unit from
+    // another SymbolFileDWARF instance.
+    assert (DebugInfo()->ContainsCompileUnit (cu));
+#endif
+
+    if (cu == NULL || die == NULL || !type_name)
+        return type_sp;
+
+    std::string qualified_name;
+
+    Log *log (LogChannelDWARF::GetLogIfAny(DWARF_LOG_TYPE_COMPLETION|DWARF_LOG_LOOKUPS));
+    if (log)
+    {
+        die->GetQualifiedName(this, cu, qualified_name);
+        GetObjectFile()->GetModule()->LogMessage (log,
+                                                  "SymbolFileDWARF::FindDefinitionTypeForDIE(die=0x%8.8x (%s), name='%s')",
+                                                  die->GetOffset(),
+                                                  qualified_name.c_str(),
+                                                  type_name.GetCString());
+    }
+
+    DIEArray die_offsets;
+
+    if (m_using_apple_tables)
+    {
+        if (m_apple_types_ap.get())
+        {
+            const bool has_tag = m_apple_types_ap->GetHeader().header_data.ContainsAtom (DWARFMappedHash::eAtomTypeTag);
+            const bool has_qualified_name_hash = m_apple_types_ap->GetHeader().header_data.ContainsAtom (DWARFMappedHash::eAtomTypeQualNameHash);
+            if (has_tag && has_qualified_name_hash)
+            {
+                if (qualified_name.empty())
+                    die->GetQualifiedName(this, cu, qualified_name);
+
+                const uint32_t qualified_name_hash = MappedHash::HashStringUsingDJB (qualified_name.c_str());
+                if (log)
+                    GetObjectFile()->GetModule()->LogMessage (log,"FindByNameAndTagAndQualifiedNameHash()");
+                m_apple_types_ap->FindByNameAndTagAndQualifiedNameHash (type_name.GetCString(), die->Tag(), qualified_name_hash, die_offsets);
+            }
+            else if (has_tag > 1)
+            {
+                if (log)
+                    GetObjectFile()->GetModule()->LogMessage (log,"FindByNameAndTag()");
+                m_apple_types_ap->FindByNameAndTag (type_name.GetCString(), die->Tag(), die_offsets);
+            }
+            else
+            {
+                m_apple_types_ap->FindByName (type_name.GetCString(), die_offsets);
+            }
+        }
+    }
+    else
+    {
+        if (!m_indexed)
+            Index ();
+        
+        m_type_index.Find (type_name, die_offsets);
+    }
+    
+    const size_t num_matches = die_offsets.size();
+
+    const dw_tag_t die_tag = die->Tag();
+    
+    DWARFCompileUnit* type_cu = NULL;
+    const DWARFDebugInfoEntry* type_die = NULL;
+    if (num_matches)
+    {
+        DWARFDebugInfo* debug_info = DebugInfo();
+        for (size_t i=0; i<num_matches; ++i)
+        {
+            const dw_offset_t die_offset = die_offsets[i];
+            type_die = debug_info->GetDIEPtrWithCompileUnitHint (die_offset, &type_cu);
+            
+            if (type_die)
+            {
+                bool try_resolving_type = false;
+
+                // Don't try and resolve the DIE we are looking for with the DIE itself!
+                if (type_die != die)
+                {
+                    const dw_tag_t type_die_tag = type_die->Tag();
+                    // Make sure the tags match
+                    if (type_die_tag == die_tag)
+                    {
+                        // The tags match, lets try resolving this type
+                        try_resolving_type = true;
+                    }
+                    else
+                    {
+                        // The tags don't match, but we need to watch our for a
+                        // forward declaration for a struct and ("struct foo")
+                        // ends up being a class ("class foo { ... };") or
+                        // vice versa.
+                        switch (type_die_tag)
+                        {
+                        case DW_TAG_class_type:
+                            // We had a "class foo", see if we ended up with a "struct foo { ... };"
+                            try_resolving_type = (die_tag == DW_TAG_structure_type);
+                            break;
+                        case DW_TAG_structure_type:
+                            // We had a "struct foo", see if we ended up with a "class foo { ... };"
+                            try_resolving_type = (die_tag == DW_TAG_class_type);
+                            break;
+                        default:
+                            // Tags don't match, don't event try to resolve
+                            // using this type whose name matches....
+                            break;
+                        }
+                    }
+                }
+                        
+                if (try_resolving_type)
+                {
+                    if (log)
+                    {
+                        std::string qualified_name;
+                        type_die->GetQualifiedName(this, cu, qualified_name);
+                        GetObjectFile()->GetModule()->LogMessage (log,
+                                                                  "SymbolFileDWARF::FindDefinitionTypeForDIE(die=0x%8.8x, name='%s') trying die=0x%8.8x (%s)",
+                                                                  die->GetOffset(),
+                                                                  type_name.GetCString(),
+                                                                  type_die->GetOffset(),
+                                                                  qualified_name.c_str());
+                    }
+                    
+                    // Make sure the decl contexts match all the way up
+                    if (DIEDeclContextsMatch(cu, die, type_cu, type_die))
+                    {
+                        Type *resolved_type = ResolveType (type_cu, type_die, false);
+                        if (resolved_type && resolved_type != DIE_IS_BEING_PARSED)
+                        {
+                            DEBUG_PRINTF ("resolved 0x%8.8" PRIx64 " (cu 0x%8.8" PRIx64 ") from %s to 0x%8.8" PRIx64 " (cu 0x%8.8" PRIx64 ")\n",
+                                          MakeUserID(die->GetOffset()), 
+                                          MakeUserID(dwarf_cu->GetOffset()),
+                                          m_obj_file->GetFileSpec().GetFilename().AsCString(),
+                                          MakeUserID(type_die->GetOffset()), 
+                                          MakeUserID(type_cu->GetOffset()));
+                            
+                            m_die_to_type[die] = resolved_type;
+                            type_sp = resolved_type->shared_from_this();
+                            break;
+                        }
+                    }
+                }
+                else
+                {
+                    if (log)
+                    {
+                        std::string qualified_name;
+                        type_die->GetQualifiedName(this, cu, qualified_name);
+                        GetObjectFile()->GetModule()->LogMessage (log,
+                                                                  "SymbolFileDWARF::FindDefinitionTypeForDIE(die=0x%8.8x, name='%s') ignoring die=0x%8.8x (%s)",
+                                                                  die->GetOffset(),
+                                                                  type_name.GetCString(),
+                                                                  type_die->GetOffset(),
+                                                                  qualified_name.c_str());
+                    }
+                }
+            }
+            else
+            {
+                if (m_using_apple_tables)
+                {
+                    GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_types accelerator table had bad die 0x%8.8x for '%s')\n",
+                                                                               die_offset, type_name.GetCString());
+                }
+            }            
+
+        }
+    }
+    return type_sp;
+}
+
+TypeSP
+SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext (const DWARFDeclContext &dwarf_decl_ctx)
+{
+    TypeSP type_sp;
+
+    const uint32_t dwarf_decl_ctx_count = dwarf_decl_ctx.GetSize();
+    if (dwarf_decl_ctx_count > 0)
+    {
+        const ConstString type_name(dwarf_decl_ctx[0].name);
+        const dw_tag_t tag = dwarf_decl_ctx[0].tag;
+
+        if (type_name)
+        {
+            Log *log (LogChannelDWARF::GetLogIfAny(DWARF_LOG_TYPE_COMPLETION|DWARF_LOG_LOOKUPS));
+            if (log)
+            {
+                GetObjectFile()->GetModule()->LogMessage (log,
+                                                          "SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext(tag=%s, qualified-name='%s')",
+                                                          DW_TAG_value_to_name(dwarf_decl_ctx[0].tag),
+                                                          dwarf_decl_ctx.GetQualifiedName());
+            }
+            
+            DIEArray die_offsets;
+            
+            if (m_using_apple_tables)
+            {
+                if (m_apple_types_ap.get())
+                {
+                    const bool has_tag = m_apple_types_ap->GetHeader().header_data.ContainsAtom (DWARFMappedHash::eAtomTypeTag);
+                    const bool has_qualified_name_hash = m_apple_types_ap->GetHeader().header_data.ContainsAtom (DWARFMappedHash::eAtomTypeQualNameHash);
+                    if (has_tag && has_qualified_name_hash)
+                    {
+                        const char *qualified_name = dwarf_decl_ctx.GetQualifiedName();
+                        const uint32_t qualified_name_hash = MappedHash::HashStringUsingDJB (qualified_name);
+                        if (log)
+                            GetObjectFile()->GetModule()->LogMessage (log,"FindByNameAndTagAndQualifiedNameHash()");
+                        m_apple_types_ap->FindByNameAndTagAndQualifiedNameHash (type_name.GetCString(), tag, qualified_name_hash, die_offsets);
+                    }
+                    else if (has_tag)
+                    {
+                        if (log)
+                            GetObjectFile()->GetModule()->LogMessage (log,"FindByNameAndTag()");
+                        m_apple_types_ap->FindByNameAndTag (type_name.GetCString(), tag, die_offsets);
+                    }
+                    else
+                    {
+                        m_apple_types_ap->FindByName (type_name.GetCString(), die_offsets);
+                    }
+                }
+            }
+            else
+            {
+                if (!m_indexed)
+                    Index ();
+                
+                m_type_index.Find (type_name, die_offsets);
+            }
+            
+            const size_t num_matches = die_offsets.size();
+            
+            
+            DWARFCompileUnit* type_cu = NULL;
+            const DWARFDebugInfoEntry* type_die = NULL;
+            if (num_matches)
+            {
+                DWARFDebugInfo* debug_info = DebugInfo();
+                for (size_t i=0; i<num_matches; ++i)
+                {
+                    const dw_offset_t die_offset = die_offsets[i];
+                    type_die = debug_info->GetDIEPtrWithCompileUnitHint (die_offset, &type_cu);
+                    
+                    if (type_die)
+                    {
+                        bool try_resolving_type = false;
+                        
+                        // Don't try and resolve the DIE we are looking for with the DIE itself!
+                        const dw_tag_t type_tag = type_die->Tag();
+                        // Make sure the tags match
+                        if (type_tag == tag)
+                        {
+                            // The tags match, lets try resolving this type
+                            try_resolving_type = true;
+                        }
+                        else
+                        {
+                            // The tags don't match, but we need to watch our for a
+                            // forward declaration for a struct and ("struct foo")
+                            // ends up being a class ("class foo { ... };") or
+                            // vice versa.
+                            switch (type_tag)
+                            {
+                                case DW_TAG_class_type:
+                                    // We had a "class foo", see if we ended up with a "struct foo { ... };"
+                                    try_resolving_type = (tag == DW_TAG_structure_type);
+                                    break;
+                                case DW_TAG_structure_type:
+                                    // We had a "struct foo", see if we ended up with a "class foo { ... };"
+                                    try_resolving_type = (tag == DW_TAG_class_type);
+                                    break;
+                                default:
+                                    // Tags don't match, don't event try to resolve
+                                    // using this type whose name matches....
+                                    break;
+                            }
+                        }
+                        
+                        if (try_resolving_type)
+                        {
+                            DWARFDeclContext type_dwarf_decl_ctx;
+                            type_die->GetDWARFDeclContext (this, type_cu, type_dwarf_decl_ctx);
+
+                            if (log)
+                            {
+                                GetObjectFile()->GetModule()->LogMessage (log,
+                                                                          "SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext(tag=%s, qualified-name='%s') trying die=0x%8.8x (%s)",
+                                                                          DW_TAG_value_to_name(dwarf_decl_ctx[0].tag),
+                                                                          dwarf_decl_ctx.GetQualifiedName(),
+                                                                          type_die->GetOffset(),
+                                                                          type_dwarf_decl_ctx.GetQualifiedName());
+                            }
+                            
+                            // Make sure the decl contexts match all the way up
+                            if (dwarf_decl_ctx == type_dwarf_decl_ctx)
+                            {
+                                Type *resolved_type = ResolveType (type_cu, type_die, false);
+                                if (resolved_type && resolved_type != DIE_IS_BEING_PARSED)
+                                {
+                                    type_sp = resolved_type->shared_from_this();
+                                    break;
+                                }
+                            }
+                        }
+                        else
+                        {
+                            if (log)
+                            {
+                                std::string qualified_name;
+                                type_die->GetQualifiedName(this, type_cu, qualified_name);
+                                GetObjectFile()->GetModule()->LogMessage (log,
+                                                                          "SymbolFileDWARF::FindDefinitionTypeForDWARFDeclContext(tag=%s, qualified-name='%s') ignoring die=0x%8.8x (%s)",
+                                                                          DW_TAG_value_to_name(dwarf_decl_ctx[0].tag),
+                                                                          dwarf_decl_ctx.GetQualifiedName(),
+                                                                          type_die->GetOffset(),
+                                                                          qualified_name.c_str());
+                            }
+                        }
+                    }
+                    else
+                    {
+                        if (m_using_apple_tables)
+                        {
+                            GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_types accelerator table had bad die 0x%8.8x for '%s')\n",
+                                                                                       die_offset, type_name.GetCString());
+                        }
+                    }            
+                    
+                }
+            }
+        }
+    }
+    return type_sp;
+}
+
+bool
+SymbolFileDWARF::CopyUniqueClassMethodTypes (SymbolFileDWARF *src_symfile,
+                                             Type *class_type,
+                                             DWARFCompileUnit* src_cu,
+                                             const DWARFDebugInfoEntry *src_class_die,
+                                             DWARFCompileUnit* dst_cu,
+                                             const DWARFDebugInfoEntry *dst_class_die,
+                                             llvm::SmallVectorImpl <const DWARFDebugInfoEntry *> &failures)
+{
+    if (!class_type || !src_cu || !src_class_die || !dst_cu || !dst_class_die)
+        return false;
+    if (src_class_die->Tag() != dst_class_die->Tag())
+        return false;
+    
+    // We need to complete the class type so we can get all of the method types
+    // parsed so we can then unique those types to their equivalent counterparts
+    // in "dst_cu" and "dst_class_die"
+    class_type->GetClangFullType();
+
+    const DWARFDebugInfoEntry *src_die;
+    const DWARFDebugInfoEntry *dst_die;
+    UniqueCStringMap<const DWARFDebugInfoEntry *> src_name_to_die;
+    UniqueCStringMap<const DWARFDebugInfoEntry *> dst_name_to_die;
+    UniqueCStringMap<const DWARFDebugInfoEntry *> src_name_to_die_artificial;
+    UniqueCStringMap<const DWARFDebugInfoEntry *> dst_name_to_die_artificial;
+    for (src_die = src_class_die->GetFirstChild(); src_die != NULL; src_die = src_die->GetSibling())
+    {
+        if (src_die->Tag() == DW_TAG_subprogram)
+        {
+            // Make sure this is a declaration and not a concrete instance by looking
+            // for DW_AT_declaration set to 1. Sometimes concrete function instances
+            // are placed inside the class definitions and shouldn't be included in
+            // the list of things are are tracking here.
+            if (src_die->GetAttributeValueAsUnsigned(src_symfile, src_cu, DW_AT_declaration, 0) == 1)
+            {
+                const char *src_name = src_die->GetMangledName (src_symfile, src_cu);
+                if (src_name)
+                {
+                    ConstString src_const_name(src_name);
+                    if (src_die->GetAttributeValueAsUnsigned(src_symfile, src_cu, DW_AT_artificial, 0))
+                        src_name_to_die_artificial.Append(src_const_name.GetCString(), src_die);
+                    else
+                        src_name_to_die.Append(src_const_name.GetCString(), src_die);
+                }
+            }
+        }
+    }
+    for (dst_die = dst_class_die->GetFirstChild(); dst_die != NULL; dst_die = dst_die->GetSibling())
+    {
+        if (dst_die->Tag() == DW_TAG_subprogram)
+        {
+            // Make sure this is a declaration and not a concrete instance by looking
+            // for DW_AT_declaration set to 1. Sometimes concrete function instances
+            // are placed inside the class definitions and shouldn't be included in
+            // the list of things are are tracking here.
+            if (dst_die->GetAttributeValueAsUnsigned(this, dst_cu, DW_AT_declaration, 0) == 1)
+            {
+                const char *dst_name = dst_die->GetMangledName (this, dst_cu);
+                if (dst_name)
+                {
+                    ConstString dst_const_name(dst_name);
+                    if (dst_die->GetAttributeValueAsUnsigned(this, dst_cu, DW_AT_artificial, 0))
+                        dst_name_to_die_artificial.Append(dst_const_name.GetCString(), dst_die);
+                    else
+                        dst_name_to_die.Append(dst_const_name.GetCString(), dst_die);
+                }
+            }
+        }
+    }
+    const uint32_t src_size = src_name_to_die.GetSize ();
+    const uint32_t dst_size = dst_name_to_die.GetSize ();
+    Log *log (LogChannelDWARF::GetLogIfAny(DWARF_LOG_DEBUG_INFO | DWARF_LOG_TYPE_COMPLETION));
+
+    // Is everything kosher so we can go through the members at top speed?
+    bool fast_path = true;
+                            
+    if (src_size != dst_size)
+    {
+        if (src_size != 0 && dst_size != 0)
+        {
+            if (log)
+                log->Printf("warning: trying to unique class DIE 0x%8.8x to 0x%8.8x, but they didn't have the same size (src=%d, dst=%d)",
+                            src_class_die->GetOffset(),
+                            dst_class_die->GetOffset(),
+                            src_size,
+                            dst_size);
+        }
+        
+        fast_path = false;
+    }
+
+    uint32_t idx;
+    
+    if (fast_path)
+    {
+        for (idx = 0; idx < src_size; ++idx)
+        {
+            src_die = src_name_to_die.GetValueAtIndexUnchecked (idx);
+            dst_die = dst_name_to_die.GetValueAtIndexUnchecked (idx);
+
+            if (src_die->Tag() != dst_die->Tag())
+            {
+                if (log)
+                    log->Printf("warning: tried to unique class DIE 0x%8.8x to 0x%8.8x, but 0x%8.8x (%s) tags didn't match 0x%8.8x (%s)",
+                                src_class_die->GetOffset(),
+                                dst_class_die->GetOffset(),
+                                src_die->GetOffset(),
+                                DW_TAG_value_to_name(src_die->Tag()),
+                                dst_die->GetOffset(),
+                                DW_TAG_value_to_name(src_die->Tag()));
+                fast_path = false;
+            }
+            
+            const char *src_name = src_die->GetMangledName (src_symfile, src_cu);
+            const char *dst_name = dst_die->GetMangledName (this, dst_cu);
+            
+            // Make sure the names match
+            if (src_name == dst_name || (strcmp (src_name, dst_name) == 0))
+                continue;
+
+            if (log)
+                log->Printf("warning: tried to unique class DIE 0x%8.8x to 0x%8.8x, but 0x%8.8x (%s) names didn't match 0x%8.8x (%s)",
+                            src_class_die->GetOffset(),
+                            dst_class_die->GetOffset(),
+                            src_die->GetOffset(),
+                            src_name,
+                            dst_die->GetOffset(),
+                            dst_name);
+            
+            fast_path = false;
+        }
+    }
+
+    // Now do the work of linking the DeclContexts and Types.
+    if (fast_path)
+    {
+        // We can do this quickly.  Just run across the tables index-for-index since
+        // we know each node has matching names and tags.
+        for (idx = 0; idx < src_size; ++idx)
+        {
+            src_die = src_name_to_die.GetValueAtIndexUnchecked (idx);
+            dst_die = dst_name_to_die.GetValueAtIndexUnchecked (idx);
+            
+            clang::DeclContext *src_decl_ctx = src_symfile->m_die_to_decl_ctx[src_die];
+            if (src_decl_ctx)
+            {
+                if (log)
+                    log->Printf ("uniquing decl context %p from 0x%8.8x for 0x%8.8x", src_decl_ctx, src_die->GetOffset(), dst_die->GetOffset());
+                LinkDeclContextToDIE (src_decl_ctx, dst_die);
+            }
+            else
+            {
+                if (log)
+                    log->Printf ("warning: tried to unique decl context from 0x%8.8x for 0x%8.8x, but none was found", src_die->GetOffset(), dst_die->GetOffset());
+            }
+            
+            Type *src_child_type = m_die_to_type[src_die];
+            if (src_child_type)
+            {
+                if (log)
+                    log->Printf ("uniquing type %p (uid=0x%" PRIx64 ") from 0x%8.8x for 0x%8.8x", src_child_type, src_child_type->GetID(), src_die->GetOffset(), dst_die->GetOffset());
+                m_die_to_type[dst_die] = src_child_type;
+            }
+            else
+            {
+                if (log)
+                    log->Printf ("warning: tried to unique lldb_private::Type from 0x%8.8x for 0x%8.8x, but none was found", src_die->GetOffset(), dst_die->GetOffset());
+            }
+        }
+    }
+    else
+    {
+        // We must do this slowly.  For each member of the destination, look
+        // up a member in the source with the same name, check its tag, and
+        // unique them if everything matches up.  Report failures.
+        
+        if (!src_name_to_die.IsEmpty() && !dst_name_to_die.IsEmpty())
+        {
+            src_name_to_die.Sort();
+        
+            for (idx = 0; idx < dst_size; ++idx)
+            {
+                const char *dst_name = dst_name_to_die.GetCStringAtIndex(idx);
+                dst_die = dst_name_to_die.GetValueAtIndexUnchecked(idx);
+                src_die = src_name_to_die.Find(dst_name, NULL);
+                
+                if (src_die && (src_die->Tag() == dst_die->Tag()))
+                {
+                    clang::DeclContext *src_decl_ctx = src_symfile->m_die_to_decl_ctx[src_die];
+                    if (src_decl_ctx)
+                    {
+                        if (log)
+                            log->Printf ("uniquing decl context %p from 0x%8.8x for 0x%8.8x", src_decl_ctx, src_die->GetOffset(), dst_die->GetOffset());
+                        LinkDeclContextToDIE (src_decl_ctx, dst_die);
+                    }
+                    else
+                    {
+                        if (log)
+                            log->Printf ("warning: tried to unique decl context from 0x%8.8x for 0x%8.8x, but none was found", src_die->GetOffset(), dst_die->GetOffset());
+                    }
+                    
+                    Type *src_child_type = m_die_to_type[src_die];
+                    if (src_child_type)
+                    {
+                        if (log)
+                            log->Printf ("uniquing type %p (uid=0x%" PRIx64 ") from 0x%8.8x for 0x%8.8x", src_child_type, src_child_type->GetID(), src_die->GetOffset(), dst_die->GetOffset());
+                        m_die_to_type[dst_die] = src_child_type;
+                    }
+                    else
+                    {
+                        if (log)
+                            log->Printf ("warning: tried to unique lldb_private::Type from 0x%8.8x for 0x%8.8x, but none was found", src_die->GetOffset(), dst_die->GetOffset());
+                    }
+                }
+                else
+                {
+                    if (log)
+                        log->Printf ("warning: couldn't find a match for 0x%8.8x", dst_die->GetOffset());
+
+                    failures.push_back(dst_die);
+                }
+            }
+        }
+    }
+    
+    const uint32_t src_size_artificial = src_name_to_die_artificial.GetSize ();
+    const uint32_t dst_size_artificial = dst_name_to_die_artificial.GetSize ();
+    
+    UniqueCStringMap<const DWARFDebugInfoEntry *> name_to_die_artificial_not_in_src;
+
+    if (src_size_artificial && dst_size_artificial)
+    {
+        dst_name_to_die_artificial.Sort();
+        
+        for (idx = 0; idx < src_size_artificial; ++idx)
+        {
+            const char *src_name_artificial = src_name_to_die_artificial.GetCStringAtIndex(idx);
+            src_die = src_name_to_die_artificial.GetValueAtIndexUnchecked (idx);
+            dst_die = dst_name_to_die_artificial.Find(src_name_artificial, NULL);
+            
+            if (dst_die)
+            {
+                // Both classes have the artificial types, link them
+                clang::DeclContext *src_decl_ctx = m_die_to_decl_ctx[src_die];
+                if (src_decl_ctx)
+                {
+                    if (log)
+                        log->Printf ("uniquing decl context %p from 0x%8.8x for 0x%8.8x", src_decl_ctx, src_die->GetOffset(), dst_die->GetOffset());
+                    LinkDeclContextToDIE (src_decl_ctx, dst_die);
+                }
+                else
+                {
+                    if (log)
+                        log->Printf ("warning: tried to unique decl context from 0x%8.8x for 0x%8.8x, but none was found", src_die->GetOffset(), dst_die->GetOffset());
+                }
+                
+                Type *src_child_type = m_die_to_type[src_die];
+                if (src_child_type)
+                {
+                    if (log)
+                        log->Printf ("uniquing type %p (uid=0x%" PRIx64 ") from 0x%8.8x for 0x%8.8x", src_child_type, src_child_type->GetID(), src_die->GetOffset(), dst_die->GetOffset());
+                    m_die_to_type[dst_die] = src_child_type;
+                }
+                else
+                {
+                    if (log)
+                        log->Printf ("warning: tried to unique lldb_private::Type from 0x%8.8x for 0x%8.8x, but none was found", src_die->GetOffset(), dst_die->GetOffset());
+                }
+            }
+        }
+    }
+
+    if (dst_size_artificial)
+    {
+        for (idx = 0; idx < dst_size_artificial; ++idx)
+        {
+            const char *dst_name_artificial = dst_name_to_die_artificial.GetCStringAtIndex(idx);
+            dst_die = dst_name_to_die_artificial.GetValueAtIndexUnchecked (idx);
+            if (log)
+                log->Printf ("warning: need to create artificial method for 0x%8.8x for method '%s'", dst_die->GetOffset(), dst_name_artificial);
+            
+            failures.push_back(dst_die);
+        }
+    }
+
+    return (failures.size() != 0);
+}
+
+TypeSP
+SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry *die, bool *type_is_new_ptr)
+{
+    TypeSP type_sp;
+
+    if (type_is_new_ptr)
+        *type_is_new_ptr = false;
+
+#if defined(LLDB_CONFIGURATION_DEBUG) or defined(LLDB_CONFIGURATION_RELEASE)
+    static DIEStack g_die_stack;
+    DIEStack::ScopedPopper scoped_die_logger(g_die_stack);
+#endif
+
+    AccessType accessibility = eAccessNone;
+    if (die != NULL)
+    {
+        Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO));
+        if (log)
+        {
+            const DWARFDebugInfoEntry *context_die;
+            clang::DeclContext *context = GetClangDeclContextContainingDIE (dwarf_cu, die, &context_die);
+            
+            GetObjectFile()->GetModule()->LogMessage (log, "SymbolFileDWARF::ParseType (die = 0x%8.8x, decl_ctx = %p (die 0x%8.8x)) %s name = '%s')",
+                        die->GetOffset(),
+                        context,
+                        context_die->GetOffset(),
+                        DW_TAG_value_to_name(die->Tag()), 
+                        die->GetName(this, dwarf_cu));
+            
+#if defined(LLDB_CONFIGURATION_DEBUG) or defined(LLDB_CONFIGURATION_RELEASE)
+            scoped_die_logger.Push (dwarf_cu, die);
+            g_die_stack.LogDIEs(log, this);
+#endif
+        }
+//
+//        Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO));
+//        if (log && dwarf_cu)
+//        {
+//            StreamString s;
+//            die->DumpLocation (this, dwarf_cu, s);
+//            GetObjectFile()->GetModule()->LogMessage (log, "SymbolFileDwarf::%s %s", __FUNCTION__, s.GetData());
+//            
+//        }
+        
+        Type *type_ptr = m_die_to_type.lookup (die);
+        TypeList* type_list = GetTypeList();
+        if (type_ptr == NULL)
+        {
+            ClangASTContext &ast = GetClangASTContext();
+            if (type_is_new_ptr)
+                *type_is_new_ptr = true;
+
+            const dw_tag_t tag = die->Tag();
+
+            bool is_forward_declaration = false;
+            DWARFDebugInfoEntry::Attributes attributes;
+            const char *type_name_cstr = NULL;
+            ConstString type_name_const_str;
+            Type::ResolveState resolve_state = Type::eResolveStateUnresolved;
+            uint64_t byte_size = 0;
+            Declaration decl;
+
+            Type::EncodingDataType encoding_data_type = Type::eEncodingIsUID;
+            ClangASTType clang_type;
+
+            dw_attr_t attr;
+
+            switch (tag)
+            {
+            case DW_TAG_base_type:
+            case DW_TAG_pointer_type:
+            case DW_TAG_reference_type:
+            case DW_TAG_rvalue_reference_type:
+            case DW_TAG_typedef:
+            case DW_TAG_const_type:
+            case DW_TAG_restrict_type:
+            case DW_TAG_volatile_type:
+            case DW_TAG_unspecified_type:
+                {
+                    // Set a bit that lets us know that we are currently parsing this
+                    m_die_to_type[die] = DIE_IS_BEING_PARSED;
+
+                    const size_t num_attributes = die->GetAttributes(this, dwarf_cu, NULL, attributes);
+                    uint32_t encoding = 0;
+                    lldb::user_id_t encoding_uid = LLDB_INVALID_UID;
+
+                    if (num_attributes > 0)
+                    {
+                        uint32_t i;
+                        for (i=0; i<num_attributes; ++i)
+                        {
+                            attr = attributes.AttributeAtIndex(i);
+                            DWARFFormValue form_value;
+                            if (attributes.ExtractFormValueAtIndex(this, i, form_value))
+                            {
+                                switch (attr)
+                                {
+                                case DW_AT_decl_file:   decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
+                                case DW_AT_decl_line:   decl.SetLine(form_value.Unsigned()); break;
+                                case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
+                                case DW_AT_name:
+                                    
+                                    type_name_cstr = form_value.AsCString(&get_debug_str_data());
+                                    // Work around a bug in llvm-gcc where they give a name to a reference type which doesn't
+                                    // include the "&"...
+                                    if (tag == DW_TAG_reference_type)
+                                    {
+                                        if (strchr (type_name_cstr, '&') == NULL)
+                                            type_name_cstr = NULL;
+                                    }
+                                    if (type_name_cstr)
+                                        type_name_const_str.SetCString(type_name_cstr);
+                                    break;
+                                case DW_AT_byte_size:   byte_size = form_value.Unsigned(); break;
+                                case DW_AT_encoding:    encoding = form_value.Unsigned(); break;
+                                case DW_AT_type:        encoding_uid = form_value.Reference(dwarf_cu); break;
+                                default:
+                                case DW_AT_sibling:
+                                    break;
+                                }
+                            }
+                        }
+                    }
+
+                    DEBUG_PRINTF ("0x%8.8" PRIx64 ": %s (\"%s\") type => 0x%8.8x\n", MakeUserID(die->GetOffset()), DW_TAG_value_to_name(tag), type_name_cstr, encoding_uid);
+
+                    switch (tag)
+                    {
+                    default:
+                        break;
+
+                    case DW_TAG_unspecified_type:
+                        if (strcmp(type_name_cstr, "nullptr_t") == 0 ||
+                            strcmp(type_name_cstr, "decltype(nullptr)") == 0 )
+                        {
+                            resolve_state = Type::eResolveStateFull;
+                            clang_type = ast.GetBasicType(eBasicTypeNullPtr);
+                            break;
+                        }
+                        // Fall through to base type below in case we can handle the type there...
+
+                    case DW_TAG_base_type:
+                        resolve_state = Type::eResolveStateFull;
+                        clang_type = ast.GetBuiltinTypeForDWARFEncodingAndBitSize (type_name_cstr, 
+                                                                                   encoding, 
+                                                                                   byte_size * 8);
+                        break;
+
+                    case DW_TAG_pointer_type:           encoding_data_type = Type::eEncodingIsPointerUID;           break;
+                    case DW_TAG_reference_type:         encoding_data_type = Type::eEncodingIsLValueReferenceUID;   break;
+                    case DW_TAG_rvalue_reference_type:  encoding_data_type = Type::eEncodingIsRValueReferenceUID;   break;
+                    case DW_TAG_typedef:                encoding_data_type = Type::eEncodingIsTypedefUID;           break;
+                    case DW_TAG_const_type:             encoding_data_type = Type::eEncodingIsConstUID;             break;
+                    case DW_TAG_restrict_type:          encoding_data_type = Type::eEncodingIsRestrictUID;          break;
+                    case DW_TAG_volatile_type:          encoding_data_type = Type::eEncodingIsVolatileUID;          break;
+                    }
+
+                    if (!clang_type && (encoding_data_type == Type::eEncodingIsPointerUID || encoding_data_type == Type::eEncodingIsTypedefUID) && sc.comp_unit != NULL)
+                    {
+                        bool translation_unit_is_objc = (sc.comp_unit->GetLanguage() == eLanguageTypeObjC || sc.comp_unit->GetLanguage() == eLanguageTypeObjC_plus_plus);
+                        
+                        if (translation_unit_is_objc)
+                        {
+                            if (type_name_cstr != NULL)
+                            {
+                                static ConstString g_objc_type_name_id("id");
+                                static ConstString g_objc_type_name_Class("Class");
+                                static ConstString g_objc_type_name_selector("SEL");
+                                
+                                if (type_name_const_str == g_objc_type_name_id)
+                                {
+                                    if (log)
+                                        GetObjectFile()->GetModule()->LogMessage (log, "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' is Objective C 'id' built-in type.",
+                                                                                  die->GetOffset(), 
+                                                                                  DW_TAG_value_to_name(die->Tag()), 
+                                                                                  die->GetName(this, dwarf_cu));
+                                    clang_type = ast.GetBasicType(eBasicTypeObjCID);
+                                    encoding_data_type = Type::eEncodingIsUID;
+                                    encoding_uid = LLDB_INVALID_UID;
+                                    resolve_state = Type::eResolveStateFull;
+
+                                }
+                                else if (type_name_const_str == g_objc_type_name_Class)
+                                {
+                                    if (log)
+                                        GetObjectFile()->GetModule()->LogMessage (log, "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' is Objective C 'Class' built-in type.",
+                                                                                  die->GetOffset(), 
+                                                                                  DW_TAG_value_to_name(die->Tag()), 
+                                                                                  die->GetName(this, dwarf_cu));
+                                    clang_type = ast.GetBasicType(eBasicTypeObjCClass);
+                                    encoding_data_type = Type::eEncodingIsUID;
+                                    encoding_uid = LLDB_INVALID_UID;
+                                    resolve_state = Type::eResolveStateFull;
+                                }
+                                else if (type_name_const_str == g_objc_type_name_selector)
+                                {
+                                    if (log)
+                                        GetObjectFile()->GetModule()->LogMessage (log, "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' is Objective C 'selector' built-in type.",
+                                                                                  die->GetOffset(), 
+                                                                                  DW_TAG_value_to_name(die->Tag()), 
+                                                                                  die->GetName(this, dwarf_cu));
+                                    clang_type = ast.GetBasicType(eBasicTypeObjCSel);
+                                    encoding_data_type = Type::eEncodingIsUID;
+                                    encoding_uid = LLDB_INVALID_UID;
+                                    resolve_state = Type::eResolveStateFull;
+                                }
+                            }
+                            else if (encoding_data_type == Type::eEncodingIsPointerUID && encoding_uid != LLDB_INVALID_UID)
+                            {
+                                // Clang sometimes erroneously emits id as objc_object*.  In that case we fix up the type to "id".
+                            
+                                DWARFDebugInfoEntry* encoding_die = dwarf_cu->GetDIEPtr(encoding_uid);
+                                
+                                if (encoding_die && encoding_die->Tag() == DW_TAG_structure_type)
+                                {                                    
+                                    if (const char *struct_name = encoding_die->GetAttributeValueAsString(this, dwarf_cu, DW_AT_name, NULL))
+                                    {
+                                        if (!strcmp(struct_name, "objc_object"))
+                                        {
+                                            if (log)
+                                                GetObjectFile()->GetModule()->LogMessage (log, "SymbolFileDWARF::ParseType (die = 0x%8.8x) %s '%s' is 'objc_object*', which we overrode to 'id'.",
+                                                                                          die->GetOffset(),
+                                                                                          DW_TAG_value_to_name(die->Tag()),
+                                                                                          die->GetName(this, dwarf_cu));
+                                            clang_type = ast.GetBasicType(eBasicTypeObjCID);
+                                            encoding_data_type = Type::eEncodingIsUID;
+                                            encoding_uid = LLDB_INVALID_UID;
+                                            resolve_state = Type::eResolveStateFull;
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                        
+                    type_sp.reset( new Type (MakeUserID(die->GetOffset()),
+                                             this, 
+                                             type_name_const_str, 
+                                             byte_size, 
+                                             NULL, 
+                                             encoding_uid, 
+                                             encoding_data_type, 
+                                             &decl, 
+                                             clang_type, 
+                                             resolve_state));
+                    
+                    m_die_to_type[die] = type_sp.get();
+
+//                  Type* encoding_type = GetUniquedTypeForDIEOffset(encoding_uid, type_sp, NULL, 0, 0, false);
+//                  if (encoding_type != NULL)
+//                  {
+//                      if (encoding_type != DIE_IS_BEING_PARSED)
+//                          type_sp->SetEncodingType(encoding_type);
+//                      else
+//                          m_indirect_fixups.push_back(type_sp.get());
+//                  }
+                }
+                break;
+
+            case DW_TAG_structure_type:
+            case DW_TAG_union_type:
+            case DW_TAG_class_type:
+                {
+                    // Set a bit that lets us know that we are currently parsing this
+                    m_die_to_type[die] = DIE_IS_BEING_PARSED;
+                    bool byte_size_valid = false;
+
+                    LanguageType class_language = eLanguageTypeUnknown;
+                    bool is_complete_objc_class = false;
+                    //bool struct_is_class = false;
+                    const size_t num_attributes = die->GetAttributes(this, dwarf_cu, NULL, attributes);
+                    if (num_attributes > 0)
+                    {
+                        uint32_t i;
+                        for (i=0; i<num_attributes; ++i)
+                        {
+                            attr = attributes.AttributeAtIndex(i);
+                            DWARFFormValue form_value;
+                            if (attributes.ExtractFormValueAtIndex(this, i, form_value))
+                            {
+                                switch (attr)
+                                {
+                                case DW_AT_decl_file:
+                                    if (dwarf_cu->DW_AT_decl_file_attributes_are_invalid())
+									{
+										// llvm-gcc outputs invalid DW_AT_decl_file attributes that always
+										// point to the compile unit file, so we clear this invalid value
+										// so that we can still unique types efficiently.
+                                        decl.SetFile(FileSpec ("<invalid>", false));
+									}
+                                    else
+                                        decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); 
+                                    break;
+
+                                case DW_AT_decl_line:
+                                    decl.SetLine(form_value.Unsigned()); 
+                                    break;
+
+                                case DW_AT_decl_column: 
+                                    decl.SetColumn(form_value.Unsigned()); 
+                                    break;
+
+                                case DW_AT_name:
+                                    type_name_cstr = form_value.AsCString(&get_debug_str_data());
+                                    type_name_const_str.SetCString(type_name_cstr);
+                                    break;
+
+                                case DW_AT_byte_size:   
+                                    byte_size = form_value.Unsigned(); 
+                                    byte_size_valid = true;
+                                    break;
+
+                                case DW_AT_accessibility: 
+                                    accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); 
+                                    break;
+
+                                case DW_AT_declaration: 
+                                    is_forward_declaration = form_value.Boolean();
+                                    break;
+
+                                case DW_AT_APPLE_runtime_class: 
+                                    class_language = (LanguageType)form_value.Signed(); 
+                                    break;
+
+                                case DW_AT_APPLE_objc_complete_type:
+                                    is_complete_objc_class = form_value.Signed(); 
+                                    break;
+                                        
+                                case DW_AT_allocated:
+                                case DW_AT_associated:
+                                case DW_AT_data_location:
+                                case DW_AT_description:
+                                case DW_AT_start_scope:
+                                case DW_AT_visibility:
+                                default:
+                                case DW_AT_sibling:
+                                    break;
+                                }
+                            }
+                        }
+                    }
+
+                    UniqueDWARFASTType unique_ast_entry;
+
+                    // Only try and unique the type if it has a name. 
+                    if (type_name_const_str &&
+                        GetUniqueDWARFASTTypeMap().Find (type_name_const_str,
+                                                         this,
+                                                         dwarf_cu,
+                                                         die,
+                                                         decl,
+                                                         byte_size_valid ? byte_size : -1,
+                                                         unique_ast_entry))
+                    {
+                        // We have already parsed this type or from another 
+                        // compile unit. GCC loves to use the "one definition
+                        // rule" which can result in multiple definitions
+                        // of the same class over and over in each compile
+                        // unit.
+                        type_sp = unique_ast_entry.m_type_sp;
+                        if (type_sp)
+                        {
+                            m_die_to_type[die] = type_sp.get();
+                            return type_sp;
+                        }
+                    }
+                    
+                    DEBUG_PRINTF ("0x%8.8" PRIx64 ": %s (\"%s\")\n", MakeUserID(die->GetOffset()), DW_TAG_value_to_name(tag), type_name_cstr);
+
+                    int tag_decl_kind = -1;
+                    AccessType default_accessibility = eAccessNone;
+                    if (tag == DW_TAG_structure_type)
+                    {
+                        tag_decl_kind = clang::TTK_Struct;
+                        default_accessibility = eAccessPublic;
+                    }
+                    else if (tag == DW_TAG_union_type)
+                    {
+                        tag_decl_kind = clang::TTK_Union;
+                        default_accessibility = eAccessPublic;
+                    }
+                    else if (tag == DW_TAG_class_type)
+                    {
+                        tag_decl_kind = clang::TTK_Class;
+                        default_accessibility = eAccessPrivate;
+                    }
+                    
+                    if (byte_size_valid && byte_size == 0 && type_name_cstr &&
+                        die->HasChildren() == false && 
+                        sc.comp_unit->GetLanguage() == eLanguageTypeObjC)
+                    {
+                        // Work around an issue with clang at the moment where
+                        // forward declarations for objective C classes are emitted
+                        // as:
+                        //  DW_TAG_structure_type [2]  
+                        //  DW_AT_name( "ForwardObjcClass" )
+                        //  DW_AT_byte_size( 0x00 )
+                        //  DW_AT_decl_file( "..." )
+                        //  DW_AT_decl_line( 1 )
+                        //
+                        // Note that there is no DW_AT_declaration and there are
+                        // no children, and the byte size is zero.
+                        is_forward_declaration = true;
+                    }
+
+                    if (class_language == eLanguageTypeObjC ||
+                        class_language == eLanguageTypeObjC_plus_plus)
+                    {
+                        if (!is_complete_objc_class && Supports_DW_AT_APPLE_objc_complete_type(dwarf_cu))
+                        {
+                            // We have a valid eSymbolTypeObjCClass class symbol whose
+                            // name matches the current objective C class that we
+                            // are trying to find and this DIE isn't the complete
+                            // definition (we checked is_complete_objc_class above and
+                            // know it is false), so the real definition is in here somewhere
+                            type_sp = FindCompleteObjCDefinitionTypeForDIE (die, type_name_const_str, true);
+
+                            if (!type_sp && GetDebugMapSymfile ())
+                            {
+                                // We weren't able to find a full declaration in
+                                // this DWARF, see if we have a declaration anywhere    
+                                // else...
+                                type_sp = m_debug_map_symfile->FindCompleteObjCDefinitionTypeForDIE (die, type_name_const_str, true);
+                            }
+                            
+                            if (type_sp)
+                            {
+                                if (log)
+                                {
+                                    GetObjectFile()->GetModule()->LogMessage (log,
+                                                                              "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is an incomplete objc type, complete type is 0x%8.8" PRIx64,
+                                                                              this,
+                                                                              die->GetOffset(), 
+                                                                              DW_TAG_value_to_name(tag),
+                                                                              type_name_cstr,
+                                                                              type_sp->GetID());
+                                }
+                                
+                                // We found a real definition for this type elsewhere
+                                // so lets use it and cache the fact that we found
+                                // a complete type for this die
+                                m_die_to_type[die] = type_sp.get();
+                                return type_sp;
+                            }
+                        }
+                    }
+                    
+
+                    if (is_forward_declaration)
+                    {
+                        // We have a forward declaration to a type and we need
+                        // to try and find a full declaration. We look in the
+                        // current type index just in case we have a forward
+                        // declaration followed by an actual declarations in the
+                        // DWARF. If this fails, we need to look elsewhere...
+                        if (log)
+                        {
+                            GetObjectFile()->GetModule()->LogMessage (log,
+                                                                      "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a forward declaration, trying to find complete type", 
+                                                                      this,
+                                                                      die->GetOffset(), 
+                                                                      DW_TAG_value_to_name(tag),
+                                                                      type_name_cstr);
+                        }
+                    
+                        DWARFDeclContext die_decl_ctx;
+                        die->GetDWARFDeclContext(this, dwarf_cu, die_decl_ctx);
+
+                        //type_sp = FindDefinitionTypeForDIE (dwarf_cu, die, type_name_const_str);
+                        type_sp = FindDefinitionTypeForDWARFDeclContext (die_decl_ctx);
+
+                        if (!type_sp && GetDebugMapSymfile ())
+                        {
+                            // We weren't able to find a full declaration in
+                            // this DWARF, see if we have a declaration anywhere    
+                            // else...
+                            type_sp = m_debug_map_symfile->FindDefinitionTypeForDWARFDeclContext (die_decl_ctx);
+                        }
+
+                        if (type_sp)
+                        {
+                            if (log)
+                            {
+                                GetObjectFile()->GetModule()->LogMessage (log,
+                                                                          "SymbolFileDWARF(%p) - 0x%8.8x: %s type \"%s\" is a forward declaration, complete type is 0x%8.8" PRIx64,
+                                                                          this,
+                                                                          die->GetOffset(), 
+                                                                          DW_TAG_value_to_name(tag),
+                                                                          type_name_cstr,
+                                                                          type_sp->GetID());
+                            }
+
+                            // We found a real definition for this type elsewhere
+                            // so lets use it and cache the fact that we found
+                            // a complete type for this die
+                            m_die_to_type[die] = type_sp.get();
+                            return type_sp;
+                        }
+                    }
+                    assert (tag_decl_kind != -1);
+                    bool clang_type_was_created = false;
+                    clang_type.SetClangType(ast.getASTContext(), m_forward_decl_die_to_clang_type.lookup (die));
+                    if (!clang_type)
+                    {
+                        const DWARFDebugInfoEntry *decl_ctx_die;
+                        
+                        clang::DeclContext *decl_ctx = GetClangDeclContextContainingDIE (dwarf_cu, die, &decl_ctx_die);
+                        if (accessibility == eAccessNone && decl_ctx)
+                        {
+                            // Check the decl context that contains this class/struct/union.
+                            // If it is a class we must give it an accessability.
+                            const clang::Decl::Kind containing_decl_kind = decl_ctx->getDeclKind();
+                            if (DeclKindIsCXXClass (containing_decl_kind))
+                                accessibility = default_accessibility;
+                        }
+
+                        ClangASTMetadata metadata;
+                        metadata.SetUserID(MakeUserID(die->GetOffset()));
+                        metadata.SetIsDynamicCXXType(ClassOrStructIsVirtual (dwarf_cu, die));
+
+                        if (type_name_cstr && strchr (type_name_cstr, '<'))
+                        {
+                            ClangASTContext::TemplateParameterInfos template_param_infos;
+                            if (ParseTemplateParameterInfos (dwarf_cu, die, template_param_infos))
+                            {
+                                clang::ClassTemplateDecl *class_template_decl = ParseClassTemplateDecl (decl_ctx,
+                                                                                                        accessibility,
+                                                                                                        type_name_cstr,
+                                                                                                        tag_decl_kind,
+                                                                                                        template_param_infos);
+                            
+                                clang::ClassTemplateSpecializationDecl *class_specialization_decl = ast.CreateClassTemplateSpecializationDecl (decl_ctx,
+                                                                                                                                               class_template_decl,
+                                                                                                                                               tag_decl_kind,
+                                                                                                                                               template_param_infos);
+                                clang_type = ast.CreateClassTemplateSpecializationType (class_specialization_decl);
+                                clang_type_was_created = true;
+                                
+                                GetClangASTContext().SetMetadata (class_template_decl, metadata);
+                                GetClangASTContext().SetMetadata (class_specialization_decl, metadata);
+                            }
+                        }
+
+                        if (!clang_type_was_created)
+                        {
+                            clang_type_was_created = true;
+                            clang_type = ast.CreateRecordType (decl_ctx, 
+                                                               accessibility, 
+                                                               type_name_cstr, 
+                                                               tag_decl_kind, 
+                                                               class_language,
+                                                               &metadata);
+                        }
+                    }
+
+                    // Store a forward declaration to this class type in case any 
+                    // parameters in any class methods need it for the clang 
+                    // types for function prototypes.
+                    LinkDeclContextToDIE(clang_type.GetDeclContextForType(), die);
+                    type_sp.reset (new Type (MakeUserID(die->GetOffset()), 
+                                             this, 
+                                             type_name_const_str, 
+                                             byte_size, 
+                                             NULL, 
+                                             LLDB_INVALID_UID, 
+                                             Type::eEncodingIsUID, 
+                                             &decl, 
+                                             clang_type, 
+                                             Type::eResolveStateForward));
+                    
+                    type_sp->SetIsCompleteObjCClass(is_complete_objc_class);
+
+
+                    // Add our type to the unique type map so we don't
+                    // end up creating many copies of the same type over
+                    // and over in the ASTContext for our module
+                    unique_ast_entry.m_type_sp = type_sp;
+                    unique_ast_entry.m_symfile = this;
+                    unique_ast_entry.m_cu = dwarf_cu;
+                    unique_ast_entry.m_die = die;
+                    unique_ast_entry.m_declaration = decl;
+                    unique_ast_entry.m_byte_size = byte_size;
+                    GetUniqueDWARFASTTypeMap().Insert (type_name_const_str, 
+                                                       unique_ast_entry);
+                    
+                    if (is_forward_declaration && die->HasChildren())
+                    {
+                        // Check to see if the DIE actually has a definition, some version of GCC will
+                        // emit DIEs with DW_AT_declaration set to true, but yet still have subprogram,
+                        // members, or inheritance, so we can't trust it
+                        const DWARFDebugInfoEntry *child_die = die->GetFirstChild();
+                        while (child_die)
+                        {
+                            switch (child_die->Tag())
+                            {
+                                case DW_TAG_inheritance:
+                                case DW_TAG_subprogram:
+                                case DW_TAG_member:
+                                case DW_TAG_APPLE_property:
+                                    child_die = NULL;
+                                    is_forward_declaration = false;
+                                    break;
+                                default:
+                                    child_die = child_die->GetSibling();
+                                    break;
+                            }
+                        }
+                    }
+
+                    if (!is_forward_declaration)
+                    {
+                        // Always start the definition for a class type so that
+                        // if the class has child classes or types that require
+                        // the class to be created for use as their decl contexts
+                        // the class will be ready to accept these child definitions.
+                        if (die->HasChildren() == false)
+                        {
+                            // No children for this struct/union/class, lets finish it
+                            clang_type.StartTagDeclarationDefinition ();
+                            clang_type.CompleteTagDeclarationDefinition ();
+                            
+                            if (tag == DW_TAG_structure_type) // this only applies in C
+                            {
+                                clang::RecordDecl *record_decl = clang_type.GetAsRecordDecl();
+                                
+                                if (record_decl)
+                                {
+                                    LayoutInfo layout_info;
+                                    
+                                    layout_info.alignment = 0;
+                                    layout_info.bit_size = 0;
+                                    
+                                    m_record_decl_to_layout_map.insert(std::make_pair(record_decl, layout_info));
+                                }
+                            }
+                        }
+                        else if (clang_type_was_created)
+                        {
+                            // Start the definition if the class is not objective C since
+                            // the underlying decls respond to isCompleteDefinition(). Objective
+                            // C decls dont' respond to isCompleteDefinition() so we can't
+                            // start the declaration definition right away. For C++ classs/union/structs
+                            // we want to start the definition in case the class is needed as the
+                            // declaration context for a contained class or type without the need
+                            // to complete that type..
+                            
+                            if (class_language != eLanguageTypeObjC &&
+                                class_language != eLanguageTypeObjC_plus_plus)
+                                clang_type.StartTagDeclarationDefinition ();
+
+                            // Leave this as a forward declaration until we need
+                            // to know the details of the type. lldb_private::Type
+                            // will automatically call the SymbolFile virtual function
+                            // "SymbolFileDWARF::ResolveClangOpaqueTypeDefinition(Type *)"
+                            // When the definition needs to be defined.
+                            m_forward_decl_die_to_clang_type[die] = clang_type.GetOpaqueQualType();
+                            m_forward_decl_clang_type_to_die[clang_type.RemoveFastQualifiers().GetOpaqueQualType()] = die;
+                            clang_type.SetHasExternalStorage (true);
+                        }
+                    }
+                    
+                }
+                break;
+
+            case DW_TAG_enumeration_type:
+                {
+                    // Set a bit that lets us know that we are currently parsing this
+                    m_die_to_type[die] = DIE_IS_BEING_PARSED;
+
+                    lldb::user_id_t encoding_uid = DW_INVALID_OFFSET;
+
+                    const size_t num_attributes = die->GetAttributes(this, dwarf_cu, NULL, attributes);
+                    if (num_attributes > 0)
+                    {
+                        uint32_t i;
+
+                        for (i=0; i<num_attributes; ++i)
+                        {
+                            attr = attributes.AttributeAtIndex(i);
+                            DWARFFormValue form_value;
+                            if (attributes.ExtractFormValueAtIndex(this, i, form_value))
+                            {
+                                switch (attr)
+                                {
+                                case DW_AT_decl_file:       decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
+                                case DW_AT_decl_line:       decl.SetLine(form_value.Unsigned()); break;
+                                case DW_AT_decl_column:     decl.SetColumn(form_value.Unsigned()); break;
+                                case DW_AT_name:
+                                    type_name_cstr = form_value.AsCString(&get_debug_str_data());
+                                    type_name_const_str.SetCString(type_name_cstr);
+                                    break;
+                                case DW_AT_type:            encoding_uid = form_value.Reference(dwarf_cu); break;
+                                case DW_AT_byte_size:       byte_size = form_value.Unsigned(); break;
+                                case DW_AT_accessibility:   break; //accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break;
+                                case DW_AT_declaration:     break; //is_forward_declaration = form_value.Boolean(); break;
+                                case DW_AT_allocated:
+                                case DW_AT_associated:
+                                case DW_AT_bit_stride:
+                                case DW_AT_byte_stride:
+                                case DW_AT_data_location:
+                                case DW_AT_description:
+                                case DW_AT_start_scope:
+                                case DW_AT_visibility:
+                                case DW_AT_specification:
+                                case DW_AT_abstract_origin:
+                                case DW_AT_sibling:
+                                    break;
+                                }
+                            }
+                        }
+
+                        DEBUG_PRINTF ("0x%8.8" PRIx64 ": %s (\"%s\")\n", MakeUserID(die->GetOffset()), DW_TAG_value_to_name(tag), type_name_cstr);
+
+                        ClangASTType enumerator_clang_type;
+                        clang_type.SetClangType (ast.getASTContext(), m_forward_decl_die_to_clang_type.lookup (die));
+                        if (!clang_type)
+                        {
+                            if (encoding_uid != DW_INVALID_OFFSET)
+                            {
+                                Type *enumerator_type = ResolveTypeUID(encoding_uid);
+                                if (enumerator_type)
+                                    enumerator_clang_type = enumerator_type->GetClangFullType();
+                            }
+                            
+                            if (!enumerator_clang_type)
+                                enumerator_clang_type = ast.GetBuiltinTypeForDWARFEncodingAndBitSize (NULL,
+                                                                                                      DW_ATE_signed,
+                                                                                                      byte_size * 8);
+                            
+                            clang_type = ast.CreateEnumerationType (type_name_cstr, 
+                                                                    GetClangDeclContextContainingDIE (dwarf_cu, die, NULL), 
+                                                                    decl,
+                                                                    enumerator_clang_type);
+                        }
+                        else
+                        {
+                            enumerator_clang_type = clang_type.GetEnumerationIntegerType ();
+                        }
+
+                        LinkDeclContextToDIE(clang_type.GetDeclContextForType(), die);
+                        
+                        type_sp.reset( new Type (MakeUserID(die->GetOffset()), 
+                                                 this, 
+                                                 type_name_const_str, 
+                                                 byte_size, 
+                                                 NULL, 
+                                                 encoding_uid, 
+                                                 Type::eEncodingIsUID,
+                                                 &decl, 
+                                                 clang_type, 
+                                                 Type::eResolveStateForward));
+
+                        clang_type.StartTagDeclarationDefinition ();
+                        if (die->HasChildren())
+                        {
+                            SymbolContext cu_sc(GetCompUnitForDWARFCompUnit(dwarf_cu));
+                            bool is_signed = false;
+                            enumerator_clang_type.IsIntegerType(is_signed);
+                            ParseChildEnumerators(cu_sc, clang_type, is_signed, type_sp->GetByteSize(), dwarf_cu, die);
+                        }
+                        clang_type.CompleteTagDeclarationDefinition ();
+                    }
+                }
+                break;
+
+            case DW_TAG_inlined_subroutine:
+            case DW_TAG_subprogram:
+            case DW_TAG_subroutine_type:
+                {
+                    // Set a bit that lets us know that we are currently parsing this
+                    m_die_to_type[die] = DIE_IS_BEING_PARSED;
+
+                    //const char *mangled = NULL;
+                    dw_offset_t type_die_offset = DW_INVALID_OFFSET;
+                    bool is_variadic = false;
+                    bool is_inline = false;
+                    bool is_static = false;
+                    bool is_virtual = false;
+                    bool is_explicit = false;
+                    bool is_artificial = false;
+                    dw_offset_t specification_die_offset = DW_INVALID_OFFSET;
+                    dw_offset_t abstract_origin_die_offset = DW_INVALID_OFFSET;
+                    dw_offset_t object_pointer_die_offset = DW_INVALID_OFFSET;
+
+                    unsigned type_quals = 0;
+                    clang::StorageClass storage = clang::SC_None;//, Extern, Static, PrivateExtern
+
+
+                    const size_t num_attributes = die->GetAttributes(this, dwarf_cu, NULL, attributes);
+                    if (num_attributes > 0)
+                    {
+                        uint32_t i;
+                        for (i=0; i<num_attributes; ++i)
+                        {
+                            attr = attributes.AttributeAtIndex(i);
+                            DWARFFormValue form_value;
+                            if (attributes.ExtractFormValueAtIndex(this, i, form_value))
+                            {
+                                switch (attr)
+                                {
+                                case DW_AT_decl_file:   decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
+                                case DW_AT_decl_line:   decl.SetLine(form_value.Unsigned()); break;
+                                case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
+                                case DW_AT_name:
+                                    type_name_cstr = form_value.AsCString(&get_debug_str_data());
+                                    type_name_const_str.SetCString(type_name_cstr);
+                                    break;
+
+                                case DW_AT_linkage_name:
+                                case DW_AT_MIPS_linkage_name:   break; // mangled = form_value.AsCString(&get_debug_str_data()); break;
+                                case DW_AT_type:                type_die_offset = form_value.Reference(dwarf_cu); break;
+                                case DW_AT_accessibility:       accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break;
+                                case DW_AT_declaration:         break; // is_forward_declaration = form_value.Boolean(); break;
+                                case DW_AT_inline:              is_inline = form_value.Boolean(); break;
+                                case DW_AT_virtuality:          is_virtual = form_value.Boolean();  break;
+                                case DW_AT_explicit:            is_explicit = form_value.Boolean();  break;
+                                case DW_AT_artificial:          is_artificial = form_value.Boolean();  break;
+                                        
+
+                                case DW_AT_external:
+                                    if (form_value.Unsigned())
+                                    {
+                                        if (storage == clang::SC_None)
+                                            storage = clang::SC_Extern;
+                                        else
+                                            storage = clang::SC_PrivateExtern;
+                                    }
+                                    break;
+
+                                case DW_AT_specification:
+                                    specification_die_offset = form_value.Reference(dwarf_cu);
+                                    break;
+
+                                case DW_AT_abstract_origin:
+                                    abstract_origin_die_offset = form_value.Reference(dwarf_cu);
+                                    break;
+
+                                case DW_AT_object_pointer:
+                                    object_pointer_die_offset = form_value.Reference(dwarf_cu);
+                                    break;
+
+                                case DW_AT_allocated:
+                                case DW_AT_associated:
+                                case DW_AT_address_class:
+                                case DW_AT_calling_convention:
+                                case DW_AT_data_location:
+                                case DW_AT_elemental:
+                                case DW_AT_entry_pc:
+                                case DW_AT_frame_base:
+                                case DW_AT_high_pc:
+                                case DW_AT_low_pc:
+                                case DW_AT_prototyped:
+                                case DW_AT_pure:
+                                case DW_AT_ranges:
+                                case DW_AT_recursive:
+                                case DW_AT_return_addr:
+                                case DW_AT_segment:
+                                case DW_AT_start_scope:
+                                case DW_AT_static_link:
+                                case DW_AT_trampoline:
+                                case DW_AT_visibility:
+                                case DW_AT_vtable_elem_location:
+                                case DW_AT_description:
+                                case DW_AT_sibling:
+                                    break;
+                                }
+                            }
+                        }
+                    }
+
+                    std::string object_pointer_name;
+                    if (object_pointer_die_offset != DW_INVALID_OFFSET)
+                    {
+                        // Get the name from the object pointer die
+                        StreamString s;
+                        if (DWARFDebugInfoEntry::GetName (this, dwarf_cu, object_pointer_die_offset, s))
+                        {
+                            object_pointer_name.assign(s.GetData());
+                        }
+                    }
+                    
+                    DEBUG_PRINTF ("0x%8.8" PRIx64 ": %s (\"%s\")\n", MakeUserID(die->GetOffset()), DW_TAG_value_to_name(tag), type_name_cstr);
+
+                    ClangASTType return_clang_type;
+                    Type *func_type = NULL;
+                    
+                    if (type_die_offset != DW_INVALID_OFFSET)
+                        func_type = ResolveTypeUID(type_die_offset);
+
+                    if (func_type)
+                        return_clang_type = func_type->GetClangForwardType();
+                    else
+                        return_clang_type = ast.GetBasicType(eBasicTypeVoid);
+
+
+                    std::vector<ClangASTType> function_param_types;
+                    std::vector<clang::ParmVarDecl*> function_param_decls;
+
+                    // Parse the function children for the parameters
+                    
+                    const DWARFDebugInfoEntry *decl_ctx_die = NULL;
+                    clang::DeclContext *containing_decl_ctx = GetClangDeclContextContainingDIE (dwarf_cu, die, &decl_ctx_die);
+                    const clang::Decl::Kind containing_decl_kind = containing_decl_ctx->getDeclKind();
+
+                    const bool is_cxx_method = DeclKindIsCXXClass (containing_decl_kind);
+                    // Start off static. This will be set to false in ParseChildParameters(...)
+                    // if we find a "this" paramters as the first parameter
+                    if (is_cxx_method)
+                        is_static = true;
+                    ClangASTContext::TemplateParameterInfos template_param_infos;
+
+                    if (die->HasChildren())
+                    {
+                        bool skip_artificial = true;
+                        ParseChildParameters (sc,
+                                              containing_decl_ctx,
+                                              dwarf_cu,
+                                              die,
+                                              skip_artificial,
+                                              is_static,
+                                              type_list,
+                                              function_param_types,
+                                              function_param_decls,
+                                              type_quals,
+                                              template_param_infos);
+                    }
+
+                    // clang_type will get the function prototype clang type after this call
+                    clang_type = ast.CreateFunctionType (return_clang_type, 
+                                                         function_param_types.data(),
+                                                         function_param_types.size(), 
+                                                         is_variadic, 
+                                                         type_quals);
+                    
+                    bool ignore_containing_context = false;
+                    
+                    if (type_name_cstr)
+                    {
+                        bool type_handled = false;
+                        if (tag == DW_TAG_subprogram)
+                        {
+                            ObjCLanguageRuntime::MethodName objc_method (type_name_cstr, true);
+                            if (objc_method.IsValid(true))
+                            {
+                                SymbolContext empty_sc;
+                                ClangASTType class_opaque_type;
+                                ConstString class_name(objc_method.GetClassName());
+                                if (class_name)
+                                {
+                                    TypeList types;
+                                    TypeSP complete_objc_class_type_sp (FindCompleteObjCDefinitionTypeForDIE (NULL, class_name, false));
+
+                                    if (complete_objc_class_type_sp)
+                                    {
+                                        ClangASTType type_clang_forward_type = complete_objc_class_type_sp->GetClangForwardType();
+                                        if (type_clang_forward_type.IsObjCObjectOrInterfaceType ())
+                                            class_opaque_type = type_clang_forward_type;
+                                    }
+                                }
+
+                                if (class_opaque_type)
+                                {
+                                    // If accessibility isn't set to anything valid, assume public for 
+                                    // now...
+                                    if (accessibility == eAccessNone)
+                                        accessibility = eAccessPublic;
+
+                                    clang::ObjCMethodDecl *objc_method_decl = class_opaque_type.AddMethodToObjCObjectType (type_name_cstr,
+                                                                                                                           clang_type,
+                                                                                                                           accessibility,
+                                                                                                                           is_artificial);
+                                    type_handled = objc_method_decl != NULL;
+                                    if (type_handled)
+                                    {
+                                        LinkDeclContextToDIE(ClangASTContext::GetAsDeclContext(objc_method_decl), die);
+                                        GetClangASTContext().SetMetadataAsUserID (objc_method_decl, MakeUserID(die->GetOffset()));
+                                    }
+                                    else
+                                    {
+                                        GetObjectFile()->GetModule()->ReportError ("{0x%8.8x}: invalid Objective-C method 0x%4.4x (%s), please file a bug and attach the file at the start of this error message",
+                                                                                   die->GetOffset(),
+                                                                                   tag,
+                                                                                   DW_TAG_value_to_name(tag));
+                                    }
+                                }
+                            }
+                            else if (is_cxx_method)
+                            {
+                                // Look at the parent of this DIE and see if is is
+                                // a class or struct and see if this is actually a
+                                // C++ method
+                                Type *class_type = ResolveType (dwarf_cu, decl_ctx_die);
+                                if (class_type)
+                                {
+                                    if (class_type->GetID() != MakeUserID(decl_ctx_die->GetOffset()))
+                                    {
+                                        // We uniqued the parent class of this function to another class
+                                        // so we now need to associate all dies under "decl_ctx_die" to
+                                        // DIEs in the DIE for "class_type"...
+                                        SymbolFileDWARF *class_symfile = NULL;
+                                        DWARFCompileUnitSP class_type_cu_sp;
+                                        const DWARFDebugInfoEntry *class_type_die = NULL;
+                                        
+                                        SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile();
+                                        if (debug_map_symfile)
+                                        {
+                                            class_symfile = debug_map_symfile->GetSymbolFileByOSOIndex(SymbolFileDWARFDebugMap::GetOSOIndexFromUserID(class_type->GetID()));
+                                            class_type_die = class_symfile->DebugInfo()->GetDIEPtr(class_type->GetID(), &class_type_cu_sp);
+                                        }
+                                        else
+                                        {
+                                            class_symfile = this;
+                                            class_type_die = DebugInfo()->GetDIEPtr(class_type->GetID(), &class_type_cu_sp);
+                                        }
+                                        if (class_type_die)
+                                        {
+                                            llvm::SmallVector<const DWARFDebugInfoEntry *, 0> failures;
+                                            
+                                            CopyUniqueClassMethodTypes (class_symfile,
+                                                                        class_type,
+                                                                        class_type_cu_sp.get(),
+                                                                        class_type_die,
+                                                                        dwarf_cu,
+                                                                        decl_ctx_die,
+                                                                        failures);
+                                            
+                                            // FIXME do something with these failures that's smarter than
+                                            // just dropping them on the ground.  Unfortunately classes don't
+                                            // like having stuff added to them after their definitions are
+                                            // complete...
+                                            
+                                            type_ptr = m_die_to_type[die];
+                                            if (type_ptr && type_ptr != DIE_IS_BEING_PARSED)
+                                            {
+                                                type_sp = type_ptr->shared_from_this();
+                                                break;
+                                            }
+                                        }
+                                    }
+                                    
+                                    if (specification_die_offset != DW_INVALID_OFFSET)
+                                    {
+                                        // We have a specification which we are going to base our function
+                                        // prototype off of, so we need this type to be completed so that the
+                                        // m_die_to_decl_ctx for the method in the specification has a valid
+                                        // clang decl context.
+                                        class_type->GetClangForwardType();
+                                        // If we have a specification, then the function type should have been
+                                        // made with the specification and not with this die.
+                                        DWARFCompileUnitSP spec_cu_sp;
+                                        const DWARFDebugInfoEntry* spec_die = DebugInfo()->GetDIEPtr(specification_die_offset, &spec_cu_sp);
+                                        clang::DeclContext *spec_clang_decl_ctx = GetClangDeclContextForDIE (sc, dwarf_cu, spec_die);
+                                        if (spec_clang_decl_ctx)
+                                        {
+                                            LinkDeclContextToDIE(spec_clang_decl_ctx, die);
+                                        }
+                                        else
+                                        {
+                                            GetObjectFile()->GetModule()->ReportWarning ("0x%8.8" PRIx64 ": DW_AT_specification(0x%8.8x) has no decl\n",
+                                                                                         MakeUserID(die->GetOffset()), 
+                                                                                         specification_die_offset);
+                                        }
+                                        type_handled = true;
+                                    }
+                                    else if (abstract_origin_die_offset != DW_INVALID_OFFSET)
+                                    {
+                                        // We have a specification which we are going to base our function
+                                        // prototype off of, so we need this type to be completed so that the
+                                        // m_die_to_decl_ctx for the method in the abstract origin has a valid
+                                        // clang decl context.
+                                        class_type->GetClangForwardType();
+
+                                        DWARFCompileUnitSP abs_cu_sp;
+                                        const DWARFDebugInfoEntry* abs_die = DebugInfo()->GetDIEPtr(abstract_origin_die_offset, &abs_cu_sp);
+                                        clang::DeclContext *abs_clang_decl_ctx = GetClangDeclContextForDIE (sc, dwarf_cu, abs_die);
+                                        if (abs_clang_decl_ctx)
+                                        {
+                                            LinkDeclContextToDIE (abs_clang_decl_ctx, die);
+                                        }
+                                        else
+                                        {
+                                            GetObjectFile()->GetModule()->ReportWarning ("0x%8.8" PRIx64 ": DW_AT_abstract_origin(0x%8.8x) has no decl\n",
+                                                                                         MakeUserID(die->GetOffset()), 
+                                                                                         abstract_origin_die_offset);
+                                        }
+                                        type_handled = true;
+                                    }
+                                    else
+                                    {
+                                        ClangASTType class_opaque_type = class_type->GetClangForwardType();
+                                        if (class_opaque_type.IsCXXClassType ())
+                                        {
+                                            if (class_opaque_type.IsBeingDefined ())
+                                            {
+                                                // Neither GCC 4.2 nor clang++ currently set a valid accessibility
+                                                // in the DWARF for C++ methods... Default to public for now...
+                                                if (accessibility == eAccessNone)
+                                                    accessibility = eAccessPublic;
+                                                
+                                                if (!is_static && !die->HasChildren())
+                                                {
+                                                    // We have a C++ member function with no children (this pointer!)
+                                                    // and clang will get mad if we try and make a function that isn't
+                                                    // well formed in the DWARF, so we will just skip it...
+                                                    type_handled = true;
+                                                }
+                                                else
+                                                {
+                                                    clang::CXXMethodDecl *cxx_method_decl;
+                                                    // REMOVE THE CRASH DESCRIPTION BELOW
+                                                    Host::SetCrashDescriptionWithFormat ("SymbolFileDWARF::ParseType() is adding a method %s to class %s in DIE 0x%8.8" PRIx64 " from %s",
+                                                                                         type_name_cstr, 
+                                                                                         class_type->GetName().GetCString(),
+                                                                                         MakeUserID(die->GetOffset()),
+                                                                                         m_obj_file->GetFileSpec().GetPath().c_str());
+
+                                                    const bool is_attr_used = false;
+                                                    
+                                                    cxx_method_decl = class_opaque_type.AddMethodToCXXRecordType (type_name_cstr,
+                                                                                                                  clang_type,
+                                                                                                                  accessibility,
+                                                                                                                  is_virtual,
+                                                                                                                  is_static,
+                                                                                                                  is_inline,
+                                                                                                                  is_explicit,
+                                                                                                                  is_attr_used,
+                                                                                                                  is_artificial);
+                                                    
+                                                    type_handled = cxx_method_decl != NULL;
+
+                                                    if (type_handled)
+                                                    {
+                                                        LinkDeclContextToDIE(ClangASTContext::GetAsDeclContext(cxx_method_decl), die);
+
+                                                        Host::SetCrashDescription (NULL);
+
+                                                        
+                                                        ClangASTMetadata metadata;
+                                                        metadata.SetUserID(MakeUserID(die->GetOffset()));
+                                                        
+                                                        if (!object_pointer_name.empty())
+                                                        {
+                                                            metadata.SetObjectPtrName(object_pointer_name.c_str());
+                                                            if (log)
+                                                                log->Printf ("Setting object pointer name: %s on method object %p.\n",
+                                                                             object_pointer_name.c_str(),
+                                                                             cxx_method_decl);
+                                                        }
+                                                        GetClangASTContext().SetMetadata (cxx_method_decl, metadata);
+                                                    }
+                                                    else
+                                                    {
+                                                        ignore_containing_context = true;
+                                                    }
+                                                }
+                                            }
+                                            else
+                                            {
+                                                // We were asked to parse the type for a method in a class, yet the
+                                                // class hasn't been asked to complete itself through the 
+                                                // clang::ExternalASTSource protocol, so we need to just have the
+                                                // class complete itself and do things the right way, then our 
+                                                // DIE should then have an entry in the m_die_to_type map. First 
+                                                // we need to modify the m_die_to_type so it doesn't think we are 
+                                                // trying to parse this DIE anymore...
+                                                m_die_to_type[die] = NULL;
+                                                
+                                                // Now we get the full type to force our class type to complete itself 
+                                                // using the clang::ExternalASTSource protocol which will parse all 
+                                                // base classes and all methods (including the method for this DIE).
+                                                class_type->GetClangFullType();
+
+                                                // The type for this DIE should have been filled in the function call above
+                                                type_ptr = m_die_to_type[die];
+                                                if (type_ptr && type_ptr != DIE_IS_BEING_PARSED)
+                                                {
+                                                    type_sp = type_ptr->shared_from_this();
+                                                    break;
+                                                }
+                                                
+                                                // FIXME This is fixing some even uglier behavior but we really need to
+                                                // uniq the methods of each class as well as the class itself.
+                                                // <rdar://problem/11240464>
+                                                type_handled = true;
+                                            }
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                            
+                        if (!type_handled)
+                        {
+                            // We just have a function that isn't part of a class
+                            clang::FunctionDecl *function_decl = ast.CreateFunctionDeclaration (ignore_containing_context ? GetClangASTContext().GetTranslationUnitDecl() : containing_decl_ctx,
+                                                                                                type_name_cstr, 
+                                                                                                clang_type, 
+                                                                                                storage, 
+                                                                                                is_inline);
+
+//                            if (template_param_infos.GetSize() > 0)
+//                            {
+//                                clang::FunctionTemplateDecl *func_template_decl = ast.CreateFunctionTemplateDecl (containing_decl_ctx,
+//                                                                                                                  function_decl,
+//                                                                                                                  type_name_cstr, 
+//                                                                                                                  template_param_infos);
+//                                
+//                                ast.CreateFunctionTemplateSpecializationInfo (function_decl,
+//                                                                              func_template_decl,
+//                                                                              template_param_infos);
+//                            }
+                            // Add the decl to our DIE to decl context map
+                            assert (function_decl);
+                            LinkDeclContextToDIE(function_decl, die);
+                            if (!function_param_decls.empty())
+                                ast.SetFunctionParameters (function_decl, 
+                                                           &function_param_decls.front(), 
+                                                           function_param_decls.size());
+                            
+                            ClangASTMetadata metadata;
+                            metadata.SetUserID(MakeUserID(die->GetOffset()));
+                            
+                            if (!object_pointer_name.empty())
+                            {
+                                metadata.SetObjectPtrName(object_pointer_name.c_str());
+                                if (log)
+                                    log->Printf ("Setting object pointer name: %s on function object %p.",
+                                                 object_pointer_name.c_str(),
+                                                function_decl);
+                            }
+                            GetClangASTContext().SetMetadata (function_decl, metadata);
+                        }
+                    }
+                    type_sp.reset( new Type (MakeUserID(die->GetOffset()), 
+                                             this, 
+                                             type_name_const_str, 
+                                             0, 
+                                             NULL, 
+                                             LLDB_INVALID_UID, 
+                                             Type::eEncodingIsUID, 
+                                             &decl, 
+                                             clang_type, 
+                                             Type::eResolveStateFull));                    
+                    assert(type_sp.get());
+                }
+                break;
+
+            case DW_TAG_array_type:
+                {
+                    // Set a bit that lets us know that we are currently parsing this
+                    m_die_to_type[die] = DIE_IS_BEING_PARSED;
+
+                    lldb::user_id_t type_die_offset = DW_INVALID_OFFSET;
+                    int64_t first_index = 0;
+                    uint32_t byte_stride = 0;
+                    uint32_t bit_stride = 0;
+                    bool is_vector = false;
+                    const size_t num_attributes = die->GetAttributes(this, dwarf_cu, NULL, attributes);
+
+                    if (num_attributes > 0)
+                    {
+                        uint32_t i;
+                        for (i=0; i<num_attributes; ++i)
+                        {
+                            attr = attributes.AttributeAtIndex(i);
+                            DWARFFormValue form_value;
+                            if (attributes.ExtractFormValueAtIndex(this, i, form_value))
+                            {
+                                switch (attr)
+                                {
+                                case DW_AT_decl_file:   decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
+                                case DW_AT_decl_line:   decl.SetLine(form_value.Unsigned()); break;
+                                case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
+                                case DW_AT_name:
+                                    type_name_cstr = form_value.AsCString(&get_debug_str_data());
+                                    type_name_const_str.SetCString(type_name_cstr);
+                                    break;
+
+                                case DW_AT_type:            type_die_offset = form_value.Reference(dwarf_cu); break;
+                                case DW_AT_byte_size:       break; // byte_size = form_value.Unsigned(); break;
+                                case DW_AT_byte_stride:     byte_stride = form_value.Unsigned(); break;
+                                case DW_AT_bit_stride:      bit_stride = form_value.Unsigned(); break;
+                                case DW_AT_GNU_vector:      is_vector = form_value.Boolean(); break;
+                                case DW_AT_accessibility:   break; // accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break;
+                                case DW_AT_declaration:     break; // is_forward_declaration = form_value.Boolean(); break;
+                                case DW_AT_allocated:
+                                case DW_AT_associated:
+                                case DW_AT_data_location:
+                                case DW_AT_description:
+                                case DW_AT_ordering:
+                                case DW_AT_start_scope:
+                                case DW_AT_visibility:
+                                case DW_AT_specification:
+                                case DW_AT_abstract_origin:
+                                case DW_AT_sibling:
+                                    break;
+                                }
+                            }
+                        }
+
+                        DEBUG_PRINTF ("0x%8.8" PRIx64 ": %s (\"%s\")\n", MakeUserID(die->GetOffset()), DW_TAG_value_to_name(tag), type_name_cstr);
+
+                        Type *element_type = ResolveTypeUID(type_die_offset);
+
+                        if (element_type)
+                        {
+                            std::vector<uint64_t> element_orders;
+                            ParseChildArrayInfo(sc, dwarf_cu, die, first_index, element_orders, byte_stride, bit_stride);
+                            if (byte_stride == 0 && bit_stride == 0)
+                                byte_stride = element_type->GetByteSize();
+                            ClangASTType array_element_type = element_type->GetClangForwardType();
+                            uint64_t array_element_bit_stride = byte_stride * 8 + bit_stride;
+                            uint64_t num_elements = 0;
+                            std::vector<uint64_t>::const_reverse_iterator pos;
+                            std::vector<uint64_t>::const_reverse_iterator end = element_orders.rend();
+                            for (pos = element_orders.rbegin(); pos != end; ++pos)
+                            {
+                                num_elements = *pos;
+                                clang_type = ast.CreateArrayType (array_element_type, 
+                                                                  num_elements,
+                                                                  is_vector);
+                                array_element_type = clang_type;
+                                array_element_bit_stride = num_elements ? array_element_bit_stride * num_elements : array_element_bit_stride;
+                            }
+                            ConstString empty_name;
+                            type_sp.reset( new Type (MakeUserID(die->GetOffset()), 
+                                                     this, 
+                                                     empty_name, 
+                                                     array_element_bit_stride / 8, 
+                                                     NULL, 
+                                                     type_die_offset, 
+                                                     Type::eEncodingIsUID, 
+                                                     &decl, 
+                                                     clang_type, 
+                                                     Type::eResolveStateFull));
+                            type_sp->SetEncodingType (element_type);
+                        }
+                    }
+                }
+                break;
+
+            case DW_TAG_ptr_to_member_type:
+                {
+                    dw_offset_t type_die_offset = DW_INVALID_OFFSET;
+                    dw_offset_t containing_type_die_offset = DW_INVALID_OFFSET;
+
+                    const size_t num_attributes = die->GetAttributes(this, dwarf_cu, NULL, attributes);
+                    
+                    if (num_attributes > 0) {
+                        uint32_t i;
+                        for (i=0; i<num_attributes; ++i)
+                        {
+                            attr = attributes.AttributeAtIndex(i);
+                            DWARFFormValue form_value;
+                            if (attributes.ExtractFormValueAtIndex(this, i, form_value))
+                            {
+                                switch (attr)
+                                {
+                                    case DW_AT_type:
+                                        type_die_offset = form_value.Reference(dwarf_cu); break;
+                                    case DW_AT_containing_type:
+                                        containing_type_die_offset = form_value.Reference(dwarf_cu); break;
+                                }
+                            }
+                        }
+                        
+                        Type *pointee_type = ResolveTypeUID(type_die_offset);
+                        Type *class_type = ResolveTypeUID(containing_type_die_offset);
+                        
+                        ClangASTType pointee_clang_type = pointee_type->GetClangForwardType();
+                        ClangASTType class_clang_type = class_type->GetClangLayoutType();
+
+                        clang_type = pointee_clang_type.CreateMemberPointerType(class_clang_type);
+
+                        byte_size = clang_type.GetByteSize();
+
+                        type_sp.reset( new Type (MakeUserID(die->GetOffset()), 
+                                                 this, 
+                                                 type_name_const_str, 
+                                                 byte_size, 
+                                                 NULL, 
+                                                 LLDB_INVALID_UID, 
+                                                 Type::eEncodingIsUID, 
+                                                 NULL, 
+                                                 clang_type, 
+                                                 Type::eResolveStateForward));
+                    }
+                                            
+                    break;
+                }
+            default:
+                GetObjectFile()->GetModule()->ReportError ("{0x%8.8x}: unhandled type tag 0x%4.4x (%s), please file a bug and attach the file at the start of this error message",
+                                                           die->GetOffset(),
+                                                           tag,
+                                                           DW_TAG_value_to_name(tag));
+                break;
+            }
+
+            if (type_sp.get())
+            {
+                const DWARFDebugInfoEntry *sc_parent_die = GetParentSymbolContextDIE(die);
+                dw_tag_t sc_parent_tag = sc_parent_die ? sc_parent_die->Tag() : 0;
+
+                SymbolContextScope * symbol_context_scope = NULL;
+                if (sc_parent_tag == DW_TAG_compile_unit)
+                {
+                    symbol_context_scope = sc.comp_unit;
+                }
+                else if (sc.function != NULL)
+                {
+                    symbol_context_scope = sc.function->GetBlock(true).FindBlockByID(MakeUserID(sc_parent_die->GetOffset()));
+                    if (symbol_context_scope == NULL)
+                        symbol_context_scope = sc.function;
+                }
+
+                if (symbol_context_scope != NULL)
+                {
+                    type_sp->SetSymbolContextScope(symbol_context_scope);
+                }
+
+                // We are ready to put this type into the uniqued list up at the module level
+                type_list->Insert (type_sp);
+
+                m_die_to_type[die] = type_sp.get();
+            }
+        }
+        else if (type_ptr != DIE_IS_BEING_PARSED)
+        {
+            type_sp = type_ptr->shared_from_this();
+        }
+    }
+    return type_sp;
+}
+
+size_t
+SymbolFileDWARF::ParseTypes
+(
+    const SymbolContext& sc, 
+    DWARFCompileUnit* dwarf_cu, 
+    const DWARFDebugInfoEntry *die, 
+    bool parse_siblings, 
+    bool parse_children
+)
+{
+    size_t types_added = 0;
+    while (die != NULL)
+    {
+        bool type_is_new = false;
+        if (ParseType(sc, dwarf_cu, die, &type_is_new).get())
+        {
+            if (type_is_new)
+                ++types_added;
+        }
+
+        if (parse_children && die->HasChildren())
+        {
+            if (die->Tag() == DW_TAG_subprogram)
+            {
+                SymbolContext child_sc(sc);
+                child_sc.function = sc.comp_unit->FindFunctionByUID(MakeUserID(die->GetOffset())).get();
+                types_added += ParseTypes(child_sc, dwarf_cu, die->GetFirstChild(), true, true);
+            }
+            else
+                types_added += ParseTypes(sc, dwarf_cu, die->GetFirstChild(), true, true);
+        }
+
+        if (parse_siblings)
+            die = die->GetSibling();
+        else
+            die = NULL;
+    }
+    return types_added;
+}
+
+
+size_t
+SymbolFileDWARF::ParseFunctionBlocks (const SymbolContext &sc)
+{
+    assert(sc.comp_unit && sc.function);
+    size_t functions_added = 0;
+    DWARFCompileUnit* dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
+    if (dwarf_cu)
+    {
+        dw_offset_t function_die_offset = sc.function->GetID();
+        const DWARFDebugInfoEntry *function_die = dwarf_cu->GetDIEPtr(function_die_offset);
+        if (function_die)
+        {
+            ParseFunctionBlocks(sc, &sc.function->GetBlock (false), dwarf_cu, function_die, LLDB_INVALID_ADDRESS, 0);
+        }
+    }
+
+    return functions_added;
+}
+
+
+size_t
+SymbolFileDWARF::ParseTypes (const SymbolContext &sc)
+{
+    // At least a compile unit must be valid
+    assert(sc.comp_unit);
+    size_t types_added = 0;
+    DWARFCompileUnit* dwarf_cu = GetDWARFCompileUnit(sc.comp_unit);
+    if (dwarf_cu)
+    {
+        if (sc.function)
+        {
+            dw_offset_t function_die_offset = sc.function->GetID();
+            const DWARFDebugInfoEntry *func_die = dwarf_cu->GetDIEPtr(function_die_offset);
+            if (func_die && func_die->HasChildren())
+            {
+                types_added = ParseTypes(sc, dwarf_cu, func_die->GetFirstChild(), true, true);
+            }
+        }
+        else
+        {
+            const DWARFDebugInfoEntry *dwarf_cu_die = dwarf_cu->DIE();
+            if (dwarf_cu_die && dwarf_cu_die->HasChildren())
+            {
+                types_added = ParseTypes(sc, dwarf_cu, dwarf_cu_die->GetFirstChild(), true, true);
+            }
+        }
+    }
+
+    return types_added;
+}
+
+size_t
+SymbolFileDWARF::ParseVariablesForContext (const SymbolContext& sc)
+{
+    if (sc.comp_unit != NULL)
+    {
+        DWARFDebugInfo* info = DebugInfo();
+        if (info == NULL)
+            return 0;
+        
+        if (sc.function)
+        {
+            DWARFCompileUnit* dwarf_cu = info->GetCompileUnitContainingDIE(sc.function->GetID()).get();
+            
+            if (dwarf_cu == NULL)
+                return 0;
+            
+            const DWARFDebugInfoEntry *function_die = dwarf_cu->GetDIEPtr(sc.function->GetID());
+            
+            dw_addr_t func_lo_pc = function_die->GetAttributeValueAsUnsigned (this, dwarf_cu, DW_AT_low_pc, LLDB_INVALID_ADDRESS);
+            if (func_lo_pc != LLDB_INVALID_ADDRESS)
+            {
+                const size_t num_variables = ParseVariables(sc, dwarf_cu, func_lo_pc, function_die->GetFirstChild(), true, true);
+            
+                // Let all blocks know they have parse all their variables
+                sc.function->GetBlock (false).SetDidParseVariables (true, true);
+                return num_variables;
+            }
+        }
+        else if (sc.comp_unit)
+        {
+            DWARFCompileUnit* dwarf_cu = info->GetCompileUnit(sc.comp_unit->GetID()).get();
+
+            if (dwarf_cu == NULL)
+                return 0;
+
+            uint32_t vars_added = 0;
+            VariableListSP variables (sc.comp_unit->GetVariableList(false));
+            
+            if (variables.get() == NULL)
+            {
+                variables.reset(new VariableList());
+                sc.comp_unit->SetVariableList(variables);
+
+                DWARFCompileUnit* match_dwarf_cu = NULL;
+                const DWARFDebugInfoEntry* die = NULL;
+                DIEArray die_offsets;
+                if (m_using_apple_tables)
+                {
+                    if (m_apple_names_ap.get())
+                    {
+                        DWARFMappedHash::DIEInfoArray hash_data_array;
+                        if (m_apple_names_ap->AppendAllDIEsInRange (dwarf_cu->GetOffset(), 
+                                                                    dwarf_cu->GetNextCompileUnitOffset(), 
+                                                                    hash_data_array))
+                        {
+                            DWARFMappedHash::ExtractDIEArray (hash_data_array, die_offsets);
+                        }
+                    }
+                }
+                else
+                {
+                    // Index if we already haven't to make sure the compile units
+                    // get indexed and make their global DIE index list
+                    if (!m_indexed)
+                        Index ();
+
+                    m_global_index.FindAllEntriesForCompileUnit (dwarf_cu->GetOffset(), 
+                                                                 dwarf_cu->GetNextCompileUnitOffset(), 
+                                                                 die_offsets);
+                }
+
+                const size_t num_matches = die_offsets.size();
+                if (num_matches)
+                {
+                    DWARFDebugInfo* debug_info = DebugInfo();
+                    for (size_t i=0; i<num_matches; ++i)
+                    {
+                        const dw_offset_t die_offset = die_offsets[i];
+                        die = debug_info->GetDIEPtrWithCompileUnitHint (die_offset, &match_dwarf_cu);
+                        if (die)
+                        {
+                            VariableSP var_sp (ParseVariableDIE(sc, dwarf_cu, die, LLDB_INVALID_ADDRESS));
+                            if (var_sp)
+                            {
+                                variables->AddVariableIfUnique (var_sp);
+                                ++vars_added;
+                            }
+                        }
+                        else
+                        {
+                            if (m_using_apple_tables)
+                            {
+                                GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_names accelerator table had bad die 0x%8.8x)\n", die_offset);
+                            }
+                        }            
+
+                    }
+                }
+            }
+            return vars_added;
+        }
+    }
+    return 0;
+}
+
+
+VariableSP
+SymbolFileDWARF::ParseVariableDIE
+(
+    const SymbolContext& sc,
+    DWARFCompileUnit* dwarf_cu,
+    const DWARFDebugInfoEntry *die,
+    const lldb::addr_t func_low_pc
+)
+{
+
+    VariableSP var_sp (m_die_to_variable_sp[die]);
+    if (var_sp)
+        return var_sp;  // Already been parsed!
+    
+    const dw_tag_t tag = die->Tag();
+    
+    if ((tag == DW_TAG_variable) ||
+        (tag == DW_TAG_constant) ||
+        (tag == DW_TAG_formal_parameter && sc.function))
+    {
+        DWARFDebugInfoEntry::Attributes attributes;
+        const size_t num_attributes = die->GetAttributes(this, dwarf_cu, NULL, attributes);
+        if (num_attributes > 0)
+        {
+            const char *name = NULL;
+            const char *mangled = NULL;
+            Declaration decl;
+            uint32_t i;
+            lldb::user_id_t type_uid = LLDB_INVALID_UID;
+            DWARFExpression location;
+            bool is_external = false;
+            bool is_artificial = false;
+            bool location_is_const_value_data = false;
+            bool has_explicit_location = false;
+            //AccessType accessibility = eAccessNone;
+
+            for (i=0; i<num_attributes; ++i)
+            {
+                dw_attr_t attr = attributes.AttributeAtIndex(i);
+                DWARFFormValue form_value;
+                if (attributes.ExtractFormValueAtIndex(this, i, form_value))
+                {
+                    switch (attr)
+                    {
+                    case DW_AT_decl_file:   decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(form_value.Unsigned())); break;
+                    case DW_AT_decl_line:   decl.SetLine(form_value.Unsigned()); break;
+                    case DW_AT_decl_column: decl.SetColumn(form_value.Unsigned()); break;
+                    case DW_AT_name:        name = form_value.AsCString(&get_debug_str_data()); break;
+                    case DW_AT_linkage_name:
+                    case DW_AT_MIPS_linkage_name: mangled = form_value.AsCString(&get_debug_str_data()); break;
+                    case DW_AT_type:        type_uid = form_value.Reference(dwarf_cu); break;
+                    case DW_AT_external:    is_external = form_value.Boolean(); break;
+                    case DW_AT_const_value:
+                        // If we have already found a DW_AT_location attribute, ignore this attribute.
+                        if (!has_explicit_location)
+                        {
+                            location_is_const_value_data = true;
+                            // The constant value will be either a block, a data value or a string.
+                            const DataExtractor& debug_info_data = get_debug_info_data();
+                            if (DWARFFormValue::IsBlockForm(form_value.Form()))
+                            {
+                                // Retrieve the value as a block expression.
+                                uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart();
+                                uint32_t block_length = form_value.Unsigned();
+                                location.CopyOpcodeData(debug_info_data, block_offset, block_length);
+                            }
+                            else if (DWARFFormValue::IsDataForm(form_value.Form()))
+                            {
+                                // Retrieve the value as a data expression.
+                                const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize());
+                                uint32_t data_offset = attributes.DIEOffsetAtIndex(i);
+                                uint32_t data_length = fixed_form_sizes[form_value.Form()];
+                                location.CopyOpcodeData(debug_info_data, data_offset, data_length);
+                            }
+                            else
+                            {
+                                // Retrieve the value as a string expression.
+                                if (form_value.Form() == DW_FORM_strp)
+                                {
+                                    const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize());
+                                    uint32_t data_offset = attributes.DIEOffsetAtIndex(i);
+                                    uint32_t data_length = fixed_form_sizes[form_value.Form()];
+                                    location.CopyOpcodeData(debug_info_data, data_offset, data_length);
+                                }
+                                else
+                                {
+                                    const char *str = form_value.AsCString(&debug_info_data);
+                                    uint32_t string_offset = str - (const char *)debug_info_data.GetDataStart();
+                                    uint32_t string_length = strlen(str) + 1;
+                                    location.CopyOpcodeData(debug_info_data, string_offset, string_length);
+                                }
+                            }
+                        }
+                        break;
+                    case DW_AT_location:
+                        {
+                            location_is_const_value_data = false;
+                            has_explicit_location = true;
+                            if (form_value.BlockData())
+                            {
+                                const DataExtractor& debug_info_data = get_debug_info_data();
+
+                                uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart();
+                                uint32_t block_length = form_value.Unsigned();
+                                location.CopyOpcodeData(get_debug_info_data(), block_offset, block_length);
+                            }
+                            else
+                            {
+                                const DataExtractor&    debug_loc_data = get_debug_loc_data();
+                                const dw_offset_t debug_loc_offset = form_value.Unsigned();
+
+                                size_t loc_list_length = DWARFLocationList::Size(debug_loc_data, debug_loc_offset);
+                                if (loc_list_length > 0)
+                                {
+                                    location.CopyOpcodeData(debug_loc_data, debug_loc_offset, loc_list_length);
+                                    assert (func_low_pc != LLDB_INVALID_ADDRESS);
+                                    location.SetLocationListSlide (func_low_pc - dwarf_cu->GetBaseAddress());
+                                }
+                            }
+                        }
+                        break;
+
+                    case DW_AT_artificial:      is_artificial = form_value.Boolean(); break;
+                    case DW_AT_accessibility:   break; //accessibility = DW_ACCESS_to_AccessType(form_value.Unsigned()); break;
+                    case DW_AT_declaration:
+                    case DW_AT_description:
+                    case DW_AT_endianity:
+                    case DW_AT_segment:
+                    case DW_AT_start_scope:
+                    case DW_AT_visibility:
+                    default:
+                    case DW_AT_abstract_origin:
+                    case DW_AT_sibling:
+                    case DW_AT_specification:
+                        break;
+                    }
+                }
+            }
+
+            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;
+
+            // 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)
+                {
+                    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());
+                    }
+                }
+
+                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)
+                    {
+                        // 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)
+                            {
+                                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)
+                                    {
+                                        if (exe_symbol->ValueIsAddress())
+                                        {
+                                            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))
+                                                {
+                                                    linked_oso_file_addr = true;
+                                                    symbol_context_scope = exe_symbol;
+                                                }
+                                            }
+                                        }
+                                    }
+                                }
+                            }
+                        }
+
+                        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)
+                            {
+                                // 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;
+                }
+            }
+
+            if (symbol_context_scope == NULL)
+            {
+                switch (parent_tag)
+                {
+                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;
+                }
+            }
+
+            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
+        // (missing location due to optimization, etc)) so we don't re-parse
+        // this DIE over and over later...
+        m_die_to_variable_sp[die] = var_sp;
+    }
+    return var_sp;
+}
+
+
+const DWARFDebugInfoEntry *
+SymbolFileDWARF::FindBlockContainingSpecification (dw_offset_t func_die_offset, 
+                                                   dw_offset_t spec_block_die_offset,
+                                                   DWARFCompileUnit **result_die_cu_handle)
+{
+    // Give the concrete function die specified by "func_die_offset", find the 
+    // concrete block whose DW_AT_specification or DW_AT_abstract_origin points
+    // to "spec_block_die_offset"
+    DWARFDebugInfo* info = DebugInfo();
+
+    const DWARFDebugInfoEntry *die = info->GetDIEPtrWithCompileUnitHint(func_die_offset, result_die_cu_handle);
+    if (die)
+    {
+        assert (*result_die_cu_handle);
+        return FindBlockContainingSpecification (*result_die_cu_handle, die, spec_block_die_offset, result_die_cu_handle);
+    }
+    return NULL;
+}
+
+
+const DWARFDebugInfoEntry *
+SymbolFileDWARF::FindBlockContainingSpecification(DWARFCompileUnit* dwarf_cu,
+                                                  const DWARFDebugInfoEntry *die,
+                                                  dw_offset_t spec_block_die_offset,
+                                                  DWARFCompileUnit **result_die_cu_handle)
+{
+    if (die)
+    {
+        switch (die->Tag())
+        {
+        case DW_TAG_subprogram:
+        case DW_TAG_inlined_subroutine:
+        case DW_TAG_lexical_block:
+            {
+                if (die->GetAttributeValueAsReference (this, dwarf_cu, DW_AT_specification, DW_INVALID_OFFSET) == spec_block_die_offset)
+                {
+                    *result_die_cu_handle = dwarf_cu;
+                    return die;
+                }
+
+                if (die->GetAttributeValueAsReference (this, dwarf_cu, DW_AT_abstract_origin, DW_INVALID_OFFSET) == spec_block_die_offset)
+                {
+                    *result_die_cu_handle = dwarf_cu;
+                    return die;
+                }
+            }
+            break;
+        }
+
+        // Give the concrete function die specified by "func_die_offset", find the 
+        // concrete block whose DW_AT_specification or DW_AT_abstract_origin points
+        // to "spec_block_die_offset"
+        for (const DWARFDebugInfoEntry *child_die = die->GetFirstChild(); child_die != NULL; child_die = child_die->GetSibling())
+        {
+            const DWARFDebugInfoEntry *result_die = FindBlockContainingSpecification (dwarf_cu,
+                                                                                      child_die,
+                                                                                      spec_block_die_offset,
+                                                                                      result_die_cu_handle);
+            if (result_die)
+                return result_die;
+        }
+    }
+    
+    *result_die_cu_handle = NULL;
+    return NULL;
+}
+
+size_t
+SymbolFileDWARF::ParseVariables
+(
+    const SymbolContext& sc,
+    DWARFCompileUnit* dwarf_cu,
+    const lldb::addr_t func_low_pc,
+    const DWARFDebugInfoEntry *orig_die,
+    bool parse_siblings,
+    bool parse_children,
+    VariableList* cc_variable_list
+)
+{
+    if (orig_die == NULL)
+        return 0;
+
+    VariableListSP variable_list_sp;
+
+    size_t vars_added = 0;
+    const DWARFDebugInfoEntry *die = orig_die;
+    while (die != NULL)
+    {
+        dw_tag_t tag = die->Tag();
+
+        // Check to see if we have already parsed this variable or constant?
+        if (m_die_to_variable_sp[die])
+        {
+            if (cc_variable_list)
+                cc_variable_list->AddVariableIfUnique (m_die_to_variable_sp[die]);
+        }
+        else
+        {
+            // We haven't already parsed it, lets do that now.
+            if ((tag == DW_TAG_variable) ||
+                (tag == DW_TAG_constant) ||
+                (tag == DW_TAG_formal_parameter && sc.function))
+            {
+                if (variable_list_sp.get() == NULL)
+                {
+                    const DWARFDebugInfoEntry *sc_parent_die = GetParentSymbolContextDIE(orig_die);
+                    dw_tag_t parent_tag = sc_parent_die ? sc_parent_die->Tag() : 0;
+                    switch (parent_tag)
+                    {
+                        case DW_TAG_compile_unit:
+                            if (sc.comp_unit != NULL)
+                            {
+                                variable_list_sp = sc.comp_unit->GetVariableList(false);
+                                if (variable_list_sp.get() == NULL)
+                                {
+                                    variable_list_sp.reset(new VariableList());
+                                    sc.comp_unit->SetVariableList(variable_list_sp);
+                                }
+                            }
+                            else
+                            {
+                                GetObjectFile()->GetModule()->ReportError ("parent 0x%8.8" PRIx64 " %s with no valid compile unit in symbol context for 0x%8.8" PRIx64 " %s.\n",
+                                                                           MakeUserID(sc_parent_die->GetOffset()),
+                                                                           DW_TAG_value_to_name (parent_tag),
+                                                                           MakeUserID(orig_die->GetOffset()),
+                                                                           DW_TAG_value_to_name (orig_die->Tag()));
+                            }
+                            break;
+                            
+                        case DW_TAG_subprogram:
+                        case DW_TAG_inlined_subroutine:
+                        case DW_TAG_lexical_block:
+                            if (sc.function != NULL)
+                            {
+                                // Check to see if we already have parsed the variables for the given scope
+                                
+                                Block *block = sc.function->GetBlock(true).FindBlockByID(MakeUserID(sc_parent_die->GetOffset()));
+                                if (block == NULL)
+                                {
+                                    // This must be a specification or abstract origin with 
+                                    // a concrete block couterpart in the current function. We need
+                                    // to find the concrete block so we can correctly add the 
+                                    // variable to it
+                                    DWARFCompileUnit *concrete_block_die_cu = dwarf_cu;
+                                    const DWARFDebugInfoEntry *concrete_block_die = FindBlockContainingSpecification (sc.function->GetID(), 
+                                                                                                                      sc_parent_die->GetOffset(), 
+                                                                                                                      &concrete_block_die_cu);
+                                    if (concrete_block_die)
+                                        block = sc.function->GetBlock(true).FindBlockByID(MakeUserID(concrete_block_die->GetOffset()));
+                                }
+                                
+                                if (block != NULL)
+                                {
+                                    const bool can_create = false;
+                                    variable_list_sp = block->GetBlockVariableList (can_create);
+                                    if (variable_list_sp.get() == NULL)
+                                    {
+                                        variable_list_sp.reset(new VariableList());
+                                        block->SetVariableList(variable_list_sp);
+                                    }
+                                }
+                            }
+                            break;
+                            
+                        default:
+                             GetObjectFile()->GetModule()->ReportError ("didn't find appropriate parent DIE for variable list for 0x%8.8" PRIx64 " %s.\n",
+                                                                        MakeUserID(orig_die->GetOffset()),
+                                                                        DW_TAG_value_to_name (orig_die->Tag()));
+                            break;
+                    }
+                }
+                
+                if (variable_list_sp)
+                {
+                    VariableSP var_sp (ParseVariableDIE(sc, dwarf_cu, die, func_low_pc));
+                    if (var_sp)
+                    {
+                        variable_list_sp->AddVariableIfUnique (var_sp);
+                        if (cc_variable_list)
+                            cc_variable_list->AddVariableIfUnique (var_sp);
+                        ++vars_added;
+                    }
+                }
+            }
+        }
+
+        bool skip_children = (sc.function == NULL && tag == DW_TAG_subprogram);
+
+        if (!skip_children && parse_children && die->HasChildren())
+        {
+            vars_added += ParseVariables(sc, dwarf_cu, func_low_pc, die->GetFirstChild(), true, true, cc_variable_list);
+        }
+
+        if (parse_siblings)
+            die = die->GetSibling();
+        else
+            die = NULL;
+    }
+    return vars_added;
+}
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+ConstString
+SymbolFileDWARF::GetPluginName()
+{
+    return GetPluginNameStatic();
+}
+
+uint32_t
+SymbolFileDWARF::GetPluginVersion()
+{
+    return 1;
+}
+
+void
+SymbolFileDWARF::CompleteTagDecl (void *baton, clang::TagDecl *decl)
+{
+    SymbolFileDWARF *symbol_file_dwarf = (SymbolFileDWARF *)baton;
+    ClangASTType clang_type = symbol_file_dwarf->GetClangASTContext().GetTypeForDecl (decl);
+    if (clang_type)
+        symbol_file_dwarf->ResolveClangOpaqueTypeDefinition (clang_type);
+}
+
+void
+SymbolFileDWARF::CompleteObjCInterfaceDecl (void *baton, clang::ObjCInterfaceDecl *decl)
+{
+    SymbolFileDWARF *symbol_file_dwarf = (SymbolFileDWARF *)baton;
+    ClangASTType clang_type = symbol_file_dwarf->GetClangASTContext().GetTypeForDecl (decl);
+    if (clang_type)
+        symbol_file_dwarf->ResolveClangOpaqueTypeDefinition (clang_type);
+}
+
+void
+SymbolFileDWARF::DumpIndexes ()
+{
+    StreamFile s(stdout, false);
+    
+    s.Printf ("DWARF index for (%s) '%s':",
+              GetObjectFile()->GetModule()->GetArchitecture().GetArchitectureName(),
+              GetObjectFile()->GetFileSpec().GetPath().c_str());
+    s.Printf("\nFunction basenames:\n");    m_function_basename_index.Dump (&s);
+    s.Printf("\nFunction fullnames:\n");    m_function_fullname_index.Dump (&s);
+    s.Printf("\nFunction methods:\n");      m_function_method_index.Dump (&s);
+    s.Printf("\nFunction selectors:\n");    m_function_selector_index.Dump (&s);
+    s.Printf("\nObjective C class selectors:\n");    m_objc_class_selectors_index.Dump (&s);
+    s.Printf("\nGlobals and statics:\n");   m_global_index.Dump (&s); 
+    s.Printf("\nTypes:\n");                 m_type_index.Dump (&s);
+    s.Printf("\nNamepaces:\n");             m_namespace_index.Dump (&s);
+}
+
+void
+SymbolFileDWARF::SearchDeclContext (const clang::DeclContext *decl_context, 
+                                    const char *name, 
+                                    llvm::SmallVectorImpl <clang::NamedDecl *> *results)
+{    
+    DeclContextToDIEMap::iterator iter = m_decl_ctx_to_die.find(decl_context);
+    
+    if (iter == m_decl_ctx_to_die.end())
+        return;
+    
+    for (DIEPointerSet::iterator pos = iter->second.begin(), end = iter->second.end(); pos != end; ++pos)
+    {
+        const DWARFDebugInfoEntry *context_die = *pos;
+    
+        if (!results)
+            return;
+        
+        DWARFDebugInfo* info = DebugInfo();
+        
+        DIEArray die_offsets;
+        
+        DWARFCompileUnit* dwarf_cu = NULL;
+        const DWARFDebugInfoEntry* die = NULL;
+        
+        if (m_using_apple_tables)
+        {
+            if (m_apple_types_ap.get())
+                m_apple_types_ap->FindByName (name, die_offsets);
+        }
+        else
+        {
+            if (!m_indexed)
+                Index ();
+            
+            m_type_index.Find (ConstString(name), die_offsets);
+        }
+        
+        const size_t num_matches = die_offsets.size();
+        
+        if (num_matches)
+        {
+            for (size_t i = 0; i < num_matches; ++i)
+            {
+                const dw_offset_t die_offset = die_offsets[i];
+                die = info->GetDIEPtrWithCompileUnitHint (die_offset, &dwarf_cu);
+
+                if (die->GetParent() != context_die)
+                    continue;
+                
+                Type *matching_type = ResolveType (dwarf_cu, die);
+                
+                clang::QualType qual_type = matching_type->GetClangForwardType().GetQualType();
+                
+                if (const clang::TagType *tag_type = llvm::dyn_cast<clang::TagType>(qual_type.getTypePtr()))
+                {
+                    clang::TagDecl *tag_decl = tag_type->getDecl();
+                    results->push_back(tag_decl);
+                }
+                else if (const clang::TypedefType *typedef_type = llvm::dyn_cast<clang::TypedefType>(qual_type.getTypePtr()))
+                {
+                    clang::TypedefNameDecl *typedef_decl = typedef_type->getDecl();
+                    results->push_back(typedef_decl); 
+                }
+            }
+        }
+    }
+}
+
+void
+SymbolFileDWARF::FindExternalVisibleDeclsByName (void *baton,
+                                                 const clang::DeclContext *decl_context,
+                                                 clang::DeclarationName decl_name,
+                                                 llvm::SmallVectorImpl <clang::NamedDecl *> *results)
+{
+    
+    switch (decl_context->getDeclKind())
+    {
+    case clang::Decl::Namespace:
+    case clang::Decl::TranslationUnit:
+        {
+            SymbolFileDWARF *symbol_file_dwarf = (SymbolFileDWARF *)baton;
+            symbol_file_dwarf->SearchDeclContext (decl_context, decl_name.getAsString().c_str(), results);
+        }
+        break;
+    default:
+        break;
+    }
+}
+
+bool 
+SymbolFileDWARF::LayoutRecordType (void *baton, 
+                                   const clang::RecordDecl *record_decl,
+                                   uint64_t &size, 
+                                   uint64_t &alignment,
+                                   llvm::DenseMap <const clang::FieldDecl *, uint64_t> &field_offsets,
+                                   llvm::DenseMap <const clang::CXXRecordDecl *, clang::CharUnits> &base_offsets,
+                                   llvm::DenseMap <const clang::CXXRecordDecl *, clang::CharUnits> &vbase_offsets)
+{
+    SymbolFileDWARF *symbol_file_dwarf = (SymbolFileDWARF *)baton;
+    return symbol_file_dwarf->LayoutRecordType (record_decl, size, alignment, field_offsets, base_offsets, vbase_offsets);
+}
+
+
+bool 
+SymbolFileDWARF::LayoutRecordType (const clang::RecordDecl *record_decl,
+                                   uint64_t &bit_size, 
+                                   uint64_t &alignment,
+                                   llvm::DenseMap <const clang::FieldDecl *, uint64_t> &field_offsets,
+                                   llvm::DenseMap <const clang::CXXRecordDecl *, clang::CharUnits> &base_offsets,
+                                   llvm::DenseMap <const clang::CXXRecordDecl *, clang::CharUnits> &vbase_offsets)
+{
+    Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO));
+    RecordDeclToLayoutMap::iterator pos = m_record_decl_to_layout_map.find (record_decl);
+    bool success = false;
+    base_offsets.clear();
+    vbase_offsets.clear();
+    if (pos != m_record_decl_to_layout_map.end())
+    {
+        bit_size = pos->second.bit_size;
+        alignment = pos->second.alignment;
+        field_offsets.swap(pos->second.field_offsets);
+        base_offsets.swap (pos->second.base_offsets);
+        vbase_offsets.swap (pos->second.vbase_offsets);
+        m_record_decl_to_layout_map.erase(pos);
+        success = true;
+    }
+    else
+    {
+        bit_size = 0;
+        alignment = 0;
+        field_offsets.clear();
+    }
+    
+    if (log)
+        GetObjectFile()->GetModule()->LogMessage (log, 
+                                                  "SymbolFileDWARF::LayoutRecordType (record_decl = %p, bit_size = %" PRIu64 ", alignment = %" PRIu64 ", field_offsets[%u],base_offsets[%u], vbase_offsets[%u]) success = %i",
+                                                  record_decl,
+                                                  bit_size,
+                                                  alignment,
+                                                  (uint32_t)field_offsets.size(),
+                                                  (uint32_t)base_offsets.size(),
+                                                  (uint32_t)vbase_offsets.size(),
+                                                  success);
+    return success;
+}
+
+
+SymbolFileDWARFDebugMap *
+SymbolFileDWARF::GetDebugMapSymfile ()
+{
+    if (m_debug_map_symfile == NULL && !m_debug_map_module_wp.expired())
+    {
+        lldb::ModuleSP module_sp (m_debug_map_module_wp.lock());
+        if (module_sp)
+        {
+            SymbolVendor *sym_vendor = module_sp->GetSymbolVendor();
+            if (sym_vendor)
+                m_debug_map_symfile = (SymbolFileDWARFDebugMap *)sym_vendor->GetSymbolFile();
+        }
+    }
+    return m_debug_map_symfile;
+}
+
+
diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
new file mode 100644
index 000000000000..b6c6d94782db
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
@@ -0,0 +1,622 @@
+//===-- SymbolFileDWARF.h --------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SymbolFileDWARF_SymbolFileDWARF_h_
+#define SymbolFileDWARF_SymbolFileDWARF_h_
+
+// C Includes
+// C++ Includes
+#include <list>
+#include <map>
+#include <set>
+#include <vector>
+
+// Other libraries and framework includes
+#include "clang/AST/CharUnits.h"
+#include "clang/AST/ExternalASTSource.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+
+#include "lldb/lldb-private.h"
+#include "lldb/Core/ClangForward.h"
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/dwarf.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Flags.h"
+#include "lldb/Core/UniqueCStringMap.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/SymbolFile.h"
+#include "lldb/Symbol/SymbolContext.h"
+
+// Project includes
+#include "DWARFDefines.h"
+#include "HashedNameToDIE.h"
+#include "NameToDIE.h"
+#include "UniqueDWARFASTType.h"
+
+//----------------------------------------------------------------------
+// Forward Declarations for this DWARF plugin
+//----------------------------------------------------------------------
+class DebugMapModule;
+class DWARFAbbreviationDeclaration;
+class DWARFAbbreviationDeclarationSet;
+class DWARFileUnit;
+class DWARFDebugAbbrev;
+class DWARFDebugAranges;
+class DWARFDebugInfo;
+class DWARFDebugInfoEntry;
+class DWARFDebugLine;
+class DWARFDebugPubnames;
+class DWARFDebugRanges;
+class DWARFDeclContext;
+class DWARFDIECollection;
+class DWARFFormValue;
+class SymbolFileDWARFDebugMap;
+
+class SymbolFileDWARF : public lldb_private::SymbolFile, public lldb_private::UserID
+{
+public:
+    friend class SymbolFileDWARFDebugMap;
+    friend class DebugMapModule;
+    friend class DWARFCompileUnit;
+    //------------------------------------------------------------------
+    // Static Functions
+    //------------------------------------------------------------------
+    static void
+    Initialize();
+
+    static void
+    Terminate();
+
+    static lldb_private::ConstString
+    GetPluginNameStatic();
+
+    static const char *
+    GetPluginDescriptionStatic();
+
+    static lldb_private::SymbolFile*
+    CreateInstance (lldb_private::ObjectFile* obj_file);
+    //------------------------------------------------------------------
+    // Constructors and Destructors
+    //------------------------------------------------------------------
+                            SymbolFileDWARF(lldb_private::ObjectFile* ofile);
+    virtual                 ~SymbolFileDWARF();
+
+    virtual uint32_t        CalculateAbilities ();
+    virtual void            InitializeObject();
+
+    //------------------------------------------------------------------
+    // Compile Unit function calls
+    //------------------------------------------------------------------
+    virtual uint32_t        GetNumCompileUnits();
+    virtual lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index);
+
+    virtual lldb::LanguageType ParseCompileUnitLanguage (const lldb_private::SymbolContext& sc);
+    virtual size_t          ParseCompileUnitFunctions (const lldb_private::SymbolContext& sc);
+    virtual bool            ParseCompileUnitLineTable (const lldb_private::SymbolContext& sc);
+    virtual bool            ParseCompileUnitSupportFiles (const lldb_private::SymbolContext& sc, lldb_private::FileSpecList& support_files);
+    virtual size_t          ParseFunctionBlocks (const lldb_private::SymbolContext& sc);
+    virtual size_t          ParseTypes (const lldb_private::SymbolContext& sc);
+    virtual size_t          ParseVariablesForContext (const lldb_private::SymbolContext& sc);
+
+    virtual lldb_private::Type* ResolveTypeUID(lldb::user_id_t type_uid);
+    virtual bool            ResolveClangOpaqueTypeDefinition (lldb_private::ClangASTType& clang_type);
+
+    virtual lldb_private::Type* ResolveType (DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry* type_die, bool assert_not_being_parsed = true);
+    virtual clang::DeclContext* GetClangDeclContextContainingTypeUID (lldb::user_id_t type_uid);
+    virtual clang::DeclContext* GetClangDeclContextForTypeUID (const lldb_private::SymbolContext &sc, lldb::user_id_t type_uid);
+
+    virtual uint32_t        ResolveSymbolContext (const lldb_private::Address& so_addr, uint32_t resolve_scope, lldb_private::SymbolContext& sc);
+    virtual uint32_t        ResolveSymbolContext (const lldb_private::FileSpec& file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, lldb_private::SymbolContextList& sc_list);
+    virtual uint32_t        FindGlobalVariables(const lldb_private::ConstString &name, const lldb_private::ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, lldb_private::VariableList& variables);
+    virtual uint32_t        FindGlobalVariables(const lldb_private::RegularExpression& regex, bool append, uint32_t max_matches, lldb_private::VariableList& variables);
+    virtual uint32_t        FindFunctions(const lldb_private::ConstString &name, const lldb_private::ClangNamespaceDecl *namespace_decl, uint32_t name_type_mask, bool include_inlines, bool append, lldb_private::SymbolContextList& sc_list);
+    virtual uint32_t        FindFunctions(const lldb_private::RegularExpression& regex, bool include_inlines, bool append, lldb_private::SymbolContextList& sc_list);
+    virtual uint32_t        FindTypes (const lldb_private::SymbolContext& sc, const lldb_private::ConstString &name, const lldb_private::ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, lldb_private::TypeList& types);
+    virtual lldb_private::TypeList *
+                            GetTypeList ();
+    virtual size_t          GetTypes (lldb_private::SymbolContextScope *sc_scope,
+                                      uint32_t type_mask,
+                                      lldb_private::TypeList &type_list);
+
+    virtual lldb_private::ClangASTContext &
+                            GetClangASTContext ();
+
+    virtual lldb_private::ClangNamespaceDecl
+            FindNamespace (const lldb_private::SymbolContext& sc, 
+                           const lldb_private::ConstString &name, 
+                           const lldb_private::ClangNamespaceDecl *parent_namespace_decl);
+
+
+    //------------------------------------------------------------------
+    // ClangASTContext callbacks for external source lookups.
+    //------------------------------------------------------------------
+    static void
+    CompleteTagDecl (void *baton, clang::TagDecl *);
+    
+    static void
+    CompleteObjCInterfaceDecl (void *baton, clang::ObjCInterfaceDecl *);
+    
+    static void
+    FindExternalVisibleDeclsByName (void *baton,
+                                    const clang::DeclContext *DC,
+                                    clang::DeclarationName Name,
+                                    llvm::SmallVectorImpl <clang::NamedDecl *> *results);
+
+    static bool 
+    LayoutRecordType (void *baton, 
+                      const clang::RecordDecl *record_decl,
+                      uint64_t &size, 
+                      uint64_t &alignment,
+                      llvm::DenseMap <const clang::FieldDecl *, uint64_t> &field_offsets,
+                      llvm::DenseMap <const clang::CXXRecordDecl *, clang::CharUnits> &base_offsets,
+                      llvm::DenseMap <const clang::CXXRecordDecl *, clang::CharUnits> &vbase_offsets);
+
+    bool 
+    LayoutRecordType (const clang::RecordDecl *record_decl,
+                      uint64_t &size, 
+                      uint64_t &alignment,
+                      llvm::DenseMap <const clang::FieldDecl *, uint64_t> &field_offsets,
+                      llvm::DenseMap <const clang::CXXRecordDecl *, clang::CharUnits> &base_offsets,
+                      llvm::DenseMap <const clang::CXXRecordDecl *, clang::CharUnits> &vbase_offsets);
+
+    struct LayoutInfo
+    {
+        LayoutInfo () :
+            bit_size(0),
+            alignment(0),
+            field_offsets(),
+            base_offsets(),
+            vbase_offsets()
+        {
+        }
+        uint64_t bit_size;
+        uint64_t alignment;
+        llvm::DenseMap <const clang::FieldDecl *, uint64_t> field_offsets;
+        llvm::DenseMap <const clang::CXXRecordDecl *, clang::CharUnits> base_offsets;
+        llvm::DenseMap <const clang::CXXRecordDecl *, clang::CharUnits> vbase_offsets;
+    };
+    //------------------------------------------------------------------
+    // PluginInterface protocol
+    //------------------------------------------------------------------
+    virtual lldb_private::ConstString
+    GetPluginName();
+
+    virtual uint32_t
+    GetPluginVersion();
+
+    // Approach 2 - count + accessor
+    // Index compile units would scan the initial compile units and register
+    // them with the module. This would only be done on demand if and only if
+    // the compile units were needed.
+    //virtual size_t        GetCompUnitCount() = 0;
+    //virtual CompUnitSP    GetCompUnitAtIndex(size_t cu_idx) = 0;
+
+    const lldb_private::DataExtractor&      get_debug_abbrev_data ();
+    const lldb_private::DataExtractor&      get_debug_aranges_data ();
+    const lldb_private::DataExtractor&      get_debug_frame_data ();
+    const lldb_private::DataExtractor&      get_debug_info_data ();
+    const lldb_private::DataExtractor&      get_debug_line_data ();
+    const lldb_private::DataExtractor&      get_debug_loc_data ();
+    const lldb_private::DataExtractor&      get_debug_ranges_data ();
+    const lldb_private::DataExtractor&      get_debug_str_data ();
+    const lldb_private::DataExtractor&      get_apple_names_data ();
+    const lldb_private::DataExtractor&      get_apple_types_data ();
+    const lldb_private::DataExtractor&      get_apple_namespaces_data ();
+    const lldb_private::DataExtractor&      get_apple_objc_data ();
+
+
+    DWARFDebugAbbrev*       DebugAbbrev();
+    const DWARFDebugAbbrev* DebugAbbrev() const;
+
+    DWARFDebugInfo*         DebugInfo();
+    const DWARFDebugInfo*   DebugInfo() const;
+
+    DWARFDebugRanges*       DebugRanges();
+    const DWARFDebugRanges* DebugRanges() const;
+
+    const lldb_private::DataExtractor&
+    GetCachedSectionData (uint32_t got_flag, 
+                          lldb::SectionType sect_type, 
+                          lldb_private::DataExtractor &data);
+
+    static bool
+    SupportedVersion(uint16_t version);
+
+    clang::DeclContext *
+    GetCachedClangDeclContextForDIE (const DWARFDebugInfoEntry *die)
+    {
+        DIEToDeclContextMap::iterator pos = m_die_to_decl_ctx.find(die);
+        if (pos != m_die_to_decl_ctx.end())
+            return pos->second;
+        else
+            return NULL;
+    }
+
+    clang::DeclContext *
+    GetClangDeclContextForDIE (const lldb_private::SymbolContext &sc, DWARFCompileUnit *cu, const DWARFDebugInfoEntry *die);
+    
+    clang::DeclContext *
+    GetClangDeclContextForDIEOffset (const lldb_private::SymbolContext &sc, dw_offset_t die_offset);
+    
+    clang::DeclContext *
+    GetClangDeclContextContainingDIE (DWARFCompileUnit *cu, 
+                                      const DWARFDebugInfoEntry *die,
+                                      const DWARFDebugInfoEntry **decl_ctx_die);
+
+    clang::DeclContext *
+    GetClangDeclContextContainingDIEOffset (dw_offset_t die_offset);
+
+    const DWARFDebugInfoEntry *
+    GetDeclContextDIEContainingDIE (DWARFCompileUnit *cu, const DWARFDebugInfoEntry *die);
+
+    void
+    SearchDeclContext (const clang::DeclContext *decl_context, 
+                       const char *name, 
+                       llvm::SmallVectorImpl <clang::NamedDecl *> *results);
+    
+    lldb_private::Flags&
+    GetFlags ()
+    {
+        return m_flags;
+    }
+
+    const lldb_private::Flags&
+    GetFlags () const
+    {
+        return m_flags;
+    }
+
+    bool
+    HasForwardDeclForClangType (const lldb_private::ClangASTType &clang_type);
+
+protected:
+
+    enum
+    {
+        flagsGotDebugAbbrevData     = (1 << 0),
+        flagsGotDebugArangesData    = (1 << 1),
+        flagsGotDebugFrameData      = (1 << 2),
+        flagsGotDebugInfoData       = (1 << 3),
+        flagsGotDebugLineData       = (1 << 4),
+        flagsGotDebugLocData        = (1 << 5),
+        flagsGotDebugMacInfoData    = (1 << 6),
+        flagsGotDebugPubNamesData   = (1 << 7),
+        flagsGotDebugPubTypesData   = (1 << 8),
+        flagsGotDebugRangesData     = (1 << 9),
+        flagsGotDebugStrData        = (1 << 10),
+        flagsGotAppleNamesData      = (1 << 11),
+        flagsGotAppleTypesData      = (1 << 12),
+        flagsGotAppleNamespacesData = (1 << 13),
+        flagsGotAppleObjCData       = (1 << 14)
+    };
+    
+    bool                    NamespaceDeclMatchesThisSymbolFile (const lldb_private::ClangNamespaceDecl *namespace_decl);
+
+    bool                    DIEIsInNamespace (const lldb_private::ClangNamespaceDecl *namespace_decl, 
+                                              DWARFCompileUnit* dwarf_cu, 
+                                              const DWARFDebugInfoEntry* die);
+
+    DISALLOW_COPY_AND_ASSIGN (SymbolFileDWARF);
+    lldb::CompUnitSP        ParseCompileUnit (DWARFCompileUnit* dwarf_cu, uint32_t cu_idx);
+    DWARFCompileUnit*       GetDWARFCompileUnit(lldb_private::CompileUnit *comp_unit);
+    DWARFCompileUnit*       GetNextUnparsedDWARFCompileUnit(DWARFCompileUnit* prev_cu);
+    lldb_private::CompileUnit*      GetCompUnitForDWARFCompUnit(DWARFCompileUnit* dwarf_cu, uint32_t cu_idx = UINT32_MAX);
+    bool                    GetFunction (DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry* func_die, lldb_private::SymbolContext& sc);
+    lldb_private::Function *        ParseCompileUnitFunction (const lldb_private::SymbolContext& sc, DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry *die);
+    size_t                  ParseFunctionBlocks (const lldb_private::SymbolContext& sc,
+                                                 lldb_private::Block *parent_block,
+                                                 DWARFCompileUnit* dwarf_cu,
+                                                 const DWARFDebugInfoEntry *die,
+                                                 lldb::addr_t subprogram_low_pc,
+                                                 uint32_t depth);
+    size_t                  ParseTypes (const lldb_private::SymbolContext& sc, DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry *die, bool parse_siblings, bool parse_children);
+    lldb::TypeSP            ParseType (const lldb_private::SymbolContext& sc, DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry *die, bool *type_is_new);
+    lldb_private::Type*     ResolveTypeUID (DWARFCompileUnit* dwarf_cu, const DWARFDebugInfoEntry* die, bool assert_not_being_parsed);
+
+    lldb::VariableSP        ParseVariableDIE(
+                                const lldb_private::SymbolContext& sc,
+                                DWARFCompileUnit* dwarf_cu,
+                                const DWARFDebugInfoEntry *die,
+                                const lldb::addr_t func_low_pc);
+
+    size_t                  ParseVariables(
+                                const lldb_private::SymbolContext& sc,
+                                DWARFCompileUnit* dwarf_cu,
+                                const lldb::addr_t func_low_pc,
+                                const DWARFDebugInfoEntry *die,
+                                bool parse_siblings,
+                                bool parse_children,
+                                lldb_private::VariableList* cc_variable_list = NULL);
+
+    class DelayedAddObjCClassProperty;
+    typedef std::vector <DelayedAddObjCClassProperty> DelayedPropertyList;
+    
+    bool                    ClassOrStructIsVirtual (
+                                DWARFCompileUnit* dwarf_cu,
+                                const DWARFDebugInfoEntry *parent_die);
+
+    size_t                  ParseChildMembers(
+                                const lldb_private::SymbolContext& sc,
+                                DWARFCompileUnit* dwarf_cu,
+                                const DWARFDebugInfoEntry *die,
+                                lldb_private::ClangASTType &class_clang_type,
+                                const lldb::LanguageType class_language,
+                                std::vector<clang::CXXBaseSpecifier *>& base_classes,
+                                std::vector<int>& member_accessibilities,
+                                DWARFDIECollection& member_function_dies,
+                                DelayedPropertyList& delayed_properties,
+                                lldb::AccessType &default_accessibility,
+                                bool &is_a_class,
+                                LayoutInfo &layout_info);
+
+    size_t                  ParseChildParameters(
+                                const lldb_private::SymbolContext& sc,
+                                clang::DeclContext *containing_decl_ctx,
+                                DWARFCompileUnit* dwarf_cu,
+                                const DWARFDebugInfoEntry *parent_die,
+                                bool skip_artificial,
+                                bool &is_static,
+                                lldb_private::TypeList* type_list,
+                                std::vector<lldb_private::ClangASTType>& function_args,
+                                std::vector<clang::ParmVarDecl*>& function_param_decls,
+                                unsigned &type_quals,
+                                lldb_private::ClangASTContext::TemplateParameterInfos &template_param_infos);
+
+    size_t                  ParseChildEnumerators(
+                                const lldb_private::SymbolContext& sc,
+                                lldb_private::ClangASTType &clang_type,
+                                bool is_signed,
+                                uint32_t enumerator_byte_size,
+                                DWARFCompileUnit* dwarf_cu,
+                                const DWARFDebugInfoEntry *enum_die);
+
+    void                    ParseChildArrayInfo(
+                                const lldb_private::SymbolContext& sc,
+                                DWARFCompileUnit* dwarf_cu,
+                                const DWARFDebugInfoEntry *parent_die,
+                                int64_t& first_index,
+                                std::vector<uint64_t>& element_orders,
+                                uint32_t& byte_stride,
+                                uint32_t& bit_stride);
+
+                            // Given a die_offset, figure out the symbol context representing that die.
+    bool                    ResolveFunction (dw_offset_t offset,
+                                             DWARFCompileUnit *&dwarf_cu,
+                                             lldb_private::SymbolContextList& sc_list);
+                            
+    bool                    ResolveFunction (DWARFCompileUnit *cu,
+                                             const DWARFDebugInfoEntry *die,
+                                             lldb_private::SymbolContextList& sc_list);
+
+    bool                    FunctionDieMatchesPartialName (
+                                const DWARFDebugInfoEntry* die,
+                                const DWARFCompileUnit *dwarf_cu,
+                                uint32_t name_type_mask,
+                                const char *partial_name,
+                                const char *base_name_start,
+                                const char *base_name_end);
+
+    void                    FindFunctions(
+                                const lldb_private::ConstString &name, 
+                                const NameToDIE &name_to_die,
+                                lldb_private::SymbolContextList& sc_list);
+
+    void                    FindFunctions (
+                                const lldb_private::RegularExpression &regex, 
+                                const NameToDIE &name_to_die,
+                                lldb_private::SymbolContextList& sc_list);
+
+    void                    FindFunctions (
+                                const lldb_private::RegularExpression &regex, 
+                                const DWARFMappedHash::MemoryTable &memory_table,
+                                lldb_private::SymbolContextList& sc_list);
+
+    lldb::TypeSP            FindDefinitionTypeForDIE (
+                                DWARFCompileUnit* dwarf_cu, 
+                                const DWARFDebugInfoEntry *die, 
+                                const lldb_private::ConstString &type_name);
+    
+    lldb::TypeSP            FindDefinitionTypeForDWARFDeclContext (
+                                const DWARFDeclContext &die_decl_ctx);
+
+    lldb::TypeSP            FindCompleteObjCDefinitionTypeForDIE (
+                                const DWARFDebugInfoEntry *die, 
+                                const lldb_private::ConstString &type_name,
+                                bool must_be_implementation);
+
+    bool                    Supports_DW_AT_APPLE_objc_complete_type (DWARFCompileUnit *cu);
+
+    lldb::TypeSP            FindCompleteObjCDefinitionType (const lldb_private::ConstString &type_name,
+                                                            bool header_definition_ok);
+
+    lldb_private::Symbol *  GetObjCClassSymbol (const lldb_private::ConstString &objc_class_name);
+
+    void                    ParseFunctions (const DIEArray &die_offsets,
+                                            lldb_private::SymbolContextList& sc_list);
+    lldb::TypeSP            GetTypeForDIE (DWARFCompileUnit *cu, 
+                                           const DWARFDebugInfoEntry* die);
+
+    uint32_t                FindTypes(std::vector<dw_offset_t> die_offsets, uint32_t max_matches, lldb_private::TypeList& types);
+
+    void                    Index();
+    
+    void                    DumpIndexes();
+
+    void                    SetDebugMapModule (const lldb::ModuleSP &module_sp)
+                            {
+                                m_debug_map_module_wp = module_sp;
+                            }
+    
+    SymbolFileDWARFDebugMap *
+                            GetDebugMapSymfile ();
+
+    const DWARFDebugInfoEntry *
+                            FindBlockContainingSpecification (dw_offset_t func_die_offset, 
+                                                              dw_offset_t spec_block_die_offset,
+                                                              DWARFCompileUnit **dwarf_cu_handle);
+
+    const DWARFDebugInfoEntry *
+                            FindBlockContainingSpecification (DWARFCompileUnit* dwarf_cu,
+                                                              const DWARFDebugInfoEntry *die,
+                                                              dw_offset_t spec_block_die_offset,
+                                                              DWARFCompileUnit **dwarf_cu_handle);
+
+    clang::NamespaceDecl *
+    ResolveNamespaceDIE (DWARFCompileUnit *curr_cu, const DWARFDebugInfoEntry *die);
+    
+    UniqueDWARFASTTypeMap &
+    GetUniqueDWARFASTTypeMap ();
+
+    void                    LinkDeclContextToDIE (clang::DeclContext *decl_ctx,
+                                                  const DWARFDebugInfoEntry *die)
+                            {
+                                m_die_to_decl_ctx[die] = decl_ctx;
+                                // There can be many DIEs for a single decl context
+                                m_decl_ctx_to_die[decl_ctx].insert(die);
+                            }
+    
+    bool
+    UserIDMatches (lldb::user_id_t uid) const
+    {
+        const lldb::user_id_t high_uid = uid & 0xffffffff00000000ull;
+        if (high_uid)
+            return high_uid == GetID();
+        return true;
+    }
+    
+    lldb::user_id_t
+    MakeUserID (dw_offset_t die_offset) const
+    {
+        return GetID() | die_offset;
+    }
+
+    static bool
+    DeclKindIsCXXClass (clang::Decl::Kind decl_kind)
+    {
+        switch (decl_kind)
+        {
+            case clang::Decl::CXXRecord:
+            case clang::Decl::ClassTemplateSpecialization:
+                return true;
+            default:
+                break;
+        }
+        return false;
+    }
+    
+    bool
+    ParseTemplateParameterInfos (DWARFCompileUnit* dwarf_cu,
+                                 const DWARFDebugInfoEntry *parent_die,
+                                 lldb_private::ClangASTContext::TemplateParameterInfos &template_param_infos);
+
+    bool
+    ParseTemplateDIE (DWARFCompileUnit* dwarf_cu,
+                      const DWARFDebugInfoEntry *die,
+                      lldb_private::ClangASTContext::TemplateParameterInfos &template_param_infos);
+
+    clang::ClassTemplateDecl *
+    ParseClassTemplateDecl (clang::DeclContext *decl_ctx,
+                            lldb::AccessType access_type,
+                            const char *parent_name,
+                            int tag_decl_kind,
+                            const lldb_private::ClangASTContext::TemplateParameterInfos &template_param_infos);
+
+    bool
+    DIEDeclContextsMatch (DWARFCompileUnit* cu1, const DWARFDebugInfoEntry *die1,
+                          DWARFCompileUnit* cu2, const DWARFDebugInfoEntry *die2);
+    
+    bool
+    ClassContainsSelector (DWARFCompileUnit *dwarf_cu,
+                           const DWARFDebugInfoEntry *class_die,
+                           const lldb_private::ConstString &selector);
+
+    bool
+    CopyUniqueClassMethodTypes (SymbolFileDWARF *class_symfile,
+                                lldb_private::Type *class_type,
+                                DWARFCompileUnit* src_cu,
+                                const DWARFDebugInfoEntry *src_class_die,
+                                DWARFCompileUnit* dst_cu,
+                                const DWARFDebugInfoEntry *dst_class_die,
+                                llvm::SmallVectorImpl <const DWARFDebugInfoEntry *> &failures);
+
+    bool
+    FixupAddress (lldb_private::Address &addr);
+
+    typedef std::set<lldb_private::Type *> TypeSet;
+
+    void
+    GetTypes (DWARFCompileUnit* dwarf_cu,
+              const DWARFDebugInfoEntry *die,
+              dw_offset_t min_die_offset,
+              dw_offset_t max_die_offset,
+              uint32_t type_mask,
+              TypeSet &type_set);
+
+    lldb::ModuleWP                  m_debug_map_module_wp;
+    SymbolFileDWARFDebugMap *       m_debug_map_symfile;
+    clang::TranslationUnitDecl *    m_clang_tu_decl;
+    lldb_private::Flags             m_flags;
+    lldb_private::DataExtractor     m_dwarf_data; 
+    lldb_private::DataExtractor     m_data_debug_abbrev;
+    lldb_private::DataExtractor     m_data_debug_aranges;
+    lldb_private::DataExtractor     m_data_debug_frame;
+    lldb_private::DataExtractor     m_data_debug_info;
+    lldb_private::DataExtractor     m_data_debug_line;
+    lldb_private::DataExtractor     m_data_debug_loc;
+    lldb_private::DataExtractor     m_data_debug_ranges;
+    lldb_private::DataExtractor     m_data_debug_str;
+    lldb_private::DataExtractor     m_data_apple_names;
+    lldb_private::DataExtractor     m_data_apple_types;
+    lldb_private::DataExtractor     m_data_apple_namespaces;
+    lldb_private::DataExtractor     m_data_apple_objc;
+
+    // The unique pointer items below are generated on demand if and when someone accesses
+    // them through a non const version of this class.
+    std::unique_ptr<DWARFDebugAbbrev>     m_abbr;
+    std::unique_ptr<DWARFDebugInfo>       m_info;
+    std::unique_ptr<DWARFDebugLine>       m_line;
+    std::unique_ptr<DWARFMappedHash::MemoryTable> m_apple_names_ap;
+    std::unique_ptr<DWARFMappedHash::MemoryTable> m_apple_types_ap;
+    std::unique_ptr<DWARFMappedHash::MemoryTable> m_apple_namespaces_ap;
+    std::unique_ptr<DWARFMappedHash::MemoryTable> m_apple_objc_ap;
+    NameToDIE                           m_function_basename_index;  // All concrete functions
+    NameToDIE                           m_function_fullname_index;  // All concrete functions
+    NameToDIE                           m_function_method_index;    // All inlined functions
+    NameToDIE                           m_function_selector_index;  // All method names for functions of classes
+    NameToDIE                           m_objc_class_selectors_index; // Given a class name, find all selectors for the class
+    NameToDIE                           m_global_index;             // Global and static variables
+    NameToDIE                           m_type_index;               // All type DIE offsets
+    NameToDIE                           m_namespace_index;          // All type DIE offsets
+    bool                                m_indexed:1,
+                                        m_is_external_ast_source:1,
+                                        m_using_apple_tables:1;
+    lldb_private::LazyBool              m_supports_DW_AT_APPLE_objc_complete_type;
+
+    std::unique_ptr<DWARFDebugRanges>     m_ranges;
+    UniqueDWARFASTTypeMap m_unique_ast_type_map;
+    typedef llvm::SmallPtrSet<const DWARFDebugInfoEntry *, 4> DIEPointerSet;
+    typedef llvm::DenseMap<const DWARFDebugInfoEntry *, clang::DeclContext *> DIEToDeclContextMap;
+    typedef llvm::DenseMap<const clang::DeclContext *, DIEPointerSet> DeclContextToDIEMap;
+    typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb_private::Type *> DIEToTypePtr;
+    typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb::VariableSP> DIEToVariableSP;
+    typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb::clang_type_t> DIEToClangType;
+    typedef llvm::DenseMap<lldb::clang_type_t, const DWARFDebugInfoEntry *> ClangTypeToDIE;
+    typedef llvm::DenseMap<const clang::RecordDecl *, LayoutInfo> RecordDeclToLayoutMap;
+    DIEToDeclContextMap m_die_to_decl_ctx;
+    DeclContextToDIEMap m_decl_ctx_to_die;
+    DIEToTypePtr m_die_to_type;
+    DIEToVariableSP m_die_to_variable_sp;
+    DIEToClangType m_forward_decl_die_to_clang_type;
+    ClangTypeToDIE m_forward_decl_clang_type_to_die;
+    RecordDeclToLayoutMap m_record_decl_to_layout_map;
+};
+
+#endif  // SymbolFileDWARF_SymbolFileDWARF_h_
diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
new file mode 100644
index 000000000000..a0430e3d52b6
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
@@ -0,0 +1,1586 @@
+//===-- SymbolFileDWARFDebugMap.cpp ----------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SymbolFileDWARFDebugMap.h"
+
+#include "DWARFDebugAranges.h"
+
+#include "lldb/Core/RangeMap.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleList.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/RegularExpression.h"
+#include "lldb/Core/Section.h"
+
+//#define DEBUG_OSO_DMAP // DO NOT CHECKIN WITH THIS NOT COMMENTED OUT
+#if defined(DEBUG_OSO_DMAP)
+#include "lldb/Core/StreamFile.h"
+#endif
+#include "lldb/Core/Timer.h"
+
+#include "lldb/Symbol/ClangExternalASTSourceCallbacks.h"
+#include "lldb/Symbol/CompileUnit.h"
+#include "lldb/Symbol/LineTable.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/SymbolVendor.h"
+#include "lldb/Symbol/VariableList.h"
+
+#include "LogChannelDWARF.h"
+#include "SymbolFileDWARF.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+// Subclass lldb_private::Module so we can intercept the "Module::GetObjectFile()" 
+// (so we can fixup the object file sections) and also for "Module::GetSymbolVendor()"
+// (so we can fixup the symbol file id.
+
+
+
+
+const SymbolFileDWARFDebugMap::FileRangeMap &
+SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap(SymbolFileDWARFDebugMap *exe_symfile)
+{
+    if (file_range_map_valid)
+        return file_range_map;
+
+    file_range_map_valid = true;
+
+    Module *oso_module = exe_symfile->GetModuleByCompUnitInfo (this);
+    if (!oso_module)
+        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)
+    {
+        ConstString object_name (oso_module->GetObjectName());
+        log->Printf("%p: SymbolFileDWARFDebugMap::CompileUnitInfo::GetFileRangeMap ('%s')",
+                    this,
+                    oso_module->GetSpecificationDescription().c_str());
+    }
+    
+
+    std::vector<SymbolFileDWARFDebugMap::CompileUnitInfo *> cu_infos;
+    if (exe_symfile->GetCompUnitInfosForModule(oso_module, cu_infos))
+    {
+        for (auto comp_unit_info : cu_infos)
+        {
+            Symtab *exe_symtab = exe_symfile->GetObjectFile()->GetSymtab();
+            ModuleSP oso_module_sp (oso_objfile->GetModule());
+            Symtab *oso_symtab = oso_objfile->GetSymtab();
+            
+            ///const uint32_t fun_resolve_flags = SymbolContext::Module | eSymbolContextCompUnit | eSymbolContextFunction;
+            //SectionList *oso_sections = oso_objfile->Sections();
+            // Now we need to make sections that map from zero based object
+            // file addresses to where things eneded up in the main executable.
+            
+            assert (comp_unit_info->first_symbol_index != UINT32_MAX);
+            // End index is one past the last valid symbol index
+            const uint32_t oso_end_idx = comp_unit_info->last_symbol_index + 1;
+            for (uint32_t idx = comp_unit_info->first_symbol_index + 2; // Skip the N_SO and N_OSO
+                 idx < oso_end_idx;
+                 ++idx)
+            {
+                Symbol *exe_symbol = exe_symtab->SymbolAtIndex(idx);
+                if (exe_symbol)
+                {
+                    if (exe_symbol->IsDebug() == false)
+                        continue;
+                    
+                    switch (exe_symbol->GetType())
+                    {
+                    default:
+                        break;
+                        
+                    case eSymbolTypeCode:
+                        {
+                            // For each N_FUN, or function that we run into in the debug map
+                            // we make a new section that we add to the sections found in the
+                            // .o file. This new section has the file address set to what the
+                            // addresses are in the .o file, and the load address is adjusted
+                            // to match where it ended up in the final executable! We do this
+                            // before we parse any dwarf info so that when it goes get parsed
+                            // all section/offset addresses that get registered will resolve
+                            // correctly to the new addresses in the main executable.
+                            
+                            // First we find the original symbol in the .o file's symbol table
+                            Symbol *oso_fun_symbol = oso_symtab->FindFirstSymbolWithNameAndType (exe_symbol->GetMangled().GetName(Mangled::ePreferMangled),
+                                                                                                 eSymbolTypeCode,
+                                                                                                 Symtab::eDebugNo,
+                                                                                                 Symtab::eVisibilityAny);
+                            if (oso_fun_symbol)
+                            {
+                                // Add the inverse OSO file address to debug map entry mapping
+                                exe_symfile->AddOSOFileRange (this,
+                                                              exe_symbol->GetAddress().GetFileAddress(),
+                                                              oso_fun_symbol->GetAddress().GetFileAddress(),
+                                                              std::min<addr_t>(exe_symbol->GetByteSize(), oso_fun_symbol->GetByteSize()));
+                                
+                            }
+                        }
+                        break;
+                        
+                    case eSymbolTypeData:
+                        {
+                            // For each N_GSYM we remap the address for the global by making
+                            // a new section that we add to the sections found in the .o file.
+                            // This new section has the file address set to what the
+                            // addresses are in the .o file, and the load address is adjusted
+                            // to match where it ended up in the final executable! We do this
+                            // before we parse any dwarf info so that when it goes get parsed
+                            // all section/offset addresses that get registered will resolve
+                            // correctly to the new addresses in the main executable. We
+                            // initially set the section size to be 1 byte, but will need to
+                            // fix up these addresses further after all globals have been
+                            // parsed to span the gaps, or we can find the global variable
+                            // sizes from the DWARF info as we are parsing.
+                            
+                            // Next we find the non-stab entry that corresponds to the N_GSYM in the .o file
+                            Symbol *oso_gsym_symbol = oso_symtab->FindFirstSymbolWithNameAndType (exe_symbol->GetMangled().GetName(Mangled::ePreferMangled),
+                                                                                                  eSymbolTypeData,
+                                                                                                  Symtab::eDebugNo,
+                                                                                                  Symtab::eVisibilityAny);
+                            
+                            if (exe_symbol && oso_gsym_symbol &&
+                                exe_symbol->ValueIsAddress() &&
+                                oso_gsym_symbol->ValueIsAddress())
+                            {
+                                // Add the inverse OSO file address to debug map entry mapping
+                                exe_symfile->AddOSOFileRange (this,
+                                                              exe_symbol->GetAddress().GetFileAddress(),
+                                                              oso_gsym_symbol->GetAddress().GetFileAddress(),
+                                                              std::min<addr_t>(exe_symbol->GetByteSize(), oso_gsym_symbol->GetByteSize()));
+                            }
+                        }
+                        break;
+                    }
+                }
+            }
+            
+            exe_symfile->FinalizeOSOFileRanges (this);
+            // We don't need the symbols anymore for the .o files
+            oso_objfile->ClearSymtab();
+        }
+    }
+    return file_range_map;
+}
+
+
+class DebugMapModule : public Module
+{
+public:
+    DebugMapModule (const ModuleSP &exe_module_sp,
+                    uint32_t cu_idx,
+                    const FileSpec& file_spec,
+                    const ArchSpec& arch,
+                    const ConstString *object_name,
+                    off_t object_offset,
+                    const TimeValue *object_mod_time_ptr) :
+        Module (file_spec, arch, object_name, object_offset, object_mod_time_ptr),
+        m_exe_module_wp (exe_module_sp),
+        m_cu_idx (cu_idx)
+    {
+    }
+
+    virtual
+    ~DebugMapModule ()
+    {
+    }
+
+    
+    virtual SymbolVendor*
+    GetSymbolVendor(bool can_create = true, lldb_private::Stream *feedback_strm = NULL)
+    {
+        // Scope for locker
+        if (m_symfile_ap.get() || can_create == false)
+            return m_symfile_ap.get();
+
+        ModuleSP exe_module_sp (m_exe_module_wp.lock());
+        if (exe_module_sp)
+        {
+            // Now get the object file outside of a locking scope
+            ObjectFile *oso_objfile = GetObjectFile ();
+            if (oso_objfile)
+            {
+                Mutex::Locker locker (m_mutex);
+                SymbolVendor* symbol_vendor = Module::GetSymbolVendor(can_create, feedback_strm);
+                if (symbol_vendor)
+                {
+                    // Set a a pointer to this class to set our OSO DWARF file know
+                    // that the DWARF is being used along with a debug map and that
+                    // it will have the remapped sections that we do below.
+                    SymbolFileDWARF *oso_symfile = SymbolFileDWARFDebugMap::GetSymbolFileAsSymbolFileDWARF(symbol_vendor->GetSymbolFile());
+                    
+                    if (!oso_symfile)
+                        return NULL;
+
+                    ObjectFile *exe_objfile = exe_module_sp->GetObjectFile();
+                    SymbolVendor *exe_sym_vendor = exe_module_sp->GetSymbolVendor();
+                    
+                    if (exe_objfile && exe_sym_vendor)
+                    {
+                        if (oso_symfile->GetNumCompileUnits() == 1)
+                        {
+                            oso_symfile->SetDebugMapModule(exe_module_sp);
+                            // Set the ID of the symbol file DWARF to the index of the OSO
+                            // shifted left by 32 bits to provide a unique prefix for any
+                            // UserID's that get created in the symbol file.
+                            oso_symfile->SetID (((uint64_t)m_cu_idx + 1ull) << 32ull);
+                        }
+                        else
+                        {
+                            oso_symfile->SetID (UINT64_MAX);
+                        }
+                    }
+                    return symbol_vendor;
+                }
+            }
+        }
+        return NULL;
+    }
+
+protected:
+    ModuleWP m_exe_module_wp;
+    const uint32_t m_cu_idx;
+};
+
+void
+SymbolFileDWARFDebugMap::Initialize()
+{
+    PluginManager::RegisterPlugin (GetPluginNameStatic(),
+                                   GetPluginDescriptionStatic(),
+                                   CreateInstance);
+}
+
+void
+SymbolFileDWARFDebugMap::Terminate()
+{
+    PluginManager::UnregisterPlugin (CreateInstance);
+}
+
+
+lldb_private::ConstString
+SymbolFileDWARFDebugMap::GetPluginNameStatic()
+{
+    static ConstString g_name("dwarf-debugmap");
+    return g_name;
+}
+
+const char *
+SymbolFileDWARFDebugMap::GetPluginDescriptionStatic()
+{
+    return "DWARF and DWARF3 debug symbol file reader (debug map).";
+}
+
+SymbolFile*
+SymbolFileDWARFDebugMap::CreateInstance (ObjectFile* obj_file)
+{
+    return new SymbolFileDWARFDebugMap (obj_file);
+}
+
+
+SymbolFileDWARFDebugMap::SymbolFileDWARFDebugMap (ObjectFile* ofile) :
+    SymbolFile(ofile),
+    m_flags(),
+    m_compile_unit_infos(),
+    m_func_indexes(),
+    m_glob_indexes(),
+    m_supports_DW_AT_APPLE_objc_complete_type (eLazyBoolCalculate)
+{
+}
+
+
+SymbolFileDWARFDebugMap::~SymbolFileDWARFDebugMap()
+{
+}
+
+void
+SymbolFileDWARFDebugMap::InitializeObject()
+{
+    // Install our external AST source callbacks so we can complete Clang types.
+    llvm::OwningPtr<clang::ExternalASTSource> ast_source_ap (
+        new ClangExternalASTSourceCallbacks (SymbolFileDWARFDebugMap::CompleteTagDecl,
+                                             SymbolFileDWARFDebugMap::CompleteObjCInterfaceDecl,
+                                             NULL,
+                                             SymbolFileDWARFDebugMap::LayoutRecordType,
+                                             this));
+
+    GetClangASTContext().SetExternalSource (ast_source_ap);
+}
+
+void
+SymbolFileDWARFDebugMap::InitOSO()
+{
+    if (m_flags.test(kHaveInitializedOSOs))
+        return;
+    
+    m_flags.set(kHaveInitializedOSOs);
+    
+    // If the object file has been stripped, there is no sense in looking further
+    // as all of the debug symbols for the debug map will not be available
+    if (m_obj_file->IsStripped())
+        return;
+    
+    // Also make sure the file type is some sort of executable. Core files, debug
+    // info files (dSYM), object files (.o files), and stub libraries all can
+    switch (m_obj_file->GetType())
+    {
+        case ObjectFile::eTypeInvalid:
+        case ObjectFile::eTypeCoreFile:
+        case ObjectFile::eTypeDebugInfo:
+        case ObjectFile::eTypeObjectFile:
+        case ObjectFile::eTypeStubLibrary:
+        case ObjectFile::eTypeUnknown:
+            return;
+            
+        case ObjectFile::eTypeExecutable:
+        case ObjectFile::eTypeDynamicLinker:
+        case ObjectFile::eTypeSharedLibrary:
+            break;
+    }
+
+    // In order to get the abilities of this plug-in, we look at the list of
+    // N_OSO entries (object files) from the symbol table and make sure that
+    // these files exist and also contain valid DWARF. If we get any of that
+    // then we return the abilities of the first N_OSO's DWARF.
+
+    Symtab* symtab = m_obj_file->GetSymtab();
+    if (symtab)
+    {
+        Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_MAP));
+
+        std::vector<uint32_t> oso_indexes;
+        // When a mach-o symbol is encoded, the n_type field is encoded in bits
+        // 23:16, and the n_desc field is encoded in bits 15:0.
+        // 
+        // To find all N_OSO entries that are part of the DWARF + debug map
+        // we find only object file symbols with the flags value as follows:
+        // bits 23:16 == 0x66 (N_OSO)
+        // bits 15: 0 == 0x0001 (specifies this is a debug map object file)
+        const uint32_t k_oso_symbol_flags_value = 0x660001u;
+
+        const uint32_t oso_index_count = symtab->AppendSymbolIndexesWithTypeAndFlagsValue(eSymbolTypeObjectFile, k_oso_symbol_flags_value, oso_indexes);
+
+        if (oso_index_count > 0)
+        {
+            symtab->AppendSymbolIndexesWithType (eSymbolTypeCode, Symtab::eDebugYes, Symtab::eVisibilityAny, m_func_indexes);
+            symtab->AppendSymbolIndexesWithType (eSymbolTypeData, Symtab::eDebugYes, Symtab::eVisibilityAny, m_glob_indexes);
+
+            symtab->SortSymbolIndexesByValue(m_func_indexes, true);
+            symtab->SortSymbolIndexesByValue(m_glob_indexes, true);
+
+            for (uint32_t sym_idx : m_func_indexes)
+            {
+                const Symbol *symbol = symtab->SymbolAtIndex(sym_idx);
+                lldb::addr_t file_addr = symbol->GetAddress().GetFileAddress();
+                lldb::addr_t byte_size = symbol->GetByteSize();
+                DebugMap::Entry debug_map_entry(file_addr, byte_size, OSOEntry(sym_idx, LLDB_INVALID_ADDRESS));
+                m_debug_map.Append(debug_map_entry);
+            }
+            for (uint32_t sym_idx : m_glob_indexes)
+            {
+                const Symbol *symbol = symtab->SymbolAtIndex(sym_idx);
+                lldb::addr_t file_addr = symbol->GetAddress().GetFileAddress();
+                lldb::addr_t byte_size = symbol->GetByteSize();
+                DebugMap::Entry debug_map_entry(file_addr, byte_size, OSOEntry(sym_idx, LLDB_INVALID_ADDRESS));
+                m_debug_map.Append(debug_map_entry);
+            }
+            m_debug_map.Sort();
+
+            m_compile_unit_infos.resize(oso_index_count);
+
+            for (uint32_t i=0; i<oso_index_count; ++i)
+            {
+                const uint32_t so_idx = oso_indexes[i] - 1;
+                const uint32_t oso_idx = oso_indexes[i];
+                const Symbol *so_symbol = symtab->SymbolAtIndex(so_idx);
+                const Symbol *oso_symbol = symtab->SymbolAtIndex(oso_idx);
+                if (so_symbol &&
+                    oso_symbol &&
+                    so_symbol->GetType() == eSymbolTypeSourceFile &&
+                    oso_symbol->GetType() == eSymbolTypeObjectFile)
+                {
+                    m_compile_unit_infos[i].so_file.SetFile(so_symbol->GetName().AsCString(), false);
+                    m_compile_unit_infos[i].oso_path = oso_symbol->GetName();
+                    TimeValue oso_mod_time;
+                    oso_mod_time.OffsetWithSeconds(oso_symbol->GetAddress().GetOffset());
+                    m_compile_unit_infos[i].oso_mod_time = oso_mod_time;
+                    uint32_t sibling_idx = so_symbol->GetSiblingIndex();
+                    // The sibling index can't be less that or equal to the current index "i"
+                    if (sibling_idx <= i)
+                    {
+                        m_obj_file->GetModule()->ReportError ("N_SO in symbol with UID %u has invalid sibling in debug map, please file a bug and attach the binary listed in this error", so_symbol->GetID());
+                    }
+                    else
+                    {
+                        const Symbol* last_symbol = symtab->SymbolAtIndex (sibling_idx - 1);
+                        m_compile_unit_infos[i].first_symbol_index = so_idx;
+                        m_compile_unit_infos[i].last_symbol_index = sibling_idx - 1;
+                        m_compile_unit_infos[i].first_symbol_id = so_symbol->GetID();
+                        m_compile_unit_infos[i].last_symbol_id = last_symbol->GetID();
+                        
+                        if (log)
+                            log->Printf("Initialized OSO 0x%8.8x: file=%s", i, oso_symbol->GetName().GetCString());
+                    }
+                }
+                else
+                {
+                    if (oso_symbol == NULL)
+                        m_obj_file->GetModule()->ReportError ("N_OSO symbol[%u] can't be found, please file a bug and attach the binary listed in this error", oso_idx);
+                    else if (so_symbol == NULL)
+                        m_obj_file->GetModule()->ReportError ("N_SO not found for N_OSO symbol[%u], please file a bug and attach the binary listed in this error", oso_idx);
+                    else if (so_symbol->GetType() != eSymbolTypeSourceFile)
+                        m_obj_file->GetModule()->ReportError ("N_SO has incorrect symbol type (%u) for N_OSO symbol[%u], please file a bug and attach the binary listed in this error", so_symbol->GetType(), oso_idx);
+                    else if (oso_symbol->GetType() != eSymbolTypeSourceFile)
+                        m_obj_file->GetModule()->ReportError ("N_OSO has incorrect symbol type (%u) for N_OSO symbol[%u], please file a bug and attach the binary listed in this error", oso_symbol->GetType(), oso_idx);
+                }
+            }
+        }
+    }
+}
+
+Module *
+SymbolFileDWARFDebugMap::GetModuleByOSOIndex (uint32_t oso_idx)
+{
+    const uint32_t cu_count = GetNumCompileUnits();
+    if (oso_idx < cu_count)
+        return GetModuleByCompUnitInfo (&m_compile_unit_infos[oso_idx]);
+    return NULL;
+}
+
+Module *
+SymbolFileDWARFDebugMap::GetModuleByCompUnitInfo (CompileUnitInfo *comp_unit_info)
+{
+    if (!comp_unit_info->oso_sp)
+    {
+        auto pos = m_oso_map.find (comp_unit_info->oso_path);
+        if (pos != m_oso_map.end())
+        {
+            comp_unit_info->oso_sp = pos->second;
+        }
+        else
+        {
+            ObjectFile *obj_file = GetObjectFile();
+            comp_unit_info->oso_sp.reset (new OSOInfo());
+            m_oso_map[comp_unit_info->oso_path] = comp_unit_info->oso_sp;
+            const char *oso_path = comp_unit_info->oso_path.GetCString();
+            FileSpec oso_file (oso_path, false);
+            ConstString oso_object;
+            if (oso_file.Exists())
+            {
+                TimeValue oso_mod_time (oso_file.GetModificationTime());
+                if (oso_mod_time != comp_unit_info->oso_mod_time)
+                {
+                    obj_file->GetModule()->ReportError ("debug map object file '%s' has changed (actual time is 0x%" PRIx64 ", debug map time is 0x%" PRIx64 ") since this executable was linked, file will be ignored",
+                                                        oso_file.GetPath().c_str(),
+                                                        oso_mod_time.GetAsSecondsSinceJan1_1970(),
+                                                        comp_unit_info->oso_mod_time.GetAsSecondsSinceJan1_1970());
+                    return NULL;
+                }
+
+            }
+            else
+            {
+                const bool must_exist = true;
+
+                if (!ObjectFile::SplitArchivePathWithObject (oso_path,
+                                                             oso_file,
+                                                             oso_object,
+                                                             must_exist))
+                {
+                    return NULL;
+                }
+            }
+            // Always create a new module for .o files. Why? Because we
+            // use the debug map, to add new sections to each .o file and
+            // even though a .o file might not have changed, the sections
+            // that get added to the .o file can change.
+            comp_unit_info->oso_sp->module_sp.reset (new DebugMapModule (obj_file->GetModule(),
+                                                                         GetCompUnitInfoIndex(comp_unit_info),
+                                                                         oso_file,
+                                                                         m_obj_file->GetModule()->GetArchitecture(),
+                                                                         oso_object ? &oso_object : NULL,
+                                                                         0,
+                                                                         oso_object ? &comp_unit_info->oso_mod_time : NULL));
+        }
+    }
+    if (comp_unit_info->oso_sp)
+        return comp_unit_info->oso_sp->module_sp.get();
+    return NULL;
+}
+
+
+bool
+SymbolFileDWARFDebugMap::GetFileSpecForSO (uint32_t oso_idx, FileSpec &file_spec)
+{
+    if (oso_idx < m_compile_unit_infos.size())
+    {
+        if (m_compile_unit_infos[oso_idx].so_file)
+        {
+            file_spec = m_compile_unit_infos[oso_idx].so_file;
+            return true;
+        }
+    }
+    return false;
+}
+
+
+
+ObjectFile *
+SymbolFileDWARFDebugMap::GetObjectFileByOSOIndex (uint32_t oso_idx)
+{
+    Module *oso_module = GetModuleByOSOIndex (oso_idx);
+    if (oso_module)
+        return oso_module->GetObjectFile();
+    return NULL;
+}
+
+SymbolFileDWARF *
+SymbolFileDWARFDebugMap::GetSymbolFile (const SymbolContext& sc)
+{
+    CompileUnitInfo *comp_unit_info = GetCompUnitInfo (sc);
+    if (comp_unit_info)
+        return GetSymbolFileByCompUnitInfo (comp_unit_info);
+    return NULL;
+}
+
+ObjectFile *
+SymbolFileDWARFDebugMap::GetObjectFileByCompUnitInfo (CompileUnitInfo *comp_unit_info)
+{
+    Module *oso_module = GetModuleByCompUnitInfo (comp_unit_info);
+    if (oso_module)
+        return oso_module->GetObjectFile();
+    return NULL;
+}
+
+
+uint32_t
+SymbolFileDWARFDebugMap::GetCompUnitInfoIndex (const CompileUnitInfo *comp_unit_info)
+{
+    if (!m_compile_unit_infos.empty())
+    {
+        const CompileUnitInfo *first_comp_unit_info = &m_compile_unit_infos.front();
+        const CompileUnitInfo *last_comp_unit_info = &m_compile_unit_infos.back();
+        if (first_comp_unit_info <= comp_unit_info && comp_unit_info <= last_comp_unit_info)
+            return comp_unit_info - first_comp_unit_info;
+    }
+    return UINT32_MAX;
+}
+
+SymbolFileDWARF *
+SymbolFileDWARFDebugMap::GetSymbolFileByOSOIndex (uint32_t oso_idx)
+{
+    if (oso_idx < m_compile_unit_infos.size())
+        return GetSymbolFileByCompUnitInfo (&m_compile_unit_infos[oso_idx]);
+    return NULL;
+}
+
+SymbolFileDWARF *
+SymbolFileDWARFDebugMap::GetSymbolFileAsSymbolFileDWARF (SymbolFile *sym_file)
+{
+    if (sym_file && sym_file->GetPluginName() == SymbolFileDWARF::GetPluginNameStatic())
+        return (SymbolFileDWARF *)sym_file;
+    return NULL;
+}
+
+SymbolFileDWARF *
+SymbolFileDWARFDebugMap::GetSymbolFileByCompUnitInfo (CompileUnitInfo *comp_unit_info)
+{
+    Module *oso_module = GetModuleByCompUnitInfo (comp_unit_info);
+    if (oso_module)
+    {
+        SymbolVendor *sym_vendor = oso_module->GetSymbolVendor();
+        if (sym_vendor)
+            return GetSymbolFileAsSymbolFileDWARF (sym_vendor->GetSymbolFile());
+    }
+    return NULL;
+}
+
+uint32_t
+SymbolFileDWARFDebugMap::CalculateAbilities ()
+{
+    // In order to get the abilities of this plug-in, we look at the list of
+    // N_OSO entries (object files) from the symbol table and make sure that
+    // these files exist and also contain valid DWARF. If we get any of that
+    // then we return the abilities of the first N_OSO's DWARF.
+
+    const uint32_t oso_index_count = GetNumCompileUnits();
+    if (oso_index_count > 0)
+    {
+        InitOSO();
+        if (!m_compile_unit_infos.empty())
+        {
+            return SymbolFile::CompileUnits    |
+                   SymbolFile::Functions       |
+                   SymbolFile::Blocks          |
+                   SymbolFile::GlobalVariables |
+                   SymbolFile::LocalVariables  |
+                   SymbolFile::VariableTypes   |
+                   SymbolFile::LineTables      ;
+        }
+    }
+    return 0;
+}
+
+uint32_t
+SymbolFileDWARFDebugMap::GetNumCompileUnits()
+{
+    InitOSO ();
+    return m_compile_unit_infos.size();
+}
+
+
+CompUnitSP
+SymbolFileDWARFDebugMap::ParseCompileUnitAtIndex(uint32_t cu_idx)
+{
+    CompUnitSP comp_unit_sp;
+    const uint32_t cu_count = GetNumCompileUnits();
+
+    if (cu_idx < cu_count)
+    {
+        Module *oso_module = GetModuleByCompUnitInfo (&m_compile_unit_infos[cu_idx]);
+        if (oso_module)
+        {
+            FileSpec so_file_spec;
+            if (GetFileSpecForSO (cu_idx, so_file_spec))
+            {
+                // User zero as the ID to match the compile unit at offset
+                // zero in each .o file since each .o file can only have
+                // one compile unit for now.
+                lldb::user_id_t cu_id = 0;
+                m_compile_unit_infos[cu_idx].compile_unit_sp.reset(new CompileUnit (m_obj_file->GetModule(),
+                                                                                    NULL,
+                                                                                    so_file_spec,
+                                                                                    cu_id,
+                                                                                    eLanguageTypeUnknown));
+            
+                if (m_compile_unit_infos[cu_idx].compile_unit_sp)
+                {
+                    // Let our symbol vendor know about this compile unit
+                    m_obj_file->GetModule()->GetSymbolVendor()->SetCompileUnitAtIndex (cu_idx, m_compile_unit_infos[cu_idx].compile_unit_sp);
+                }
+            }
+        }
+        comp_unit_sp = m_compile_unit_infos[cu_idx].compile_unit_sp;
+    }
+
+    return comp_unit_sp;
+}
+
+SymbolFileDWARFDebugMap::CompileUnitInfo *
+SymbolFileDWARFDebugMap::GetCompUnitInfo (const SymbolContext& sc)
+{
+    const uint32_t cu_count = GetNumCompileUnits();
+    for (uint32_t i=0; i<cu_count; ++i)
+    {
+        if (sc.comp_unit == m_compile_unit_infos[i].compile_unit_sp.get())
+            return &m_compile_unit_infos[i];
+    }
+    return NULL;
+}
+
+
+size_t
+SymbolFileDWARFDebugMap::GetCompUnitInfosForModule (const lldb_private::Module *module, std::vector<CompileUnitInfo *>& cu_infos)
+{
+    const uint32_t cu_count = GetNumCompileUnits();
+    for (uint32_t i=0; i<cu_count; ++i)
+    {
+        if (module == GetModuleByCompUnitInfo (&m_compile_unit_infos[i]))
+            cu_infos.push_back (&m_compile_unit_infos[i]);
+    }
+    return cu_infos.size();
+}
+
+lldb::LanguageType
+SymbolFileDWARFDebugMap::ParseCompileUnitLanguage (const SymbolContext& sc)
+{
+    SymbolFileDWARF *oso_dwarf = GetSymbolFile (sc);
+    if (oso_dwarf)
+        return oso_dwarf->ParseCompileUnitLanguage (sc);
+    return eLanguageTypeUnknown;
+}
+
+size_t
+SymbolFileDWARFDebugMap::ParseCompileUnitFunctions (const SymbolContext& sc)
+{
+    SymbolFileDWARF *oso_dwarf = GetSymbolFile (sc);
+    if (oso_dwarf)
+        return oso_dwarf->ParseCompileUnitFunctions (sc);
+    return 0;
+}
+
+bool
+SymbolFileDWARFDebugMap::ParseCompileUnitLineTable (const SymbolContext& sc)
+{
+    SymbolFileDWARF *oso_dwarf = GetSymbolFile (sc);
+    if (oso_dwarf)
+        return oso_dwarf->ParseCompileUnitLineTable (sc);
+    return false;
+}
+
+bool
+SymbolFileDWARFDebugMap::ParseCompileUnitSupportFiles (const SymbolContext& sc, FileSpecList &support_files)
+{
+    SymbolFileDWARF *oso_dwarf = GetSymbolFile (sc);
+    if (oso_dwarf)
+        return oso_dwarf->ParseCompileUnitSupportFiles (sc, support_files);
+    return false;
+}
+
+
+size_t
+SymbolFileDWARFDebugMap::ParseFunctionBlocks (const SymbolContext& sc)
+{
+    SymbolFileDWARF *oso_dwarf = GetSymbolFile (sc);
+    if (oso_dwarf)
+        return oso_dwarf->ParseFunctionBlocks (sc);
+    return 0;
+}
+
+
+size_t
+SymbolFileDWARFDebugMap::ParseTypes (const SymbolContext& sc)
+{
+    SymbolFileDWARF *oso_dwarf = GetSymbolFile (sc);
+    if (oso_dwarf)
+        return oso_dwarf->ParseTypes (sc);
+    return 0;
+}
+
+
+size_t
+SymbolFileDWARFDebugMap::ParseVariablesForContext (const SymbolContext& sc)
+{
+    SymbolFileDWARF *oso_dwarf = GetSymbolFile (sc);
+    if (oso_dwarf)
+        return oso_dwarf->ParseVariablesForContext (sc);
+    return 0;
+}
+
+
+
+Type*
+SymbolFileDWARFDebugMap::ResolveTypeUID(lldb::user_id_t type_uid)
+{
+    const uint64_t oso_idx = GetOSOIndexFromUserID (type_uid);
+    SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex (oso_idx);
+    if (oso_dwarf)
+        return oso_dwarf->ResolveTypeUID (type_uid);
+    return NULL;
+}
+
+bool
+SymbolFileDWARFDebugMap::ResolveClangOpaqueTypeDefinition (ClangASTType& clang_type)
+{
+    // We have a struct/union/class/enum that needs to be fully resolved.
+    return false;
+}
+
+uint32_t
+SymbolFileDWARFDebugMap::ResolveSymbolContext (const Address& exe_so_addr, uint32_t resolve_scope, SymbolContext& sc)
+{
+    uint32_t resolved_flags = 0;
+    Symtab* symtab = m_obj_file->GetSymtab();
+    if (symtab)
+    {
+        const addr_t exe_file_addr = exe_so_addr.GetFileAddress();
+
+        const DebugMap::Entry *debug_map_entry = m_debug_map.FindEntryThatContains (exe_file_addr);
+        if (debug_map_entry)
+        {
+
+            sc.symbol = symtab->SymbolAtIndex(debug_map_entry->data.GetExeSymbolIndex());
+
+            if (sc.symbol != NULL)
+            {
+                resolved_flags |= eSymbolContextSymbol;
+
+                uint32_t oso_idx = 0;
+                CompileUnitInfo* comp_unit_info = GetCompileUnitInfoForSymbolWithID (sc.symbol->GetID(), &oso_idx);
+                if (comp_unit_info)
+                {
+                    comp_unit_info->GetFileRangeMap(this);
+                    Module *oso_module = GetModuleByCompUnitInfo (comp_unit_info);
+                    if (oso_module)
+                    {
+                        lldb::addr_t oso_file_addr = exe_file_addr - debug_map_entry->GetRangeBase() + debug_map_entry->data.GetOSOFileAddress();
+                        Address oso_so_addr;
+                        if (oso_module->ResolveFileAddress(oso_file_addr, oso_so_addr))
+                        {
+                            resolved_flags |= oso_module->GetSymbolVendor()->ResolveSymbolContext (oso_so_addr, resolve_scope, sc);
+                        }
+                    }
+                }
+            }
+        }
+    }
+    return resolved_flags;
+}
+
+
+uint32_t
+SymbolFileDWARFDebugMap::ResolveSymbolContext (const FileSpec& file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list)
+{
+    const uint32_t initial = sc_list.GetSize();
+    const uint32_t cu_count = GetNumCompileUnits();
+
+    for (uint32_t i=0; i<cu_count; ++i)
+    {
+        // If we are checking for inlines, then we need to look through all
+        // compile units no matter if "file_spec" matches.
+        bool resolve = check_inlines;
+        
+        if (!resolve)
+        {
+            FileSpec so_file_spec;
+            if (GetFileSpecForSO (i, so_file_spec))
+            {
+                // Match the full path if the incoming file_spec has a directory (not just a basename)
+                const bool full_match = file_spec.GetDirectory();
+                resolve = FileSpec::Equal (file_spec, so_file_spec, full_match);
+            }
+        }
+        if (resolve)
+        {
+            SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex (i);
+            if (oso_dwarf)
+                oso_dwarf->ResolveSymbolContext(file_spec, line, check_inlines, resolve_scope, sc_list);
+        }
+    }
+    return sc_list.GetSize() - initial;
+}
+
+uint32_t
+SymbolFileDWARFDebugMap::PrivateFindGlobalVariables
+(
+    const ConstString &name,
+    const ClangNamespaceDecl *namespace_decl,
+    const std::vector<uint32_t> &indexes,   // Indexes into the symbol table that match "name"
+    uint32_t max_matches,
+    VariableList& variables
+)
+{
+    const uint32_t original_size = variables.GetSize();
+    const size_t match_count = indexes.size();
+    for (size_t i=0; i<match_count; ++i)
+    {
+        uint32_t oso_idx;
+        CompileUnitInfo* comp_unit_info = GetCompileUnitInfoForSymbolWithIndex (indexes[i], &oso_idx);
+        if (comp_unit_info)
+        {
+            SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex (oso_idx);
+            if (oso_dwarf)
+            {
+                if (oso_dwarf->FindGlobalVariables(name, namespace_decl, true, max_matches, variables))
+                    if (variables.GetSize() > max_matches)
+                        break;
+            }
+        }
+    }
+    return variables.GetSize() - original_size;
+}
+
+uint32_t
+SymbolFileDWARFDebugMap::FindGlobalVariables (const ConstString &name, const ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, VariableList& variables)
+{
+
+    // If we aren't appending the results to this list, then clear the list
+    if (!append)
+        variables.Clear();
+
+    // Remember how many variables are in the list before we search in case
+    // we are appending the results to a variable list.
+    const uint32_t original_size = variables.GetSize();
+
+    uint32_t total_matches = 0;
+    SymbolFileDWARF *oso_dwarf;
+    for (uint32_t oso_idx = 0; ((oso_dwarf = GetSymbolFileByOSOIndex (oso_idx)) != NULL); ++oso_idx)
+    {
+        const uint32_t oso_matches = oso_dwarf->FindGlobalVariables (name,
+                                                                     namespace_decl,
+                                                                     true, 
+                                                                     max_matches, 
+                                                                     variables);
+        if (oso_matches > 0)
+        {
+            total_matches += oso_matches;
+
+            // Are we getting all matches?
+            if (max_matches == UINT32_MAX)
+                continue;   // Yep, continue getting everything
+
+            // If we have found enough matches, lets get out
+            if (max_matches >= total_matches)
+                break;
+
+            // Update the max matches for any subsequent calls to find globals
+            // in any other object files with DWARF
+            max_matches -= oso_matches;
+        }
+    }
+    // Return the number of variable that were appended to the list
+    return variables.GetSize() - original_size;
+}
+
+
+uint32_t
+SymbolFileDWARFDebugMap::FindGlobalVariables (const RegularExpression& regex, bool append, uint32_t max_matches, VariableList& variables)
+{
+    // If we aren't appending the results to this list, then clear the list
+    if (!append)
+        variables.Clear();
+
+    // Remember how many variables are in the list before we search in case
+    // we are appending the results to a variable list.
+    const uint32_t original_size = variables.GetSize();
+
+    uint32_t total_matches = 0;
+    SymbolFileDWARF *oso_dwarf;
+    for (uint32_t oso_idx = 0; ((oso_dwarf = GetSymbolFileByOSOIndex (oso_idx)) != NULL); ++oso_idx)
+    {
+        const uint32_t oso_matches = oso_dwarf->FindGlobalVariables (regex, 
+                                                                     true, 
+                                                                     max_matches, 
+                                                                     variables);
+        if (oso_matches > 0)
+        {
+            total_matches += oso_matches;
+
+            // Are we getting all matches?
+            if (max_matches == UINT32_MAX)
+                continue;   // Yep, continue getting everything
+
+            // If we have found enough matches, lets get out
+            if (max_matches >= total_matches)
+                break;
+
+            // Update the max matches for any subsequent calls to find globals
+            // in any other object files with DWARF
+            max_matches -= oso_matches;
+        }
+    }
+    // Return the number of variable that were appended to the list
+    return variables.GetSize() - original_size;
+}
+
+
+int
+SymbolFileDWARFDebugMap::SymbolContainsSymbolWithIndex (uint32_t *symbol_idx_ptr, const CompileUnitInfo *comp_unit_info)
+{
+    const uint32_t symbol_idx = *symbol_idx_ptr;
+
+    if (symbol_idx < comp_unit_info->first_symbol_index)
+        return -1;
+
+    if (symbol_idx <= comp_unit_info->last_symbol_index)
+        return 0;
+
+    return 1;
+}
+
+
+int
+SymbolFileDWARFDebugMap::SymbolContainsSymbolWithID (user_id_t *symbol_idx_ptr, const CompileUnitInfo *comp_unit_info)
+{
+    const user_id_t symbol_id = *symbol_idx_ptr;
+
+    if (symbol_id < comp_unit_info->first_symbol_id)
+        return -1;
+
+    if (symbol_id <= comp_unit_info->last_symbol_id)
+        return 0;
+
+    return 1;
+}
+
+
+SymbolFileDWARFDebugMap::CompileUnitInfo*
+SymbolFileDWARFDebugMap::GetCompileUnitInfoForSymbolWithIndex (uint32_t symbol_idx, uint32_t *oso_idx_ptr)
+{
+    const uint32_t oso_index_count = m_compile_unit_infos.size();
+    CompileUnitInfo *comp_unit_info = NULL;
+    if (oso_index_count)
+    {
+        comp_unit_info = (CompileUnitInfo*)bsearch(&symbol_idx, 
+                                                   &m_compile_unit_infos[0], 
+                                                   m_compile_unit_infos.size(), 
+                                                   sizeof(CompileUnitInfo), 
+                                                   (ComparisonFunction)SymbolContainsSymbolWithIndex);
+    }
+
+    if (oso_idx_ptr)
+    {
+        if (comp_unit_info != NULL)
+            *oso_idx_ptr = comp_unit_info - &m_compile_unit_infos[0];
+        else
+            *oso_idx_ptr = UINT32_MAX;
+    }
+    return comp_unit_info;
+}
+
+SymbolFileDWARFDebugMap::CompileUnitInfo*
+SymbolFileDWARFDebugMap::GetCompileUnitInfoForSymbolWithID (user_id_t symbol_id, uint32_t *oso_idx_ptr)
+{
+    const uint32_t oso_index_count = m_compile_unit_infos.size();
+    CompileUnitInfo *comp_unit_info = NULL;
+    if (oso_index_count)
+    {
+        comp_unit_info = (CompileUnitInfo*)::bsearch (&symbol_id, 
+                                                      &m_compile_unit_infos[0], 
+                                                      m_compile_unit_infos.size(), 
+                                                      sizeof(CompileUnitInfo), 
+                                                      (ComparisonFunction)SymbolContainsSymbolWithID);
+    }
+
+    if (oso_idx_ptr)
+    {
+        if (comp_unit_info != NULL)
+            *oso_idx_ptr = comp_unit_info - &m_compile_unit_infos[0];
+        else
+            *oso_idx_ptr = UINT32_MAX;
+    }
+    return comp_unit_info;
+}
+
+
+static void
+RemoveFunctionsWithModuleNotEqualTo (const ModuleSP &module_sp, SymbolContextList &sc_list, uint32_t start_idx)
+{
+    // We found functions in .o files. Not all functions in the .o files
+    // will have made it into the final output file. The ones that did
+    // make it into the final output file will have a section whose module
+    // matches the module from the ObjectFile for this SymbolFile. When
+    // the modules don't match, then we have something that was in a
+    // .o file, but doesn't map to anything in the final executable.
+    uint32_t i=start_idx;
+    while (i < sc_list.GetSize())
+    {
+        SymbolContext sc;
+        sc_list.GetContextAtIndex(i, sc);
+        if (sc.function)
+        {
+            const SectionSP section_sp (sc.function->GetAddressRange().GetBaseAddress().GetSection());
+            if (section_sp->GetModule() != module_sp)
+            {
+                sc_list.RemoveContextAtIndex(i);
+                continue;
+            }
+        }
+        ++i;
+    }
+}
+
+uint32_t
+SymbolFileDWARFDebugMap::FindFunctions(const ConstString &name, const ClangNamespaceDecl *namespace_decl, uint32_t name_type_mask, bool include_inlines, bool append, SymbolContextList& sc_list)
+{
+    Timer scoped_timer (__PRETTY_FUNCTION__,
+                        "SymbolFileDWARFDebugMap::FindFunctions (name = %s)",
+                        name.GetCString());
+
+    uint32_t initial_size = 0;
+    if (append)
+        initial_size = sc_list.GetSize();
+    else
+        sc_list.Clear();
+
+    uint32_t oso_idx = 0;
+    SymbolFileDWARF *oso_dwarf;
+    while ((oso_dwarf = GetSymbolFileByOSOIndex (oso_idx++)) != NULL)
+    {
+        uint32_t sc_idx = sc_list.GetSize();
+        if (oso_dwarf->FindFunctions(name, namespace_decl, name_type_mask, include_inlines, true, sc_list))
+        {
+            RemoveFunctionsWithModuleNotEqualTo (m_obj_file->GetModule(), sc_list, sc_idx);
+        }
+    }
+
+    return sc_list.GetSize() - initial_size;
+}
+
+
+uint32_t
+SymbolFileDWARFDebugMap::FindFunctions (const RegularExpression& regex, bool include_inlines, bool append, SymbolContextList& sc_list)
+{
+    Timer scoped_timer (__PRETTY_FUNCTION__,
+                        "SymbolFileDWARFDebugMap::FindFunctions (regex = '%s')",
+                        regex.GetText());
+
+    uint32_t initial_size = 0;
+    if (append)
+        initial_size = sc_list.GetSize();
+    else
+        sc_list.Clear();
+
+    uint32_t oso_idx = 0;
+    SymbolFileDWARF *oso_dwarf;
+    while ((oso_dwarf = GetSymbolFileByOSOIndex (oso_idx++)) != NULL)
+    {
+        uint32_t sc_idx = sc_list.GetSize();
+        
+        if (oso_dwarf->FindFunctions(regex, include_inlines, true, sc_list))
+        {
+            RemoveFunctionsWithModuleNotEqualTo (m_obj_file->GetModule(), sc_list, sc_idx);
+        }
+    }
+
+    return sc_list.GetSize() - initial_size;
+}
+
+size_t
+SymbolFileDWARFDebugMap::GetTypes (SymbolContextScope *sc_scope,
+                                   uint32_t type_mask,
+                                   TypeList &type_list)
+{
+    Timer scoped_timer (__PRETTY_FUNCTION__,
+                        "SymbolFileDWARFDebugMap::GetTypes (type_mask = 0x%8.8x)",
+                        type_mask);
+    
+    
+    uint32_t initial_size = type_list.GetSize();
+    SymbolFileDWARF *oso_dwarf = NULL;
+    if (sc_scope)
+    {
+        SymbolContext sc;
+        sc_scope->CalculateSymbolContext(&sc);
+        
+        CompileUnitInfo *cu_info = GetCompUnitInfo (sc);
+        if (cu_info)
+        {
+            oso_dwarf = GetSymbolFileByCompUnitInfo (cu_info);
+            if (oso_dwarf)
+                oso_dwarf->GetTypes (sc_scope, type_mask, type_list);
+        }
+    }
+    else
+    {
+        uint32_t oso_idx = 0;
+        while ((oso_dwarf = GetSymbolFileByOSOIndex (oso_idx++)) != NULL)
+        {
+            oso_dwarf->GetTypes (sc_scope, type_mask, type_list);
+        }
+    }
+    return type_list.GetSize() - initial_size;
+}
+
+
+TypeSP
+SymbolFileDWARFDebugMap::FindDefinitionTypeForDWARFDeclContext (const DWARFDeclContext &die_decl_ctx)
+{
+    TypeSP type_sp;
+    SymbolFileDWARF *oso_dwarf;
+    for (uint32_t oso_idx = 0; ((oso_dwarf = GetSymbolFileByOSOIndex (oso_idx)) != NULL); ++oso_idx)
+    {
+        type_sp = oso_dwarf->FindDefinitionTypeForDWARFDeclContext (die_decl_ctx);
+        if (type_sp)
+            break;
+    }
+    return type_sp;
+}
+
+
+
+bool
+SymbolFileDWARFDebugMap::Supports_DW_AT_APPLE_objc_complete_type (SymbolFileDWARF *skip_dwarf_oso)
+{
+    if (m_supports_DW_AT_APPLE_objc_complete_type == eLazyBoolCalculate)
+    {
+        m_supports_DW_AT_APPLE_objc_complete_type = eLazyBoolNo;
+        SymbolFileDWARF *oso_dwarf;
+        for (uint32_t oso_idx = 0; ((oso_dwarf = GetSymbolFileByOSOIndex (oso_idx)) != NULL); ++oso_idx)
+        {
+            if (skip_dwarf_oso != oso_dwarf && oso_dwarf->Supports_DW_AT_APPLE_objc_complete_type(NULL))
+            {
+                m_supports_DW_AT_APPLE_objc_complete_type = eLazyBoolYes;
+                break;
+            }
+        }
+    }
+    return m_supports_DW_AT_APPLE_objc_complete_type == eLazyBoolYes;
+}
+
+TypeSP
+SymbolFileDWARFDebugMap::FindCompleteObjCDefinitionTypeForDIE (const DWARFDebugInfoEntry *die, 
+                                                               const ConstString &type_name,
+                                                               bool must_be_implementation)
+{
+    TypeSP type_sp;
+    SymbolFileDWARF *oso_dwarf;
+    for (uint32_t oso_idx = 0; ((oso_dwarf = GetSymbolFileByOSOIndex (oso_idx)) != NULL); ++oso_idx)
+    {
+        type_sp = oso_dwarf->FindCompleteObjCDefinitionTypeForDIE (die, type_name, must_be_implementation);
+        if (type_sp)
+            break;
+    }
+    return type_sp;
+}
+
+uint32_t
+SymbolFileDWARFDebugMap::FindTypes 
+(
+    const SymbolContext& sc, 
+    const ConstString &name,
+    const ClangNamespaceDecl *namespace_decl,
+    bool append, 
+    uint32_t max_matches, 
+    TypeList& types
+)
+{
+    if (!append)
+        types.Clear();
+
+    const uint32_t initial_types_size = types.GetSize();
+    SymbolFileDWARF *oso_dwarf;
+
+    if (sc.comp_unit)
+    {
+        oso_dwarf = GetSymbolFile (sc);
+        if (oso_dwarf)
+            return oso_dwarf->FindTypes (sc, name, namespace_decl, append, max_matches, types);
+    }
+    else
+    {
+        uint32_t oso_idx = 0;
+        while ((oso_dwarf = GetSymbolFileByOSOIndex (oso_idx++)) != NULL)
+            oso_dwarf->FindTypes (sc, name, namespace_decl, append, max_matches, types);
+    }
+
+    return types.GetSize() - initial_types_size;
+}
+
+//
+//uint32_t
+//SymbolFileDWARFDebugMap::FindTypes (const SymbolContext& sc, const RegularExpression& regex, bool append, uint32_t max_matches, Type::Encoding encoding, lldb::user_id_t udt_uid, TypeList& types)
+//{
+//  SymbolFileDWARF *oso_dwarf = GetSymbolFile (sc);
+//  if (oso_dwarf)
+//      return oso_dwarf->FindTypes (sc, regex, append, max_matches, encoding, udt_uid, types);
+//  return 0;
+//}
+
+
+ClangNamespaceDecl
+SymbolFileDWARFDebugMap::FindNamespace (const lldb_private::SymbolContext& sc, 
+                                        const lldb_private::ConstString &name,
+                                        const ClangNamespaceDecl *parent_namespace_decl)
+{
+    ClangNamespaceDecl matching_namespace;
+    SymbolFileDWARF *oso_dwarf;
+
+    if (sc.comp_unit)
+    {
+        oso_dwarf = GetSymbolFile (sc);
+        if (oso_dwarf)
+            matching_namespace = oso_dwarf->FindNamespace (sc, name, parent_namespace_decl);
+    }
+    else
+    {
+        for (uint32_t oso_idx = 0; 
+             ((oso_dwarf = GetSymbolFileByOSOIndex (oso_idx)) != NULL); 
+             ++oso_idx)
+        {
+            matching_namespace = oso_dwarf->FindNamespace (sc, name, parent_namespace_decl);
+
+            if (matching_namespace)
+                break;
+        }
+    }
+
+    return matching_namespace;
+}
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+lldb_private::ConstString
+SymbolFileDWARFDebugMap::GetPluginName()
+{
+    return GetPluginNameStatic();
+}
+
+uint32_t
+SymbolFileDWARFDebugMap::GetPluginVersion()
+{
+    return 1;
+}
+
+lldb::CompUnitSP
+SymbolFileDWARFDebugMap::GetCompileUnit (SymbolFileDWARF *oso_dwarf)
+{
+    if (oso_dwarf)
+    {
+        const uint32_t cu_count = GetNumCompileUnits();
+        for (uint32_t cu_idx=0; cu_idx<cu_count; ++cu_idx)
+        {
+            SymbolFileDWARF *oso_symfile = GetSymbolFileByCompUnitInfo (&m_compile_unit_infos[cu_idx]);
+            if (oso_symfile == oso_dwarf)
+            {
+                if (!m_compile_unit_infos[cu_idx].compile_unit_sp)
+                    m_compile_unit_infos[cu_idx].compile_unit_sp = ParseCompileUnitAtIndex (cu_idx);
+
+                return m_compile_unit_infos[cu_idx].compile_unit_sp;
+            }
+        }
+    }
+    assert(!"this shouldn't happen");
+    return lldb::CompUnitSP();
+}
+
+SymbolFileDWARFDebugMap::CompileUnitInfo *
+SymbolFileDWARFDebugMap::GetCompileUnitInfo (SymbolFileDWARF *oso_dwarf)
+{
+    if (oso_dwarf)
+    {
+        const uint32_t cu_count = GetNumCompileUnits();
+        for (uint32_t cu_idx=0; cu_idx<cu_count; ++cu_idx)
+        {
+            SymbolFileDWARF *oso_symfile = GetSymbolFileByCompUnitInfo (&m_compile_unit_infos[cu_idx]);
+            if (oso_symfile == oso_dwarf)
+            {
+                return &m_compile_unit_infos[cu_idx];
+            }
+        }
+    }
+    return NULL;
+}
+
+
+void
+SymbolFileDWARFDebugMap::SetCompileUnit (SymbolFileDWARF *oso_dwarf, const CompUnitSP &cu_sp)
+{
+    if (oso_dwarf)
+    {
+        const uint32_t cu_count = GetNumCompileUnits();
+        for (uint32_t cu_idx=0; cu_idx<cu_count; ++cu_idx)
+        {
+            SymbolFileDWARF *oso_symfile = GetSymbolFileByCompUnitInfo (&m_compile_unit_infos[cu_idx]);
+            if (oso_symfile == oso_dwarf)
+            {
+                if (m_compile_unit_infos[cu_idx].compile_unit_sp)
+                {
+                    assert (m_compile_unit_infos[cu_idx].compile_unit_sp.get() == cu_sp.get());
+                }
+                else
+                {
+                    m_compile_unit_infos[cu_idx].compile_unit_sp = cu_sp;
+                    m_obj_file->GetModule()->GetSymbolVendor()->SetCompileUnitAtIndex(cu_idx, cu_sp);
+                }
+            }
+        }
+    }
+}
+
+
+void
+SymbolFileDWARFDebugMap::CompleteTagDecl (void *baton, clang::TagDecl *decl)
+{
+    SymbolFileDWARFDebugMap *symbol_file_dwarf = (SymbolFileDWARFDebugMap *)baton;
+    ClangASTType clang_type = symbol_file_dwarf->GetClangASTContext().GetTypeForDecl (decl);
+    if (clang_type)
+    {
+        SymbolFileDWARF *oso_dwarf;
+
+        for (uint32_t oso_idx = 0; ((oso_dwarf = symbol_file_dwarf->GetSymbolFileByOSOIndex (oso_idx)) != NULL); ++oso_idx)
+        {
+            if (oso_dwarf->HasForwardDeclForClangType (clang_type))
+            {
+                oso_dwarf->ResolveClangOpaqueTypeDefinition (clang_type);
+                return;
+            }
+        }
+    }
+}
+
+void
+SymbolFileDWARFDebugMap::CompleteObjCInterfaceDecl (void *baton, clang::ObjCInterfaceDecl *decl)
+{
+    SymbolFileDWARFDebugMap *symbol_file_dwarf = (SymbolFileDWARFDebugMap *)baton;
+    ClangASTType clang_type = symbol_file_dwarf->GetClangASTContext().GetTypeForDecl (decl);
+    if (clang_type)
+    {
+        SymbolFileDWARF *oso_dwarf;
+
+        for (uint32_t oso_idx = 0; ((oso_dwarf = symbol_file_dwarf->GetSymbolFileByOSOIndex (oso_idx)) != NULL); ++oso_idx)
+        {
+            if (oso_dwarf->HasForwardDeclForClangType (clang_type))
+            {
+                oso_dwarf->ResolveClangOpaqueTypeDefinition (clang_type);
+                return;
+            }
+        }
+    }
+}
+
+bool 
+SymbolFileDWARFDebugMap::LayoutRecordType (void *baton, 
+                                           const clang::RecordDecl *record_decl,
+                                           uint64_t &size, 
+                                           uint64_t &alignment,
+                                           llvm::DenseMap <const clang::FieldDecl *, uint64_t> &field_offsets,
+                                           llvm::DenseMap <const clang::CXXRecordDecl *, clang::CharUnits> &base_offsets,
+                                           llvm::DenseMap <const clang::CXXRecordDecl *, clang::CharUnits> &vbase_offsets)
+{
+    SymbolFileDWARFDebugMap *symbol_file_dwarf = (SymbolFileDWARFDebugMap *)baton;
+    SymbolFileDWARF *oso_dwarf;
+    for (uint32_t oso_idx = 0; ((oso_dwarf = symbol_file_dwarf->GetSymbolFileByOSOIndex (oso_idx)) != NULL); ++oso_idx)
+    {
+        if (oso_dwarf->LayoutRecordType (record_decl, size, alignment, field_offsets, base_offsets, vbase_offsets))
+            return true;
+    }
+    return false;
+}
+
+
+
+clang::DeclContext*
+SymbolFileDWARFDebugMap::GetClangDeclContextContainingTypeUID (lldb::user_id_t type_uid)
+{
+    const uint64_t oso_idx = GetOSOIndexFromUserID (type_uid);
+    SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex (oso_idx);
+    if (oso_dwarf)
+        return oso_dwarf->GetClangDeclContextContainingTypeUID (type_uid);
+    return NULL;
+}
+
+clang::DeclContext*
+SymbolFileDWARFDebugMap::GetClangDeclContextForTypeUID (const lldb_private::SymbolContext &sc, lldb::user_id_t type_uid)
+{
+    const uint64_t oso_idx = GetOSOIndexFromUserID (type_uid);
+    SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex (oso_idx);
+    if (oso_dwarf)
+        return oso_dwarf->GetClangDeclContextForTypeUID (sc, type_uid);
+    return NULL;
+}
+
+bool
+SymbolFileDWARFDebugMap::AddOSOFileRange (CompileUnitInfo *cu_info,
+                                          lldb::addr_t exe_file_addr,
+                                          lldb::addr_t oso_file_addr,
+                                          lldb::addr_t oso_byte_size)
+{
+    const uint32_t debug_map_idx = m_debug_map.FindEntryIndexThatContains(exe_file_addr);
+    if (debug_map_idx != UINT32_MAX)
+    {
+        DebugMap::Entry *debug_map_entry = m_debug_map.FindEntryThatContains(exe_file_addr);
+        debug_map_entry->data.SetOSOFileAddress(oso_file_addr);
+        cu_info->file_range_map.Append(FileRangeMap::Entry(oso_file_addr, oso_byte_size, exe_file_addr));
+        return true;
+    }
+    return false;
+}
+
+void
+SymbolFileDWARFDebugMap::FinalizeOSOFileRanges (CompileUnitInfo *cu_info)
+{
+    cu_info->file_range_map.Sort();
+#if defined(DEBUG_OSO_DMAP)
+    const FileRangeMap &oso_file_range_map = cu_info->GetFileRangeMap(this);
+    const size_t n = oso_file_range_map.GetSize();
+    printf ("SymbolFileDWARFDebugMap::FinalizeOSOFileRanges (cu_info = %p) %s\n",
+            cu_info,
+            cu_info->oso_sp->module_sp->GetFileSpec().GetPath().c_str());
+    for (size_t i=0; i<n; ++i)
+    {
+        const FileRangeMap::Entry &entry = oso_file_range_map.GetEntryRef(i);
+        printf ("oso [0x%16.16" PRIx64 " - 0x%16.16" PRIx64 ") ==> exe [0x%16.16" PRIx64 " - 0x%16.16" PRIx64 ")\n",
+                entry.GetRangeBase(), entry.GetRangeEnd(),
+                entry.data, entry.data + entry.GetByteSize());
+    }
+#endif
+}
+
+lldb::addr_t
+SymbolFileDWARFDebugMap::LinkOSOFileAddress (SymbolFileDWARF *oso_symfile, lldb::addr_t oso_file_addr)
+{
+    CompileUnitInfo *cu_info = GetCompileUnitInfo (oso_symfile);
+    if (cu_info)
+    {
+        const FileRangeMap::Entry *oso_range_entry = cu_info->GetFileRangeMap(this).FindEntryThatContains(oso_file_addr);
+        if (oso_range_entry)
+        {
+            const DebugMap::Entry *debug_map_entry = m_debug_map.FindEntryThatContains(oso_range_entry->data);
+            if (debug_map_entry)
+            {
+                const lldb::addr_t offset = oso_file_addr - oso_range_entry->GetRangeBase();
+                const lldb::addr_t exe_file_addr = debug_map_entry->GetRangeBase() + offset;
+                return exe_file_addr;
+            }
+        }
+    }
+    return LLDB_INVALID_ADDRESS;
+}
+
+bool
+SymbolFileDWARFDebugMap::LinkOSOAddress (Address &addr)
+{
+    // Make sure this address hasn't been fixed already
+    Module *exe_module = GetObjectFile()->GetModule().get();
+    Module *addr_module = addr.GetModule().get();
+    if (addr_module == exe_module)
+        return true; // Address is already in terms of the main executable module
+
+    CompileUnitInfo *cu_info = GetCompileUnitInfo (GetSymbolFileAsSymbolFileDWARF(addr_module->GetSymbolVendor()->GetSymbolFile()));
+    if (cu_info)
+    {
+        const lldb::addr_t oso_file_addr = addr.GetFileAddress();
+        const FileRangeMap::Entry *oso_range_entry = cu_info->GetFileRangeMap(this).FindEntryThatContains(oso_file_addr);
+        if (oso_range_entry)
+        {
+            const DebugMap::Entry *debug_map_entry = m_debug_map.FindEntryThatContains(oso_range_entry->data);
+            if (debug_map_entry)
+            {
+                const lldb::addr_t offset = oso_file_addr - oso_range_entry->GetRangeBase();
+                const lldb::addr_t exe_file_addr = debug_map_entry->GetRangeBase() + offset;
+                return exe_module->ResolveFileAddress(exe_file_addr, addr);
+            }
+        }
+    }
+    return true;
+}
+
+LineTable *
+SymbolFileDWARFDebugMap::LinkOSOLineTable (SymbolFileDWARF *oso_dwarf, LineTable *line_table)
+{
+    CompileUnitInfo *cu_info = GetCompileUnitInfo (oso_dwarf);
+    if (cu_info)
+        return line_table->LinkLineTable(cu_info->GetFileRangeMap(this));
+    return NULL;
+}
+
+size_t
+SymbolFileDWARFDebugMap::AddOSOARanges (SymbolFileDWARF* dwarf2Data, DWARFDebugAranges* debug_aranges)
+{
+    size_t num_line_entries_added = 0;
+    if (debug_aranges && dwarf2Data)
+    {
+        CompileUnitInfo *compile_unit_info = GetCompileUnitInfo(dwarf2Data);
+        if (compile_unit_info)
+        {
+            const FileRangeMap &file_range_map = compile_unit_info->GetFileRangeMap(this);
+            for (size_t idx = 0;
+                 idx < file_range_map.GetSize();
+                 idx++)
+            {
+                const FileRangeMap::Entry* entry = file_range_map.GetEntryAtIndex(idx);
+                if (entry)
+                {
+                    printf ("[0x%16.16" PRIx64 " - 0x%16.16" PRIx64 ")\n", entry->GetRangeBase(), entry->GetRangeEnd());
+                    debug_aranges->AppendRange(dwarf2Data->GetID(), entry->GetRangeBase(), entry->GetRangeEnd());
+                    num_line_entries_added++;
+                }
+            }
+        }
+    }
+    return num_line_entries_added;
+}
+
diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
new file mode 100644
index 000000000000..06330b98dc19
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
@@ -0,0 +1,420 @@
+//===-- SymbolFileDWARFDebugMap.h ------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SymbolFileDWARF_SymbolFileDWARFDebugMap_h_
+#define SymbolFileDWARF_SymbolFileDWARFDebugMap_h_
+
+
+#include <vector>
+#include <bitset>
+
+#include "clang/AST/CharUnits.h"
+
+#include "lldb/Core/RangeMap.h"
+#include "lldb/Symbol/SymbolFile.h"
+
+#include "UniqueDWARFASTType.h"
+
+class SymbolFileDWARF;
+class DWARFCompileUnit;
+class DWARFDebugAranges;
+class DWARFDebugInfoEntry;
+class DWARFDeclContext;
+class DebugMapModule;
+
+class SymbolFileDWARFDebugMap : public lldb_private::SymbolFile
+{
+public:
+    
+    //------------------------------------------------------------------
+    // Static Functions
+    //------------------------------------------------------------------
+    static void
+    Initialize();
+
+    static void
+    Terminate();
+
+    static lldb_private::ConstString
+    GetPluginNameStatic();
+
+    static const char *
+    GetPluginDescriptionStatic();
+
+    static lldb_private::SymbolFile *
+    CreateInstance (lldb_private::ObjectFile* obj_file);
+
+    //------------------------------------------------------------------
+    // Constructors and Destructors
+    //------------------------------------------------------------------
+                            SymbolFileDWARFDebugMap (lldb_private::ObjectFile* ofile);
+    virtual               ~ SymbolFileDWARFDebugMap ();
+
+    virtual uint32_t        CalculateAbilities ();
+
+    virtual void            InitializeObject();
+
+    //------------------------------------------------------------------
+    // Compile Unit function calls
+    //------------------------------------------------------------------
+    virtual uint32_t        GetNumCompileUnits ();
+    virtual lldb::CompUnitSP ParseCompileUnitAtIndex (uint32_t index);
+
+    virtual lldb::LanguageType ParseCompileUnitLanguage (const lldb_private::SymbolContext& sc);
+    virtual size_t          ParseCompileUnitFunctions (const lldb_private::SymbolContext& sc);
+    virtual bool            ParseCompileUnitLineTable (const lldb_private::SymbolContext& sc);
+    virtual bool            ParseCompileUnitSupportFiles (const lldb_private::SymbolContext& sc, lldb_private::FileSpecList &support_files);
+    virtual size_t          ParseFunctionBlocks (const lldb_private::SymbolContext& sc);
+    virtual size_t          ParseTypes (const lldb_private::SymbolContext& sc);
+    virtual size_t          ParseVariablesForContext (const lldb_private::SymbolContext& sc);
+
+    virtual lldb_private::Type* ResolveTypeUID (lldb::user_id_t type_uid);
+    virtual clang::DeclContext* GetClangDeclContextContainingTypeUID (lldb::user_id_t type_uid);
+    virtual clang::DeclContext* GetClangDeclContextForTypeUID (const lldb_private::SymbolContext &sc, lldb::user_id_t type_uid);
+    virtual bool            ResolveClangOpaqueTypeDefinition (lldb_private::ClangASTType& clang_type);
+    virtual uint32_t        ResolveSymbolContext (const lldb_private::Address& so_addr, uint32_t resolve_scope, lldb_private::SymbolContext& sc);
+    virtual uint32_t        ResolveSymbolContext (const lldb_private::FileSpec& file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, lldb_private::SymbolContextList& sc_list);
+    virtual uint32_t        FindGlobalVariables (const lldb_private::ConstString &name, const lldb_private::ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, lldb_private::VariableList& variables);
+    virtual uint32_t        FindGlobalVariables (const lldb_private::RegularExpression& regex, bool append, uint32_t max_matches, lldb_private::VariableList& variables);
+    virtual uint32_t        FindFunctions (const lldb_private::ConstString &name, const lldb_private::ClangNamespaceDecl *namespace_decl, uint32_t name_type_mask, bool include_inlines, bool append, lldb_private::SymbolContextList& sc_list);
+    virtual uint32_t        FindFunctions (const lldb_private::RegularExpression& regex, bool include_inlines, bool append, lldb_private::SymbolContextList& sc_list);
+    virtual uint32_t        FindTypes (const lldb_private::SymbolContext& sc, const lldb_private::ConstString &name, const lldb_private::ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, lldb_private::TypeList& types);
+    virtual lldb_private::ClangNamespaceDecl
+                            FindNamespace (const lldb_private::SymbolContext& sc,
+                                           const lldb_private::ConstString &name,
+                                           const lldb_private::ClangNamespaceDecl *parent_namespace_decl);
+    virtual size_t          GetTypes (lldb_private::SymbolContextScope *sc_scope,
+                                      uint32_t type_mask,
+                                      lldb_private::TypeList &type_list);
+
+
+    //------------------------------------------------------------------
+    // ClangASTContext callbacks for external source lookups.
+    //------------------------------------------------------------------
+    static void
+    CompleteTagDecl (void *baton, clang::TagDecl *);
+    
+    static void
+    CompleteObjCInterfaceDecl (void *baton, clang::ObjCInterfaceDecl *);
+    
+    static bool 
+    LayoutRecordType (void *baton, 
+                      const clang::RecordDecl *record_decl,
+                      uint64_t &size, 
+                      uint64_t &alignment,
+                      llvm::DenseMap <const clang::FieldDecl *, uint64_t> &field_offsets,
+                      llvm::DenseMap <const clang::CXXRecordDecl *, clang::CharUnits> &base_offsets,
+                      llvm::DenseMap <const clang::CXXRecordDecl *, clang::CharUnits> &vbase_offsets);
+
+
+    //------------------------------------------------------------------
+    // PluginInterface protocol
+    //------------------------------------------------------------------
+    virtual lldb_private::ConstString
+    GetPluginName();
+
+    virtual uint32_t
+    GetPluginVersion();
+
+protected:
+    enum
+    {
+        kHaveInitializedOSOs = (1 << 0),
+        kNumFlags
+    };
+
+    friend class DWARFCompileUnit;
+    friend class SymbolFileDWARF;
+    friend class DebugMapModule;
+    struct OSOInfo
+    {
+        lldb::ModuleSP module_sp;
+        
+        OSOInfo() :
+            module_sp ()
+        {
+        }
+    };
+    
+    typedef std::shared_ptr<OSOInfo> OSOInfoSP;
+
+    typedef lldb_private::RangeDataVector<lldb::addr_t, lldb::addr_t, lldb::addr_t> FileRangeMap;
+
+    //------------------------------------------------------------------
+    // Class specific types
+    //------------------------------------------------------------------
+    struct CompileUnitInfo
+    {
+        lldb_private::FileSpec so_file;
+        lldb_private::ConstString oso_path;
+        lldb_private::TimeValue oso_mod_time;
+        OSOInfoSP oso_sp;
+        lldb::CompUnitSP compile_unit_sp;
+        uint32_t first_symbol_index;
+        uint32_t last_symbol_index;
+        uint32_t first_symbol_id;
+        uint32_t last_symbol_id;
+        FileRangeMap file_range_map;
+        bool file_range_map_valid;
+        
+
+        CompileUnitInfo() :
+            so_file (),
+            oso_path (),
+            oso_mod_time (),
+            oso_sp (),
+            compile_unit_sp (),
+            first_symbol_index (UINT32_MAX),
+            last_symbol_index (UINT32_MAX),
+            first_symbol_id (UINT32_MAX),
+            last_symbol_id (UINT32_MAX),
+            file_range_map (),
+            file_range_map_valid (false)
+        {
+        }
+        
+        const FileRangeMap &
+        GetFileRangeMap(SymbolFileDWARFDebugMap *exe_symfile);
+    };
+
+    //------------------------------------------------------------------
+    // Protected Member Functions
+    //------------------------------------------------------------------
+    void
+    InitOSO ();
+
+    static uint32_t
+    GetOSOIndexFromUserID (lldb::user_id_t uid)
+    {
+        return (uint32_t)((uid >> 32ull) - 1ull);
+    }
+    
+    static SymbolFileDWARF *
+    GetSymbolFileAsSymbolFileDWARF (SymbolFile *sym_file);
+    
+    bool
+    GetFileSpecForSO (uint32_t oso_idx, lldb_private::FileSpec &file_spec);
+
+    CompileUnitInfo *
+    GetCompUnitInfo (const lldb_private::SymbolContext& sc);
+
+    size_t
+    GetCompUnitInfosForModule (const lldb_private::Module *oso_module,
+                               std::vector<CompileUnitInfo *>& cu_infos);
+    
+    lldb_private::Module *
+    GetModuleByCompUnitInfo (CompileUnitInfo *comp_unit_info);
+
+    lldb_private::Module *
+    GetModuleByOSOIndex (uint32_t oso_idx);
+
+    lldb_private::ObjectFile *
+    GetObjectFileByCompUnitInfo (CompileUnitInfo *comp_unit_info);
+
+    lldb_private::ObjectFile *
+    GetObjectFileByOSOIndex (uint32_t oso_idx);
+
+    uint32_t
+    GetCompUnitInfoIndex (const CompileUnitInfo *comp_unit_info);
+
+    SymbolFileDWARF *
+    GetSymbolFile (const lldb_private::SymbolContext& sc);
+
+    SymbolFileDWARF *
+    GetSymbolFileByCompUnitInfo (CompileUnitInfo *comp_unit_info);
+
+    SymbolFileDWARF *
+    GetSymbolFileByOSOIndex (uint32_t oso_idx);
+
+    CompileUnitInfo *
+    GetCompileUnitInfoForSymbolWithIndex (uint32_t symbol_idx, uint32_t *oso_idx_ptr);
+    
+    CompileUnitInfo *
+    GetCompileUnitInfoForSymbolWithID (lldb::user_id_t symbol_id, uint32_t *oso_idx_ptr);
+
+    static int
+    SymbolContainsSymbolWithIndex (uint32_t *symbol_idx_ptr, const CompileUnitInfo *comp_unit_info);
+
+    static int
+    SymbolContainsSymbolWithID (lldb::user_id_t *symbol_idx_ptr, const CompileUnitInfo *comp_unit_info);
+
+    uint32_t
+    PrivateFindGlobalVariables (const lldb_private::ConstString &name,
+                                const lldb_private::ClangNamespaceDecl *namespace_decl,
+                                const std::vector<uint32_t> &name_symbol_indexes,
+                                uint32_t max_matches,
+                                lldb_private::VariableList& variables);
+
+
+    void
+    SetCompileUnit (SymbolFileDWARF *oso_dwarf, const lldb::CompUnitSP &cu_sp);
+
+    lldb::CompUnitSP
+    GetCompileUnit (SymbolFileDWARF *oso_dwarf);
+    
+    CompileUnitInfo *
+    GetCompileUnitInfo (SymbolFileDWARF *oso_dwarf);
+
+    lldb::TypeSP
+    FindDefinitionTypeForDWARFDeclContext (const DWARFDeclContext &die_decl_ctx);    
+
+    bool
+    Supports_DW_AT_APPLE_objc_complete_type (SymbolFileDWARF *skip_dwarf_oso);
+
+    lldb::TypeSP
+    FindCompleteObjCDefinitionTypeForDIE (const DWARFDebugInfoEntry *die, 
+                                          const lldb_private::ConstString &type_name,
+                                          bool must_be_implementation);
+    
+
+    UniqueDWARFASTTypeMap &
+    GetUniqueDWARFASTTypeMap ()
+    {
+        return m_unique_ast_type_map;
+    }
+    
+    
+    //------------------------------------------------------------------
+    // OSOEntry
+    //------------------------------------------------------------------
+    class OSOEntry
+    {
+    public:
+        
+        OSOEntry () :
+        m_exe_sym_idx (UINT32_MAX),
+        m_oso_file_addr (LLDB_INVALID_ADDRESS)
+        {
+        }
+        
+        OSOEntry (uint32_t exe_sym_idx,
+                  lldb::addr_t oso_file_addr) :
+        m_exe_sym_idx (exe_sym_idx),
+        m_oso_file_addr (oso_file_addr)
+        {
+        }
+        
+        uint32_t
+        GetExeSymbolIndex () const
+        {
+            return m_exe_sym_idx;
+        }
+        
+        bool
+        operator < (const OSOEntry &rhs) const
+        {
+            return m_exe_sym_idx < rhs.m_exe_sym_idx;
+        }
+        
+        lldb::addr_t
+        GetOSOFileAddress () const
+        {
+            return m_oso_file_addr;
+        }
+        
+        void
+        SetOSOFileAddress (lldb::addr_t oso_file_addr)
+        {
+            m_oso_file_addr = oso_file_addr;
+        }
+    protected:
+        uint32_t m_exe_sym_idx;
+        lldb::addr_t m_oso_file_addr;
+    };
+
+    typedef lldb_private::RangeDataVector<lldb::addr_t, lldb::addr_t, OSOEntry> DebugMap;
+
+    //------------------------------------------------------------------
+    // Member Variables
+    //------------------------------------------------------------------
+    std::bitset<kNumFlags> m_flags;
+    std::vector<CompileUnitInfo> m_compile_unit_infos;
+    std::vector<uint32_t> m_func_indexes;   // Sorted by address
+    std::vector<uint32_t> m_glob_indexes;
+    std::map<lldb_private::ConstString, OSOInfoSP> m_oso_map;
+    UniqueDWARFASTTypeMap m_unique_ast_type_map;
+    lldb_private::LazyBool m_supports_DW_AT_APPLE_objc_complete_type;
+    DebugMap m_debug_map;
+    
+    //------------------------------------------------------------------
+    // When an object file from the debug map gets parsed in
+    // SymbolFileDWARF, it needs to tell the debug map about the object
+    // files addresses by calling this function once for each N_FUN,
+    // N_GSYM and N_STSYM and after all entries in the debug map have
+    // been matched up, FinalizeOSOFileRanges() should be called.
+    //------------------------------------------------------------------
+    bool
+    AddOSOFileRange (CompileUnitInfo *cu_info,
+                     lldb::addr_t exe_file_addr,
+                     lldb::addr_t oso_file_addr,
+                     lldb::addr_t oso_byte_size);
+    
+    //------------------------------------------------------------------
+    // Called after calling AddOSOFileRange() for each object file debug
+    // map entry to finalize the info for the unlinked compile unit.
+    //------------------------------------------------------------------
+    void
+    FinalizeOSOFileRanges (CompileUnitInfo *cu_info);
+
+    //------------------------------------------------------------------
+    /// Convert \a addr from a .o file address, to an executable address.
+    ///
+    /// @param[in] addr
+    ///     A section offset address from a .o file
+    ///
+    /// @return
+    ///     Returns true if \a addr was converted to be an executable
+    ///     section/offset address, false otherwise.
+    //------------------------------------------------------------------
+    bool
+    LinkOSOAddress (lldb_private::Address &addr);
+    
+    //------------------------------------------------------------------
+    /// Convert a .o file "file address" to an executable "file address".
+    ///
+    /// @param[in] oso_symfile
+    ///     The DWARF symbol file that contains \a oso_file_addr
+    ///
+    /// @param[in] oso_file_addr
+    ///     A .o file "file address" to convert.
+    ///
+    /// @return
+    ///     LLDB_INVALID_ADDRESS if \a oso_file_addr is not in the
+    ///     linked executable, otherwise a valid "file address" from the
+    ///     linked executable that contains the debug map.
+    //------------------------------------------------------------------
+    lldb::addr_t
+    LinkOSOFileAddress (SymbolFileDWARF *oso_symfile, lldb::addr_t oso_file_addr);
+            
+    //------------------------------------------------------------------
+    /// Given a line table full of lines with "file adresses" that are
+    /// for a .o file represented by \a oso_symfile, link a new line table
+    /// and return it.
+    ///
+    /// @param[in] oso_symfile
+    ///     The DWARF symbol file that produced the \a line_table
+    ///
+    /// @param[in] addr
+    ///     A section offset address from a .o file
+    ///
+    /// @return
+    ///     Returns a valid line table full of linked addresses, or NULL
+    ///     if none of the line table adresses exist in the main
+    ///     executable.
+    //------------------------------------------------------------------
+    lldb_private::LineTable *
+    LinkOSOLineTable (SymbolFileDWARF *oso_symfile,
+                      lldb_private::LineTable *line_table);
+    
+    size_t
+    AddOSOARanges (SymbolFileDWARF* dwarf2Data,
+                   DWARFDebugAranges* debug_aranges);
+};
+
+#endif // #ifndef SymbolFileDWARF_SymbolFileDWARFDebugMap_h_
diff --git a/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp b/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp
new file mode 100644
index 000000000000..94044c0feb30
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.cpp
@@ -0,0 +1,94 @@
+//===-- UniqueDWARFASTType.cpp ----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "UniqueDWARFASTType.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Symbol/Declaration.h"
+
+#include "DWARFDebugInfoEntry.h"
+
+bool
+UniqueDWARFASTTypeList::Find 
+(
+    SymbolFileDWARF *symfile,
+    const DWARFCompileUnit *cu,
+    const DWARFDebugInfoEntry *die, 
+    const lldb_private::Declaration &decl,
+    const int32_t byte_size,
+    UniqueDWARFASTType &entry
+) const
+{
+    collection::const_iterator pos, end = m_collection.end();
+    for (pos = m_collection.begin(); pos != end; ++pos)
+    {
+        // Make sure the tags match
+        if (pos->m_die->Tag() == die->Tag())
+        {
+            // Validate byte sizes of both types only if both are valid.
+            if (pos->m_byte_size < 0 || byte_size < 0 || pos->m_byte_size == byte_size)
+            {
+                // Make sure the file and line match
+                if (pos->m_declaration == decl)
+                {
+                    // The type has the same name, and was defined on the same
+                    // file and line. Now verify all of the parent DIEs match.
+                    const DWARFDebugInfoEntry *parent_arg_die = die->GetParent();
+                    const DWARFDebugInfoEntry *parend_pos_die = pos->m_die->GetParent();
+                    bool match = true;
+                    bool done = false;
+                    while (!done && match && parent_arg_die && parend_pos_die)
+                    {
+                        if (parent_arg_die->Tag() == parend_pos_die->Tag())
+                        {
+                            const dw_tag_t tag = parent_arg_die->Tag();
+                            switch (tag)
+                            {
+                            case DW_TAG_class_type:
+                            case DW_TAG_structure_type:
+                            case DW_TAG_union_type:
+                            case DW_TAG_namespace:
+                                {
+                                    const char *parent_arg_die_name = parent_arg_die->GetName(symfile, cu);
+                                    if (parent_arg_die_name == NULL)  // Anonymous (i.e. no-name) struct
+                                    {
+                                        match = false;
+                                    }
+                                    else
+                                    {
+                                        const char *parent_pos_die_name = parend_pos_die->GetName(pos->m_symfile, pos->m_cu);
+                                        if (parent_pos_die_name == NULL || strcmp (parent_arg_die_name, parent_pos_die_name))
+                                            match = false;
+                                    }
+                                }
+                                break;
+                            
+                            case DW_TAG_compile_unit:
+                                done = true;
+                                break;
+                            }
+                        }
+                        parent_arg_die = parent_arg_die->GetParent();
+                        parend_pos_die = parend_pos_die->GetParent();
+                    }
+
+                    if (match)
+                    {
+                        entry = *pos;
+                        return true;
+                    }
+                }
+            }
+        }
+    }
+    return false;
+}
diff --git a/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h b/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h
new file mode 100644
index 000000000000..c85e175235ca
--- /dev/null
+++ b/source/Plugins/SymbolFile/DWARF/UniqueDWARFASTType.h
@@ -0,0 +1,175 @@
+//===-- UniqueDWARFASTType.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_UniqueDWARFASTType_h_
+#define lldb_UniqueDWARFASTType_h_
+
+// C Includes
+// C++ Includes
+#include <vector>
+
+// Other libraries and framework includes
+#include "llvm/ADT/DenseMap.h"
+
+// Project includes
+#include "lldb/Symbol/Declaration.h"
+
+class DWARFCompileUnit;
+class DWARFDebugInfoEntry;
+class SymbolFileDWARF;
+
+class UniqueDWARFASTType
+{
+public:
+	//------------------------------------------------------------------
+	// Constructors and Destructors
+	//------------------------------------------------------------------
+	UniqueDWARFASTType () :
+        m_type_sp (),
+        m_symfile (NULL),
+        m_cu (NULL),
+        m_die (NULL),
+        m_declaration (),
+        m_byte_size (-1) // Set to negative value to make sure we have a valid value
+    {
+    }
+
+	UniqueDWARFASTType (lldb::TypeSP &type_sp,
+                        SymbolFileDWARF *symfile,
+                        DWARFCompileUnit *cu,
+                        DWARFDebugInfoEntry *die,
+                        const lldb_private::Declaration &decl,
+                        int32_t byte_size) :
+        m_type_sp (type_sp),
+        m_symfile (symfile),
+        m_cu (cu),
+        m_die (die),
+        m_declaration (decl),
+        m_byte_size (byte_size)
+    {
+    }
+    
+    UniqueDWARFASTType (const UniqueDWARFASTType &rhs) :
+        m_type_sp (rhs.m_type_sp),
+        m_symfile (rhs.m_symfile),
+        m_cu (rhs.m_cu),
+        m_die (rhs.m_die),
+        m_declaration (rhs.m_declaration),
+        m_byte_size (rhs.m_byte_size)
+    {
+    }
+
+	~UniqueDWARFASTType()
+    {
+    }
+
+    UniqueDWARFASTType &
+    operator= (const UniqueDWARFASTType &rhs)
+    {
+        if (this != &rhs)
+        {
+            m_type_sp = rhs.m_type_sp;
+            m_symfile = rhs.m_symfile;
+            m_cu = rhs.m_cu;
+            m_die = rhs.m_die;
+            m_declaration = rhs.m_declaration;
+            m_byte_size = rhs.m_byte_size;
+        }
+        return *this;
+    }
+
+    lldb::TypeSP m_type_sp;
+    SymbolFileDWARF *m_symfile;
+    const DWARFCompileUnit *m_cu;
+    const DWARFDebugInfoEntry *m_die;
+    lldb_private::Declaration m_declaration;
+    int32_t m_byte_size;
+};
+
+class UniqueDWARFASTTypeList
+{
+public:
+    UniqueDWARFASTTypeList () :
+        m_collection()
+    {
+    }
+    
+    ~UniqueDWARFASTTypeList ()
+    {
+    }
+    
+    uint32_t
+    GetSize()
+    {
+        return (uint32_t)m_collection.size();
+    }
+    
+    void
+    Append (const UniqueDWARFASTType &entry)
+    {
+        m_collection.push_back (entry);
+    }
+    
+    bool
+    Find (SymbolFileDWARF *symfile,
+          const DWARFCompileUnit *cu,
+          const DWARFDebugInfoEntry *die, 
+          const lldb_private::Declaration &decl,
+          const int32_t byte_size,
+          UniqueDWARFASTType &entry) const;
+    
+protected:
+    typedef std::vector<UniqueDWARFASTType> collection;
+    collection m_collection;
+};
+
+class UniqueDWARFASTTypeMap
+{
+public:
+    UniqueDWARFASTTypeMap () :
+        m_collection ()
+    {
+    }
+    
+    ~UniqueDWARFASTTypeMap ()
+    {
+    }
+
+    void
+    Insert (const lldb_private::ConstString &name, 
+            const UniqueDWARFASTType &entry)
+    {
+        m_collection[name.GetCString()].Append (entry);
+    }
+
+    bool
+    Find (const lldb_private::ConstString &name, 
+          SymbolFileDWARF *symfile,
+          const DWARFCompileUnit *cu,
+          const DWARFDebugInfoEntry *die, 
+          const lldb_private::Declaration &decl,
+          const int32_t byte_size,
+          UniqueDWARFASTType &entry) const
+    {
+        const char *unique_name_cstr = name.GetCString();
+        collection::const_iterator pos = m_collection.find (unique_name_cstr);
+        if (pos != m_collection.end())
+        {
+            return pos->second.Find (symfile, cu, die, decl, byte_size, entry);
+        }
+        return false;
+    }
+
+protected:
+    // A unique name string should be used
+    typedef llvm::DenseMap<const char *, UniqueDWARFASTTypeList> collection;
+    collection m_collection;
+};
+
+#endif	// lldb_UniqueDWARFASTType_h_
diff --git a/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp b/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp
new file mode 100644
index 000000000000..9beba517ec83
--- /dev/null
+++ b/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp
@@ -0,0 +1,407 @@
+//===-- SymbolFileSymtab.cpp ------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SymbolFileSymtab.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/RegularExpression.h"
+#include "lldb/Core/Timer.h"
+#include "lldb/Symbol/ClangExternalASTSourceCommon.h"
+#include "lldb/Symbol/CompileUnit.h"
+#include "lldb/Symbol/Function.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/Symbol.h"
+#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Symbol/Symtab.h"
+#include "lldb/Symbol/TypeList.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+void
+SymbolFileSymtab::Initialize()
+{
+    PluginManager::RegisterPlugin (GetPluginNameStatic(),
+                                   GetPluginDescriptionStatic(),
+                                   CreateInstance);
+}
+
+void
+SymbolFileSymtab::Terminate()
+{
+    PluginManager::UnregisterPlugin (CreateInstance);
+}
+
+
+lldb_private::ConstString
+SymbolFileSymtab::GetPluginNameStatic()
+{
+    static ConstString g_name("symtab");
+    return g_name;
+}
+
+const char *
+SymbolFileSymtab::GetPluginDescriptionStatic()
+{
+    return "Reads debug symbols from an object file's symbol table.";
+}
+
+
+SymbolFile*
+SymbolFileSymtab::CreateInstance (ObjectFile* obj_file)
+{
+    return new SymbolFileSymtab(obj_file);
+}
+
+size_t
+SymbolFileSymtab::GetTypes (SymbolContextScope *sc_scope, uint32_t type_mask, lldb_private::TypeList &type_list)
+{
+    return 0;
+}
+
+SymbolFileSymtab::SymbolFileSymtab(ObjectFile* obj_file) :
+    SymbolFile(obj_file),
+    m_source_indexes(),
+    m_func_indexes(),
+    m_code_indexes(),
+    m_objc_class_name_to_index ()
+{
+}
+
+SymbolFileSymtab::~SymbolFileSymtab()
+{
+}
+
+ClangASTContext &       
+SymbolFileSymtab::GetClangASTContext ()
+{    
+    ClangASTContext &ast = m_obj_file->GetModule()->GetClangASTContext();
+    
+    return ast;
+}
+
+uint32_t
+SymbolFileSymtab::CalculateAbilities ()
+{
+    uint32_t abilities = 0;
+    if (m_obj_file)
+    {
+        const Symtab *symtab = m_obj_file->GetSymtab();
+        if (symtab)
+        {
+            //----------------------------------------------------------------------
+            // The snippet of code below will get the indexes the module symbol
+            // table entries that are code, data, or function related (debug info),
+            // sort them by value (address) and dump the sorted symbols.
+            //----------------------------------------------------------------------
+            if (symtab->AppendSymbolIndexesWithType(eSymbolTypeSourceFile, m_source_indexes))
+            {
+                abilities |= CompileUnits;
+            }
+
+            if (symtab->AppendSymbolIndexesWithType(eSymbolTypeCode, Symtab::eDebugYes, Symtab::eVisibilityAny, m_func_indexes))
+            {
+                symtab->SortSymbolIndexesByValue(m_func_indexes, true);
+                abilities |= Functions;
+            }
+
+            if (symtab->AppendSymbolIndexesWithType(eSymbolTypeCode, Symtab::eDebugNo, Symtab::eVisibilityAny, m_code_indexes))
+            {
+                symtab->SortSymbolIndexesByValue(m_code_indexes, true);
+            }
+
+            if (symtab->AppendSymbolIndexesWithType(eSymbolTypeData, m_data_indexes))
+            {
+                symtab->SortSymbolIndexesByValue(m_data_indexes, true);
+                abilities |= GlobalVariables;
+            }
+            
+            lldb_private::Symtab::IndexCollection objc_class_indexes;
+            if (symtab->AppendSymbolIndexesWithType (eSymbolTypeObjCClass, objc_class_indexes))
+            {
+                symtab->AppendSymbolNamesToMap (objc_class_indexes,
+                                                true,
+                                                true,
+                                                m_objc_class_name_to_index);
+                m_objc_class_name_to_index.Sort();
+            }
+        }
+    }
+    return abilities;
+}
+
+uint32_t
+SymbolFileSymtab::GetNumCompileUnits()
+{
+    // If we don't have any source file symbols we will just have one compile unit for
+    // the entire object file
+    if (m_source_indexes.empty())
+        return 0;
+
+    // If we have any source file symbols we will logically orgnize the object symbols
+    // using these.
+    return m_source_indexes.size();
+}
+
+CompUnitSP
+SymbolFileSymtab::ParseCompileUnitAtIndex(uint32_t idx)
+{
+    CompUnitSP cu_sp;
+
+    // If we don't have any source file symbols we will just have one compile unit for
+    // the entire object file
+    if (idx < m_source_indexes.size())
+    {
+        const Symbol *cu_symbol = m_obj_file->GetSymtab()->SymbolAtIndex(m_source_indexes[idx]);
+        if (cu_symbol)
+            cu_sp.reset(new CompileUnit (m_obj_file->GetModule(), NULL, cu_symbol->GetMangled().GetName().AsCString(), 0, eLanguageTypeUnknown));
+    }
+    return cu_sp;
+}
+
+lldb::LanguageType
+SymbolFileSymtab::ParseCompileUnitLanguage (const SymbolContext& sc)
+{
+    return eLanguageTypeUnknown;
+}
+
+
+size_t
+SymbolFileSymtab::ParseCompileUnitFunctions (const SymbolContext &sc)
+{
+    size_t num_added = 0;
+    // We must at least have a valid compile unit
+    assert (sc.comp_unit != NULL);
+    const Symtab *symtab = m_obj_file->GetSymtab();
+    const Symbol *curr_symbol = NULL;
+    const Symbol *next_symbol = NULL;
+//  const char *prefix = m_obj_file->SymbolPrefix();
+//  if (prefix == NULL)
+//      prefix == "";
+//
+//  const uint32_t prefix_len = strlen(prefix);
+
+    // If we don't have any source file symbols we will just have one compile unit for
+    // the entire object file
+    if (m_source_indexes.empty())
+    {
+        // The only time we will have a user ID of zero is when we don't have
+        // and source file symbols and we declare one compile unit for the
+        // entire object file
+        if (!m_func_indexes.empty())
+        {
+
+        }
+
+        if (!m_code_indexes.empty())
+        {
+//          StreamFile s(stdout);
+//          symtab->Dump(&s, m_code_indexes);
+
+            uint32_t idx = 0;   // Index into the indexes
+            const uint32_t num_indexes = m_code_indexes.size();
+            for (idx = 0; idx < num_indexes; ++idx)
+            {
+                uint32_t symbol_idx = m_code_indexes[idx];
+                curr_symbol = symtab->SymbolAtIndex(symbol_idx);
+                if (curr_symbol)
+                {
+                    // Union of all ranges in the function DIE (if the function is discontiguous)
+                    AddressRange func_range(curr_symbol->GetAddress(), 0);
+                    if (func_range.GetBaseAddress().IsSectionOffset())
+                    {
+                        uint32_t symbol_size = curr_symbol->GetByteSize();
+                        if (symbol_size != 0 && !curr_symbol->GetSizeIsSibling())
+                            func_range.SetByteSize(symbol_size);
+                        else if (idx + 1 < num_indexes)
+                        {
+                            next_symbol = symtab->SymbolAtIndex(m_code_indexes[idx + 1]);
+                            if (next_symbol)
+                            {
+                                func_range.SetByteSize(next_symbol->GetAddress().GetOffset() - curr_symbol->GetAddress().GetOffset());
+                            }
+                        }
+
+                        FunctionSP func_sp(new Function(sc.comp_unit,
+                                                            symbol_idx,                 // UserID is the DIE offset
+                                                            LLDB_INVALID_UID,           // We don't have any type info for this function
+                                                            curr_symbol->GetMangled(),  // Linker/mangled name
+                                                            NULL,                       // no return type for a code symbol...
+                                                            func_range));               // first address range
+
+                        if (func_sp.get() != NULL)
+                        {
+                            sc.comp_unit->AddFunction(func_sp);
+                            ++num_added;
+                        }
+                    }
+                }
+            }
+
+        }
+    }
+    else
+    {
+        // We assume we
+    }
+    return num_added;
+}
+
+bool
+SymbolFileSymtab::ParseCompileUnitLineTable (const SymbolContext &sc)
+{
+    return false;
+}
+
+bool
+SymbolFileSymtab::ParseCompileUnitSupportFiles (const SymbolContext& sc, FileSpecList &support_files)
+{
+    return false;
+}
+
+size_t
+SymbolFileSymtab::ParseFunctionBlocks (const SymbolContext &sc)
+{
+    return 0;
+}
+
+
+size_t
+SymbolFileSymtab::ParseTypes (const SymbolContext &sc)
+{
+    return 0;
+}
+
+
+size_t
+SymbolFileSymtab::ParseVariablesForContext (const SymbolContext& sc)
+{
+    return 0;
+}
+
+Type*
+SymbolFileSymtab::ResolveTypeUID(lldb::user_id_t type_uid)
+{
+    return NULL;
+}
+
+bool
+SymbolFileSymtab::ResolveClangOpaqueTypeDefinition (lldb_private::ClangASTType& clang_opaque_type)
+{
+    return false;
+}
+
+ClangNamespaceDecl 
+SymbolFileSymtab::FindNamespace (const SymbolContext& sc, const ConstString &name, const ClangNamespaceDecl *namespace_decl)
+{
+    return ClangNamespaceDecl();
+}
+
+uint32_t
+SymbolFileSymtab::ResolveSymbolContext (const Address& so_addr, uint32_t resolve_scope, SymbolContext& sc)
+{
+    if (m_obj_file->GetSymtab() == NULL)
+        return 0;
+
+    uint32_t resolved_flags = 0;
+    if (resolve_scope & eSymbolContextSymbol)
+    {
+        sc.symbol = m_obj_file->GetSymtab()->FindSymbolContainingFileAddress(so_addr.GetFileAddress());
+        if (sc.symbol)
+            resolved_flags |= eSymbolContextSymbol;
+    }
+    return resolved_flags;
+}
+
+uint32_t
+SymbolFileSymtab::ResolveSymbolContext (const FileSpec& file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list)
+{
+    return 0;
+}
+
+uint32_t
+SymbolFileSymtab::FindGlobalVariables(const ConstString &name, const ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, VariableList& variables)
+{
+    return 0;
+}
+
+uint32_t
+SymbolFileSymtab::FindGlobalVariables(const RegularExpression& regex, bool append, uint32_t max_matches, VariableList& variables)
+{
+    return 0;
+}
+
+uint32_t
+SymbolFileSymtab::FindFunctions(const ConstString &name, const ClangNamespaceDecl *namespace_decl, uint32_t name_type_mask, bool include_inlines,  bool append, SymbolContextList& sc_list)
+{
+    Timer scoped_timer (__PRETTY_FUNCTION__,
+                        "SymbolFileSymtab::FindFunctions (name = '%s')",
+                        name.GetCString());
+    // If we ever support finding STABS or COFF debug info symbols, 
+    // we will need to add support here. We are not trying to find symbols
+    // here, just "lldb_private::Function" objects that come from complete 
+    // debug information. Any symbol queries should go through the symbol
+    // table itself in the module's object file.
+    return 0;
+}
+
+uint32_t
+SymbolFileSymtab::FindFunctions(const RegularExpression& regex, bool include_inlines, bool append, SymbolContextList& sc_list)
+{
+    Timer scoped_timer (__PRETTY_FUNCTION__,
+                        "SymbolFileSymtab::FindFunctions (regex = '%s')",
+                        regex.GetText());
+    // If we ever support finding STABS or COFF debug info symbols, 
+    // we will need to add support here. We are not trying to find symbols
+    // here, just "lldb_private::Function" objects that come from complete 
+    // debug information. Any symbol queries should go through the symbol
+    // table itself in the module's object file.
+    return 0;
+}
+
+static int CountMethodArgs(const char *method_signature)
+{
+    int num_args = 0;
+    
+    for (const char *colon_pos = strchr(method_signature, ':');
+         colon_pos != NULL;
+         colon_pos = strchr(colon_pos + 1, ':'))
+    {
+        num_args++;
+    }
+    
+    return num_args;
+}
+
+uint32_t
+SymbolFileSymtab::FindTypes (const lldb_private::SymbolContext& sc, 
+                             const lldb_private::ConstString &name, 
+                             const ClangNamespaceDecl *namespace_decl, 
+                             bool append, 
+                             uint32_t max_matches, 
+                             lldb_private::TypeList& types)
+{
+    return 0;
+}
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+lldb_private::ConstString
+SymbolFileSymtab::GetPluginName()
+{
+    return GetPluginNameStatic();
+}
+
+uint32_t
+SymbolFileSymtab::GetPluginVersion()
+{
+    return 1;
+}
diff --git a/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h b/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h
new file mode 100644
index 000000000000..914efe6eb3c2
--- /dev/null
+++ b/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.h
@@ -0,0 +1,142 @@
+//===-- SymbolFileSymtab.h --------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_SymbolFileSymtab_h_
+#define liblldb_SymbolFileSymtab_h_
+
+#include "lldb/Symbol/SymbolFile.h"
+#include "lldb/Symbol/Symtab.h"
+#include <vector>
+
+class SymbolFileSymtab : public lldb_private::SymbolFile
+{
+public:
+    //------------------------------------------------------------------
+    // Static Functions
+    //------------------------------------------------------------------
+    static void
+    Initialize();
+
+    static void
+    Terminate();
+
+    static lldb_private::ConstString
+    GetPluginNameStatic();
+
+    static const char *
+    GetPluginDescriptionStatic();
+
+    static lldb_private::SymbolFile*
+    CreateInstance (lldb_private::ObjectFile* obj_file);
+
+    //------------------------------------------------------------------
+    // Constructors and Destructors
+    //------------------------------------------------------------------
+    SymbolFileSymtab(lldb_private::ObjectFile* obj_file);
+
+    virtual
+    ~SymbolFileSymtab();
+
+    virtual uint32_t        CalculateAbilities ();
+
+    //------------------------------------------------------------------
+    // Compile Unit function calls
+    //------------------------------------------------------------------
+    virtual uint32_t
+    GetNumCompileUnits();
+
+    virtual lldb::CompUnitSP
+    ParseCompileUnitAtIndex(uint32_t index);
+
+    virtual lldb::LanguageType
+    ParseCompileUnitLanguage (const lldb_private::SymbolContext& sc);
+
+    virtual size_t
+    ParseCompileUnitFunctions (const lldb_private::SymbolContext& sc);
+
+    virtual bool
+    ParseCompileUnitLineTable (const lldb_private::SymbolContext& sc);
+
+    virtual bool
+    ParseCompileUnitSupportFiles (const lldb_private::SymbolContext& sc, lldb_private::FileSpecList &support_files);
+
+    virtual size_t
+    ParseFunctionBlocks (const lldb_private::SymbolContext& sc);
+
+    virtual size_t
+    ParseTypes (const lldb_private::SymbolContext& sc);
+
+    virtual size_t
+    ParseVariablesForContext (const lldb_private::SymbolContext& sc);
+
+    virtual lldb_private::Type*
+    ResolveTypeUID(lldb::user_id_t type_uid);
+
+    virtual bool
+    ResolveClangOpaqueTypeDefinition (lldb_private::ClangASTType& clang_type);
+
+    virtual uint32_t
+    ResolveSymbolContext (const lldb_private::Address& so_addr, uint32_t resolve_scope, lldb_private::SymbolContext& sc);
+
+    virtual uint32_t
+    ResolveSymbolContext (const lldb_private::FileSpec& file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, lldb_private::SymbolContextList& sc_list);
+
+    virtual uint32_t
+    FindGlobalVariables(const lldb_private::ConstString &name, const lldb_private::ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, lldb_private::VariableList& variables);
+
+    virtual uint32_t
+    FindGlobalVariables(const lldb_private::RegularExpression& regex, bool append, uint32_t max_matches, lldb_private::VariableList& variables);
+
+    virtual uint32_t
+    FindFunctions(const lldb_private::ConstString &name, const lldb_private::ClangNamespaceDecl *namespace_decl, uint32_t name_type_mask, bool include_inlines, bool append, lldb_private::SymbolContextList& sc_list);
+
+    virtual uint32_t
+    FindFunctions(const lldb_private::RegularExpression& regex, bool include_inlines, bool append, lldb_private::SymbolContextList& sc_list);
+
+    virtual uint32_t
+    FindTypes (const lldb_private::SymbolContext& sc,const lldb_private::ConstString &name, const lldb_private::ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, lldb_private::TypeList& types);
+
+    virtual size_t
+    GetTypes (lldb_private::SymbolContextScope *sc_scope,
+              uint32_t type_mask,
+              lldb_private::TypeList &type_list);
+
+    virtual lldb_private::ClangNamespaceDecl
+    FindNamespace (const lldb_private::SymbolContext& sc, 
+                   const lldb_private::ConstString &name, 
+                   const lldb_private::ClangNamespaceDecl *parent_namespace_decl);
+
+    //------------------------------------------------------------------
+    // PluginInterface protocol
+    //------------------------------------------------------------------
+    virtual lldb_private::ConstString
+    GetPluginName();
+
+    virtual uint32_t
+    GetPluginVersion();
+
+protected:
+    typedef std::map<lldb_private::ConstString, lldb::TypeSP> TypeMap;
+
+    lldb_private::Symtab::IndexCollection m_source_indexes;
+    lldb_private::Symtab::IndexCollection m_func_indexes;
+    lldb_private::Symtab::IndexCollection m_code_indexes;
+    lldb_private::Symtab::IndexCollection m_data_indexes;
+    lldb_private::Symtab::NameToIndexMap m_objc_class_name_to_index;
+    TypeMap m_objc_class_types;
+
+    lldb_private::ClangASTContext &
+    GetClangASTContext ();
+    
+private:
+    DISALLOW_COPY_AND_ASSIGN (SymbolFileSymtab);
+};
+
+
+#endif  // liblldb_SymbolFileSymtab_h_
diff --git a/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp b/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp
new file mode 100644
index 000000000000..6500aabdcea3
--- /dev/null
+++ b/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp
@@ -0,0 +1,199 @@
+//===-- SymbolVendorELF.cpp ----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SymbolVendorELF.h"
+
+//#include <libxml/parser.h>
+// #include <libxml/tree.h>
+#include <string.h>
+
+// #include <AvailabilityMacros.h>
+
+#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Section.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Core/Timer.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Host/Symbols.h"
+#include "lldb/Symbol/ObjectFile.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// SymbolVendorELF constructor
+//----------------------------------------------------------------------
+SymbolVendorELF::SymbolVendorELF(const lldb::ModuleSP &module_sp) :
+    SymbolVendor (module_sp)
+{
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+SymbolVendorELF::~SymbolVendorELF()
+{
+}
+
+void
+SymbolVendorELF::Initialize()
+{
+    PluginManager::RegisterPlugin (GetPluginNameStatic(),
+                                   GetPluginDescriptionStatic(),
+                                   CreateInstance);
+}
+
+void
+SymbolVendorELF::Terminate()
+{
+    PluginManager::UnregisterPlugin (CreateInstance);
+}
+
+
+lldb_private::ConstString
+SymbolVendorELF::GetPluginNameStatic()
+{
+    static ConstString g_name("ELF");
+    return g_name;
+}
+
+const char *
+SymbolVendorELF::GetPluginDescriptionStatic()
+{
+    return "Symbol vendor for ELF that looks for dSYM files that match executables.";
+}
+
+
+
+//----------------------------------------------------------------------
+// CreateInstance
+//
+// Platforms can register a callback to use when creating symbol
+// vendors to allow for complex debug information file setups, and to
+// also allow for finding separate debug information files.
+//----------------------------------------------------------------------
+SymbolVendor*
+SymbolVendorELF::CreateInstance (const lldb::ModuleSP &module_sp, lldb_private::Stream *feedback_strm)
+{
+    if (!module_sp)
+        return NULL;
+
+    ObjectFile *obj_file = module_sp->GetObjectFile();
+    if (!obj_file)
+        return NULL;
+
+    static ConstString obj_file_elf("elf");
+    ConstString obj_name = obj_file->GetPluginName();
+    if (obj_name != obj_file_elf)
+        return NULL;
+
+    lldb_private::UUID uuid;
+    if (!obj_file->GetUUID (&uuid))
+        return NULL;
+
+    // Get the .gnu_debuglink file (if specified).
+    FileSpecList file_spec_list = obj_file->GetDebugSymbolFilePaths();
+
+    // If the module specified a filespec, use it first.
+    FileSpec debug_symbol_fspec (module_sp->GetSymbolFileFileSpec());
+    if (debug_symbol_fspec)
+        file_spec_list.Insert (0, debug_symbol_fspec);
+
+    // If we have no debug symbol files, then nothing to do.
+    if (file_spec_list.IsEmpty())
+        return NULL;
+
+    Timer scoped_timer (__PRETTY_FUNCTION__,
+                        "SymbolVendorELF::CreateInstance (module = %s)",
+                        module_sp->GetFileSpec().GetPath().c_str());
+
+    for (size_t idx = 0; idx < file_spec_list.GetSize(); ++idx)
+    {
+        ModuleSpec module_spec;
+        const FileSpec fspec = file_spec_list.GetFileSpecAtIndex (idx);
+
+        module_spec.GetFileSpec() = obj_file->GetFileSpec();
+        module_spec.GetFileSpec().ResolvePath();
+        module_spec.GetSymbolFileSpec() = fspec;
+        module_spec.GetUUID() = uuid;
+        FileSpec dsym_fspec = Symbols::LocateExecutableSymbolFile (module_spec);
+        if (dsym_fspec)
+        {
+            DataBufferSP dsym_file_data_sp;
+            lldb::offset_t dsym_file_data_offset = 0;
+            ObjectFileSP dsym_objfile_sp = ObjectFile::FindPlugin(module_sp, &dsym_fspec, 0, dsym_fspec.GetByteSize(), dsym_file_data_sp, dsym_file_data_offset);
+            if (dsym_objfile_sp)
+            {
+                // This objfile is for debugging purposes. Sadly, ObjectFileELF won't be able
+                // to figure this out consistently as the symbol file may not have stripped the
+                // code sections, etc.
+                dsym_objfile_sp->SetType (ObjectFile::eTypeDebugInfo);
+
+                SymbolVendorELF* symbol_vendor = new SymbolVendorELF(module_sp);
+                if (symbol_vendor)
+                {
+                    // Get the module unified section list and add our debug sections to that.
+                    SectionList *module_section_list = module_sp->GetSectionList();
+                    SectionList *objfile_section_list = dsym_objfile_sp->GetSectionList();
+
+                    static const SectionType g_sections[] =
+                    {
+                        eSectionTypeDWARFDebugAranges,
+                        eSectionTypeDWARFDebugInfo,
+                        eSectionTypeDWARFDebugAbbrev,
+                        eSectionTypeDWARFDebugFrame,
+                        eSectionTypeDWARFDebugLine,
+                        eSectionTypeDWARFDebugStr,
+                        eSectionTypeDWARFDebugLoc,
+                        eSectionTypeDWARFDebugMacInfo,
+                        eSectionTypeDWARFDebugPubNames,
+                        eSectionTypeDWARFDebugPubTypes,
+                        eSectionTypeDWARFDebugRanges,
+                        eSectionTypeELFSymbolTable,
+                    };
+                    for (size_t idx = 0; idx < sizeof(g_sections) / sizeof(g_sections[0]); ++idx)
+                    {
+                        SectionType section_type = g_sections[idx];
+                        SectionSP section_sp (objfile_section_list->FindSectionByType (section_type, true));
+                        if (section_sp)
+                        {
+                            SectionSP module_section_sp (module_section_list->FindSectionByType (section_type, true));
+                            if (module_section_sp)
+                                module_section_list->ReplaceSection (module_section_sp->GetID(), section_sp);
+                            else
+                                module_section_list->AddSection (section_sp);
+                        }
+                    }
+
+                    symbol_vendor->AddSymbolFileRepresentation (dsym_objfile_sp);
+                    return symbol_vendor;
+                }
+            }
+        }
+    }
+    return NULL;
+}
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+ConstString
+SymbolVendorELF::GetPluginName()
+{
+    return GetPluginNameStatic();
+}
+
+uint32_t
+SymbolVendorELF::GetPluginVersion()
+{
+    return 1;
+}
+
diff --git a/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.h b/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.h
new file mode 100644
index 000000000000..acd62b6cc3ab
--- /dev/null
+++ b/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.h
@@ -0,0 +1,58 @@
+//===-- SymbolVendorELF.h ------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_SymbolVendorELF_h_
+#define liblldb_SymbolVendorELF_h_
+
+#include "lldb/lldb-private.h"
+#include "lldb/Symbol/SymbolVendor.h"
+
+class SymbolVendorELF : public lldb_private::SymbolVendor
+{
+public:
+    //------------------------------------------------------------------
+    // Static Functions
+    //------------------------------------------------------------------
+    static void
+    Initialize();
+
+    static void
+    Terminate();
+
+    static lldb_private::ConstString
+    GetPluginNameStatic();
+
+    static const char *
+    GetPluginDescriptionStatic();
+
+    static lldb_private::SymbolVendor*
+    CreateInstance (const lldb::ModuleSP &module_sp, lldb_private::Stream *feedback_strm);
+
+    //------------------------------------------------------------------
+    // Constructors and Destructors
+    //------------------------------------------------------------------
+    SymbolVendorELF (const lldb::ModuleSP &module_sp);
+
+    virtual
+    ~SymbolVendorELF();
+
+    //------------------------------------------------------------------
+    // PluginInterface protocol
+    //------------------------------------------------------------------
+    virtual lldb_private::ConstString
+    GetPluginName();
+
+    virtual uint32_t
+    GetPluginVersion();
+
+private:
+    DISALLOW_COPY_AND_ASSIGN (SymbolVendorELF);
+};
+
+#endif  // liblldb_SymbolVendorELF_h_
diff --git a/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp b/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
new file mode 100644
index 000000000000..c93dea9b5d3c
--- /dev/null
+++ b/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp
@@ -0,0 +1,670 @@
+//===-- UnwindAssemblyInstEmulation.cpp --------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "UnwindAssemblyInstEmulation.h"
+
+#include "lldb/Core/Address.h"
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Disassembler.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+
+//-----------------------------------------------------------------------------------------------
+//  UnwindAssemblyInstEmulation method definitions 
+//-----------------------------------------------------------------------------------------------
+
+bool
+UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly (AddressRange& range, 
+                                                                   Thread& thread, 
+                                                                   UnwindPlan& unwind_plan)
+{
+    if (range.GetByteSize() > 0 && 
+        range.GetBaseAddress().IsValid() &&
+        m_inst_emulator_ap.get())
+    {
+     
+        // The the instruction emulation subclass setup the unwind plan for the
+        // first instruction.
+        m_inst_emulator_ap->CreateFunctionEntryUnwind (unwind_plan);
+
+        // CreateFunctionEntryUnwind should have created the first row. If it
+        // doesn't, then we are done.
+        if (unwind_plan.GetRowCount() == 0)
+            return false;
+        
+        ExecutionContext exe_ctx;
+        thread.CalculateExecutionContext(exe_ctx);
+        DisassemblerSP disasm_sp (Disassembler::DisassembleRange (m_arch,
+                                                                  NULL,
+                                                                  NULL,
+                                                                  exe_ctx,
+                                                                  range));
+        
+        Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
+
+        if (disasm_sp)
+        {
+            
+            m_range_ptr = &range;
+            m_thread_ptr = &thread;
+            m_unwind_plan_ptr = &unwind_plan;
+
+            const uint32_t addr_byte_size = m_arch.GetAddressByteSize();
+            const bool show_address = true;
+            const bool show_bytes = true;
+            m_inst_emulator_ap->GetRegisterInfo (unwind_plan.GetRegisterKind(), 
+                                                 unwind_plan.GetInitialCFARegister(), 
+                                                 m_cfa_reg_info);
+            
+            m_fp_is_cfa = false;
+            m_register_values.clear();
+            m_pushed_regs.clear();
+
+            // Initialize the CFA with a known value. In the 32 bit case
+            // it will be 0x80000000, and in the 64 bit case 0x8000000000000000.
+            // We use the address byte size to be safe for any future addresss sizes
+            m_initial_sp = (1ull << ((addr_byte_size * 8) - 1));
+            RegisterValue cfa_reg_value;
+            cfa_reg_value.SetUInt (m_initial_sp, m_cfa_reg_info.byte_size);
+            SetRegisterValue (m_cfa_reg_info, cfa_reg_value);
+
+            const InstructionList &inst_list = disasm_sp->GetInstructionList ();
+            const size_t num_instructions = inst_list.GetSize();
+
+            if (num_instructions > 0)
+            {
+                Instruction *inst = inst_list.GetInstructionAtIndex (0).get();
+                const addr_t base_addr = inst->GetAddress().GetFileAddress();
+
+                // Make a copy of the current instruction Row and save it in m_curr_row
+                // so we can add updates as we process the instructions.  
+                UnwindPlan::RowSP last_row = unwind_plan.GetLastRow();
+                UnwindPlan::Row *newrow = new UnwindPlan::Row;
+                if (last_row.get())
+                    *newrow = *last_row.get();
+                m_curr_row.reset(newrow);
+
+                // Once we've seen the initial prologue instructions complete, save a
+                // copy of the CFI at that point into prologue_completed_row for possible
+                // use later.
+                int instructions_since_last_prologue_insn = 0;     // # of insns since last CFI was update
+
+                bool reinstate_prologue_next_instruction = false;  // Next iteration, re-install the prologue row of CFI
+
+                bool last_instruction_restored_return_addr_reg = false;  // re-install the prologue row of CFI if the next instruction is a branch immediate
+
+                bool return_address_register_has_been_saved = false; // if we've seen the ra register get saved yet
+
+                UnwindPlan::RowSP prologue_completed_row;          // copy of prologue row of CFI
+
+                // cache the pc register number (in whatever register numbering this UnwindPlan uses) for
+                // quick reference during instruction parsing.
+                uint32_t pc_reg_num = LLDB_INVALID_REGNUM;
+                RegisterInfo pc_reg_info;
+                if (m_inst_emulator_ap->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, pc_reg_info))
+                    pc_reg_num = pc_reg_info.kinds[unwind_plan.GetRegisterKind()];
+                else
+                    pc_reg_num = LLDB_INVALID_REGNUM;
+
+                // cache the return address register number (in whatever register numbering this UnwindPlan uses) for
+                // quick reference during instruction parsing.
+                uint32_t ra_reg_num = LLDB_INVALID_REGNUM;
+                RegisterInfo ra_reg_info;
+                if (m_inst_emulator_ap->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, ra_reg_info))
+                    ra_reg_num = ra_reg_info.kinds[unwind_plan.GetRegisterKind()];
+                else
+                    ra_reg_num = LLDB_INVALID_REGNUM;
+
+                for (size_t idx=0; idx<num_instructions; ++idx)
+                {
+                    m_curr_row_modified = false;
+                    m_curr_insn_restored_a_register = false;
+                    inst = inst_list.GetInstructionAtIndex (idx).get();
+                    if (inst)
+                    {
+                        if (log && log->GetVerbose ())
+                        {
+                            StreamString strm;
+                            inst->Dump(&strm, inst_list.GetMaxOpcocdeByteSize (), show_address, show_bytes, NULL);
+                            log->PutCString (strm.GetData());
+                        }
+
+                        m_inst_emulator_ap->SetInstruction (inst->GetOpcode(), 
+                                                            inst->GetAddress(), 
+                                                            exe_ctx.GetTargetPtr());
+
+                        m_inst_emulator_ap->EvaluateInstruction (eEmulateInstructionOptionIgnoreConditions);
+
+                        // Were there any changes to the CFI while evaluating this instruction?
+                        if (m_curr_row_modified)
+                        {
+                            reinstate_prologue_next_instruction = false;
+                            m_curr_row->SetOffset (inst->GetAddress().GetFileAddress() + inst->GetOpcode().GetByteSize() - base_addr);
+                            // Append the new row
+                            unwind_plan.AppendRow (m_curr_row);
+
+                            // Allocate a new Row for m_curr_row, copy the current state into it
+                            UnwindPlan::Row *newrow = new UnwindPlan::Row;
+                            *newrow = *m_curr_row.get();
+                            m_curr_row.reset(newrow);
+
+                            // If m_curr_insn_restored_a_register == true, we're looking at an epilogue instruction.
+                            // Set instructions_since_last_prologue_insn to a very high number so we don't append 
+                            // any of these epilogue instructions to our prologue_complete row.
+                            if (m_curr_insn_restored_a_register == false && instructions_since_last_prologue_insn < 8)
+                              instructions_since_last_prologue_insn = 0;
+                            else
+                              instructions_since_last_prologue_insn = 99;
+
+                            UnwindPlan::Row::RegisterLocation pc_regloc;
+                            UnwindPlan::Row::RegisterLocation ra_regloc;
+
+                            // While parsing the instructions of this function, if we've ever
+                            // seen the return address register (aka lr on arm) in a non-IsSame() state,
+                            // it has been saved on the stack.  If it's evern back to IsSame(), we've
+                            // executed an epilogue.
+                            if (ra_reg_num != LLDB_INVALID_REGNUM
+                                && m_curr_row->GetRegisterInfo (ra_reg_num, ra_regloc)
+                                && !ra_regloc.IsSame())
+                            {
+                                return_address_register_has_been_saved = true;
+                            }
+
+                            // If the caller's pc is "same", we've just executed an epilogue and we return to the caller
+                            // after this instruction completes executing.
+                            // If there are any instructions past this, there must have been flow control over this
+                            // epilogue so we'll reinstate the original prologue setup instructions.
+                            if (prologue_completed_row.get()
+                                && pc_reg_num != LLDB_INVALID_REGNUM 
+                                && m_curr_row->GetRegisterInfo (pc_reg_num, pc_regloc)
+                                && pc_regloc.IsSame())
+                            {
+                                if (log && log->GetVerbose())
+                                    log->Printf("UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly -- pc is <same>, restore prologue instructions.");
+                                reinstate_prologue_next_instruction = true;
+                            }
+                            else if (prologue_completed_row.get()
+                                     && return_address_register_has_been_saved
+                                     && ra_reg_num != LLDB_INVALID_REGNUM
+                                     && m_curr_row->GetRegisterInfo (ra_reg_num, ra_regloc)
+                                     && ra_regloc.IsSame())
+                            {
+                                if (log && log->GetVerbose())
+                                    log->Printf("UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly -- lr is <same>, restore prologue instruction if the next instruction is a branch immediate.");
+                                last_instruction_restored_return_addr_reg = true;
+                            }
+                        }
+                        else
+                        {
+                            // If the previous instruction was a return-to-caller (epilogue), and we're still executing
+                            // instructions in this function, there must be a code path that jumps over that epilogue.
+                            // Also detect the case where we epilogue & branch imm to another function (tail-call opt)
+                            // instead of a normal pop lr-into-pc exit.
+                            // Reinstate the frame setup from the prologue.
+                            if (reinstate_prologue_next_instruction
+                                || (m_curr_insn_is_branch_immediate && last_instruction_restored_return_addr_reg))
+                            {
+                                if (log && log->GetVerbose())
+                                    log->Printf("UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly -- Reinstating prologue instruction set");
+                                UnwindPlan::Row *newrow = new UnwindPlan::Row;
+                                *newrow = *prologue_completed_row.get();
+                                m_curr_row.reset(newrow);
+                                m_curr_row->SetOffset (inst->GetAddress().GetFileAddress() + inst->GetOpcode().GetByteSize() - base_addr);
+                                unwind_plan.AppendRow(m_curr_row);
+
+                                newrow = new UnwindPlan::Row;
+                                *newrow = *m_curr_row.get();
+                                m_curr_row.reset(newrow);
+
+                                reinstate_prologue_next_instruction = false;
+                                last_instruction_restored_return_addr_reg = false; 
+                                m_curr_insn_is_branch_immediate = false;
+                            }
+
+                            // clear both of these if either one wasn't set
+                            if (last_instruction_restored_return_addr_reg)
+                            {
+                                last_instruction_restored_return_addr_reg = false;
+                            }
+                            if (m_curr_insn_is_branch_immediate)
+                            {
+                                m_curr_insn_is_branch_immediate = false;
+                            }
+ 
+                            // Stop updating the prologue instructions if we've seen 8 non-prologue instructions
+                            // in a row.
+                            if (instructions_since_last_prologue_insn++ < 8)
+                            {
+                                UnwindPlan::Row *newrow = new UnwindPlan::Row;
+                                *newrow = *m_curr_row.get();
+                                prologue_completed_row.reset(newrow);
+                                if (log && log->GetVerbose())
+                                    log->Printf("UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly -- saving a copy of the current row as the prologue row.");
+                            }
+                        }
+                    }
+                }
+            }
+            // FIXME: The DisassemblerLLVMC has a reference cycle and won't go away if it has any active instructions.
+            // I'll fix that but for now, just clear the list and it will go away nicely.
+            disasm_sp->GetInstructionList().Clear();
+        }
+        
+        if (log && log->GetVerbose ())
+        {
+            StreamString strm;
+            lldb::addr_t base_addr = range.GetBaseAddress().GetLoadAddress(thread.CalculateTarget().get());
+            strm.Printf ("Resulting unwind rows for [0x%" PRIx64 " - 0x%" PRIx64 "):", base_addr, base_addr + range.GetByteSize());
+            unwind_plan.Dump(strm, &thread, base_addr);
+            log->PutCString (strm.GetData());
+        }
+        return unwind_plan.GetRowCount() > 0;
+    }
+    return false;
+}
+
+bool
+UnwindAssemblyInstEmulation::GetFastUnwindPlan (AddressRange& func, 
+                                                Thread& thread, 
+                                                UnwindPlan &unwind_plan)
+{
+    return false;
+}
+
+bool
+UnwindAssemblyInstEmulation::FirstNonPrologueInsn (AddressRange& func, 
+                                                   const ExecutionContext &exe_ctx, 
+                                                   Address& first_non_prologue_insn)
+{
+    return false;
+}
+
+UnwindAssembly *
+UnwindAssemblyInstEmulation::CreateInstance (const ArchSpec &arch)
+{
+    std::unique_ptr<EmulateInstruction> inst_emulator_ap (EmulateInstruction::FindPlugin (arch, eInstructionTypePrologueEpilogue, NULL));
+    // Make sure that all prologue instructions are handled
+    if (inst_emulator_ap.get())
+        return new UnwindAssemblyInstEmulation (arch, inst_emulator_ap.release());
+    return NULL;
+}
+
+
+//------------------------------------------------------------------
+// PluginInterface protocol in UnwindAssemblyParser_x86
+//------------------------------------------------------------------
+ConstString
+UnwindAssemblyInstEmulation::GetPluginName()
+{
+    return GetPluginNameStatic();
+}
+
+uint32_t
+UnwindAssemblyInstEmulation::GetPluginVersion()
+{
+    return 1;
+}
+
+void
+UnwindAssemblyInstEmulation::Initialize()
+{
+    PluginManager::RegisterPlugin (GetPluginNameStatic(),
+                                   GetPluginDescriptionStatic(),
+                                   CreateInstance);
+}
+
+void
+UnwindAssemblyInstEmulation::Terminate()
+{
+    PluginManager::UnregisterPlugin (CreateInstance);
+}
+
+
+ConstString
+UnwindAssemblyInstEmulation::GetPluginNameStatic()
+{
+    static ConstString g_name("inst-emulation");
+    return g_name;
+}
+
+const char *
+UnwindAssemblyInstEmulation::GetPluginDescriptionStatic()
+{
+    return "Instruction emulation based unwind information.";
+}
+
+
+uint64_t 
+UnwindAssemblyInstEmulation::MakeRegisterKindValuePair (const RegisterInfo &reg_info)
+{
+    uint32_t reg_kind, reg_num;
+    if (EmulateInstruction::GetBestRegisterKindAndNumber (&reg_info, reg_kind, reg_num))
+        return (uint64_t)reg_kind << 24 | reg_num;
+    return 0ull;
+}
+
+void
+UnwindAssemblyInstEmulation::SetRegisterValue (const RegisterInfo &reg_info, const RegisterValue &reg_value)
+{
+    m_register_values[MakeRegisterKindValuePair (reg_info)] = reg_value;
+}
+
+bool
+UnwindAssemblyInstEmulation::GetRegisterValue (const RegisterInfo &reg_info, RegisterValue &reg_value)
+{
+    const uint64_t reg_id = MakeRegisterKindValuePair (reg_info);
+    RegisterValueMap::const_iterator pos = m_register_values.find(reg_id);
+    if (pos != m_register_values.end())
+    {
+        reg_value = pos->second;
+        return true; // We had a real value that comes from an opcode that wrote
+                     // to it...
+    }
+    // We are making up a value that is recognizable...
+    reg_value.SetUInt(reg_id, reg_info.byte_size);
+    return false;
+}
+
+
+size_t
+UnwindAssemblyInstEmulation::ReadMemory (EmulateInstruction *instruction,
+                                         void *baton,
+                                         const EmulateInstruction::Context &context, 
+                                         lldb::addr_t addr, 
+                                         void *dst,
+                                         size_t dst_len)
+{
+    Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
+
+    if (log && log->GetVerbose ())
+    {
+        StreamString strm;
+        strm.Printf ("UnwindAssemblyInstEmulation::ReadMemory    (addr = 0x%16.16" PRIx64 ", dst = %p, dst_len = %" PRIu64 ", context = ",
+                     addr,
+                     dst,
+                     (uint64_t)dst_len);
+        context.Dump(strm, instruction);
+        log->PutCString (strm.GetData ());
+    }
+    memset (dst, 0, dst_len);
+    return dst_len;
+}
+
+size_t
+UnwindAssemblyInstEmulation::WriteMemory (EmulateInstruction *instruction,
+                                          void *baton,
+                                          const EmulateInstruction::Context &context, 
+                                          lldb::addr_t addr, 
+                                          const void *dst,
+                                          size_t dst_len)
+{
+    if (baton && dst && dst_len)
+        return ((UnwindAssemblyInstEmulation *)baton)->WriteMemory (instruction, context, addr, dst, dst_len);
+    return 0;
+}
+
+size_t
+UnwindAssemblyInstEmulation::WriteMemory (EmulateInstruction *instruction,
+                                          const EmulateInstruction::Context &context, 
+                                          lldb::addr_t addr, 
+                                          const void *dst,
+                                          size_t dst_len)
+{
+    DataExtractor data (dst, 
+                        dst_len, 
+                        instruction->GetArchitecture ().GetByteOrder(), 
+                        instruction->GetArchitecture ().GetAddressByteSize());
+
+    Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
+
+    if (log && log->GetVerbose ())
+    {
+        StreamString strm;
+
+        strm.PutCString ("UnwindAssemblyInstEmulation::WriteMemory   (");
+        data.Dump(&strm, 0, eFormatBytes, 1, dst_len, UINT32_MAX, addr, 0, 0);
+        strm.PutCString (", context = ");
+        context.Dump(strm, instruction);
+        log->PutCString (strm.GetData());
+    }
+    
+    const bool can_replace = true;
+    const bool cant_replace = false;
+
+    switch (context.type)
+    {
+        default:
+        case EmulateInstruction::eContextInvalid:
+        case EmulateInstruction::eContextReadOpcode:
+        case EmulateInstruction::eContextImmediate:
+        case EmulateInstruction::eContextAdjustBaseRegister:
+        case EmulateInstruction::eContextRegisterPlusOffset:
+        case EmulateInstruction::eContextAdjustPC:
+        case EmulateInstruction::eContextRegisterStore:
+        case EmulateInstruction::eContextRegisterLoad:  
+        case EmulateInstruction::eContextRelativeBranchImmediate:
+        case EmulateInstruction::eContextAbsoluteBranchRegister:
+        case EmulateInstruction::eContextSupervisorCall:
+        case EmulateInstruction::eContextTableBranchReadMemory:
+        case EmulateInstruction::eContextWriteRegisterRandomBits:
+        case EmulateInstruction::eContextWriteMemoryRandomBits:
+        case EmulateInstruction::eContextArithmetic:
+        case EmulateInstruction::eContextAdvancePC:    
+        case EmulateInstruction::eContextReturnFromException:
+        case EmulateInstruction::eContextPopRegisterOffStack:
+        case EmulateInstruction::eContextAdjustStackPointer:
+            break;
+            
+        case EmulateInstruction::eContextPushRegisterOnStack:
+            {
+                uint32_t reg_num = LLDB_INVALID_REGNUM;
+                bool is_return_address_reg = false;
+                const uint32_t unwind_reg_kind = m_unwind_plan_ptr->GetRegisterKind();
+                if (context.info_type == EmulateInstruction::eInfoTypeRegisterToRegisterPlusOffset)
+                {
+                    reg_num = context.info.RegisterToRegisterPlusOffset.data_reg.kinds[unwind_reg_kind];
+                    if (context.info.RegisterToRegisterPlusOffset.data_reg.kinds[eRegisterKindGeneric] == LLDB_REGNUM_GENERIC_RA)
+                        is_return_address_reg = true;
+                }
+                else
+                {
+                    assert (!"unhandled case, add code to handle this!");
+                }
+                
+                if (reg_num != LLDB_INVALID_REGNUM)
+                {
+                    if (m_pushed_regs.find (reg_num) == m_pushed_regs.end())
+                    {
+                        m_pushed_regs[reg_num] = addr;
+                        const int32_t offset = addr - m_initial_sp;
+                        m_curr_row->SetRegisterLocationToAtCFAPlusOffset (reg_num, offset, cant_replace);
+                        m_curr_row_modified = true;
+                        if (is_return_address_reg)
+                        {
+                            // This push was pushing the return address register,
+                            // so this is also how we will unwind the PC...
+                            RegisterInfo pc_reg_info;
+                            if (instruction->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, pc_reg_info))
+                            {
+                                uint32_t pc_reg_num = pc_reg_info.kinds[unwind_reg_kind];
+                                if (pc_reg_num != LLDB_INVALID_REGNUM)
+                                {
+                                    m_curr_row->SetRegisterLocationToAtCFAPlusOffset (pc_reg_num, offset, can_replace);
+                                    m_curr_row_modified = true;
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+            break;
+            
+    }
+
+    return dst_len;
+}
+
+bool
+UnwindAssemblyInstEmulation::ReadRegister (EmulateInstruction *instruction,
+                                           void *baton,
+                                           const RegisterInfo *reg_info,
+                                           RegisterValue &reg_value)
+{
+    
+    if (baton && reg_info)
+        return ((UnwindAssemblyInstEmulation *)baton)->ReadRegister (instruction, reg_info, reg_value);
+    return false;
+}
+bool
+UnwindAssemblyInstEmulation::ReadRegister (EmulateInstruction *instruction,
+                                           const RegisterInfo *reg_info,
+                                           RegisterValue &reg_value)
+{
+    bool synthetic = GetRegisterValue (*reg_info, reg_value);
+
+    Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
+    
+    if (log && log->GetVerbose ())
+    {
+        
+        StreamString strm;
+        strm.Printf ("UnwindAssemblyInstEmulation::ReadRegister  (name = \"%s\") => synthetic_value = %i, value = ", reg_info->name, synthetic);
+        reg_value.Dump(&strm, reg_info, false, false, eFormatDefault);
+        log->PutCString(strm.GetData());
+    }
+    return true;
+}
+
+bool
+UnwindAssemblyInstEmulation::WriteRegister (EmulateInstruction *instruction,
+                                            void *baton,
+                                            const EmulateInstruction::Context &context, 
+                                            const RegisterInfo *reg_info,
+                                            const RegisterValue &reg_value)
+{
+    if (baton && reg_info)
+        return ((UnwindAssemblyInstEmulation *)baton)->WriteRegister (instruction, context, reg_info, reg_value);
+    return false;
+}
+bool
+UnwindAssemblyInstEmulation::WriteRegister (EmulateInstruction *instruction,
+                                            const EmulateInstruction::Context &context, 
+                                            const RegisterInfo *reg_info,
+                                            const RegisterValue &reg_value)
+{
+    Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
+
+    if (log && log->GetVerbose ())
+    {
+        
+        StreamString strm;
+        strm.Printf ("UnwindAssemblyInstEmulation::WriteRegister (name = \"%s\", value = ", reg_info->name);
+        reg_value.Dump(&strm, reg_info, false, false, eFormatDefault);
+        strm.PutCString (", context = ");
+        context.Dump(strm, instruction);
+        log->PutCString(strm.GetData());
+    }
+
+    const bool must_replace = true;
+    SetRegisterValue (*reg_info, reg_value);
+
+    switch (context.type)
+    {
+        case EmulateInstruction::eContextInvalid:
+        case EmulateInstruction::eContextReadOpcode:
+        case EmulateInstruction::eContextImmediate:
+        case EmulateInstruction::eContextAdjustBaseRegister:
+        case EmulateInstruction::eContextRegisterPlusOffset:
+        case EmulateInstruction::eContextAdjustPC:
+        case EmulateInstruction::eContextRegisterStore:
+        case EmulateInstruction::eContextRegisterLoad:  
+        case EmulateInstruction::eContextAbsoluteBranchRegister:
+        case EmulateInstruction::eContextSupervisorCall:
+        case EmulateInstruction::eContextTableBranchReadMemory:
+        case EmulateInstruction::eContextWriteRegisterRandomBits:
+        case EmulateInstruction::eContextWriteMemoryRandomBits:
+        case EmulateInstruction::eContextArithmetic:
+        case EmulateInstruction::eContextAdvancePC:    
+        case EmulateInstruction::eContextReturnFromException:
+        case EmulateInstruction::eContextPushRegisterOnStack:
+//            {
+//                const uint32_t reg_num = reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()];
+//                if (reg_num != LLDB_INVALID_REGNUM)
+//                {
+//                    const bool can_replace_only_if_unspecified = true;
+//
+//                    m_curr_row.SetRegisterLocationToUndefined (reg_num, 
+//                                                               can_replace_only_if_unspecified, 
+//                                                               can_replace_only_if_unspecified);
+//                    m_curr_row_modified = true;
+//                }
+//            }
+            break;
+
+        case EmulateInstruction::eContextRelativeBranchImmediate:
+            {
+                
+                {
+                    m_curr_insn_is_branch_immediate = true;
+                }
+            }
+            break;
+
+        case EmulateInstruction::eContextPopRegisterOffStack:
+            {
+                const uint32_t reg_num = reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()];
+                if (reg_num != LLDB_INVALID_REGNUM)
+                {
+                    m_curr_row->SetRegisterLocationToSame (reg_num, must_replace);
+                    m_curr_row_modified = true;
+                    m_curr_insn_restored_a_register = true;
+                }
+            }
+            break;
+
+        case EmulateInstruction::eContextSetFramePointer:
+            if (!m_fp_is_cfa)
+            {
+                m_fp_is_cfa = true;
+                m_cfa_reg_info = *reg_info;
+                const uint32_t cfa_reg_num = reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()];
+                assert (cfa_reg_num != LLDB_INVALID_REGNUM);
+                m_curr_row->SetCFARegister(cfa_reg_num);
+                m_curr_row->SetCFAOffset(m_initial_sp - reg_value.GetAsUInt64());
+                m_curr_row_modified = true;
+            }
+            break;
+
+        case EmulateInstruction::eContextAdjustStackPointer:
+            // If we have created a frame using the frame pointer, don't follow
+            // subsequent adjustments to the stack pointer.
+            if (!m_fp_is_cfa)
+            {
+                m_curr_row->SetCFAOffset (m_initial_sp - reg_value.GetAsUInt64());
+                m_curr_row_modified = true;
+            }
+            break;
+    }
+    return true;
+}
+
+
diff --git a/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h b/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h
new file mode 100644
index 000000000000..6a02f0a55104
--- /dev/null
+++ b/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h
@@ -0,0 +1,185 @@
+//===-- UnwindAssemblyInstEmulation.h ----------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_UnwindAssemblyInstEmulation_h_
+#define liblldb_UnwindAssemblyInstEmulation_h_
+
+#include "lldb/lldb-private.h"
+#include "lldb/Core/EmulateInstruction.h"
+#include "lldb/Core/RegisterValue.h"
+#include "lldb/Symbol/UnwindPlan.h"
+#include "lldb/Target/UnwindAssembly.h"
+
+class UnwindAssemblyInstEmulation : public lldb_private::UnwindAssembly
+{
+public:
+
+    virtual
+    ~UnwindAssemblyInstEmulation () 
+    {
+    }
+
+    virtual bool
+    GetNonCallSiteUnwindPlanFromAssembly (lldb_private::AddressRange& func, 
+                                          lldb_private::Thread& thread, 
+                                          lldb_private::UnwindPlan& unwind_plan);
+
+    virtual bool
+    GetFastUnwindPlan (lldb_private::AddressRange& func, 
+                       lldb_private::Thread& thread, 
+                       lldb_private::UnwindPlan &unwind_plan);
+
+    // thread may be NULL in which case we only use the Target (e.g. if this is called pre-process-launch).
+    virtual bool
+    FirstNonPrologueInsn (lldb_private::AddressRange& func, 
+                          const lldb_private::ExecutionContext &exe_ctx, 
+                          lldb_private::Address& first_non_prologue_insn);
+
+    static lldb_private::UnwindAssembly *
+    CreateInstance (const lldb_private::ArchSpec &arch);
+
+    //------------------------------------------------------------------
+    // PluginInterface protocol
+    //------------------------------------------------------------------
+    static void
+    Initialize();
+
+    static void
+    Terminate();
+
+    static lldb_private::ConstString
+    GetPluginNameStatic();
+
+    static const char *
+    GetPluginDescriptionStatic();
+
+    virtual lldb_private::ConstString
+    GetPluginName();
+    
+    virtual uint32_t
+    GetPluginVersion();
+    
+private:
+    
+    static size_t
+    ReadMemory (lldb_private::EmulateInstruction *instruction,
+                void *baton,
+                const lldb_private::EmulateInstruction::Context &context, 
+                lldb::addr_t addr, 
+                void *dst,
+                size_t length);
+
+    static size_t
+    WriteMemory (lldb_private::EmulateInstruction *instruction,
+                 void *baton,
+                 const lldb_private::EmulateInstruction::Context &context, 
+                 lldb::addr_t addr, 
+                 const void *dst,
+                 size_t length);
+    
+    static bool
+    ReadRegister (lldb_private::EmulateInstruction *instruction,
+                  void *baton,
+                  const lldb_private::RegisterInfo *reg_info,
+                  lldb_private::RegisterValue &reg_value);
+    
+    static bool
+    WriteRegister (lldb_private::EmulateInstruction *instruction,
+                   void *baton,
+                   const lldb_private::EmulateInstruction::Context &context, 
+                   const lldb_private::RegisterInfo *reg_info,
+                   const lldb_private::RegisterValue &reg_value);
+
+
+//    size_t
+//    ReadMemory (lldb_private::EmulateInstruction *instruction,
+//                const lldb_private::EmulateInstruction::Context &context, 
+//                lldb::addr_t addr, 
+//                void *dst,
+//                size_t length);
+    
+    size_t
+    WriteMemory (lldb_private::EmulateInstruction *instruction,
+                 const lldb_private::EmulateInstruction::Context &context, 
+                 lldb::addr_t addr, 
+                 const void *dst,
+                 size_t length);
+
+    bool
+    ReadRegister (lldb_private::EmulateInstruction *instruction,
+                  const lldb_private::RegisterInfo *reg_info,
+                  lldb_private::RegisterValue &reg_value);
+
+    bool
+    WriteRegister (lldb_private::EmulateInstruction *instruction,
+                   const lldb_private::EmulateInstruction::Context &context, 
+                   const lldb_private::RegisterInfo *reg_info,
+                   const lldb_private::RegisterValue &reg_value);
+
+    // Call CreateInstance to get an instance of this class
+    UnwindAssemblyInstEmulation (const lldb_private::ArchSpec &arch,
+                                 lldb_private::EmulateInstruction *inst_emulator) :
+        UnwindAssembly (arch),
+        m_inst_emulator_ap (inst_emulator),
+        m_range_ptr (NULL),
+        m_thread_ptr (NULL),
+        m_unwind_plan_ptr (NULL),
+        m_curr_row (),
+        m_cfa_reg_info (),
+        m_fp_is_cfa (false),
+        m_register_values (),
+        m_pushed_regs(),
+        m_curr_row_modified (false),
+        m_curr_insn_is_branch_immediate (false),
+        m_curr_insn_restored_a_register (false)
+    {
+        if (m_inst_emulator_ap.get())
+        {
+            m_inst_emulator_ap->SetBaton (this);
+            m_inst_emulator_ap->SetCallbacks (ReadMemory, WriteMemory, ReadRegister, WriteRegister);
+        }
+    }
+
+    static uint64_t 
+    MakeRegisterKindValuePair (const lldb_private::RegisterInfo &reg_info);
+    
+    void
+    SetRegisterValue (const lldb_private::RegisterInfo &reg_info, 
+                      const lldb_private::RegisterValue &reg_value);
+
+    bool
+    GetRegisterValue (const lldb_private::RegisterInfo &reg_info, 
+                      lldb_private::RegisterValue &reg_value);
+
+    std::unique_ptr<lldb_private::EmulateInstruction> m_inst_emulator_ap;    
+    lldb_private::AddressRange* m_range_ptr; 
+    lldb_private::Thread* m_thread_ptr;
+    lldb_private::UnwindPlan* m_unwind_plan_ptr;
+    lldb_private::UnwindPlan::RowSP m_curr_row;
+    typedef std::map<uint64_t, uint64_t> PushedRegisterToAddrMap;
+    uint64_t m_initial_sp;
+    lldb_private::RegisterInfo m_cfa_reg_info;
+    bool m_fp_is_cfa;
+    typedef std::map<uint64_t, lldb_private::RegisterValue> RegisterValueMap;
+    RegisterValueMap m_register_values;
+    PushedRegisterToAddrMap m_pushed_regs;
+
+    // While processing the instruction stream, we need to communicate some state change
+    // information up to the higher level loop that makes decisions about how to push
+    // the unwind instructions for the UnwindPlan we're constructing.
+    
+    // The instruction we're processing updated the UnwindPlan::Row contents
+    bool m_curr_row_modified;
+    // The instruction we're examining is a branch immediate instruction
+    bool m_curr_insn_is_branch_immediate;
+    // The instruction we're processing restored a caller's reg value (e.g. in an epilogue)
+    bool m_curr_insn_restored_a_register;
+};
+
+#endif // liblldb_UnwindAssemblyInstEmulation_h_
diff --git a/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp b/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp
new file mode 100644
index 000000000000..d491683f6875
--- /dev/null
+++ b/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp
@@ -0,0 +1,973 @@
+//===-- UnwindAssembly-x86.cpp ----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "UnwindAssembly-x86.h"
+
+#include "llvm-c/Disassembler.h"
+#include "llvm/Support/TargetSelect.h"
+
+#include "lldb/Core/Address.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Symbol/UnwindPlan.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/UnwindAssembly.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+enum CPU {
+    k_i386,
+    k_x86_64
+};
+
+enum i386_register_numbers {
+    k_machine_eax = 0,
+    k_machine_ecx = 1,
+    k_machine_edx = 2,
+    k_machine_ebx = 3,
+    k_machine_esp = 4,
+    k_machine_ebp = 5,
+    k_machine_esi = 6,
+    k_machine_edi = 7,
+    k_machine_eip = 8
+};
+
+enum x86_64_register_numbers {
+    k_machine_rax = 0,
+    k_machine_rcx = 1,
+    k_machine_rdx = 2,
+    k_machine_rbx = 3,
+    k_machine_rsp = 4,
+    k_machine_rbp = 5,
+    k_machine_rsi = 6,
+    k_machine_rdi = 7,
+    k_machine_r8 = 8,
+    k_machine_r9 = 9,
+    k_machine_r10 = 10,
+    k_machine_r11 = 11,
+    k_machine_r12 = 12,
+    k_machine_r13 = 13,
+    k_machine_r14 = 14,
+    k_machine_r15 = 15,
+    k_machine_rip = 16
+};
+
+struct regmap_ent {
+    const char *name;
+    int machine_regno;
+    int lldb_regno;
+};
+
+static struct regmap_ent i386_register_map[] = {
+    {"eax", k_machine_eax, -1},
+    {"ecx", k_machine_ecx, -1},
+    {"edx", k_machine_edx, -1},
+    {"ebx", k_machine_ebx, -1},
+    {"esp", k_machine_esp, -1},
+    {"ebp", k_machine_ebp, -1},
+    {"esi", k_machine_esi, -1},
+    {"edi", k_machine_edi, -1},
+    {"eip", k_machine_eip, -1}
+};
+
+const int size_of_i386_register_map = sizeof (i386_register_map) / sizeof (struct regmap_ent);
+
+static int i386_register_map_initialized = 0;
+
+static struct regmap_ent x86_64_register_map[] = {
+    {"rax", k_machine_rax, -1},
+    {"rcx", k_machine_rcx, -1},
+    {"rdx", k_machine_rdx, -1},
+    {"rbx", k_machine_rbx, -1},
+    {"rsp", k_machine_rsp, -1},
+    {"rbp", k_machine_rbp, -1},
+    {"rsi", k_machine_rsi, -1},
+    {"rdi", k_machine_rdi, -1},
+    {"r8", k_machine_r8, -1},
+    {"r9", k_machine_r9, -1},
+    {"r10", k_machine_r10, -1},
+    {"r11", k_machine_r11, -1},
+    {"r12", k_machine_r12, -1},
+    {"r13", k_machine_r13, -1},
+    {"r14", k_machine_r14, -1},
+    {"r15", k_machine_r15, -1},
+    {"rip", k_machine_rip, -1}
+};
+
+const int size_of_x86_64_register_map = sizeof (x86_64_register_map) / sizeof (struct regmap_ent);
+
+static int x86_64_register_map_initialized = 0;
+
+//-----------------------------------------------------------------------------------------------
+//  AssemblyParse_x86 local-file class definition & implementation functions
+//-----------------------------------------------------------------------------------------------
+
+class AssemblyParse_x86 {
+public:
+
+    AssemblyParse_x86 (const ExecutionContext &exe_ctx, int cpu, ArchSpec &arch, AddressRange func);
+
+    ~AssemblyParse_x86 ();
+
+    bool get_non_call_site_unwind_plan (UnwindPlan &unwind_plan);
+
+    bool get_fast_unwind_plan (AddressRange& func, UnwindPlan &unwind_plan);
+
+    bool find_first_non_prologue_insn (Address &address);
+
+private:
+    enum { kMaxInstructionByteSize = 32 };
+
+    bool nonvolatile_reg_p (int machine_regno);
+    bool push_rbp_pattern_p ();
+    bool push_0_pattern_p ();
+    bool mov_rsp_rbp_pattern_p ();
+    bool sub_rsp_pattern_p (int& amount);
+    bool push_reg_p (int& regno);
+    bool mov_reg_to_local_stack_frame_p (int& regno, int& fp_offset);
+    bool ret_pattern_p ();
+    uint32_t extract_4 (uint8_t *b);
+    bool machine_regno_to_lldb_regno (int machine_regno, uint32_t& lldb_regno);
+    bool instruction_length (Address addr, int &length);
+
+    const ExecutionContext m_exe_ctx;
+
+    AddressRange m_func_bounds;
+
+    Address m_cur_insn;
+    uint8_t m_cur_insn_bytes[kMaxInstructionByteSize];
+
+    int m_machine_ip_regnum;
+    int m_machine_sp_regnum;
+    int m_machine_fp_regnum;
+
+    int m_lldb_ip_regnum;
+    int m_lldb_sp_regnum;
+    int m_lldb_fp_regnum;
+
+    int m_wordsize;
+    int m_cpu;
+    ArchSpec m_arch;
+    ::LLVMDisasmContextRef m_disasm_context;
+
+    DISALLOW_COPY_AND_ASSIGN (AssemblyParse_x86);
+};
+
+AssemblyParse_x86::AssemblyParse_x86 (const ExecutionContext &exe_ctx, int cpu, ArchSpec &arch, AddressRange func) :
+    m_exe_ctx (exe_ctx), 
+    m_func_bounds(func), 
+    m_cur_insn (),
+    m_machine_ip_regnum (LLDB_INVALID_REGNUM),
+    m_machine_sp_regnum (LLDB_INVALID_REGNUM),
+    m_machine_fp_regnum (LLDB_INVALID_REGNUM),
+    m_lldb_ip_regnum (LLDB_INVALID_REGNUM), 
+    m_lldb_sp_regnum (LLDB_INVALID_REGNUM),
+    m_lldb_fp_regnum (LLDB_INVALID_REGNUM),
+    m_wordsize (-1), 
+    m_cpu(cpu),
+    m_arch(arch)
+{
+    int *initialized_flag = NULL;
+    if (cpu == k_i386)
+    {
+        m_machine_ip_regnum = k_machine_eip;
+        m_machine_sp_regnum = k_machine_esp;
+        m_machine_fp_regnum = k_machine_ebp;
+        m_wordsize = 4;
+        initialized_flag = &i386_register_map_initialized;
+    }
+    else
+    {
+        m_machine_ip_regnum = k_machine_rip;
+        m_machine_sp_regnum = k_machine_rsp;
+        m_machine_fp_regnum = k_machine_rbp;
+        m_wordsize = 8;
+        initialized_flag = &x86_64_register_map_initialized;
+    }
+
+    // we only look at prologue - it will be complete earlier than 512 bytes into func
+    if (m_func_bounds.GetByteSize() == 0)
+        m_func_bounds.SetByteSize(512);
+
+    Thread *thread = m_exe_ctx.GetThreadPtr();
+    if (thread && *initialized_flag == 0)
+    {
+        RegisterContext *reg_ctx = thread->GetRegisterContext().get();
+        if (reg_ctx)
+        {
+            struct regmap_ent *ent;
+            int count, i;
+            if (cpu == k_i386)
+            {
+                ent = i386_register_map;
+                count = size_of_i386_register_map;
+            }
+            else
+            {
+                ent = x86_64_register_map;
+                count = size_of_x86_64_register_map;
+            }
+            for (i = 0; i < count; i++, ent++)
+            {
+                const RegisterInfo *ri = reg_ctx->GetRegisterInfoByName (ent->name);
+                if (ri)
+                    ent->lldb_regno = ri->kinds[eRegisterKindLLDB];
+            }
+            *initialized_flag = 1;
+        }
+    }
+
+   // on initial construction we may not have a Thread so these have to remain
+   // uninitialized until we can get a RegisterContext to set up the register map table
+   if (*initialized_flag == 1)
+   {
+       uint32_t lldb_regno;
+       if (machine_regno_to_lldb_regno (m_machine_sp_regnum, lldb_regno))
+           m_lldb_sp_regnum = lldb_regno;
+       if (machine_regno_to_lldb_regno (m_machine_fp_regnum, lldb_regno))
+           m_lldb_fp_regnum = lldb_regno;
+       if (machine_regno_to_lldb_regno (m_machine_ip_regnum, lldb_regno))
+           m_lldb_ip_regnum = lldb_regno;
+   }
+
+   m_disasm_context = ::LLVMCreateDisasm(m_arch.GetTriple().getTriple().c_str(), 
+                                          (void*)this, 
+                                          /*TagType=*/1,
+                                          NULL,
+                                          NULL);
+}
+
+AssemblyParse_x86::~AssemblyParse_x86 ()
+{
+    ::LLVMDisasmDispose(m_disasm_context);
+}
+
+// This function expects an x86 native register number (i.e. the bits stripped out of the 
+// actual instruction), not an lldb register number.
+
+bool
+AssemblyParse_x86::nonvolatile_reg_p (int machine_regno)
+{
+    if (m_cpu == k_i386)
+    {
+          switch (machine_regno) {
+              case k_machine_ebx:
+              case k_machine_ebp:  // not actually a nonvolatile but often treated as such by convention
+              case k_machine_esi:
+              case k_machine_edi:
+              case k_machine_esp:
+                  return true;
+              default:
+                  return false;
+          }
+    }
+    if (m_cpu == k_x86_64)
+    {
+          switch (machine_regno) {
+              case k_machine_rbx:
+              case k_machine_rsp:
+              case k_machine_rbp:  // not actually a nonvolatile but often treated as such by convention
+              case k_machine_r12:
+              case k_machine_r13:
+              case k_machine_r14:
+              case k_machine_r15:
+                  return true;
+              default:
+                  return false;
+          }
+    }
+    return false;
+}
+
+
+// Macro to detect if this is a REX mode prefix byte. 
+#define REX_W_PREFIX_P(opcode) (((opcode) & (~0x5)) == 0x48)
+
+// The high bit which should be added to the source register number (the "R" bit)
+#define REX_W_SRCREG(opcode) (((opcode) & 0x4) >> 2)
+
+// The high bit which should be added to the destination register number (the "B" bit)
+#define REX_W_DSTREG(opcode) ((opcode) & 0x1)
+
+// pushq %rbp [0x55]
+bool AssemblyParse_x86::push_rbp_pattern_p () {
+    uint8_t *p = m_cur_insn_bytes;
+    if (*p == 0x55)
+      return true;
+    return false;
+}
+
+// pushq $0 ; the first instruction in start() [0x6a 0x00]
+bool AssemblyParse_x86::push_0_pattern_p ()
+{
+    uint8_t *p = m_cur_insn_bytes;
+    if (*p == 0x6a && *(p + 1) == 0x0)
+        return true;
+    return false;
+}
+
+// movq %rsp, %rbp [0x48 0x8b 0xec] or [0x48 0x89 0xe5]
+// movl %esp, %ebp [0x8b 0xec] or [0x89 0xe5]
+bool AssemblyParse_x86::mov_rsp_rbp_pattern_p () {
+    uint8_t *p = m_cur_insn_bytes;
+    if (m_wordsize == 8 && *p == 0x48)
+      p++;
+    if (*(p) == 0x8b && *(p + 1) == 0xec)
+        return true;
+    if (*(p) == 0x89 && *(p + 1) == 0xe5)
+        return true;
+    return false;
+}
+
+// subq $0x20, %rsp 
+bool AssemblyParse_x86::sub_rsp_pattern_p (int& amount) {
+    uint8_t *p = m_cur_insn_bytes;
+    if (m_wordsize == 8 && *p == 0x48)
+      p++;
+    // 8-bit immediate operand
+    if (*p == 0x83 && *(p + 1) == 0xec) {
+        amount = (int8_t) *(p + 2);
+        return true;
+    }
+    // 32-bit immediate operand
+    if (*p == 0x81 && *(p + 1) == 0xec) {
+        amount = (int32_t) extract_4 (p + 2);
+        return true;
+    }
+    // Not handled:  [0x83 0xc4] for imm8 with neg values
+    // [0x81 0xc4] for imm32 with neg values
+    return false;
+}
+
+// pushq %rbx
+// pushl $ebx
+bool AssemblyParse_x86::push_reg_p (int& regno) {
+    uint8_t *p = m_cur_insn_bytes;
+    int regno_prefix_bit = 0;
+    // If we have a rex prefix byte, check to see if a B bit is set
+    if (m_wordsize == 8 && *p == 0x41) {
+        regno_prefix_bit = 1 << 3;
+        p++;
+    }
+    if (*p >= 0x50 && *p <= 0x57) {
+        regno = (*p - 0x50) | regno_prefix_bit;
+        return true;
+    }
+    return false;
+}
+
+// Look for an instruction sequence storing a nonvolatile register
+// on to the stack frame.
+
+//  movq %rax, -0x10(%rbp) [0x48 0x89 0x45 0xf0]
+//  movl %eax, -0xc(%ebp)  [0x89 0x45 0xf4]
+bool AssemblyParse_x86::mov_reg_to_local_stack_frame_p (int& regno, int& rbp_offset) {
+    uint8_t *p = m_cur_insn_bytes;
+    int src_reg_prefix_bit = 0;
+    int target_reg_prefix_bit = 0;
+
+    if (m_wordsize == 8 && REX_W_PREFIX_P (*p)) {
+        src_reg_prefix_bit = REX_W_SRCREG (*p) << 3;
+        target_reg_prefix_bit = REX_W_DSTREG (*p) << 3;
+        if (target_reg_prefix_bit == 1) {
+            // rbp/ebp don't need a prefix bit - we know this isn't the
+            // reg we care about.
+            return false;
+        }
+        p++;
+    }
+
+    if (*p == 0x89) {
+        /* Mask off the 3-5 bits which indicate the destination register
+           if this is a ModR/M byte.  */
+        int opcode_destreg_masked_out = *(p + 1) & (~0x38);
+
+        /* Is this a ModR/M byte with Mod bits 01 and R/M bits 101 
+           and three bits between them, e.g. 01nnn101
+           We're looking for a destination of ebp-disp8 or ebp-disp32.   */
+        int immsize;
+        if (opcode_destreg_masked_out == 0x45)
+          immsize = 2;
+        else if (opcode_destreg_masked_out == 0x85)
+          immsize = 4;
+        else
+          return false;
+
+        int offset = 0;
+        if (immsize == 2)
+          offset = (int8_t) *(p + 2);
+        if (immsize == 4)
+             offset = (uint32_t) extract_4 (p + 2);
+        if (offset > 0)
+          return false;
+
+        regno = ((*(p + 1) >> 3) & 0x7) | src_reg_prefix_bit;
+        rbp_offset = offset > 0 ? offset : -offset;
+        return true;
+    }
+    return false;
+}
+
+// ret [0xc9] or [0xc2 imm8] or [0xca imm8]
+bool 
+AssemblyParse_x86::ret_pattern_p () 
+{
+    uint8_t *p = m_cur_insn_bytes;
+    if (*p == 0xc9 || *p == 0xc2 || *p == 0xca || *p == 0xc3)
+        return true;
+    return false;
+}
+
+uint32_t
+AssemblyParse_x86::extract_4 (uint8_t *b)
+{
+    uint32_t v = 0;
+    for (int i = 3; i >= 0; i--)
+        v = (v << 8) | b[i];
+    return v;
+}
+
+bool 
+AssemblyParse_x86::machine_regno_to_lldb_regno (int machine_regno, uint32_t &lldb_regno)
+{
+    struct regmap_ent *ent;
+    int count, i;
+    if (m_cpu == k_i386)
+    {
+        ent = i386_register_map;
+        count = size_of_i386_register_map;
+    }
+    else
+    {
+        ent = x86_64_register_map;
+        count = size_of_x86_64_register_map;
+    }
+    for (i = 0; i < count; i++, ent++)
+    {
+        if (ent->machine_regno == machine_regno)
+            if (ent->lldb_regno != -1)
+            {
+                lldb_regno = ent->lldb_regno;
+                return true;
+            }
+    }
+    return false;
+}
+
+bool
+AssemblyParse_x86::instruction_length (Address addr, int &length)
+{
+    const uint32_t max_op_byte_size = m_arch.GetMaximumOpcodeByteSize();
+    llvm::SmallVector <uint8_t, 32> opcode_data;
+    opcode_data.resize (max_op_byte_size);
+
+    if (!addr.IsValid())
+        return false;
+
+    const bool prefer_file_cache = true;
+    Error error;
+    Target *target = m_exe_ctx.GetTargetPtr();
+    if (target->ReadMemory (addr, prefer_file_cache, opcode_data.data(), max_op_byte_size, error) == -1)
+    {
+        return false;
+    }
+   
+    char out_string[512];
+    const addr_t pc = addr.GetFileAddress();
+    const size_t inst_size = ::LLVMDisasmInstruction (m_disasm_context,
+                                                      opcode_data.data(),
+                                                      max_op_byte_size,
+                                                      pc, // PC value
+                                                      out_string,
+                                                      sizeof(out_string));
+
+    length = inst_size;
+    return true;
+}
+
+
+bool 
+AssemblyParse_x86::get_non_call_site_unwind_plan (UnwindPlan &unwind_plan)
+{
+    UnwindPlan::RowSP row(new UnwindPlan::Row);
+    int non_prologue_insn_count = 0;
+    m_cur_insn = m_func_bounds.GetBaseAddress ();
+    int current_func_text_offset = 0;
+    int current_sp_bytes_offset_from_cfa = 0;
+    UnwindPlan::Row::RegisterLocation initial_regloc;
+    Error error;
+
+    if (!m_cur_insn.IsValid())
+    {
+        return false;
+    }
+
+    unwind_plan.SetPlanValidAddressRange (m_func_bounds);
+    unwind_plan.SetRegisterKind (eRegisterKindLLDB);
+
+    // At the start of the function, find the CFA by adding wordsize to the SP register
+    row->SetOffset (current_func_text_offset);
+    row->SetCFARegister (m_lldb_sp_regnum);
+    row->SetCFAOffset (m_wordsize);
+
+    // caller's stack pointer value before the call insn is the CFA address
+    initial_regloc.SetIsCFAPlusOffset (0);
+    row->SetRegisterInfo (m_lldb_sp_regnum, initial_regloc);
+
+    // saved instruction pointer can be found at CFA - wordsize.
+    current_sp_bytes_offset_from_cfa = m_wordsize;
+    initial_regloc.SetAtCFAPlusOffset (-current_sp_bytes_offset_from_cfa);
+    row->SetRegisterInfo (m_lldb_ip_regnum, initial_regloc);
+
+    unwind_plan.AppendRow (row);
+
+    // Allocate a new Row, populate it with the existing Row contents.
+    UnwindPlan::Row *newrow = new UnwindPlan::Row;
+    *newrow = *row.get();
+    row.reset(newrow);
+
+    const bool prefer_file_cache = true;
+
+    Target *target = m_exe_ctx.GetTargetPtr();
+    while (m_func_bounds.ContainsFileAddress (m_cur_insn) && non_prologue_insn_count < 10)
+    {
+        int stack_offset, insn_len;
+        int machine_regno;          // register numbers masked directly out of instructions
+        uint32_t lldb_regno;        // register numbers in lldb's eRegisterKindLLDB numbering scheme
+
+        if (!instruction_length (m_cur_insn, insn_len) || insn_len == 0 || insn_len > kMaxInstructionByteSize)
+        {
+            // An unrecognized/junk instruction
+            break;
+        }
+        if (target->ReadMemory (m_cur_insn, prefer_file_cache, m_cur_insn_bytes, insn_len, error) == -1)
+        {
+           // Error reading the instruction out of the file, stop scanning
+           break;
+        }
+
+        if (push_rbp_pattern_p ())
+        {
+            row->SetOffset (current_func_text_offset + insn_len);
+            current_sp_bytes_offset_from_cfa += m_wordsize;
+            row->SetCFAOffset (current_sp_bytes_offset_from_cfa);
+            UnwindPlan::Row::RegisterLocation regloc;
+            regloc.SetAtCFAPlusOffset (-row->GetCFAOffset());
+            row->SetRegisterInfo (m_lldb_fp_regnum, regloc);
+            unwind_plan.AppendRow (row);
+            // Allocate a new Row, populate it with the existing Row contents.
+            newrow = new UnwindPlan::Row;
+            *newrow = *row.get();
+            row.reset(newrow);
+            goto loopnext;
+        }
+
+        if (mov_rsp_rbp_pattern_p ())
+        {
+            row->SetOffset (current_func_text_offset + insn_len);
+            row->SetCFARegister (m_lldb_fp_regnum);
+            unwind_plan.AppendRow (row);
+            // Allocate a new Row, populate it with the existing Row contents.
+            newrow = new UnwindPlan::Row;
+            *newrow = *row.get();
+            row.reset(newrow);
+            goto loopnext;
+        }
+
+        // This is the start() function (or a pthread equivalent), it starts with a pushl $0x0 which puts the
+        // saved pc value of 0 on the stack.  In this case we want to pretend we didn't see a stack movement at all --
+        // normally the saved pc value is already on the stack by the time the function starts executing.
+        if (push_0_pattern_p ())
+        {
+            goto loopnext;
+        }
+
+        if (push_reg_p (machine_regno))
+        {
+            current_sp_bytes_offset_from_cfa += m_wordsize;
+            if (nonvolatile_reg_p (machine_regno) && machine_regno_to_lldb_regno (machine_regno, lldb_regno))
+            {
+                row->SetOffset (current_func_text_offset + insn_len);
+                if (row->GetCFARegister() == m_lldb_sp_regnum)
+                {
+                    row->SetCFAOffset (current_sp_bytes_offset_from_cfa);
+                }
+                UnwindPlan::Row::RegisterLocation regloc;
+                regloc.SetAtCFAPlusOffset (-current_sp_bytes_offset_from_cfa);
+                row->SetRegisterInfo (lldb_regno, regloc);
+                unwind_plan.AppendRow (row);
+                // Allocate a new Row, populate it with the existing Row contents.
+                newrow = new UnwindPlan::Row;
+                *newrow = *row.get();
+                row.reset(newrow);
+            }
+            goto loopnext;
+        }
+
+        if (mov_reg_to_local_stack_frame_p (machine_regno, stack_offset) && nonvolatile_reg_p (machine_regno))
+        {
+            if (machine_regno_to_lldb_regno (machine_regno, lldb_regno))
+            {
+                row->SetOffset (current_func_text_offset + insn_len);
+                UnwindPlan::Row::RegisterLocation regloc;
+                regloc.SetAtCFAPlusOffset (-row->GetCFAOffset());
+                row->SetRegisterInfo (lldb_regno, regloc);
+                unwind_plan.AppendRow (row);
+                // Allocate a new Row, populate it with the existing Row contents.
+                newrow = new UnwindPlan::Row;
+                *newrow = *row.get();
+                row.reset(newrow);
+                goto loopnext;
+            }
+        }
+
+        if (sub_rsp_pattern_p (stack_offset))
+        {
+            current_sp_bytes_offset_from_cfa += stack_offset;
+            if (row->GetCFARegister() == m_lldb_sp_regnum)
+            {
+                row->SetOffset (current_func_text_offset + insn_len);
+                row->SetCFAOffset (current_sp_bytes_offset_from_cfa);
+                unwind_plan.AppendRow (row);
+                // Allocate a new Row, populate it with the existing Row contents.
+                newrow = new UnwindPlan::Row;
+                *newrow = *row.get();
+                row.reset(newrow);
+            }
+            goto loopnext;
+        }
+
+        if (ret_pattern_p ())
+        {
+            // we know where the end of the function is; set the limit on the PlanValidAddressRange
+            // in case our initial "high pc" value was overly large
+            // int original_size = m_func_bounds.GetByteSize();
+            // int calculated_size = m_cur_insn.GetOffset() - m_func_bounds.GetBaseAddress().GetOffset() + insn_len + 1;
+            // m_func_bounds.SetByteSize (calculated_size);
+            // unwind_plan.SetPlanValidAddressRange (m_func_bounds);
+            break;
+        }
+
+        // FIXME recognize the i386 picbase setup instruction sequence,
+        // 0x1f16:  call   0x1f1b                   ; main + 11 at /private/tmp/a.c:3
+        // 0x1f1b:  popl   %eax
+        // and record the temporary stack movements if the CFA is not expressed in terms of ebp.
+
+        non_prologue_insn_count++;
+loopnext:
+        m_cur_insn.SetOffset (m_cur_insn.GetOffset() + insn_len);
+        current_func_text_offset += insn_len;
+    }
+    
+    // Now look at the byte at the end of the AddressRange for a limited attempt at describing the
+    // epilogue.  We're looking for the sequence
+
+    //  [ 0x5d ] mov %rbp, %rsp
+    //  [ 0xc3 ] ret
+    //  [ 0xe8 xx xx xx xx ] call __stack_chk_fail  (this is sometimes the final insn in the function)
+
+    // We want to add a Row describing how to unwind when we're stopped on the 'ret' instruction where the
+    // CFA is no longer defined in terms of rbp, but is now defined in terms of rsp like on function entry.
+
+    uint64_t ret_insn_offset = LLDB_INVALID_ADDRESS;
+    Address end_of_fun(m_func_bounds.GetBaseAddress());
+    end_of_fun.SetOffset (end_of_fun.GetOffset() + m_func_bounds.GetByteSize());
+    
+    if (m_func_bounds.GetByteSize() > 7)
+    {
+        uint8_t bytebuf[7];
+        Address last_seven_bytes(end_of_fun);
+        last_seven_bytes.SetOffset (last_seven_bytes.GetOffset() - 7);
+        if (target->ReadMemory (last_seven_bytes, prefer_file_cache, bytebuf, 7, error) != -1)
+        {
+            if (bytebuf[5] == 0x5d && bytebuf[6] == 0xc3)  // mov, ret
+            {
+                ret_insn_offset = m_func_bounds.GetByteSize() - 1;
+            }
+            else if (bytebuf[0] == 0x5d && bytebuf[1] == 0xc3 && bytebuf[2] == 0xe8) // mov, ret, call
+            {
+                ret_insn_offset = m_func_bounds.GetByteSize() - 6;
+            }
+        }
+    } else if (m_func_bounds.GetByteSize() > 2)
+    {
+        uint8_t bytebuf[2];
+        Address last_two_bytes(end_of_fun);
+        last_two_bytes.SetOffset (last_two_bytes.GetOffset() - 2);
+        if (target->ReadMemory (last_two_bytes, prefer_file_cache, bytebuf, 2, error) != -1)
+        {
+            if (bytebuf[0] == 0x5d && bytebuf[1] == 0xc3) // mov, ret
+            {
+                ret_insn_offset = m_func_bounds.GetByteSize() - 1;
+            }
+        }
+    }
+
+    if (ret_insn_offset != LLDB_INVALID_ADDRESS)
+    {
+        // Create a fresh, empty Row and RegisterLocation - don't mention any other registers
+        UnwindPlan::RowSP epi_row(new UnwindPlan::Row);
+        UnwindPlan::Row::RegisterLocation epi_regloc;
+
+        // When the ret instruction is about to be executed, here's our state
+        epi_row->SetOffset (ret_insn_offset);
+        epi_row->SetCFARegister (m_lldb_sp_regnum);
+        epi_row->SetCFAOffset (m_wordsize);
+       
+        // caller's stack pointer value before the call insn is the CFA address
+        epi_regloc.SetIsCFAPlusOffset (0);
+        epi_row->SetRegisterInfo (m_lldb_sp_regnum, epi_regloc);
+
+        // saved instruction pointer can be found at CFA - wordsize
+        epi_regloc.SetAtCFAPlusOffset (-m_wordsize);
+        epi_row->SetRegisterInfo (m_lldb_ip_regnum, epi_regloc);
+
+        unwind_plan.AppendRow (epi_row);
+    }
+    
+    unwind_plan.SetSourceName ("assembly insn profiling");
+    unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
+    unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolYes);
+
+    return true;
+}
+
+/* The "fast unwind plan" is valid for functions that follow the usual convention of 
+   using the frame pointer register (ebp, rbp), i.e. the function prologue looks like
+     push   %rbp      [0x55]
+     mov    %rsp,%rbp [0x48 0x89 0xe5]   (this is a 2-byte insn seq on i386)
+*/
+
+bool 
+AssemblyParse_x86::get_fast_unwind_plan (AddressRange& func, UnwindPlan &unwind_plan)
+{
+    UnwindPlan::RowSP row(new UnwindPlan::Row);
+    UnwindPlan::Row::RegisterLocation pc_reginfo;
+    UnwindPlan::Row::RegisterLocation sp_reginfo;
+    UnwindPlan::Row::RegisterLocation fp_reginfo;
+    unwind_plan.SetRegisterKind (eRegisterKindLLDB);
+
+    if (!func.GetBaseAddress().IsValid())
+        return false;
+
+    Target *target = m_exe_ctx.GetTargetPtr();
+
+    uint8_t bytebuf[4];
+    Error error;
+    const bool prefer_file_cache = true;
+    if (target->ReadMemory (func.GetBaseAddress(), prefer_file_cache, bytebuf, sizeof (bytebuf), error) == -1)
+        return false;
+
+    uint8_t i386_prologue[] = {0x55, 0x89, 0xe5};
+    uint8_t x86_64_prologue[] = {0x55, 0x48, 0x89, 0xe5};
+    int prologue_size;
+
+    if (memcmp (bytebuf, i386_prologue, sizeof (i386_prologue)) == 0)
+    {
+        prologue_size = sizeof (i386_prologue);
+    }
+    else if (memcmp (bytebuf, x86_64_prologue, sizeof (x86_64_prologue)) == 0)
+    {
+        prologue_size = sizeof (x86_64_prologue);
+    }
+    else
+    {
+        return false;
+    }
+
+    pc_reginfo.SetAtCFAPlusOffset (-m_wordsize);
+    row->SetRegisterInfo (m_lldb_ip_regnum, pc_reginfo);
+
+    sp_reginfo.SetIsCFAPlusOffset (0);
+    row->SetRegisterInfo (m_lldb_sp_regnum, sp_reginfo);
+
+    // Zero instructions into the function
+    row->SetCFARegister (m_lldb_sp_regnum);
+    row->SetCFAOffset (m_wordsize);
+    row->SetOffset (0);
+    unwind_plan.AppendRow (row);
+    UnwindPlan::Row *newrow = new UnwindPlan::Row;
+    *newrow = *row.get();
+    row.reset(newrow);
+
+    // push %rbp has executed - stack moved, rbp now saved
+    row->SetCFAOffset (2 * m_wordsize);
+    fp_reginfo.SetAtCFAPlusOffset (2 * -m_wordsize);
+    row->SetRegisterInfo (m_lldb_fp_regnum, fp_reginfo);
+    row->SetOffset (1);
+    unwind_plan.AppendRow (row);
+
+    newrow = new UnwindPlan::Row;
+    *newrow = *row.get();
+    row.reset(newrow);
+    
+    // mov %rsp, %rbp has executed
+    row->SetCFARegister (m_lldb_fp_regnum);
+    row->SetCFAOffset (2 * m_wordsize);
+    row->SetOffset (prologue_size);     /// 3 or 4 bytes depending on arch
+    unwind_plan.AppendRow (row);
+
+    newrow = new UnwindPlan::Row;
+    *newrow = *row.get();
+    row.reset(newrow);
+
+    unwind_plan.SetPlanValidAddressRange (func);
+    unwind_plan.SetSourceName ("fast unwind assembly profiling");
+    unwind_plan.SetSourcedFromCompiler (eLazyBoolNo);
+    unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolNo);
+    return true;
+}
+
+bool 
+AssemblyParse_x86::find_first_non_prologue_insn (Address &address)
+{
+    m_cur_insn = m_func_bounds.GetBaseAddress ();
+    if (!m_cur_insn.IsValid())
+    {
+        return false;
+    }
+
+    const bool prefer_file_cache = true;
+    Target *target = m_exe_ctx.GetTargetPtr();
+    while (m_func_bounds.ContainsFileAddress (m_cur_insn))
+    {
+        Error error;
+        int insn_len, offset, regno;
+        if (!instruction_length (m_cur_insn, insn_len) || insn_len > kMaxInstructionByteSize || insn_len == 0)
+        {
+            // An error parsing the instruction, i.e. probably data/garbage - stop scanning
+            break;
+        }
+        if (target->ReadMemory (m_cur_insn, prefer_file_cache, m_cur_insn_bytes, insn_len, error) == -1)
+        {
+           // Error reading the instruction out of the file, stop scanning
+           break;
+        }
+
+        if (push_rbp_pattern_p () || mov_rsp_rbp_pattern_p () || sub_rsp_pattern_p (offset)
+            || push_reg_p (regno) || mov_reg_to_local_stack_frame_p (regno, offset))
+        {
+            m_cur_insn.SetOffset (m_cur_insn.GetOffset() + insn_len);
+            continue;
+        }
+
+        // Unknown non-prologue instruction - stop scanning
+        break;
+    }
+
+    address = m_cur_insn;
+    return true;
+}
+
+
+
+
+
+
+//-----------------------------------------------------------------------------------------------
+//  UnwindAssemblyParser_x86 method definitions 
+//-----------------------------------------------------------------------------------------------
+
+UnwindAssembly_x86::UnwindAssembly_x86 (const ArchSpec &arch, int cpu) : 
+    lldb_private::UnwindAssembly(arch), 
+    m_cpu(cpu),
+    m_arch(arch)
+{
+}
+
+
+UnwindAssembly_x86::~UnwindAssembly_x86 ()
+{
+}
+
+bool
+UnwindAssembly_x86::GetNonCallSiteUnwindPlanFromAssembly (AddressRange& func, Thread& thread, UnwindPlan& unwind_plan)
+{
+    ExecutionContext exe_ctx (thread.shared_from_this());
+    AssemblyParse_x86 asm_parse(exe_ctx, m_cpu, m_arch, func);
+    return asm_parse.get_non_call_site_unwind_plan (unwind_plan);
+}
+
+bool
+UnwindAssembly_x86::GetFastUnwindPlan (AddressRange& func, Thread& thread, UnwindPlan &unwind_plan)
+{
+    ExecutionContext exe_ctx (thread.shared_from_this());
+    AssemblyParse_x86 asm_parse(exe_ctx, m_cpu, m_arch, func);
+    return asm_parse.get_fast_unwind_plan (func, unwind_plan);
+}
+
+bool
+UnwindAssembly_x86::FirstNonPrologueInsn (AddressRange& func, const ExecutionContext &exe_ctx, Address& first_non_prologue_insn)
+{
+    AssemblyParse_x86 asm_parse(exe_ctx, m_cpu, m_arch, func);
+    return asm_parse.find_first_non_prologue_insn (first_non_prologue_insn);
+}
+
+UnwindAssembly *
+UnwindAssembly_x86::CreateInstance (const ArchSpec &arch)
+{
+    const llvm::Triple::ArchType cpu = arch.GetMachine ();
+    if (cpu == llvm::Triple::x86)
+        return new UnwindAssembly_x86 (arch, k_i386);
+    else if (cpu == llvm::Triple::x86_64)
+        return new UnwindAssembly_x86 (arch, k_x86_64);
+    return NULL;
+}
+
+
+//------------------------------------------------------------------
+// PluginInterface protocol in UnwindAssemblyParser_x86
+//------------------------------------------------------------------
+
+ConstString
+UnwindAssembly_x86::GetPluginName()
+{
+    return GetPluginNameStatic();
+}
+
+
+uint32_t
+UnwindAssembly_x86::GetPluginVersion()
+{
+    return 1;
+}
+
+void
+UnwindAssembly_x86::Initialize()
+{
+    PluginManager::RegisterPlugin (GetPluginNameStatic(),
+                                   GetPluginDescriptionStatic(),
+                                   CreateInstance);
+}
+
+void
+UnwindAssembly_x86::Terminate()
+{
+    PluginManager::UnregisterPlugin (CreateInstance);
+}
+
+
+lldb_private::ConstString
+UnwindAssembly_x86::GetPluginNameStatic()
+{
+    static ConstString g_name("x86");
+    return g_name;
+}
+
+const char *
+UnwindAssembly_x86::GetPluginDescriptionStatic()
+{
+    return "i386 and x86_64 assembly language profiler plugin.";
+}
diff --git a/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.h b/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.h
new file mode 100644
index 000000000000..eebaa7b6c803
--- /dev/null
+++ b/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.h
@@ -0,0 +1,73 @@
+//===-- UnwindAssembly-x86.h -------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_UnwindAssembly_x86_h_
+#define liblldb_UnwindAssembly_x86_h_
+
+#include "llvm-c/Disassembler.h"
+
+#include "lldb/lldb-private.h"
+#include "lldb/Target/UnwindAssembly.h"
+
+class UnwindAssembly_x86 : public lldb_private::UnwindAssembly
+{
+public:
+
+    ~UnwindAssembly_x86 ();
+
+    virtual bool
+    GetNonCallSiteUnwindPlanFromAssembly (lldb_private::AddressRange& func, 
+                                          lldb_private::Thread& thread, 
+                                          lldb_private::UnwindPlan& unwind_plan);
+
+    virtual bool
+    GetFastUnwindPlan (lldb_private::AddressRange& func, 
+                       lldb_private::Thread& thread, 
+                       lldb_private::UnwindPlan &unwind_plan);
+
+    // thread may be NULL in which case we only use the Target (e.g. if this is called pre-process-launch).
+    virtual bool
+    FirstNonPrologueInsn (lldb_private::AddressRange& func, 
+                          const lldb_private::ExecutionContext &exe_ctx,
+                          lldb_private::Address& first_non_prologue_insn);
+
+    static lldb_private::UnwindAssembly *
+    CreateInstance (const lldb_private::ArchSpec &arch);
+
+
+    //------------------------------------------------------------------
+    // PluginInterface protocol
+    //------------------------------------------------------------------
+    static void
+    Initialize();
+
+    static void
+    Terminate();
+
+    static lldb_private::ConstString
+    GetPluginNameStatic();
+
+    static const char *
+    GetPluginDescriptionStatic();
+
+    virtual lldb_private::ConstString
+    GetPluginName();
+    
+    virtual uint32_t
+    GetPluginVersion();
+    
+private:
+    UnwindAssembly_x86 (const lldb_private::ArchSpec &arch, int cpu);
+
+    int m_cpu;
+    lldb_private::ArchSpec m_arch;
+};
+
+
+#endif // liblldb_UnwindAssembly_x86_h_
-- 
cgit v1.2.3