Skip to content

Commit

Permalink
Add basic USDT support for s390x (iovisor#2266)
Browse files Browse the repository at this point in the history
Approach and code shamelessly borrowed from "422db709: Add basic USDT
support for powerpc64".
  • Loading branch information
mephi42 authored and yonghong-song committed Mar 12, 2019
1 parent 6d147e6 commit ba41501
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 0 deletions.
7 changes: 7 additions & 0 deletions src/cc/usdt.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ class Argument {
friend class ArgumentParser;
friend class ArgumentParser_aarch64;
friend class ArgumentParser_powerpc64;
friend class ArgumentParser_s390x;
friend class ArgumentParser_x64;
};

Expand Down Expand Up @@ -130,6 +131,12 @@ class ArgumentParser_powerpc64 : public ArgumentParser {
ArgumentParser_powerpc64(const char *arg) : ArgumentParser(arg) {}
};

class ArgumentParser_s390x : public ArgumentParser {
public:
bool parse(Argument *dest);
ArgumentParser_s390x(const char *arg) : ArgumentParser(arg) {}
};

class ArgumentParser_x64 : public ArgumentParser {
private:
enum Register {
Expand Down
2 changes: 2 additions & 0 deletions src/cc/usdt/usdt.cc
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ Location::Location(uint64_t addr, const std::string &bin_path, const char *arg_f
ArgumentParser_aarch64 parser(arg_fmt);
#elif __powerpc64__
ArgumentParser_powerpc64 parser(arg_fmt);
#elif __s390x__
ArgumentParser_s390x parser(arg_fmt);
#else
ArgumentParser_x64 parser(arg_fmt);
#endif
Expand Down
53 changes: 53 additions & 0 deletions src/cc/usdt/usdt_args.cc
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,59 @@ bool ArgumentParser_powerpc64::parse(Argument *dest) {
return true;
}

bool ArgumentParser_s390x::parse(Argument *dest) {
if (done())
return false;

bool matched;
std::cmatch matches;
#define S390X_IMM "(-?[0-9]+)"
std::regex arg_n_regex("^" S390X_IMM "@");
// <imm>
std::regex arg_op_regex_imm("^" S390X_IMM "(?: +|$)");
// %r<N>
#define S390X_REG "%r([0-9]|1[0-5])"
std::regex arg_op_regex_reg("^" S390X_REG "(?: +|$)");
// <disp>(%r<N>,%r<N>)
std::regex arg_op_regex_mem("^" S390X_IMM "?\\(" S390X_REG
"(?:," S390X_REG ")?\\)(?: +|$)");
#undef S390X_IMM
#undef S390X_REG

matched = std::regex_search(arg_ + cur_pos_, matches, arg_n_regex);
if (matched) {
dest->arg_size_ = stoi(matches.str(1));
cur_pos_ += matches.length(0);

if (std::regex_search(arg_ + cur_pos_, matches, arg_op_regex_imm)) {
dest->constant_ = stoi(matches.str(1));
} else if (std::regex_search(arg_ + cur_pos_, matches, arg_op_regex_reg)) {
dest->base_register_name_ = "gprs[" + matches.str(1) + "]";
} else if (std::regex_search(arg_ + cur_pos_, matches, arg_op_regex_mem)) {
if (matches.length(1) > 0) {
dest->deref_offset_ = stoi(matches.str(1));
}
dest->base_register_name_ = "gprs[" + matches.str(2) + "]";
if (matches.length(3) > 0) {
dest->index_register_name_ = "gprs[" + matches.str(3) + "]";
}
} else {
matched = false;
}
}

if (!matched) {
print_error(cur_pos_);
skip_until_whitespace_from(cur_pos_);
skip_whitespace_from(cur_pos_);
return false;
}

cur_pos_ += matches.length(0);
skip_whitespace_from(cur_pos_);
return true;
}

ssize_t ArgumentParser_x64::parse_identifier(ssize_t pos,
optional<std::string> *result) {
if (isalpha(arg_[pos]) || arg_[pos] == '_') {
Expand Down
46 changes: 46 additions & 0 deletions tests/cc/test_usdt_args.cc
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ TEST_CASE("test usdt argument parsing", "[usdt]") {
USDT::ArgumentParser_aarch64 parser("4@[x32,200]");
#elif __powerpc64__
USDT::ArgumentParser_powerpc64 parser("4@-12(42)");
#elif __s390x__
USDT::ArgumentParser_s390x parser("4@-12(%r42)");
#elif defined(__x86_64__)
USDT::ArgumentParser_x64 parser("4@i%ra+1r");
#endif
Expand Down Expand Up @@ -121,6 +123,50 @@ TEST_CASE("test usdt argument parsing", "[usdt]") {
verify_register(parser, 2, 1097);
verify_register(parser, 4, "gpr[30]", 108);
verify_register(parser, -2, "gpr[31]", -4);
#elif __s390x__
USDT::ArgumentParser_s390x parser(
"-4@%r0 8@%r0 8@0 4@0(%r0) -2@0(%r0) "
"1@%r0 -2@%r3 -8@9 -1@0(%r4) -4@16(%r6) "
"2@%r7 4@%r11 4@-67 8@-16(%r15) 1@-52(%r11) "
"-8@%r4 -8@%r14 2@-11 -2@14(%r13) -8@-32(%r12) "
"4@%r5 2@%r11 -8@-693 -1@-23(%r10) 4@28(%r9) "
"-2@%r3 -4@%r8 2@1097 4@108(%r7) -2@-4(%r6)");

verify_register(parser, -4, "gprs[0]");
verify_register(parser, 8, "gprs[0]");
verify_register(parser, 8, 0);
verify_register(parser, 4, "gprs[0]", 0);
verify_register(parser, -2, "gprs[0]", 0);

verify_register(parser, 1, "gprs[0]");
verify_register(parser, -2, "gprs[3]");
verify_register(parser, -8, 9);
verify_register(parser, -1, "gprs[4]", 0);
verify_register(parser, -4, "gprs[6]", 16);

verify_register(parser, 2, "gprs[7]");
verify_register(parser, 4, "gprs[11]");
verify_register(parser, 4, -67);
verify_register(parser, 8, "gprs[15]", -16);
verify_register(parser, 1, "gprs[11]", -52);

verify_register(parser, -8, "gprs[4]");
verify_register(parser, -8, "gprs[14]");
verify_register(parser, 2, -11);
verify_register(parser, -2, "gprs[13]", 14);
verify_register(parser, -8, "gprs[12]", -32);

verify_register(parser, 4, "gprs[5]");
verify_register(parser, 2, "gprs[11]");
verify_register(parser, -8, -693);
verify_register(parser, -1, "gprs[10]", -23);
verify_register(parser, 4, "gprs[9]", 28);

verify_register(parser, -2, "gprs[3]");
verify_register(parser, -4, "gprs[8]");
verify_register(parser, 2, 1097);
verify_register(parser, 4, "gprs[7]", 108);
verify_register(parser, -2, "gprs[6]", -4);
#elif defined(__x86_64__)
USDT::ArgumentParser_x64 parser(
"-4@$0 8@$1234 %rdi %rax %rsi "
Expand Down

0 comments on commit ba41501

Please sign in to comment.