Commit 0721fa5a authored by Vicent Marti's avatar Vicent Marti

usdt: Use `optional` to properly handle missing args

parent 2a520481
...@@ -17,28 +17,33 @@ ...@@ -17,28 +17,33 @@
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
#include "vendor/optional.hpp"
namespace USDT { namespace USDT {
using std::experimental::optional;
using std::experimental::nullopt;
class ArgumentParser; class ArgumentParser;
class Argument { class Argument {
private: private:
int arg_size_; optional<int> arg_size_;
int constant_; optional<int> constant_;
int deref_offset_; optional<int> deref_offset_;
std::string deref_ident_; optional<std::string> deref_ident_;
std::string register_name_; optional<std::string> register_name_;
public: public:
Argument(); Argument();
~Argument(); ~Argument();
const std::string &deref_ident() const { return deref_ident_; } int arg_size() const { return arg_size_.value_or(sizeof(void *)); }
const std::string &register_name() const { return register_name_; }
int arg_size() const { return arg_size_; } const optional<std::string> &deref_ident() const { return deref_ident_; }
int constant() const { return constant_; } const optional<std::string> &register_name() const { return register_name_; }
int deref_offset() const { return deref_offset_; } const optional<int> constant() const { return constant_; }
const optional<int> deref_offset() const { return deref_offset_; }
friend class ArgumentParser; friend class ArgumentParser;
}; };
...@@ -49,8 +54,8 @@ class ArgumentParser { ...@@ -49,8 +54,8 @@ class ArgumentParser {
protected: protected:
virtual bool validate_register(const std::string &reg, int *reg_size) = 0; virtual bool validate_register(const std::string &reg, int *reg_size) = 0;
ssize_t parse_number(ssize_t pos, int *number); ssize_t parse_number(ssize_t pos, optional<int> *number);
ssize_t parse_identifier(ssize_t pos, std::string *ident); ssize_t parse_identifier(ssize_t pos, optional<std::string> *ident);
ssize_t parse_register(ssize_t pos, Argument *dest); ssize_t parse_register(ssize_t pos, Argument *dest);
ssize_t parse_expr(ssize_t pos, Argument *dest); ssize_t parse_expr(ssize_t pos, Argument *dest);
ssize_t parse_1(ssize_t pos, Argument *dest); ssize_t parse_1(ssize_t pos, Argument *dest);
......
...@@ -13,26 +13,29 @@ ...@@ -13,26 +13,29 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
#include <unordered_map>
#include "usdt.h" #include "usdt.h"
#include <unordered_map>
namespace USDT { namespace USDT {
Argument::Argument() : arg_size_(0), constant_(0), deref_offset_(0) {} Argument::Argument() {}
Argument::~Argument() {} Argument::~Argument() {}
ssize_t ArgumentParser::parse_number(ssize_t pos, int *number) { ssize_t ArgumentParser::parse_number(ssize_t pos, optional<int> *result) {
char *endp; char *endp;
*number = strtol(arg_ + pos, &endp, 0); int number = strtol(arg_ + pos, &endp, 0);
if (endp > arg_ + pos)
*result = number;
return endp - arg_; return endp - arg_;
} }
ssize_t ArgumentParser::parse_identifier(ssize_t pos, std::string *ident) { ssize_t ArgumentParser::parse_identifier(ssize_t pos,
optional<std::string> *result) {
if (isalpha(arg_[pos]) || arg_[pos] == '_') { if (isalpha(arg_[pos]) || arg_[pos] == '_') {
ssize_t start = pos++; ssize_t start = pos++;
while (isalnum(arg_[pos]) || arg_[pos] == '_') pos++; while (isalnum(arg_[pos]) || arg_[pos] == '_') pos++;
ident->assign(arg_ + start, pos - start); if (pos - start)
result->emplace(arg_ + start, pos - start);
} }
return pos; return pos;
} }
...@@ -42,9 +45,17 @@ ssize_t ArgumentParser::parse_register(ssize_t pos, Argument *dest) { ...@@ -42,9 +45,17 @@ ssize_t ArgumentParser::parse_register(ssize_t pos, Argument *dest) {
if (arg_[start] != '%') if (arg_[start] != '%')
return -start; return -start;
while (isalnum(arg_[pos])) pos++; while (isalnum(arg_[pos])) pos++;
dest->register_name_.assign(arg_ + start, pos - start);
if (!validate_register(dest->register_name(), &dest->arg_size_)) std::string regname(arg_ + start, pos - start);
int regsize = 0;
if (!validate_register(regname, &regsize))
return -start; return -start;
dest->register_name_ = regname;
if (!dest->arg_size_)
dest->arg_size_ = regsize;
return pos; return pos;
} }
...@@ -59,10 +70,11 @@ ssize_t ArgumentParser::parse_expr(ssize_t pos, Argument *dest) { ...@@ -59,10 +70,11 @@ ssize_t ArgumentParser::parse_expr(ssize_t pos, Argument *dest) {
pos = parse_number(pos, &dest->deref_offset_); pos = parse_number(pos, &dest->deref_offset_);
if (arg_[pos] == '+') { if (arg_[pos] == '+') {
pos = parse_identifier(pos + 1, &dest->deref_ident_); pos = parse_identifier(pos + 1, &dest->deref_ident_);
if (dest->deref_ident().empty()) if (!dest->deref_ident_)
return -pos; return -pos;
} }
} else { } else {
dest->deref_offset_ = 0;
pos = parse_identifier(pos, &dest->deref_ident_); pos = parse_identifier(pos, &dest->deref_ident_);
} }
...@@ -78,9 +90,9 @@ ssize_t ArgumentParser::parse_expr(ssize_t pos, Argument *dest) { ...@@ -78,9 +90,9 @@ ssize_t ArgumentParser::parse_expr(ssize_t pos, Argument *dest) {
ssize_t ArgumentParser::parse_1(ssize_t pos, Argument *dest) { ssize_t ArgumentParser::parse_1(ssize_t pos, Argument *dest) {
if (isdigit(arg_[pos]) || arg_[pos] == '-') { if (isdigit(arg_[pos]) || arg_[pos] == '-') {
int asize; optional<int> asize;
ssize_t m = parse_number(pos, &asize); ssize_t m = parse_number(pos, &asize);
if (arg_[m] == '@') { if (arg_[m] == '@' && asize) {
dest->arg_size_ = asize; dest->arg_size_ = asize;
return parse_expr(m + 1, dest); return parse_expr(m + 1, dest);
} }
...@@ -132,8 +144,7 @@ bool ArgumentParser_x64::validate_register(const std::string &reg, ...@@ -132,8 +144,7 @@ bool ArgumentParser_x64::validate_register(const std::string &reg,
auto it = registers_.find(reg); auto it = registers_.find(reg);
if (it == registers_.end()) if (it == registers_.end())
return false; return false;
if (*reg_size == 0) *reg_size = it->second;
*reg_size = it->second;
return true; return true;
} }
} }
This diff is collapsed.
...@@ -2,14 +2,30 @@ ...@@ -2,14 +2,30 @@
#include "catch.hpp" #include "catch.hpp"
#include "usdt.h" #include "usdt.h"
using std::experimental::optional;
using std::experimental::nullopt;
static void verify_register(USDT::ArgumentParser_x64 &parser, int arg_size, static void verify_register(USDT::ArgumentParser_x64 &parser, int arg_size,
const std::string &register_name, int constant, int constant) {
int deref_offset, const std::string &deref_ident) {
USDT::Argument arg; USDT::Argument arg;
REQUIRE(parser.parse(&arg)); REQUIRE(parser.parse(&arg));
REQUIRE(arg.arg_size() == arg_size); REQUIRE(arg.arg_size() == arg_size);
REQUIRE(arg.register_name() == register_name);
REQUIRE(arg.constant());
REQUIRE(arg.constant() == constant); REQUIRE(arg.constant() == constant);
}
static void verify_register(USDT::ArgumentParser_x64 &parser, int arg_size,
const std::string &regname,
optional<int> deref_offset = nullopt,
optional<std::string> deref_ident = nullopt) {
USDT::Argument arg;
REQUIRE(parser.parse(&arg));
REQUIRE(arg.arg_size() == arg_size);
REQUIRE(arg.register_name());
REQUIRE(arg.register_name() == regname);
REQUIRE(arg.deref_offset() == deref_offset); REQUIRE(arg.deref_offset() == deref_offset);
REQUIRE(arg.deref_ident() == deref_ident); REQUIRE(arg.deref_ident() == deref_ident);
} }
...@@ -22,17 +38,20 @@ TEST_CASE("test usdt argument parsing", "[usdt]") { ...@@ -22,17 +38,20 @@ TEST_CASE("test usdt argument parsing", "[usdt]") {
"-4@global_max_action(%rip) " "-4@global_max_action(%rip) "
"8@24+mp_(%rip) "); "8@24+mp_(%rip) ");
verify_register(parser, -4, "", 0, 0, ""); verify_register(parser, -4, 0);
verify_register(parser, 8, "", 1234, 0, ""); verify_register(parser, 8, 1234);
verify_register(parser, 8, "%rdi", 0, 0, "");
verify_register(parser, 8, "%rax", 0, 0, ""); verify_register(parser, 8, "%rdi");
verify_register(parser, 8, "%rsi", 0, 0, ""); verify_register(parser, 8, "%rax");
verify_register(parser, -8, "%rbx", 0, 0, ""); verify_register(parser, 8, "%rsi");
verify_register(parser, 4, "%r12", 0, 0, ""); verify_register(parser, -8, "%rbx");
verify_register(parser, 8, "%rbp", 0, -8, ""); verify_register(parser, 4, "%r12");
verify_register(parser, 4, "%rax", 0, 0, "");
verify_register(parser, -4, "%rip", 0, 0, "global_max_action"); verify_register(parser, 8, "%rbp", -8);
verify_register(parser, 8, "%rip", 0, 24, "mp_"); verify_register(parser, 4, "%rax", 0);
verify_register(parser, -4, "%rip", 0, std::string("global_max_action"));
verify_register(parser, 8, "%rip", 24, std::string("mp_"));
REQUIRE(parser.done()); REQUIRE(parser.done());
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment