Compare commits

..
5 Commits
9 changed files with 336 additions and 397 deletions

No files matched your search

-339
View File
@@ -1,339 +0,0 @@
add=binary add of two registers (numeric or string concatenation)
add_empty_string=convert a value to string by concatenating with the empty string
add_n=numeric add (operands known to be numeric)
add_own_private_by_sym=add a private own property using a symbol key
add_s=string add (operands known to be strings)
add32=32-bit integer add
async_break_check=check if execution should break asynchronously
bit_and=bitwise AND of two registers
bit_not=bitwise NOT of a register
bit_or=bitwise OR of two registers
bit_xor=bitwise XOR of two registers
call=call a function with a given number of arguments
call_builtin=call a builtin function by id
call_builtin_long=call a builtin function by id (long form)
call_direct=call a function whose code address is statically known
call_direct_long_index=call a function with a long function index
call_long=call a function with a long argument count
call_require=call the require builtin to import a module
call_with_new_target=call a function passing an explicit new.target
call_with_new_target_long=call with new.target (long form)
call1=call a function with 1 argument
call2=call a function with 2 arguments
call3=call a function with 3 arguments
call4=call a function with 4 arguments
catch=mark catch handler entry, receives the thrown exception
coerce_this_n_s=coerce 'this' to an object in non-strict mode
coerce_this_ns=coerce 'this' to an object in non-strict mode
complete_generator=mark generator as completed
construct=invoke a constructor with a given number of arguments
construct_long=invoke a constructor (long form)
create_async_closure=create an async closure
create_async_closure_long_index=create an async closure (long function index)
create_base_class=create a class with no superclass
create_base_class_long_index=create a base class (long function index)
create_closure=create a closure from a function
create_closure_long_index=create a closure (long function index)
create_derived_class=create a class that extends a superclass
create_derived_class_long_index=create a derived class (long function index)
create_environment=create a new lexical environment for the current function
create_function_environment=create the function's lexical environment
create_generator=create a generator function instance
create_generator_closure=create a generator closure
create_generator_closure_long_index=create a generator closure (long function index)
create_generator_long_index=create a generator (long function index)
create_inner_environment=create an inner (nested) lexical environment
create_private_name=create a unique private name symbol
create_reg_exp=create a RegExp object from a pattern and flags
create_this=create the 'this' object for a constructor call
create_this_for_new=allocate 'this' for a 'new' expression
create_this_for_super=allocate 'this' for a super constructor call
create_top_level_environment=create the top-level lexical environment
debugger=trigger the JavaScript debugger statement
debugger_check=check if a debugger break is requested
debugger_check_break=check and yield to debugger if breakpoint is set
dec=decrement a register by 1
declare_global_var=declare a variable on the global object
define_own_by_id=define an own property by string id
define_own_by_id_long=define an own property by string id (long form)
define_own_by_index=define an own indexed property
define_own_by_index_l=define an own indexed property (long form)
define_own_by_val=define an own property by computed value
define_own_getter_setter_by_val=define accessor (getter/setter) property
define_own_in_dense_array=define an element in a dense array literal
define_own_in_dense_array_l=define an element in a dense array literal (long)
del_by_id=delete a property by string id
del_by_id_long=delete a property by string id (long form)
del_by_id_loose=delete a property by id (loose mode)
del_by_id_loose_long=delete a property by id (loose, long form)
del_by_id_strict=delete a property by id (strict mode)
del_by_id_strict_long=delete a property by id (strict, long form)
del_by_val=delete a property by computed value
del_by_val_loose=delete a property by computed value (loose mode)
del_by_val_strict=delete a property by computed value (strict mode)
direct_eval=invoke direct eval()
div=divide two registers
div_n=numeric divide (operands known to be numeric)
divi32=signed 32-bit integer divide
divu32=unsigned 32-bit integer divide
eq=loose equality comparison (==)
fast_array_append=append all elements of a fast array to another
fast_array_length=read the length of a fast array
fast_array_load=load element from a fast array by index
fast_array_push=push a value into a fast array
fast_array_store=store value into a fast array at index
get_arguments_length=read 'arguments.length' lazily
get_arguments_prop_by_val=read an element from 'arguments' lazily
get_arguments_prop_by_val_loose=read 'arguments' element (loose mode)
get_arguments_prop_by_val_strict=read 'arguments' element (strict mode)
get_builtin_closure=get a closure for a builtin function
get_by_id=load a property by string id
get_by_id_long=load a property by string id (long form)
get_by_id_short=load a property by string id (short cache)
get_by_id_with_receiver_long=load a property with explicit receiver (long form)
get_by_index=load an element by integer index
get_by_val=load a property by computed value
get_by_val_with_receiver=load a property by computed value with receiver
get_closure_environment=get the environment of an enclosing closure
get_environment=get the lexical environment at a given depth
get_global_object=get the global object
get_new_target=read the new.target meta-property
get_next_p_name=advance a for-in property iterator
get_next_pname=advance a for-in property iterator
get_own_by_slot_idx=load own property by inline cache slot index
get_own_by_slot_idx_long=load own property by slot index (long form)
get_own_private_by_sym=load an own private property by symbol
get_p_name_list=initialize a for-in property name list
get_parent_environment=get the parent of a lexical environment
get_pname_list=initialize a for-in property name list
greater=greater than comparison (>)
greater_eq=greater than or equal comparison (>=)
inc=increment a register by 1
instance_of=instanceof operator
is_in='in' operator (property exists in object)
iterator_begin=start iteration over an iterable
iterator_close=close (cleanup) an iterator
iterator_next=advance an iterator and read the next value
j_equal=branch if loose equal
j_equal_long=branch if loose equal (long offset)
j_greater=branch if greater than
j_greater_equal=branch if greater than or equal
j_greater_equal_long=branch if greater than or equal (long offset)
j_greater_equal_n=branch if greater or equal (numeric)
j_greater_equal_n_long=branch if greater or equal (numeric, long offset)
j_greater_long=branch if greater than (long offset)
j_greater_n=branch if greater than (numeric)
j_greater_n_long=branch if greater than (numeric, long offset)
j_less=branch if less than
j_less_equal=branch if less than or equal
j_less_equal_long=branch if less than or equal (long offset)
j_less_equal_n=branch if less than or equal (numeric)
j_less_equal_n_long=branch if less than or equal (numeric, long offset)
j_less_long=branch if less than (long offset)
j_less_n=branch if less than (numeric)
j_less_n_long=branch if less than (numeric, long offset)
j_not_equal=branch if loose not equal
j_not_equal_long=branch if loose not equal (long offset)
j_not_greater=branch if not greater than
j_not_greater_equal=branch if not greater than or equal
j_not_greater_equal_long=branch if not greater than or equal (long offset)
j_not_greater_equal_n=branch if not greater than or equal (numeric)
j_not_greater_equal_n_long=branch if not greater than or equal (numeric, long offset)
j_not_greater_long=branch if not greater than (long offset)
j_not_greater_n=branch if not greater than (numeric)
j_not_greater_n_long=branch if not greater than (numeric, long offset)
j_not_less=branch if not less than
j_not_less_equal=branch if not less than or equal
j_not_less_equal_long=branch if not less than or equal (long offset)
j_not_less_equal_n=branch if not less than or equal (numeric)
j_not_less_equal_n_long=branch if not less than or equal (numeric, long offset)
j_not_less_long=branch if not less than (long offset)
j_not_less_n=branch if not less than (numeric)
j_not_less_n_long=branch if not less than (numeric, long offset)
j_strict_equal=branch if strict equal (===)
j_strict_equal_long=branch if strict equal (long offset)
j_strict_not_equal=branch if strict not equal (!==)
j_strict_not_equal_long=branch if strict not equal (long offset)
jequal=branch if loose equal
jequal_long=branch if loose equal (long offset)
jgreater=branch if greater than
jgreater_equal=branch if greater than or equal
jgreater_equal_long=branch if greater than or equal (long offset)
jgreater_equal_n=branch if greater or equal (numeric)
jgreater_equal_nlong=branch if greater or equal (numeric, long offset)
jgreater_long=branch if greater than (long offset)
jgreater_n=branch if greater than (numeric)
jgreater_nlong=branch if greater than (numeric, long offset)
jless=branch if less than
jless_equal=branch if less than or equal
jless_equal_long=branch if less than or equal (long offset)
jless_equal_n=branch if less than or equal (numeric)
jless_equal_nlong=branch if less than or equal (numeric, long offset)
jless_long=branch if less than (long offset)
jless_n=branch if less than (numeric)
jless_nlong=branch if less than (numeric, long offset)
jmp=unconditional branch
jmp_builtin_is=branch if value is a specific builtin
jmp_builtin_is_long=branch if value is a specific builtin (long offset)
jmp_builtin_is_not=branch if value is not a specific builtin
jmp_builtin_is_not_long=branch if value is not a specific builtin (long offset)
jmp_false=branch if value is falsy
jmp_false_long=branch if value is falsy (long offset)
jmp_long=unconditional branch (long offset)
jmp_true=branch if value is truthy
jmp_true_long=branch if value is truthy (long offset)
jmp_type_of_is=branch if typeof value matches a tag
jmp_undefined=branch if value is undefined
jmp_undefined_long=branch if value is undefined (long offset)
jnot_equal=branch if loose not equal
jnot_equal_long=branch if loose not equal (long offset)
jnot_greater=branch if not greater than
jnot_greater_equal=branch if not greater than or equal
jnot_greater_equal_long=branch if not greater than or equal (long offset)
jnot_greater_equal_n=branch if not greater than or equal (numeric)
jnot_greater_equal_nlong=branch if not greater than or equal (numeric, long offset)
jnot_greater_long=branch if not greater than (long offset)
jnot_greater_n=branch if not greater than (numeric)
jnot_greater_nlong=branch if not greater than (numeric, long offset)
jnot_less=branch if not less than
jnot_less_equal=branch if not less than or equal
jnot_less_equal_long=branch if not less than or equal (long offset)
jnot_less_equal_n=branch if not less than or equal (numeric)
jnot_less_equal_nlong=branch if not less than or equal (numeric, long offset)
jnot_less_long=branch if not less than (long offset)
jnot_less_n=branch if not less than (numeric)
jnot_less_nlong=branch if not less than (numeric, long offset)
jstrict_equal=branch if strict equal (===)
jstrict_equal_long=branch if strict equal (long offset)
jstrict_not_equal=branch if strict not equal (!==)
jstrict_not_equal_long=branch if strict not equal (long offset)
l_shift=left shift (<<)
less=less than comparison (<)
less_eq=less than or equal comparison (<=)
load_const_big_int=load a BigInt constant
load_const_big_int_long_index=load a BigInt constant (long index)
load_const_double=load a double-precision float constant
load_const_empty=load the 'empty' sentinel value
load_const_false=load the boolean false constant
load_const_int=load an integer constant
load_const_null=load the null constant
load_const_string=load a string constant by id
load_const_string_long_index=load a string constant by id (long index)
load_const_true=load the boolean true constant
load_const_u_int8=load an 8-bit unsigned integer constant
load_const_uint8=load an 8-bit unsigned integer constant
load_const_undefined=load the undefined constant
load_const_zero=load the integer zero constant
load_from_environment=read a variable from a lexical environment slot
load_from_environment_l=read from environment slot (long index)
load_param=read a function parameter into a register
load_param_long=read a function parameter (long index)
load_parent_no_traps=load object's prototype skipping proxy traps
load_this_n_s=load 'this' in non-strict mode
load_this_ns=load 'this' in non-strict mode
loadi16=load a signed 16-bit integer
loadi32=load a signed 32-bit integer
loadi8=load a signed 8-bit integer
loadu16=load an unsigned 16-bit integer
loadu32=load an unsigned 32-bit integer
loadu8=load an unsigned 8-bit integer
lshift=left shift (<<)
mod=modulo (%) operation
mov=copy a register into another register
mov_long=copy a register (long form)
mul=multiply two registers
mul_n=numeric multiply (operands known to be numeric)
mul32=32-bit integer multiply
name=get the name (string id) of an object
negate=arithmetic negation (unary minus)
neq=loose inequality comparison (!=)
new_array=create an empty array of given size
new_array_with_buffer=create an array initialized from a literal buffer
new_array_with_buffer_long=create an array from a literal buffer (long form)
new_fast_array=create a new fast (dense, integer-indexed) array
new_object=create an empty object
new_object_with_buffer=create an object initialized from a literal buffer
new_object_with_buffer_and_parent=create an object from a buffer with a given prototype
new_object_with_buffer_long=create an object from a literal buffer (long form)
new_object_with_parent=create an empty object with a given prototype
new_typed_object_with_buffer=create a typed object from a literal buffer
not=logical NOT (!)
private_is_in=test if a private name is present in an object
profile_point=marker used by the profiler to record execution
put_by_id=store a property by string id
put_by_id_long=store a property by string id (long form)
put_by_id_loose=store a property by id (loose mode)
put_by_id_loose_long=store a property by id (loose, long form)
put_by_id_strict=store a property by id (strict mode)
put_by_id_strict_long=store a property by id (strict, long form)
put_by_val=store a property by computed value
put_by_val_loose=store a property by computed value (loose mode)
put_by_val_strict=store a property by computed value (strict mode)
put_by_val_with_receiver=store a property by computed value with receiver
put_new_own_by_id=define a new own property by id
put_new_own_by_id_long=define a new own property by id (long form)
put_new_own_by_id_short=define a new own property by id (short form)
put_new_own_n_eby_id=define a new own non-enumerable property by id
put_new_own_n_eby_id_long=define a new own non-enumerable property by id (long form)
put_new_own_ne_by_id=define a new own non-enumerable property by id
put_new_own_ne_by_id_long=define a new own non-enumerable property by id (long form)
put_own_by_index=define an own property by integer index
put_own_by_index_l=define an own property by integer index (long form)
put_own_by_slot_idx=store an own property by inline cache slot
put_own_by_slot_idx_long=store an own property by slot index (long form)
put_own_by_val=define an own property by computed value
put_own_getter_setter_by_val=define an own accessor (getter/setter) property
put_own_private_by_sym=store an own private property by symbol
r_shift=signed right shift (>>)
reify_arguments=create the actual 'arguments' object lazily
reify_arguments_loose=reify 'arguments' object in loose mode
reify_arguments_strict=reify 'arguments' object in strict mode
resume_generator=resume a suspended generator
ret=return from the current function
rshift=signed right shift (>>)
save_generator=suspend the current generator and yield
save_generator_long=suspend the current generator (long offset)
select_object=pick the object operand among two values
start_generator=initialize execution of a generator body
store_n_pto_environment=store non-pointer value to environment slot
store_n_pto_environment_l=store non-pointer value to environment slot (long index)
store_np_to_environment=store non-pointer value to environment slot
store_np_to_environment_l=store non-pointer value to environment slot (long index)
store_to_environment=store a variable into a lexical environment slot
store_to_environment_l=store into environment slot (long index)
store16=store a 16-bit value to memory
store32=store a 32-bit value to memory
store8=store an 8-bit value to memory
strict_eq=strict equality comparison (===)
strict_neq=strict inequality comparison (!==)
string_switch_imm=switch on a string with an inline jump table
sub=subtract two registers
sub_n=numeric subtract (operands known to be numeric)
sub32=32-bit integer subtract
switch_imm=switch on an integer with an inline jump table
throw=throw an exception
throw_if_empty=throw a ReferenceError if value is the empty sentinel (TDZ)
throw_if_has_restricted_global_property=throw if a restricted global property already exists
throw_if_this_initialized=throw if 'this' has already been initialized in a derived ctor
throw_if_undefined=throw a TypeError if the value is undefined
throw_if_undefined_inst=throw TypeError if the value is undefined (instance form)
to_int32=convert a value to a signed 32-bit integer (ToInt32)
to_number=convert a value to a number (ToNumber)
to_numeric=convert a value to numeric (ToNumeric, supports BigInt)
to_property_key=convert a value to a property key (ToPropertyKey)
to_uint32=convert a value to an unsigned 32-bit integer (ToUint32)
try_get_by_id=load a property by id, throwing if missing
try_get_by_id_long=load a property by id, throwing if missing (long form)
try_put_by_id=store a property by id, throwing if missing
try_put_by_id_long=store a property by id, throwing if missing (long form)
try_put_by_id_loose=store a property by id, throwing if missing (loose)
try_put_by_id_loose_long=store a property by id, throwing if missing (loose, long form)
try_put_by_id_strict=store a property by id, throwing if missing (strict)
try_put_by_id_strict_long=store a property by id, throwing if missing (strict, long form)
type_of=typeof operator
type_of_is=test if typeof value equals a specific tag
typed_load_parent=load the prototype of a typed object
u_int_switch_imm=switch on an unsigned integer with an inline jump table
u_rshift=unsigned right shift (>>>)
unreachable=trap; this point should never be reached
urshift=unsigned right shift (>>>)
+1 -1
View File
@@ -1,7 +1,7 @@
project(
'r2hermes',
'c',
version: '1.2.2',
version: '1.2.4',
license: 'MIT',
default_options: [
'c_std=c11',
+11 -12
View File
@@ -233,11 +233,10 @@ static Result emit_call_fixed(TokenString *out, const ParsedInstruction *insn, i
static Result emit_call_with_argc(TokenString *out, const ParsedInstruction *insn) {
RETURN_IF_ERROR (add (out, reg_l_safe (insn, 0)));
RETURN_IF_ERROR (add (out, create_assignment_token ()));
RETURN_IF_ERROR (add (out, reg_r_safe (insn, 0)));
RETURN_IF_ERROR (add (out, create_left_parenthesis_token ()));
RETURN_IF_ERROR (add (out, reg_r_safe (insn, 1)));
RETURN_IF_ERROR (add (out, create_left_parenthesis_token ()));
char buf2[32];
snprintf (buf2, sizeof (buf2), ", /*argc:%u*/", (unsigned)insn->arg3);
snprintf (buf2, sizeof (buf2), "/*argc:%u*/", (unsigned)insn->arg3);
RETURN_IF_ERROR (add (out, create_raw_token (buf2)));
return add (out, create_right_parenthesis_token ());
}
@@ -685,12 +684,12 @@ Result _hbc_translate_instruction_to_tokens(const ParsedInstruction *insn_c, Tok
RETURN_IF_ERROR (add (out, reg_l_safe (insn_c, 0)));
RETURN_IF_ERROR (add (out, create_assignment_token ()));
StringBuffer sb;
_hbc_string_buffer_init (&sb, 48);
RETURN_IF_ERROR (_hbc_string_buffer_init (&sb, 48));
_hbc_string_buffer_append (&sb, "try_get(");
char nb[16];
snprintf (nb, sizeof (nb), "r%u", (unsigned)insn->arg2);
_hbc_string_buffer_append (&sb, nb);
_hbc_format_property_from_string_id (insn->hbc_reader, (op == OP_TryGetById)? insn->arg4: insn->arg4, &sb);
_hbc_format_property_from_string_id (insn->hbc_reader, insn->arg4, &sb);
_hbc_string_buffer_append (&sb, ")");
Token *t = create_raw_token (sb.data? sb.data: "try_get(r0)");
_hbc_string_buffer_free (&sb);
@@ -724,13 +723,13 @@ Result _hbc_translate_instruction_to_tokens(const ParsedInstruction *insn_c, Tok
case OP_PutOwnByIndex:
case OP_PutOwnByIndexL:
{
/* obj[idx] = value */
/* obj[idx] = value; operands: obj reg, value reg, literal idx */
RETURN_IF_ERROR (add (out, reg_r_safe (insn_c, 0)));
RETURN_IF_ERROR (add (out, create_raw_token ("[")));
RETURN_IF_ERROR (add (out, reg_r_safe (insn_c, 1)));
RETURN_IF_ERROR (add (out, num_token_u32 (insn->arg3)));
RETURN_IF_ERROR (add (out, create_raw_token ("]")));
RETURN_IF_ERROR (add (out, create_assignment_token ()));
RETURN_IF_ERROR (add (out, reg_r_safe (insn_c, 2)));
RETURN_IF_ERROR (add (out, reg_r_safe (insn_c, 1)));
break;
}
case OP_PutByVal:
@@ -750,7 +749,7 @@ Result _hbc_translate_instruction_to_tokens(const ParsedInstruction *insn_c, Tok
/* rObj["name"] = rVal */
RETURN_IF_ERROR (add (out, reg_r_safe (insn_c, 0)));
RETURN_IF_ERROR (add (out, create_raw_token ("[")));
u32 sid = (op == OP_PutById)? insn->arg4: insn->arg4;
u32 sid = insn->arg4;
RETURN_IF_ERROR (add (out, quoted_string (insn->hbc_reader, sid)));
RETURN_IF_ERROR (add (out, create_raw_token ("]")));
RETURN_IF_ERROR (add (out, create_assignment_token ()));
@@ -1098,10 +1097,10 @@ Result _hbc_translate_instruction_to_tokens(const ParsedInstruction *insn_c, Tok
RETURN_IF_ERROR (add (out, reg_l_safe (insn_c, 0)));
RETURN_IF_ERROR (add (out, create_assignment_token ()));
RETURN_IF_ERROR (add (out, create_raw_token ("fn_")));
RETURN_IF_ERROR (add (out, num_token_u32 ((op == OP_CallDirect)? insn->arg4: insn->arg4)));
RETURN_IF_ERROR (add (out, num_token_u32 (insn->arg3)));
RETURN_IF_ERROR (add (out, create_left_parenthesis_token ()));
RETURN_IF_ERROR (add (out, create_raw_token ("/*argc:")));
RETURN_IF_ERROR (add (out, num_token_u32 (insn->arg3)));
RETURN_IF_ERROR (add (out, num_token_u32 (insn->arg2)));
RETURN_IF_ERROR (add (out, create_raw_token ("*/")));
RETURN_IF_ERROR (add (out, create_right_parenthesis_token ()));
break;
@@ -1340,7 +1339,7 @@ Result _hbc_translate_instruction_to_tokens(const ParsedInstruction *insn_c, Tok
/* Fallback: emit a comment-like raw token with mnemonic */
StringBuffer sb;
_hbc_string_buffer_init (&sb, 64);
RETURN_IF_ERROR (_hbc_string_buffer_init (&sb, 64));
_hbc_string_buffer_append (&sb, "/* ");
_hbc_string_buffer_append (&sb, insn->inst->name);
_hbc_string_buffer_append (&sb, " */");
+4 -1
View File
@@ -455,10 +455,13 @@ Result hbc_dec(const HBCDecodeCtx *ctx, HBCInsnInfo *out) {
switch (operand_type) {
case OPERAND_TYPE_REG8:
case OPERAND_TYPE_UINT8:
case OPERAND_TYPE_ADDR8:
operand_values[i] = ctx->bytes[pos];
pos += 1;
break;
case OPERAND_TYPE_ADDR8:
operand_values[i] = (u32)(i32)(i8)ctx->bytes[pos];
pos += 1;
break;
case OPERAND_TYPE_UINT16:
operand_values[i] = ctx->bytes[pos] | (ctx->bytes[pos + 1] << 8);
pos += 2;
+15 -13
View File
@@ -131,7 +131,7 @@ Result hbc_encoder_parse_instruction(HBCEncoder *encoder, const char *asm_line,
}
/* Parse operands separated by commas */
while (*line && operand_count < 6) {
while (*line) {
/* Skip whitespace */
while (*line && isspace (*line)) {
line++;
@@ -177,13 +177,16 @@ Result hbc_encoder_parse_instruction(HBCEncoder *encoder, const char *asm_line,
}
*trim_end = '\0';
/* Parse operand based on expected type */
if (operand_count < 6 && inst->operands[operand_count].operand_type != OPERAND_TYPE_NONE) {
OperandType expected_type = inst->operands[operand_count].operand_type;
char *endptr;
bool parse_success = false;
if (operand_count >= 6 || inst->operands[operand_count].operand_type == OPERAND_TYPE_NONE) {
return ERROR_RESULT (RESULT_ERROR_PARSING_FAILED, "Incorrect number of operands");
}
switch (expected_type) {
/* Parse operand based on expected type */
OperandType expected_type = inst->operands[operand_count].operand_type;
char *endptr;
bool parse_success = false;
switch (expected_type) {
case OPERAND_TYPE_REG8:
case OPERAND_TYPE_REG32:
/* Register: rN or RN */
@@ -268,13 +271,12 @@ Result hbc_encoder_parse_instruction(HBCEncoder *encoder, const char *asm_line,
break;
}
if (!parse_success) {
return ERROR_RESULT (RESULT_ERROR_PARSING_FAILED, "Invalid operand format");
}
operand_count++;
if (!parse_success) {
return ERROR_RESULT (RESULT_ERROR_PARSING_FAILED, "Invalid operand format");
}
operand_count++;
/* Move to next operand */
line = operand_end;
if (*line == ',') {
@@ -338,7 +340,7 @@ Result hbc_encoder_encode_instruction(HBCEncoder *encoder, const HBCEncodedInstr
/* Write operands based on their types */
for (int i = 0; i < 6 && inst->operands[i].operand_type != OPERAND_TYPE_NONE; i++) {
OperandType type = inst->operands[i].operand_type;
u32 value = operand_values[i];
u64 value = operand_values[i];
switch (type) {
case OPERAND_TYPE_REG8:
+6 -13
View File
@@ -984,12 +984,9 @@ Result _hbc_reader_read_string_tables(HBCReader *reader) {
is_utf16 = reader->small_string_table[i].isUTF16;
}
size_t decoded_length = (size_t)length;
size_t available = (size_t)offset > string_storage_size? 0: string_storage_size - (size_t)offset;
if ((size_t)offset > string_storage_size ||
decoded_length == SIZE_MAX ||
(is_utf16 && decoded_length > available / 2) ||
(!is_utf16 && decoded_length > available)) {
/* Overflow-safe bounds check via subtraction */
const u32 bpc = is_utf16? 2: 1;
if (offset > string_storage_size || length > (string_storage_size - offset) / bpc) {
fprintf (stderr, "Warning: String %u offset/length out of bounds, treating as empty string\n", i);
reader->strings[i] = strdup ("");
if (!reader->strings[i]) {
@@ -1000,9 +997,7 @@ Result _hbc_reader_read_string_tables(HBCReader *reader) {
continue;
}
/* Allocate string buffer (+1 for null terminator) */
size_t buffer_size = decoded_length + 1;
char *str = (char *)malloc (buffer_size);
char *str = (char *)malloc (length * bpc + 1);
if (!str) {
free (string_storage);
reader->string_table_storage = NULL;
@@ -1339,10 +1334,8 @@ Result _hbc_reader_read_bigints(HBCReader *reader) {
u32 offset = bigint_table[i].offset;
u32 length = bigint_table[i].length;
/* Check bounds */
size_t bigint_available = (size_t)offset > reader->header.bigIntStorageSize? 0:
(size_t)reader->header.bigIntStorageSize - (size_t)offset;
if ((size_t)offset > reader->header.bigIntStorageSize || (size_t)length > bigint_available) {
/* Overflow-safe bounds check via subtraction */
if (offset > reader->header.bigIntStorageSize || length > reader->header.bigIntStorageSize - offset) {
fprintf (stderr, "Warning: BigInt %u has invalid offset/length (%u+%u exceeds %u)\n", i, offset, length, reader->header.bigIntStorageSize);
/* Use zero for this value */
reader->bigint_values[i] = 0;
+4 -7
View File
@@ -363,11 +363,9 @@ Result _hbc_generate_r2_script(const char *input_file, const char *output_file)
u32 length = string_infos[i].length;
bool isUTF16 = string_infos[i].isUTF16;
/* Skip strings with obviously invalid offsets/lengths */
size_t available = (size_t)offset > string_storage_size? 0: string_storage_size - (size_t)offset;
if ((size_t)offset > string_storage_size ||
(isUTF16 && (size_t)length > available / 2) ||
(!isUTF16 && (size_t)length > available)) {
/* Overflow-safe bounds check via subtraction */
const u32 bpc = isUTF16? 2: 1;
if (offset > string_storage_size || length > (string_storage_size - offset) / bpc) {
continue;
}
@@ -433,9 +431,8 @@ Result _hbc_generate_r2_script(const char *input_file, const char *output_file)
snprintf (unique_name, sizeof (unique_name), "%s_%u", sanitized_name[0]? sanitized_name: "str", i);
/* Write the string flag - offset is relative to string storage base */
size_t size = isUTF16? (size_t)length * 2: (size_t)length;
uint32_t addr = (unsigned long) (reader.file_buffer.position - string_storage_size + offset);
fprintf (out, "'f str.%s %zu 0x%08x\n", unique_name, size, addr);
fprintf (out, "'f str.%s %u 0x%08x\n", unique_name, length * bpc, addr);
#if 0
/* Add flag for string length */
if (isUTF16) {
+7 -10
View File
@@ -285,21 +285,18 @@ static RList *strings(RBinFile *bf) {
if (hbc_get_string_meta (hbc, i, &meta).code != RESULT_SUCCESS) {
continue;
}
if (meta.length == 0) {
const size_t str_len = strlen (str);
if (str_len == 0) {
continue;
}
RBinString *ptr = R_NEW0 (RBinString);
if (meta.length >= R_BIN_SIZEOF_STRINGS) {
ptr->string = r_str_ndup (str, R_BIN_SIZEOF_STRINGS - 4);
if (ptr->string) {
char *tmp = r_str_newf ("%s...", ptr->string);
free (ptr->string);
ptr->string = tmp;
}
if (str_len >= R_BIN_SIZEOF_STRINGS) {
char *trunc = r_str_ndup (str, R_BIN_SIZEOF_STRINGS - 4);
ptr->string = r_str_newf ("%s...", trunc? trunc: "");
free (trunc);
} else {
ptr->string = r_str_ndup (str, meta.length);
ptr->string = r_str_ndup (str, str_len);
}
if (!ptr->string) {
free (ptr);
+288 -1
View File
@@ -284,7 +284,7 @@ EXPECT=<<EOF
EOF
RUN
NAME=hbc assembler
NAME=hbc pa ret
FILE=--
CMDS=<<EOF
-a hbc
@@ -294,3 +294,290 @@ EXPECT=<<EOF
5c00
EOF
RUN
NAME=hbc pa get_global_object
FILE=--
CMDS=<<EOF
-a hbc
pa get_global_object r0
EOF
EXPECT=<<EOF
3000
EOF
RUN
NAME=hbc pa mov two regs
FILE=--
CMDS=<<EOF
-a hbc
pa mov r2, r1
EOF
EXPECT=<<EOF
080201
EOF
RUN
NAME=hbc pa construct three operands
FILE=--
CMDS=<<EOF
-a hbc
pa construct r0, r0, 1
EOF
EXPECT=<<EOF
50000001
EOF
RUN
NAME=hbc pa select_object three regs
FILE=--
CMDS=<<EOF
-a hbc
pa select_object r0, r1, r0
EOF
EXPECT=<<EOF
6b000100
EOF
RUN
NAME=hbc pa store_to_environment
FILE=--
CMDS=<<EOF
-a hbc
pa store_to_environment r1, 1, r0
EOF
EXPECT=<<EOF
2a010100
EOF
RUN
NAME=hbc pa rejects extra operand
FILE=--
CMDS=<<EOF
-a hbc
"pa ret r0, r1"
EOF
EXPECT=<<EOF
EOF
RUN
NAME=hbc pa rejects multiple extra operands
FILE=--
CMDS=<<EOF
-a hbc
"pa ret r0, r1, r2"
EOF
EXPECT=<<EOF
EOF
RUN
NAME=hbc pa rejects extra operand on zero-arg instr
FILE=--
CMDS=<<EOF
-a hbc
"pa get_global_object r0, r1"
EOF
EXPECT=<<EOF
EOF
RUN
NAME=hbc pa rejects missing operand
FILE=--
CMDS=<<EOF
-a hbc
pa ret
EOF
EXPECT=<<EOF
EOF
RUN
NAME=hbc pa rejects truncated mov
FILE=--
CMDS=<<EOF
-a hbc
pa mov r2
EOF
EXPECT=<<EOF
EOF
RUN
NAME=hbc pa rejects unknown mnemonic
FILE=--
CMDS=<<EOF
-a hbc
pa bogus_op r0
EOF
EXPECT=<<EOF
EOF
RUN
NAME=hbc pad ret
FILE=--
CMDS=<<EOF
-a hbc
pad 5c00
EOF
EXPECT=<<EOF
ret r0
EOF
RUN
NAME=hbc pad get_global_object
FILE=--
CMDS=<<EOF
-a hbc
pad 3000
EOF
EXPECT=<<EOF
get_global_object r0
EOF
RUN
NAME=hbc pad mov
FILE=--
CMDS=<<EOF
-a hbc
pad 080201
EOF
EXPECT=<<EOF
mov r2, r1
EOF
RUN
NAME=hbc pad construct
FILE=--
CMDS=<<EOF
-a hbc
pad 50000001
EOF
EXPECT=<<EOF
construct r0, r0, 1
EOF
RUN
NAME=hbc pad select_object
FILE=--
CMDS=<<EOF
-a hbc
pad 6b000100
EOF
EXPECT=<<EOF
select_object r0, r1, r0
EOF
RUN
NAME=hbc pad store_to_environment
FILE=--
CMDS=<<EOF
-a hbc
pad 2a010100
EOF
EXPECT=<<EOF
store_to_environment r1, 1, r0
EOF
RUN
NAME=hbc pa+pad roundtrip ret
FILE=--
CMDS=<<EOF
-a hbc
pad `pa ret r0`
EOF
EXPECT=<<EOF
ret r0
EOF
RUN
NAME=hbc pa+pad roundtrip mov
FILE=--
CMDS=<<EOF
-a hbc
pad `pa mov r2, r1`
EOF
EXPECT=<<EOF
mov r2, r1
EOF
RUN
NAME=hbc pa+pad roundtrip construct
FILE=--
CMDS=<<EOF
-a hbc
pad `pa construct r0, r0, 1`
EOF
EXPECT=<<EOF
construct r0, r0, 1
EOF
RUN
NAME=hbc pi ret after wx
FILE=malloc://16
CMDS=<<EOF
-a hbc
wx 5c00
pi 1
EOF
EXPECT=<<EOF
ret r0
EOF
RUN
NAME=hbc pi mov after wx
FILE=malloc://16
CMDS=<<EOF
-a hbc
wx 080201
pi 1
EOF
EXPECT=<<EOF
mov r2, r1
EOF
RUN
NAME=hbc pi construct after wx
FILE=malloc://16
CMDS=<<EOF
-a hbc
wx 50000001
pi 1
EOF
EXPECT=<<EOF
construct r0, r0, 1
EOF
RUN
NAME=hbc pa+wx+pi roundtrip ret
FILE=malloc://16
CMDS=<<EOF
-a hbc
wx `pa ret r0`
pi 1
EOF
EXPECT=<<EOF
ret r0
EOF
RUN
NAME=hbc pa+wx+pi roundtrip mov
FILE=malloc://16
CMDS=<<EOF
-a hbc
wx `pa mov r2, r1`
pi 1
EOF
EXPECT=<<EOF
mov r2, r1
EOF
RUN
NAME=hbc pa+wx+pi roundtrip store_to_environment
FILE=malloc://16
CMDS=<<EOF
-a hbc
wx `pa store_to_environment r1, 1, r0`
pi 1
EOF
EXPECT=<<EOF
store_to_environment r1, 1, r0
EOF
RUN