class TestDynldr

Public Instance Methods

cp() click to toggle source
# File tests/parse_c.rb, line 10
def cp
        @cp ||= Metasm::Ia32.new.new_cparser
end
d() click to toggle source
# File tests/dynldr.rb, line 10
def d; Metasm::DynLdr; end
test_allocstruct() click to toggle source
# File tests/parse_c.rb, line 176
        def test_allocstruct
cp.parse <<EOS
struct foo_outer {
        int i;
        struct {
                int j;
                int k;
        } inner;
};
EOS
                s = cp.alloc_c_struct('foo_outer', :i => :size)
                assert_equal(12, s.sizeof)
                assert_equal(12, s.i)
                assert_raise(RuntimeError) { s.l = 42 }
                assert_nothing_raised { s.j = 0x12345678 }
                assert_nothing_raised { s.inner.k = 0x3333_3333 }
                assert_equal(4, s.inner.stroff)
                assert_equal("0C0000007856341233333333", s.str.unpack('H*')[0].upcase)
        end
test_bitfields() click to toggle source
# File tests/parse_c.rb, line 123
        def test_bitfields
                cp.parse <<EOS
struct foo_bits {
        __int32 f0:4;
        __int32 :0;
        __int32 f1:4;
        __int32 f2:4;
        __int8  f3;
        __int32 f4:4;
        __int32 f5:30;
};

struct foo_n_bits {
        struct foo_bits;
};

struct foo2_bits {
        __int64 f0:30;
        __int64 f1:30;
        __int64 f2:30;
};

struct foo3_bits {
        __int16 f0:8;
        __int16 f1:4;
        __int16 f2:1;
};
EOS
                st = cp.toplevel.struct['foo_bits']
                assert_equal(20, cp.sizeof(st))
                assert_equal([0, 4], st.bitoffsetof(cp, 'f1'))
                assert_equal([4, 4], st.bitoffsetof(cp, 'f2'))
                assert_equal(8,  st.offsetof(cp, 'f3'))
                assert_equal(12,  st.offsetof(cp, 'f4'))
                assert_equal([0, 30],  st.bitoffsetof(cp, 'f5'))

                st = cp.toplevel.struct['foo_n_bits']
                assert_equal(20, cp.sizeof(st))
                assert_equal([0, 4], st.bitoffsetof(cp, 'f1'))
                assert_equal([4, 4], st.bitoffsetof(cp, 'f2'))
                assert_equal(8,  st.offsetof(cp, 'f3'))
                assert_equal(12,  st.offsetof(cp, 'f4'))
                assert_equal([0, 30],  st.bitoffsetof(cp, 'f5'))

                st = cp.toplevel.struct['foo2_bits']
                assert_equal([0, 30], st.bitoffsetof(cp, 'f0'))
                assert_equal([30, 30], st.bitoffsetof(cp, 'f1'))
                assert_equal([0, 30], st.bitoffsetof(cp, 'f2'))

                st = cp.toplevel.struct['foo3_bits']
                assert_equal(2, cp.sizeof(st))
        end
test_callback() click to toggle source
# File tests/dynldr.rb, line 42
def test_callback
        c1 = d.callback_alloc_c('int lol(int);') { |i| i+1 }
        c2 = d.callback_alloc_c('int lol(int);') { |i| i+2 }
        c3 = d.callback_alloc_c('int lol(int);') { |i| i/2 }

        d.new_func_c "int blop(int i, int (*fp)(int)) { return fp(i); }"
        
        assert_equal(2, d.blop(1, c1))
        assert_equal(4, d.blop(2, c2))
        assert_equal(6, d.blop(13, c3))
end
test_cmpstruct() click to toggle source
# File tests/parse_c.rb, line 196
        def test_cmpstruct
st = <<EOS
struct foo {
        struct foo *p;
        int i;
};

struct s1 {
        struct s2 *p;
};

struct s2 {
        struct s1 *p;
};
EOS
                cp.parse st
                cp.parse <<EOS
struct t1 {
        struct t2 *pt;
};
struct t2 {
        struct t1 *pt;
};
EOS

                cp2 = Metasm::Ia32.new.new_cparser
                cp2.parse(st)
                cp2.parse <<EOS
struct t1 {
        struct t2 *pt;
};
struct t2 {
        struct t3 *pt;
};
struct t3 {
        struct t1 *pt;
};
EOS
                assert_equal(true, cp.toplevel.struct['foo'] == cp2.toplevel.struct['foo'])
                assert_equal(true, cp.toplevel.struct['s1'].compare_deep(cp2.toplevel.struct['s1']))
                assert_equal(true, cp.toplevel.struct['t1'] == cp2.toplevel.struct['t1'])     # expected failure
                assert_equal(false, !!cp.toplevel.struct['t1'].compare_deep(cp2.toplevel.struct['t1']))
        end
test_new_api_c() click to toggle source
# File tests/dynldr.rb, line 12
def test_new_api_c
        str = "1234"
        d.new_api_c('int memcpy(char*, char*, int)')
        d.memcpy(str, "9999", 2)
        assert_equal('9934', str)
end
test_new_func_asm() click to toggle source
# File tests/dynldr.rb, line 34
def test_new_func_asm
        if d.host_cpu.shortname == 'ia32'
                ret = d.new_func_asm('int __fastcall bla(int)', "lea eax, [ecx+1]\nret") { d.bla(42) }
                assert_equal(43, ret)
                assert_equal(false, d.respond_to?(:bla))
        end
end
test_new_func_c() click to toggle source
# File tests/dynldr.rb, line 19
        def test_new_func_c
                c_src = <<EOS
int sprintf(char*, char*, ...);                 // stdlib external
void fufu(int i, char* ptr)
{
        static int meh;                                // .data
        meh = i;
        sprintf(ptr, "lolzor %i\\n", meh);     // string constant = .rodata
}
EOS
                buf = 'aaaaaaaaaaaaaaaaaa'
                d.new_func_c(c_src) { d.fufu(42, buf) }
                assert_equal("lolzor 42\n\000aaaaaaa", buf)
        end
test_parse_c() click to toggle source
# File tests/parse_c.rb, line 14
        def test_parse_c
                assert_nothing_raised {
                        cp.parse("static int i_1=42; __stdcall __int64 foo_1(const char*);")
                }

                assert_kind_of(Metasm::C::Function, cp.toplevel.symbol['foo_1'].type)

                assert_raise(Metasm::ParseError) { cp.parse("static extern int fu;") }
                cp.readtok until cp.eos?

                assert_nothing_raised { cp.parse("const volatile volatile const char const * const * blarg_0;") }

                assert_nothing_raised { cp.parse("void *ptr = &ptr;") }

                assert_raise(Metasm::ParseError) { cp.parse("void *ptr = ptr;") }
                cp.readtok until cp.eos?

                assert_nothing_raised { cp.parse("struct { int sz; } bla = { .sz = sizeof(bla) };") }

                assert_raise(Metasm::ParseError) { cp.parse("signed unsigned int fu;") }
                cp.readtok until cp.eos?

                assert_raise(Metasm::ParseError) { cp.parse("long long long fu;") }
                cp.readtok until cp.eos?

                assert_raise(Metasm::ParseError) { cp.parse("void badarg(int i, int i) {}") }
                cp.readtok until cp.eos?

                assert_raise(Metasm::ParseError) { cp.parse("struct strun; union strun;") }
                cp.readtok until cp.eos?

                assert_raise(Metasm::ParseError) { cp.parse "asm <<EOA
 foo
 EOA
" }
                cp.readtok until cp.eos?

                assert_nothing_raised { cp.parse "asm <<-EOA
 foo
 EOA
" }
        end
test_struct() click to toggle source
# File tests/parse_c.rb, line 59
        def test_struct
                cp.parse <<EOS
struct foo_2 {
        __int32 a;
        __int8 b;
        __int32 c;
        __int8 d;
};

struct foo_3 {
        __int8 a;
        __int8 b;
        __int16 c;
        __int32 d;
};

struct foo_4 {
        __int32 a;
        __int8 b;
        __int32 c;
        __int8 d;
} __attribute__((packed));

union foo_5 {
        __int64;
        struct {
                __int8;
                __int8*;
        };
        struct {
                __int16[8];
        };
};
EOS
                assert_equal(16, cp.sizeof(cp.toplevel.struct['foo_2']))
                assert_equal(8, cp.toplevel.struct['foo_2'].offsetof(cp, 'c'))
                assert_equal(8,  cp.sizeof(cp.toplevel.struct['foo_3']))
                assert_equal(10, cp.sizeof(cp.toplevel.struct['foo_4']))
                assert_equal(4, cp.toplevel.struct['foo_4'].offsetof(cp, 'b'))
                assert_equal(5, cp.toplevel.struct['foo_4'].offsetof(cp, 'c'))
                assert_equal(16, cp.sizeof(cp.toplevel.struct['foo_5']))

                assert_raise(Metasm::ParseError) { cp.parse("struct foo_3 { __int32 a; };") }
                cp.readtok until cp.eos?
                assert_nothing_raised { cp.parse("struct foo_3 { __int8 a; __int8 b; __int16 c; __int32 d; };") }

                assert_nothing_raised {
                        cp.parse <<EOS
struct scop { int i; };

void func1(void) {
        struct scop { __int64 j; __int64 z; };
        struct scop s;
        s.j = 0;
}

void func2(void) {
        struct scop s;
        s.i = 0;
}
EOS
                }
        end