Blame SOURCES/bcc-0.8.0-usdt-s390x.patch

5d1f51
From ba41501bb2ca89312061b31c08e570a11c092370 Mon Sep 17 00:00:00 2001
5d1f51
From: mephi42 <mephi42@gmail.com>
5d1f51
Date: Tue, 12 Mar 2019 07:02:56 +0100
5d1f51
Subject: [PATCH] Add basic USDT support for s390x (#2266)
5d1f51
5d1f51
Approach and code shamelessly borrowed from "422db709: Add basic USDT
5d1f51
support for powerpc64".
5d1f51
---
5d1f51
 src/cc/usdt.h              |  7 +++++
5d1f51
 src/cc/usdt/usdt.cc        |  2 ++
5d1f51
 src/cc/usdt/usdt_args.cc   | 53 ++++++++++++++++++++++++++++++++++++++
5d1f51
 tests/cc/test_usdt_args.cc | 46 +++++++++++++++++++++++++++++++++
5d1f51
 4 files changed, 108 insertions(+)
5d1f51
5d1f51
diff --git a/src/cc/usdt.h b/src/cc/usdt.h
5d1f51
index 6d89fd644..406cfd546 100644
5d1f51
--- a/src/cc/usdt.h
5d1f51
+++ b/src/cc/usdt.h
5d1f51
@@ -81,6 +81,7 @@ class Argument {
5d1f51
   friend class ArgumentParser;
5d1f51
   friend class ArgumentParser_aarch64;
5d1f51
   friend class ArgumentParser_powerpc64;
5d1f51
+  friend class ArgumentParser_s390x;
5d1f51
   friend class ArgumentParser_x64;
5d1f51
 };
5d1f51
 
5d1f51
@@ -130,6 +131,12 @@ class ArgumentParser_powerpc64 : public ArgumentParser {
5d1f51
   ArgumentParser_powerpc64(const char *arg) : ArgumentParser(arg) {}
5d1f51
 };
5d1f51
 
5d1f51
+class ArgumentParser_s390x : public ArgumentParser {
5d1f51
+public:
5d1f51
+  bool parse(Argument *dest);
5d1f51
+  ArgumentParser_s390x(const char *arg) : ArgumentParser(arg) {}
5d1f51
+};
5d1f51
+
5d1f51
 class ArgumentParser_x64 : public ArgumentParser {
5d1f51
 private:
5d1f51
   enum Register {
5d1f51
diff --git a/src/cc/usdt/usdt.cc b/src/cc/usdt/usdt.cc
5d1f51
index 0914fe3a5..c91faa016 100644
5d1f51
--- a/src/cc/usdt/usdt.cc
5d1f51
+++ b/src/cc/usdt/usdt.cc
5d1f51
@@ -40,6 +40,8 @@ Location::Location(uint64_t addr, const std::string &bin_path, const char *arg_f
5d1f51
   ArgumentParser_aarch64 parser(arg_fmt);
5d1f51
 #elif __powerpc64__
5d1f51
   ArgumentParser_powerpc64 parser(arg_fmt);
5d1f51
+#elif __s390x__
5d1f51
+  ArgumentParser_s390x parser(arg_fmt);
5d1f51
 #else
5d1f51
   ArgumentParser_x64 parser(arg_fmt);
5d1f51
 #endif
5d1f51
diff --git a/src/cc/usdt/usdt_args.cc b/src/cc/usdt/usdt_args.cc
5d1f51
index b27e515f4..3e2045575 100644
5d1f51
--- a/src/cc/usdt/usdt_args.cc
5d1f51
+++ b/src/cc/usdt/usdt_args.cc
5d1f51
@@ -285,6 +285,59 @@ bool ArgumentParser_powerpc64::parse(Argument *dest) {
5d1f51
   return true;
5d1f51
 }
5d1f51
 
5d1f51
+bool ArgumentParser_s390x::parse(Argument *dest) {
5d1f51
+  if (done())
5d1f51
+    return false;
5d1f51
+
5d1f51
+  bool matched;
5d1f51
+  std::cmatch matches;
5d1f51
+#define S390X_IMM "(-?[0-9]+)"
5d1f51
+  std::regex arg_n_regex("^" S390X_IMM "@");
5d1f51
+  // <imm>
5d1f51
+  std::regex arg_op_regex_imm("^" S390X_IMM "(?: +|$)");
5d1f51
+  // %r<N>
5d1f51
+#define S390X_REG "%r([0-9]|1[0-5])"
5d1f51
+  std::regex arg_op_regex_reg("^" S390X_REG "(?: +|$)");
5d1f51
+  // <disp>(%r<N>,%r<N>)
5d1f51
+  std::regex arg_op_regex_mem("^" S390X_IMM "?\\(" S390X_REG
5d1f51
+                              "(?:," S390X_REG ")?\\)(?: +|$)");
5d1f51
+#undef S390X_IMM
5d1f51
+#undef S390X_REG
5d1f51
+
5d1f51
+  matched = std::regex_search(arg_ + cur_pos_, matches, arg_n_regex);
5d1f51
+  if (matched) {
5d1f51
+    dest->arg_size_ = stoi(matches.str(1));
5d1f51
+    cur_pos_ += matches.length(0);
5d1f51
+
5d1f51
+    if (std::regex_search(arg_ + cur_pos_, matches, arg_op_regex_imm)) {
5d1f51
+      dest->constant_ = stoi(matches.str(1));
5d1f51
+    } else if (std::regex_search(arg_ + cur_pos_, matches, arg_op_regex_reg)) {
5d1f51
+      dest->base_register_name_ = "gprs[" + matches.str(1) + "]";
5d1f51
+    } else if (std::regex_search(arg_ + cur_pos_, matches, arg_op_regex_mem)) {
5d1f51
+      if (matches.length(1) > 0) {
5d1f51
+        dest->deref_offset_ = stoi(matches.str(1));
5d1f51
+      }
5d1f51
+      dest->base_register_name_ = "gprs[" + matches.str(2) + "]";
5d1f51
+      if (matches.length(3) > 0) {
5d1f51
+        dest->index_register_name_ = "gprs[" + matches.str(3) + "]";
5d1f51
+      }
5d1f51
+    } else {
5d1f51
+      matched = false;
5d1f51
+    }
5d1f51
+  }
5d1f51
+
5d1f51
+  if (!matched) {
5d1f51
+    print_error(cur_pos_);
5d1f51
+    skip_until_whitespace_from(cur_pos_);
5d1f51
+    skip_whitespace_from(cur_pos_);
5d1f51
+    return false;
5d1f51
+  }
5d1f51
+
5d1f51
+  cur_pos_ += matches.length(0);
5d1f51
+  skip_whitespace_from(cur_pos_);
5d1f51
+  return true;
5d1f51
+}
5d1f51
+
5d1f51
 ssize_t ArgumentParser_x64::parse_identifier(ssize_t pos,
5d1f51
                                              optional<std::string> *result) {
5d1f51
   if (isalpha(arg_[pos]) || arg_[pos] == '_') {
5d1f51
diff --git a/tests/cc/test_usdt_args.cc b/tests/cc/test_usdt_args.cc
5d1f51
index 3a96c5aac..db1f8c8e6 100644
5d1f51
--- a/tests/cc/test_usdt_args.cc
5d1f51
+++ b/tests/cc/test_usdt_args.cc
5d1f51
@@ -58,6 +58,8 @@ TEST_CASE("test usdt argument parsing", "[usdt]") {
5d1f51
     USDT::ArgumentParser_aarch64 parser("4@[x32,200]");
5d1f51
 #elif __powerpc64__
5d1f51
     USDT::ArgumentParser_powerpc64 parser("4@-12(42)");
5d1f51
+#elif __s390x__
5d1f51
+    USDT::ArgumentParser_s390x parser("4@-12(%r42)");
5d1f51
 #elif defined(__x86_64__)
5d1f51
     USDT::ArgumentParser_x64 parser("4@i%ra+1r");
5d1f51
 #endif
5d1f51
@@ -121,6 +123,50 @@ TEST_CASE("test usdt argument parsing", "[usdt]") {
5d1f51
     verify_register(parser, 2, 1097);
5d1f51
     verify_register(parser, 4, "gpr[30]", 108);
5d1f51
     verify_register(parser, -2, "gpr[31]", -4);
5d1f51
+#elif __s390x__
5d1f51
+    USDT::ArgumentParser_s390x parser(
5d1f51
+        "-4@%r0 8@%r0 8@0 4@0(%r0) -2@0(%r0) "
5d1f51
+        "1@%r0 -2@%r3 -8@9 -1@0(%r4) -4@16(%r6) "
5d1f51
+        "2@%r7 4@%r11 4@-67 8@-16(%r15) 1@-52(%r11) "
5d1f51
+        "-8@%r4 -8@%r14 2@-11 -2@14(%r13) -8@-32(%r12) "
5d1f51
+        "4@%r5 2@%r11 -8@-693 -1@-23(%r10) 4@28(%r9) "
5d1f51
+        "-2@%r3 -4@%r8 2@1097 4@108(%r7) -2@-4(%r6)");
5d1f51
+
5d1f51
+    verify_register(parser, -4, "gprs[0]");
5d1f51
+    verify_register(parser, 8, "gprs[0]");
5d1f51
+    verify_register(parser, 8, 0);
5d1f51
+    verify_register(parser, 4, "gprs[0]", 0);
5d1f51
+    verify_register(parser, -2, "gprs[0]", 0);
5d1f51
+
5d1f51
+    verify_register(parser, 1, "gprs[0]");
5d1f51
+    verify_register(parser, -2, "gprs[3]");
5d1f51
+    verify_register(parser, -8, 9);
5d1f51
+    verify_register(parser, -1, "gprs[4]", 0);
5d1f51
+    verify_register(parser, -4, "gprs[6]", 16);
5d1f51
+
5d1f51
+    verify_register(parser, 2, "gprs[7]");
5d1f51
+    verify_register(parser, 4, "gprs[11]");
5d1f51
+    verify_register(parser, 4, -67);
5d1f51
+    verify_register(parser, 8, "gprs[15]", -16);
5d1f51
+    verify_register(parser, 1, "gprs[11]", -52);
5d1f51
+
5d1f51
+    verify_register(parser, -8, "gprs[4]");
5d1f51
+    verify_register(parser, -8, "gprs[14]");
5d1f51
+    verify_register(parser, 2, -11);
5d1f51
+    verify_register(parser, -2, "gprs[13]", 14);
5d1f51
+    verify_register(parser, -8, "gprs[12]", -32);
5d1f51
+
5d1f51
+    verify_register(parser, 4, "gprs[5]");
5d1f51
+    verify_register(parser, 2, "gprs[11]");
5d1f51
+    verify_register(parser, -8, -693);
5d1f51
+    verify_register(parser, -1, "gprs[10]", -23);
5d1f51
+    verify_register(parser, 4, "gprs[9]", 28);
5d1f51
+
5d1f51
+    verify_register(parser, -2, "gprs[3]");
5d1f51
+    verify_register(parser, -4, "gprs[8]");
5d1f51
+    verify_register(parser, 2, 1097);
5d1f51
+    verify_register(parser, 4, "gprs[7]", 108);
5d1f51
+    verify_register(parser, -2, "gprs[6]", -4);
5d1f51
 #elif defined(__x86_64__)
5d1f51
     USDT::ArgumentParser_x64 parser(
5d1f51
         "-4@$0 8@$1234 %rdi %rax %rsi "