mirror of
https://github.com/Ed94/raddebugger.git
synced 2026-08-14 17:28:07 +00:00
argument parser for simple STAP arguments
This commit is contained in:
committed by
Ryan Fleury
parent
c4c9ef5182
commit
bda3a71379
@@ -616,6 +616,22 @@ str8_is_integer(String8 string, U32 radix)
|
||||
return result;
|
||||
}
|
||||
|
||||
internal B32
|
||||
str8_is_integer_signed(String8 string, U32 radix)
|
||||
{
|
||||
B32 result = 0;
|
||||
String8 sign = str8_prefix(string, 1);
|
||||
if(str8_match(sign, str8_lit("-"), 0))
|
||||
{
|
||||
result = str8_is_integer(str8_skip(string, 1), radix);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = str8_is_integer(string, radix);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal U64
|
||||
u64_from_str8(String8 string, U32 radix)
|
||||
{
|
||||
|
||||
@@ -233,6 +233,7 @@ internal String8 push_cstr(Arena *arena, String8 str); // TODO(rjf): this is unn
|
||||
//- rjf: string -> integer
|
||||
internal S64 sign_from_str8(String8 string, String8 *string_tail);
|
||||
internal B32 str8_is_integer(String8 string, U32 radix);
|
||||
internal B32 str8_is_integer_signed(String8 string, U32 radix);
|
||||
internal U64 u64_from_str8(String8 string, U32 radix);
|
||||
internal S64 s64_from_str8(String8 string, U32 radix);
|
||||
internal U32 u32_from_str8(String8 string, U32 radix);
|
||||
|
||||
@@ -0,0 +1,364 @@
|
||||
// Copyright (c) Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
internal B32
|
||||
stap_is_scale_valid(U64 scale)
|
||||
{
|
||||
local_persist B8 valid_sizes[9] = { 0, 1, 1, 0, 1, 0, 0, 0, 1 };
|
||||
B32 is_valid = scale < ArrayCount(valid_sizes) && valid_sizes[scale];
|
||||
return is_valid;
|
||||
}
|
||||
|
||||
internal U64
|
||||
stap_parse_digit(U8 *begin, U8 *end, U64 *digit_out)
|
||||
{
|
||||
U8 *ptr = begin;
|
||||
if (ptr < end && *ptr == '-') {
|
||||
ptr += 1;
|
||||
}
|
||||
for (;ptr < end; ptr += 1) {
|
||||
if (!char_is_digit(*ptr, 10)) { break; }
|
||||
}
|
||||
String8 digit_str = str8(begin, (U64)(ptr - begin));
|
||||
if (digit_out) {
|
||||
*digit_out = u64_from_str8(digit_str, 10);
|
||||
}
|
||||
return digit_str.size;
|
||||
}
|
||||
|
||||
internal U64
|
||||
stap_skip_whitespace(U8 *begin, U8 *end)
|
||||
{
|
||||
U8 *ptr = begin;
|
||||
for (; ptr < end && *ptr == ' '; ptr += 1);
|
||||
U64 size = (U64)(ptr - begin);
|
||||
return size;
|
||||
}
|
||||
|
||||
internal U64
|
||||
stap_parse_ident(U8 *begin, U8 *end, String8 *ident_out)
|
||||
{
|
||||
U8 *ptr = begin;
|
||||
for (; ptr < end; ptr += 1) {
|
||||
if (!char_is_alpha(*ptr) && !char_is_digit(*ptr, 10)) { break; }
|
||||
}
|
||||
String8 ident = str8(begin, (U64)(ptr - begin));
|
||||
if (ident_out) { *ident_out = ident; }
|
||||
return ident.size;
|
||||
}
|
||||
|
||||
internal U64
|
||||
stap_size_from_arg(String8 string)
|
||||
{
|
||||
U64 tag_sep = str8_find_needle(string, 0, str8_lit("@"), 0);
|
||||
U64 next_tag_sep = str8_find_needle(string, tag_sep + 1, str8_lit("@"), 0);
|
||||
U64 arg_end = str8_find_needle_reverse(string, next_tag_sep, str8_lit(" "), 0);
|
||||
return arg_end == 0 ? string.size : arg_end;
|
||||
}
|
||||
|
||||
internal String8List
|
||||
stap_list_from_string(Arena *arena, String8 string)
|
||||
{
|
||||
String8List result = {0};
|
||||
for (U64 cursor = 0, arg_size; cursor < string.size; cursor += arg_size) {
|
||||
arg_size = stap_size_from_arg(str8_skip(string, cursor));
|
||||
String8 arg = str8_substr(string, r1u64(cursor, cursor + arg_size));
|
||||
str8_list_push(arena, &result, arg);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
internal String8
|
||||
stap_parse_args_x64(String8 string, STAP_Arg *arg_out)
|
||||
{
|
||||
String8 error = str8_lit("unknown parse error");
|
||||
U64 sep_pos = str8_find_needle(string, 0, str8_lit("@"), 0);
|
||||
if (sep_pos < string.size) {
|
||||
STAP_Arg arg = {0};
|
||||
|
||||
String8 tag = str8_prefix(string, sep_pos + 1);
|
||||
String8 oper = str8_skip(string, tag.size);
|
||||
|
||||
STAP_ArgValueType arg_value_type = STAP_ArgValueType_Null;
|
||||
U64 arg_value_size = 0;
|
||||
B32 infer_arg_value_size = 1;
|
||||
U64 tag_size = 0;
|
||||
{
|
||||
U8 *ptr = tag.str, *end = tag.str + tag.size;
|
||||
|
||||
// is signed?
|
||||
if (ptr >= end) { goto operand_parse_exit; }
|
||||
if (*ptr == '-') {
|
||||
arg_value_type = STAP_ArgValueType_S;
|
||||
ptr += 1;
|
||||
}
|
||||
|
||||
// parse optional size
|
||||
if (ptr >= end) { goto operand_parse_exit; }
|
||||
if (char_is_digit(*ptr, 10)) {
|
||||
arg_value_size = *ptr - '0';
|
||||
if (!stap_is_scale_valid(arg_value_size)) {
|
||||
error = str8_lit("invalid operand size");
|
||||
goto operand_parse_exit;
|
||||
}
|
||||
ptr += 1;
|
||||
infer_arg_value_size = 0;
|
||||
}
|
||||
|
||||
// is this float?
|
||||
if (ptr >= end) { goto operand_parse_exit; }
|
||||
if (*ptr == 'f') {
|
||||
if (arg_value_type != STAP_ArgValueType_Null) {
|
||||
error = str8_lit("illegal combination of modifiers '-' and 'f'");
|
||||
goto operand_parse_exit;
|
||||
}
|
||||
ptr += 1;
|
||||
arg_value_type = STAP_ArgValueType_F;
|
||||
}
|
||||
|
||||
// assume default value type to be unsigned
|
||||
if (arg_value_type == STAP_ArgValueType_Null) {
|
||||
arg_value_type = STAP_ArgValueType_U;
|
||||
}
|
||||
|
||||
if (ptr >= end) { goto operand_parse_exit; }
|
||||
if (*ptr != '@') {
|
||||
error = str8_lit("failed to find @");
|
||||
goto operand_parse_exit;
|
||||
}
|
||||
ptr += 1;
|
||||
|
||||
tag_size = (U64)(ptr - tag.str);
|
||||
}
|
||||
|
||||
U64 memory_ref_start = str8_find_needle_reverse(oper, 0, str8_lit("("), 0);
|
||||
// memory operand
|
||||
if (memory_ref_start > 0 && memory_ref_start < oper.size) {
|
||||
//
|
||||
// Expected syntax for memory operand: { [Disp] (Base [',' Index [',' Scale]]) } | { $IMM } | { %reg }
|
||||
//
|
||||
// Disp: { [+|-]Digits } | { Expr }
|
||||
// Base: %reg
|
||||
// Index: %reg
|
||||
// Scale: 1|2|4|8
|
||||
// Expr: A small C-like infix expression
|
||||
//
|
||||
|
||||
// find closing ')'
|
||||
U64 memory_ref_end = str8_find_needle(oper, memory_ref_start+1, str8_lit(")"), 0);
|
||||
if (memory_ref_end > oper.size) {
|
||||
error = str8_lit("missing closing ')'");
|
||||
goto operand_parse_exit;
|
||||
}
|
||||
if (memory_ref_end >= oper.size) {
|
||||
error = str8_lit("expression does not terminate after ')'");
|
||||
goto operand_parse_exit;
|
||||
}
|
||||
|
||||
// parse displacement
|
||||
String8 disp_str = str8_skip_chop_whitespace(str8_prefix(oper, memory_ref_start-1));
|
||||
if (disp_str.size > 0 && !str8_is_integer_signed(disp_str, 10)) {
|
||||
error = str8_lit("displacement is too complicated, only integral displacement is supported");
|
||||
goto operand_parse_exit;
|
||||
}
|
||||
S64 disp = s64_from_str8(disp_str, 10);
|
||||
|
||||
// parse base, index, scale
|
||||
String8 base_index_scale = str8_skip_chop_whitespace(str8_substr(oper, r1u64(memory_ref_start, memory_ref_end)));
|
||||
U64 first_comma = str8_find_needle(base_index_scale, 0, str8_lit(","), 0);
|
||||
U64 second_comma = str8_find_needle(base_index_scale, first_comma+1, str8_lit(","), 0);
|
||||
String8 base_str = str8_skip_chop_whitespace(str8_substr(base_index_scale, r1u64(0, first_comma)));
|
||||
String8 index_str = str8_skip_chop_whitespace(str8_substr(base_index_scale, r1u64(first_comma + 1, second_comma)));
|
||||
String8 scale_str = str8_skip_chop_whitespace(str8_substr(base_index_scale, r1u64(second_comma + 1, memory_ref_end)));
|
||||
|
||||
// syntax check
|
||||
if(first_comma >= base_index_scale.size && base_str.size == 0) {
|
||||
error = str8_lit("missing base register");
|
||||
goto operand_parse_exit;
|
||||
}
|
||||
if (first_comma < base_index_scale.size && index_str.size == 0) {
|
||||
error = str8_lit("missing index register");
|
||||
goto operand_parse_exit;
|
||||
}
|
||||
if (second_comma < base_index_scale.size && scale_str.size == 0) {
|
||||
error = str8_lit("missing scale");
|
||||
goto operand_parse_exit;
|
||||
}
|
||||
if (base_str.size > 0 && !str8_match(str8_lit("%"), base_str, StringMatchFlag_RightSideSloppy)) {
|
||||
error = str8_lit("invalid base register");
|
||||
goto operand_parse_exit;
|
||||
}
|
||||
if (first_comma < base_index_scale.size && (index_str.size < 2 || !str8_match(str8_lit("%"), index_str, StringMatchFlag_RightSideSloppy))) {
|
||||
error = str8_lit("invalid index register");
|
||||
goto operand_parse_exit;
|
||||
}
|
||||
if (second_comma < base_index_scale.size && (scale_str.size > 0 && !str8_is_integer(scale_str, 10))) {
|
||||
error = str8_lit("invalid of scale (expected unsigned integral type)");
|
||||
goto operand_parse_exit;
|
||||
}
|
||||
|
||||
// stip '%' prefix
|
||||
base_str = str8_skip(base_str, 1);
|
||||
index_str = str8_skip(index_str, 1);
|
||||
|
||||
// parse base
|
||||
B8 base_is_alias = 0;
|
||||
U32 base_reg_code = 0;
|
||||
if (base_str.size) {
|
||||
base_reg_code = regs_reg_code_from_name(Arch_x64, base_str);
|
||||
if (base_reg_code == 0) {
|
||||
base_reg_code = regs_alias_code_from_name(Arch_x64, base_str);
|
||||
base_is_alias = base_reg_code != 0;
|
||||
}
|
||||
if (base_reg_code == 0) {
|
||||
error = str8_lit("unknown base register");
|
||||
goto operand_parse_exit;
|
||||
}
|
||||
}
|
||||
|
||||
// parse index
|
||||
B8 index_is_alias = 0;
|
||||
U32 index_reg_code = 0;
|
||||
if (index_str.size) {
|
||||
index_reg_code = regs_reg_code_from_name(Arch_x64, index_str);
|
||||
if (index_reg_code == 0) {
|
||||
index_reg_code = regs_alias_code_from_name(Arch_x64, index_str);
|
||||
index_is_alias = index_reg_code != 0;
|
||||
}
|
||||
if (index_reg_code == 0) {
|
||||
error = str8_lit("unknown index register");
|
||||
}
|
||||
}
|
||||
|
||||
// parse scale
|
||||
U64 scale = 1;
|
||||
if (scale_str.size) {
|
||||
scale = u64_from_str8(scale_str, 10);
|
||||
if (!stap_is_scale_valid(scale)) {
|
||||
error = str8_lit("invalid scale value (expected 1/2/4/8)");
|
||||
goto operand_parse_exit;
|
||||
}
|
||||
}
|
||||
|
||||
if (infer_arg_value_size) {
|
||||
error = str8_lit("memory operands must have a sice");
|
||||
goto operand_parse_exit;
|
||||
}
|
||||
|
||||
// fill out memory ref portion
|
||||
arg.type = STAP_ArgType_MemoryRef;
|
||||
arg.memory_ref.disp = disp;
|
||||
arg.memory_ref.base.reg_code = base_reg_code;
|
||||
arg.memory_ref.base.is_alias = base_is_alias;
|
||||
arg.memory_ref.index.reg_code = index_reg_code;
|
||||
arg.memory_ref.index.is_alias = index_is_alias;
|
||||
arg.memory_ref.scale = scale;
|
||||
}
|
||||
// $imm
|
||||
else if (str8_match(str8_lit("$"), oper, StringMatchFlag_RightSideSloppy)) {
|
||||
String8 imm_str = str8_skip(oper, 1);
|
||||
|
||||
U64 imm_size = str8_find_needle(imm_str, 0, str8_lit(" "), 0);
|
||||
if (imm_size > imm_str.size ) {
|
||||
imm_size = imm_str.size;
|
||||
}
|
||||
imm_str = str8_prefix(imm_str, imm_size);
|
||||
|
||||
if (imm_str.size == 0) {
|
||||
goto operand_parse_exit;
|
||||
}
|
||||
|
||||
U64 imm = 0;
|
||||
B32 is_parsed = 0;
|
||||
switch (arg_value_type) {
|
||||
case STAP_ArgValueType_Null:
|
||||
case STAP_ArgValueType_U:
|
||||
case STAP_ArgValueType_F: {
|
||||
is_parsed = try_u64_from_str8_c_rules(imm_str, &imm);
|
||||
} break;
|
||||
case STAP_ArgValueType_S: {
|
||||
is_parsed = try_s64_from_str8_c_rules(imm_str, (S64 *)&imm);
|
||||
} break;
|
||||
default: { InvalidPath; } break;
|
||||
}
|
||||
|
||||
if (!is_parsed) {
|
||||
error = str8_lit("failed to parse immediate");
|
||||
goto operand_parse_exit;
|
||||
}
|
||||
|
||||
arg.type = STAP_ArgType_Imm;
|
||||
arg.imm = imm;
|
||||
}
|
||||
// %reg
|
||||
else if (str8_match(str8_lit("%"), oper, StringMatchFlag_RightSideSloppy)) {
|
||||
// skip %
|
||||
String8 reg_str = str8_skip(oper, 1);
|
||||
if (reg_str.size == 0) {
|
||||
goto operand_parse_exit;
|
||||
}
|
||||
|
||||
B8 is_reg_alias = 0;
|
||||
U32 reg_code = regs_reg_code_from_name(Arch_x64, reg_str);
|
||||
if (reg_code == 0) {
|
||||
reg_code = regs_alias_code_from_name(Arch_x64, reg_str);
|
||||
is_reg_alias = reg_code != 0;
|
||||
}
|
||||
if (reg_code == 0) {
|
||||
error = str8_lit("invalid register name");
|
||||
goto operand_parse_exit;
|
||||
}
|
||||
|
||||
arg.type = STAP_ArgType_Reg;
|
||||
arg.reg.is_alias = is_reg_alias;
|
||||
arg.reg.reg_code = reg_code;
|
||||
} else {
|
||||
goto operand_parse_exit;
|
||||
}
|
||||
|
||||
// fill out value portion
|
||||
arg.value_type = arg_value_type == STAP_ArgValueType_Null ? STAP_ArgValueType_U : arg_value_type;
|
||||
arg.value_size = arg_value_size;
|
||||
|
||||
// write output
|
||||
if (arg_out) {
|
||||
*arg_out = arg;
|
||||
}
|
||||
|
||||
// clear error tracker
|
||||
error = str8_zero();
|
||||
|
||||
operand_parse_exit:;
|
||||
} else {
|
||||
error = str8_lit("invalid argument string");
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
internal STAP_ArgArray
|
||||
stap_arg_array_from_string(Arena *arena, Arch arch, String8 string)
|
||||
{
|
||||
Temp scratch = scratch_begin(&arena, 1);
|
||||
String8List arg_strings = stap_list_from_string(scratch.arena, string);
|
||||
STAP_ArgArray result = {0};
|
||||
result.v = push_array(arena, STAP_Arg, arg_strings.node_count);
|
||||
for EachNode(n, String8Node, arg_strings.first) {
|
||||
STAP_Arg *arg = &result.v[result.count++];
|
||||
|
||||
switch (arch) {
|
||||
case Arch_Null: {} break;
|
||||
case Arch_x64: {
|
||||
stap_parse_args_x64(n->string, arg);
|
||||
} break;
|
||||
case Arch_x86:
|
||||
case Arch_arm32:
|
||||
case Arch_arm64: { NotImplemented; } break;
|
||||
default: { InvalidPath; } break;
|
||||
}
|
||||
}
|
||||
scratch_end(scratch);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
// Copyright (c) Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#ifndef STAP_PARSE_H
|
||||
#define STAP_PARSE_H
|
||||
|
||||
typedef enum STAP_ArgType
|
||||
{
|
||||
STAP_ArgType_Null,
|
||||
STAP_ArgType_Imm,
|
||||
STAP_ArgType_Reg,
|
||||
STAP_ArgType_MemoryRef,
|
||||
} STAP_ArgType;
|
||||
|
||||
typedef enum STAP_ArgValueType
|
||||
{
|
||||
STAP_ArgValueType_Null,
|
||||
STAP_ArgValueType_U,
|
||||
STAP_ArgValueType_S,
|
||||
STAP_ArgValueType_F,
|
||||
} STAP_ArgValueType;
|
||||
|
||||
typedef struct STAP_Arg
|
||||
{
|
||||
STAP_ArgValueType value_type;
|
||||
U64 value_size;
|
||||
STAP_ArgType type;
|
||||
union {
|
||||
U64 imm;
|
||||
struct {
|
||||
U32 reg_code;
|
||||
B8 is_alias;
|
||||
} reg;
|
||||
struct {
|
||||
S64 disp;
|
||||
struct {
|
||||
U32 reg_code;
|
||||
B8 is_alias;
|
||||
} base;
|
||||
struct {
|
||||
U32 reg_code;
|
||||
B8 is_alias;
|
||||
} index;
|
||||
U64 scale;
|
||||
} memory_ref;
|
||||
};
|
||||
} STAP_Arg;
|
||||
|
||||
typedef struct STAP_ArgArray
|
||||
{
|
||||
U64 count;
|
||||
STAP_Arg *v;
|
||||
} STAP_ArgArray;
|
||||
|
||||
typedef struct STAP_ArgValue
|
||||
{
|
||||
STAP_ArgValueType value_type;
|
||||
U8 value_size;
|
||||
void *raw_ptr;
|
||||
} STAP_ArgValue;
|
||||
|
||||
typedef struct STAP_ArgValueArray
|
||||
{
|
||||
U64 count;
|
||||
STAP_ArgValue *v;
|
||||
} STAP_ArgValueArray;
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
internal String8 stap_parse_args_x64(String8 string, STAP_Arg *arg_out);
|
||||
internal STAP_ArgArray stap_arg_array_from_string(Arena *arena, Arch arch, String8 string);
|
||||
|
||||
#endif // STAP_PARSE_H
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
// Copyright (c) Epic Games Tools
|
||||
// Licensed under the MIT license (https://opensource.org/license/mit/)
|
||||
|
||||
#define BUILD_TITLE "STAP Parser Test"
|
||||
#define BUILD_CONSOLE_INTERFACE 1
|
||||
|
||||
#include "base/base_inc.h"
|
||||
#include "os/os_inc.h"
|
||||
#include "regs/regs.h"
|
||||
#include "stap/stap_parse.h"
|
||||
|
||||
#include "base/base_inc.c"
|
||||
#include "os/os_inc.c"
|
||||
#include "regs/regs.c"
|
||||
#include "stap/stap_parse.c"
|
||||
|
||||
internal void
|
||||
entry_point(CmdLine *cmd_line)
|
||||
{
|
||||
B32 passed = 0;
|
||||
STAP_Arg arg = {0};
|
||||
String8 error = {0};
|
||||
String8 string = {0};
|
||||
|
||||
string = str8_lit("-2@$-123");
|
||||
error = stap_parse_args_x64(string, &arg);
|
||||
if (error.size != 0) { goto exit; }
|
||||
AssertAlways(arg.value_type == STAP_ArgValueType_S);
|
||||
AssertAlways(arg.value_size == 2);
|
||||
AssertAlways(arg.type == STAP_ArgType_Imm);
|
||||
AssertAlways((S64)arg.imm == -123);
|
||||
|
||||
string = str8_lit("1@$43");
|
||||
error = stap_parse_args_x64(string, &arg);
|
||||
if (error.size != 0) { goto exit; }
|
||||
AssertAlways(arg.value_type == STAP_ArgValueType_U);
|
||||
AssertAlways(arg.value_size == 1);
|
||||
AssertAlways(arg.type == STAP_ArgType_Imm);
|
||||
AssertAlways((S64)arg.imm == 43);
|
||||
|
||||
string = str8_lit("4f@%eax");
|
||||
error = stap_parse_args_x64(string, &arg);
|
||||
if (error.size != 0) { goto exit; }
|
||||
AssertAlways(arg.value_type == STAP_ArgValueType_F);
|
||||
AssertAlways(arg.value_size == 4);
|
||||
AssertAlways(arg.type == STAP_ArgType_Reg);
|
||||
AssertAlways(arg.reg.is_alias == 1);
|
||||
AssertAlways(arg.reg.reg_code == REGS_AliasCodeX64_eax);
|
||||
|
||||
string = str8_lit("4@(%rdi)");
|
||||
error = stap_parse_args_x64(string, &arg);
|
||||
if (error.size != 0) { goto exit; }
|
||||
AssertAlways(arg.value_size == 4);
|
||||
AssertAlways(arg.value_type == STAP_ArgValueType_U);
|
||||
AssertAlways(arg.type == STAP_ArgType_MemoryRef);
|
||||
AssertAlways(arg.memory_ref.disp == 0);
|
||||
AssertAlways(arg.memory_ref.base.reg_code == REGS_RegCodeX64_rdi);
|
||||
AssertAlways(!arg.memory_ref.base.is_alias);
|
||||
AssertAlways(arg.memory_ref.index.reg_code == 0);
|
||||
AssertAlways(arg.memory_ref.index.is_alias == 0);
|
||||
AssertAlways(arg.memory_ref.scale == 1);
|
||||
|
||||
string = str8_lit("4@-22(%rdi)");
|
||||
error = stap_parse_args_x64(string, &arg);
|
||||
if (error.size != 0) { goto exit; }
|
||||
AssertAlways(arg.value_size == 4);
|
||||
AssertAlways(arg.value_type == STAP_ArgValueType_U);
|
||||
AssertAlways(arg.type == STAP_ArgType_MemoryRef);
|
||||
AssertAlways(arg.memory_ref.disp == -22);
|
||||
AssertAlways(arg.memory_ref.base.reg_code == REGS_RegCodeX64_rdi);
|
||||
AssertAlways(!arg.memory_ref.base.is_alias);
|
||||
AssertAlways(arg.memory_ref.index.reg_code == 0);
|
||||
AssertAlways(arg.memory_ref.index.is_alias == 0);
|
||||
AssertAlways(arg.memory_ref.scale == 1);
|
||||
|
||||
string = str8_lit("4@32(%rax,%rsi,8)");
|
||||
error = stap_parse_args_x64(string, &arg);
|
||||
if (error.size != 0) { goto exit; }
|
||||
AssertAlways(arg.value_size == 4);
|
||||
AssertAlways(arg.value_type == STAP_ArgValueType_U);
|
||||
AssertAlways(arg.memory_ref.disp == 32);
|
||||
AssertAlways(arg.memory_ref.base.reg_code == REGS_RegCodeX64_rax);
|
||||
AssertAlways(arg.memory_ref.base.is_alias == 0);
|
||||
AssertAlways(arg.memory_ref.index.reg_code == REGS_RegCodeX64_rsi);
|
||||
AssertAlways(arg.memory_ref.index.is_alias == 0);
|
||||
AssertAlways(arg.memory_ref.scale == 8);
|
||||
|
||||
string = str8_lit("4@32(,%rsi,8)");
|
||||
error = stap_parse_args_x64(string, &arg);
|
||||
if (error.size != 0) { goto exit; }
|
||||
AssertAlways(arg.value_size == 4);
|
||||
AssertAlways(arg.value_type == STAP_ArgValueType_U);
|
||||
AssertAlways(arg.memory_ref.disp == 32);
|
||||
AssertAlways(arg.memory_ref.base.reg_code == 0);
|
||||
AssertAlways(arg.memory_ref.index.reg_code == REGS_RegCodeX64_rsi);
|
||||
AssertAlways(arg.memory_ref.scale == 8);
|
||||
|
||||
error = stap_parse_args_x64(str8_lit("4@(,,)"), &arg);
|
||||
if (error.size == 0) { goto exit; }
|
||||
|
||||
error = stap_parse_args_x64(str8_lit("4@()"), &arg);
|
||||
if (error.size == 0) { goto exit; }
|
||||
|
||||
error = stap_parse_args_x64(str8_lit("4@(%rdi, %rsi, 8"), &arg);
|
||||
if (error.size == 0) { goto exit; }
|
||||
|
||||
error = stap_parse_args_x64(str8_lit("4@( ,, 8"), &arg);
|
||||
if (error.size == 0) { goto exit; }
|
||||
|
||||
passed = 1;
|
||||
exit:;
|
||||
AssertAlways(passed);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user