def __seek__( cpu, mem, kernel, func_signature=FunctionType(IntegerType(SysCallLocation), ( AbstractDeclarator(IntegerType(SysCallLocation), SysCallLocation), AbstractDeclarator(IntegerType(SysCallLocation), SysCallLocation), AbstractDeclarator(IntegerType(SysCallLocation), SysCallLocation), ), SysCallLocation)): # int __seek__(int file_id, int offset, int whence); values = args(func_signature, cpu, mem) file_id, offset, whence = values return_value = Integer(-1, LocationNotSet) try: file_id = kernel.opened_files[file_id] file_id.seek(offset, whence) return_value = Integer(0, LocationNotSet) except KeyError as _: logger.warning( 'trying to fseek on non-opened file_id {f}'.format(f=file_id)) except Exception as ex: logger.warning('failed to fseek on file {f}, error: {m}'.format( f=getattr(file_id, 'name', file_id), m=ex)) __return__(return_value, cpu, mem, kernel)
def __write__( cpu, mem, kernel, func_signature=FunctionType( IntegerType(SysCallLocation), (AbstractDeclarator(IntegerType(SysCallLocation), SysCallLocation), AbstractDeclarator( PointerType(CharType(SysCallLocation), SysCallLocation), SysCallLocation), AbstractDeclarator( LongType(LongType(IntegerType(SysCallLocation), SysCallLocation), SysCallLocation, unsigned=True), SysCallLocation)), SysCallLocation)): # int __write__(int file_id, char *buffer, unsigned long long number_of_bytes); # // returns 0 on success or -1 on failure. values = args(func_signature, cpu, mem) file_id, buffer_ptr, number_of_bytes = values return_value = Integer(-1, LocationNotSet) values = ''.join(imap(chr, __buffer__(buffer_ptr, number_of_bytes, mem))) try: file_id = kernel.opened_files[int(file_id)] file_id.write(values) return_value = Integer(0, LocationNotSet) except KeyError as _: logger.warning( 'trying to write to a non-opened file_id {f}'.format(f=file_id)) except Exception as ex: logger.warning('failed to write to file {f}, error: {m}'.format( f=getattr(file_id, 'name', file_id), m=ex)) return_value = Integer(-1, LocationNotSet) __return__(return_value, cpu, mem, kernel)
def __close__( cpu, mem, kernel, func_signature=FunctionType( IntegerType(SysCallLocation), (AbstractDeclarator(IntegerType(SysCallLocation), SysCallLocation), ), SysCallLocation)): # int __close__(int); // returns 0 on success or -1 on failure # // returns 0 on success or -1 on failure. values = args(func_signature, cpu, mem) file_obj = file_id = next(values) return_value = Integer(-1, SysCallLocation) try: if file_id not in std_files: file_obj = kernel.opened_files.pop(file_id) file_obj.flush() file_obj.close() return_value = Integer(0, SysCallLocation) except KeyError as _: logger.warning( 'trying to close a non-opened file_id {f}'.format(f=file_id)) except Exception as ex: logger.warning('failed to close file {f}, error: {m}'.format(f=getattr( file_obj, 'name', file_obj), m=ex)) __return__(return_value, cpu, mem, kernel)
def numeric_operator(value, expr, symbol_table): return symbol_table['__ expression __']( BinaryExpression( ConstantExpression(value, IntegerType(loc(expr)), loc(expr)), TOKENS.STAR, exp(expr), max(c_type(exp(expr)), IntegerType(loc(expr)))(loc(expr)), loc(expr), ), symbol_table, )
def test_simple_declarations(self): code = """ int foo(int (*)(void *, int[1])); int a, b = 1, c = 5 + 5; """ decs = translation_unit(preprocess(tokenize(source(code)))) int_type = IntegerType('') exp_decls = [ Declaration( 'foo', FunctionType(int_type, [AbstractDeclarator(PointerType(FunctionType( int_type, [ AbstractDeclarator(PointerType(VoidType(''), ''), ''), AbstractDeclarator(ArrayType(int_type, 1, ''), ''), ], '', ), ''), '')], ''), '', ), Declaration('a', int_type, ''), Definition('b', int_type, ConstantExpression(1, int_type, ''), '', None), Definition('c', int_type, ConstantExpression(10, int_type, ''), '', None) ] for got_dec, exp_dec in izip(decs, exp_decls): self.assertEqual(got_dec, exp_dec)
def patch_comp_assignment(instrs, expr_type, location): # At this point the stack contains the Address followed by the calculated value ... # we need to swap them and call set, but we mut be careful that both have the same size before calling swap # or we could corrupt the value ... if size(expr_type) == size(void_pointer_type): # result type and pointer type (address) equal no alignment required return chain(instrs, set_instr(swap(size(void_pointer_type), location), size(void_pointer_type), location)) if size(expr_type) < size(void_pointer_type): # size of result type is less than address we need to align if isinstance(expr_type, DoubleType): # since we are using cast to the alignment we need too interpret assert size(double_type) == size(long_type) # result type as integral type for casting may change value expr_type = LongType(location, unsigned=True) elif isinstance(expr_type, FloatType): assert size(float_type) == size(integer_type) expr_type = IntegerType(location, unsigned=True) return cast( # convert the value back to its original size removing any alignment added bytes after set ... set_instr( # set values assuming little endian architecture TODO: check on that assertion! chain(cast(instrs, expr_type, void_pointer_type, location), swap(size(void_pointer_type), location)), size(expr_type), # if sizes differ, cast value to pointer type extending bytes, and swap location ), void_pointer_type, expr_type, location ) else: raise ValueError('{l} unable to patch compound assignment value size {s} exceeds address size {a}'.format( l=location, s=size(expr_type), a=size(void_pointer_type) ))
def __open__(cpu, mem, kernel, func_signature=FunctionType(IntegerType(SysCallLocation), ( AbstractDeclarator( PointerType(CharType(SysCallLocation), SysCallLocation), SysCallLocation), AbstractDeclarator( PointerType(CharType(SysCallLocation), SysCallLocation), SysCallLocation), ), SysCallLocation)): # int __open__(const char * file_path, const char *mode); // returns file_id on success or -1 of failure. values = args(func_signature, cpu, mem) file_id = Integer(-1, LocationNotSet) file_path_ptr, file_mode_ptr = values file_mode = __str__(file_mode_ptr, mem) if file_path_ptr in std_files: file_id = file_path_ptr else: file_name = __str__(file_path_ptr, mem) try: file_obj = open(file_name, file_mode) file_id = file_obj.fileno() kernel.opened_files[file_id] = file_obj except Exception as ex: logger.warning('failed to open file {f}, error: {m}'.format( f=file_name, m=ex)) __return__(file_id, cpu, mem, kernel)
def specifier_qualifier_list(tokens, symbol_table): const, volatile = type_qualifiers(tokens, symbol_table, (False, False)) base_type = type_specifier(tokens, symbol_table, IntegerType(loc(peek(tokens, EOFLocation)))) base_type.const, base_type.volatile = type_qualifiers( tokens, symbol_table, (const, volatile)) return base_type
def get_type(suffix_str, location): _type, _eval = IntegerType(location, unsigned=unsigned_suffix in suffix_str), int _type, _eval = (long_suffix in suffix_str and LongType( _type, loc(_type), unsigned(_type))) or _type, long _type, _eval = (long_long_suffix in suffix_str and LongType( _type, loc(_type), unsigned(_type))) or _type, long return _type, _eval
def test_bitwise_not(self): source = """ { int a = -10; a = ~a; } """ self.evaluate(source) self.assert_base_element(ConstantExpression(9, IntegerType()))
def __init__(self, exp, operator, ctype, location=LocationNotSet): super(IncDecExpr, self).__init__( exp, operator, ConstantExpression(1, IntegerType(location, unsigned=unsigned(ctype)), location), ctype, location) ExpressionNode.__init__( self, exp, ctype, location) # CompoundAssignment uses itself as exp
def test_plus(self): source = """ { int a = 10; a = +a; } """ self.evaluate(source) self.assert_base_element(ConstantExpression(10, IntegerType()))
def inc_dec(value, expr, symbol_table): return symbol_table['__ expression __']( CompoundAssignmentExpression( exp(expr), TOKENS.PLUS_EQUAL, ConstantExpression( value, IntegerType(loc(expr), unsigned=unsigned(c_type(expr))), loc(expr)), c_type(expr)(loc(expr)), loc(expr)), symbol_table, )
def test_address_of(self): source = """ { int a = 10; int *b = &a; a = (unsigned long long)&a - (unsigned long long)b; } """ self.evaluate(source) self.assert_base_element(ConstantExpression(0, IntegerType()))
def test_decrement(self): source = """ { int a = 10; int b = a--; a = b - a; } """ self.evaluate(source) self.assert_base_element(ConstantExpression(1, IntegerType()))
def test_increment(self): source = """ { int a = 10; int b = ++a; a = a - b; } """ self.evaluate(source) self.assert_base_element(ConstantExpression(0, IntegerType()))
def test_dereference(self): source = """ { int a = 10; int *b = &a; *b = 9; } """ self.evaluate(source) self.assert_base_element(ConstantExpression(9, IntegerType()))
def __return__(value, cpu, mem, os, func_signature=FunctionType(IntegerType(SysCallLocation), (), SysCallLocation)): cpu.instr_pointer = mem[cpu.base_pointer + word_size] # get return instruction ... assert size(c_type(c_type(func_signature))) == word_size mem[cpu.base_pointer + 2 * word_size] = value
def test_two_d_array(self): source = """ { int b; int a[5][3]; a[2][2] = 5; b = a[2][2]; } """ self.evaluate(source) self.assert_base_element(ConstantExpression(5, IntegerType()))
def test_function_pointer(self): source = """ int foo(int value){ return value + 1; } int main() { int (*foo_fp)(int) = &foo; return foo_fp(10); } """ self.evaluate(source) self.assert_base_element(ConstantExpression(11, IntegerType()))
def test_function_return(self): source = """ int a; int foo1(int a1) { return a1; } double foo(int a2, double a3) { return a2; } int main() { return foo(foo1(11), 10); } """ self.evaluate(source) self.assert_base_element(ConstantExpression(11, IntegerType()))
def test_function_call_parameters(self): source = """ int a; void foo(int a1){ a = a1; } int main() { foo(10); return a; } """ self.evaluate(source) self.assert_base_element(ConstantExpression(10, IntegerType()))
def __exit__( cpu, mem, kernel, func_signature=FunctionType(VoidType(SysCallLocation), (AbstractDeclarator( IntegerType(SysCallLocation), SysCallLocation), ), SysCallLocation)): # void exit(int return_value); value, = args(func_signature, cpu, mem) # Flush and close all opened files except stdio for file_id in ifilter(lambda file_id: file_id not in dict(std_files), kernel.opened_files): kernel.opened_files[file_id].flush() kernel.opened_files[file_id].close() mem[-size(IntegerType() )] = value # Set the return status on top of the stack cpu.base_pointer = cpu.stack_pointer = push_integral.core_type( -word_size) # reset stack/base pointers ... mem[cpu.instr_pointer + word_size] = Halt( SysCallLocation) # Halt machine ...
def __tell__( cpu, mem, kernel, func_signature=FunctionType( IntegerType(SysCallLocation), (AbstractDeclarator(IntegerType(SysCallLocation), SysCallLocation), ), SysCallLocation)): # int __tell__(int); values = args(func_signature, cpu, mem) return_value = Integer(-1, LocationNotSet) file_id, = values try: file_id = kernel.opened_files[file_id] return_value = Integer(file_id.tell(), LocationNotSet) except KeyError as _: logger.warning( 'trying to ftell on a non-opened file_id {f}'.format(f=file_id)) except Exception as ex: logger.warning('failed to ftell on file {f}, error: {m}'.format( f=getattr(file_id, 'name', file_id), m=ex)) __return__(return_value, cpu, mem, kernel)
def __read__( cpu, mem, kernel, func_signature=FunctionType( IntegerType(SysCallLocation), (AbstractDeclarator(IntegerType(SysCallLocation), SysCallLocation), AbstractDeclarator( PointerType(CharType(SysCallLocation), SysCallLocation), SysCallLocation), AbstractDeclarator( LongType( LongType(IntegerType(SysCallLocation), SysCallLocation, unsigned=True), SysCallLocation), SysCallLocation)), SysCallLocation)): # int __read__(int file_id, char *dest, unsigned long long number_of_bytes); # // returns the number of elements read on success or -1 on failure values = args(func_signature, cpu, mem) file_id, dest_ptr, number_of_bytes = values return_value = Integer(-1, LocationNotSet) try: file_id = kernel.opened_files[file_id] values = file_id.read(number_of_bytes) for addr, value in izip(xrange(dest_ptr, dest_ptr + len(values)), imap(ord, values)): mem[addr] = Byte(value, LocationNotSet) return_value = Integer(len(values), LocationNotSet) except KeyError as _: logger.warning( 'trying to read from a non-opened file_id {f}'.format(f=file_id)) except Exception as ex: logger.warning('failed to read from file {f}, error: {m}'.format( f=getattr(file_id, 'name', file_id), m=ex)) __return__(return_value, cpu, mem, kernel)
def test_array_subscript(self): source = """ { int b; int a[10]; int c = 1; a[2] = 10; b = a[2]; a[0] = -1; a[9] = -1; b = b - c; } """ self.evaluate(source) self.assert_base_element(ConstantExpression(9, IntegerType()))
def test_function_struct_return(self): source = """ int a; struct foo {int a; char b[10]; double v;}; struct foo test(char f) { struct foo c; c.b[2] = f; return c; } int main() { struct foo v = test('a'); return v.b[2]; } """ self.evaluate(source) self.assert_base_element(ConstantExpression(ord('a'), IntegerType()))
def test_nested_struct_member_selection(self): source = """ { int value; struct foo { int a; struct foo2 { double b; char g[10]; } n; char e; } a, b; double c, d; a.n.g[2] = 'a'; value = a.n.g[2]; } """ self.evaluate(source) self.assert_base_element(ConstantExpression(ord('a'), IntegerType()))
def parse_enum_members(tokens, symbol_table): constant_expression = symbol_table['__ constant_expression __'] location, members, current_value = loc(consume(tokens)), OrderedDict(), 0 while peek(tokens, TOKENS.RIGHT_BRACE) != TOKENS.RIGHT_BRACE: ident = error_if_not_type(consume(tokens, ''), IDENTIFIER) value = ConstantExpression(current_value, IntegerType(location), location) if peek_or_terminal(tokens) == TOKENS.EQUAL and consume(tokens): value = constant_expression(tokens, symbol_table) _ = error_if_not_type(c_type(value), IntegerType) current_value = error_if_not_type(exp(value), (int, long)) symbol_table[ident] = value # Add value to symbol_table members[ident] = Definition(ident, c_type(value), value, location) _ = peek_or_terminal(tokens) == TOKENS.COMMA and consume(tokens) _ = error_if_not_value(tokens, TOKENS.RIGHT_BRACE) return members
def test_struct_member_selection_pointer(self): source = """ { int value; struct foo { int a; struct foo2 { char a; int g[10]; double c; } *b, c; char d; } a, *b; int d; a.b = &a.c; b = &a; b->b->g[2] = 10; value = b->b->g[2]; } """ self.evaluate(source) self.assert_base_element(ConstantExpression(10, IntegerType()))