diff --git a/src/regs/regs.c b/src/regs/regs.c index f55d133a..2127200d 100644 --- a/src/regs/regs.c +++ b/src/regs/regs.c @@ -9,6 +9,54 @@ //////////////////////////////// //~ rjf: Helpers +internal REGS_RegCode +regs_reg_code_from_name(Arch arch, String8 name) +{ + String8 *name_table = regs_reg_code_string_table_from_arch(arch); + U64 name_count = regs_reg_code_count_from_arch(arch); + for EachIndex(i, name_count) + { + if(str8_match(name_table[i], name, StringMatchFlag_CaseInsensitive)) + { + return (REGS_RegCode)i; + } + } + return 0; +} + +internal REGS_AliasCode +regs_alias_code_from_name(Arch arch, String8 name) +{ + String8 *alias_table = regs_alias_code_string_table_from_arch(arch); + U64 alias_count = regs_alias_code_count_from_arch(arch); + for EachIndex(i, alias_count) + { + if(str8_match(alias_table[i], name, StringMatchFlag_CaseInsensitive)) + { + return (REGS_RegCode)i; + } + } + return 0; +} + +internal Rng1U64 +regs_range_from_code(Arch arch, B32 is_alias, U64 reg_code) +{ + Rng1U64 range = {0}; + if(is_alias) + { + REGS_Slice slice = regs_alias_code_slice_table_from_arch(arch)[reg_code]; + REGS_Rng rng = regs_reg_code_rng_table_from_arch(arch)[reg_code]; + range = r1u64(rng.byte_off + slice.byte_off, rng.byte_off + slice.byte_off + slice.byte_size); + } + else + { + REGS_Rng rng = regs_reg_code_rng_table_from_arch(arch)[reg_code]; + range = r1u64(rng.byte_off, rng.byte_off + rng.byte_size); + } + return range; +} + internal U64 regs_rip_from_arch_block(Arch arch, void *block) { diff --git a/src/regs/regs.h b/src/regs/regs.h index 4d781fc9..27c1efcd 100644 --- a/src/regs/regs.h +++ b/src/regs/regs.h @@ -108,6 +108,9 @@ struct REGS_Slice //////////////////////////////// //~ rjf: Helpers +internal REGS_RegCode regs_reg_code_from_name(Arch arch, String8 name); +internal REGS_AliasCode regs_alias_code_from_name(Arch arch, String8 name); +internal Rng1U64 regs_range_from_code(Arch arch, B32 is_alias, U64 reg_code); internal U64 regs_block_size_from_arch(Arch arch); internal U64 regs_reg_code_count_from_arch(Arch arch); internal U64 regs_alias_code_count_from_arch(Arch arch); diff --git a/src/stap/stap_parse.c b/src/stap/stap_parse.c index 932b47d0..ae9302b0 100644 --- a/src/stap/stap_parse.c +++ b/src/stap/stap_parse.c @@ -4,9 +4,7 @@ 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; + return IsPow2(scale) && scale <= 8; } internal U64 @@ -52,7 +50,7 @@ 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); + U64 arg_end = str8_find_needle_reverse(string, string.size - next_tag_sep, str8_lit(" "), 0); return arg_end == 0 ? string.size : arg_end; } @@ -292,8 +290,8 @@ stap_parse_args_x64(String8 string, STAP_Arg *arg_out) } // %reg else if (str8_match(str8_lit("%"), oper, StringMatchFlag_RightSideSloppy)) { - // skip % - String8 reg_str = str8_skip(oper, 1); + // skip % and strip white space + String8 reg_str = str8_skip_chop_whitespace(str8_skip(oper, 1)); if (reg_str.size == 0) { goto operand_parse_exit; } @@ -361,4 +359,80 @@ stap_arg_array_from_string(Arena *arena, Arch arch, String8 string) return result; } +internal B32 +stap_read_arg(STAP_Arg arg, + Arch arch, + void *reg_block, + STAP_MemoryRead *memory_read, + void *memory_read_ctx, + void *raw_value) +{ + AssertAlways(arg.value_size <= 8); + + B32 is_value_read = 0; + + switch (arg.type) { + case STAP_ArgType_Null: break; + case STAP_ArgType_Imm: { + MemoryCopy(raw_value, &arg.imm, arg.value_size); + is_value_read = 1; + } break; + case STAP_ArgType_Reg: { + Rng1U64 range = regs_range_from_code(arch, arg.reg.is_alias, arg.reg.reg_code); + U64 copy_size = Min(arg.value_size, dim_1u64(range)); + MemoryCopy(raw_value, (U8 *)reg_block + range.min, copy_size); + is_value_read = 1; + } break; + case STAP_ArgType_MemoryRef: { + U64 base = 0; + if(arg.memory_ref.base.reg_code) { + Rng1U64 range = regs_range_from_code(arch, arg.memory_ref.base.is_alias, arg.memory_ref.base.reg_code); + U64 copy_size = Min(sizeof(base), dim_1u64(range)); + MemoryCopy(&base, (U8 *)reg_block + range.min, copy_size); + } + + U64 index = 0; + if(arg.memory_ref.index.reg_code) { + Rng1U64 range = regs_range_from_code(arch, arg.memory_ref.index.is_alias, arg.memory_ref.index.reg_code); + U64 copy_size = Min(sizeof(base), dim_1u64(range)); + MemoryCopy(&index, (U8 *)reg_block + range.min, copy_size); + } + + U64 addr = arg.memory_ref.disp + (base + index * arg.memory_ref.scale); + if (memory_read(addr, raw_value, arg.value_size, memory_read_ctx)) { + is_value_read = 1; + } + } break; + default: { InvalidPath; } break; + } + + if (arg.value_size < 8) { + if (arg.value_type == STAP_ArgValueType_S) { + *(U64 *)raw_value = extend_sign64(*(U64 *)raw_value, arg.value_size); + } else if (arg.value_type == STAP_ArgValueType_F) { + Assert(arg.value_size == 4); + *(F64 *)raw_value = *(F32 *)raw_value; + } + } + + return is_value_read; +} + +internal B32 +stap_read_arg_u(STAP_Arg arg, Arch arch, void *reg_block, STAP_MemoryRead *memory_read, void *memory_read_ctx, U64 *u_out) +{ + return stap_read_arg(arg, arch, reg_block, memory_read, memory_read_ctx, u_out); +} + +internal B32 +stap_read_arg_s(STAP_Arg arg, Arch arch, void *reg_block, STAP_MemoryRead *memory_read, void *memory_read_ctx, S64 *s_out) +{ + return stap_read_arg(arg, arch, reg_block, memory_read, memory_read_ctx, s_out); +} + +internal B32 +stap_read_arg_f(STAP_Arg arg, Arch arch, void *reg_block, STAP_MemoryRead *memory_read, void *memory_read_ctx, F64 *f_out) +{ + return stap_read_arg(arg, arch, reg_block, memory_read, memory_read_ctx, f_out); +} diff --git a/src/stap/stap_parse.h b/src/stap/stap_parse.h index 74897711..43101a36 100644 --- a/src/stap/stap_parse.h +++ b/src/stap/stap_parse.h @@ -65,10 +65,18 @@ typedef struct STAP_ArgValueArray STAP_ArgValue *v; } STAP_ArgValueArray; +#define STAP_MEMORY_READ(name) B32 name(U64 addr, void *buffer, U64 read_size, void *raw_ctx) +typedef STAP_MEMORY_READ(STAP_MemoryRead); + //////////////////////////////// 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); +internal B32 stap_read_arg(STAP_Arg arg, Arch arch, void *reg_block, STAP_MemoryRead *memory_read, void *memory_read_ctx, void *raw_value); +internal B32 stap_read_arg_u(STAP_Arg arg, Arch arch, void *reg_block, STAP_MemoryRead *memory_read, void *memory_read_ctx, U64 *u_out); +internal B32 stap_read_arg_s(STAP_Arg arg, Arch arch, void *reg_block, STAP_MemoryRead *memory_read, void *memory_read_ctx, S64 *s_out); +internal B32 stap_read_arg_f(STAP_Arg arg, Arch arch, void *reg_block, STAP_MemoryRead *memory_read, void *memory_read_ctx, F64 *f_out); + #endif // STAP_PARSE_H