metasm 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/BUGS +11 -0
- data/CREDITS +17 -0
- data/README +270 -0
- data/TODO +114 -0
- data/doc/code_organisation.txt +146 -0
- data/doc/const_missing.txt +16 -0
- data/doc/core_classes.txt +75 -0
- data/doc/feature_list.txt +53 -0
- data/doc/index.txt +59 -0
- data/doc/install_notes.txt +170 -0
- data/doc/style.css +3 -0
- data/doc/use_cases.txt +18 -0
- data/lib/metasm.rb +80 -0
- data/lib/metasm/arm.rb +12 -0
- data/lib/metasm/arm/debug.rb +39 -0
- data/lib/metasm/arm/decode.rb +167 -0
- data/lib/metasm/arm/encode.rb +77 -0
- data/lib/metasm/arm/main.rb +75 -0
- data/lib/metasm/arm/opcodes.rb +177 -0
- data/lib/metasm/arm/parse.rb +130 -0
- data/lib/metasm/arm/render.rb +55 -0
- data/lib/metasm/compile_c.rb +1457 -0
- data/lib/metasm/dalvik.rb +8 -0
- data/lib/metasm/dalvik/decode.rb +196 -0
- data/lib/metasm/dalvik/main.rb +60 -0
- data/lib/metasm/dalvik/opcodes.rb +366 -0
- data/lib/metasm/decode.rb +213 -0
- data/lib/metasm/decompile.rb +2659 -0
- data/lib/metasm/disassemble.rb +2068 -0
- data/lib/metasm/disassemble_api.rb +1280 -0
- data/lib/metasm/dynldr.rb +1329 -0
- data/lib/metasm/encode.rb +333 -0
- data/lib/metasm/exe_format/a_out.rb +194 -0
- data/lib/metasm/exe_format/autoexe.rb +82 -0
- data/lib/metasm/exe_format/bflt.rb +189 -0
- data/lib/metasm/exe_format/coff.rb +455 -0
- data/lib/metasm/exe_format/coff_decode.rb +901 -0
- data/lib/metasm/exe_format/coff_encode.rb +1078 -0
- data/lib/metasm/exe_format/dex.rb +457 -0
- data/lib/metasm/exe_format/dol.rb +145 -0
- data/lib/metasm/exe_format/elf.rb +923 -0
- data/lib/metasm/exe_format/elf_decode.rb +979 -0
- data/lib/metasm/exe_format/elf_encode.rb +1375 -0
- data/lib/metasm/exe_format/macho.rb +827 -0
- data/lib/metasm/exe_format/main.rb +228 -0
- data/lib/metasm/exe_format/mz.rb +164 -0
- data/lib/metasm/exe_format/nds.rb +172 -0
- data/lib/metasm/exe_format/pe.rb +437 -0
- data/lib/metasm/exe_format/serialstruct.rb +246 -0
- data/lib/metasm/exe_format/shellcode.rb +114 -0
- data/lib/metasm/exe_format/xcoff.rb +167 -0
- data/lib/metasm/gui.rb +23 -0
- data/lib/metasm/gui/cstruct.rb +373 -0
- data/lib/metasm/gui/dasm_coverage.rb +199 -0
- data/lib/metasm/gui/dasm_decomp.rb +369 -0
- data/lib/metasm/gui/dasm_funcgraph.rb +103 -0
- data/lib/metasm/gui/dasm_graph.rb +1354 -0
- data/lib/metasm/gui/dasm_hex.rb +543 -0
- data/lib/metasm/gui/dasm_listing.rb +599 -0
- data/lib/metasm/gui/dasm_main.rb +906 -0
- data/lib/metasm/gui/dasm_opcodes.rb +291 -0
- data/lib/metasm/gui/debug.rb +1228 -0
- data/lib/metasm/gui/gtk.rb +884 -0
- data/lib/metasm/gui/qt.rb +495 -0
- data/lib/metasm/gui/win32.rb +3004 -0
- data/lib/metasm/gui/x11.rb +621 -0
- data/lib/metasm/ia32.rb +14 -0
- data/lib/metasm/ia32/compile_c.rb +1523 -0
- data/lib/metasm/ia32/debug.rb +193 -0
- data/lib/metasm/ia32/decode.rb +1167 -0
- data/lib/metasm/ia32/decompile.rb +564 -0
- data/lib/metasm/ia32/encode.rb +314 -0
- data/lib/metasm/ia32/main.rb +233 -0
- data/lib/metasm/ia32/opcodes.rb +872 -0
- data/lib/metasm/ia32/parse.rb +327 -0
- data/lib/metasm/ia32/render.rb +91 -0
- data/lib/metasm/main.rb +1193 -0
- data/lib/metasm/mips.rb +11 -0
- data/lib/metasm/mips/compile_c.rb +7 -0
- data/lib/metasm/mips/decode.rb +253 -0
- data/lib/metasm/mips/encode.rb +51 -0
- data/lib/metasm/mips/main.rb +72 -0
- data/lib/metasm/mips/opcodes.rb +443 -0
- data/lib/metasm/mips/parse.rb +51 -0
- data/lib/metasm/mips/render.rb +43 -0
- data/lib/metasm/os/gnu_exports.rb +270 -0
- data/lib/metasm/os/linux.rb +1112 -0
- data/lib/metasm/os/main.rb +1686 -0
- data/lib/metasm/os/remote.rb +527 -0
- data/lib/metasm/os/windows.rb +2027 -0
- data/lib/metasm/os/windows_exports.rb +745 -0
- data/lib/metasm/parse.rb +876 -0
- data/lib/metasm/parse_c.rb +3938 -0
- data/lib/metasm/pic16c/decode.rb +42 -0
- data/lib/metasm/pic16c/main.rb +17 -0
- data/lib/metasm/pic16c/opcodes.rb +68 -0
- data/lib/metasm/ppc.rb +11 -0
- data/lib/metasm/ppc/decode.rb +264 -0
- data/lib/metasm/ppc/decompile.rb +251 -0
- data/lib/metasm/ppc/encode.rb +51 -0
- data/lib/metasm/ppc/main.rb +129 -0
- data/lib/metasm/ppc/opcodes.rb +410 -0
- data/lib/metasm/ppc/parse.rb +52 -0
- data/lib/metasm/preprocessor.rb +1277 -0
- data/lib/metasm/render.rb +130 -0
- data/lib/metasm/sh4.rb +8 -0
- data/lib/metasm/sh4/decode.rb +336 -0
- data/lib/metasm/sh4/main.rb +292 -0
- data/lib/metasm/sh4/opcodes.rb +381 -0
- data/lib/metasm/x86_64.rb +12 -0
- data/lib/metasm/x86_64/compile_c.rb +1025 -0
- data/lib/metasm/x86_64/debug.rb +59 -0
- data/lib/metasm/x86_64/decode.rb +268 -0
- data/lib/metasm/x86_64/encode.rb +264 -0
- data/lib/metasm/x86_64/main.rb +135 -0
- data/lib/metasm/x86_64/opcodes.rb +118 -0
- data/lib/metasm/x86_64/parse.rb +68 -0
- data/misc/bottleneck.rb +61 -0
- data/misc/cheader-findpppath.rb +58 -0
- data/misc/hexdiff.rb +74 -0
- data/misc/hexdump.rb +55 -0
- data/misc/metasm-all.rb +13 -0
- data/misc/objdiff.rb +47 -0
- data/misc/objscan.rb +40 -0
- data/misc/pdfparse.rb +661 -0
- data/misc/ppc_pdf2oplist.rb +192 -0
- data/misc/tcp_proxy_hex.rb +84 -0
- data/misc/txt2html.rb +440 -0
- data/samples/a.out.rb +31 -0
- data/samples/asmsyntax.rb +77 -0
- data/samples/bindiff.rb +555 -0
- data/samples/compilation-steps.rb +49 -0
- data/samples/cparser_makestackoffset.rb +55 -0
- data/samples/dasm-backtrack.rb +38 -0
- data/samples/dasmnavig.rb +318 -0
- data/samples/dbg-apihook.rb +228 -0
- data/samples/dbghelp.rb +143 -0
- data/samples/disassemble-gui.rb +102 -0
- data/samples/disassemble.rb +133 -0
- data/samples/dump_upx.rb +95 -0
- data/samples/dynamic_ruby.rb +1929 -0
- data/samples/elf_list_needed.rb +46 -0
- data/samples/elf_listexports.rb +33 -0
- data/samples/elfencode.rb +25 -0
- data/samples/exeencode.rb +128 -0
- data/samples/factorize-headers-elfimports.rb +77 -0
- data/samples/factorize-headers-peimports.rb +109 -0
- data/samples/factorize-headers.rb +43 -0
- data/samples/gdbclient.rb +583 -0
- data/samples/generate_libsigs.rb +102 -0
- data/samples/hotfix_gtk_dbg.rb +59 -0
- data/samples/install_win_env.rb +78 -0
- data/samples/lindebug.rb +924 -0
- data/samples/linux_injectsyscall.rb +95 -0
- data/samples/machoencode.rb +31 -0
- data/samples/metasm-shell.rb +91 -0
- data/samples/pe-hook.rb +69 -0
- data/samples/pe-ia32-cpuid.rb +203 -0
- data/samples/pe-mips.rb +35 -0
- data/samples/pe-shutdown.rb +78 -0
- data/samples/pe-testrelocs.rb +51 -0
- data/samples/pe-testrsrc.rb +24 -0
- data/samples/pe_listexports.rb +31 -0
- data/samples/peencode.rb +19 -0
- data/samples/peldr.rb +494 -0
- data/samples/preprocess-flatten.rb +19 -0
- data/samples/r0trace.rb +308 -0
- data/samples/rubstop.rb +399 -0
- data/samples/scan_pt_gnu_stack.rb +54 -0
- data/samples/scanpeexports.rb +62 -0
- data/samples/shellcode-c.rb +40 -0
- data/samples/shellcode-dynlink.rb +146 -0
- data/samples/source.asm +34 -0
- data/samples/struct_offset.rb +47 -0
- data/samples/testpe.rb +32 -0
- data/samples/testraw.rb +45 -0
- data/samples/win32genloader.rb +132 -0
- data/samples/win32hooker-advanced.rb +169 -0
- data/samples/win32hooker.rb +96 -0
- data/samples/win32livedasm.rb +33 -0
- data/samples/win32remotescan.rb +133 -0
- data/samples/wintrace.rb +92 -0
- data/tests/all.rb +8 -0
- data/tests/dasm.rb +39 -0
- data/tests/dynldr.rb +35 -0
- data/tests/encodeddata.rb +132 -0
- data/tests/ia32.rb +82 -0
- data/tests/mips.rb +116 -0
- data/tests/parse_c.rb +239 -0
- data/tests/preprocessor.rb +269 -0
- data/tests/x86_64.rb +62 -0
- metadata +255 -0
data/tests/parse_c.rb
ADDED
@@ -0,0 +1,239 @@
|
|
1
|
+
# This file is part of Metasm, the Ruby assembly manipulation suite
|
2
|
+
# Copyright (C) 2006-2009 Yoann GUILLOT
|
3
|
+
#
|
4
|
+
# Licence is LGPL, see LICENCE in the top-level directory
|
5
|
+
|
6
|
+
require 'test/unit'
|
7
|
+
require 'metasm'
|
8
|
+
|
9
|
+
class TestDynldr < Test::Unit::TestCase
|
10
|
+
def cp
|
11
|
+
@cp ||= Metasm::Ia32.new.new_cparser
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_parse_c
|
15
|
+
assert_nothing_raised {
|
16
|
+
cp.parse("static int i_1=42; __stdcall __int64 foo_1(const char*);")
|
17
|
+
}
|
18
|
+
|
19
|
+
assert_kind_of(Metasm::C::Function, cp.toplevel.symbol['foo_1'].type)
|
20
|
+
|
21
|
+
assert_raise(Metasm::ParseError) { cp.parse("static extern int fu;") }
|
22
|
+
cp.readtok until cp.eos?
|
23
|
+
|
24
|
+
assert_nothing_raised { cp.parse("const volatile volatile const char const * const * blarg_0;") }
|
25
|
+
|
26
|
+
assert_nothing_raised { cp.parse("void *ptr = &ptr;") }
|
27
|
+
|
28
|
+
assert_raise(Metasm::ParseError) { cp.parse("void *ptr = ptr;") }
|
29
|
+
cp.readtok until cp.eos?
|
30
|
+
|
31
|
+
assert_nothing_raised { cp.parse("struct { int sz; } bla = { .sz = sizeof(bla) };") }
|
32
|
+
|
33
|
+
assert_raise(Metasm::ParseError) { cp.parse("signed unsigned int fu;") }
|
34
|
+
cp.readtok until cp.eos?
|
35
|
+
|
36
|
+
assert_raise(Metasm::ParseError) { cp.parse("long long long fu;") }
|
37
|
+
cp.readtok until cp.eos?
|
38
|
+
|
39
|
+
assert_raise(Metasm::ParseError) { cp.parse("void badarg(int i, int i) {}") }
|
40
|
+
cp.readtok until cp.eos?
|
41
|
+
|
42
|
+
assert_raise(Metasm::ParseError) { cp.parse("struct strun; union strun;") }
|
43
|
+
cp.readtok until cp.eos?
|
44
|
+
|
45
|
+
assert_raise(Metasm::ParseError) { cp.parse <<EOS }
|
46
|
+
asm <<EOA
|
47
|
+
foo
|
48
|
+
EOA
|
49
|
+
EOS
|
50
|
+
cp.readtok until cp.eos?
|
51
|
+
|
52
|
+
assert_nothing_raised { cp.parse <<EOS }
|
53
|
+
asm <<-EOA
|
54
|
+
foo
|
55
|
+
EOA
|
56
|
+
EOS
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_struct
|
60
|
+
cp.parse <<EOS
|
61
|
+
struct foo_2 {
|
62
|
+
__int32 a;
|
63
|
+
__int8 b;
|
64
|
+
__int32 c;
|
65
|
+
__int8 d;
|
66
|
+
};
|
67
|
+
|
68
|
+
struct foo_3 {
|
69
|
+
__int8 a;
|
70
|
+
__int8 b;
|
71
|
+
__int16 c;
|
72
|
+
__int32 d;
|
73
|
+
};
|
74
|
+
|
75
|
+
struct foo_4 {
|
76
|
+
__int32 a;
|
77
|
+
__int8 b;
|
78
|
+
__int32 c;
|
79
|
+
__int8 d;
|
80
|
+
} __attribute__((packed));
|
81
|
+
|
82
|
+
union foo_5 {
|
83
|
+
__int64;
|
84
|
+
struct {
|
85
|
+
__int8;
|
86
|
+
__int8*;
|
87
|
+
};
|
88
|
+
struct {
|
89
|
+
__int16[8];
|
90
|
+
};
|
91
|
+
};
|
92
|
+
EOS
|
93
|
+
assert_equal(16, cp.sizeof(cp.toplevel.struct['foo_2']))
|
94
|
+
assert_equal(8, cp.toplevel.struct['foo_2'].offsetof(cp, 'c'))
|
95
|
+
assert_equal(8, cp.sizeof(cp.toplevel.struct['foo_3']))
|
96
|
+
assert_equal(10, cp.sizeof(cp.toplevel.struct['foo_4']))
|
97
|
+
assert_equal(4, cp.toplevel.struct['foo_4'].offsetof(cp, 'b'))
|
98
|
+
assert_equal(5, cp.toplevel.struct['foo_4'].offsetof(cp, 'c'))
|
99
|
+
assert_equal(16, cp.sizeof(cp.toplevel.struct['foo_5']))
|
100
|
+
|
101
|
+
assert_raise(Metasm::ParseError) { cp.parse("struct foo_3 { __int32 a; };") }
|
102
|
+
cp.readtok until cp.eos?
|
103
|
+
assert_nothing_raised { cp.parse("struct foo_3 { __int8 a; __int8 b; __int16 c; __int32 d; };") }
|
104
|
+
|
105
|
+
assert_nothing_raised {
|
106
|
+
cp.parse <<EOS
|
107
|
+
struct scop { int i; };
|
108
|
+
|
109
|
+
void func1(void) {
|
110
|
+
struct scop { __int64 j; __int64 z; };
|
111
|
+
struct scop s;
|
112
|
+
s.j = 0;
|
113
|
+
}
|
114
|
+
|
115
|
+
void func2(void) {
|
116
|
+
struct scop s;
|
117
|
+
s.i = 0;
|
118
|
+
}
|
119
|
+
EOS
|
120
|
+
}
|
121
|
+
end
|
122
|
+
|
123
|
+
def test_bitfields
|
124
|
+
cp.parse <<EOS
|
125
|
+
struct foo_bits {
|
126
|
+
__int32 f0:4;
|
127
|
+
__int32 :0;
|
128
|
+
__int32 f1:4;
|
129
|
+
__int32 f2:4;
|
130
|
+
__int8 f3;
|
131
|
+
__int32 f4:4;
|
132
|
+
__int32 f5:30;
|
133
|
+
};
|
134
|
+
|
135
|
+
struct foo_n_bits {
|
136
|
+
struct foo_bits;
|
137
|
+
};
|
138
|
+
|
139
|
+
struct foo2_bits {
|
140
|
+
__int64 f0:30;
|
141
|
+
__int64 f1:30;
|
142
|
+
__int64 f2:30;
|
143
|
+
};
|
144
|
+
|
145
|
+
struct foo3_bits {
|
146
|
+
__int16 f0:8;
|
147
|
+
__int16 f1:4;
|
148
|
+
__int16 f2:1;
|
149
|
+
};
|
150
|
+
EOS
|
151
|
+
st = cp.toplevel.struct['foo_bits']
|
152
|
+
assert_equal(20, cp.sizeof(st))
|
153
|
+
assert_equal([0, 4], st.bitoffsetof(cp, 'f1'))
|
154
|
+
assert_equal([4, 4], st.bitoffsetof(cp, 'f2'))
|
155
|
+
assert_equal(8, st.offsetof(cp, 'f3'))
|
156
|
+
assert_equal(12, st.offsetof(cp, 'f4'))
|
157
|
+
assert_equal([0, 30], st.bitoffsetof(cp, 'f5'))
|
158
|
+
|
159
|
+
st = cp.toplevel.struct['foo_n_bits']
|
160
|
+
assert_equal(20, cp.sizeof(st))
|
161
|
+
assert_equal([0, 4], st.bitoffsetof(cp, 'f1'))
|
162
|
+
assert_equal([4, 4], st.bitoffsetof(cp, 'f2'))
|
163
|
+
assert_equal(8, st.offsetof(cp, 'f3'))
|
164
|
+
assert_equal(12, st.offsetof(cp, 'f4'))
|
165
|
+
assert_equal([0, 30], st.bitoffsetof(cp, 'f5'))
|
166
|
+
|
167
|
+
st = cp.toplevel.struct['foo2_bits']
|
168
|
+
assert_equal([0, 30], st.bitoffsetof(cp, 'f0'))
|
169
|
+
assert_equal([30, 30], st.bitoffsetof(cp, 'f1'))
|
170
|
+
assert_equal([0, 30], st.bitoffsetof(cp, 'f2'))
|
171
|
+
|
172
|
+
st = cp.toplevel.struct['foo3_bits']
|
173
|
+
assert_equal(2, cp.sizeof(st))
|
174
|
+
end
|
175
|
+
|
176
|
+
def test_allocstruct
|
177
|
+
cp.parse <<EOS
|
178
|
+
struct foo_outer {
|
179
|
+
int i;
|
180
|
+
struct {
|
181
|
+
int j;
|
182
|
+
int k;
|
183
|
+
} inner;
|
184
|
+
};
|
185
|
+
EOS
|
186
|
+
s = cp.alloc_c_struct('foo_outer', :i => :size)
|
187
|
+
assert_equal(12, s.sizeof)
|
188
|
+
assert_equal(12, s.i)
|
189
|
+
assert_raise(RuntimeError) { s.l = 42 }
|
190
|
+
assert_nothing_raised { s.j = 0x12345678 }
|
191
|
+
assert_nothing_raised { s.inner.k = 0x3333_3333 }
|
192
|
+
assert_equal(4, s.inner.stroff)
|
193
|
+
assert_equal("0C0000007856341233333333", s.str.unpack('H*')[0].upcase)
|
194
|
+
end
|
195
|
+
|
196
|
+
def test_cmpstruct
|
197
|
+
st = <<EOS
|
198
|
+
struct foo {
|
199
|
+
struct foo *p;
|
200
|
+
int i;
|
201
|
+
};
|
202
|
+
|
203
|
+
struct s1 {
|
204
|
+
struct s2 *p;
|
205
|
+
};
|
206
|
+
|
207
|
+
struct s2 {
|
208
|
+
struct s1 *p;
|
209
|
+
};
|
210
|
+
EOS
|
211
|
+
cp.parse st
|
212
|
+
cp.parse <<EOS
|
213
|
+
struct t1 {
|
214
|
+
struct t2 *pt;
|
215
|
+
};
|
216
|
+
struct t2 {
|
217
|
+
struct t1 *pt;
|
218
|
+
};
|
219
|
+
EOS
|
220
|
+
|
221
|
+
cp2 = Metasm::Ia32.new.new_cparser
|
222
|
+
cp2.parse(st)
|
223
|
+
cp2.parse <<EOS
|
224
|
+
struct t1 {
|
225
|
+
struct t2 *pt;
|
226
|
+
};
|
227
|
+
struct t2 {
|
228
|
+
struct t3 *pt;
|
229
|
+
};
|
230
|
+
struct t3 {
|
231
|
+
struct t1 *pt;
|
232
|
+
};
|
233
|
+
EOS
|
234
|
+
assert_equal(true, cp.toplevel.struct['foo'] == cp2.toplevel.struct['foo'])
|
235
|
+
assert_equal(true, cp.toplevel.struct['s1'].compare_deep(cp2.toplevel.struct['s1']))
|
236
|
+
assert_equal(true, cp.toplevel.struct['t1'] == cp2.toplevel.struct['t1']) # expected failure
|
237
|
+
assert_equal(false, !!cp.toplevel.struct['t1'].compare_deep(cp2.toplevel.struct['t1']))
|
238
|
+
end
|
239
|
+
end
|
@@ -0,0 +1,269 @@
|
|
1
|
+
# This file is part of Metasm, the Ruby assembly manipulation suite
|
2
|
+
# Copyright (C) 2006-2009 Yoann GUILLOT
|
3
|
+
#
|
4
|
+
# Licence is LGPL, see LICENCE in the top-level directory
|
5
|
+
|
6
|
+
|
7
|
+
require 'test/unit'
|
8
|
+
require 'metasm/preprocessor'
|
9
|
+
require 'metasm/parse'
|
10
|
+
|
11
|
+
|
12
|
+
# BEWARE OF TEH RUBY PARSER
|
13
|
+
# use single-quoted source strings
|
14
|
+
class TestPreproc < Test::Unit::TestCase
|
15
|
+
def load txt, bt = caller.first
|
16
|
+
p = Metasm::Preprocessor.new
|
17
|
+
bt =~ /^(.*?):(\d+)/
|
18
|
+
p.feed txt, $1, $2.to_i+1
|
19
|
+
p
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_gettok
|
23
|
+
p = load <<'EOS'
|
24
|
+
test boo
|
25
|
+
" bla bla\
|
26
|
+
\"\\" \
|
27
|
+
xx
|
28
|
+
EOS
|
29
|
+
assert_equal \
|
30
|
+
['test', :space, :string, :eol, :quoted, :space, 'xx', :eol, true],
|
31
|
+
[p.readtok.raw, p.readtok.type, p.readtok.type, p.readtok.type, p.readtok.type, p.readtok.type, p.readtok.raw, p.readtok.type, p.eos?]
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_comment
|
35
|
+
p = load <<'EOS'
|
36
|
+
foo /*/ bar ' " * /*/ baz
|
37
|
+
kikoo // lol \
|
38
|
+
asv
|
39
|
+
EOS
|
40
|
+
toks = []
|
41
|
+
nil while tok = p.readtok and (tok.type == :space or tok.type == :eol)
|
42
|
+
until p.eos?
|
43
|
+
toks << tok.raw
|
44
|
+
nil while tok = p.readtok and (tok.type == :space or tok.type == :eol)
|
45
|
+
end
|
46
|
+
assert_equal %w[foo baz kikoo], toks
|
47
|
+
end
|
48
|
+
|
49
|
+
def helper_preparse(text, result)
|
50
|
+
p = load(text, caller.first)
|
51
|
+
yield p if block_given?
|
52
|
+
txt = ''
|
53
|
+
until p.eos? or not t = p.readtok
|
54
|
+
txt << t.raw
|
55
|
+
end
|
56
|
+
assert_equal(result, txt.strip)
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_preproc
|
60
|
+
# ignores eol/space at begin/end
|
61
|
+
helper_preparse(<<EOS, '')
|
62
|
+
#if 0 // test # as first char
|
63
|
+
toto
|
64
|
+
#endif
|
65
|
+
EOS
|
66
|
+
helper_preparse(<<EOS, 'coucou')
|
67
|
+
#define tutu
|
68
|
+
#if defined ( tutu )
|
69
|
+
tutu coucou
|
70
|
+
#endif
|
71
|
+
EOS
|
72
|
+
helper_preparse('a #define b', 'a #define b')
|
73
|
+
helper_preparse(<<EOS, "// true !\nblu")
|
74
|
+
#ifdef toto // this is false
|
75
|
+
bla
|
76
|
+
#elif .2_3e-4 > 2 /* this one too */
|
77
|
+
blo
|
78
|
+
#elif (1+1)*2 > 2 // true !
|
79
|
+
blu
|
80
|
+
#elif 4 > 2 // not you
|
81
|
+
ble
|
82
|
+
#else
|
83
|
+
bli
|
84
|
+
#endif
|
85
|
+
EOS
|
86
|
+
helper_preparse(<<'EOS', 'ab#define x')
|
87
|
+
a\
|
88
|
+
b\
|
89
|
+
#define x
|
90
|
+
EOS
|
91
|
+
p = load('__LINE__,__DATE__,__TIME__')
|
92
|
+
assert_equal(__LINE__, p.readtok.value) ; p.readtok
|
93
|
+
assert_not_equal('__DATE__', p.readtok.raw) ; p.readtok
|
94
|
+
assert_not_equal('__TIME__', p.readtok.raw)
|
95
|
+
|
96
|
+
helper_preparse(<<EOS, 'toto 1 toto 12 toto 3+(3-2) otot hoho')
|
97
|
+
#define azer(k) 12
|
98
|
+
# define xxx azer(7)
|
99
|
+
#define macro(a, b, c) toto a toto b toto c otot
|
100
|
+
macro(1, xxx, 3+(3-2)) hoho
|
101
|
+
EOS
|
102
|
+
helper_preparse(<<EOS, 'c')
|
103
|
+
#define a b
|
104
|
+
#define d c
|
105
|
+
#define c d
|
106
|
+
#define b c
|
107
|
+
a
|
108
|
+
EOS
|
109
|
+
helper_preparse(<<EOS, 'b')
|
110
|
+
#define b c
|
111
|
+
#define a b
|
112
|
+
#undef b
|
113
|
+
a
|
114
|
+
EOS
|
115
|
+
helper_preparse(<<EOS, 'toto tutu huhu()')
|
116
|
+
#define toto() abcd
|
117
|
+
#define tata huhu
|
118
|
+
toto tutu tata()
|
119
|
+
EOS
|
120
|
+
helper_preparse(<<EOS, '"haha"')
|
121
|
+
#define d(a) #a
|
122
|
+
d(haha)
|
123
|
+
EOS
|
124
|
+
helper_preparse(<<EOS, '{')
|
125
|
+
#define toto(a) a
|
126
|
+
toto({)
|
127
|
+
EOS
|
128
|
+
helper_preparse(<<EOS, 'x(, 1)')
|
129
|
+
#define d(a,b) x(a, b)
|
130
|
+
d(,1)
|
131
|
+
EOS
|
132
|
+
helper_preparse(<<EOS, '"foo" "4"')
|
133
|
+
#define str(x) #x
|
134
|
+
#define xstr(x) str(x)
|
135
|
+
#define foo 4
|
136
|
+
str(foo) xstr(foo)
|
137
|
+
EOS
|
138
|
+
begin
|
139
|
+
File.open('tests/prepro_testinclude.asm', 'w') { |fd| fd.puts '#define out in' }
|
140
|
+
helper_preparse(<<EOS, 'in')
|
141
|
+
#pragma include_path "."
|
142
|
+
#include <tests/prepro_testinclude.asm>
|
143
|
+
out
|
144
|
+
EOS
|
145
|
+
ensure
|
146
|
+
File.unlink('tests/prepro_testinclude.asm') rescue nil
|
147
|
+
end
|
148
|
+
|
149
|
+
helper_preparse(<<EOS, 'in') { |p_| p_.hooked_include['bla.h'] = '#define out in' }
|
150
|
+
#include <bla.h>
|
151
|
+
out
|
152
|
+
EOS
|
153
|
+
helper_preparse(<<EOS, 'in') { |p_| p_.define('out', 'in') }
|
154
|
+
out
|
155
|
+
EOS
|
156
|
+
helper_preparse(<<EOS, 'in') { |p_| p_.define_strong('out', 'in') }
|
157
|
+
out
|
158
|
+
EOS
|
159
|
+
helper_preparse(<<EOS, 'in') { |p_| p_.define_strong('out', 'in') }
|
160
|
+
#define out poil
|
161
|
+
out
|
162
|
+
EOS
|
163
|
+
helper_preparse(<<EOS, 'in') { |p_| p_.define('out', 'in') ; p_.define_weak('out', 'poil') }
|
164
|
+
out
|
165
|
+
EOS
|
166
|
+
p = load <<EOS
|
167
|
+
#define cct(a, b) a ## _ ## b
|
168
|
+
cct(toto, tutu)
|
169
|
+
EOS
|
170
|
+
nil while tok = p.readtok and (tok.type == :space or tok.type == :eol)
|
171
|
+
assert_equal('toto_tutu', tok.raw) # check we get only 1 token back
|
172
|
+
|
173
|
+
# assert_outputs_a_warning ?
|
174
|
+
helper_preparse(<<EOS, <<EOS.strip)
|
175
|
+
#define va1(a, b...) toto(a, ##b)
|
176
|
+
#define va3(a, ...) toto(a, __VA_ARGS__)
|
177
|
+
va1(1, 2);
|
178
|
+
va1(1,2);
|
179
|
+
va1(1);
|
180
|
+
va3(1, 2);
|
181
|
+
va3(1);
|
182
|
+
EOS
|
183
|
+
toto(1, 2);
|
184
|
+
toto(1,2);
|
185
|
+
toto(1);
|
186
|
+
toto(1, 2);
|
187
|
+
toto(1, );
|
188
|
+
EOS
|
189
|
+
|
190
|
+
helper_preparse(<<EOS, "#define a c\n#define b d\na b")
|
191
|
+
#define x(z) z
|
192
|
+
#define y #define
|
193
|
+
x(#)define a c
|
194
|
+
y b d
|
195
|
+
a b
|
196
|
+
EOS
|
197
|
+
helper_preparse("#define a(a) a(a)\na(1)", '1(1)')
|
198
|
+
helper_preparse("#if 0\n#endif", '')
|
199
|
+
helper_preparse("#if 0U\n#endif", '')
|
200
|
+
helper_preparse("#if 0L\n#endif", '')
|
201
|
+
helper_preparse("#if 0LLU\n#endif", '')
|
202
|
+
end
|
203
|
+
|
204
|
+
def test_floats
|
205
|
+
t_float = lambda { |txt|
|
206
|
+
text = <<EOS
|
207
|
+
#if #{txt}
|
208
|
+
1
|
209
|
+
#endif
|
210
|
+
EOS
|
211
|
+
p = load text, caller.first
|
212
|
+
txt = ''
|
213
|
+
t = nil
|
214
|
+
txt << t.raw until p.eos? or not t = p.readtok
|
215
|
+
assert_equal('1', txt.strip)
|
216
|
+
}
|
217
|
+
t_float['1 > 0']
|
218
|
+
t_float['1.0 > 0']
|
219
|
+
t_float['1e2 > 10 && 1.0e2 < 1000']
|
220
|
+
t_float['1.0e+2 > 10']
|
221
|
+
t_float['10_00e-2 > 1 && 10_00e-2 < 100']
|
222
|
+
t_float['.1e2 > 1']
|
223
|
+
#t_float['0x1.p2L > 1 && 0x1p2f < 5']
|
224
|
+
t_float['0x1.p2L > 1']
|
225
|
+
t_float['0x1p2f < 5']
|
226
|
+
end
|
227
|
+
|
228
|
+
def test_errors
|
229
|
+
test_err = lambda { |txt| assert_raise(Metasm::ParseError) { p = load(txt, caller.first) ; p.readtok until p.eos? } }
|
230
|
+
t_float = lambda { |txt| assert_raise(Metasm::ParseError) { p = load("#if #{txt}\n#endif", caller.first) ; p.readtok } }
|
231
|
+
test_err["\"abc\n\""]
|
232
|
+
test_err['"abc\x"']
|
233
|
+
test_err['/*']
|
234
|
+
test_err['#if 0']
|
235
|
+
test_err["#define toto(tutu,"]
|
236
|
+
test_err["#define toto( (tutu, tata)"]
|
237
|
+
test_err['#error bla']
|
238
|
+
test_err[<<EOS]
|
239
|
+
#if 0
|
240
|
+
#elif 1
|
241
|
+
#else
|
242
|
+
#if 2
|
243
|
+
#endif
|
244
|
+
EOS
|
245
|
+
test_err[<<EOS]
|
246
|
+
#define abc(def)
|
247
|
+
abc (1, 3)
|
248
|
+
EOS
|
249
|
+
test_err["#if 0LUL\n#endif"]
|
250
|
+
# warnings only
|
251
|
+
#test_err["#define aa\n#define aa"]
|
252
|
+
#test_err['#define a(b) #c']
|
253
|
+
#test_err['#define a(b, b)']
|
254
|
+
#test_err['#define a ##z']
|
255
|
+
t_float['1e++4']
|
256
|
+
t_float['1.0e 4']
|
257
|
+
t_float['_1.0']
|
258
|
+
t_float['.e2']
|
259
|
+
t_float['1.1e+_1']
|
260
|
+
t_float['.2e']
|
261
|
+
t_float['.']
|
262
|
+
t_float['1.2e*4']
|
263
|
+
t_float['0x1.e4']
|
264
|
+
t_float['0x1.p4a']
|
265
|
+
t_float['0x.p1']
|
266
|
+
t_float['0x.1lp1']
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|