[Lldb-commits] [lldb] r266308 - Support Linux on SystemZ as platform

Ulrich Weigand via lldb-commits lldb-commits at lists.llvm.org
Thu Apr 14 07:28:35 PDT 2016


Author: uweigand
Date: Thu Apr 14 09:28:34 2016
New Revision: 266308

URL: http://llvm.org/viewvc/llvm-project?rev=266308&view=rev
Log:
Support Linux on SystemZ as platform

This patch adds support for Linux on SystemZ:
- A new ArchSpec value of eCore_s390x_generic
- A new directory Plugins/ABI/SysV-s390x providing an ABI implementation
- Register context support
- Native Linux support including watchpoint support
- ELF core file support
- Misc. support throughout the code base (e.g. breakpoint opcodes)
- Test case updates to support the platform

This should provide complete support for debugging the SystemZ platform.
Not yet supported are optional features like transaction support (zEC12)
or SIMD vector support (z13).

There is no instruction emulation, since our ABI requires that all code
provide correct DWARF CFI at all PC locations in .eh_frame to support
unwinding (i.e. -fasynchronous-unwind-tables is on by default).

The implementation follows existing platforms in a mostly straightforward
manner.  A couple of things that are different:

- We do not use PTRACE_PEEKUSER / PTRACE_POKEUSER to access single registers,
  since some registers (access register) reside at offsets in the user area
  that are multiples of 4, but the PTRACE_PEEKUSER interface only allows
  accessing aligned 8-byte blocks in the user area.  Instead, we use a s390
  specific ptrace interface PTRACE_PEEKUSR_AREA / PTRACE_POKEUSR_AREA that
  allows accessing a whole block of the user area in one go, so in effect
  allowing to treat parts of the user area as register sets.

- SystemZ hardware does not provide any means to implement read watchpoints,
  only write watchpoints.  In fact, we can only support a *single* write
  watchpoint (but this can span a range of arbitrary size).  In LLDB this
  means we support only a single watchpoint.  I've set all test cases that
  require read watchpoints (or multiple watchpoints) to expected failure
  on the platform.  [ Note that there were two test cases that install
  a read/write watchpoint even though they nowhere rely on the "read"
  property.  I've changed those to simply use plain write watchpoints. ]

Differential Revision: http://reviews.llvm.org/D18978


Added:
    lldb/trunk/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/s390x.core   (with props)
    lldb/trunk/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/s390x.out   (with props)
    lldb/trunk/source/Plugins/ABI/SysV-s390x/
    lldb/trunk/source/Plugins/ABI/SysV-s390x/ABISysV_s390x.cpp
    lldb/trunk/source/Plugins/ABI/SysV-s390x/ABISysV_s390x.h
    lldb/trunk/source/Plugins/ABI/SysV-s390x/CMakeLists.txt
    lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp
    lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.h
    lldb/trunk/source/Plugins/Process/Utility/RegisterContextLinux_s390x.cpp
    lldb/trunk/source/Plugins/Process/Utility/RegisterContextLinux_s390x.h
    lldb/trunk/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.cpp
    lldb/trunk/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.h
    lldb/trunk/source/Plugins/Process/Utility/RegisterContext_s390x.h
    lldb/trunk/source/Plugins/Process/Utility/RegisterInfos_s390x.h
    lldb/trunk/source/Plugins/Process/Utility/lldb-s390x-register-enums.h
    lldb/trunk/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.cpp
    lldb/trunk/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.h
Modified:
    lldb/trunk/cmake/LLDBDependencies.cmake
    lldb/trunk/include/lldb/Core/ArchSpec.h
    lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_conditions/TestBreakpointConditions.py
    lldb/trunk/packages/Python/lldbsuite/test/functionalities/disassembly/TestDisassembleBreakpoint.py
    lldb/trunk/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/TestLinuxCore.py
    lldb/trunk/packages/Python/lldbsuite/test/functionalities/watchpoint/hello_watchlocation/TestWatchLocation.py
    lldb/trunk/packages/Python/lldbsuite/test/functionalities/watchpoint/step_over_watchpoint/TestStepOverWatchpoint.py
    lldb/trunk/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_commands/TestWatchpointCommands.py
    lldb/trunk/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_events/TestWatchpointEvents.py
    lldb/trunk/packages/Python/lldbsuite/test/lldbplatformutil.py
    lldb/trunk/packages/Python/lldbsuite/test/make/Makefile.rules
    lldb/trunk/packages/Python/lldbsuite/test/python_api/watchpoint/TestSetWatchpoint.py
    lldb/trunk/packages/Python/lldbsuite/test/python_api/watchpoint/TestWatchpointIgnoreCount.py
    lldb/trunk/packages/Python/lldbsuite/test/python_api/watchpoint/TestWatchpointIter.py
    lldb/trunk/packages/Python/lldbsuite/test/python_api/watchpoint/watchlocation/TestTargetWatchAddress.py
    lldb/trunk/packages/Python/lldbsuite/test/tools/lldb-mi/control/TestMiExec.py
    lldb/trunk/packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py
    lldb/trunk/source/API/SystemInitializerFull.cpp
    lldb/trunk/source/Core/ArchSpec.cpp
    lldb/trunk/source/Host/common/HostInfoBase.cpp
    lldb/trunk/source/Plugins/ABI/CMakeLists.txt
    lldb/trunk/source/Plugins/ObjectFile/ELF/ELFHeader.cpp
    lldb/trunk/source/Plugins/Platform/Linux/PlatformLinux.cpp
    lldb/trunk/source/Plugins/Process/Linux/CMakeLists.txt
    lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp
    lldb/trunk/source/Plugins/Process/Utility/CMakeLists.txt
    lldb/trunk/source/Plugins/Process/elf-core/CMakeLists.txt
    lldb/trunk/source/Plugins/Process/elf-core/ThreadElfCore.cpp
    lldb/trunk/source/Plugins/Process/elf-core/ThreadElfCore.h
    lldb/trunk/source/Target/Platform.cpp
    lldb/trunk/source/Target/Thread.cpp

Modified: lldb/trunk/cmake/LLDBDependencies.cmake
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/cmake/LLDBDependencies.cmake?rev=266308&r1=266307&r2=266308&view=diff
==============================================================================
--- lldb/trunk/cmake/LLDBDependencies.cmake (original)
+++ lldb/trunk/cmake/LLDBDependencies.cmake Thu Apr 14 09:28:34 2016
@@ -66,6 +66,7 @@ set( LLDB_USED_LIBS
   lldbPluginABISysV_ppc64
   lldbPluginABISysV_mips
   lldbPluginABISysV_mips64
+  lldbPluginABISysV_s390x
   lldbPluginInstructionARM
   lldbPluginInstructionARM64
   lldbPluginInstructionMIPS

Modified: lldb/trunk/include/lldb/Core/ArchSpec.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/ArchSpec.h?rev=266308&r1=266307&r2=266308&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/ArchSpec.h (original)
+++ lldb/trunk/include/lldb/Core/ArchSpec.h Thu Apr 14 09:28:34 2016
@@ -151,6 +151,8 @@ public:
         eCore_ppc64_generic,
         eCore_ppc64_ppc970_64,
         
+        eCore_s390x_generic,
+
         eCore_sparc_generic,
         
         eCore_sparc9_generic,

Modified: lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_conditions/TestBreakpointConditions.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_conditions/TestBreakpointConditions.py?rev=266308&r1=266307&r2=266308&view=diff
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_conditions/TestBreakpointConditions.py (original)
+++ lldb/trunk/packages/Python/lldbsuite/test/functionalities/breakpoint/breakpoint_conditions/TestBreakpointConditions.py Thu Apr 14 09:28:34 2016
@@ -113,6 +113,8 @@ class BreakpointConditionsTestCase(TestB
             self.runCmd("breakpoint modify -c ($r0&&i)")
         elif re.match("mips",arch):
             self.runCmd("breakpoint modify -c ($r2&&i)")
+        elif arch in ['s390x']:
+            self.runCmd("breakpoint modify -c ($r2&&i)")
         self.runCmd("run")
 
         self.expect("process status", PROCESS_STOPPED,

Modified: lldb/trunk/packages/Python/lldbsuite/test/functionalities/disassembly/TestDisassembleBreakpoint.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/functionalities/disassembly/TestDisassembleBreakpoint.py?rev=266308&r1=266307&r2=266308&view=diff
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/functionalities/disassembly/TestDisassembleBreakpoint.py (original)
+++ lldb/trunk/packages/Python/lldbsuite/test/functionalities/disassembly/TestDisassembleBreakpoint.py Thu Apr 14 09:28:34 2016
@@ -43,6 +43,9 @@ class DisassemblyTestCase(TestBase):
         elif re.match("mips" , arch):
             breakpoint_opcodes = ["break"]
             instructions = ['lw', 'sw']
+        elif arch in ["s390x"]:
+            breakpoint_opcodes = [".long"]
+            instructions = [' l ', ' a ', ' st ']
         else:
             # TODO please add your arch here
             self.fail('unimplemented for arch = "{arch}"'.format(arch=self.getArchitecture()))

Modified: lldb/trunk/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/TestLinuxCore.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/TestLinuxCore.py?rev=266308&r1=266307&r2=266308&view=diff
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/TestLinuxCore.py (original)
+++ lldb/trunk/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/TestLinuxCore.py Thu Apr 14 09:28:34 2016
@@ -19,6 +19,7 @@ class LinuxCoreTestCase(TestBase):
 
     _i386_pid   = 32306
     _x86_64_pid = 32259
+    _s390x_pid  = 1045
 
     @skipIf(bugnumber="llvm.org/pr26947")
     def test_i386(self):
@@ -29,6 +30,10 @@ class LinuxCoreTestCase(TestBase):
         """Test that lldb can read the process information from an x86_64 linux core file."""
         self.do_test("x86_64", self._x86_64_pid)
 
+    def test_s390x(self):
+        """Test that lldb can read the process information from an s390x linux core file."""
+        self.do_test("s390x", self._s390x_pid)
+
     def test_same_pid_running(self):
         """Test that we read the information from the core correctly even if we have a running
         process with the same PID around"""

Added: lldb/trunk/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/s390x.core
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/s390x.core?rev=266308&view=auto
==============================================================================
Binary file - no diff available.

Propchange: lldb/trunk/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/s390x.core
------------------------------------------------------------------------------
    svn:mime-type = application/x-coredump

Added: lldb/trunk/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/s390x.out
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/s390x.out?rev=266308&view=auto
==============================================================================
Binary file - no diff available.

Propchange: lldb/trunk/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/s390x.out
------------------------------------------------------------------------------
    svn:executable = *

Propchange: lldb/trunk/packages/Python/lldbsuite/test/functionalities/postmortem/linux-core/s390x.out
------------------------------------------------------------------------------
    svn:mime-type = application/x-executable

Modified: lldb/trunk/packages/Python/lldbsuite/test/functionalities/watchpoint/hello_watchlocation/TestWatchLocation.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/functionalities/watchpoint/hello_watchlocation/TestWatchLocation.py?rev=266308&r1=266307&r2=266308&view=diff
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/functionalities/watchpoint/hello_watchlocation/TestWatchLocation.py (original)
+++ lldb/trunk/packages/Python/lldbsuite/test/functionalities/watchpoint/hello_watchlocation/TestWatchLocation.py Thu Apr 14 09:28:34 2016
@@ -33,6 +33,7 @@ class HelloWatchLocationTestCase(TestBas
     @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported
     @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows")
     @expectedFailureAll(triple = re.compile('^mips')) # Most of the MIPS boards provide only one H/W watchpoints, and S/W watchpoints are not supported yet
+    @expectedFailureAll(archs=['s390x']) # SystemZ also currently supports only one H/W watchpoint
     @skipIfDarwin
     def test_hello_watchlocation(self):
         """Test watching a location with '-s size' option."""

Modified: lldb/trunk/packages/Python/lldbsuite/test/functionalities/watchpoint/step_over_watchpoint/TestStepOverWatchpoint.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/functionalities/watchpoint/step_over_watchpoint/TestStepOverWatchpoint.py?rev=266308&r1=266307&r2=266308&view=diff
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/functionalities/watchpoint/step_over_watchpoint/TestStepOverWatchpoint.py (original)
+++ lldb/trunk/packages/Python/lldbsuite/test/functionalities/watchpoint/step_over_watchpoint/TestStepOverWatchpoint.py Thu Apr 14 09:28:34 2016
@@ -20,6 +20,7 @@ class TestStepOverWatchpoint(TestBase):
     @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported
     @expectedFailureAll(oslist=["linux"], archs=['aarch64', 'arm'], bugnumber="llvm.org/pr26031")
     @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows")
+    @expectedFailureAll(archs=['s390x']) # Read-write watchpoints not supported on SystemZ
     def test(self):
         """Test stepping over watchpoints."""
         self.build()

Modified: lldb/trunk/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_commands/TestWatchpointCommands.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_commands/TestWatchpointCommands.py?rev=266308&r1=266307&r2=266308&view=diff
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_commands/TestWatchpointCommands.py (original)
+++ lldb/trunk/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_commands/TestWatchpointCommands.py Thu Apr 14 09:28:34 2016
@@ -32,6 +32,7 @@ class WatchpointCommandsTestCase(TestBas
 
     @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported
     @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows")
+    @expectedFailureAll(archs=['s390x']) # Read-write watchpoints not supported on SystemZ
     def test_rw_watchpoint(self):
         """Test read_write watchpoint and expect to stop two times."""
         self.build(dictionary=self.d)
@@ -92,6 +93,7 @@ class WatchpointCommandsTestCase(TestBas
 
     @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported
     @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows")
+    @expectedFailureAll(archs=['s390x']) # Read-write watchpoints not supported on SystemZ
     def test_rw_watchpoint_delete(self):
         """Test delete watchpoint and expect not to stop for watchpoint."""
         self.build(dictionary=self.d)
@@ -137,6 +139,7 @@ class WatchpointCommandsTestCase(TestBas
 
     @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported
     @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows")
+    @expectedFailureAll(archs=['s390x']) # Read-write watchpoints not supported on SystemZ
     def test_rw_watchpoint_set_ignore_count(self):
         """Test watchpoint ignore count and expect to not to stop at all."""
         self.build(dictionary=self.d)
@@ -186,6 +189,7 @@ class WatchpointCommandsTestCase(TestBas
 
     @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported
     @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows")
+    @expectedFailureAll(archs=['s390x']) # Read-write watchpoints not supported on SystemZ
     def test_rw_disable_after_first_stop(self):
         """Test read_write watchpoint but disable it after the first stop."""
         self.build(dictionary=self.d)
@@ -245,6 +249,7 @@ class WatchpointCommandsTestCase(TestBas
 
     @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported
     @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows")
+    @expectedFailureAll(archs=['s390x']) # Read-write watchpoints not supported on SystemZ
     def test_rw_disable_then_enable(self):
         """Test read_write watchpoint, disable initially, then enable it."""
         self.build(dictionary=self.d)

Modified: lldb/trunk/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_events/TestWatchpointEvents.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_events/TestWatchpointEvents.py?rev=266308&r1=266307&r2=266308&view=diff
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_events/TestWatchpointEvents.py (original)
+++ lldb/trunk/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_events/TestWatchpointEvents.py Thu Apr 14 09:28:34 2016
@@ -59,7 +59,7 @@ class TestWatchpointEvents (TestBase):
         self.listener.StartListeningForEvents (self.target_bcast, lldb.SBTarget.eBroadcastBitWatchpointChanged)
 
         error = lldb.SBError()
-        local_watch = local_var.Watch(True, True, True, error)
+        local_watch = local_var.Watch(True, False, True, error)
         if not error.Success():
             self.fail ("Failed to make watchpoint for local_var: %s"%(error.GetCString()))
 

Modified: lldb/trunk/packages/Python/lldbsuite/test/lldbplatformutil.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/lldbplatformutil.py?rev=266308&r1=266307&r2=266308&view=diff
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/lldbplatformutil.py (original)
+++ lldb/trunk/packages/Python/lldbsuite/test/lldbplatformutil.py Thu Apr 14 09:28:34 2016
@@ -29,6 +29,8 @@ def check_first_register_readable(test_c
         test_case.expect("register read x0", substrs = ['x0 = 0x'])
     elif re.match("mips",arch):
         test_case.expect("register read zero", substrs = ['zero = 0x'])
+    elif arch in ['s390x']:
+    	test_case.expect("register read r0", substrs = ['r0 = 0x'])
     else:
         # TODO: Add check for other architectures
         test_case.fail("Unsupported architecture for test case (arch: %s)" % test_case.getArchitecture())

Modified: lldb/trunk/packages/Python/lldbsuite/test/make/Makefile.rules
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/make/Makefile.rules?rev=266308&r1=266307&r2=266308&view=diff
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/make/Makefile.rules (original)
+++ lldb/trunk/packages/Python/lldbsuite/test/make/Makefile.rules Thu Apr 14 09:28:34 2016
@@ -168,6 +168,10 @@ else
 		override ARCH :=
 		override ARCHFLAG :=
 	endif
+	ifeq "$(ARCH)" "s390x"
+		override ARCH :=
+		override ARCHFLAG :=
+	endif
 	ifeq "$(findstring mips,$(ARCH))" "mips"
 		override ARCHFLAG := -
 	endif

Modified: lldb/trunk/packages/Python/lldbsuite/test/python_api/watchpoint/TestSetWatchpoint.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/python_api/watchpoint/TestSetWatchpoint.py?rev=266308&r1=266307&r2=266308&view=diff
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/python_api/watchpoint/TestSetWatchpoint.py (original)
+++ lldb/trunk/packages/Python/lldbsuite/test/python_api/watchpoint/TestSetWatchpoint.py Thu Apr 14 09:28:34 2016
@@ -28,6 +28,7 @@ class SetWatchpointAPITestCase(TestBase)
     @add_test_categories(['pyapi'])
     @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported
     @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows")
+    @expectedFailureAll(archs=['s390x']) # Read-write watchpoints not supported on SystemZ
     def test_watch_val(self):
         """Exercise SBValue.Watch() API to set a watchpoint."""
         self.build()

Modified: lldb/trunk/packages/Python/lldbsuite/test/python_api/watchpoint/TestWatchpointIgnoreCount.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/python_api/watchpoint/TestWatchpointIgnoreCount.py?rev=266308&r1=266307&r2=266308&view=diff
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/python_api/watchpoint/TestWatchpointIgnoreCount.py (original)
+++ lldb/trunk/packages/Python/lldbsuite/test/python_api/watchpoint/TestWatchpointIgnoreCount.py Thu Apr 14 09:28:34 2016
@@ -28,6 +28,7 @@ class WatchpointIgnoreCountTestCase(Test
     @add_test_categories(['pyapi'])
     @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported
     @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24446: WINDOWS XFAIL TRIAGE - Watchpoints not supported on Windows")
+    @expectedFailureAll(archs=['s390x']) # Read-write watchpoints not supported on SystemZ
     def test_set_watch_ignore_count(self):
         """Test SBWatchpoint.SetIgnoreCount() API."""
         self.build()

Modified: lldb/trunk/packages/Python/lldbsuite/test/python_api/watchpoint/TestWatchpointIter.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/python_api/watchpoint/TestWatchpointIter.py?rev=266308&r1=266307&r2=266308&view=diff
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/python_api/watchpoint/TestWatchpointIter.py (original)
+++ lldb/trunk/packages/Python/lldbsuite/test/python_api/watchpoint/TestWatchpointIter.py Thu Apr 14 09:28:34 2016
@@ -58,7 +58,7 @@ class WatchpointIteratorTestCase(TestBas
         # Watch 'global' for read and write.
         value = frame0.FindValue('global', lldb.eValueTypeVariableGlobal)
         error = lldb.SBError();
-        watchpoint = value.Watch(True, True, True, error)
+        watchpoint = value.Watch(True, False, True, error)
         self.assertTrue(value and watchpoint,
                         "Successfully found the variable and set a watchpoint")
         self.DebugSBValue(value)

Modified: lldb/trunk/packages/Python/lldbsuite/test/python_api/watchpoint/watchlocation/TestTargetWatchAddress.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/python_api/watchpoint/watchlocation/TestTargetWatchAddress.py?rev=266308&r1=266307&r2=266308&view=diff
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/python_api/watchpoint/watchlocation/TestTargetWatchAddress.py (original)
+++ lldb/trunk/packages/Python/lldbsuite/test/python_api/watchpoint/watchlocation/TestTargetWatchAddress.py Thu Apr 14 09:28:34 2016
@@ -93,6 +93,7 @@ class TargetWatchAddressAPITestCase(Test
     @add_test_categories(['pyapi'])
     @expectedFailureAndroid(archs=['arm', 'aarch64']) # Watchpoints not supported
     @skipIf(archs=['mips', 'mipsel', 'mips64', 'mips64el']) # No size constraint on MIPS for watches
+    @skipIf(archs=['s390x']) # Likewise on SystemZ
     def test_watch_address_with_invalid_watch_size(self):
         """Exercise SBTarget.WatchAddress() API but pass an invalid watch_size."""
         self.build()

Modified: lldb/trunk/packages/Python/lldbsuite/test/tools/lldb-mi/control/TestMiExec.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/tools/lldb-mi/control/TestMiExec.py?rev=266308&r1=266307&r2=266308&view=diff
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/tools/lldb-mi/control/TestMiExec.py (original)
+++ lldb/trunk/packages/Python/lldbsuite/test/tools/lldb-mi/control/TestMiExec.py Thu Apr 14 09:28:34 2016
@@ -234,18 +234,20 @@ class MiExecTestCase(lldbmi_testcase.MiT
         # Test that --thread is optional
         self.runCmd("-exec-next-instruction --frame 0")
         self.expect("\^running")
-        self.expect("\*stopped,reason=\"end-stepping-range\".+?main\.cpp\",line=\"28\"")
+        # Depending on compiler, it can stop at different line
+        self.expect("\*stopped,reason=\"end-stepping-range\".+?main\.cpp\",line=\"(28|29)\"")
 
         # Test that --frame is optional
         self.runCmd("-exec-next-instruction --thread 1")
         self.expect("\^running")
-        self.expect("\*stopped,reason=\"end-stepping-range\".+?main\.cpp\",line=\"29\"")
+        # Depending on compiler, it can stop at different line
+        self.expect("\*stopped,reason=\"end-stepping-range\".+?main\.cpp\",line=\"(29|30)\"")
 
         # Test that both --thread and --frame are optional
         self.runCmd("-exec-next-instruction")
         self.expect("\^running")
         # Depending on compiler, it can stop at different line
-        self.expect("\*stopped,reason=\"end-stepping-range\".+?main\.cpp\",line=\"(29|30)\"")
+        self.expect("\*stopped,reason=\"end-stepping-range\".+?main\.cpp\",line=\"(29|30|31)\"")
 
         # Test that an invalid --thread is handled
         self.runCmd("-exec-next-instruction --thread 0")

Modified: lldb/trunk/packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py?rev=266308&r1=266307&r2=266308&view=diff
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py (original)
+++ lldb/trunk/packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py Thu Apr 14 09:28:34 2016
@@ -1355,6 +1355,9 @@ class GdbRemoteTestCaseBase(TestBase):
         #MIPS required "3" (ADDIU, SB, LD) machine instructions for updation of variable value
         if re.match("mips",arch):
            expected_step_count = 3
+        #S390X requires "2" (LARL, MVI) machine instructions for updation of variable value
+        if re.match("s390x",arch):
+           expected_step_count = 2
         self.assertEqual(step_count, expected_step_count)
 
         # Verify we hit the next state.

Modified: lldb/trunk/source/API/SystemInitializerFull.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SystemInitializerFull.cpp?rev=266308&r1=266307&r2=266308&view=diff
==============================================================================
--- lldb/trunk/source/API/SystemInitializerFull.cpp (original)
+++ lldb/trunk/source/API/SystemInitializerFull.cpp Thu Apr 14 09:28:34 2016
@@ -39,6 +39,7 @@
 #include "Plugins/ABI/SysV-mips64/ABISysV_mips64.h"
 #include "Plugins/ABI/SysV-ppc/ABISysV_ppc.h"
 #include "Plugins/ABI/SysV-ppc64/ABISysV_ppc64.h"
+#include "Plugins/ABI/SysV-s390x/ABISysV_s390x.h"
 #include "Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h"
 #include "Plugins/Disassembler/llvm/DisassemblerLLVMC.h"
 #include "Plugins/DynamicLoader/Static/DynamicLoaderStatic.h"
@@ -302,6 +303,7 @@ SystemInitializerFull::Initialize()
     ABISysV_ppc64::Initialize();
     ABISysV_mips::Initialize();
     ABISysV_mips64::Initialize();
+    ABISysV_s390x::Initialize();
     DisassemblerLLVMC::Initialize();
 
     JITLoaderGDB::Initialize();
@@ -430,6 +432,7 @@ SystemInitializerFull::Terminate()
     ABISysV_ppc64::Terminate();
     ABISysV_mips::Terminate();
     ABISysV_mips64::Terminate();
+    ABISysV_s390x::Terminate();
     DisassemblerLLVMC::Terminate();
 
     JITLoaderGDB::Terminate();

Modified: lldb/trunk/source/Core/ArchSpec.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ArchSpec.cpp?rev=266308&r1=266307&r2=266308&view=diff
==============================================================================
--- lldb/trunk/source/Core/ArchSpec.cpp (original)
+++ lldb/trunk/source/Core/ArchSpec.cpp Thu Apr 14 09:28:34 2016
@@ -130,6 +130,8 @@ static const CoreDefinition g_core_defin
     { eByteOrderBig   , 8, 4, 4, llvm::Triple::ppc64  , ArchSpec::eCore_ppc64_generic   , "powerpc64" },
     { eByteOrderBig   , 8, 4, 4, llvm::Triple::ppc64  , ArchSpec::eCore_ppc64_ppc970_64 , "ppc970-64" },
     
+    { eByteOrderBig   , 8, 2, 6, llvm::Triple::systemz, ArchSpec::eCore_s390x_generic   , "s390x"     },
+
     { eByteOrderLittle, 4, 4, 4, llvm::Triple::sparc  , ArchSpec::eCore_sparc_generic   , "sparc"     },
     { eByteOrderLittle, 8, 4, 4, llvm::Triple::sparcv9, ArchSpec::eCore_sparc9_generic  , "sparcv9"   },
 
@@ -285,6 +287,7 @@ static const ArchDefinitionEntry g_elf_a
     { ArchSpec::eCore_ppc64_generic   , llvm::ELF::EM_PPC64  , LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu }, // PowerPC64
     { ArchSpec::eCore_arm_generic     , llvm::ELF::EM_ARM    , LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu }, // ARM
     { ArchSpec::eCore_arm_aarch64     , llvm::ELF::EM_AARCH64, LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu }, // ARM64
+    { ArchSpec::eCore_s390x_generic   , llvm::ELF::EM_S390   , LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu }, // SystemZ
     { ArchSpec::eCore_sparc9_generic  , llvm::ELF::EM_SPARCV9, LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu }, // SPARC V9
     { ArchSpec::eCore_x86_64_x86_64   , llvm::ELF::EM_X86_64 , LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu }, // AMD64
     { ArchSpec::eCore_mips32          , llvm::ELF::EM_MIPS   , ArchSpec::eMIPSSubType_mips32,     0xFFFFFFFFu, 0xFFFFFFFFu }, // mips32

Modified: lldb/trunk/source/Host/common/HostInfoBase.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Host/common/HostInfoBase.cpp?rev=266308&r1=266307&r2=266308&view=diff
==============================================================================
--- lldb/trunk/source/Host/common/HostInfoBase.cpp (original)
+++ lldb/trunk/source/Host/common/HostInfoBase.cpp Thu Apr 14 09:28:34 2016
@@ -420,6 +420,7 @@ HostInfoBase::ComputeHostArchitectureSup
         case llvm::Triple::mips64:
         case llvm::Triple::mips64el:
         case llvm::Triple::sparcv9:
+        case llvm::Triple::systemz:
             arch_64.SetTriple(triple);
             break;
     }

Modified: lldb/trunk/source/Plugins/ABI/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ABI/CMakeLists.txt?rev=266308&r1=266307&r2=266308&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ABI/CMakeLists.txt (original)
+++ lldb/trunk/source/Plugins/ABI/CMakeLists.txt Thu Apr 14 09:28:34 2016
@@ -5,6 +5,7 @@ add_subdirectory(SysV-ppc)
 add_subdirectory(SysV-ppc64)
 add_subdirectory(SysV-mips)
 add_subdirectory(SysV-mips64)
+add_subdirectory(SysV-s390x)
 add_subdirectory(SysV-i386)
 add_subdirectory(SysV-x86_64)
 add_subdirectory(MacOSX-i386)

Added: lldb/trunk/source/Plugins/ABI/SysV-s390x/ABISysV_s390x.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ABI/SysV-s390x/ABISysV_s390x.cpp?rev=266308&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/ABI/SysV-s390x/ABISysV_s390x.cpp (added)
+++ lldb/trunk/source/Plugins/ABI/SysV-s390x/ABISysV_s390x.cpp Thu Apr 14 09:28:34 2016
@@ -0,0 +1,808 @@
+//===-- ABISysV_s390x.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_s390x.h"
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/Triple.h"
+
+// Project includes
+#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/ValueObjectMemory.h"
+#include "lldb/Core/ValueObjectRegister.h"
+#include "lldb/Symbol/UnwindPlan.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+enum dwarf_regnums
+{
+    // General Purpose Registers
+    dwarf_r0_s390x = 0,
+    dwarf_r1_s390x,
+    dwarf_r2_s390x,
+    dwarf_r3_s390x,
+    dwarf_r4_s390x,
+    dwarf_r5_s390x,
+    dwarf_r6_s390x,
+    dwarf_r7_s390x,
+    dwarf_r8_s390x,
+    dwarf_r9_s390x,
+    dwarf_r10_s390x,
+    dwarf_r11_s390x,
+    dwarf_r12_s390x,
+    dwarf_r13_s390x,
+    dwarf_r14_s390x,
+    dwarf_r15_s390x,
+    // Floating Point Registers / Vector Registers 0-15
+    dwarf_f0_s390x = 16,
+    dwarf_f2_s390x,
+    dwarf_f4_s390x,
+    dwarf_f6_s390x,
+    dwarf_f1_s390x,
+    dwarf_f3_s390x,
+    dwarf_f5_s390x,
+    dwarf_f7_s390x,
+    dwarf_f8_s390x,
+    dwarf_f10_s390x,
+    dwarf_f12_s390x,
+    dwarf_f14_s390x,
+    dwarf_f9_s390x,
+    dwarf_f11_s390x,
+    dwarf_f13_s390x,
+    dwarf_f15_s390x,
+    // Access Registers
+    dwarf_acr0_s390x = 48,
+    dwarf_acr1_s390x,
+    dwarf_acr2_s390x,
+    dwarf_acr3_s390x,
+    dwarf_acr4_s390x,
+    dwarf_acr5_s390x,
+    dwarf_acr6_s390x,
+    dwarf_acr7_s390x,
+    dwarf_acr8_s390x,
+    dwarf_acr9_s390x,
+    dwarf_acr10_s390x,
+    dwarf_acr11_s390x,
+    dwarf_acr12_s390x,
+    dwarf_acr13_s390x,
+    dwarf_acr14_s390x,
+    dwarf_acr15_s390x,
+    // Program Status Word
+    dwarf_pswm_s390x = 64,
+    dwarf_pswa_s390x,
+    // Vector Registers 16-31
+    dwarf_v16_s390x = 68,
+    dwarf_v18_s390x,
+    dwarf_v20_s390x,
+    dwarf_v22_s390x,
+    dwarf_v17_s390x,
+    dwarf_v19_s390x,
+    dwarf_v21_s390x,
+    dwarf_v23_s390x,
+    dwarf_v24_s390x,
+    dwarf_v26_s390x,
+    dwarf_v28_s390x,
+    dwarf_v30_s390x,
+    dwarf_v25_s390x,
+    dwarf_v27_s390x,
+    dwarf_v29_s390x,
+    dwarf_v31_s390x,
+};
+
+// RegisterKind: EHFrame, DWARF, Generic, Process Plugin, LLDB
+
+#define DEFINE_REG(name, size, alt, generic)                                                               \
+    {                                                                                                      \
+        #name, alt, size, 0, eEncodingUint, eFormatHex,                                                    \
+        { dwarf_##name##_s390x, dwarf_##name##_s390x, generic, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }, \
+        NULL, NULL,                                                                                        \
+    }
+
+static RegisterInfo g_register_infos[] =
+{
+    DEFINE_REG(r0, 8, nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_REG(r1, 8, nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_REG(r2, 8, "arg1", LLDB_REGNUM_GENERIC_ARG1),
+    DEFINE_REG(r3, 8, "arg2", LLDB_REGNUM_GENERIC_ARG2),
+    DEFINE_REG(r4, 8, "arg3", LLDB_REGNUM_GENERIC_ARG3),
+    DEFINE_REG(r5, 8, "arg4", LLDB_REGNUM_GENERIC_ARG4),
+    DEFINE_REG(r6, 8, "arg5", LLDB_REGNUM_GENERIC_ARG5),
+    DEFINE_REG(r7, 8, nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_REG(r8, 8, nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_REG(r9, 8, nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_REG(r10, 8, nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_REG(r11, 8, "fp", LLDB_REGNUM_GENERIC_FP),
+    DEFINE_REG(r12, 8, nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_REG(r13, 8, nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_REG(r14, 8, nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_REG(r15, 8, "sp", LLDB_REGNUM_GENERIC_SP),
+    DEFINE_REG(acr0, 4, nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_REG(acr1, 4, nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_REG(acr2, 4, nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_REG(acr3, 4, nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_REG(acr4, 4, nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_REG(acr5, 4, nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_REG(acr6, 4, nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_REG(acr7, 4, nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_REG(acr8, 4, nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_REG(acr9, 4, nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_REG(acr10, 4, nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_REG(acr11, 4, nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_REG(acr12, 4, nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_REG(acr13, 4, nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_REG(acr14, 4, nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_REG(acr15, 4, nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_REG(pswm, 8, "flags", LLDB_REGNUM_GENERIC_FLAGS),
+    DEFINE_REG(pswa, 8, "pc", LLDB_REGNUM_GENERIC_PC),
+    DEFINE_REG(f0, 8, nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_REG(f1, 8, nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_REG(f2, 8, nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_REG(f3, 8, nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_REG(f4, 8, nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_REG(f5, 8, nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_REG(f6, 8, nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_REG(f7, 8, nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_REG(f8, 8, nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_REG(f9, 8, nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_REG(f10, 8, nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_REG(f11, 8, nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_REG(f12, 8, nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_REG(f13, 8, nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_REG(f14, 8, nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_REG(f15, 8, nullptr, LLDB_INVALID_REGNUM),
+};
+
+static const uint32_t k_num_register_infos = llvm::array_lengthof(g_register_infos);
+static bool g_register_info_names_constified = false;
+
+const lldb_private::RegisterInfo *
+ABISysV_s390x::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_s390x::GetRedZoneSize() const
+{
+    return 0;
+}
+
+//------------------------------------------------------------------
+// Static Functions
+//------------------------------------------------------------------
+
+ABISP
+ABISysV_s390x::CreateInstance(const ArchSpec &arch)
+{
+    static ABISP g_abi_sp;
+    if (arch.GetTriple().getArch() == llvm::Triple::systemz)
+    {
+        if (!g_abi_sp)
+            g_abi_sp.reset(new ABISysV_s390x);
+        return g_abi_sp;
+    }
+    return ABISP();
+}
+
+bool
+ABISysV_s390x::PrepareTrivialCall(Thread &thread, addr_t sp, addr_t func_addr, addr_t return_addr,
+                                  llvm::ArrayRef<addr_t> args) const
+{
+    Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
+
+    if (log)
+    {
+        StreamString s;
+        s.Printf("ABISysV_s390x::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);
+
+        for (size_t i = 0; i < args.size(); ++i)
+            s.Printf(", arg%" PRIu64 " = 0x%" PRIx64, static_cast<uint64_t>(i + 1), args[i]);
+        s.PutCString(")");
+        log->PutCString(s.GetString().c_str());
+    }
+
+    RegisterContext *reg_ctx = thread.GetRegisterContext().get();
+    if (!reg_ctx)
+        return false;
+
+    const RegisterInfo *pc_reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
+    const RegisterInfo *sp_reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
+    const RegisterInfo *ra_reg_info = reg_ctx->GetRegisterInfoByName("r14", 0);
+    ProcessSP process_sp(thread.GetProcess());
+
+    // Allocate a new stack frame and space for stack arguments if necessary
+
+    addr_t arg_pos = 0;
+    if (args.size() > 5)
+    {
+        sp -= 8 * (args.size() - 5);
+        arg_pos = sp;
+    }
+
+    sp -= 160;
+
+    // Process arguments
+
+    for (size_t i = 0; i < args.size(); ++i)
+    {
+        if (i < 5)
+        {
+            const RegisterInfo *reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + i);
+            if (log)
+                log->Printf("About to write arg%" PRIu64 " (0x%" PRIx64 ") into %s", static_cast<uint64_t>(i + 1),
+                            args[i], reg_info->name);
+            if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, args[i]))
+                return false;
+        }
+        else
+        {
+            Error error;
+            if (log)
+                log->Printf("About to write arg%" PRIu64 " (0x%" PRIx64 ") onto stack", static_cast<uint64_t>(i + 1),
+                            args[i]);
+            if (!process_sp->WritePointerToMemory(arg_pos, args[i], error))
+                return false;
+            arg_pos += 8;
+        }
+    }
+
+    // %r14 is set to the return address
+
+    if (log)
+        log->Printf("Writing RA: 0x%" PRIx64, (uint64_t)return_addr);
+
+    if (!reg_ctx->WriteRegisterFromUnsigned(ra_reg_info, return_addr))
+        return false;
+
+    // %r15 is set to the actual stack value.
+
+    if (log)
+        log->Printf("Writing SP: 0x%" PRIx64, (uint64_t)sp);
+
+    if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_info, sp))
+        return false;
+
+    // %pc is set to the address of the called function.
+
+    if (log)
+        log->Printf("Writing PC: 0x%" PRIx64, (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 < 5)
+    {
+        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 + 8 - byte_size, byte_size,
+                                                             is_signed, scalar, error))
+        {
+            current_stack_argument += 8;
+            return true;
+        }
+        return false;
+    }
+    return true;
+}
+
+bool
+ABISysV_s390x::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;
+
+    uint32_t argument_register_ids[5];
+
+    argument_register_ids[0] =
+        reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1)->kinds[eRegisterKindLLDB];
+    argument_register_ids[1] =
+        reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG2)->kinds[eRegisterKindLLDB];
+    argument_register_ids[2] =
+        reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG3)->kinds[eRegisterKindLLDB];
+    argument_register_ids[3] =
+        reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG4)->kinds[eRegisterKindLLDB];
+    argument_register_ids[4] =
+        reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG5)->kinds[eRegisterKindLLDB];
+
+    unsigned int current_argument_register = 0;
+
+    return false;
+    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?
+        CompilerType compiler_type = value->GetCompilerType();
+        if (!compiler_type)
+            return false;
+        bool is_signed;
+
+        if (compiler_type.IsIntegerType(is_signed))
+        {
+            ReadIntegerArgument(value->GetScalar(), compiler_type.GetBitSize(&thread), is_signed, thread,
+                                argument_register_ids, current_argument_register, current_stack_argument);
+        }
+        else if (compiler_type.IsPointerType())
+        {
+            ReadIntegerArgument(value->GetScalar(), compiler_type.GetBitSize(&thread), false, thread,
+                                argument_register_ids, current_argument_register, current_stack_argument);
+        }
+    }
+
+    return true;
+}
+
+Error
+ABISysV_s390x::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;
+    }
+
+    CompilerType compiler_type = new_value_sp->GetCompilerType();
+    if (!compiler_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 (compiler_type.IsIntegerType(is_signed) || compiler_type.IsPointerType())
+    {
+        const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName("r2", 0);
+
+        DataExtractor data;
+        Error data_error;
+        size_t num_bytes = new_value_sp->GetData(data, data_error);
+        if (data_error.Fail())
+        {
+            error.SetErrorStringWithFormat("Couldn't convert return value to raw data: %s", data_error.AsCString());
+            return error;
+        }
+        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 (compiler_type.IsFloatingPointType(count, is_complex))
+    {
+        if (is_complex)
+            error.SetErrorString("We don't support returning complex values at present");
+        else
+        {
+            size_t bit_width = compiler_type.GetBitSize(frame_sp.get());
+            if (bit_width <= 64)
+            {
+                const RegisterInfo *f0_info = reg_ctx->GetRegisterInfoByName("f0", 0);
+                RegisterValue f0_value;
+                DataExtractor data;
+                Error data_error;
+                size_t num_bytes = new_value_sp->GetData(data, data_error);
+                if (data_error.Fail())
+                {
+                    error.SetErrorStringWithFormat("Couldn't convert return value to raw data: %s",
+                                                   data_error.AsCString());
+                    return error;
+                }
+
+                unsigned char buffer[8];
+                ByteOrder byte_order = data.GetByteOrder();
+
+                data.CopyByteOrderedData(0, num_bytes, buffer, 8, byte_order);
+                f0_value.SetBytes(buffer, 8, byte_order);
+                reg_ctx->WriteRegister(f0_info, f0_value);
+                set_it_simple = true;
+            }
+            else
+            {
+                // FIXME - don't know how to do 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_s390x::GetReturnValueObjectSimple(Thread &thread, CompilerType &return_compiler_type) const
+{
+    ValueObjectSP return_valobj_sp;
+    Value value;
+
+    if (!return_compiler_type)
+        return return_valobj_sp;
+
+    // value.SetContext (Value::eContextTypeClangType, return_value_type);
+    value.SetCompilerType(return_compiler_type);
+
+    RegisterContext *reg_ctx = thread.GetRegisterContext().get();
+    if (!reg_ctx)
+        return return_valobj_sp;
+
+    const uint32_t type_flags = return_compiler_type.GetTypeInfo();
+    if (type_flags & eTypeIsScalar)
+    {
+        value.SetValueType(Value::eValueTypeScalar);
+
+        bool success = false;
+        if (type_flags & eTypeIsInteger)
+        {
+            // Extract the register context so we can read arguments from registers
+
+            const size_t byte_size = return_compiler_type.GetByteSize(nullptr);
+            uint64_t raw_value =
+                thread.GetRegisterContext()->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("r2", 0), 0);
+            const bool is_signed = (type_flags & 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 & eTypeIsFloat)
+        {
+            if (type_flags & eTypeIsComplex)
+            {
+                // Don't handle complex yet.
+            }
+            else
+            {
+                const size_t byte_size = return_compiler_type.GetByteSize(nullptr);
+                if (byte_size <= sizeof(long double))
+                {
+                    const RegisterInfo *f0_info = reg_ctx->GetRegisterInfoByName("f0", 0);
+                    RegisterValue f0_value;
+                    if (reg_ctx->ReadRegister(f0_info, f0_value))
+                    {
+                        DataExtractor data;
+                        if (f0_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 yet.
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        if (success)
+            return_valobj_sp =
+                ValueObjectConstResult::Create(thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
+    }
+    else if (type_flags & eTypeIsPointer)
+    {
+        unsigned r2_id = reg_ctx->GetRegisterInfoByName("r2", 0)->kinds[eRegisterKindLLDB];
+        value.GetScalar() = (uint64_t)thread.GetRegisterContext()->ReadRegisterAsUnsigned(r2_id, 0);
+        value.SetValueType(Value::eValueTypeScalar);
+        return_valobj_sp = ValueObjectConstResult::Create(thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
+    }
+
+    return return_valobj_sp;
+}
+
+ValueObjectSP
+ABISysV_s390x::GetReturnValueObjectImpl(Thread &thread, CompilerType &return_compiler_type) const
+{
+    ValueObjectSP return_valobj_sp;
+
+    if (!return_compiler_type)
+        return return_valobj_sp;
+
+    ExecutionContext exe_ctx(thread.shared_from_this());
+    return_valobj_sp = GetReturnValueObjectSimple(thread, return_compiler_type);
+    if (return_valobj_sp)
+        return return_valobj_sp;
+
+    RegisterContextSP reg_ctx_sp = thread.GetRegisterContext();
+    if (!reg_ctx_sp)
+        return return_valobj_sp;
+
+    if (return_compiler_type.IsAggregateType())
+    {
+        // FIXME: This is just taking a guess, r2 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.
+
+        unsigned r2_id = reg_ctx_sp->GetRegisterInfoByName("r2", 0)->kinds[eRegisterKindLLDB];
+        lldb::addr_t storage_addr = (uint64_t)thread.GetRegisterContext()->ReadRegisterAsUnsigned(r2_id, 0);
+        return_valobj_sp = ValueObjectMemory::Create(&thread, "", Address(storage_addr, nullptr), return_compiler_type);
+    }
+
+    return return_valobj_sp;
+}
+
+bool
+ABISysV_s390x::CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan)
+{
+    unwind_plan.Clear();
+    unwind_plan.SetRegisterKind(eRegisterKindDWARF);
+
+    UnwindPlan::RowSP row(new UnwindPlan::Row);
+
+    // Our Call Frame Address is the stack pointer value + 160
+    row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r15_s390x, 160);
+
+    // The previous PC is in r14
+    row->SetRegisterLocationToRegister(dwarf_pswa_s390x, dwarf_r14_s390x, true);
+
+    // All other registers are the same.
+    unwind_plan.AppendRow(row);
+    unwind_plan.SetSourceName("s390x at-func-entry default");
+    unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
+    return true;
+}
+
+bool
+ABISysV_s390x::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan)
+{
+    // There's really no default way to unwind on s390x.
+    // Trust the .eh_frame CFI, which should always be good.
+    return false;
+}
+
+bool
+ABISysV_s390x::GetFallbackRegisterLocation (const RegisterInfo *reg_info,
+                                            UnwindPlan::Row::RegisterLocation &unwind_regloc)
+{
+    // 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.
+    if (RegisterIsVolatile(reg_info))
+    {
+        unwind_regloc.SetUndefined();
+        return true;
+    }
+
+    return false;
+}
+
+bool
+ABISysV_s390x::RegisterIsVolatile(const RegisterInfo *reg_info)
+{
+    return !RegisterIsCalleeSaved(reg_info);
+}
+
+bool
+ABISysV_s390x::RegisterIsCalleeSaved(const RegisterInfo *reg_info)
+{
+    if (reg_info)
+    {
+        // Preserved registers are :
+        //    r6-r13, r15
+        //    f8-f15
+
+        const char *name = reg_info->name;
+        if (name[0] == 'r')
+        {
+            switch (name[1])
+            {
+                case '6': // r6
+                case '7': // r7
+                case '8': // r8
+                case '9': // r9
+                    return name[2] == '\0';
+
+                case '1': // r10, r11, r12, r13, r15
+                    if ((name[2] >= '0' && name[2] <= '3') || name[2] == '5')
+                        return name[3] == '\0';
+                    break;
+
+                default:
+                    break;
+            }
+        }
+        if (name[0] == 'f')
+        {
+            switch (name[1])
+            {
+                case '8': // r8
+                case '9': // r9
+                    return name[2] == '\0';
+
+                case '1': // r10, r11, r12, r13, r14, r15
+                    if (name[2] >= '0' && name[2] <= '5')
+                        return name[3] == '\0';
+                    break;
+
+                default:
+                    break;
+            }
+        }
+
+        // Accept shorter-variant versions
+        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_s390x::Initialize()
+{
+    PluginManager::RegisterPlugin(GetPluginNameStatic(), "System V ABI for s390x targets", CreateInstance);
+}
+
+void
+ABISysV_s390x::Terminate()
+{
+    PluginManager::UnregisterPlugin(CreateInstance);
+}
+
+lldb_private::ConstString
+ABISysV_s390x::GetPluginNameStatic()
+{
+    static ConstString g_name("sysv-s390x");
+    return g_name;
+}
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+
+lldb_private::ConstString
+ABISysV_s390x::GetPluginName()
+{
+    return GetPluginNameStatic();
+}
+
+uint32_t
+ABISysV_s390x::GetPluginVersion()
+{
+    return 1;
+}

Added: lldb/trunk/source/Plugins/ABI/SysV-s390x/ABISysV_s390x.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ABI/SysV-s390x/ABISysV_s390x.h?rev=266308&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/ABI/SysV-s390x/ABISysV_s390x.h (added)
+++ lldb/trunk/source/Plugins/ABI/SysV-s390x/ABISysV_s390x.h Thu Apr 14 09:28:34 2016
@@ -0,0 +1,120 @@
+//===-- ABISysV_s390x.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_s390x_h_
+#define liblldb_ABISysV_s390x_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/lldb-private.h"
+#include "lldb/Target/ABI.h"
+
+class ABISysV_s390x : public lldb_private::ABI
+{
+public:
+    ~ABISysV_s390x() override = default;
+
+    size_t
+    GetRedZoneSize() const override;
+
+    bool
+    PrepareTrivialCall(lldb_private::Thread &thread, lldb::addr_t sp, lldb::addr_t functionAddress,
+                       lldb::addr_t returnAddress, llvm::ArrayRef<lldb::addr_t> args) const override;
+
+    bool
+    GetArgumentValues(lldb_private::Thread &thread, lldb_private::ValueList &values) const override;
+
+    lldb_private::Error
+    SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override;
+
+    lldb::ValueObjectSP
+    GetReturnValueObjectImpl(lldb_private::Thread &thread, lldb_private::CompilerType &type) const override;
+
+    bool
+    CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override;
+
+    bool
+    CreateDefaultUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override;
+
+    bool
+    RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override;
+
+    bool
+    GetFallbackRegisterLocation (const lldb_private::RegisterInfo *reg_info,
+                                 lldb_private::UnwindPlan::Row::RegisterLocation &unwind_regloc) override;
+
+    bool
+    CallFrameAddressIsValid(lldb::addr_t cfa) override
+    {
+        // Make sure the stack call frame addresses 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;
+    }
+
+    bool
+    CodeAddressIsValid(lldb::addr_t pc) override
+    {
+        // Code addressed must be 2 byte aligned
+        if (pc & 1ull)
+            return false;
+        return true;
+    }
+
+    const lldb_private::RegisterInfo *
+    GetRegisterInfoArray(uint32_t &count) override;
+
+    //------------------------------------------------------------------
+    // Static Functions
+    //------------------------------------------------------------------
+
+    static void
+    Initialize();
+
+    static void
+    Terminate();
+
+    static lldb::ABISP
+    CreateInstance(const lldb_private::ArchSpec &arch);
+
+    static lldb_private::ConstString
+    GetPluginNameStatic();
+
+    //------------------------------------------------------------------
+    // PluginInterface protocol
+    //------------------------------------------------------------------
+
+    lldb_private::ConstString
+    GetPluginName() override;
+
+    uint32_t
+    GetPluginVersion() override;
+
+protected:
+    void
+    CreateRegisterMapIfNeeded();
+
+    lldb::ValueObjectSP
+    GetReturnValueObjectSimple(lldb_private::Thread &thread, lldb_private::CompilerType &ast_type) const;
+
+    bool
+    RegisterIsCalleeSaved(const lldb_private::RegisterInfo *reg_info);
+
+private:
+    ABISysV_s390x() : lldb_private::ABI()
+    {
+        // Call CreateInstance instead.
+    }
+};
+
+#endif // liblldb_ABISysV_s390x_h_

Added: lldb/trunk/source/Plugins/ABI/SysV-s390x/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ABI/SysV-s390x/CMakeLists.txt?rev=266308&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/ABI/SysV-s390x/CMakeLists.txt (added)
+++ lldb/trunk/source/Plugins/ABI/SysV-s390x/CMakeLists.txt Thu Apr 14 09:28:34 2016
@@ -0,0 +1,3 @@
+add_lldb_library(lldbPluginABISysV_s390x
+  ABISysV_s390x.cpp
+  )

Modified: lldb/trunk/source/Plugins/ObjectFile/ELF/ELFHeader.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ObjectFile/ELF/ELFHeader.cpp?rev=266308&r1=266307&r2=266308&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ObjectFile/ELF/ELFHeader.cpp (original)
+++ lldb/trunk/source/Plugins/ObjectFile/ELF/ELFHeader.cpp Thu Apr 14 09:28:34 2016
@@ -198,6 +198,9 @@ ELFHeader::GetRelocationJumpSlotType() c
     case EM_MIPS:
         slot = R_MIPS_JUMP_SLOT;
         break;
+    case EM_S390:
+        slot = R_390_JMP_SLOT;
+        break;
     }
 
     return slot;

Modified: lldb/trunk/source/Plugins/Platform/Linux/PlatformLinux.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Platform/Linux/PlatformLinux.cpp?rev=266308&r1=266307&r2=266308&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Platform/Linux/PlatformLinux.cpp (original)
+++ lldb/trunk/source/Plugins/Platform/Linux/PlatformLinux.cpp Thu Apr 14 09:28:34 2016
@@ -485,6 +485,7 @@ PlatformLinux::GetSupportedArchitectureA
             case 6: triple.setArchName("mips"); break;
             case 7: triple.setArchName("mips64el"); break;
             case 8: triple.setArchName("mipsel"); break;
+            case 9: triple.setArchName("s390x"); break;
             default: return false;
         }
         // Leave the vendor as "llvm::Triple:UnknownVendor" and don't specify the vendor by

Modified: lldb/trunk/source/Plugins/Process/Linux/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/CMakeLists.txt?rev=266308&r1=266307&r2=266308&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/CMakeLists.txt (original)
+++ lldb/trunk/source/Plugins/Process/Linux/CMakeLists.txt Thu Apr 14 09:28:34 2016
@@ -9,6 +9,7 @@ add_lldb_library(lldbPluginProcessLinux
   NativeRegisterContextLinux_arm64.cpp
   NativeRegisterContextLinux_x86_64.cpp
   NativeRegisterContextLinux_mips64.cpp
+  NativeRegisterContextLinux_s390x.cpp
   NativeThreadLinux.cpp
   ProcFileReader.cpp
   SingleStepCheck.cpp

Modified: lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp?rev=266308&r1=266307&r2=266308&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp Thu Apr 14 09:28:34 2016
@@ -2247,6 +2247,7 @@ NativeProcessLinux::GetSoftwareBreakpoin
     // FIXME put this behind a breakpoint protocol class that can be
     // set per architecture.  Need ARM, MIPS support here.
     static const uint8_t g_i386_opcode [] = { 0xCC };
+    static const uint8_t g_s390x_opcode[] = { 0x00, 0x01 };
 
     switch (m_arch.GetMachine ())
     {
@@ -2255,6 +2256,10 @@ NativeProcessLinux::GetSoftwareBreakpoin
             actual_opcode_size = static_cast<uint32_t> (sizeof(g_i386_opcode));
             return Error ();
 
+        case llvm::Triple::systemz:
+            actual_opcode_size = static_cast<uint32_t> (sizeof(g_s390x_opcode));
+            return Error ();
+
         case llvm::Triple::arm:
         case llvm::Triple::aarch64:
         case llvm::Triple::mips64:
@@ -2294,6 +2299,7 @@ NativeProcessLinux::GetSoftwareBreakpoin
     static const uint8_t g_i386_opcode [] = { 0xCC };
     static const uint8_t g_mips64_opcode[] = { 0x00, 0x00, 0x00, 0x0d };
     static const uint8_t g_mips64el_opcode[] = { 0x0d, 0x00, 0x00, 0x00 };
+    static const uint8_t g_s390x_opcode[] = { 0x00, 0x01 };
     static const uint8_t g_thumb_breakpoint_opcode[] = { 0x01, 0xde };
 
     switch (m_arch.GetMachine ())
@@ -2337,6 +2343,11 @@ NativeProcessLinux::GetSoftwareBreakpoin
         actual_opcode_size = sizeof(g_mips64el_opcode);
         return Error ();
 
+    case llvm::Triple::systemz:
+        trap_opcode_bytes = g_s390x_opcode;
+        actual_opcode_size = sizeof(g_s390x_opcode);
+        return Error ();
+
     default:
         assert(false && "CPU type not supported!");
         return Error ("CPU type not supported");

Added: lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp?rev=266308&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp (added)
+++ lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.cpp Thu Apr 14 09:28:34 2016
@@ -0,0 +1,716 @@
+//===-- NativeRegisterContextLinux_s390x.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(__s390x__) && defined(__linux__)
+
+#include "NativeRegisterContextLinux_s390x.h"
+
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/RegisterValue.h"
+#include "lldb/Host/HostInfo.h"
+
+#include "Plugins/Process/Utility/RegisterContextLinux_s390x.h"
+
+#include <asm/ptrace.h>
+#include <linux/uio.h>
+#include <sys/ptrace.h>
+
+using namespace lldb_private;
+using namespace lldb_private::process_linux;
+
+// ----------------------------------------------------------------------------
+// Private namespace.
+// ----------------------------------------------------------------------------
+
+namespace
+{
+    // s390x 64-bit general purpose registers.
+    static const uint32_t g_gpr_regnums_s390x[] =
+    {
+        lldb_r0_s390x,
+        lldb_r1_s390x,
+        lldb_r2_s390x,
+        lldb_r3_s390x,
+        lldb_r4_s390x,
+        lldb_r5_s390x,
+        lldb_r6_s390x,
+        lldb_r7_s390x,
+        lldb_r8_s390x,
+        lldb_r9_s390x,
+        lldb_r10_s390x,
+        lldb_r11_s390x,
+        lldb_r12_s390x,
+        lldb_r13_s390x,
+        lldb_r14_s390x,
+        lldb_r15_s390x,
+        lldb_acr0_s390x,
+        lldb_acr1_s390x,
+        lldb_acr2_s390x,
+        lldb_acr3_s390x,
+        lldb_acr4_s390x,
+        lldb_acr5_s390x,
+        lldb_acr6_s390x,
+        lldb_acr7_s390x,
+        lldb_acr8_s390x,
+        lldb_acr9_s390x,
+        lldb_acr10_s390x,
+        lldb_acr11_s390x,
+        lldb_acr12_s390x,
+        lldb_acr13_s390x,
+        lldb_acr14_s390x,
+        lldb_acr15_s390x,
+        lldb_pswm_s390x,
+        lldb_pswa_s390x,
+        LLDB_INVALID_REGNUM // register sets need to end with this flag
+    };
+    static_assert((sizeof(g_gpr_regnums_s390x) / sizeof(g_gpr_regnums_s390x[0])) - 1 == k_num_gpr_registers_s390x,
+                  "g_gpr_regnums_s390x has wrong number of register infos");
+
+    // s390x 64-bit floating point registers.
+    static const uint32_t g_fpu_regnums_s390x[] =
+    {
+        lldb_f0_s390x,
+        lldb_f1_s390x,
+        lldb_f2_s390x,
+        lldb_f3_s390x,
+        lldb_f4_s390x,
+        lldb_f5_s390x,
+        lldb_f6_s390x,
+        lldb_f7_s390x,
+        lldb_f8_s390x,
+        lldb_f9_s390x,
+        lldb_f10_s390x,
+        lldb_f11_s390x,
+        lldb_f12_s390x,
+        lldb_f13_s390x,
+        lldb_f14_s390x,
+        lldb_f15_s390x,
+        lldb_fpc_s390x,
+        LLDB_INVALID_REGNUM // register sets need to end with this flag
+    };
+    static_assert((sizeof(g_fpu_regnums_s390x) / sizeof(g_fpu_regnums_s390x[0])) - 1 == k_num_fpr_registers_s390x,
+                  "g_fpu_regnums_s390x has wrong number of register infos");
+
+    // s390x Linux operating-system information.
+    static const uint32_t g_linux_regnums_s390x[] =
+    {
+        lldb_orig_r2_s390x,
+        lldb_last_break_s390x,
+        lldb_system_call_s390x,
+        LLDB_INVALID_REGNUM // register sets need to end with this flag
+    };
+    static_assert((sizeof(g_linux_regnums_s390x) / sizeof(g_linux_regnums_s390x[0])) - 1 == k_num_linux_registers_s390x,
+                  "g_linux_regnums_s390x has wrong number of register infos");
+
+    // Number of register sets provided by this context.
+    enum
+    {
+        k_num_register_sets = 3
+    };
+
+    // Register sets for s390x 64-bit.
+    static const RegisterSet g_reg_sets_s390x[k_num_register_sets] =
+    {
+        { "General Purpose Registers", "gpr", k_num_gpr_registers_s390x, g_gpr_regnums_s390x },
+        { "Floating Point Registers", "fpr", k_num_fpr_registers_s390x, g_fpu_regnums_s390x },
+        { "Linux Operating System Data", "linux", k_num_linux_registers_s390x, g_linux_regnums_s390x },
+    };
+}
+
+#define REG_CONTEXT_SIZE (sizeof(s390_regs) + sizeof(s390_fp_regs) + 4)
+
+// ----------------------------------------------------------------------------
+// Required ptrace defines.
+// ----------------------------------------------------------------------------
+
+#define NT_S390_LAST_BREAK  0x306 /* s390 breaking event address */
+#define NT_S390_SYSTEM_CALL 0x307 /* s390 system call restart data */
+
+NativeRegisterContextLinux *
+NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(const ArchSpec &target_arch,
+                                                                 NativeThreadProtocol &native_thread,
+                                                                 uint32_t concrete_frame_idx)
+{
+    return new NativeRegisterContextLinux_s390x(target_arch, native_thread, concrete_frame_idx);
+}
+
+// ----------------------------------------------------------------------------
+// NativeRegisterContextLinux_s390x members.
+// ----------------------------------------------------------------------------
+
+static RegisterInfoInterface *
+CreateRegisterInfoInterface(const ArchSpec &target_arch)
+{
+    assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) &&
+           "Register setting path assumes this is a 64-bit host");
+    return new RegisterContextLinux_s390x(target_arch);
+}
+
+NativeRegisterContextLinux_s390x::NativeRegisterContextLinux_s390x(const ArchSpec &target_arch,
+                                                                   NativeThreadProtocol &native_thread,
+                                                                   uint32_t concrete_frame_idx)
+    : NativeRegisterContextLinux(native_thread, concrete_frame_idx, CreateRegisterInfoInterface(target_arch))
+{
+    // Set up data about ranges of valid registers.
+    switch (target_arch.GetMachine())
+    {
+        case llvm::Triple::systemz:
+            m_reg_info.num_registers = k_num_registers_s390x;
+            m_reg_info.num_gpr_registers = k_num_gpr_registers_s390x;
+            m_reg_info.num_fpr_registers = k_num_fpr_registers_s390x;
+            m_reg_info.last_gpr = k_last_gpr_s390x;
+            m_reg_info.first_fpr = k_first_fpr_s390x;
+            m_reg_info.last_fpr = k_last_fpr_s390x;
+            break;
+        default:
+            assert(false && "Unhandled target architecture.");
+            break;
+    }
+
+    // Clear out the watchpoint state.
+    m_watchpoint_addr = LLDB_INVALID_ADDRESS;
+}
+
+uint32_t
+NativeRegisterContextLinux_s390x::GetRegisterSetCount() const
+{
+    uint32_t sets = 0;
+    for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index)
+    {
+        if (IsRegisterSetAvailable(set_index))
+            ++sets;
+    }
+
+    return sets;
+}
+
+uint32_t
+NativeRegisterContextLinux_s390x::GetUserRegisterCount() const
+{
+    uint32_t count = 0;
+    for (uint32_t set_index = 0; set_index < k_num_register_sets; ++set_index)
+    {
+        const RegisterSet *set = GetRegisterSet(set_index);
+        if (set)
+            count += set->num_registers;
+    }
+    return count;
+}
+
+const RegisterSet *
+NativeRegisterContextLinux_s390x::GetRegisterSet(uint32_t set_index) const
+{
+    if (!IsRegisterSetAvailable(set_index))
+        return nullptr;
+
+    switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine())
+    {
+        case llvm::Triple::systemz:
+            return &g_reg_sets_s390x[set_index];
+        default:
+            assert(false && "Unhandled target architecture.");
+            return nullptr;
+    }
+
+    return nullptr;
+}
+
+bool
+NativeRegisterContextLinux_s390x::IsRegisterSetAvailable(uint32_t set_index) const
+{
+    return set_index < k_num_register_sets;
+}
+
+bool
+NativeRegisterContextLinux_s390x::IsGPR(uint32_t reg_index) const
+{
+    // GPRs come first.  "orig_r2" counts as GPR since it is part of the GPR register area.
+    return reg_index <= m_reg_info.last_gpr || reg_index == lldb_orig_r2_s390x;
+}
+
+bool
+NativeRegisterContextLinux_s390x::IsFPR(uint32_t reg_index) const
+{
+    return (m_reg_info.first_fpr <= reg_index && reg_index <= m_reg_info.last_fpr);
+}
+
+Error
+NativeRegisterContextLinux_s390x::ReadRegister(const RegisterInfo *reg_info, RegisterValue &reg_value)
+{
+    if (!reg_info)
+        return Error("reg_info NULL");
+
+    const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
+    if (reg == LLDB_INVALID_REGNUM)
+        return Error("register \"%s\" is an internal-only lldb register, cannot read directly", reg_info->name);
+
+    if (IsGPR(reg))
+    {
+        s390_regs regs;
+        Error error = DoReadGPR(&regs, sizeof(regs));
+        if (error.Fail())
+            return error;
+
+        uint8_t *src = (uint8_t *)&regs + reg_info->byte_offset;
+        assert(reg_info->byte_offset + reg_info->byte_size <= sizeof(regs));
+        switch (reg_info->byte_size)
+        {
+            case 4:
+                reg_value.SetUInt32(*(uint32_t *)src);
+                break;
+            case 8:
+                reg_value.SetUInt64(*(uint64_t *)src);
+                break;
+            default:
+                assert(false && "Unhandled data size.");
+                return Error("unhandled byte size: %" PRIu32, reg_info->byte_size);
+        }
+        return Error();
+    }
+
+    if (IsFPR(reg))
+    {
+        s390_fp_regs fp_regs;
+        Error error = DoReadFPR(&fp_regs, sizeof(fp_regs));
+        if (error.Fail())
+            return error;
+
+        // byte_offset is just the offset within FPR, not the whole user area.
+        uint8_t *src = (uint8_t *)&fp_regs + reg_info->byte_offset;
+        assert(reg_info->byte_offset + reg_info->byte_size <= sizeof(fp_regs));
+        switch (reg_info->byte_size)
+        {
+            case 4:
+                reg_value.SetUInt32(*(uint32_t *)src);
+                break;
+            case 8:
+                reg_value.SetUInt64(*(uint64_t *)src);
+                break;
+            default:
+                assert(false && "Unhandled data size.");
+                return Error("unhandled byte size: %" PRIu32, reg_info->byte_size);
+        }
+        return Error();
+    }
+
+    if (reg == lldb_last_break_s390x)
+    {
+        uint64_t last_break;
+        Error error = DoReadRegisterSet(NT_S390_LAST_BREAK, &last_break, 8);
+        if (error.Fail())
+            return error;
+
+        reg_value.SetUInt64(last_break);
+        return Error();
+    }
+
+    if (reg == lldb_system_call_s390x)
+    {
+        uint32_t system_call;
+        Error error = DoReadRegisterSet(NT_S390_SYSTEM_CALL, &system_call, 4);
+        if (error.Fail())
+            return error;
+
+        reg_value.SetUInt32(system_call);
+        return Error();
+    }
+
+    return Error("failed - register wasn't recognized");
+}
+
+Error
+NativeRegisterContextLinux_s390x::WriteRegister(const RegisterInfo *reg_info, const RegisterValue &reg_value)
+{
+    if (!reg_info)
+        return Error("reg_info NULL");
+
+    const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
+    if (reg == LLDB_INVALID_REGNUM)
+        return Error("register \"%s\" is an internal-only lldb register, cannot write directly", reg_info->name);
+
+    if (IsGPR(reg))
+    {
+        s390_regs regs;
+        Error error = DoReadGPR(&regs, sizeof(regs));
+        if (error.Fail())
+            return error;
+
+        uint8_t *dst = (uint8_t *)&regs + reg_info->byte_offset;
+        assert(reg_info->byte_offset + reg_info->byte_size <= sizeof(regs));
+        switch (reg_info->byte_size)
+        {
+            case 4:
+                *(uint32_t *)dst = reg_value.GetAsUInt32();
+                break;
+            case 8:
+                *(uint64_t *)dst = reg_value.GetAsUInt64();
+                break;
+            default:
+                assert(false && "Unhandled data size.");
+                return Error("unhandled byte size: %" PRIu32, reg_info->byte_size);
+        }
+        return DoWriteGPR(&regs, sizeof(regs));
+    }
+
+    if (IsFPR(reg))
+    {
+        s390_fp_regs fp_regs;
+        Error error = DoReadFPR(&fp_regs, sizeof(fp_regs));
+        if (error.Fail())
+            return error;
+
+        // byte_offset is just the offset within fp_regs, not the whole user area.
+        uint8_t *dst = (uint8_t *)&fp_regs + reg_info->byte_offset;
+        assert(reg_info->byte_offset + reg_info->byte_size <= sizeof(fp_regs));
+        switch (reg_info->byte_size)
+        {
+            case 4:
+                *(uint32_t *)dst = reg_value.GetAsUInt32();
+                break;
+            case 8:
+                *(uint64_t *)dst = reg_value.GetAsUInt64();
+                break;
+            default:
+                assert(false && "Unhandled data size.");
+                return Error("unhandled byte size: %" PRIu32, reg_info->byte_size);
+        }
+        return DoWriteFPR(&fp_regs, sizeof(fp_regs));
+    }
+
+    if (reg == lldb_last_break_s390x)
+    {
+        return Error("The last break address is read-only");
+    }
+
+    if (reg == lldb_system_call_s390x)
+    {
+        uint32_t system_call = reg_value.GetAsUInt32();
+        return DoWriteRegisterSet(NT_S390_SYSTEM_CALL, &system_call, 4);
+    }
+
+    return Error("failed - register wasn't recognized");
+}
+
+Error
+NativeRegisterContextLinux_s390x::ReadAllRegisterValues(lldb::DataBufferSP &data_sp)
+{
+    Error error;
+
+    data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0));
+    if (!data_sp)
+    {
+        error.SetErrorStringWithFormat("failed to allocate DataBufferHeap instance of size %" PRIu64, REG_CONTEXT_SIZE);
+        return error;
+    }
+
+    uint8_t *dst = data_sp->GetBytes();
+    if (dst == nullptr)
+    {
+        error.SetErrorStringWithFormat("DataBufferHeap instance of size %" PRIu64 " returned a null pointer",
+                                       REG_CONTEXT_SIZE);
+        return error;
+    }
+
+    error = DoReadGPR(dst, sizeof(s390_regs));
+    dst += sizeof(s390_regs);
+    if (error.Fail())
+        return error;
+
+    error = DoReadFPR(dst, sizeof(s390_fp_regs));
+    dst += sizeof(s390_fp_regs);
+    if (error.Fail())
+        return error;
+
+    // Ignore errors if the regset is unsupported (happens on older kernels).
+    DoReadRegisterSet(NT_S390_SYSTEM_CALL, dst, 4);
+    dst += 4;
+
+    // To enable inferior function calls while the process is stopped in
+    // an interrupted system call, we need to clear the system call flag.
+    // It will be restored to its original value by WriteAllRegisterValues.
+    // Again we ignore error if the regset is unsupported.
+    uint32_t system_call = 0;
+    DoWriteRegisterSet(NT_S390_SYSTEM_CALL, &system_call, 4);
+
+    return error;
+}
+
+Error
+NativeRegisterContextLinux_s390x::WriteAllRegisterValues(const lldb::DataBufferSP &data_sp)
+{
+    Error error;
+
+    if (!data_sp)
+    {
+        error.SetErrorStringWithFormat("NativeRegisterContextLinux_s390x::%s invalid data_sp provided", __FUNCTION__);
+        return error;
+    }
+
+    if (data_sp->GetByteSize() != REG_CONTEXT_SIZE)
+    {
+        error.SetErrorStringWithFormat(
+            "NativeRegisterContextLinux_s390x::%s data_sp contained mismatched data size, expected %" PRIu64
+            ", actual %" PRIu64,
+            __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize());
+        return error;
+    }
+
+    uint8_t *src = data_sp->GetBytes();
+    if (src == nullptr)
+    {
+        error.SetErrorStringWithFormat(
+            "NativeRegisterContextLinux_s390x::%s DataBuffer::GetBytes() returned a null pointer", __FUNCTION__);
+        return error;
+    }
+
+    error = DoWriteGPR(src, sizeof(s390_regs));
+    src += sizeof(s390_regs);
+    if (error.Fail())
+        return error;
+
+    error = DoWriteFPR(src, sizeof(s390_fp_regs));
+    src += sizeof(s390_fp_regs);
+    if (error.Fail())
+        return error;
+
+    // Ignore errors if the regset is unsupported (happens on older kernels).
+    DoWriteRegisterSet(NT_S390_SYSTEM_CALL, src, 4);
+    src += 4;
+
+    return error;
+}
+
+Error
+NativeRegisterContextLinux_s390x::DoReadRegisterValue(uint32_t offset, const char *reg_name, uint32_t size,
+                                                      RegisterValue &value)
+{
+    return Error("DoReadRegisterValue unsupported");
+}
+
+Error
+NativeRegisterContextLinux_s390x::DoWriteRegisterValue(uint32_t offset, const char *reg_name,
+                                                       const RegisterValue &value)
+{
+    return Error("DoWriteRegisterValue unsupported");
+}
+
+Error
+NativeRegisterContextLinux_s390x::PeekUserArea(uint32_t offset, void *buf, size_t buf_size)
+{
+    ptrace_area parea;
+    parea.len = buf_size;
+    parea.process_addr = (addr_t)buf;
+    parea.kernel_addr = offset;
+
+    return NativeProcessLinux::PtraceWrapper(PTRACE_PEEKUSR_AREA, m_thread.GetID(), &parea);
+}
+
+Error
+NativeRegisterContextLinux_s390x::PokeUserArea(uint32_t offset, const void *buf, size_t buf_size)
+{
+    ptrace_area parea;
+    parea.len = buf_size;
+    parea.process_addr = (addr_t)buf;
+    parea.kernel_addr = offset;
+
+    return NativeProcessLinux::PtraceWrapper(PTRACE_POKEUSR_AREA, m_thread.GetID(), &parea);
+}
+
+Error
+NativeRegisterContextLinux_s390x::DoReadGPR(void *buf, size_t buf_size)
+{
+    assert(buf_size == sizeof(s390_regs));
+    return PeekUserArea(offsetof(user_regs_struct, psw), buf, buf_size);
+}
+
+Error
+NativeRegisterContextLinux_s390x::DoWriteGPR(void *buf, size_t buf_size)
+{
+    assert(buf_size == sizeof(s390_regs));
+    return PokeUserArea(offsetof(user_regs_struct, psw), buf, buf_size);
+}
+
+Error
+NativeRegisterContextLinux_s390x::DoReadFPR(void *buf, size_t buf_size)
+{
+    assert(buf_size == sizeof(s390_fp_regs));
+    return PeekUserArea(offsetof(user_regs_struct, fp_regs), buf, buf_size);
+}
+
+Error
+NativeRegisterContextLinux_s390x::DoWriteFPR(void *buf, size_t buf_size)
+{
+    assert(buf_size == sizeof(s390_fp_regs));
+    return PokeUserArea(offsetof(user_regs_struct, fp_regs), buf, buf_size);
+}
+
+Error
+NativeRegisterContextLinux_s390x::DoReadRegisterSet(uint32_t regset, void *buf, size_t buf_size)
+{
+    struct iovec iov;
+    iov.iov_base = buf;
+    iov.iov_len = buf_size;
+
+    return ReadRegisterSet(&iov, buf_size, regset);
+}
+
+Error
+NativeRegisterContextLinux_s390x::DoWriteRegisterSet(uint32_t regset, const void *buf, size_t buf_size)
+{
+    struct iovec iov;
+    iov.iov_base = const_cast<void *>(buf);
+    iov.iov_len = buf_size;
+
+    return WriteRegisterSet(&iov, buf_size, regset);
+}
+
+Error
+NativeRegisterContextLinux_s390x::IsWatchpointHit(uint32_t wp_index, bool &is_hit)
+{
+    per_lowcore_bits per_lowcore;
+
+    if (wp_index >= NumSupportedHardwareWatchpoints())
+        return Error("Watchpoint index out of range");
+
+    if (m_watchpoint_addr == LLDB_INVALID_ADDRESS)
+    {
+        is_hit = false;
+        return Error();
+    }
+
+    Error error = PeekUserArea(offsetof(user_regs_struct, per_info.lowcore), &per_lowcore, sizeof(per_lowcore));
+    if (error.Fail())
+    {
+        is_hit = false;
+        return error;
+    }
+
+    is_hit = (per_lowcore.perc_storage_alteration == 1 && per_lowcore.perc_store_real_address == 0);
+
+    if (is_hit)
+    {
+        // Do not report this watchpoint again.
+        memset(&per_lowcore, 0, sizeof(per_lowcore));
+        PokeUserArea(offsetof(user_regs_struct, per_info.lowcore), &per_lowcore, sizeof(per_lowcore));
+    }
+
+    return Error();
+}
+
+Error
+NativeRegisterContextLinux_s390x::GetWatchpointHitIndex(uint32_t &wp_index, lldb::addr_t trap_addr)
+{
+    uint32_t num_hw_wps = NumSupportedHardwareWatchpoints();
+    for (wp_index = 0; wp_index < num_hw_wps; ++wp_index)
+    {
+        bool is_hit;
+        Error error = IsWatchpointHit(wp_index, is_hit);
+        if (error.Fail())
+        {
+            wp_index = LLDB_INVALID_INDEX32;
+            return error;
+        }
+        else if (is_hit)
+        {
+            return error;
+        }
+    }
+    wp_index = LLDB_INVALID_INDEX32;
+    return Error();
+}
+
+Error
+NativeRegisterContextLinux_s390x::IsWatchpointVacant(uint32_t wp_index, bool &is_vacant)
+{
+    if (wp_index >= NumSupportedHardwareWatchpoints())
+        return Error("Watchpoint index out of range");
+
+    is_vacant = m_watchpoint_addr == LLDB_INVALID_ADDRESS;
+
+    return Error();
+}
+
+bool
+NativeRegisterContextLinux_s390x::ClearHardwareWatchpoint(uint32_t wp_index)
+{
+    per_struct per_info;
+
+    if (wp_index >= NumSupportedHardwareWatchpoints())
+        return false;
+
+    Error error = PeekUserArea(offsetof(user_regs_struct, per_info), &per_info, sizeof(per_info));
+    if (error.Fail())
+        return false;
+
+    per_info.control_regs.bits.em_storage_alteration = 0;
+    per_info.control_regs.bits.storage_alt_space_ctl = 0;
+    per_info.starting_addr = 0;
+    per_info.ending_addr = 0;
+
+    error = PokeUserArea(offsetof(user_regs_struct, per_info), &per_info, sizeof(per_info));
+    if (error.Fail())
+        return false;
+
+    m_watchpoint_addr = LLDB_INVALID_ADDRESS;
+    return true;
+}
+
+Error
+NativeRegisterContextLinux_s390x::ClearAllHardwareWatchpoints()
+{
+    if (ClearHardwareWatchpoint(0))
+        return Error();
+    return Error("Clearing all hardware watchpoints failed.");
+}
+
+uint32_t
+NativeRegisterContextLinux_s390x::SetHardwareWatchpoint(lldb::addr_t addr, size_t size, uint32_t watch_flags)
+{
+    per_struct per_info;
+
+    if (watch_flags != 0x1)
+        return LLDB_INVALID_INDEX32;
+
+    if (m_watchpoint_addr != LLDB_INVALID_ADDRESS)
+        return LLDB_INVALID_INDEX32;
+
+    Error error = PeekUserArea(offsetof(user_regs_struct, per_info), &per_info, sizeof(per_info));
+    if (error.Fail())
+        return LLDB_INVALID_INDEX32;
+
+    per_info.control_regs.bits.em_storage_alteration = 1;
+    per_info.control_regs.bits.storage_alt_space_ctl = 1;
+    per_info.starting_addr = addr;
+    per_info.ending_addr = addr + size - 1;
+
+    error = PokeUserArea(offsetof(user_regs_struct, per_info), &per_info, sizeof(per_info));
+    if (error.Fail())
+        return LLDB_INVALID_INDEX32;
+
+    m_watchpoint_addr = addr;
+    return 0;
+}
+
+lldb::addr_t
+NativeRegisterContextLinux_s390x::GetWatchpointAddress(uint32_t wp_index)
+{
+    if (wp_index >= NumSupportedHardwareWatchpoints())
+        return LLDB_INVALID_ADDRESS;
+    return m_watchpoint_addr;
+}
+
+uint32_t
+NativeRegisterContextLinux_s390x::NumSupportedHardwareWatchpoints()
+{
+    return 1;
+}
+
+#endif // defined(__s390x__) && defined(__linux__)

Added: lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.h?rev=266308&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.h (added)
+++ lldb/trunk/source/Plugins/Process/Linux/NativeRegisterContextLinux_s390x.h Thu Apr 14 09:28:34 2016
@@ -0,0 +1,141 @@
+//===-- NativeRegisterContextLinux_s390x.h ----------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#if defined(__s390x__) && defined(__linux__)
+
+#ifndef lldb_NativeRegisterContextLinux_s390x_h
+#define lldb_NativeRegisterContextLinux_s390x_h
+
+#include "Plugins/Process/Linux/NativeRegisterContextLinux.h"
+#include "Plugins/Process/Utility/RegisterContext_s390x.h"
+#include "Plugins/Process/Utility/lldb-s390x-register-enums.h"
+
+namespace lldb_private
+{
+namespace process_linux
+{
+
+class NativeProcessLinux;
+
+class NativeRegisterContextLinux_s390x : public NativeRegisterContextLinux
+{
+public:
+    NativeRegisterContextLinux_s390x(const ArchSpec &target_arch, NativeThreadProtocol &native_thread,
+                                     uint32_t concrete_frame_idx);
+
+    uint32_t
+    GetRegisterSetCount() const override;
+
+    const RegisterSet *
+    GetRegisterSet(uint32_t set_index) const override;
+
+    uint32_t
+    GetUserRegisterCount() const override;
+
+    Error
+    ReadRegister(const RegisterInfo *reg_info, RegisterValue &reg_value) override;
+
+    Error
+    WriteRegister(const RegisterInfo *reg_info, const RegisterValue &reg_value) override;
+
+    Error
+    ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
+
+    Error
+    WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
+
+    Error
+    IsWatchpointHit(uint32_t wp_index, bool &is_hit) override;
+
+    Error
+    GetWatchpointHitIndex(uint32_t &wp_index, lldb::addr_t trap_addr) override;
+
+    Error
+    IsWatchpointVacant(uint32_t wp_index, bool &is_vacant) override;
+
+    bool
+    ClearHardwareWatchpoint(uint32_t wp_index) override;
+
+    Error
+    ClearAllHardwareWatchpoints() override;
+
+    uint32_t
+    SetHardwareWatchpoint(lldb::addr_t addr, size_t size, uint32_t watch_flags) override;
+
+    lldb::addr_t
+    GetWatchpointAddress(uint32_t wp_index) override;
+
+    uint32_t
+    NumSupportedHardwareWatchpoints() override;
+
+protected:
+    Error
+    DoReadRegisterValue(uint32_t offset, const char *reg_name, uint32_t size, RegisterValue &value) override;
+
+    Error
+    DoWriteRegisterValue(uint32_t offset, const char *reg_name, const RegisterValue &value) override;
+
+    Error
+    DoReadGPR(void *buf, size_t buf_size) override;
+
+    Error
+    DoWriteGPR(void *buf, size_t buf_size) override;
+
+    Error
+    DoReadFPR(void *buf, size_t buf_size) override;
+
+    Error
+    DoWriteFPR(void *buf, size_t buf_size) override;
+
+private:
+    // Info about register ranges.
+    struct RegInfo
+    {
+        uint32_t num_registers;
+        uint32_t num_gpr_registers;
+        uint32_t num_fpr_registers;
+
+        uint32_t last_gpr;
+        uint32_t first_fpr;
+        uint32_t last_fpr;
+    };
+
+    // Private member variables.
+    RegInfo m_reg_info;
+    lldb::addr_t m_watchpoint_addr;
+
+    // Private member methods.
+    bool
+    IsRegisterSetAvailable(uint32_t set_index) const;
+
+    bool
+    IsGPR(uint32_t reg_index) const;
+
+    bool
+    IsFPR(uint32_t reg_index) const;
+
+    Error
+    PeekUserArea(uint32_t offset, void *buf, size_t buf_size);
+
+    Error
+    PokeUserArea(uint32_t offset, const void *buf, size_t buf_size);
+
+    Error
+    DoReadRegisterSet(uint32_t regset, void *buf, size_t buf_size);
+
+    Error
+    DoWriteRegisterSet(uint32_t regset, const void *buf, size_t buf_size);
+};
+
+} // namespace process_linux
+} // namespace lldb_private
+
+#endif // #ifndef lldb_NativeRegisterContextLinux_s390x_h
+
+#endif // defined(__s390x__) && defined(__linux__)

Modified: lldb/trunk/source/Plugins/Process/Utility/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Utility/CMakeLists.txt?rev=266308&r1=266307&r2=266308&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/CMakeLists.txt (original)
+++ lldb/trunk/source/Plugins/Process/Utility/CMakeLists.txt Thu Apr 14 09:28:34 2016
@@ -28,6 +28,7 @@ add_lldb_library(lldbPluginProcessUtilit
   RegisterContextLinux_x86_64.cpp
   RegisterContextLinux_mips64.cpp
   RegisterContextLinux_mips.cpp
+  RegisterContextLinux_s390x.cpp
   RegisterContextLLDB.cpp
   RegisterContextMacOSXFrameBackchain.cpp
   RegisterContextMach_arm.cpp
@@ -39,6 +40,7 @@ add_lldb_library(lldbPluginProcessUtilit
   RegisterContextPOSIX_arm64.cpp
   RegisterContextPOSIX_mips64.cpp
   RegisterContextPOSIX_powerpc.cpp
+  RegisterContextPOSIX_s390x.cpp
   RegisterContextPOSIX_x86.cpp
   RegisterContextThreadMemory.cpp
   StopInfoMachException.cpp

Added: lldb/trunk/source/Plugins/Process/Utility/RegisterContextLinux_s390x.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Utility/RegisterContextLinux_s390x.cpp?rev=266308&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/RegisterContextLinux_s390x.cpp (added)
+++ lldb/trunk/source/Plugins/Process/Utility/RegisterContextLinux_s390x.cpp Thu Apr 14 09:28:34 2016
@@ -0,0 +1,98 @@
+//===-- RegisterContextLinux_s390x.cpp --------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "RegisterContextPOSIX_s390x.h"
+#include "RegisterContextLinux_s390x.h"
+
+using namespace lldb_private;
+using namespace lldb;
+
+//---------------------------------------------------------------------------
+// Include RegisterInfos_s390x to declare our g_register_infos_s390x structure.
+//---------------------------------------------------------------------------
+#define DECLARE_REGISTER_INFOS_S390X_STRUCT
+#include "RegisterInfos_s390x.h"
+#undef DECLARE_REGISTER_INFOS_S390X_STRUCT
+
+static const RegisterInfo *
+GetRegisterInfoPtr(const ArchSpec &target_arch)
+{
+    switch (target_arch.GetMachine())
+    {
+        case llvm::Triple::systemz:
+            return g_register_infos_s390x;
+        default:
+            assert(false && "Unhandled target architecture.");
+            return nullptr;
+    }
+}
+
+static uint32_t
+GetRegisterInfoCount(const ArchSpec &target_arch)
+{
+    switch (target_arch.GetMachine())
+    {
+        case llvm::Triple::systemz:
+            return k_num_registers_s390x;
+        default:
+            assert(false && "Unhandled target architecture.");
+            return 0;
+    }
+}
+
+static uint32_t
+GetUserRegisterInfoCount(const ArchSpec &target_arch)
+{
+    switch (target_arch.GetMachine())
+    {
+        case llvm::Triple::systemz:
+            return k_num_user_registers_s390x + k_num_linux_registers_s390x;
+        default:
+            assert(false && "Unhandled target architecture.");
+            return 0;
+    }
+}
+
+RegisterContextLinux_s390x::RegisterContextLinux_s390x(const ArchSpec &target_arch)
+    : lldb_private::RegisterInfoInterface(target_arch),
+      m_register_info_p(GetRegisterInfoPtr(target_arch)),
+      m_register_info_count(GetRegisterInfoCount(target_arch)),
+      m_user_register_count(GetUserRegisterInfoCount(target_arch))
+{
+}
+
+const std::vector<lldb_private::RegisterInfo> *
+RegisterContextLinux_s390x::GetDynamicRegisterInfoP() const
+{
+    return &d_register_infos;
+}
+
+const RegisterInfo *
+RegisterContextLinux_s390x::GetRegisterInfo() const
+{
+    return m_register_info_p;
+}
+
+uint32_t
+RegisterContextLinux_s390x::GetRegisterCount() const
+{
+    return m_register_info_count;
+}
+
+uint32_t
+RegisterContextLinux_s390x::GetUserRegisterCount() const
+{
+    return m_user_register_count;
+}
+
+size_t
+RegisterContextLinux_s390x::GetGPRSize() const
+{
+    return 0;
+}

Added: lldb/trunk/source/Plugins/Process/Utility/RegisterContextLinux_s390x.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Utility/RegisterContextLinux_s390x.h?rev=266308&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/RegisterContextLinux_s390x.h (added)
+++ lldb/trunk/source/Plugins/Process/Utility/RegisterContextLinux_s390x.h Thu Apr 14 09:28:34 2016
@@ -0,0 +1,42 @@
+//===-- RegisterContextLinux_s390x.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_s390x_h_
+#define liblldb_RegisterContextLinux_s390x_h_
+
+#include "RegisterInfoInterface.h"
+
+class RegisterContextLinux_s390x : public lldb_private::RegisterInfoInterface
+{
+public:
+    RegisterContextLinux_s390x(const lldb_private::ArchSpec &target_arch);
+
+    size_t
+    GetGPRSize() const override;
+
+    const lldb_private::RegisterInfo *
+    GetRegisterInfo() const override;
+
+    uint32_t
+    GetRegisterCount() const override;
+
+    uint32_t
+    GetUserRegisterCount() const override;
+
+    const std::vector<lldb_private::RegisterInfo> *
+    GetDynamicRegisterInfoP() const override;
+
+private:
+    const lldb_private::RegisterInfo *m_register_info_p;
+    uint32_t m_register_info_count;
+    uint32_t m_user_register_count;
+    std::vector<lldb_private::RegisterInfo> d_register_infos;
+};
+
+#endif

Added: lldb/trunk/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.cpp?rev=266308&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.cpp (added)
+++ lldb/trunk/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.cpp Thu Apr 14 09:28:34 2016
@@ -0,0 +1,265 @@
+//===-- RegisterContextPOSIX_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 <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/Host/Endian.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+#include "llvm/Support/Compiler.h"
+
+#include "RegisterContext_s390x.h"
+#include "RegisterContextPOSIX_s390x.h"
+
+using namespace lldb_private;
+using namespace lldb;
+
+// s390x 64-bit general purpose registers.
+static const uint32_t g_gpr_regnums_s390x[] =
+{
+    lldb_r0_s390x,
+    lldb_r1_s390x,
+    lldb_r2_s390x,
+    lldb_r3_s390x,
+    lldb_r4_s390x,
+    lldb_r5_s390x,
+    lldb_r6_s390x,
+    lldb_r7_s390x,
+    lldb_r8_s390x,
+    lldb_r9_s390x,
+    lldb_r10_s390x,
+    lldb_r11_s390x,
+    lldb_r12_s390x,
+    lldb_r13_s390x,
+    lldb_r14_s390x,
+    lldb_r15_s390x,
+    lldb_acr0_s390x,
+    lldb_acr1_s390x,
+    lldb_acr2_s390x,
+    lldb_acr3_s390x,
+    lldb_acr4_s390x,
+    lldb_acr5_s390x,
+    lldb_acr6_s390x,
+    lldb_acr7_s390x,
+    lldb_acr8_s390x,
+    lldb_acr9_s390x,
+    lldb_acr10_s390x,
+    lldb_acr11_s390x,
+    lldb_acr12_s390x,
+    lldb_acr13_s390x,
+    lldb_acr14_s390x,
+    lldb_acr15_s390x,
+    lldb_pswm_s390x,
+    lldb_pswa_s390x,
+    LLDB_INVALID_REGNUM // register sets need to end with this flag
+};
+static_assert((sizeof(g_gpr_regnums_s390x) / sizeof(g_gpr_regnums_s390x[0])) - 1 == k_num_gpr_registers_s390x,
+              "g_gpr_regnums_s390x has wrong number of register infos");
+
+// s390x 64-bit floating point registers.
+static const uint32_t g_fpu_regnums_s390x[] =
+{
+    lldb_f0_s390x,
+    lldb_f1_s390x,
+    lldb_f2_s390x,
+    lldb_f3_s390x,
+    lldb_f4_s390x,
+    lldb_f5_s390x,
+    lldb_f6_s390x,
+    lldb_f7_s390x,
+    lldb_f8_s390x,
+    lldb_f9_s390x,
+    lldb_f10_s390x,
+    lldb_f11_s390x,
+    lldb_f12_s390x,
+    lldb_f13_s390x,
+    lldb_f14_s390x,
+    lldb_f15_s390x,
+    lldb_fpc_s390x,
+    LLDB_INVALID_REGNUM // register sets need to end with this flag
+};
+static_assert((sizeof(g_fpu_regnums_s390x) / sizeof(g_fpu_regnums_s390x[0])) - 1 == k_num_fpr_registers_s390x,
+              "g_fpu_regnums_s390x has wrong number of register infos");
+
+// Number of register sets provided by this context.
+enum
+{
+    k_num_register_sets = 2
+};
+
+// Register sets for s390x 64-bit.
+static const RegisterSet g_reg_sets_s390x[k_num_register_sets] =
+{
+    { "General Purpose Registers", "gpr", k_num_gpr_registers_s390x, g_gpr_regnums_s390x },
+    { "Floating Point Registers", "fpr", k_num_fpr_registers_s390x, g_fpu_regnums_s390x },
+};
+
+bool
+RegisterContextPOSIX_s390x::IsGPR(unsigned reg)
+{
+    return reg <= m_reg_info.last_gpr; // GPRs come first.
+}
+
+bool
+RegisterContextPOSIX_s390x::IsFPR(unsigned reg)
+{
+    return (m_reg_info.first_fpr <= reg && reg <= m_reg_info.last_fpr);
+}
+
+RegisterContextPOSIX_s390x::RegisterContextPOSIX_s390x(Thread &thread, uint32_t concrete_frame_idx,
+                                                       RegisterInfoInterface *register_info)
+    : RegisterContext(thread, concrete_frame_idx)
+{
+    m_register_info_ap.reset(register_info);
+
+    switch (register_info->m_target_arch.GetMachine())
+    {
+        case llvm::Triple::systemz:
+            m_reg_info.num_registers = k_num_registers_s390x;
+            m_reg_info.num_gpr_registers = k_num_gpr_registers_s390x;
+            m_reg_info.num_fpr_registers = k_num_fpr_registers_s390x;
+            m_reg_info.last_gpr = k_last_gpr_s390x;
+            m_reg_info.first_fpr = k_first_fpr_s390x;
+            m_reg_info.last_fpr = k_last_fpr_s390x;
+            break;
+        default:
+            assert(false && "Unhandled target architecture.");
+            break;
+    }
+}
+
+RegisterContextPOSIX_s390x::~RegisterContextPOSIX_s390x()
+{
+}
+
+void
+RegisterContextPOSIX_s390x::Invalidate()
+{
+}
+
+void
+RegisterContextPOSIX_s390x::InvalidateAllRegisters()
+{
+}
+
+const RegisterInfo *
+RegisterContextPOSIX_s390x::GetRegisterInfo()
+{
+    return m_register_info_ap->GetRegisterInfo();
+}
+
+const RegisterInfo *
+RegisterContextPOSIX_s390x::GetRegisterInfoAtIndex(size_t reg)
+{
+    if (reg < m_reg_info.num_registers)
+        return &GetRegisterInfo()[reg];
+    else
+        return NULL;
+}
+
+size_t
+RegisterContextPOSIX_s390x::GetRegisterCount()
+{
+    return m_reg_info.num_registers;
+}
+
+unsigned
+RegisterContextPOSIX_s390x::GetRegisterOffset(unsigned reg)
+{
+    assert(reg < m_reg_info.num_registers && "Invalid register number.");
+    return GetRegisterInfo()[reg].byte_offset;
+}
+
+unsigned
+RegisterContextPOSIX_s390x::GetRegisterSize(unsigned reg)
+{
+    assert(reg < m_reg_info.num_registers && "Invalid register number.");
+    return GetRegisterInfo()[reg].byte_size;
+}
+
+const char *
+RegisterContextPOSIX_s390x::GetRegisterName(unsigned reg)
+{
+    assert(reg < m_reg_info.num_registers && "Invalid register offset.");
+    return GetRegisterInfo()[reg].name;
+}
+
+bool
+RegisterContextPOSIX_s390x::IsRegisterSetAvailable(size_t set_index)
+{
+    return set_index < k_num_register_sets;
+}
+
+size_t
+RegisterContextPOSIX_s390x::GetRegisterSetCount()
+{
+    size_t sets = 0;
+    for (size_t set = 0; set < k_num_register_sets; ++set)
+    {
+        if (IsRegisterSetAvailable(set))
+            ++sets;
+    }
+
+    return sets;
+}
+
+const RegisterSet *
+RegisterContextPOSIX_s390x::GetRegisterSet(size_t set)
+{
+    if (IsRegisterSetAvailable(set))
+    {
+        switch (m_register_info_ap->m_target_arch.GetMachine())
+        {
+            case llvm::Triple::systemz:
+                return &g_reg_sets_s390x[set];
+            default:
+                assert(false && "Unhandled target architecture.");
+                return NULL;
+        }
+    }
+    return NULL;
+}
+
+lldb::ByteOrder
+RegisterContextPOSIX_s390x::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;
+}
+
+// Used when parsing DWARF and EH frame information and any other
+// object file sections that contain register numbers in them.
+uint32_t
+RegisterContextPOSIX_s390x::ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num)
+{
+    const uint32_t num_regs = GetRegisterCount();
+
+    assert(kind < kNumRegisterKinds);
+    for (uint32_t reg_idx = 0; reg_idx < num_regs; ++reg_idx)
+    {
+        const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg_idx);
+
+        if (reg_info->kinds[kind] == num)
+            return reg_idx;
+    }
+
+    return LLDB_INVALID_REGNUM;
+}

Added: lldb/trunk/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.h?rev=266308&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.h (added)
+++ lldb/trunk/source/Plugins/Process/Utility/RegisterContextPOSIX_s390x.h Thu Apr 14 09:28:34 2016
@@ -0,0 +1,103 @@
+//===-- RegisterContextPOSIX_s390x.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_s390x_h_
+#define liblldb_RegisterContextPOSIX_s390x_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/Log.h"
+#include "lldb/Target/RegisterContext.h"
+#include "RegisterInfoInterface.h"
+#include "RegisterContext_s390x.h"
+#include "lldb-s390x-register-enums.h"
+
+class ProcessMonitor;
+
+class RegisterContextPOSIX_s390x : public lldb_private::RegisterContext
+{
+public:
+    RegisterContextPOSIX_s390x(lldb_private::Thread &thread, uint32_t concrete_frame_idx,
+                               lldb_private::RegisterInfoInterface *register_info);
+
+    ~RegisterContextPOSIX_s390x() override;
+
+    void
+    Invalidate();
+
+    void
+    InvalidateAllRegisters() override;
+
+    size_t
+    GetRegisterCount() override;
+
+    virtual unsigned
+    GetRegisterSize(unsigned reg);
+
+    virtual unsigned
+    GetRegisterOffset(unsigned reg);
+
+    const lldb_private::RegisterInfo *
+    GetRegisterInfoAtIndex(size_t reg) override;
+
+    size_t
+    GetRegisterSetCount() override;
+
+    const lldb_private::RegisterSet *
+    GetRegisterSet(size_t set) override;
+
+    const char *
+    GetRegisterName(unsigned reg);
+
+    uint32_t
+    ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num) override;
+
+protected:
+    struct RegInfo
+    {
+        uint32_t num_registers;
+        uint32_t num_gpr_registers;
+        uint32_t num_fpr_registers;
+
+        uint32_t last_gpr;
+        uint32_t first_fpr;
+        uint32_t last_fpr;
+    };
+
+    RegInfo m_reg_info;
+    std::unique_ptr<lldb_private::RegisterInfoInterface> m_register_info_ap;
+
+    virtual bool
+    IsRegisterSetAvailable(size_t set_index);
+
+    virtual const lldb_private::RegisterInfo *
+    GetRegisterInfo();
+
+    bool
+    IsGPR(unsigned reg);
+
+    bool
+    IsFPR(unsigned reg);
+
+    lldb::ByteOrder
+    GetByteOrder();
+
+    virtual bool
+    ReadGPR() = 0;
+    virtual bool
+    ReadFPR() = 0;
+    virtual bool
+    WriteGPR() = 0;
+    virtual bool
+    WriteFPR() = 0;
+};
+
+#endif // liblldb_RegisterContextPOSIX_s390x_h_

Added: lldb/trunk/source/Plugins/Process/Utility/RegisterContext_s390x.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Utility/RegisterContext_s390x.h?rev=266308&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/RegisterContext_s390x.h (added)
+++ lldb/trunk/source/Plugins/Process/Utility/RegisterContext_s390x.h Thu Apr 14 09:28:34 2016
@@ -0,0 +1,93 @@
+//===-- RegisterContext_s390x.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_s390x_h_
+#define liblldb_RegisterContext_s390x_h_
+
+//---------------------------------------------------------------------------
+// SystemZ ehframe, dwarf regnums
+//---------------------------------------------------------------------------
+
+// EHFrame and DWARF Register numbers (eRegisterKindEHFrame & eRegisterKindDWARF)
+enum
+{
+    // General Purpose Registers
+    dwarf_r0_s390x = 0,
+    dwarf_r1_s390x,
+    dwarf_r2_s390x,
+    dwarf_r3_s390x,
+    dwarf_r4_s390x,
+    dwarf_r5_s390x,
+    dwarf_r6_s390x,
+    dwarf_r7_s390x,
+    dwarf_r8_s390x,
+    dwarf_r9_s390x,
+    dwarf_r10_s390x,
+    dwarf_r11_s390x,
+    dwarf_r12_s390x,
+    dwarf_r13_s390x,
+    dwarf_r14_s390x,
+    dwarf_r15_s390x,
+    // Floating Point Registers / Vector Registers 0-15
+    dwarf_f0_s390x = 16,
+    dwarf_f2_s390x,
+    dwarf_f4_s390x,
+    dwarf_f6_s390x,
+    dwarf_f1_s390x,
+    dwarf_f3_s390x,
+    dwarf_f5_s390x,
+    dwarf_f7_s390x,
+    dwarf_f8_s390x,
+    dwarf_f10_s390x,
+    dwarf_f12_s390x,
+    dwarf_f14_s390x,
+    dwarf_f9_s390x,
+    dwarf_f11_s390x,
+    dwarf_f13_s390x,
+    dwarf_f15_s390x,
+    // Access Registers
+    dwarf_acr0_s390x = 48,
+    dwarf_acr1_s390x,
+    dwarf_acr2_s390x,
+    dwarf_acr3_s390x,
+    dwarf_acr4_s390x,
+    dwarf_acr5_s390x,
+    dwarf_acr6_s390x,
+    dwarf_acr7_s390x,
+    dwarf_acr8_s390x,
+    dwarf_acr9_s390x,
+    dwarf_acr10_s390x,
+    dwarf_acr11_s390x,
+    dwarf_acr12_s390x,
+    dwarf_acr13_s390x,
+    dwarf_acr14_s390x,
+    dwarf_acr15_s390x,
+    // Program Status Word
+    dwarf_pswm_s390x = 64,
+    dwarf_pswa_s390x,
+    // Vector Registers 16-31
+    dwarf_v16_s390x = 68,
+    dwarf_v18_s390x,
+    dwarf_v20_s390x,
+    dwarf_v22_s390x,
+    dwarf_v17_s390x,
+    dwarf_v19_s390x,
+    dwarf_v21_s390x,
+    dwarf_v23_s390x,
+    dwarf_v24_s390x,
+    dwarf_v26_s390x,
+    dwarf_v28_s390x,
+    dwarf_v30_s390x,
+    dwarf_v25_s390x,
+    dwarf_v27_s390x,
+    dwarf_v29_s390x,
+    dwarf_v31_s390x,
+};
+
+#endif

Added: lldb/trunk/source/Plugins/Process/Utility/RegisterInfos_s390x.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Utility/RegisterInfos_s390x.h?rev=266308&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/RegisterInfos_s390x.h (added)
+++ lldb/trunk/source/Plugins/Process/Utility/RegisterInfos_s390x.h Thu Apr 14 09:28:34 2016
@@ -0,0 +1,132 @@
+//===-- RegisterInfos_s390x.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
+#include <stddef.h>
+
+// C++ Includes
+// Other libraries and framework includes
+#include "llvm/Support/Compiler.h"
+
+// Project includes
+
+#ifdef DECLARE_REGISTER_INFOS_S390X_STRUCT
+
+// Computes the offset of the given GPR in the user data area.
+#define GPR_OFFSET(num) (16 + 8 * num)
+// Computes the offset of the given ACR in the user data area.
+#define ACR_OFFSET(num) (16 + 8 * 16 + 4 * num)
+// Computes the offset of the given FPR in the extended data area.
+#define FPR_OFFSET(num) (8 + 8 * num)
+
+// RegisterKind: EHFrame, DWARF, Generic, Process Plugin, LLDB
+
+#define DEFINE_GPR(name, size, offset, alt, generic)                                                                   \
+    {                                                                                                                  \
+        #name, alt, size, offset, eEncodingUint, eFormatHex,                                                           \
+        { dwarf_##name##_s390x, dwarf_##name##_s390x, generic, LLDB_INVALID_REGNUM, lldb_##name##_s390x },             \
+        NULL, NULL,                                                                                                    \
+    }
+
+#define DEFINE_GPR_NODWARF(name, size, offset, alt, generic)                                                           \
+    {                                                                                                                  \
+        #name, alt, size, offset, eEncodingUint, eFormatHex,                                                           \
+        { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, generic, LLDB_INVALID_REGNUM, lldb_##name##_s390x },               \
+        NULL, NULL,                                                                                                    \
+    }
+
+#define DEFINE_FPR(name, size, offset)                                                                                 \
+    {                                                                                                                  \
+        #name, NULL, size, offset, eEncodingUint, eFormatHex,                                                          \
+        { dwarf_##name##_s390x, dwarf_##name##_s390x, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_##name##_s390x }, \
+        NULL, NULL,                                                                                                    \
+    }
+
+#define DEFINE_FPR_NODWARF(name, size, offset)                                                                         \
+    {                                                                                                                  \
+        #name, NULL, size, offset, eEncodingUint, eFormatHex,                                                          \
+        { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_##name##_s390x },   \
+        NULL, NULL,                                                                                                    \
+    }
+
+static RegisterInfo g_register_infos_s390x[] =
+{
+    // General purpose registers.
+    DEFINE_GPR(r0, 8, GPR_OFFSET(0), nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_GPR(r1, 8, GPR_OFFSET(1), nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_GPR(r2, 8, GPR_OFFSET(2), "arg1", LLDB_REGNUM_GENERIC_ARG1),
+    DEFINE_GPR(r3, 8, GPR_OFFSET(3), "arg2", LLDB_REGNUM_GENERIC_ARG2),
+    DEFINE_GPR(r4, 8, GPR_OFFSET(4), "arg3", LLDB_REGNUM_GENERIC_ARG3),
+    DEFINE_GPR(r5, 8, GPR_OFFSET(5), "arg4", LLDB_REGNUM_GENERIC_ARG4),
+    DEFINE_GPR(r6, 8, GPR_OFFSET(6), "arg5", LLDB_REGNUM_GENERIC_ARG5),
+    DEFINE_GPR(r7, 8, GPR_OFFSET(7), nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_GPR(r8, 8, GPR_OFFSET(8), nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_GPR(r9, 8, GPR_OFFSET(9), nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_GPR(r10, 8, GPR_OFFSET(10), nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_GPR(r11, 8, GPR_OFFSET(11), "fp", LLDB_REGNUM_GENERIC_FP),
+    DEFINE_GPR(r12, 8, GPR_OFFSET(12), nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_GPR(r13, 8, GPR_OFFSET(13), nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_GPR(r14, 8, GPR_OFFSET(14), nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_GPR(r15, 8, GPR_OFFSET(15), "sp", LLDB_REGNUM_GENERIC_SP),
+    DEFINE_GPR(acr0, 4, ACR_OFFSET(0), nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_GPR(acr1, 4, ACR_OFFSET(1), nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_GPR(acr2, 4, ACR_OFFSET(2), nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_GPR(acr3, 4, ACR_OFFSET(3), nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_GPR(acr4, 4, ACR_OFFSET(4), nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_GPR(acr5, 4, ACR_OFFSET(5), nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_GPR(acr6, 4, ACR_OFFSET(6), nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_GPR(acr7, 4, ACR_OFFSET(7), nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_GPR(acr8, 4, ACR_OFFSET(8), nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_GPR(acr9, 4, ACR_OFFSET(9), nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_GPR(acr10, 4, ACR_OFFSET(10), nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_GPR(acr11, 4, ACR_OFFSET(11), nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_GPR(acr12, 4, ACR_OFFSET(12), nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_GPR(acr13, 4, ACR_OFFSET(13), nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_GPR(acr14, 4, ACR_OFFSET(14), nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_GPR(acr15, 4, ACR_OFFSET(15), nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_GPR(pswm, 8, 0, "flags", LLDB_REGNUM_GENERIC_FLAGS),
+    DEFINE_GPR(pswa, 8, 8, "pc", LLDB_REGNUM_GENERIC_PC),
+
+    // Floating point registers.
+    DEFINE_FPR(f0, 8, FPR_OFFSET(0)),
+    DEFINE_FPR(f1, 8, FPR_OFFSET(1)),
+    DEFINE_FPR(f2, 8, FPR_OFFSET(2)),
+    DEFINE_FPR(f3, 8, FPR_OFFSET(3)),
+    DEFINE_FPR(f4, 8, FPR_OFFSET(4)),
+    DEFINE_FPR(f5, 8, FPR_OFFSET(5)),
+    DEFINE_FPR(f6, 8, FPR_OFFSET(6)),
+    DEFINE_FPR(f7, 8, FPR_OFFSET(7)),
+    DEFINE_FPR(f8, 8, FPR_OFFSET(8)),
+    DEFINE_FPR(f9, 8, FPR_OFFSET(9)),
+    DEFINE_FPR(f10, 8, FPR_OFFSET(10)),
+    DEFINE_FPR(f11, 8, FPR_OFFSET(11)),
+    DEFINE_FPR(f12, 8, FPR_OFFSET(12)),
+    DEFINE_FPR(f13, 8, FPR_OFFSET(13)),
+    DEFINE_FPR(f14, 8, FPR_OFFSET(14)),
+    DEFINE_FPR(f15, 8, FPR_OFFSET(15)),
+    DEFINE_FPR_NODWARF(fpc, 4, 0),
+
+    // Linux operating-specific info.
+    DEFINE_GPR_NODWARF(orig_r2, 8, 16 + 16 * 8 + 16 * 4, nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_GPR_NODWARF(last_break, 8, 0, nullptr, LLDB_INVALID_REGNUM),
+    DEFINE_GPR_NODWARF(system_call, 4, 0, nullptr, LLDB_INVALID_REGNUM),
+};
+
+static_assert((sizeof(g_register_infos_s390x) / sizeof(g_register_infos_s390x[0])) == k_num_registers_s390x,
+              "g_register_infos_s390x has wrong number of register infos");
+
+#undef GPR_OFFSET
+#undef ACR_OFFSET
+#undef FPR_OFFSET
+#undef DEFINE_GPR
+#undef DEFINE_GPR_NODWARF
+#undef DEFINE_FPR
+#undef DEFINE_FPR_NODWARF
+
+#endif // DECLARE_REGISTER_INFOS_S390X_STRUCT

Added: lldb/trunk/source/Plugins/Process/Utility/lldb-s390x-register-enums.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Utility/lldb-s390x-register-enums.h?rev=266308&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Process/Utility/lldb-s390x-register-enums.h (added)
+++ lldb/trunk/source/Plugins/Process/Utility/lldb-s390x-register-enums.h Thu Apr 14 09:28:34 2016
@@ -0,0 +1,94 @@
+//===-- lldb-s390x-register-enums.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_s390x_register_enums_h
+#define lldb_s390x_register_enums_h
+
+namespace lldb_private
+{
+// LLDB register codes (e.g. RegisterKind == eRegisterKindLLDB)
+
+//---------------------------------------------------------------------------
+// Internal codes for all s390x registers.
+//---------------------------------------------------------------------------
+enum
+{
+    k_first_gpr_s390x,
+    lldb_r0_s390x = k_first_gpr_s390x,
+    lldb_r1_s390x,
+    lldb_r2_s390x,
+    lldb_r3_s390x,
+    lldb_r4_s390x,
+    lldb_r5_s390x,
+    lldb_r6_s390x,
+    lldb_r7_s390x,
+    lldb_r8_s390x,
+    lldb_r9_s390x,
+    lldb_r10_s390x,
+    lldb_r11_s390x,
+    lldb_r12_s390x,
+    lldb_r13_s390x,
+    lldb_r14_s390x,
+    lldb_r15_s390x,
+    lldb_acr0_s390x,
+    lldb_acr1_s390x,
+    lldb_acr2_s390x,
+    lldb_acr3_s390x,
+    lldb_acr4_s390x,
+    lldb_acr5_s390x,
+    lldb_acr6_s390x,
+    lldb_acr7_s390x,
+    lldb_acr8_s390x,
+    lldb_acr9_s390x,
+    lldb_acr10_s390x,
+    lldb_acr11_s390x,
+    lldb_acr12_s390x,
+    lldb_acr13_s390x,
+    lldb_acr14_s390x,
+    lldb_acr15_s390x,
+    lldb_pswm_s390x,
+    lldb_pswa_s390x,
+    k_last_gpr_s390x = lldb_pswa_s390x,
+
+    k_first_fpr_s390x,
+    lldb_f0_s390x = k_first_fpr_s390x,
+    lldb_f1_s390x,
+    lldb_f2_s390x,
+    lldb_f3_s390x,
+    lldb_f4_s390x,
+    lldb_f5_s390x,
+    lldb_f6_s390x,
+    lldb_f7_s390x,
+    lldb_f8_s390x,
+    lldb_f9_s390x,
+    lldb_f10_s390x,
+    lldb_f11_s390x,
+    lldb_f12_s390x,
+    lldb_f13_s390x,
+    lldb_f14_s390x,
+    lldb_f15_s390x,
+    lldb_fpc_s390x,
+    k_last_fpr_s390x = lldb_fpc_s390x,
+
+    // These are only available on Linux.
+    k_first_linux_s390x,
+    lldb_orig_r2_s390x = k_first_linux_s390x,
+    lldb_last_break_s390x,
+    lldb_system_call_s390x,
+    k_last_linux_s390x = lldb_system_call_s390x,
+
+    k_num_registers_s390x,
+    k_num_gpr_registers_s390x = k_last_gpr_s390x - k_first_gpr_s390x + 1,
+    k_num_fpr_registers_s390x = k_last_fpr_s390x - k_first_fpr_s390x + 1,
+    k_num_linux_registers_s390x = k_last_linux_s390x - k_first_linux_s390x + 1,
+    k_num_user_registers_s390x = k_num_gpr_registers_s390x + k_num_fpr_registers_s390x,
+};
+}
+
+#endif // #ifndef lldb_s390x_register_enums_h

Modified: lldb/trunk/source/Plugins/Process/elf-core/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/elf-core/CMakeLists.txt?rev=266308&r1=266307&r2=266308&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/elf-core/CMakeLists.txt (original)
+++ lldb/trunk/source/Plugins/Process/elf-core/CMakeLists.txt Thu Apr 14 09:28:34 2016
@@ -7,5 +7,6 @@ add_lldb_library(lldbPluginProcessElfCor
   RegisterContextPOSIXCore_arm64.cpp
   RegisterContextPOSIXCore_mips64.cpp
   RegisterContextPOSIXCore_powerpc.cpp
+  RegisterContextPOSIXCore_s390x.cpp
   RegisterContextPOSIXCore_x86_64.cpp
   )

Added: lldb/trunk/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.cpp?rev=266308&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.cpp (added)
+++ lldb/trunk/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.cpp Thu Apr 14 09:28:34 2016
@@ -0,0 +1,115 @@
+//===-- RegisterContextCorePOSIX_s390x.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 "RegisterContextPOSIXCore_s390x.h"
+
+using namespace lldb_private;
+
+RegisterContextCorePOSIX_s390x::RegisterContextCorePOSIX_s390x(Thread &thread, RegisterInfoInterface *register_info,
+                                                               const DataExtractor &gpregset,
+                                                               const DataExtractor &fpregset)
+    : RegisterContextPOSIX_s390x(thread, 0, register_info)
+{
+    m_gpr_buffer.reset(new DataBufferHeap(gpregset.GetDataStart(), gpregset.GetByteSize()));
+    m_gpr.SetData(m_gpr_buffer);
+    m_gpr.SetByteOrder(gpregset.GetByteOrder());
+
+    m_fpr_buffer.reset(new DataBufferHeap(fpregset.GetDataStart(), fpregset.GetByteSize()));
+    m_fpr.SetData(m_fpr_buffer);
+    m_fpr.SetByteOrder(fpregset.GetByteOrder());
+}
+
+RegisterContextCorePOSIX_s390x::~RegisterContextCorePOSIX_s390x()
+{
+}
+
+bool
+RegisterContextCorePOSIX_s390x::ReadGPR()
+{
+    return true;
+}
+
+bool
+RegisterContextCorePOSIX_s390x::ReadFPR()
+{
+    return true;
+}
+
+bool
+RegisterContextCorePOSIX_s390x::WriteGPR()
+{
+    assert(0);
+    return false;
+}
+
+bool
+RegisterContextCorePOSIX_s390x::WriteFPR()
+{
+    assert(0);
+    return false;
+}
+
+bool
+RegisterContextCorePOSIX_s390x::ReadRegister(const RegisterInfo *reg_info, RegisterValue &value)
+{
+    const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
+    if (reg == LLDB_INVALID_REGNUM)
+        return false;
+
+    if (IsGPR(reg))
+    {
+        lldb::offset_t offset = reg_info->byte_offset;
+        uint64_t v = m_gpr.GetMaxU64(&offset, reg_info->byte_size);
+        if (offset == reg_info->byte_offset + reg_info->byte_size)
+        {
+            value.SetUInt(v, reg_info->byte_size);
+            return true;
+        }
+    }
+
+    if (IsFPR(reg))
+    {
+        lldb::offset_t offset = reg_info->byte_offset;
+        uint64_t v = m_fpr.GetMaxU64(&offset, reg_info->byte_size);
+        if (offset == reg_info->byte_offset + reg_info->byte_size)
+        {
+            value.SetUInt(v, reg_info->byte_size);
+            return true;
+        }
+    }
+
+    return false;
+}
+
+bool
+RegisterContextCorePOSIX_s390x::ReadAllRegisterValues(lldb::DataBufferSP &data_sp)
+{
+    return false;
+}
+
+bool
+RegisterContextCorePOSIX_s390x::WriteRegister(const RegisterInfo *reg_info, const RegisterValue &value)
+{
+    return false;
+}
+
+bool
+RegisterContextCorePOSIX_s390x::WriteAllRegisterValues(const lldb::DataBufferSP &data_sp)
+{
+    return false;
+}
+
+bool
+RegisterContextCorePOSIX_s390x::HardwareSingleStep(bool enable)
+{
+    return false;
+}

Added: lldb/trunk/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.h?rev=266308&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.h (added)
+++ lldb/trunk/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_s390x.h Thu Apr 14 09:28:34 2016
@@ -0,0 +1,65 @@
+//===-- RegisterContextCorePOSIX_s390x.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_RegisterContextCorePOSIX_s390x_h_
+#define liblldb_RegisterContextCorePOSIX_s390x_h_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/DataBufferHeap.h"
+#include "Plugins/Process/Utility/RegisterContextPOSIX_s390x.h"
+
+class RegisterContextCorePOSIX_s390x : public RegisterContextPOSIX_s390x
+{
+public:
+    RegisterContextCorePOSIX_s390x(lldb_private::Thread &thread, lldb_private::RegisterInfoInterface *register_info,
+                                   const lldb_private::DataExtractor &gpregset,
+                                   const lldb_private::DataExtractor &fpregset);
+
+    ~RegisterContextCorePOSIX_s390x() override;
+
+    bool
+    ReadRegister(const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value) override;
+
+    bool
+    WriteRegister(const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value) override;
+
+    bool
+    ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
+
+    bool
+    WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
+
+    bool
+    HardwareSingleStep(bool enable) override;
+
+protected:
+    bool
+    ReadGPR() override;
+
+    bool
+    ReadFPR() override;
+
+    bool
+    WriteGPR() override;
+
+    bool
+    WriteFPR() override;
+
+private:
+    lldb::DataBufferSP m_gpr_buffer;
+    lldb_private::DataExtractor m_gpr;
+
+    lldb::DataBufferSP m_fpr_buffer;
+    lldb_private::DataExtractor m_fpr;
+};
+
+#endif // liblldb_RegisterContextCorePOSIX_s390x_h_

Modified: lldb/trunk/source/Plugins/Process/elf-core/ThreadElfCore.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/elf-core/ThreadElfCore.cpp?rev=266308&r1=266307&r2=266308&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/elf-core/ThreadElfCore.cpp (original)
+++ lldb/trunk/source/Plugins/Process/elf-core/ThreadElfCore.cpp Thu Apr 14 09:28:34 2016
@@ -18,6 +18,7 @@
 #include "ProcessElfCore.h"
 #include "Plugins/Process/Utility/RegisterContextLinux_arm.h"
 #include "Plugins/Process/Utility/RegisterContextLinux_arm64.h"
+#include "Plugins/Process/Utility/RegisterContextLinux_s390x.h"
 #include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h"
 #include "Plugins/Process/Utility/RegisterContextFreeBSD_arm.h"
 #include "Plugins/Process/Utility/RegisterContextFreeBSD_arm64.h"
@@ -29,6 +30,7 @@
 #include "RegisterContextPOSIXCore_arm64.h"
 #include "RegisterContextPOSIXCore_mips64.h"
 #include "RegisterContextPOSIXCore_powerpc.h"
+#include "RegisterContextPOSIXCore_s390x.h"
 #include "RegisterContextPOSIXCore_x86_64.h"
 
 using namespace lldb;
@@ -139,6 +141,9 @@ ThreadElfCore::CreateRegisterContextForF
                     case llvm::Triple::aarch64:
                         reg_interface = new RegisterContextLinux_arm64(arch);
                         break;
+                    case llvm::Triple::systemz:
+                        reg_interface = new RegisterContextLinux_s390x(arch);
+                        break;
                     case llvm::Triple::x86_64:
                         reg_interface = new RegisterContextLinux_x86_64(arch);
                         break;
@@ -174,6 +179,9 @@ ThreadElfCore::CreateRegisterContextForF
             case llvm::Triple::ppc64:
                 m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_powerpc (*this, reg_interface, m_gpregset_data, m_fpregset_data, m_vregset_data));
                 break;
+            case llvm::Triple::systemz:
+                m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_s390x (*this, reg_interface, m_gpregset_data, m_fpregset_data));
+                break;
             case llvm::Triple::x86:
             case llvm::Triple::x86_64:
                 m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_x86_64 (*this, reg_interface, m_gpregset_data, m_fpregset_data));
@@ -218,6 +226,7 @@ ELFLinuxPrStatus::Parse(DataExtractor &d
     size_t len;
     switch(arch.GetCore())
     {
+        case ArchSpec::eCore_s390x_generic:
         case ArchSpec::eCore_x86_64_x86_64:
             len = data.ExtractBytes(0, ELFLINUXPRSTATUS64_SIZE, byteorder, this);
             return len == ELFLINUXPRSTATUS64_SIZE;
@@ -241,6 +250,7 @@ ELFLinuxPrPsInfo::Parse(DataExtractor &d
     size_t len;
     switch(arch.GetCore())
     {
+        case ArchSpec::eCore_s390x_generic:
         case ArchSpec::eCore_x86_64_x86_64:
             len = data.ExtractBytes(0, ELFLINUXPRPSINFO64_SIZE, byteorder, this);
             return len == ELFLINUXPRPSINFO64_SIZE;

Modified: lldb/trunk/source/Plugins/Process/elf-core/ThreadElfCore.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/elf-core/ThreadElfCore.h?rev=266308&r1=266307&r2=266308&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/elf-core/ThreadElfCore.h (original)
+++ lldb/trunk/source/Plugins/Process/elf-core/ThreadElfCore.h Thu Apr 14 09:28:34 2016
@@ -68,6 +68,7 @@ struct ELFLinuxPrStatus
     {
         switch(arch.GetCore())
         {
+            case lldb_private::ArchSpec::eCore_s390x_generic:
             case lldb_private::ArchSpec::eCore_x86_64_x86_64:
                 return ELFLINUXPRSTATUS64_SIZE;
             default:
@@ -102,6 +103,7 @@ struct ELFLinuxPrPsInfo
     {
         switch(arch.GetCore())
         {
+            case lldb_private::ArchSpec::eCore_s390x_generic:
             case lldb_private::ArchSpec::eCore_x86_64_x86_64:
                 return ELFLINUXPRPSINFO64_SIZE;
             default:

Modified: lldb/trunk/source/Target/Platform.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Platform.cpp?rev=266308&r1=266307&r2=266308&view=diff
==============================================================================
--- lldb/trunk/source/Target/Platform.cpp (original)
+++ lldb/trunk/source/Target/Platform.cpp Thu Apr 14 09:28:34 2016
@@ -2118,6 +2118,14 @@ Platform::GetSoftwareBreakpointTrapOpcod
         }
         break;
 
+    case llvm::Triple::systemz:
+        {
+            static const uint8_t g_hex_opcode[] = {0x00, 0x01};
+            trap_opcode = g_hex_opcode;
+            trap_opcode_size = sizeof(g_hex_opcode);
+        }
+        break;
+
     case llvm::Triple::hexagon:
         {
             static const uint8_t g_hex_opcode[] = {0x0c, 0xdb, 0x00, 0x54};

Modified: lldb/trunk/source/Target/Thread.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Thread.cpp?rev=266308&r1=266307&r2=266308&view=diff
==============================================================================
--- lldb/trunk/source/Target/Thread.cpp (original)
+++ lldb/trunk/source/Target/Thread.cpp Thu Apr 14 09:28:34 2016
@@ -2340,6 +2340,7 @@ Thread::GetUnwinder ()
             case llvm::Triple::mips64el:
             case llvm::Triple::ppc:
             case llvm::Triple::ppc64:
+            case llvm::Triple::systemz:
             case llvm::Triple::hexagon:
                 m_unwinder_ap.reset (new UnwindLLDB (*this));
                 break;




More information about the lldb-commits mailing list