gold: Add s390 -fsplit-stack support.
authorMarcin Kościelnicki <koriakin@0x04.net>
Sun, 13 Dec 2015 01:53:09 +0000 (02:53 +0100)
committerMarcin Kościelnicki <koriakin@0x04.net>
Mon, 15 Feb 2016 10:59:25 +0000 (11:59 +0100)
gold/ChangeLog:

* s390.cc (Target_s390::match_view_u): New helper method.
(Target_s390::do_is_call_to_non_split): New method.
(Target_s390::ss_code_st_r14): New const.
(Target_s390::ss_code_l_r14): New const.
(Target_s390::ss_code_bras_8): New const.
(Target_s390::ss_code_l_basr): New const.
(Target_s390::ss_code_a_basr): New const.
(Target_s390::ss_code_ear): New const.
(Target_s390::ss_code_c): New const.
(Target_s390::ss_code_larl): New const.
(Target_s390::ss_code_brasl): New const.
(Target_s390::ss_code_jg): New const.
(Target_s390::ss_code_jgl): New const.
(Target_s390::ss_match_mcount): New helper method.
(Target_s390::ss_match_l): New helper method.
(Target_s390::ss_match_ahi): New helper method.
(Target_s390::ss_match_alfi): New helper method.
(Target_s390::ss_match_cr): New helper method.
(Target_s390::do_calls_non_split): New method.
* testsuite/Makefile.am: Added new tests.
* testsuite/split_s390.sh: New test.
* testsuite/split_s390_1_a1.s: New test.
* testsuite/split_s390_1_a2.s: New test.
* testsuite/split_s390_1_n1.s: New test.
* testsuite/split_s390_1_n2.s: New test.
* testsuite/split_s390_1_z1.s: New test.
* testsuite/split_s390_1_z2.s: New test.
* testsuite/split_s390_1_z3.s: New test.
* testsuite/split_s390_1_z4.s: New test.
* testsuite/split_s390_2_ns.s: New test.
* testsuite/split_s390_2_s.s: New test.
* testsuite/split_s390x_1_a1.s: New test.
* testsuite/split_s390x_1_a2.s: New test.
* testsuite/split_s390x_1_n1.s: New test.
* testsuite/split_s390x_1_n2.s: New test.
* testsuite/split_s390x_1_z1.s: New test.
* testsuite/split_s390x_1_z2.s: New test.
* testsuite/split_s390x_1_z3.s: New test.
* testsuite/split_s390x_1_z4.s: New test.
* testsuite/split_s390x_2_ns.s: New test.
* testsuite/split_s390x_2_s.s: New test.

25 files changed:
gold/ChangeLog
gold/s390.cc
gold/testsuite/Makefile.am
gold/testsuite/Makefile.in
gold/testsuite/split_s390.sh [new file with mode: 0755]
gold/testsuite/split_s390_1_a1.s [new file with mode: 0644]
gold/testsuite/split_s390_1_a2.s [new file with mode: 0644]
gold/testsuite/split_s390_1_n1.s [new file with mode: 0644]
gold/testsuite/split_s390_1_n2.s [new file with mode: 0644]
gold/testsuite/split_s390_1_z1.s [new file with mode: 0644]
gold/testsuite/split_s390_1_z2.s [new file with mode: 0644]
gold/testsuite/split_s390_1_z3.s [new file with mode: 0644]
gold/testsuite/split_s390_1_z4.s [new file with mode: 0644]
gold/testsuite/split_s390_2_ns.s [new file with mode: 0644]
gold/testsuite/split_s390_2_s.s [new file with mode: 0644]
gold/testsuite/split_s390x_1_a1.s [new file with mode: 0644]
gold/testsuite/split_s390x_1_a2.s [new file with mode: 0644]
gold/testsuite/split_s390x_1_n1.s [new file with mode: 0644]
gold/testsuite/split_s390x_1_n2.s [new file with mode: 0644]
gold/testsuite/split_s390x_1_z1.s [new file with mode: 0644]
gold/testsuite/split_s390x_1_z2.s [new file with mode: 0644]
gold/testsuite/split_s390x_1_z3.s [new file with mode: 0644]
gold/testsuite/split_s390x_1_z4.s [new file with mode: 0644]
gold/testsuite/split_s390x_2_ns.s [new file with mode: 0644]
gold/testsuite/split_s390x_2_s.s [new file with mode: 0644]

index 8534b5195aa138f9a6cc031330e69875bc547d84..1e261e2aacd4ef5f61be645ac9d5819b06d6a07b 100644 (file)
@@ -1,3 +1,48 @@
+2016-02-15  Marcin Kościelnicki  <koriakin@0x04.net>
+
+       * s390.cc (Target_s390::match_view_u): New helper method.
+       (Target_s390::do_is_call_to_non_split): New method.
+       (Target_s390::ss_code_st_r14): New const.
+       (Target_s390::ss_code_l_r14): New const.
+       (Target_s390::ss_code_bras_8): New const.
+       (Target_s390::ss_code_l_basr): New const.
+       (Target_s390::ss_code_a_basr): New const.
+       (Target_s390::ss_code_ear): New const.
+       (Target_s390::ss_code_c): New const.
+       (Target_s390::ss_code_larl): New const.
+       (Target_s390::ss_code_brasl): New const.
+       (Target_s390::ss_code_jg): New const.
+       (Target_s390::ss_code_jgl): New const.
+       (Target_s390::ss_match_mcount): New helper method.
+       (Target_s390::ss_match_l): New helper method.
+       (Target_s390::ss_match_ahi): New helper method.
+       (Target_s390::ss_match_alfi): New helper method.
+       (Target_s390::ss_match_cr): New helper method.
+       (Target_s390::do_calls_non_split): New method.
+       * testsuite/Makefile.am: Added new tests.
+       * testsuite/Makefile.in: Regenerate.
+       * testsuite/split_s390.sh: New test.
+       * testsuite/split_s390_1_a1.s: New test.
+       * testsuite/split_s390_1_a2.s: New test.
+       * testsuite/split_s390_1_n1.s: New test.
+       * testsuite/split_s390_1_n2.s: New test.
+       * testsuite/split_s390_1_z1.s: New test.
+       * testsuite/split_s390_1_z2.s: New test.
+       * testsuite/split_s390_1_z3.s: New test.
+       * testsuite/split_s390_1_z4.s: New test.
+       * testsuite/split_s390_2_ns.s: New test.
+       * testsuite/split_s390_2_s.s: New test.
+       * testsuite/split_s390x_1_a1.s: New test.
+       * testsuite/split_s390x_1_a2.s: New test.
+       * testsuite/split_s390x_1_n1.s: New test.
+       * testsuite/split_s390x_1_n2.s: New test.
+       * testsuite/split_s390x_1_z1.s: New test.
+       * testsuite/split_s390x_1_z2.s: New test.
+       * testsuite/split_s390x_1_z3.s: New test.
+       * testsuite/split_s390x_1_z4.s: New test.
+       * testsuite/split_s390x_2_ns.s: New test.
+       * testsuite/split_s390x_2_s.s: New test.
+
 2016-02-11 Rahul Chaudhry  <rahulchaudhry@google.com>
 
        * aarch64.cc (Target_aarch64::scan_erratum_843419_span): Remove
index 2671441a2ac7bb2ff06a4909b52edb25cc309774..5245ecab0debc3f99aaa0b35eacc252b6fda9aa5 100644 (file)
@@ -417,6 +417,20 @@ class Target_s390 : public Sized_target<size, true>
   do_can_check_for_function_pointers() const
   { return true; }
 
+  // Return whether SYM is call to a non-split function.
+  bool
+  do_is_call_to_non_split(const Symbol* sym, const unsigned char* preloc,
+                         const unsigned char* view,
+                         section_size_type view_size) const;
+
+  // Adjust -fsplit-stack code which calls non-split-stack code.
+  void
+  do_calls_non_split(Relobj* object, unsigned int shndx,
+                    section_offset_type fnoffset, section_size_type fnsize,
+                    const unsigned char* prelocs, size_t reloc_count,
+                    unsigned char* view, section_size_type view_size,
+                    std::string* from, std::string* to) const;
+
   // Return the size of the GOT section.
   section_size_type
   got_size() const
@@ -693,6 +707,17 @@ class Target_s390 : public Sized_target<size, true>
                                  this->rela_dyn_section(layout));
   }
 
+  // A function for targets to call.  Return whether BYTES/LEN matches
+  // VIEW/VIEW_SIZE at OFFSET.  Like the one in Target, but takes
+  // an unsigned char * parameter.
+  bool
+  match_view_u(const unsigned char* view, section_size_type view_size,
+     section_offset_type offset, const unsigned char* bytes, size_t len) const
+    {
+      return this->match_view(view, view_size, offset,
+                             reinterpret_cast<const char*>(bytes), len);
+    }
+
   // Information about this specific target which we pass to the
   // general Target structure.
   static Target::Target_info s390_info;
@@ -730,6 +755,42 @@ class Target_s390 : public Sized_target<size, true>
   bool tls_base_symbol_defined_;
   // For use in do_tls_offset_for_*
   Layout *layout_;
+
+  // Code sequences for -fsplit-stack matching.
+  static const unsigned char ss_code_st_r14[];
+  static const unsigned char ss_code_l_r14[];
+  static const unsigned char ss_code_bras_8[];
+  static const unsigned char ss_code_l_basr[];
+  static const unsigned char ss_code_a_basr[];
+  static const unsigned char ss_code_ear[];
+  static const unsigned char ss_code_c[];
+  static const unsigned char ss_code_larl[];
+  static const unsigned char ss_code_brasl[];
+  static const unsigned char ss_code_jg[];
+  static const unsigned char ss_code_jgl[];
+
+  // Variable code sequence matchers for -fsplit-stack.
+  bool ss_match_mcount(unsigned char* view,
+                      section_size_type view_size,
+                      section_offset_type *offset) const;
+  bool ss_match_l(unsigned char* view,
+                 section_size_type view_size,
+                 section_offset_type *offset,
+                 int *guard_reg) const;
+  bool ss_match_ahi(unsigned char* view,
+                   section_size_type view_size,
+                   section_offset_type *offset,
+                   int guard_reg,
+                   uint32_t *arg) const;
+  bool ss_match_alfi(unsigned char* view,
+                    section_size_type view_size,
+                    section_offset_type *offset,
+                    int guard_reg,
+                    uint32_t *arg) const;
+  bool ss_match_cr(unsigned char* view,
+                  section_size_type view_size,
+                  section_offset_type *offset,
+                  int guard_reg) const;
 };
 
 template<>
@@ -4192,6 +4253,550 @@ Target_s390<size>::do_code_fill(section_size_type length) const
   return std::string(length, static_cast<char>(0x07));
 }
 
+// Return whether SYM should be treated as a call to a non-split
+// function.  We don't want that to be true of a larl instruction
+// that merely loads its address.
+
+template<int size>
+bool
+Target_s390<size>::do_is_call_to_non_split(const Symbol* sym,
+                                          const unsigned char* preloc,
+                                          const unsigned char* view,
+                                          section_size_type view_size) const
+{
+  if (sym->type() != elfcpp::STT_FUNC)
+    return false;
+  typename Reloc_types<elfcpp::SHT_RELA, size, true>::Reloc reloc(preloc);
+  typename elfcpp::Elf_types<size>::Elf_WXword r_info
+    = reloc.get_r_info();
+  unsigned int r_type = elfcpp::elf_r_type<size>(r_info);
+  section_offset_type offset = reloc.get_r_offset();
+  switch (r_type)
+    {
+    // PLT refs always involve calling the function.
+    case elfcpp::R_390_PLT12DBL:
+    case elfcpp::R_390_PLT16DBL:
+    case elfcpp::R_390_PLT24DBL:
+    case elfcpp::R_390_PLT32:
+    case elfcpp::R_390_PLT32DBL:
+    case elfcpp::R_390_PLT64:
+    case elfcpp::R_390_PLTOFF16:
+    case elfcpp::R_390_PLTOFF32:
+    case elfcpp::R_390_PLTOFF64:
+    // Could be used for calls for -msmall-exec.
+    case elfcpp::R_390_PC16DBL:
+      return true;
+
+    // Tricky case.  When used in a brasl, jg, and other branch instructions,
+    // it's a call or a sibcall.  However, when used in larl, it only loads
+    // the function's address - not a call.
+    case elfcpp::R_390_PC32DBL:
+      {
+       if (offset < 2
+           || offset + 4 > static_cast<section_offset_type>(view_size))
+         {
+           // Should not happen.
+           gold_error(_("instruction with PC32DBL not wholly within section"));
+           return false;
+         }
+
+       uint8_t op0 = view[offset-2];
+       uint8_t op1 = view[offset-1] & 0xf;
+
+       // LARL
+       if (op0 == 0xc0 && op1 == 0)
+         return false;
+
+       // Otherwise, it's either a call instruction, a branch instruction
+       // (used as a sibcall), or a data manipulation instruction (which
+       // has no business being used on a function, and can be ignored).
+        return true;
+      }
+
+    // Otherwise, it's probably not a call.
+    default:
+      return false;
+    }
+}
+
+// Code sequences to match below.
+
+template<>
+const unsigned char
+Target_s390<32>::ss_code_st_r14[] = {
+  0x50, 0xe0, 0xf0, 0x04,              // st %r14, 4(%r15)
+};
+
+template<>
+const unsigned char
+Target_s390<64>::ss_code_st_r14[] = {
+  0xe3, 0xe0, 0xf0, 0x08, 0x00, 0x24   // stg %r14, 8(%r15)
+};
+
+template<>
+const unsigned char
+Target_s390<32>::ss_code_l_r14[] = {
+  0x58, 0xe0, 0xf0, 0x04,              // l %r14, 4(%r15)
+};
+
+template<>
+const unsigned char
+Target_s390<64>::ss_code_l_r14[] = {
+  0xe3, 0xe0, 0xf0, 0x08, 0x00, 0x04   // lg %r14, 8(%r15)
+};
+
+template<int size>
+const unsigned char
+Target_s390<size>::ss_code_bras_8[] = {
+  0xa7, 0x15, 0x00, 0x06,              // bras %r1, .+0xc
+};
+
+template<int size>
+const unsigned char
+Target_s390<size>::ss_code_l_basr[] = {
+  0x58, 0xe0, 0x10, 0x00,              // l %r14, 0(%r1)
+  0x58, 0x10, 0x10, 0x04,              // l %r1, 4(%r1)
+  0x0d, 0xee,                          // basr %r14, %r14
+};
+
+template<int size>
+const unsigned char
+Target_s390<size>::ss_code_a_basr[] = {
+  0x18, 0xe1,                          // lr %r14, %r1
+  0x5a, 0xe0, 0x10, 0x00,              // a %r14, 0(%r1)
+  0x5a, 0x10, 0x10, 0x04,              // a %r1, 4(%r1)
+  0x0d, 0xee,                          // basr %r14, %r14
+};
+
+template<>
+const unsigned char
+Target_s390<32>::ss_code_ear[] = {
+  0xb2, 0x4f, 0x00, 0x10,              // ear %r1, %a0
+};
+
+template<>
+const unsigned char
+Target_s390<64>::ss_code_ear[] = {
+  0xb2, 0x4f, 0x00, 0x10,              // ear %r1, %a0
+  0xeb, 0x11, 0x00, 0x20, 0x00, 0x0d,  // sllg %r1,%r1,32
+  0xb2, 0x4f, 0x00, 0x11,              // ear %r1, %a1
+};
+
+template<>
+const unsigned char
+Target_s390<32>::ss_code_c[] = {
+  0x59, 0xf0, 0x10, 0x20,              // c %r15, 0x20(%r1)
+};
+
+template<>
+const unsigned char
+Target_s390<64>::ss_code_c[] = {
+  0xe3, 0xf0, 0x10, 0x38, 0x00, 0x20,  // cg %r15, 0x38(%r1)
+};
+
+template<int size>
+const unsigned char
+Target_s390<size>::ss_code_larl[] = {
+  0xc0, 0x10,                          // larl %r1, ...
+};
+
+template<int size>
+const unsigned char
+Target_s390<size>::ss_code_brasl[] = {
+  0xc0, 0xe5,                          // brasl %r14, ...
+};
+
+template<int size>
+const unsigned char
+Target_s390<size>::ss_code_jg[] = {
+  0xc0, 0xf4,                          // jg ...
+};
+
+template<int size>
+const unsigned char
+Target_s390<size>::ss_code_jgl[] = {
+  0xc0, 0x44,                          // jgl ...
+};
+
+template<int size>
+bool
+Target_s390<size>::ss_match_mcount(unsigned char* view,
+                                  section_size_type view_size,
+                                  section_offset_type *offset) const
+{
+  // Match the mcount call sequence.
+  section_offset_type myoff = *offset;
+
+  // First, look for the store instruction saving %r14.
+  if (!this->match_view_u(view, view_size, myoff, ss_code_st_r14,
+                         sizeof ss_code_st_r14))
+    return false;
+  myoff += sizeof ss_code_st_r14;
+
+  // Now, param load and the actual call.
+  if (this->match_view_u(view, view_size, myoff, ss_code_larl,
+                        sizeof ss_code_larl))
+    {
+      myoff += sizeof ss_code_larl + 4;
+
+      // After larl, expect a brasl.
+      if (!this->match_view_u(view, view_size, myoff, ss_code_brasl,
+                             sizeof ss_code_brasl))
+       return false;
+      myoff += sizeof ss_code_brasl + 4;
+    }
+  else if (size == 32 &&
+          this->match_view_u(view, view_size, myoff, ss_code_bras_8,
+                             sizeof ss_code_bras_8))
+    {
+      // The bras skips over a block of 8 bytes, loading its address
+      // to %r1.
+      myoff += sizeof ss_code_bras_8 + 8;
+
+      // Now, there are two sequences used for actual load and call,
+      // absolute and PIC.
+      if (this->match_view_u(view, view_size, myoff, ss_code_l_basr,
+                            sizeof ss_code_l_basr))
+        myoff += sizeof ss_code_l_basr;
+      else if (this->match_view_u(view, view_size, myoff, ss_code_a_basr,
+                                 sizeof ss_code_a_basr))
+        myoff += sizeof ss_code_a_basr;
+      else
+       return false;
+    }
+  else
+    return false;
+
+  // Finally, a load bringing %r14 back.
+  if (!this->match_view_u(view, view_size, myoff, ss_code_l_r14,
+                         sizeof ss_code_l_r14))
+    return false;
+  myoff += sizeof ss_code_l_r14;
+
+  // Found it.
+  *offset = myoff;
+  return true;
+}
+
+template<>
+bool
+Target_s390<32>::ss_match_l(unsigned char* view,
+                           section_size_type view_size,
+                           section_offset_type *offset,
+                           int *guard_reg) const
+{
+  // l %guard_reg, 0x20(%r1)
+  if (convert_to_section_size_type(*offset + 4) > view_size
+      || view[*offset] != 0x58
+      || (view[*offset + 1] & 0xf) != 0x0
+      || view[*offset + 2] != 0x10
+      || view[*offset + 3] != 0x20)
+    return false;
+  *offset += 4;
+  *guard_reg = view[*offset + 1] >> 4 & 0xf;
+  return true;
+}
+
+template<>
+bool
+Target_s390<64>::ss_match_l(unsigned char* view,
+                           section_size_type view_size,
+                           section_offset_type *offset,
+                           int *guard_reg) const
+{
+  // lg %guard_reg, 0x38(%r1)
+  if (convert_to_section_size_type(*offset + 6) > view_size
+      || view[*offset] != 0xe3
+      || (view[*offset + 1] & 0xf) != 0x0
+      || view[*offset + 2] != 0x10
+      || view[*offset + 3] != 0x38
+      || view[*offset + 4] != 0x00
+      || view[*offset + 5] != 0x04)
+    return false;
+  *offset += 6;
+  *guard_reg = view[*offset + 1] >> 4 & 0xf;
+  return true;
+}
+
+template<int size>
+bool
+Target_s390<size>::ss_match_ahi(unsigned char* view,
+                               section_size_type view_size,
+                               section_offset_type *offset,
+                               int guard_reg,
+                               uint32_t *arg) const
+{
+  int op = size == 32 ? 0xa : 0xb;
+  // a[g]hi %guard_reg, <arg>
+  if (convert_to_section_size_type(*offset + 4) > view_size
+      || view[*offset] != 0xa7
+      || view[*offset + 1] != (guard_reg << 4 | op)
+      // Disallow negative size.
+      || view[*offset + 2] & 0x80)
+    return false;
+  *arg = elfcpp::Swap<16, true>::readval(view + *offset + 2);
+  *offset += 4;
+  return true;
+}
+
+template<int size>
+bool
+Target_s390<size>::ss_match_alfi(unsigned char* view,
+                                section_size_type view_size,
+                                section_offset_type *offset,
+                                int guard_reg,
+                                uint32_t *arg) const
+{
+  int op = size == 32 ? 0xb : 0xa;
+  // al[g]fi %guard_reg, <arg>
+  if (convert_to_section_size_type(*offset + 6) > view_size
+      || view[*offset] != 0xc2
+      || view[*offset + 1] != (guard_reg << 4 | op))
+    return false;
+  *arg = elfcpp::Swap<32, true>::readval(view + *offset + 2);
+  *offset += 6;
+  return true;
+}
+
+template<>
+bool
+Target_s390<32>::ss_match_cr(unsigned char* view,
+                            section_size_type view_size,
+                            section_offset_type *offset,
+                            int guard_reg) const
+{
+  // cr %r15, %guard_reg
+  if (convert_to_section_size_type(*offset + 2) > view_size
+      || view[*offset] != 0x19
+      || view[*offset + 1] != (0xf0 | guard_reg))
+    return false;
+  *offset += 2;
+  return true;
+}
+
+template<>
+bool
+Target_s390<64>::ss_match_cr(unsigned char* view,
+                            section_size_type view_size,
+                            section_offset_type *offset,
+                            int guard_reg) const
+{
+  // cgr %r15, %guard_reg
+  if (convert_to_section_size_type(*offset + 4) > view_size
+      || view[*offset] != 0xb9
+      || view[*offset + 1] != 0x20
+      || view[*offset + 2] != 0x00
+      || view[*offset + 3] != (0xf0 | guard_reg))
+    return false;
+  *offset += 4;
+  return true;
+}
+
+
+// FNOFFSET in section SHNDX in OBJECT is the start of a function
+// compiled with -fsplit-stack.  The function calls non-split-stack
+// code.  We have to change the function so that it always ensures
+// that it has enough stack space to run some random function.
+
+template<int size>
+void
+Target_s390<size>::do_calls_non_split(Relobj* object, unsigned int shndx,
+                                     section_offset_type fnoffset,
+                                     section_size_type,
+                                     const unsigned char *prelocs,
+                                     size_t reloc_count,
+                                     unsigned char* view,
+                                     section_size_type view_size,
+                                     std::string*,
+                                     std::string*) const
+{
+  // true if there's a conditional call to __morestack in the function,
+  // false if there's an unconditional one.
+  bool conditional = false;
+  // Offset of the byte after the compare insn, if conditional.
+  section_offset_type cmpend = 0;
+  // Type and immediate offset of the add instruction that adds frame size
+  // to guard.
+  enum {
+    SS_ADD_NONE,
+    SS_ADD_AHI,
+    SS_ADD_ALFI,
+  } fsadd_type = SS_ADD_NONE;
+  section_offset_type fsadd_offset = 0;
+  uint32_t fsadd_frame_size = 0;
+  // Register used for loading guard.  Usually r1, but can also be r0 or r2-r5.
+  int guard_reg;
+  // Offset of the conditional jump.
+  section_offset_type jump_offset = 0;
+  // Section view and offset of param block.
+  section_offset_type param_offset = 0;
+  unsigned char *param_view = 0;
+  section_size_type param_view_size = 0;
+  // Current position in function.
+  section_offset_type curoffset = fnoffset;
+  // And the position of split-stack prologue.
+  section_offset_type ssoffset;
+  // Frame size.
+  typename elfcpp::Elf_types<size>::Elf_Addr frame_size;
+  // Relocation parsing.
+  typedef typename Reloc_types<elfcpp::SHT_RELA, size, true>::Reloc Reltype;
+  const int reloc_size = Reloc_types<elfcpp::SHT_RELA, size, true>::reloc_size;
+  const unsigned char *pr = prelocs;
+
+  // If the function was compiled with -pg, the profiling code may come before
+  // the split-stack prologue.  Skip it.
+
+  this->ss_match_mcount(view, view_size, &curoffset);
+  ssoffset = curoffset;
+
+  // First, figure out if there's a conditional call by looking for the
+  // extract-tp, add, cmp sequence.
+
+  if (this->match_view_u(view, view_size, curoffset, ss_code_ear,
+                        sizeof ss_code_ear))
+    {
+      // Found extract-tp, now look for an add and compare.
+      curoffset += sizeof ss_code_ear;
+      conditional = true;
+      if (this->match_view_u(view, view_size, curoffset, ss_code_c,
+                            sizeof ss_code_c))
+       {
+         // Found a direct compare of stack pointer with the guard,
+         // we're done here.
+         curoffset += sizeof ss_code_c;
+       }
+      else if (this->ss_match_l(view, view_size, &curoffset, &guard_reg))
+       {
+         // Found a load of guard to register, look for an add and compare.
+          if (this->ss_match_ahi(view, view_size, &curoffset, guard_reg,
+                                &fsadd_frame_size))
+           {
+             fsadd_type = SS_ADD_AHI;
+             fsadd_offset = curoffset - 2;
+           }
+         else if (this->ss_match_alfi(view, view_size, &curoffset, guard_reg,
+                                      &fsadd_frame_size))
+           {
+             fsadd_type = SS_ADD_ALFI;
+             fsadd_offset = curoffset - 4;
+           }
+         else
+            {
+             goto bad;
+            }
+         // Now, there has to be a compare.
+          if (!this->ss_match_cr(view, view_size, &curoffset, guard_reg))
+           goto bad;
+       }
+      else
+        {
+         goto bad;
+        }
+      cmpend = curoffset;
+    }
+
+  // Second, look for the call.
+  if (!this->match_view_u(view, view_size, curoffset, ss_code_larl,
+                         sizeof ss_code_larl))
+    goto bad;
+  curoffset += sizeof ss_code_larl;
+
+  // Find out larl's operand.  It should be a local symbol in .rodata
+  // section.
+  for (size_t i = 0; i < reloc_count; ++i, pr += reloc_size)
+    {
+      Reltype reloc(pr);
+      if (static_cast<section_offset_type>(reloc.get_r_offset())
+          == curoffset)
+        {
+          typename elfcpp::Elf_types<size>::Elf_WXword r_info
+            = reloc.get_r_info();
+          unsigned int r_sym = elfcpp::elf_r_sym<size>(r_info);
+          unsigned int r_type = elfcpp::elf_r_type<size>(r_info);
+          if (r_type != elfcpp::R_390_PC32DBL)
+            goto bad;
+          if (r_sym >= object->local_symbol_count())
+            goto bad;
+          Sized_relobj_file<size, true> *object_sized =
+            static_cast<Sized_relobj_file<size, true> *>(object);
+          const Symbol_value<size>* sym = object_sized->local_symbol(r_sym);
+          bool param_shndx_ordinary;
+          const unsigned int param_shndx =
+            sym->input_shndx(&param_shndx_ordinary);
+          if (!param_shndx_ordinary)
+            goto bad;
+          param_offset = sym->input_value() + reloc.get_r_addend() - 2
+                         - object->output_section(param_shndx)->address()
+                         - object->output_section_offset(param_shndx);
+          param_view = object->get_output_view(param_shndx,
+                                                  &param_view_size);
+          break;
+        }
+    }
+
+  if (!param_view)
+    goto bad;
+
+  curoffset += 4;
+
+  // Now, there has to be a jump to __morestack.
+  jump_offset = curoffset;
+
+  if (this->match_view_u(view, view_size, curoffset,
+                       conditional ? ss_code_jgl : ss_code_jg,
+                       sizeof ss_code_jg))
+    curoffset += sizeof ss_code_jg;
+  else
+    goto bad;
+
+  curoffset += 4;
+
+  // Read the frame size.
+  if (convert_to_section_size_type(param_offset + size / 8) > param_view_size)
+    goto bad;
+  frame_size = elfcpp::Swap<size, true>::readval(param_view + param_offset);
+
+  // Sanity check.
+  if (fsadd_type != SS_ADD_NONE && fsadd_frame_size != frame_size)
+    goto bad;
+
+  // Bump the frame size.
+  frame_size += parameters->options().split_stack_adjust_size();
+
+  // Store it to the param block.
+  elfcpp::Swap<size, true>::writeval(param_view + param_offset, frame_size);
+
+  if (!conditional)
+    {
+      // If the call was already unconditional, we're done.
+    }
+  else if (frame_size <= 0xffffffff && fsadd_type == SS_ADD_ALFI)
+    {
+      // Using alfi to add the frame size, and it still fits.  Adjust it.
+      elfcpp::Swap_unaligned<32, true>::writeval(view + fsadd_offset,
+                                                frame_size);
+    }
+  else
+    {
+      // We were either relying on the backoff area, or used ahi to load
+      // frame size.  This won't fly, as our new frame size is too large.
+      // Convert the sequence to unconditional by nopping out the comparison,
+      // and rewiring the jump.
+      this->set_view_to_nop(view, view_size, ssoffset, cmpend - ssoffset);
+
+      // The jump is jgl, we'll mutate it to jg.
+      view[jump_offset+1] = 0xf4;
+    }
+
+  return;
+
+bad:
+  if (!object->has_no_split_stack())
+      object->error(_("failed to match split-stack sequence at "
+                     "section %u offset %0zx"),
+                   shndx, static_cast<size_t>(fnoffset));
+}
+
 // Relocate section data.
 
 template<int size>
index ca2420523a3831f521d378660ba96da3fb85b133..7240f98fed6cffae546152ff8134f39184e2db13 100644 (file)
@@ -3397,6 +3397,180 @@ MOSTLYCLEANFILES += arm_farcall_thumb_arm arm_farcall_thumb_arm_5t
 
 endif DEFAULT_TARGET_ARM
 
+if DEFAULT_TARGET_S390
+
+check_SCRIPTS += split_s390.sh
+check_DATA += split_s390_z1.stdout split_s390_z2.stdout split_s390_z3.stdout \
+       split_s390_z4.stdout split_s390_n1.stdout split_s390_n2.stdout \
+       split_s390_a1.stdout split_s390_a2.stdout split_s390_z1_ns.stdout \
+       split_s390_z2_ns.stdout split_s390_z3_ns.stdout split_s390_z4_ns.stdout \
+       split_s390_n1_ns.stdout split_s390_n2_ns.stdout split_s390_r.stdout \
+       split_s390x_z1.stdout split_s390x_z2.stdout split_s390x_z3.stdout \
+       split_s390x_z4.stdout split_s390x_n1.stdout split_s390x_n2.stdout \
+       split_s390x_a1.stdout split_s390x_a2.stdout split_s390x_z1_ns.stdout \
+       split_s390x_z2_ns.stdout split_s390x_z3_ns.stdout \
+       split_s390x_z4_ns.stdout split_s390x_n1_ns.stdout \
+       split_s390x_n2_ns.stdout split_s390x_r.stdout
+SPLIT_DEFSYMS = --defsym __morestack=0x100 --defsym __morestack_non_split=0x200
+split_s390_1_z1.o: split_s390_1_z1.s
+       $(TEST_AS) -m31 -o $@ $<
+split_s390_1_z2.o: split_s390_1_z2.s
+       $(TEST_AS) -m31 -o $@ $<
+split_s390_1_z3.o: split_s390_1_z3.s
+       $(TEST_AS) -m31 -o $@ $<
+split_s390_1_z4.o: split_s390_1_z4.s
+       $(TEST_AS) -m31 -o $@ $<
+split_s390_1_n1.o: split_s390_1_n1.s
+       $(TEST_AS) -m31 -o $@ $<
+split_s390_1_n2.o: split_s390_1_n2.s
+       $(TEST_AS) -m31 -o $@ $<
+split_s390_1_a1.o: split_s390_1_a1.s
+       $(TEST_AS) -m31 -o $@ $<
+split_s390_1_a2.o: split_s390_1_a2.s
+       $(TEST_AS) -m31 -o $@ $<
+split_s390_2_s.o: split_s390_2_s.s
+       $(TEST_AS) -m31 -o $@ $<
+split_s390_2_ns.o: split_s390_2_ns.s
+       $(TEST_AS) -m31 -o $@ $<
+split_s390_z1: split_s390_1_z1.o split_s390_2_s.o ../ld-new
+       ../ld-new $(SPLIT_DEFSYMS) -o $@ split_s390_1_z1.o split_s390_2_s.o
+split_s390_z1.stdout: split_s390_z1
+       $(TEST_OBJDUMP) -j .rodata -j .text -D $< > $@
+split_s390_z2: split_s390_1_z2.o split_s390_2_s.o ../ld-new
+       ../ld-new $(SPLIT_DEFSYMS) -o $@ split_s390_1_z2.o split_s390_2_s.o
+split_s390_z2.stdout: split_s390_z2
+       $(TEST_OBJDUMP) -j .rodata -j .text -D $< > $@
+split_s390_z3: split_s390_1_z3.o split_s390_2_s.o ../ld-new
+       ../ld-new $(SPLIT_DEFSYMS) -o $@ split_s390_1_z3.o split_s390_2_s.o
+split_s390_z3.stdout: split_s390_z3
+       $(TEST_OBJDUMP) -j .rodata -j .text -D $< > $@
+split_s390_z4: split_s390_1_z4.o split_s390_2_s.o ../ld-new
+       ../ld-new $(SPLIT_DEFSYMS) -o $@ split_s390_1_z4.o split_s390_2_s.o
+split_s390_z4.stdout: split_s390_z4
+       $(TEST_OBJDUMP) -j .rodata -j .text -D $< > $@
+split_s390_n1: split_s390_1_n1.o split_s390_2_s.o ../ld-new
+       ../ld-new $(SPLIT_DEFSYMS) -o $@ split_s390_1_n1.o split_s390_2_s.o
+split_s390_n1.stdout: split_s390_n1
+       $(TEST_OBJDUMP) -d $< > $@
+split_s390_n2: split_s390_1_n2.o split_s390_2_s.o ../ld-new
+       ../ld-new $(SPLIT_DEFSYMS) -o $@ split_s390_1_n2.o split_s390_2_s.o
+split_s390_n2.stdout: split_s390_n2
+       $(TEST_OBJDUMP) -d $< > $@
+split_s390_z1_ns: split_s390_1_z1.o split_s390_2_ns.o ../ld-new
+       ../ld-new $(SPLIT_DEFSYMS) -o $@ split_s390_1_z1.o split_s390_2_ns.o
+split_s390_z1_ns.stdout: split_s390_z1_ns
+       $(TEST_OBJDUMP) -j .rodata -j .text -D $< > $@
+split_s390_z2_ns: split_s390_1_z2.o split_s390_2_ns.o ../ld-new
+       ../ld-new $(SPLIT_DEFSYMS) -o $@ split_s390_1_z2.o split_s390_2_ns.o
+split_s390_z2_ns.stdout: split_s390_z2_ns
+       $(TEST_OBJDUMP) -j .rodata -j .text -D $< > $@
+split_s390_z3_ns: split_s390_1_z3.o split_s390_2_ns.o ../ld-new
+       ../ld-new $(SPLIT_DEFSYMS) -o $@ split_s390_1_z3.o split_s390_2_ns.o
+split_s390_z3_ns.stdout: split_s390_z3_ns
+       $(TEST_OBJDUMP) -j .rodata -j .text -D $< > $@
+split_s390_z4_ns: split_s390_1_z4.o split_s390_2_ns.o ../ld-new
+       ../ld-new $(SPLIT_DEFSYMS) -o $@ split_s390_1_z4.o split_s390_2_ns.o
+split_s390_z4_ns.stdout: split_s390_z4_ns
+       $(TEST_OBJDUMP) -j .rodata -j .text -D $< > $@
+split_s390_n1_ns: split_s390_1_n1.o split_s390_2_ns.o ../ld-new
+       ../ld-new $(SPLIT_DEFSYMS) -o $@ split_s390_1_n1.o split_s390_2_ns.o
+split_s390_n1_ns.stdout: split_s390_n1_ns
+       $(TEST_OBJDUMP) -d $< > $@
+split_s390_n2_ns.stdout: split_s390_1_n2.o split_s390_2_ns.o ../ld-new
+       ../ld-new $(SPLIT_DEFSYMS) -o split_s390_n2 split_s390_1_n2.o split_s390_2_ns.o > $@ 2>&1 || exit 0
+split_s390_a1.stdout: split_s390_1_a1.o split_s390_2_ns.o ../ld-new
+       ../ld-new $(SPLIT_DEFSYMS) -o split_s390_a1 split_s390_1_a1.o split_s390_2_ns.o > $@ 2>&1 || exit 0
+split_s390_a2: split_s390_1_a2.o split_s390_2_ns.o ../ld-new
+       ../ld-new $(SPLIT_DEFSYMS) -o $@ split_s390_1_a2.o split_s390_2_ns.o
+split_s390_a2.stdout: split_s390_a2
+       $(TEST_OBJDUMP) -d $< > $@
+split_s390_r.stdout: split_s390_1_z1.o split_s390_2_ns.o ../ld-new
+       ../ld-new -r split_s390_1_z1.o split_s390_2_ns.o -o split_s390_r > $@ 2>&1 || exit 0
+split_s390x_1_z1.o: split_s390x_1_z1.s
+       $(TEST_AS) -m64 -o $@ $<
+split_s390x_1_z2.o: split_s390x_1_z2.s
+       $(TEST_AS) -m64 -o $@ $<
+split_s390x_1_z3.o: split_s390x_1_z3.s
+       $(TEST_AS) -m64 -o $@ $<
+split_s390x_1_z4.o: split_s390x_1_z4.s
+       $(TEST_AS) -m64 -o $@ $<
+split_s390x_1_n1.o: split_s390x_1_n1.s
+       $(TEST_AS) -m64 -o $@ $<
+split_s390x_1_n2.o: split_s390x_1_n2.s
+       $(TEST_AS) -m64 -o $@ $<
+split_s390x_1_a1.o: split_s390x_1_a1.s
+       $(TEST_AS) -m64 -o $@ $<
+split_s390x_1_a2.o: split_s390x_1_a2.s
+       $(TEST_AS) -m64 -o $@ $<
+split_s390x_2_s.o: split_s390x_2_s.s
+       $(TEST_AS) -m64 -o $@ $<
+split_s390x_2_ns.o: split_s390x_2_ns.s
+       $(TEST_AS) -m64 -o $@ $<
+split_s390x_z1: split_s390x_1_z1.o split_s390x_2_s.o ../ld-new
+       ../ld-new $(SPLIT_DEFSYMS) -o $@ split_s390x_1_z1.o split_s390x_2_s.o
+split_s390x_z1.stdout: split_s390x_z1
+       $(TEST_OBJDUMP) -j .rodata -j .text -D $< > $@
+split_s390x_z2: split_s390x_1_z2.o split_s390x_2_s.o ../ld-new
+       ../ld-new $(SPLIT_DEFSYMS) -o $@ split_s390x_1_z2.o split_s390x_2_s.o
+split_s390x_z2.stdout: split_s390x_z2
+       $(TEST_OBJDUMP) -j .rodata -j .text -D $< > $@
+split_s390x_z3: split_s390x_1_z3.o split_s390x_2_s.o ../ld-new
+       ../ld-new $(SPLIT_DEFSYMS) -o $@ split_s390x_1_z3.o split_s390x_2_s.o
+split_s390x_z3.stdout: split_s390x_z3
+       $(TEST_OBJDUMP) -j .rodata -j .text -D $< > $@
+split_s390x_z4: split_s390x_1_z4.o split_s390x_2_s.o ../ld-new
+       ../ld-new $(SPLIT_DEFSYMS) -o $@ split_s390x_1_z4.o split_s390x_2_s.o
+split_s390x_z4.stdout: split_s390x_z4
+       $(TEST_OBJDUMP) -j .rodata -j .text -D $< > $@
+split_s390x_n1: split_s390x_1_n1.o split_s390x_2_s.o ../ld-new
+       ../ld-new $(SPLIT_DEFSYMS) -o $@ split_s390x_1_n1.o split_s390x_2_s.o
+split_s390x_n1.stdout: split_s390x_n1
+       $(TEST_OBJDUMP) -d $< > $@
+split_s390x_n2: split_s390x_1_n2.o split_s390x_2_s.o ../ld-new
+       ../ld-new $(SPLIT_DEFSYMS) -o $@ split_s390x_1_n2.o split_s390x_2_s.o
+split_s390x_n2.stdout: split_s390x_n2
+       $(TEST_OBJDUMP) -d $< > $@
+split_s390x_z1_ns: split_s390x_1_z1.o split_s390x_2_ns.o ../ld-new
+       ../ld-new $(SPLIT_DEFSYMS) -o $@ split_s390x_1_z1.o split_s390x_2_ns.o
+split_s390x_z1_ns.stdout: split_s390x_z1_ns
+       $(TEST_OBJDUMP) -j .rodata -j .text -D $< > $@
+split_s390x_z2_ns: split_s390x_1_z2.o split_s390x_2_ns.o ../ld-new
+       ../ld-new $(SPLIT_DEFSYMS) -o $@ split_s390x_1_z2.o split_s390x_2_ns.o
+split_s390x_z2_ns.stdout: split_s390x_z2_ns
+       $(TEST_OBJDUMP) -j .rodata -j .text -D $< > $@
+split_s390x_z3_ns: split_s390x_1_z3.o split_s390x_2_ns.o ../ld-new
+       ../ld-new $(SPLIT_DEFSYMS) -o $@ split_s390x_1_z3.o split_s390x_2_ns.o
+split_s390x_z3_ns.stdout: split_s390x_z3_ns
+       $(TEST_OBJDUMP) -j .rodata -j .text -D $< > $@
+split_s390x_z4_ns: split_s390x_1_z4.o split_s390x_2_ns.o ../ld-new
+       ../ld-new $(SPLIT_DEFSYMS) -o $@ split_s390x_1_z4.o split_s390x_2_ns.o
+split_s390x_z4_ns.stdout: split_s390x_z4_ns
+       $(TEST_OBJDUMP) -j .rodata -j .text -D $< > $@
+split_s390x_n1_ns: split_s390x_1_n1.o split_s390x_2_ns.o ../ld-new
+       ../ld-new $(SPLIT_DEFSYMS) -o $@ split_s390x_1_n1.o split_s390x_2_ns.o
+split_s390x_n1_ns.stdout: split_s390x_n1_ns
+       $(TEST_OBJDUMP) -d $< > $@
+split_s390x_n2_ns.stdout: split_s390x_1_n2.o split_s390x_2_ns.o ../ld-new
+       ../ld-new $(SPLIT_DEFSYMS) -o split_s390x_n2 split_s390x_1_n2.o split_s390x_2_ns.o > $@ 2>&1 || exit 0
+split_s390x_a1.stdout: split_s390x_1_a1.o split_s390x_2_ns.o ../ld-new
+       ../ld-new $(SPLIT_DEFSYMS) -o split_s390x_a1 split_s390x_1_a1.o split_s390x_2_ns.o > $@ 2>&1 || exit 0
+split_s390x_a2: split_s390x_1_a2.o split_s390x_2_ns.o ../ld-new
+       ../ld-new $(SPLIT_DEFSYMS) -o $@ split_s390x_1_a2.o split_s390x_2_ns.o
+split_s390x_a2.stdout: split_s390x_a2
+       $(TEST_OBJDUMP) -d $< > $@
+split_s390x_r.stdout: split_s390x_1_z1.o split_s390x_2_ns.o ../ld-new
+       ../ld-new -r split_s390x_1_z1.o split_s390x_2_ns.o -o split_s390x_r > $@ 2>&1 || exit 0
+MOSTLYCLEANFILES += split_s390_z1 split_s390_z2 split_s390_z3 \
+       split_s390_z4 split_s390_n1 split_s390_n2 split_s390_a1 \
+       split_s390_a2 split_s390_z1_ns split_s390_z2_ns split_s390_z3_ns \
+       split_s390_z4_ns split_s390_n1_ns split_s390_n2_ns split_s390_r \
+       split_s390x_z1 split_s390x_z2 split_s390x_z3 split_s390x_z4 \
+       split_s390x_n1 split_s390x_n2 split_s390x_a1 split_s390x_a2 \
+       split_s390x_z1_ns split_s390x_z2_ns split_s390x_z3_ns \
+       split_s390x_z4_ns split_s390x_n1_ns split_s390x_n2_ns split_s390x_r
+
+endif DEFAULT_TARGET_S390
+
 endif NATIVE_OR_CROSS_LINKER
 
 # Tests for the dwp tool.
index 253493f0a2a16db0c54824a7d85871ffeeed93cb..3cdf1a410aa2260b1afa96adfc6abf88b0772ab4 100644 (file)
@@ -837,10 +837,32 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \
 @DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ arm_farcall_thumb_thumb_6m \
 @DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ arm_farcall_thumb_arm \
 @DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ arm_farcall_thumb_arm_5t
-@DEFAULT_TARGET_X86_64_TRUE@am__append_88 = *.dwo *.dwp
-@DEFAULT_TARGET_X86_64_TRUE@am__append_89 = dwp_test_1.sh \
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@am__append_88 = split_s390.sh
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@am__append_89 = split_s390_z1.stdout split_s390_z2.stdout split_s390_z3.stdout \
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        split_s390_z4.stdout split_s390_n1.stdout split_s390_n2.stdout \
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        split_s390_a1.stdout split_s390_a2.stdout split_s390_z1_ns.stdout \
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        split_s390_z2_ns.stdout split_s390_z3_ns.stdout split_s390_z4_ns.stdout \
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        split_s390_n1_ns.stdout split_s390_n2_ns.stdout split_s390_r.stdout \
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        split_s390x_z1.stdout split_s390x_z2.stdout split_s390x_z3.stdout \
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        split_s390x_z4.stdout split_s390x_n1.stdout split_s390x_n2.stdout \
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        split_s390x_a1.stdout split_s390x_a2.stdout split_s390x_z1_ns.stdout \
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        split_s390x_z2_ns.stdout split_s390x_z3_ns.stdout \
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        split_s390x_z4_ns.stdout split_s390x_n1_ns.stdout \
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        split_s390x_n2_ns.stdout split_s390x_r.stdout
+
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@am__append_90 = split_s390_z1 split_s390_z2 split_s390_z3 \
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        split_s390_z4 split_s390_n1 split_s390_n2 split_s390_a1 \
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        split_s390_a2 split_s390_z1_ns split_s390_z2_ns split_s390_z3_ns \
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        split_s390_z4_ns split_s390_n1_ns split_s390_n2_ns split_s390_r \
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        split_s390x_z1 split_s390x_z2 split_s390x_z3 split_s390x_z4 \
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        split_s390x_n1 split_s390x_n2 split_s390x_a1 split_s390x_a2 \
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        split_s390x_z1_ns split_s390x_z2_ns split_s390x_z3_ns \
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        split_s390x_z4_ns split_s390x_n1_ns split_s390x_n2_ns split_s390x_r
+
+@DEFAULT_TARGET_X86_64_TRUE@am__append_91 = *.dwo *.dwp
+@DEFAULT_TARGET_X86_64_TRUE@am__append_92 = dwp_test_1.sh \
 @DEFAULT_TARGET_X86_64_TRUE@   dwp_test_2.sh
-@DEFAULT_TARGET_X86_64_TRUE@am__append_90 = dwp_test_1.stdout \
+@DEFAULT_TARGET_X86_64_TRUE@am__append_93 = dwp_test_1.stdout \
 @DEFAULT_TARGET_X86_64_TRUE@   dwp_test_2.stdout
 subdir = testsuite
 DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am
@@ -2492,7 +2514,7 @@ MOSTLYCLEANFILES = *.so *.syms *.stdout $(am__append_4) \
        $(am__append_45) $(am__append_51) $(am__append_67) \
        $(am__append_70) $(am__append_72) $(am__append_75) \
        $(am__append_78) $(am__append_81) $(am__append_84) \
-       $(am__append_87) $(am__append_88)
+       $(am__append_87) $(am__append_90) $(am__append_91)
 
 # We will add to these later, for each individual test.  Note
 # that we add each test under check_SCRIPTS or check_PROGRAMS;
@@ -2502,13 +2524,13 @@ check_SCRIPTS = $(am__append_2) $(am__append_20) $(am__append_26) \
        $(am__append_42) $(am__append_46) $(am__append_49) \
        $(am__append_65) $(am__append_68) $(am__append_73) \
        $(am__append_76) $(am__append_79) $(am__append_82) \
-       $(am__append_85) $(am__append_89)
+       $(am__append_85) $(am__append_88) $(am__append_92)
 check_DATA = $(am__append_3) $(am__append_21) $(am__append_27) \
        $(am__append_30) $(am__append_36) $(am__append_39) \
        $(am__append_43) $(am__append_47) $(am__append_50) \
        $(am__append_66) $(am__append_69) $(am__append_74) \
        $(am__append_77) $(am__append_80) $(am__append_83) \
-       $(am__append_86) $(am__append_90)
+       $(am__append_86) $(am__append_89) $(am__append_93)
 BUILT_SOURCES = $(am__append_33)
 TESTS = $(check_SCRIPTS) $(check_PROGRAMS)
 
@@ -3011,6 +3033,7 @@ LDADD = libgoldtest.a ../libgold.a ../../libiberty/libiberty.a $(LIBINTL) \
 @DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@exception_x86_64_bnd_test_LDFLAGS = $(exception_test_LDFLAGS)
 @DEFAULT_TARGET_X86_64_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@exception_x86_64_bnd_test_LDADD = exception_x86_64_bnd_1.o exception_x86_64_bnd_2.o
 @DEFAULT_TARGET_I386_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@SPLIT_DEFSYMS = --defsym __morestack=0x100 --defsym __morestack_non_split=0x200
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@SPLIT_DEFSYMS = --defsym __morestack=0x100 --defsym __morestack_non_split=0x200
 @DEFAULT_TARGET_X32_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@SPLIT_DEFSYMS = --defsym __morestack=0x100 --defsym __morestack_non_split=0x200
 @DEFAULT_TARGET_X86_64_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@SPLIT_DEFSYMS = --defsym __morestack=0x100 --defsym __morestack_non_split=0x200
 all: $(BUILT_SOURCES)
@@ -4580,6 +4603,8 @@ arm_farcall_thumb_thumb.sh.log: arm_farcall_thumb_thumb.sh
        @p='arm_farcall_thumb_thumb.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
 arm_farcall_thumb_arm.sh.log: arm_farcall_thumb_arm.sh
        @p='arm_farcall_thumb_arm.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
+split_s390.sh.log: split_s390.sh
+       @p='split_s390.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
 dwp_test_1.sh.log: dwp_test_1.sh
        @p='dwp_test_1.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
 dwp_test_2.sh.log: dwp_test_2.sh
@@ -6896,6 +6921,154 @@ uninstall-am:
 
 @DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@arm_farcall_thumb_arm_5t.o: arm_farcall_thumb_arm.s
 @DEFAULT_TARGET_ARM_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@ $(TEST_AS) -march=armv5t -o $@ $<
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390_1_z1.o: split_s390_1_z1.s
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        $(TEST_AS) -m31 -o $@ $<
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390_1_z2.o: split_s390_1_z2.s
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        $(TEST_AS) -m31 -o $@ $<
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390_1_z3.o: split_s390_1_z3.s
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        $(TEST_AS) -m31 -o $@ $<
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390_1_z4.o: split_s390_1_z4.s
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        $(TEST_AS) -m31 -o $@ $<
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390_1_n1.o: split_s390_1_n1.s
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        $(TEST_AS) -m31 -o $@ $<
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390_1_n2.o: split_s390_1_n2.s
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        $(TEST_AS) -m31 -o $@ $<
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390_1_a1.o: split_s390_1_a1.s
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        $(TEST_AS) -m31 -o $@ $<
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390_1_a2.o: split_s390_1_a2.s
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        $(TEST_AS) -m31 -o $@ $<
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390_2_s.o: split_s390_2_s.s
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        $(TEST_AS) -m31 -o $@ $<
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390_2_ns.o: split_s390_2_ns.s
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        $(TEST_AS) -m31 -o $@ $<
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390_z1: split_s390_1_z1.o split_s390_2_s.o ../ld-new
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        ../ld-new $(SPLIT_DEFSYMS) -o $@ split_s390_1_z1.o split_s390_2_s.o
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390_z1.stdout: split_s390_z1
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        $(TEST_OBJDUMP) -j .rodata -j .text -D $< > $@
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390_z2: split_s390_1_z2.o split_s390_2_s.o ../ld-new
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        ../ld-new $(SPLIT_DEFSYMS) -o $@ split_s390_1_z2.o split_s390_2_s.o
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390_z2.stdout: split_s390_z2
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        $(TEST_OBJDUMP) -j .rodata -j .text -D $< > $@
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390_z3: split_s390_1_z3.o split_s390_2_s.o ../ld-new
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        ../ld-new $(SPLIT_DEFSYMS) -o $@ split_s390_1_z3.o split_s390_2_s.o
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390_z3.stdout: split_s390_z3
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        $(TEST_OBJDUMP) -j .rodata -j .text -D $< > $@
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390_z4: split_s390_1_z4.o split_s390_2_s.o ../ld-new
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        ../ld-new $(SPLIT_DEFSYMS) -o $@ split_s390_1_z4.o split_s390_2_s.o
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390_z4.stdout: split_s390_z4
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        $(TEST_OBJDUMP) -j .rodata -j .text -D $< > $@
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390_n1: split_s390_1_n1.o split_s390_2_s.o ../ld-new
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        ../ld-new $(SPLIT_DEFSYMS) -o $@ split_s390_1_n1.o split_s390_2_s.o
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390_n1.stdout: split_s390_n1
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        $(TEST_OBJDUMP) -d $< > $@
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390_n2: split_s390_1_n2.o split_s390_2_s.o ../ld-new
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        ../ld-new $(SPLIT_DEFSYMS) -o $@ split_s390_1_n2.o split_s390_2_s.o
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390_n2.stdout: split_s390_n2
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        $(TEST_OBJDUMP) -d $< > $@
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390_z1_ns: split_s390_1_z1.o split_s390_2_ns.o ../ld-new
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        ../ld-new $(SPLIT_DEFSYMS) -o $@ split_s390_1_z1.o split_s390_2_ns.o
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390_z1_ns.stdout: split_s390_z1_ns
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        $(TEST_OBJDUMP) -j .rodata -j .text -D $< > $@
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390_z2_ns: split_s390_1_z2.o split_s390_2_ns.o ../ld-new
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        ../ld-new $(SPLIT_DEFSYMS) -o $@ split_s390_1_z2.o split_s390_2_ns.o
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390_z2_ns.stdout: split_s390_z2_ns
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        $(TEST_OBJDUMP) -j .rodata -j .text -D $< > $@
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390_z3_ns: split_s390_1_z3.o split_s390_2_ns.o ../ld-new
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        ../ld-new $(SPLIT_DEFSYMS) -o $@ split_s390_1_z3.o split_s390_2_ns.o
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390_z3_ns.stdout: split_s390_z3_ns
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        $(TEST_OBJDUMP) -j .rodata -j .text -D $< > $@
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390_z4_ns: split_s390_1_z4.o split_s390_2_ns.o ../ld-new
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        ../ld-new $(SPLIT_DEFSYMS) -o $@ split_s390_1_z4.o split_s390_2_ns.o
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390_z4_ns.stdout: split_s390_z4_ns
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        $(TEST_OBJDUMP) -j .rodata -j .text -D $< > $@
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390_n1_ns: split_s390_1_n1.o split_s390_2_ns.o ../ld-new
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        ../ld-new $(SPLIT_DEFSYMS) -o $@ split_s390_1_n1.o split_s390_2_ns.o
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390_n1_ns.stdout: split_s390_n1_ns
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        $(TEST_OBJDUMP) -d $< > $@
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390_n2_ns.stdout: split_s390_1_n2.o split_s390_2_ns.o ../ld-new
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        ../ld-new $(SPLIT_DEFSYMS) -o split_s390_n2 split_s390_1_n2.o split_s390_2_ns.o > $@ 2>&1 || exit 0
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390_a1.stdout: split_s390_1_a1.o split_s390_2_ns.o ../ld-new
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        ../ld-new $(SPLIT_DEFSYMS) -o split_s390_a1 split_s390_1_a1.o split_s390_2_ns.o > $@ 2>&1 || exit 0
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390_a2: split_s390_1_a2.o split_s390_2_ns.o ../ld-new
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        ../ld-new $(SPLIT_DEFSYMS) -o $@ split_s390_1_a2.o split_s390_2_ns.o
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390_a2.stdout: split_s390_a2
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        $(TEST_OBJDUMP) -d $< > $@
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390_r.stdout: split_s390_1_z1.o split_s390_2_ns.o ../ld-new
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        ../ld-new -r split_s390_1_z1.o split_s390_2_ns.o -o split_s390_r > $@ 2>&1 || exit 0
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390x_1_z1.o: split_s390x_1_z1.s
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        $(TEST_AS) -m64 -o $@ $<
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390x_1_z2.o: split_s390x_1_z2.s
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        $(TEST_AS) -m64 -o $@ $<
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390x_1_z3.o: split_s390x_1_z3.s
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        $(TEST_AS) -m64 -o $@ $<
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390x_1_z4.o: split_s390x_1_z4.s
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        $(TEST_AS) -m64 -o $@ $<
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390x_1_n1.o: split_s390x_1_n1.s
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        $(TEST_AS) -m64 -o $@ $<
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390x_1_n2.o: split_s390x_1_n2.s
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        $(TEST_AS) -m64 -o $@ $<
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390x_1_a1.o: split_s390x_1_a1.s
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        $(TEST_AS) -m64 -o $@ $<
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390x_1_a2.o: split_s390x_1_a2.s
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        $(TEST_AS) -m64 -o $@ $<
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390x_2_s.o: split_s390x_2_s.s
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        $(TEST_AS) -m64 -o $@ $<
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390x_2_ns.o: split_s390x_2_ns.s
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        $(TEST_AS) -m64 -o $@ $<
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390x_z1: split_s390x_1_z1.o split_s390x_2_s.o ../ld-new
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        ../ld-new $(SPLIT_DEFSYMS) -o $@ split_s390x_1_z1.o split_s390x_2_s.o
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390x_z1.stdout: split_s390x_z1
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        $(TEST_OBJDUMP) -j .rodata -j .text -D $< > $@
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390x_z2: split_s390x_1_z2.o split_s390x_2_s.o ../ld-new
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        ../ld-new $(SPLIT_DEFSYMS) -o $@ split_s390x_1_z2.o split_s390x_2_s.o
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390x_z2.stdout: split_s390x_z2
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        $(TEST_OBJDUMP) -j .rodata -j .text -D $< > $@
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390x_z3: split_s390x_1_z3.o split_s390x_2_s.o ../ld-new
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        ../ld-new $(SPLIT_DEFSYMS) -o $@ split_s390x_1_z3.o split_s390x_2_s.o
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390x_z3.stdout: split_s390x_z3
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        $(TEST_OBJDUMP) -j .rodata -j .text -D $< > $@
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390x_z4: split_s390x_1_z4.o split_s390x_2_s.o ../ld-new
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        ../ld-new $(SPLIT_DEFSYMS) -o $@ split_s390x_1_z4.o split_s390x_2_s.o
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390x_z4.stdout: split_s390x_z4
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        $(TEST_OBJDUMP) -j .rodata -j .text -D $< > $@
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390x_n1: split_s390x_1_n1.o split_s390x_2_s.o ../ld-new
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        ../ld-new $(SPLIT_DEFSYMS) -o $@ split_s390x_1_n1.o split_s390x_2_s.o
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390x_n1.stdout: split_s390x_n1
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        $(TEST_OBJDUMP) -d $< > $@
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390x_n2: split_s390x_1_n2.o split_s390x_2_s.o ../ld-new
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        ../ld-new $(SPLIT_DEFSYMS) -o $@ split_s390x_1_n2.o split_s390x_2_s.o
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390x_n2.stdout: split_s390x_n2
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        $(TEST_OBJDUMP) -d $< > $@
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390x_z1_ns: split_s390x_1_z1.o split_s390x_2_ns.o ../ld-new
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        ../ld-new $(SPLIT_DEFSYMS) -o $@ split_s390x_1_z1.o split_s390x_2_ns.o
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390x_z1_ns.stdout: split_s390x_z1_ns
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        $(TEST_OBJDUMP) -j .rodata -j .text -D $< > $@
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390x_z2_ns: split_s390x_1_z2.o split_s390x_2_ns.o ../ld-new
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        ../ld-new $(SPLIT_DEFSYMS) -o $@ split_s390x_1_z2.o split_s390x_2_ns.o
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390x_z2_ns.stdout: split_s390x_z2_ns
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        $(TEST_OBJDUMP) -j .rodata -j .text -D $< > $@
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390x_z3_ns: split_s390x_1_z3.o split_s390x_2_ns.o ../ld-new
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        ../ld-new $(SPLIT_DEFSYMS) -o $@ split_s390x_1_z3.o split_s390x_2_ns.o
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390x_z3_ns.stdout: split_s390x_z3_ns
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        $(TEST_OBJDUMP) -j .rodata -j .text -D $< > $@
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390x_z4_ns: split_s390x_1_z4.o split_s390x_2_ns.o ../ld-new
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        ../ld-new $(SPLIT_DEFSYMS) -o $@ split_s390x_1_z4.o split_s390x_2_ns.o
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390x_z4_ns.stdout: split_s390x_z4_ns
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        $(TEST_OBJDUMP) -j .rodata -j .text -D $< > $@
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390x_n1_ns: split_s390x_1_n1.o split_s390x_2_ns.o ../ld-new
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        ../ld-new $(SPLIT_DEFSYMS) -o $@ split_s390x_1_n1.o split_s390x_2_ns.o
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390x_n1_ns.stdout: split_s390x_n1_ns
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        $(TEST_OBJDUMP) -d $< > $@
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390x_n2_ns.stdout: split_s390x_1_n2.o split_s390x_2_ns.o ../ld-new
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        ../ld-new $(SPLIT_DEFSYMS) -o split_s390x_n2 split_s390x_1_n2.o split_s390x_2_ns.o > $@ 2>&1 || exit 0
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390x_a1.stdout: split_s390x_1_a1.o split_s390x_2_ns.o ../ld-new
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        ../ld-new $(SPLIT_DEFSYMS) -o split_s390x_a1 split_s390x_1_a1.o split_s390x_2_ns.o > $@ 2>&1 || exit 0
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390x_a2: split_s390x_1_a2.o split_s390x_2_ns.o ../ld-new
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        ../ld-new $(SPLIT_DEFSYMS) -o $@ split_s390x_1_a2.o split_s390x_2_ns.o
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390x_a2.stdout: split_s390x_a2
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        $(TEST_OBJDUMP) -d $< > $@
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@split_s390x_r.stdout: split_s390x_1_z1.o split_s390x_2_ns.o ../ld-new
+@DEFAULT_TARGET_S390_TRUE@@NATIVE_OR_CROSS_LINKER_TRUE@        ../ld-new -r split_s390x_1_z1.o split_s390x_2_ns.o -o split_s390x_r > $@ 2>&1 || exit 0
 
 # Tests for the dwp tool.
 # We don't want to rely yet on GCC support for -gsplit-dwarf,
diff --git a/gold/testsuite/split_s390.sh b/gold/testsuite/split_s390.sh
new file mode 100755 (executable)
index 0000000..a4234e1
--- /dev/null
@@ -0,0 +1,117 @@
+#!/bin/sh
+
+# split_s390.sh -- test -fstack-split for s390
+
+# Copyright (C) 2009-2015 Free Software Foundation, Inc.
+# Written by Marcin Kościelnicki <koriakin@0x04.net>.
+
+# This file is part of gold.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, USA.
+
+match()
+{
+  if ! egrep "$1" "$2" >/dev/null 2>&1; then
+    echo 1>&2 "could not find '$1' in $2"
+    exit 1
+  fi
+}
+
+nomatch()
+{
+  if egrep "$1" "$2" >/dev/null 2>&1; then
+    echo 1>&2 "found unexpected '$1' in $2"
+    exit 1
+  fi
+}
+
+match 'jg.*__morestack>?$' split_s390_z1.stdout
+match 'long.*0x00100000$' split_s390_z1.stdout
+match 'jg.*__morestack>?$' split_s390_z1_ns.stdout
+match 'long.*0x00104000$' split_s390_z1_ns.stdout
+
+match 'ear.*$' split_s390_z2.stdout
+match 'jgl.*__morestack>?$' split_s390_z2.stdout
+nomatch 'jg    .*__morestack>?$' split_s390_z2.stdout
+match 'long.*0x00000100$' split_s390_z2.stdout
+nomatch 'ear.*$' split_s390_z2_ns.stdout
+nomatch 'jgl.*__morestack>?$' split_s390_z2_ns.stdout
+match 'jg      .*__morestack>?$' split_s390_z2_ns.stdout
+match 'long.*0x00004100$' split_s390_z2_ns.stdout
+
+match 'ear.*$' split_s390_z3.stdout
+match 'jgl.*__morestack>?$' split_s390_z3.stdout
+nomatch 'jg    .*__morestack>?$' split_s390_z3.stdout
+match 'long.*0x00001000$' split_s390_z3.stdout
+nomatch 'ear.*$' split_s390_z3_ns.stdout
+nomatch 'jgl.*__morestack>?$' split_s390_z3_ns.stdout
+match 'jg      .*__morestack>?$' split_s390_z3_ns.stdout
+match 'long.*0x00005000$' split_s390_z3_ns.stdout
+
+match 'alfi.*%r1,1048576$' split_s390_z4.stdout
+match 'jgl.*__morestack>?$' split_s390_z4.stdout
+match 'long.*0x00100000$' split_s390_z4.stdout
+match 'alfi.*%r1,1064960$' split_s390_z4_ns.stdout
+match 'jgl.*__morestack>?$' split_s390_z4_ns.stdout
+match 'long.*0x00104000$' split_s390_z4_ns.stdout
+
+match 'jg.*__morestack>?$' split_s390x_z1.stdout
+match 'long.*0x00100000$' split_s390x_z1.stdout
+match 'jg.*__morestack>?$' split_s390x_z1_ns.stdout
+match 'long.*0x00104000$' split_s390x_z1_ns.stdout
+
+match 'ear.*$' split_s390x_z2.stdout
+match 'jgl.*__morestack>?$' split_s390x_z2.stdout
+nomatch 'jg    .*__morestack>?$' split_s390x_z2.stdout
+match 'long.*0x00000100$' split_s390x_z2.stdout
+nomatch 'ear.*$' split_s390x_z2_ns.stdout
+nomatch 'jgl.*__morestack>?$' split_s390x_z2_ns.stdout
+match 'jg      .*__morestack>?$' split_s390x_z2_ns.stdout
+match 'long.*0x00004100$' split_s390x_z2_ns.stdout
+
+match 'ear.*$' split_s390x_z3.stdout
+match 'jgl.*__morestack>?$' split_s390x_z3.stdout
+nomatch 'jg    .*__morestack>?$' split_s390x_z3.stdout
+match 'long.*0x00001000$' split_s390x_z3.stdout
+nomatch 'ear.*$' split_s390x_z3_ns.stdout
+nomatch 'jgl.*__morestack>?$' split_s390x_z3_ns.stdout
+match 'jg      .*__morestack>?$' split_s390x_z3_ns.stdout
+match 'long.*0x00005000$' split_s390x_z3_ns.stdout
+
+match 'algfi.*%r1,1048576$' split_s390x_z4.stdout
+match 'jgl.*__morestack>?$' split_s390x_z4.stdout
+match 'long.*0x00100000$' split_s390x_z4.stdout
+match 'algfi.*%r1,1064960$' split_s390x_z4_ns.stdout
+match 'jgl.*__morestack>?$' split_s390x_z4_ns.stdout
+match 'long.*0x00104000$' split_s390x_z4_ns.stdout
+
+match 'larl' split_s390_n1.stdout
+match 'larl' split_s390_n1_ns.stdout
+match 'larl' split_s390x_n1.stdout
+match 'larl' split_s390x_n1_ns.stdout
+match 'j.*fn2' split_s390_n2.stdout
+match 'j.*fn2' split_s390x_n2.stdout
+match 'failed to match' split_s390_n2_ns.stdout
+match 'failed to match' split_s390x_n2_ns.stdout
+
+match 'failed to match' split_s390_a1.stdout
+match 'failed to match' split_s390x_a1.stdout
+
+match 'brasl.*__morestack>?$' split_s390_a2.stdout
+match 'brasl.*__morestack>?$' split_s390x_a2.stdout
+
+match 'cannot mix' split_s390_r.stdout
+match 'cannot mix' split_s390x_r.stdout
diff --git a/gold/testsuite/split_s390_1_a1.s b/gold/testsuite/split_s390_1_a1.s
new file mode 100644 (file)
index 0000000..f1537af
--- /dev/null
@@ -0,0 +1,27 @@
+# split_s390_1_a1.s: s390 specific, adjustment failure
+
+       .text
+
+       .global fn1
+       .type   fn1,@function
+fn1:
+       .cfi_startproc
+       stm     %r13, %r15, 0x34(%r15)
+       .cfi_offset     %r13, -0x2c
+       .cfi_offset     %r14, -0x28
+       .cfi_offset     %r15, -0x24
+       ahi     %r15, -0x60
+       .cfi_adjust_cfa_offset  0x60
+       brasl   %r14, __morestack
+       brasl   %r14, fn2
+       lm      %r13, %r15, 0x94(%r15)
+       .cfi_restore    %r13
+       .cfi_restore    %r14
+       .cfi_restore    %r15
+       .cfi_adjust_cfa_offset  -0x60
+       br      %r14
+       .cfi_endproc
+       .size   fn1,. - fn1
+
+       .section        .note.GNU-stack,"",@progbits
+       .section        .note.GNU-split-stack,"",@progbits
diff --git a/gold/testsuite/split_s390_1_a2.s b/gold/testsuite/split_s390_1_a2.s
new file mode 100644 (file)
index 0000000..b5633ff
--- /dev/null
@@ -0,0 +1,28 @@
+# split_s390_1_a2.s: s390 specific, permitted adjustment failure
+
+       .text
+
+       .global fn1
+       .type   fn1,@function
+fn1:
+       .cfi_startproc
+       stm     %r13, %r15, 0x34(%r15)
+       .cfi_offset     %r13, -0x2c
+       .cfi_offset     %r14, -0x28
+       .cfi_offset     %r15, -0x24
+       ahi     %r15, -0x60
+       .cfi_adjust_cfa_offset  0x60
+       brasl   %r14, __morestack
+       brasl   %r14, fn2
+       lm      %r13, %r15, 0x94(%r15)
+       .cfi_restore    %r13
+       .cfi_restore    %r14
+       .cfi_restore    %r15
+       .cfi_adjust_cfa_offset  -0x60
+       br      %r14
+       .cfi_endproc
+       .size   fn1,. - fn1
+
+       .section        .note.GNU-stack,"",@progbits
+       .section        .note.GNU-split-stack,"",@progbits
+       .section        .note.GNU-no-split-stack,"",@progbits
diff --git a/gold/testsuite/split_s390_1_n1.s b/gold/testsuite/split_s390_1_n1.s
new file mode 100644 (file)
index 0000000..a0db5b0
--- /dev/null
@@ -0,0 +1,16 @@
+# split_s390_1_n1.s: s390 specific test case for -fsplit-stack -
+# no stack frame, load function address.
+
+       .text
+
+       .global fn1
+       .type   fn1,@function
+fn1:
+       .cfi_startproc
+       larl    %r2, fn2
+       br      %r14
+       .cfi_endproc
+       .size   fn1,. - fn1
+
+       .section        .note.GNU-stack,"",@progbits
+       .section        .note.GNU-split-stack,"",@progbits
diff --git a/gold/testsuite/split_s390_1_n2.s b/gold/testsuite/split_s390_1_n2.s
new file mode 100644 (file)
index 0000000..3d684ee
--- /dev/null
@@ -0,0 +1,15 @@
+# split_s390_1_n2.s: s390 specific test case for -fsplit-stack -
+# no stack frame, short sibcall (will fail)
+
+       .text
+
+       .global fn1
+       .type   fn1,@function
+fn1:
+       .cfi_startproc
+       j       fn2
+       .cfi_endproc
+       .size   fn1,. - fn1
+
+       .section        .note.GNU-stack,"",@progbits
+       .section        .note.GNU-split-stack,"",@progbits
diff --git a/gold/testsuite/split_s390_1_z1.s b/gold/testsuite/split_s390_1_z1.s
new file mode 100644 (file)
index 0000000..42adf55
--- /dev/null
@@ -0,0 +1,37 @@
+# split_s390_z3.s: s390 specific test case for -fsplit-stack -
+# zarch mode, unconditional call
+
+       .text
+
+       .global fn1
+       .type   fn1,@function
+fn1:
+       .cfi_startproc
+       larl    %r1, .L1
+       jg      __morestack
+       .section .rodata
+       .align 4
+.L1:
+       .long   0x100000
+       .long   0
+       .long   .L2-.L1
+       .previous
+.L2:
+       stm     %r13, %r15, 0x34(%r15)
+       .cfi_offset     %r13, -0x2c
+       .cfi_offset     %r14, -0x28
+       .cfi_offset     %r15, -0x24
+       ahi     %r15, -0x60
+       .cfi_adjust_cfa_offset  0x60
+       brasl   %r14, fn2
+       lm      %r13, %r15, 0x94(%r15)
+       .cfi_restore    %r13
+       .cfi_restore    %r14
+       .cfi_restore    %r15
+       .cfi_adjust_cfa_offset  -0x60
+       br      %r14
+       .cfi_endproc
+       .size   fn1,. - fn1
+
+       .section        .note.GNU-stack,"",@progbits
+       .section        .note.GNU-split-stack,"",@progbits
diff --git a/gold/testsuite/split_s390_1_z2.s b/gold/testsuite/split_s390_1_z2.s
new file mode 100644 (file)
index 0000000..4a9cff3
--- /dev/null
@@ -0,0 +1,39 @@
+# split_s390_z2.s: s390 specific test case for -fsplit-stack -
+# zarch mode, conditional call, no add
+
+       .text
+
+       .global fn1
+       .type   fn1,@function
+fn1:
+       .cfi_startproc
+       ear     %r1, %a0
+       c       %r15, 0x20(%r1)
+       larl    %r1, .L1
+       jgl     __morestack
+       .section .rodata
+       .align 4
+.L1:
+       .long   0x100
+       .long   0
+       .long   .L2-.L1
+       .previous
+.L2:
+       stm     %r13, %r15, 0x34(%r15)
+       .cfi_offset     %r13, -0x2c
+       .cfi_offset     %r14, -0x28
+       .cfi_offset     %r15, -0x24
+       ahi     %r15, -0x60
+       .cfi_adjust_cfa_offset  0x60
+       brasl   %r14, fn2
+       lm      %r13, %r15, 0x94(%r15)
+       .cfi_restore    %r13
+       .cfi_restore    %r14
+       .cfi_restore    %r15
+       .cfi_adjust_cfa_offset  -0x60
+       br      %r14
+       .cfi_endproc
+       .size   fn1,. - fn1
+
+       .section        .note.GNU-stack,"",@progbits
+       .section        .note.GNU-split-stack,"",@progbits
diff --git a/gold/testsuite/split_s390_1_z3.s b/gold/testsuite/split_s390_1_z3.s
new file mode 100644 (file)
index 0000000..8f0cb54
--- /dev/null
@@ -0,0 +1,41 @@
+# split_s390_z3.s: s390 specific test case for -fsplit-stack -
+# zarch mode, conditional call, ahi.
+
+       .text
+
+       .global fn1
+       .type   fn1,@function
+fn1:
+       .cfi_startproc
+       ear     %r1, %a0
+       l       %r1, 0x20(%r1)
+       ahi     %r1, 0x1000
+       cr      %r15, %r1
+       larl    %r1, .L1
+       jgl     __morestack
+       .section .rodata
+       .align 4
+.L1:
+       .long   0x1000
+       .long   0
+       .long   .L2-.L1
+       .previous
+.L2:
+       stm     %r13, %r15, 0x34(%r15)
+       .cfi_offset     %r13, -0x2c
+       .cfi_offset     %r14, -0x28
+       .cfi_offset     %r15, -0x24
+       ahi     %r15, -0x60
+       .cfi_adjust_cfa_offset  0x60
+       brasl   %r14, fn2
+       lm      %r13, %r15, 0x94(%r15)
+       .cfi_restore    %r13
+       .cfi_restore    %r14
+       .cfi_restore    %r15
+       .cfi_adjust_cfa_offset  -0x60
+       br      %r14
+       .cfi_endproc
+       .size   fn1,. - fn1
+
+       .section        .note.GNU-stack,"",@progbits
+       .section        .note.GNU-split-stack,"",@progbits
diff --git a/gold/testsuite/split_s390_1_z4.s b/gold/testsuite/split_s390_1_z4.s
new file mode 100644 (file)
index 0000000..b80bf40
--- /dev/null
@@ -0,0 +1,41 @@
+# split_s390_z4.s: s390 specific test case for -fsplit-stack -
+# zarch mode, conditional call, alfi.
+
+       .text
+
+       .global fn1
+       .type   fn1,@function
+fn1:
+       .cfi_startproc
+       ear     %r1, %a0
+       l       %r1, 0x20(%r1)
+       alfi    %r1, 0x100000
+       cr      %r15, %r1
+       larl    %r1, .L1
+       jgl     __morestack
+       .section .rodata
+       .align 4
+.L1:
+       .long   0x100000
+       .long   0
+       .long   .L2-.L1
+       .previous
+.L2:
+       stm     %r13, %r15, 0x34(%r15)
+       .cfi_offset     %r13, -0x2c
+       .cfi_offset     %r14, -0x28
+       .cfi_offset     %r15, -0x24
+       ahi     %r15, -0x60
+       .cfi_adjust_cfa_offset  0x60
+       brasl   %r14, fn2
+       lm      %r13, %r15, 0x94(%r15)
+       .cfi_restore    %r13
+       .cfi_restore    %r14
+       .cfi_restore    %r15
+       .cfi_adjust_cfa_offset  -0x60
+       br      %r14
+       .cfi_endproc
+       .size   fn1,. - fn1
+
+       .section        .note.GNU-stack,"",@progbits
+       .section        .note.GNU-split-stack,"",@progbits
diff --git a/gold/testsuite/split_s390_2_ns.s b/gold/testsuite/split_s390_2_ns.s
new file mode 100644 (file)
index 0000000..fb5a993
--- /dev/null
@@ -0,0 +1,12 @@
+# split_s390_2_ns.s: s390 specific, -fsplit-stack calling non-split
+
+       .text
+
+       .global fn2
+       .type   fn2,@function
+fn2:
+       br      %r14
+
+       .size   fn2,. - fn2
+
+       .section        .note.GNU-stack,"",@progbits
diff --git a/gold/testsuite/split_s390_2_s.s b/gold/testsuite/split_s390_2_s.s
new file mode 100644 (file)
index 0000000..3df8009
--- /dev/null
@@ -0,0 +1,13 @@
+# split_s390_2_s.s: s390 specific, -fsplit-stack calling -fsplit-stack
+
+       .text
+
+       .global fn2
+       .type   fn2,@function
+fn2:
+       br      %r14
+
+       .size   fn2,. - fn2
+
+       .section        .note.GNU-stack,"",@progbits
+       .section        .note.GNU-split-stack,"",@progbits
diff --git a/gold/testsuite/split_s390x_1_a1.s b/gold/testsuite/split_s390x_1_a1.s
new file mode 100644 (file)
index 0000000..ccc62cb
--- /dev/null
@@ -0,0 +1,27 @@
+# split_s390x_1_a1.s: s390x specific, adjustment failure
+
+       .text
+
+       .global fn1
+       .type   fn1,@function
+fn1:
+       .cfi_startproc
+       stmg    %r13, %r15, 0x68(%r15)
+       .cfi_offset     %r13, -0x38
+       .cfi_offset     %r14, -0x30
+       .cfi_offset     %r15, -0x28
+       aghi    %r15, -0xa0
+       .cfi_adjust_cfa_offset  0xa0
+       brasl   %r14, __morestack
+       brasl   %r14, fn2
+       lmg     %r13, %r15, 0x108(%r15)
+       .cfi_restore    %r13
+       .cfi_restore    %r14
+       .cfi_restore    %r15
+       .cfi_adjust_cfa_offset  -0xa0
+       br      %r14
+       .cfi_endproc
+       .size   fn1,. - fn1
+
+       .section        .note.GNU-stack,"",@progbits
+       .section        .note.GNU-split-stack,"",@progbits
diff --git a/gold/testsuite/split_s390x_1_a2.s b/gold/testsuite/split_s390x_1_a2.s
new file mode 100644 (file)
index 0000000..a5c067b
--- /dev/null
@@ -0,0 +1,28 @@
+# split_s390x_1_a2.s: s390x specific, permitted adjustment failure
+
+       .text
+
+       .global fn1
+       .type   fn1,@function
+fn1:
+       .cfi_startproc
+       stmg    %r13, %r15, 0x68(%r15)
+       .cfi_offset     %r13, -0x38
+       .cfi_offset     %r14, -0x30
+       .cfi_offset     %r15, -0x28
+       aghi    %r15, -0xa0
+       .cfi_adjust_cfa_offset  0xa0
+       brasl   %r14, __morestack
+       brasl   %r14, fn2
+       lmg     %r13, %r15, 0x108(%r15)
+       .cfi_restore    %r13
+       .cfi_restore    %r14
+       .cfi_restore    %r15
+       .cfi_adjust_cfa_offset  -0xa0
+       br      %r14
+       .cfi_endproc
+       .size   fn1,. - fn1
+
+       .section        .note.GNU-stack,"",@progbits
+       .section        .note.GNU-split-stack,"",@progbits
+       .section        .note.GNU-no-split-stack,"",@progbits
diff --git a/gold/testsuite/split_s390x_1_n1.s b/gold/testsuite/split_s390x_1_n1.s
new file mode 100644 (file)
index 0000000..3b69f25
--- /dev/null
@@ -0,0 +1,16 @@
+# split_s390x_1_n1.s: s390x specific test case for -fsplit-stack -
+# no stack frame, load function address.
+
+       .text
+
+       .global fn1
+       .type   fn1,@function
+fn1:
+       .cfi_startproc
+       larl    %r2, fn2
+       br      %r14
+       .cfi_endproc
+       .size   fn1,. - fn1
+
+       .section        .note.GNU-stack,"",@progbits
+       .section        .note.GNU-split-stack,"",@progbits
diff --git a/gold/testsuite/split_s390x_1_n2.s b/gold/testsuite/split_s390x_1_n2.s
new file mode 100644 (file)
index 0000000..762cd19
--- /dev/null
@@ -0,0 +1,15 @@
+# split_s390x_1_n2.s: s390x specific test case for -fsplit-stack -
+# no stack frame, short sibcall (will fail)
+
+       .text
+
+       .global fn1
+       .type   fn1,@function
+fn1:
+       .cfi_startproc
+       j       fn2
+       .cfi_endproc
+       .size   fn1,. - fn1
+
+       .section        .note.GNU-stack,"",@progbits
+       .section        .note.GNU-split-stack,"",@progbits
diff --git a/gold/testsuite/split_s390x_1_z1.s b/gold/testsuite/split_s390x_1_z1.s
new file mode 100644 (file)
index 0000000..4af34cd
--- /dev/null
@@ -0,0 +1,37 @@
+# split_s390x_1_z1.s: s390x specific test case for -fsplit-stack -
+# unconditional call.
+
+       .text
+
+       .global fn1
+       .type   fn1,@function
+fn1:
+       .cfi_startproc
+       larl    %r1, .L1
+       jg      __morestack
+       .section .rodata
+       .align 8
+.L1:
+       .quad   0x100000
+       .quad   0
+       .quad   .L2-.L1
+       .previous
+.L2:
+       stmg    %r13, %r15, 0x68(%r15)
+       .cfi_offset     %r13, -0x38
+       .cfi_offset     %r14, -0x30
+       .cfi_offset     %r15, -0x28
+       aghi    %r15, -0xa0
+       .cfi_adjust_cfa_offset  0xa0
+       brasl   %r14, fn2
+       lmg     %r13, %r15, 0x108(%r15)
+       .cfi_restore    %r13
+       .cfi_restore    %r14
+       .cfi_restore    %r15
+       .cfi_adjust_cfa_offset  -0xa0
+       br      %r14
+       .cfi_endproc
+       .size   fn1,. - fn1
+
+       .section        .note.GNU-stack,"",@progbits
+       .section        .note.GNU-split-stack,"",@progbits
diff --git a/gold/testsuite/split_s390x_1_z2.s b/gold/testsuite/split_s390x_1_z2.s
new file mode 100644 (file)
index 0000000..a184f77
--- /dev/null
@@ -0,0 +1,41 @@
+# split_s390x_1_z2.s: s390x specific test case for -fsplit-stack -
+# conditional call, no add.
+
+       .text
+
+       .global fn1
+       .type   fn1,@function
+fn1:
+       .cfi_startproc
+       ear     %r1, %a0
+       sllg    %r1, %r1, 32
+       ear     %r1, %a1
+       cg      %r15, 0x38(%r1)
+       larl    %r1, .L1
+       jgl     __morestack
+       .section .rodata
+       .align 8
+.L1:
+       .quad   0x100
+       .quad   0
+       .quad   .L2-.L1
+       .previous
+.L2:
+       stmg    %r13, %r15, 0x68(%r15)
+       .cfi_offset     %r13, -0x38
+       .cfi_offset     %r14, -0x30
+       .cfi_offset     %r15, -0x28
+       aghi    %r15, -0xa0
+       .cfi_adjust_cfa_offset  0xa0
+       brasl   %r14, fn2
+       lmg     %r13, %r15, 0x108(%r15)
+       .cfi_restore    %r13
+       .cfi_restore    %r14
+       .cfi_restore    %r15
+       .cfi_adjust_cfa_offset  -0xa0
+       br      %r14
+       .cfi_endproc
+       .size   fn1,. - fn1
+
+       .section        .note.GNU-stack,"",@progbits
+       .section        .note.GNU-split-stack,"",@progbits
diff --git a/gold/testsuite/split_s390x_1_z3.s b/gold/testsuite/split_s390x_1_z3.s
new file mode 100644 (file)
index 0000000..b0a4b0b
--- /dev/null
@@ -0,0 +1,43 @@
+# split_s390x_1_z3.s: s390x specific test case for -fsplit-stack -
+# conditional call, ahi.
+
+       .text
+
+       .global fn1
+       .type   fn1,@function
+fn1:
+       .cfi_startproc
+       ear     %r1, %a0
+       sllg    %r1, %r1, 32
+       ear     %r1, %a1
+       lg      %r1, 0x38(%r1)
+       aghi    %r1, 0x1000
+       cgr     %r15, %r1
+       larl    %r1, .L1
+       jgl     __morestack
+       .section .rodata
+       .align 8
+.L1:
+       .quad   0x1000
+       .quad   0
+       .quad   .L2-.L1
+       .previous
+.L2:
+       stmg    %r13, %r15, 0x68(%r15)
+       .cfi_offset     %r13, -0x38
+       .cfi_offset     %r14, -0x30
+       .cfi_offset     %r15, -0x28
+       aghi    %r15, -0xa0
+       .cfi_adjust_cfa_offset  0xa0
+       brasl   %r14, fn2
+       lmg     %r13, %r15, 0x108(%r15)
+       .cfi_restore    %r13
+       .cfi_restore    %r14
+       .cfi_restore    %r15
+       .cfi_adjust_cfa_offset  -0xa0
+       br      %r14
+       .cfi_endproc
+       .size   fn1,. - fn1
+
+       .section        .note.GNU-stack,"",@progbits
+       .section        .note.GNU-split-stack,"",@progbits
diff --git a/gold/testsuite/split_s390x_1_z4.s b/gold/testsuite/split_s390x_1_z4.s
new file mode 100644 (file)
index 0000000..a3b942e
--- /dev/null
@@ -0,0 +1,43 @@
+# split_s390x_1_z4.s: s390x specific test case for -fsplit-stack -
+# conditional call, alfi.
+
+       .text
+
+       .global fn1
+       .type   fn1,@function
+fn1:
+       .cfi_startproc
+       ear     %r1, %a0
+       sllg    %r1, %r1, 32
+       ear     %r1, %a1
+       lg      %r1, 0x38(%r1)
+       algfi   %r1, 0x100000
+       cgr     %r15, %r1
+       larl    %r1, .L1
+       jgl     __morestack
+       .section .rodata
+       .align 8
+.L1:
+       .quad   0x100000
+       .quad   0
+       .quad   .L2-.L1
+       .previous
+.L2:
+       stmg    %r13, %r15, 0x68(%r15)
+       .cfi_offset     %r13, -0x38
+       .cfi_offset     %r14, -0x30
+       .cfi_offset     %r15, -0x28
+       aghi    %r15, -0xa0
+       .cfi_adjust_cfa_offset  0xa0
+       brasl   %r14, fn2
+       lmg     %r13, %r15, 0x108(%r15)
+       .cfi_restore    %r13
+       .cfi_restore    %r14
+       .cfi_restore    %r15
+       .cfi_adjust_cfa_offset  -0xa0
+       br      %r14
+       .cfi_endproc
+       .size   fn1,. - fn1
+
+       .section        .note.GNU-stack,"",@progbits
+       .section        .note.GNU-split-stack,"",@progbits
diff --git a/gold/testsuite/split_s390x_2_ns.s b/gold/testsuite/split_s390x_2_ns.s
new file mode 100644 (file)
index 0000000..f073eee
--- /dev/null
@@ -0,0 +1,12 @@
+# split_s390x_2_ns.s: s390x specific, -fsplit-stack calling non-split
+
+       .text
+
+       .global fn2
+       .type   fn2,@function
+fn2:
+       br      %r14
+
+       .size   fn2,. - fn2
+
+       .section        .note.GNU-stack,"",@progbits
diff --git a/gold/testsuite/split_s390x_2_s.s b/gold/testsuite/split_s390x_2_s.s
new file mode 100644 (file)
index 0000000..787d2fe
--- /dev/null
@@ -0,0 +1,13 @@
+# split_s390x_2_s.s: s390x specific, -fsplit-stack calling non-split
+
+       .text
+
+       .global fn2
+       .type   fn2,@function
+fn2:
+       br      %r14
+
+       .size   fn2,. - fn2
+
+       .section        .note.GNU-stack,"",@progbits
+       .section        .note.GNU-split-stack,"",@progbits