metasm 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (192) hide show
  1. data/BUGS +11 -0
  2. data/CREDITS +17 -0
  3. data/README +270 -0
  4. data/TODO +114 -0
  5. data/doc/code_organisation.txt +146 -0
  6. data/doc/const_missing.txt +16 -0
  7. data/doc/core_classes.txt +75 -0
  8. data/doc/feature_list.txt +53 -0
  9. data/doc/index.txt +59 -0
  10. data/doc/install_notes.txt +170 -0
  11. data/doc/style.css +3 -0
  12. data/doc/use_cases.txt +18 -0
  13. data/lib/metasm.rb +80 -0
  14. data/lib/metasm/arm.rb +12 -0
  15. data/lib/metasm/arm/debug.rb +39 -0
  16. data/lib/metasm/arm/decode.rb +167 -0
  17. data/lib/metasm/arm/encode.rb +77 -0
  18. data/lib/metasm/arm/main.rb +75 -0
  19. data/lib/metasm/arm/opcodes.rb +177 -0
  20. data/lib/metasm/arm/parse.rb +130 -0
  21. data/lib/metasm/arm/render.rb +55 -0
  22. data/lib/metasm/compile_c.rb +1457 -0
  23. data/lib/metasm/dalvik.rb +8 -0
  24. data/lib/metasm/dalvik/decode.rb +196 -0
  25. data/lib/metasm/dalvik/main.rb +60 -0
  26. data/lib/metasm/dalvik/opcodes.rb +366 -0
  27. data/lib/metasm/decode.rb +213 -0
  28. data/lib/metasm/decompile.rb +2659 -0
  29. data/lib/metasm/disassemble.rb +2068 -0
  30. data/lib/metasm/disassemble_api.rb +1280 -0
  31. data/lib/metasm/dynldr.rb +1329 -0
  32. data/lib/metasm/encode.rb +333 -0
  33. data/lib/metasm/exe_format/a_out.rb +194 -0
  34. data/lib/metasm/exe_format/autoexe.rb +82 -0
  35. data/lib/metasm/exe_format/bflt.rb +189 -0
  36. data/lib/metasm/exe_format/coff.rb +455 -0
  37. data/lib/metasm/exe_format/coff_decode.rb +901 -0
  38. data/lib/metasm/exe_format/coff_encode.rb +1078 -0
  39. data/lib/metasm/exe_format/dex.rb +457 -0
  40. data/lib/metasm/exe_format/dol.rb +145 -0
  41. data/lib/metasm/exe_format/elf.rb +923 -0
  42. data/lib/metasm/exe_format/elf_decode.rb +979 -0
  43. data/lib/metasm/exe_format/elf_encode.rb +1375 -0
  44. data/lib/metasm/exe_format/macho.rb +827 -0
  45. data/lib/metasm/exe_format/main.rb +228 -0
  46. data/lib/metasm/exe_format/mz.rb +164 -0
  47. data/lib/metasm/exe_format/nds.rb +172 -0
  48. data/lib/metasm/exe_format/pe.rb +437 -0
  49. data/lib/metasm/exe_format/serialstruct.rb +246 -0
  50. data/lib/metasm/exe_format/shellcode.rb +114 -0
  51. data/lib/metasm/exe_format/xcoff.rb +167 -0
  52. data/lib/metasm/gui.rb +23 -0
  53. data/lib/metasm/gui/cstruct.rb +373 -0
  54. data/lib/metasm/gui/dasm_coverage.rb +199 -0
  55. data/lib/metasm/gui/dasm_decomp.rb +369 -0
  56. data/lib/metasm/gui/dasm_funcgraph.rb +103 -0
  57. data/lib/metasm/gui/dasm_graph.rb +1354 -0
  58. data/lib/metasm/gui/dasm_hex.rb +543 -0
  59. data/lib/metasm/gui/dasm_listing.rb +599 -0
  60. data/lib/metasm/gui/dasm_main.rb +906 -0
  61. data/lib/metasm/gui/dasm_opcodes.rb +291 -0
  62. data/lib/metasm/gui/debug.rb +1228 -0
  63. data/lib/metasm/gui/gtk.rb +884 -0
  64. data/lib/metasm/gui/qt.rb +495 -0
  65. data/lib/metasm/gui/win32.rb +3004 -0
  66. data/lib/metasm/gui/x11.rb +621 -0
  67. data/lib/metasm/ia32.rb +14 -0
  68. data/lib/metasm/ia32/compile_c.rb +1523 -0
  69. data/lib/metasm/ia32/debug.rb +193 -0
  70. data/lib/metasm/ia32/decode.rb +1167 -0
  71. data/lib/metasm/ia32/decompile.rb +564 -0
  72. data/lib/metasm/ia32/encode.rb +314 -0
  73. data/lib/metasm/ia32/main.rb +233 -0
  74. data/lib/metasm/ia32/opcodes.rb +872 -0
  75. data/lib/metasm/ia32/parse.rb +327 -0
  76. data/lib/metasm/ia32/render.rb +91 -0
  77. data/lib/metasm/main.rb +1193 -0
  78. data/lib/metasm/mips.rb +11 -0
  79. data/lib/metasm/mips/compile_c.rb +7 -0
  80. data/lib/metasm/mips/decode.rb +253 -0
  81. data/lib/metasm/mips/encode.rb +51 -0
  82. data/lib/metasm/mips/main.rb +72 -0
  83. data/lib/metasm/mips/opcodes.rb +443 -0
  84. data/lib/metasm/mips/parse.rb +51 -0
  85. data/lib/metasm/mips/render.rb +43 -0
  86. data/lib/metasm/os/gnu_exports.rb +270 -0
  87. data/lib/metasm/os/linux.rb +1112 -0
  88. data/lib/metasm/os/main.rb +1686 -0
  89. data/lib/metasm/os/remote.rb +527 -0
  90. data/lib/metasm/os/windows.rb +2027 -0
  91. data/lib/metasm/os/windows_exports.rb +745 -0
  92. data/lib/metasm/parse.rb +876 -0
  93. data/lib/metasm/parse_c.rb +3938 -0
  94. data/lib/metasm/pic16c/decode.rb +42 -0
  95. data/lib/metasm/pic16c/main.rb +17 -0
  96. data/lib/metasm/pic16c/opcodes.rb +68 -0
  97. data/lib/metasm/ppc.rb +11 -0
  98. data/lib/metasm/ppc/decode.rb +264 -0
  99. data/lib/metasm/ppc/decompile.rb +251 -0
  100. data/lib/metasm/ppc/encode.rb +51 -0
  101. data/lib/metasm/ppc/main.rb +129 -0
  102. data/lib/metasm/ppc/opcodes.rb +410 -0
  103. data/lib/metasm/ppc/parse.rb +52 -0
  104. data/lib/metasm/preprocessor.rb +1277 -0
  105. data/lib/metasm/render.rb +130 -0
  106. data/lib/metasm/sh4.rb +8 -0
  107. data/lib/metasm/sh4/decode.rb +336 -0
  108. data/lib/metasm/sh4/main.rb +292 -0
  109. data/lib/metasm/sh4/opcodes.rb +381 -0
  110. data/lib/metasm/x86_64.rb +12 -0
  111. data/lib/metasm/x86_64/compile_c.rb +1025 -0
  112. data/lib/metasm/x86_64/debug.rb +59 -0
  113. data/lib/metasm/x86_64/decode.rb +268 -0
  114. data/lib/metasm/x86_64/encode.rb +264 -0
  115. data/lib/metasm/x86_64/main.rb +135 -0
  116. data/lib/metasm/x86_64/opcodes.rb +118 -0
  117. data/lib/metasm/x86_64/parse.rb +68 -0
  118. data/misc/bottleneck.rb +61 -0
  119. data/misc/cheader-findpppath.rb +58 -0
  120. data/misc/hexdiff.rb +74 -0
  121. data/misc/hexdump.rb +55 -0
  122. data/misc/metasm-all.rb +13 -0
  123. data/misc/objdiff.rb +47 -0
  124. data/misc/objscan.rb +40 -0
  125. data/misc/pdfparse.rb +661 -0
  126. data/misc/ppc_pdf2oplist.rb +192 -0
  127. data/misc/tcp_proxy_hex.rb +84 -0
  128. data/misc/txt2html.rb +440 -0
  129. data/samples/a.out.rb +31 -0
  130. data/samples/asmsyntax.rb +77 -0
  131. data/samples/bindiff.rb +555 -0
  132. data/samples/compilation-steps.rb +49 -0
  133. data/samples/cparser_makestackoffset.rb +55 -0
  134. data/samples/dasm-backtrack.rb +38 -0
  135. data/samples/dasmnavig.rb +318 -0
  136. data/samples/dbg-apihook.rb +228 -0
  137. data/samples/dbghelp.rb +143 -0
  138. data/samples/disassemble-gui.rb +102 -0
  139. data/samples/disassemble.rb +133 -0
  140. data/samples/dump_upx.rb +95 -0
  141. data/samples/dynamic_ruby.rb +1929 -0
  142. data/samples/elf_list_needed.rb +46 -0
  143. data/samples/elf_listexports.rb +33 -0
  144. data/samples/elfencode.rb +25 -0
  145. data/samples/exeencode.rb +128 -0
  146. data/samples/factorize-headers-elfimports.rb +77 -0
  147. data/samples/factorize-headers-peimports.rb +109 -0
  148. data/samples/factorize-headers.rb +43 -0
  149. data/samples/gdbclient.rb +583 -0
  150. data/samples/generate_libsigs.rb +102 -0
  151. data/samples/hotfix_gtk_dbg.rb +59 -0
  152. data/samples/install_win_env.rb +78 -0
  153. data/samples/lindebug.rb +924 -0
  154. data/samples/linux_injectsyscall.rb +95 -0
  155. data/samples/machoencode.rb +31 -0
  156. data/samples/metasm-shell.rb +91 -0
  157. data/samples/pe-hook.rb +69 -0
  158. data/samples/pe-ia32-cpuid.rb +203 -0
  159. data/samples/pe-mips.rb +35 -0
  160. data/samples/pe-shutdown.rb +78 -0
  161. data/samples/pe-testrelocs.rb +51 -0
  162. data/samples/pe-testrsrc.rb +24 -0
  163. data/samples/pe_listexports.rb +31 -0
  164. data/samples/peencode.rb +19 -0
  165. data/samples/peldr.rb +494 -0
  166. data/samples/preprocess-flatten.rb +19 -0
  167. data/samples/r0trace.rb +308 -0
  168. data/samples/rubstop.rb +399 -0
  169. data/samples/scan_pt_gnu_stack.rb +54 -0
  170. data/samples/scanpeexports.rb +62 -0
  171. data/samples/shellcode-c.rb +40 -0
  172. data/samples/shellcode-dynlink.rb +146 -0
  173. data/samples/source.asm +34 -0
  174. data/samples/struct_offset.rb +47 -0
  175. data/samples/testpe.rb +32 -0
  176. data/samples/testraw.rb +45 -0
  177. data/samples/win32genloader.rb +132 -0
  178. data/samples/win32hooker-advanced.rb +169 -0
  179. data/samples/win32hooker.rb +96 -0
  180. data/samples/win32livedasm.rb +33 -0
  181. data/samples/win32remotescan.rb +133 -0
  182. data/samples/wintrace.rb +92 -0
  183. data/tests/all.rb +8 -0
  184. data/tests/dasm.rb +39 -0
  185. data/tests/dynldr.rb +35 -0
  186. data/tests/encodeddata.rb +132 -0
  187. data/tests/ia32.rb +82 -0
  188. data/tests/mips.rb +116 -0
  189. data/tests/parse_c.rb +239 -0
  190. data/tests/preprocessor.rb +269 -0
  191. data/tests/x86_64.rb +62 -0
  192. metadata +255 -0
@@ -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
+