1 /* 2 * Copyright (c) 2016 GitHub, Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 #include <iostream> 17 #include <string> 18 19 #include "catch.hpp" 20 #include "usdt.h" 21 22 using std::experimental::optional; 23 using std::experimental::nullopt; 24 25 static void verify_register(USDT::ArgumentParser &parser, int arg_size, 26 int constant) { 27 USDT::Argument arg; 28 REQUIRE(parser.parse(&arg)); 29 REQUIRE(arg.arg_size() == arg_size); 30 31 REQUIRE(arg.constant()); 32 REQUIRE(arg.constant() == constant); 33 } 34 35 static void verify_register(USDT::ArgumentParser &parser, int arg_size, 36 const std::string ®name, 37 optional<int> deref_offset = nullopt, 38 optional<std::string> deref_ident = nullopt, 39 optional<std::string> index_regname = nullopt, 40 optional<int> scale = nullopt) { 41 USDT::Argument arg; 42 REQUIRE(parser.parse(&arg)); 43 REQUIRE(arg.arg_size() == arg_size); 44 45 REQUIRE(arg.base_register_name()); 46 REQUIRE(arg.base_register_name() == regname); 47 48 REQUIRE(arg.deref_offset() == deref_offset); 49 REQUIRE(arg.deref_ident() == deref_ident); 50 51 REQUIRE(arg.index_register_name() == index_regname); 52 REQUIRE(arg.scale() == scale); 53 } 54 55 TEST_CASE("test usdt argument parsing", "[usdt]") { 56 SECTION("parse failure") { 57 #ifdef __aarch64__ 58 USDT::ArgumentParser_aarch64 parser("4@[x32,200]"); 59 #elif __powerpc64__ 60 USDT::ArgumentParser_powerpc64 parser("4@-12(42)"); 61 #elif defined(__x86_64__) 62 USDT::ArgumentParser_x64 parser("4@i%ra+1r"); 63 #endif 64 USDT::Argument arg; 65 REQUIRE(!parser.parse(&arg)); 66 int i; 67 for (i = 0; i < 10 && !parser.done(); ++i) { 68 parser.parse(&arg); 69 } 70 // Make sure we reach termination 71 REQUIRE(i < 10); 72 } 73 SECTION("argument examples from the Python implementation") { 74 #ifdef __aarch64__ 75 USDT::ArgumentParser_aarch64 parser("-1@x0 4@5 8@[x12] -4@[x31,-40]"); 76 verify_register(parser, -1, "regs[0]"); 77 verify_register(parser, 4, 5); 78 verify_register(parser, 8, "regs[12]", 0); 79 verify_register(parser, -4, "regs[31]", -40); 80 #elif __powerpc64__ 81 USDT::ArgumentParser_powerpc64 parser( 82 "-4@0 8@%r0 8@i0 4@0(%r0) -2@0(0) " 83 "1@0 -2@%r3 -8@i9 -1@0(%r4) -4@16(6) " 84 "2@7 4@%r11 4@i-67 8@-16(%r17) 1@-52(11) " 85 "-8@13 -8@%r25 2@i-11 -2@14(%r26) -8@-32(24) " 86 "4@29 2@%r17 -8@i-693 -1@-23(%r31) 4@28(30) " 87 "-2@31 -4@%r30 2@i1097 4@108(%r30) -2@-4(31)"); 88 89 verify_register(parser, -4, "gpr[0]"); 90 verify_register(parser, 8, "gpr[0]"); 91 verify_register(parser, 8, 0); 92 verify_register(parser, 4, "gpr[0]", 0); 93 verify_register(parser, -2, "gpr[0]", 0); 94 95 verify_register(parser, 1, "gpr[0]"); 96 verify_register(parser, -2, "gpr[3]"); 97 verify_register(parser, -8, 9); 98 verify_register(parser, -1, "gpr[4]", 0); 99 verify_register(parser, -4, "gpr[6]", 16); 100 101 verify_register(parser, 2, "gpr[7]"); 102 verify_register(parser, 4, "gpr[11]"); 103 verify_register(parser, 4, -67); 104 verify_register(parser, 8, "gpr[17]", -16); 105 verify_register(parser, 1, "gpr[11]", -52); 106 107 verify_register(parser, -8, "gpr[13]"); 108 verify_register(parser, -8, "gpr[25]"); 109 verify_register(parser, 2, -11); 110 verify_register(parser, -2, "gpr[26]", 14); 111 verify_register(parser, -8, "gpr[24]", -32); 112 113 verify_register(parser, 4, "gpr[29]"); 114 verify_register(parser, 2, "gpr[17]"); 115 verify_register(parser, -8, -693); 116 verify_register(parser, -1, "gpr[31]", -23); 117 verify_register(parser, 4, "gpr[30]", 28); 118 119 verify_register(parser, -2, "gpr[31]"); 120 verify_register(parser, -4, "gpr[30]"); 121 verify_register(parser, 2, 1097); 122 verify_register(parser, 4, "gpr[30]", 108); 123 verify_register(parser, -2, "gpr[31]", -4); 124 #elif defined(__x86_64__) 125 USDT::ArgumentParser_x64 parser( 126 "-4@$0 8@$1234 %rdi %rax %rsi " 127 "-8@%rbx 4@%r12 8@-8(%rbp) 4@(%rax) " 128 "-4@global_max_action(%rip) " 129 "8@24+mp_(%rip) " 130 "-4@CheckpointStats+40(%rip) " 131 "4@glob-2(%rip) " 132 "8@(%rax,%rdx,8) " 133 "4@(%rbx,%rcx)"); 134 135 verify_register(parser, -4, 0); 136 verify_register(parser, 8, 1234); 137 138 verify_register(parser, 8, "di"); 139 verify_register(parser, 8, "ax"); 140 verify_register(parser, 8, "si"); 141 verify_register(parser, -8, "bx"); 142 verify_register(parser, 4, "r12"); 143 144 verify_register(parser, 8, "bp", -8); 145 verify_register(parser, 4, "ax", 0); 146 147 verify_register(parser, -4, "ip", 0, std::string("global_max_action")); 148 verify_register(parser, 8, "ip", 24, std::string("mp_")); 149 verify_register(parser, -4, "ip", 40, std::string("CheckpointStats")); 150 verify_register(parser, 4, "ip", -2, std::string("glob")); 151 152 verify_register(parser, 8, "ax", 0, nullopt, std::string("dx"), 8); 153 verify_register(parser, 4, "bx", 0, nullopt, std::string("cx")); 154 #endif 155 156 REQUIRE(parser.done()); 157 } 158 } 159