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.
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
+