metasm 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+
|