mirror of
https://github.com/VirusTotal/yara.git
synced 2026-10-12 02:10:00 +00:00
Move code to new arena.
This commit is contained in:
+18
-4
@@ -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");
|
||||
}
|
||||
*/
|
||||
@@ -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
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
+83
-59
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user