Move code to new arena.

This commit is contained in:
Victor M. Alvarez
2020-02-25 15:43:10 +01:00
parent f8e4d25a5f
commit 2886e2aa1a
12 changed files with 459 additions and 404 deletions
+18 -4
View File
@@ -32,13 +32,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <string.h>
#include <yara/arena.h>
#include <yara/arena2.h>
#include <yara/ahocorasick.h>
#include <yara/compiler.h>
#include <yara/error.h>
#include <yara/utils.h>
#include <yara/mem.h>
typedef struct _QUEUE_NODE
{
YR_AC_STATE* value;
@@ -681,7 +682,8 @@ static int _yr_ac_build_transition_table(
// Prints automaton state for debug purposes. This function is invoked by
// yr_ac_print_automaton, is not intended to be used stand-alone.
//
//TODO(vmalvarez): Remove or re-implement
/*
static void _yr_ac_print_automaton_state(
YR_AC_STATE* state)
{
@@ -757,7 +759,7 @@ static void _yr_ac_print_automaton_state(
_yr_ac_print_automaton_state(child_state);
child_state = child_state->siblings;
}
}
}*/
//
@@ -832,6 +834,7 @@ int yr_ac_automaton_destroy(
int yr_ac_add_string(
YR_AC_AUTOMATON* automaton,
YR_STRING* string,
uint32_t string_idx,
YR_ATOM_LIST_ITEM* atom,
YR_ARENA* matches_arena)
{
@@ -873,10 +876,12 @@ int yr_ac_add_string(
offsetof(YR_AC_MATCH, next),
EOL);
if (result == ERROR_SUCCESS)
{
new_match->backtrack = state->depth + atom->backtrack;
new_match->string = string;
new_match->string_idx = string_idx;
new_match->forward_code = atom->forward_code;
new_match->backward_code = atom->backward_code;
new_match->next = state->matches;
@@ -909,6 +914,13 @@ int yr_ac_compile(
FAIL_ON_ERROR(_yr_ac_optimize_failure_links(automaton));
FAIL_ON_ERROR(_yr_ac_build_transition_table(automaton));
/*FAIL_ON_ERROR(yr_arena2_write_data(
arena,
YR_AC_TRANSITION_TABLE,
automaton->t_table,
automaton->tables_size * sizeof(YR_AC_TRANSITION),
NULL));*/
FAIL_ON_ERROR(yr_arena_reserve_memory(
arena,
automaton->tables_size * sizeof(tables->transitions[0]) +
@@ -967,10 +979,12 @@ int yr_ac_compile(
//
// Prints automaton for debug purposes.
//
//TODO(vmalvarez): Remove or re-implement
/*
void yr_ac_print_automaton(YR_AC_AUTOMATON* automaton)
{
printf("-------------------------------------------------------\n");
_yr_ac_print_automaton_state(automaton->root);
printf("-------------------------------------------------------\n");
}
*/
+10
View File
@@ -345,6 +345,16 @@ void* yr_arena2_get_ptr(
}
yr_arena_off_t yr_arena2_get_current_offset(
YR_ARENA2* arena,
int buffer_id)
{
assert(buffer_id < arena->num_buffers);
return arena->buffers[buffer_id].used;
}
int yr_arena2_ptr_to_ref(
YR_ARENA2* arena,
const void* address,
+11 -17
View File
@@ -214,10 +214,6 @@ YR_API int yr_compiler_create(
result = yr_arena2_create(
YR_NUM_SECTIONS, 50*1048576, &new_compiler->arena);
if (result == ERROR_SUCCESS)
result = yr_arena_create(
65536, ARENA_FLAGS_RELOCATABLE, &new_compiler->code_arena);
if (result == ERROR_SUCCESS)
result = yr_arena_create(
65536, ARENA_FLAGS_RELOCATABLE, &new_compiler->re_code_arena);
@@ -255,7 +251,6 @@ YR_API void yr_compiler_destroy(
yr_arena2_destroy(compiler->arena);
yr_arena_destroy(compiler->compiled_rules_arena);
yr_arena_destroy(compiler->code_arena);
yr_arena_destroy(compiler->re_code_arena);
yr_arena_destroy(compiler->automaton_arena);
yr_arena_destroy(compiler->matches_arena);
@@ -663,8 +658,9 @@ static int _yr_compiler_compile_rules(
int result;
// Write halt instruction at the end of code.
yr_arena_write_data(
compiler->code_arena,
yr_arena2_write_data(
compiler->arena,
YR_CODE_SECTION,
&halt,
sizeof(uint8_t),
NULL);
@@ -720,8 +716,8 @@ static int _yr_compiler_compile_rules(
rules_file_header->externals_list_head = (YR_EXTERNAL_VARIABLE*) \
yr_arena2_get_ptr(compiler->arena, YR_EXTERNAL_VARIABLES_TABLE, 0);
rules_file_header->code_start = (uint8_t*) yr_arena_base_address(
compiler->code_arena);
rules_file_header->code_start = (uint8_t*) yr_arena2_get_ptr(
compiler->arena, YR_CODE_SECTION, 0);
rules_file_header->ac_match_table = tables.matches;
rules_file_header->ac_transition_table = tables.transitions;
@@ -730,14 +726,6 @@ static int _yr_compiler_compile_rules(
if (result == ERROR_SUCCESS)
{
result = yr_arena_append(
arena,
compiler->code_arena);
}
if (result == ERROR_SUCCESS)
{
compiler->code_arena = NULL;
result = yr_arena_append(
arena,
compiler->re_code_arena);
@@ -796,6 +784,12 @@ static int _yr_compiler_compile_rules(
arena, compiler->arena, YR_SZ_POOL);
}
if (result == ERROR_SUCCESS)
{
result = yr_arena_append_arena2_buffer(
arena, compiler->arena, YR_CODE_SECTION);
}
if (result == ERROR_SUCCESS)
{
compiler->compiled_rules_arena = arena;
+24 -13
View File
@@ -179,18 +179,24 @@ static const uint8_t* jmp_if(
int condition,
const uint8_t* ip)
{
const uint8_t* result;
size_t off;
if (condition)
{
result = *(const uint8_t**)(ip);
// The condition is true, the instruction pointer is incremented in the
// amount specified by the jump's offset. The offset is relative to the
// jump opcode, but now the instruction pointer is pointing past the opcode
// that's why we decrement the offset by 1.
off = *(int32_t*)(ip) - 1;
}
else
{
result = ip + sizeof(uint64_t);
// The condition is false, the execution flow proceeds with the instruction
// right after the jump.
off = sizeof(int32_t);
}
return result;
return ip + off;
}
@@ -356,7 +362,7 @@ int yr_execute_code(
uint64_t start_time;
#endif
YR_INIT_RULE_ARGS init_rule_args;
uint32_t rule_idx;
YR_RULE* current_rule = NULL;
YR_RULE* rule;
@@ -407,7 +413,10 @@ int yr_execute_code(
while(!stop)
{
// Read the opcode from the address indicated by the instruction pointer.
opcode = *ip;
// Advance the instruction pointer, which now points past the opcode.
ip++;
switch(opcode)
@@ -776,14 +785,16 @@ int yr_execute_code(
break;
case OP_INIT_RULE:
memcpy(&init_rule_args, ip, sizeof(init_rule_args));
current_rule = &context->rules->rules_list_head[init_rule_args.rule_idx];
if (RULE_IS_DISABLED(current_rule))
ip = init_rule_args.jmp_addr;
else
ip += sizeof(init_rule_args);
// After the opcode there's an int32_t corresponding to the jump's
// offset and an uint32_t corresponding to the rule's index.
rule_idx = *(uint32_t*)(ip + sizeof(int32_t));
current_rule = &context->rules->rules_list_head[rule_idx];
// If the rule is disabled let's skip its code.
ip = jmp_if(RULE_IS_DISABLED(current_rule), ip);
// Skip the bytes corresponding to the rule's index, but only if not
// taking the jump.
if (!RULE_IS_DISABLED(current_rule))
ip += sizeof(uint32_t);
break;
case OP_MATCH_RULE:
+208 -184
View File
File diff suppressed because it is too large Load Diff
+83 -59
View File
@@ -1379,7 +1379,7 @@ expression
// JL_P repeat ; if M[1] is less M[3] repeat
//
// exit:
// POP ; remove the itertor object from the stack
// POP ; remove the iterator object from the stack
//
// PUSH_M 0 ; pushes number of true results for <expression>
// PUSH_M 2 ; pushes value of <min_expression>
@@ -1434,14 +1434,14 @@ expression
YR_LOOP_CONTEXT* loop_ctx = &compiler->loop[compiler->loop_index];
YR_FIXUP* fixup;
uint8_t* loop_start_addr;
void* jmp_arg_addr;
YR_ARENA2_REFERENCE loop_start_ref;
YR_ARENA2_REFERENCE jmp_offset_ref;
int var_frame = _yr_compiler_get_var_frame(compiler);
int i;
fail_if_error(yr_parser_emit(
yyscanner, OP_ITER_NEXT, &loop_start_addr));
yyscanner, OP_ITER_NEXT, &loop_start_ref));
// For each variable generate an instruction that pops the value from
// the stack and store it into one memory slot starting at var_frame + 3
@@ -1453,31 +1453,32 @@ expression
yyscanner, OP_POP_M, var_frame + 3 + i, NULL, NULL));
}
fail_if_error(yr_parser_emit_with_arg_reloc(
fail_if_error(yr_parser_emit_with_arg_int32(
yyscanner,
OP_JTRUE_P,
0,
0, // still don't know the jump offset, use 0 for now.
NULL,
&jmp_arg_addr));
&jmp_offset_ref));
// Push a new fixup entry in the fixup stack so that the jump
// destination is set once we know it.
// We still don't know the jump's target, so we push a fixup entry
// in the stack, so that the jump's offset can be set once we know it.
fixup = (YR_FIXUP*) yr_malloc(sizeof(YR_FIXUP));
if (fixup == NULL)
fail_if_error(ERROR_INSUFFICIENT_MEMORY);
fixup->address = jmp_arg_addr;
fixup->ref = jmp_offset_ref;
fixup->next = compiler->fixup_stack_head;
compiler->fixup_stack_head = fixup;
loop_ctx->addr = loop_start_addr;
loop_ctx->start_ref = loop_start_ref;
}
'(' boolean_expression ')'
{
int32_t jmp_offset;
YR_FIXUP* fixup;
uint8_t* pop_addr;
YR_ARENA2_REFERENCE pop_ref;
int var_frame = _yr_compiler_get_var_frame(compiler);
@@ -1490,10 +1491,14 @@ expression
fail_if_error(yr_parser_emit_with_arg(
yyscanner, OP_PUSH_M, var_frame + 2, NULL, NULL));
fail_if_error(yr_parser_emit_with_arg_reloc(
jmp_offset = \
compiler->loop[compiler->loop_index].start_ref.offset -
yr_arena2_get_current_offset(compiler->arena, YR_CODE_SECTION);
fail_if_error(yr_parser_emit_with_arg_int32(
yyscanner,
OP_JUNDEF_P,
compiler->loop[compiler->loop_index].addr,
jmp_offset,
NULL,
NULL));
@@ -1503,24 +1508,38 @@ expression
fail_if_error(yr_parser_emit_with_arg(
yyscanner, OP_PUSH_M, var_frame + 2, NULL, NULL));
fail_if_error(yr_parser_emit_with_arg_reloc(
jmp_offset = \
compiler->loop[compiler->loop_index].start_ref.offset -
yr_arena2_get_current_offset(compiler->arena, YR_CODE_SECTION);
fail_if_error(yr_parser_emit_with_arg_int32(
yyscanner,
OP_JL_P,
compiler->loop[compiler->loop_index].addr,
jmp_offset,
NULL,
NULL));
fail_if_error(yr_parser_emit(
yyscanner, OP_POP, &pop_addr));
yyscanner, OP_POP, &pop_ref));
// Pop from the stack the fixup entry containing the jump's address
// that needs to be fixed.
// Pop from the stack the fixup entry containing the reference to
// the jump offset that needs to be fixed.
fixup = compiler->fixup_stack_head;
compiler->fixup_stack_head = fixup->next;
// Fix the jump's target address.
*(void**)(fixup->address) = (void*)(pop_addr);
// The fixup entry has a reference to the jump offset that need
// to be fixed, convert the address into a pointer.
int32_t* jmp_offset_addr = (int32_t*) yr_arena2_ref_to_ptr(
compiler->arena, &fixup->ref);
// The reference in the fixup entry points to the jump's offset
// but the jump instruction is one byte before, that's why we add
// one to the offset.
jmp_offset = pop_ref.offset - fixup->ref.offset + 1;
// Fix the jump's offset.
*jmp_offset_addr = jmp_offset;
yr_free(fixup);
@@ -1544,9 +1563,10 @@ expression
}
| _FOR_ for_expression _OF_ string_set ':'
{
YR_ARENA2_REFERENCE ref;
int result = ERROR_SUCCESS;
int var_frame;
uint8_t* addr;
if (compiler->loop_index + 1 == YR_MAX_LOOP_NESTING)
result = ERROR_LOOP_NESTING_LIMIT_EXCEEDED;
@@ -1568,12 +1588,12 @@ expression
// Pop the first string.
yr_parser_emit_with_arg(
yyscanner, OP_POP_M, var_frame, &addr, NULL);
yyscanner, OP_POP_M, var_frame, &ref, NULL);
compiler->loop_for_of_var_index = var_frame;
compiler->loop[compiler->loop_index].vars_internal_count = 3;
compiler->loop[compiler->loop_index].vars_count = 0;
compiler->loop[compiler->loop_index].addr = addr;
compiler->loop[compiler->loop_index].start_ref = ref;
}
'(' boolean_expression ')'
{
@@ -1594,12 +1614,16 @@ expression
yr_parser_emit_with_arg(
yyscanner, OP_INCR_M, var_frame + 2, NULL, NULL);
int32_t jmp_offset = \
compiler->loop[compiler->loop_index].start_ref.offset -
yr_arena2_get_current_offset(compiler->arena, YR_CODE_SECTION);
// If next string is not undefined, go back to the
// beginning of the loop.
yr_parser_emit_with_arg_reloc(
yr_parser_emit_with_arg_int32(
yyscanner,
OP_JNUNDEF,
compiler->loop[compiler->loop_index].addr,
jmp_offset,
NULL,
NULL);
@@ -1641,43 +1665,43 @@ expression
| boolean_expression _AND_
{
YR_FIXUP* fixup;
void* jmp_destination_addr;
YR_ARENA2_REFERENCE jmp_offset_ref;
fail_if_error(yr_parser_emit_with_arg_reloc(
fail_if_error(yr_parser_emit_with_arg_int32(
yyscanner,
OP_JFALSE,
0, // still don't know the jump destination
0, // still don't know the jump offset, use 0 for now.
NULL,
&jmp_destination_addr));
&jmp_offset_ref));
// create a fixup entry for the jump and push it in the stack
// Create a fixup entry for the jump and push it in the stack.
fixup = (YR_FIXUP*) yr_malloc(sizeof(YR_FIXUP));
if (fixup == NULL)
fail_if_error(ERROR_INSUFFICIENT_MEMORY);
fixup->address = jmp_destination_addr;
fixup->ref = jmp_offset_ref;
fixup->next = compiler->fixup_stack_head;
compiler->fixup_stack_head = fixup;
}
boolean_expression
{
YR_FIXUP* fixup;
uint8_t* nop_addr;
fail_if_error(yr_parser_emit(yyscanner, OP_AND, NULL));
// Generate a do-nothing instruction (NOP) in order to get its address
// and use it as the destination for the OP_JFALSE. We can not simply
// use the address of the OP_AND instruction +1 because we can't be
// sure that the instruction following the OP_AND is going to be in
// the same arena page. As we don't have a reliable way of getting the
// address of the next instruction we generate the OP_NOP.
fail_if_error(yr_parser_emit(yyscanner, OP_NOP, &nop_addr));
fixup = compiler->fixup_stack_head;
*(void**)(fixup->address) = (void*) nop_addr;
int32_t* jmp_offset_addr = (int32_t*) yr_arena2_ref_to_ptr(
compiler->arena, &fixup->ref);
int32_t jmp_offset = \
yr_arena2_get_current_offset(compiler->arena, YR_CODE_SECTION) -
fixup->ref.offset + 1;
*jmp_offset_addr = jmp_offset;
// Remove fixup from the stack.
compiler->fixup_stack_head = fixup->next;
yr_free(fixup);
@@ -1686,42 +1710,42 @@ expression
| boolean_expression _OR_
{
YR_FIXUP* fixup;
void* jmp_destination_addr;
YR_ARENA2_REFERENCE jmp_offset_ref;
fail_if_error(yr_parser_emit_with_arg_reloc(
fail_if_error(yr_parser_emit_with_arg_int32(
yyscanner,
OP_JTRUE,
0, // still don't know the jump destination
0, // still don't know the jump destination, use 0 for now.
NULL,
&jmp_destination_addr));
&jmp_offset_ref));
fixup = (YR_FIXUP*) yr_malloc(sizeof(YR_FIXUP));
if (fixup == NULL)
fail_if_error(ERROR_INSUFFICIENT_MEMORY);
fixup->address = jmp_destination_addr;
fixup->ref = jmp_offset_ref;
fixup->next = compiler->fixup_stack_head;
compiler->fixup_stack_head = fixup;
}
boolean_expression
{
YR_FIXUP* fixup;
uint8_t* nop_addr;
fail_if_error(yr_parser_emit(yyscanner, OP_OR, NULL));
// Generate a do-nothing instruction (NOP) in order to get its address
// and use it as the destination for the OP_JFALSE. We can not simply
// use the address of the OP_OR instruction +1 because we can't be
// sure that the instruction following the OP_AND is going to be in
// the same arena page. As we don't have a reliable way of getting the
// address of the next instruction we generate the OP_NOP.
fail_if_error(yr_parser_emit(yyscanner, OP_NOP, &nop_addr));
fixup = compiler->fixup_stack_head;
*(void**)(fixup->address) = (void*)(nop_addr);
int32_t jmp_offset = \
yr_arena2_get_current_offset(compiler->arena, YR_CODE_SECTION) -
fixup->ref.offset + 1;
int32_t* jmp_offset_addr = (int32_t*) yr_arena2_ref_to_ptr(
compiler->arena, &fixup->ref);
*jmp_offset_addr = jmp_offset;
// Remove fixup from the stack.
compiler->fixup_stack_head = fixup->next;
yr_free(fixup);
+1
View File
@@ -62,6 +62,7 @@ int yr_ac_automaton_destroy(
int yr_ac_add_string(
YR_AC_AUTOMATON* automaton,
YR_STRING* string,
uint32_t string_idx,
YR_ATOM_LIST_ITEM* atom,
YR_ARENA* matches_arena);
+4
View File
@@ -180,6 +180,10 @@ void* yr_arena2_get_ptr(
yr_arena_off_t offset);
yr_arena_off_t yr_arena2_get_current_offset(
YR_ARENA2* arena,
int buffer_id);
int yr_arena2_allocate_memory(
YR_ARENA2* arena,
+9 -3
View File
@@ -67,6 +67,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define YR_CODE_SECTION 6
#define YR_RE_CODE_SECTION 7
// This is the number of buffers used by the compiler, should match the number
// of items in the list above.
#define YR_NUM_SECTIONS 8
@@ -125,7 +126,6 @@ typedef void (*YR_COMPILER_RE_AST_CALLBACK_FUNC)(
typedef struct _YR_FIXUP
{
YR_ARENA2_REFERENCE ref;
void* address;
struct _YR_FIXUP* next;
} YR_FIXUP;
@@ -138,7 +138,9 @@ typedef struct _YR_FIXUP
typedef struct _YR_LOOP_CONTEXT
{
uint8_t* addr;
// Reference indicating the the place in the code where the loop starts. The
// loop goes back to this address on each iteration.
YR_ARENA2_REFERENCE start_ref;
// vars_count is the number of local variables defined by the loop, and vars
// is an array of expressions with the identifier and type for each of those
@@ -180,6 +182,10 @@ typedef struct _YR_COMPILER
// Similar to YR_CODE_SECTION, but it contains the code for regular
// expressions. This is the code executed by yr_re_exec and
// yr_re_fast_exec.
// YR_AC_TRANSITION_TABLE:
// Contains the Aho-Corasick transition table.
// YR_AC_MATCHES_TABLE:
// An array of YR_AC_MATCH structures.
//
YR_ARENA2* arena;
@@ -202,7 +208,7 @@ typedef struct _YR_COMPILER
jmp_buf error_recovery;
YR_ARENA* code_arena;
//YR_ARENA* code_arena;
YR_ARENA* re_code_arena;
YR_ARENA* compiled_rules_arena;
YR_ARENA* matches_arena;
+15 -7
View File
@@ -37,31 +37,39 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
int yr_parser_emit(
yyscan_t yyscanner,
uint8_t instruction,
uint8_t** instruction_address);
YR_ARENA2_REFERENCE* instruction_ref);
int yr_parser_emit_with_arg(
yyscan_t yyscanner,
uint8_t instruction,
int64_t argument,
uint8_t** instruction_address,
int64_t** argument_address);
YR_ARENA2_REFERENCE* instruction_ref,
YR_ARENA2_REFERENCE* argument_ref);
int yr_parser_emit_with_arg_int32(
yyscan_t yyscanner,
uint8_t instruction,
int32_t argument,
YR_ARENA2_REFERENCE* instruction_ref,
YR_ARENA2_REFERENCE* argument_ref);
int yr_parser_emit_with_arg_double(
yyscan_t yyscanner,
uint8_t instruction,
double argument,
uint8_t** instruction_address,
double** argument_address);
YR_ARENA2_REFERENCE* instruction_ref,
YR_ARENA2_REFERENCE* argument_ref);
int yr_parser_emit_with_arg_reloc(
yyscan_t yyscanner,
uint8_t instruction,
void* argument,
uint8_t** instruction_address,
void** argument_address);
YR_ARENA2_REFERENCE* instruction_ref,
YR_ARENA2_REFERENCE* argument_ref);
int yr_parser_check_types(
+1 -11
View File
@@ -387,6 +387,7 @@ struct YR_EXTERNAL_VARIABLE
struct YR_AC_MATCH
{
uint16_t backtrack;
uint32_t string_idx;
DECLARE_REFERENCE(YR_STRING*, string);
DECLARE_REFERENCE(const uint8_t*, forward_code);
@@ -427,17 +428,6 @@ typedef struct YARA_RULES_FILE_HEADER
} YARA_RULES_FILE_HEADER;
typedef struct _YR_INIT_RULE_ARGS
{
// Index of the rule in the rules table.
uint32_t rule_idx;
// Address of the first instruction belonging to the next rule. This is
// used when a rule is disabled and we want to skip its code.
DECLARE_REFERENCE(const uint8_t*, jmp_addr);
} YR_INIT_RULE_ARGS;
#pragma pack(pop)
+75 -106
View File
@@ -55,20 +55,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
int yr_parser_emit(
yyscan_t yyscanner,
uint8_t instruction,
uint8_t** instruction_address)
YR_ARENA2_REFERENCE* instruction_ref)
{
yr_arena2_write_data(
return yr_arena2_write_data(
yyget_extra(yyscanner)->arena,
YR_CODE_SECTION,
&instruction,
sizeof(uint8_t),
NULL);
return yr_arena_write_data(
yyget_extra(yyscanner)->code_arena,
&instruction,
sizeof(uint8_t),
(void**) instruction_address);
instruction_ref);
}
@@ -76,15 +70,15 @@ int yr_parser_emit_with_arg_double(
yyscan_t yyscanner,
uint8_t instruction,
double argument,
uint8_t** instruction_address,
double** argument_address)
YR_ARENA2_REFERENCE* instruction_ref,
YR_ARENA2_REFERENCE* argument_ref)
{
int result = yr_arena2_write_data(
yyget_extra(yyscanner)->arena,
YR_CODE_SECTION,
&instruction,
sizeof(uint8_t),
NULL);
instruction_ref);
if (result == ERROR_SUCCESS)
result = yr_arena2_write_data(
@@ -92,21 +86,33 @@ int yr_parser_emit_with_arg_double(
YR_CODE_SECTION,
&argument,
sizeof(double),
NULL);
argument_ref);
return result;
}
int yr_parser_emit_with_arg_int32(
yyscan_t yyscanner,
uint8_t instruction,
int32_t argument,
YR_ARENA2_REFERENCE* instruction_ref,
YR_ARENA2_REFERENCE* argument_ref)
{
int result = yr_arena2_write_data(
yyget_extra(yyscanner)->arena,
YR_CODE_SECTION,
&instruction,
sizeof(uint8_t),
instruction_ref);
if (result == ERROR_SUCCESS)
result = yr_arena_write_data(
yyget_extra(yyscanner)->code_arena,
&instruction,
sizeof(uint8_t),
(void**) instruction_address);
if (result == ERROR_SUCCESS)
result = yr_arena_write_data(
yyget_extra(yyscanner)->code_arena,
result = yr_arena2_write_data(
yyget_extra(yyscanner)->arena,
YR_CODE_SECTION,
&argument,
sizeof(double),
(void**) argument_address);
sizeof(int32_t),
argument_ref);
return result;
}
@@ -116,15 +122,15 @@ int yr_parser_emit_with_arg(
yyscan_t yyscanner,
uint8_t instruction,
int64_t argument,
uint8_t** instruction_address,
int64_t** argument_address)
YR_ARENA2_REFERENCE* instruction_ref,
YR_ARENA2_REFERENCE* argument_ref)
{
int result = yr_arena2_write_data(
yyget_extra(yyscanner)->arena,
YR_CODE_SECTION,
&instruction,
sizeof(uint8_t),
NULL);
instruction_ref);
if (result == ERROR_SUCCESS)
result = yr_arena2_write_data(
@@ -132,21 +138,7 @@ int yr_parser_emit_with_arg(
YR_CODE_SECTION,
&argument,
sizeof(int64_t),
NULL);
if (result == ERROR_SUCCESS)
result = yr_arena_write_data(
yyget_extra(yyscanner)->code_arena,
&instruction,
sizeof(uint8_t),
(void**) instruction_address);
if (result == ERROR_SUCCESS)
result = yr_arena_write_data(
yyget_extra(yyscanner)->code_arena,
&argument,
sizeof(int64_t),
(void**) argument_address);
argument_ref);
return result;
}
@@ -156,10 +148,10 @@ int yr_parser_emit_with_arg_reloc(
yyscan_t yyscanner,
uint8_t instruction,
void* argument,
uint8_t** instruction_address,
void** argument_address)
YR_ARENA2_REFERENCE* instruction_ref,
YR_ARENA2_REFERENCE* argument_ref)
{
int64_t* ptr = NULL;
YR_ARENA2_REFERENCE ref;
DECLARE_REFERENCE(void*, ptr) arg;
@@ -171,9 +163,7 @@ int yr_parser_emit_with_arg_reloc(
YR_CODE_SECTION,
&instruction,
sizeof(uint8_t),
NULL);
YR_ARENA2_REFERENCE ref;
instruction_ref);
if (result == ERROR_SUCCESS)
result = yr_arena2_write_data(
@@ -190,29 +180,8 @@ int yr_parser_emit_with_arg_reloc(
ref.offset,
EOL2);
if (result == ERROR_SUCCESS)
result = yr_arena_write_data(
yyget_extra(yyscanner)->code_arena,
&instruction,
sizeof(uint8_t),
(void**) instruction_address);
if (result == ERROR_SUCCESS)
result = yr_arena_write_data(
yyget_extra(yyscanner)->code_arena,
&arg,
sizeof(arg),
(void**) &ptr);
if (result == ERROR_SUCCESS)
result = yr_arena_make_ptr_relocatable(
yyget_extra(yyscanner)->code_arena,
ptr,
0,
EOL);
if (argument_address != NULL)
*argument_address = (void*) ptr;
if (argument_ref != NULL)
*argument_ref = ref;
return result;
}
@@ -521,6 +490,7 @@ static int _yr_parser_write_string(
result = yr_ac_add_string(
compiler->automaton,
string,
compiler->current_string_idx,
atom_list,
compiler->matches_arena);
}
@@ -886,7 +856,6 @@ int yr_parser_reduce_rule_declaration_phase_1(
YR_ARENA2_REFERENCE* rule_ref)
{
YR_FIXUP *fixup;
YR_INIT_RULE_ARGS *init_rule_args;
YR_COMPILER* compiler = yyget_extra(yyscanner);
YR_NAMESPACE* ns = (YR_NAMESPACE*) yr_arena2_get_ptr(
@@ -944,33 +913,36 @@ int yr_parser_reduce_rule_declaration_phase_1(
memset(rule->time_cost_per_thread, 0, sizeof(rule->time_cost_per_thread));
#endif
FAIL_ON_ERROR(yr_parser_emit(
YR_ARENA2_REFERENCE jmp_offset_ref;
// The OP_INIT_RULE instruction behaves like a jump. When the rule is disabled
// it skips over the rule's code and go straight to the next rule's code. The
// jmp_offset_ref variable points to the jump's offset. The offset is set to 0
// as we don't know the jump target yet. When we finish generating the rule's
// code in yr_parser_reduce_rule_declaration_phase_2 the jump offset is set to
// its final value.
FAIL_ON_ERROR(yr_parser_emit_with_arg_int32(
yyscanner,
OP_INIT_RULE,
0,
NULL,
&jmp_offset_ref));
FAIL_ON_ERROR(yr_arena2_write_data(
compiler->arena,
YR_CODE_SECTION,
&compiler->current_rule_idx,
sizeof(compiler->current_rule_idx),
NULL));
FAIL_ON_ERROR(yr_arena_allocate_struct(
compiler->code_arena,
sizeof(YR_INIT_RULE_ARGS),
(void**) &init_rule_args,
offsetof(YR_INIT_RULE_ARGS, jmp_addr),
EOL));
init_rule_args->rule_idx = compiler->current_rule_idx;
// jmp_addr holds the address to jump to when we want to skip the code for
// the rule. It is initialized as NULL at this point because we don't know
// the address until emitting the code for the rule's condition. The address
// is set in yr_parser_reduce_rule_declaration_phase_2.
init_rule_args->jmp_addr = NULL;
// Create a fixup entry for the jump and push it in the stack
fixup = (YR_FIXUP*) yr_malloc(sizeof(YR_FIXUP));
if (fixup == NULL)
return ERROR_INSUFFICIENT_MEMORY;
fixup->address = (void*) &(init_rule_args->jmp_addr);
fixup->ref = jmp_offset_ref;
fixup->next = compiler->fixup_stack_head;
compiler->fixup_stack_head = fixup;
@@ -992,9 +964,6 @@ int yr_parser_reduce_rule_declaration_phase_2(
{
uint32_t max_strings_per_rule;
uint32_t strings_in_rule = 0;
uint8_t* nop_inst_addr = NULL;
int result;
YR_FIXUP *fixup;
YR_STRING* string;
@@ -1046,25 +1015,25 @@ int yr_parser_reduce_rule_declaration_phase_2(
string++;
}
result = yr_parser_emit_with_arg(
FAIL_ON_ERROR(yr_parser_emit_with_arg(
yyscanner,
OP_MATCH_RULE,
compiler->current_rule_idx,
NULL,
NULL);
// Generate a do-nothing instruction (NOP) in order to get its address
// and use it as the destination for the OP_INIT_RULE skip jump. We can not
// simply use the address of the OP_MATCH_RULE instruction +1 because we
// can't be sure that the instruction following the OP_MATCH_RULE is going to
// be in the same arena page. As we don't have a reliable way of getting the
// address of the next instruction we generate the OP_NOP.
if (result == ERROR_SUCCESS)
result = yr_parser_emit(yyscanner, OP_NOP, &nop_inst_addr);
NULL));
fixup = compiler->fixup_stack_head;
*(void**)(fixup->address) = (void*) nop_inst_addr;
int32_t* jmp_offset_addr = yr_arena2_ref_to_ptr(
compiler->arena, &fixup->ref);
int32_t jmp_offset = \
yr_arena2_get_current_offset(compiler->arena, YR_CODE_SECTION) -
fixup->ref.offset + 1;
*jmp_offset_addr = jmp_offset;
// Remove fixup from the stack.
compiler->fixup_stack_head = fixup->next;
yr_free(fixup);
@@ -1072,7 +1041,7 @@ int yr_parser_reduce_rule_declaration_phase_2(
// a new one.
compiler->current_rule_idx++;
return result;
return ERROR_SUCCESS;
}