metasm 1.0.0 → 1.0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (276) hide show
  1. checksums.yaml +7 -0
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +3 -0
  4. data/.gitignore +3 -0
  5. data/.hgtags +3 -0
  6. data/Gemfile +3 -0
  7. data/INSTALL +61 -0
  8. data/LICENCE +458 -0
  9. data/README +29 -21
  10. data/Rakefile +10 -0
  11. data/TODO +10 -12
  12. data/doc/code_organisation.txt +3 -1
  13. data/doc/core/DynLdr.txt +247 -0
  14. data/doc/core/ExeFormat.txt +43 -0
  15. data/doc/core/Expression.txt +220 -0
  16. data/doc/core/GNUExports.txt +27 -0
  17. data/doc/core/Ia32.txt +236 -0
  18. data/doc/core/SerialStruct.txt +108 -0
  19. data/doc/core/VirtualString.txt +145 -0
  20. data/doc/core/WindowsExports.txt +61 -0
  21. data/doc/core/index.txt +1 -0
  22. data/doc/style.css +6 -3
  23. data/doc/usage/debugger.txt +327 -0
  24. data/doc/usage/index.txt +1 -0
  25. data/doc/use_cases.txt +2 -2
  26. data/metasm.gemspec +23 -0
  27. data/{lib/metasm.rb → metasm.rb} +15 -3
  28. data/{lib/metasm → metasm}/compile_c.rb +15 -9
  29. data/metasm/cpu/arc.rb +8 -0
  30. data/metasm/cpu/arc/decode.rb +404 -0
  31. data/metasm/cpu/arc/main.rb +191 -0
  32. data/metasm/cpu/arc/opcodes.rb +588 -0
  33. data/metasm/cpu/arm.rb +14 -0
  34. data/{lib/metasm → metasm/cpu}/arm/debug.rb +2 -2
  35. data/{lib/metasm → metasm/cpu}/arm/decode.rb +15 -18
  36. data/{lib/metasm → metasm/cpu}/arm/encode.rb +23 -8
  37. data/{lib/metasm → metasm/cpu}/arm/main.rb +3 -6
  38. data/metasm/cpu/arm/opcodes.rb +324 -0
  39. data/{lib/metasm → metasm/cpu}/arm/parse.rb +25 -13
  40. data/{lib/metasm → metasm/cpu}/arm/render.rb +2 -2
  41. data/metasm/cpu/arm64.rb +15 -0
  42. data/metasm/cpu/arm64/debug.rb +38 -0
  43. data/metasm/cpu/arm64/decode.rb +285 -0
  44. data/metasm/cpu/arm64/encode.rb +41 -0
  45. data/metasm/cpu/arm64/main.rb +105 -0
  46. data/metasm/cpu/arm64/opcodes.rb +232 -0
  47. data/metasm/cpu/arm64/parse.rb +20 -0
  48. data/metasm/cpu/arm64/render.rb +95 -0
  49. data/{lib/metasm/mips/compile_c.rb → metasm/cpu/bpf.rb} +4 -2
  50. data/metasm/cpu/bpf/decode.rb +110 -0
  51. data/metasm/cpu/bpf/main.rb +60 -0
  52. data/metasm/cpu/bpf/opcodes.rb +81 -0
  53. data/metasm/cpu/bpf/render.rb +30 -0
  54. data/{lib/metasm/ppc.rb → metasm/cpu/cy16.rb} +2 -4
  55. data/metasm/cpu/cy16/decode.rb +247 -0
  56. data/metasm/cpu/cy16/main.rb +63 -0
  57. data/metasm/cpu/cy16/opcodes.rb +78 -0
  58. data/metasm/cpu/cy16/render.rb +30 -0
  59. data/metasm/cpu/dalvik.rb +11 -0
  60. data/{lib/metasm → metasm/cpu}/dalvik/decode.rb +34 -34
  61. data/{lib/metasm → metasm/cpu}/dalvik/main.rb +71 -4
  62. data/{lib/metasm → metasm/cpu}/dalvik/opcodes.rb +21 -12
  63. data/{lib/metasm/mips.rb → metasm/cpu/ebpf.rb} +3 -4
  64. data/metasm/cpu/ebpf/debug.rb +61 -0
  65. data/metasm/cpu/ebpf/decode.rb +142 -0
  66. data/metasm/cpu/ebpf/main.rb +58 -0
  67. data/metasm/cpu/ebpf/opcodes.rb +97 -0
  68. data/metasm/cpu/ebpf/render.rb +36 -0
  69. data/metasm/cpu/ia32.rb +17 -0
  70. data/{lib/metasm → metasm/cpu}/ia32/compile_c.rb +23 -9
  71. data/{lib/metasm → metasm/cpu}/ia32/debug.rb +44 -6
  72. data/{lib/metasm → metasm/cpu}/ia32/decode.rb +342 -128
  73. data/{lib/metasm → metasm/cpu}/ia32/decompile.rb +75 -53
  74. data/{lib/metasm → metasm/cpu}/ia32/encode.rb +19 -13
  75. data/{lib/metasm → metasm/cpu}/ia32/main.rb +66 -8
  76. data/metasm/cpu/ia32/opcodes.rb +1424 -0
  77. data/{lib/metasm → metasm/cpu}/ia32/parse.rb +55 -17
  78. data/{lib/metasm → metasm/cpu}/ia32/render.rb +32 -5
  79. data/metasm/cpu/mcs51.rb +8 -0
  80. data/metasm/cpu/mcs51/decode.rb +99 -0
  81. data/metasm/cpu/mcs51/main.rb +87 -0
  82. data/metasm/cpu/mcs51/opcodes.rb +120 -0
  83. data/metasm/cpu/mips.rb +14 -0
  84. data/metasm/cpu/mips/debug.rb +42 -0
  85. data/{lib/metasm → metasm/cpu}/mips/decode.rb +59 -38
  86. data/{lib/metasm → metasm/cpu}/mips/encode.rb +4 -3
  87. data/{lib/metasm → metasm/cpu}/mips/main.rb +13 -6
  88. data/{lib/metasm → metasm/cpu}/mips/opcodes.rb +87 -18
  89. data/{lib/metasm → metasm/cpu}/mips/parse.rb +1 -1
  90. data/{lib/metasm → metasm/cpu}/mips/render.rb +1 -1
  91. data/{lib/metasm/dalvik.rb → metasm/cpu/msp430.rb} +1 -1
  92. data/metasm/cpu/msp430/decode.rb +243 -0
  93. data/metasm/cpu/msp430/main.rb +62 -0
  94. data/metasm/cpu/msp430/opcodes.rb +101 -0
  95. data/metasm/cpu/openrisc.rb +11 -0
  96. data/metasm/cpu/openrisc/debug.rb +106 -0
  97. data/metasm/cpu/openrisc/decode.rb +182 -0
  98. data/metasm/cpu/openrisc/decompile.rb +350 -0
  99. data/metasm/cpu/openrisc/main.rb +70 -0
  100. data/metasm/cpu/openrisc/opcodes.rb +109 -0
  101. data/metasm/cpu/openrisc/render.rb +37 -0
  102. data/{lib/metasm → metasm/cpu}/pic16c/decode.rb +6 -7
  103. data/{lib/metasm → metasm/cpu}/pic16c/main.rb +0 -0
  104. data/{lib/metasm → metasm/cpu}/pic16c/opcodes.rb +1 -1
  105. data/metasm/cpu/ppc.rb +11 -0
  106. data/{lib/metasm → metasm/cpu}/ppc/decode.rb +18 -37
  107. data/{lib/metasm → metasm/cpu}/ppc/decompile.rb +3 -3
  108. data/{lib/metasm → metasm/cpu}/ppc/encode.rb +2 -2
  109. data/{lib/metasm → metasm/cpu}/ppc/main.rb +23 -18
  110. data/{lib/metasm → metasm/cpu}/ppc/opcodes.rb +11 -6
  111. data/metasm/cpu/ppc/parse.rb +55 -0
  112. data/metasm/cpu/python.rb +8 -0
  113. data/metasm/cpu/python/decode.rb +116 -0
  114. data/metasm/cpu/python/main.rb +36 -0
  115. data/metasm/cpu/python/opcodes.rb +180 -0
  116. data/{lib/metasm → metasm/cpu}/sh4.rb +1 -1
  117. data/{lib/metasm → metasm/cpu}/sh4/decode.rb +50 -23
  118. data/{lib/metasm → metasm/cpu}/sh4/main.rb +38 -27
  119. data/{lib/metasm → metasm/cpu}/sh4/opcodes.rb +7 -8
  120. data/metasm/cpu/st20.rb +9 -0
  121. data/metasm/cpu/st20/decode.rb +173 -0
  122. data/metasm/cpu/st20/decompile.rb +283 -0
  123. data/metasm/cpu/st20/main.rb +37 -0
  124. data/metasm/cpu/st20/opcodes.rb +140 -0
  125. data/{lib/metasm/arm.rb → metasm/cpu/webasm.rb} +4 -5
  126. data/metasm/cpu/webasm/debug.rb +31 -0
  127. data/metasm/cpu/webasm/decode.rb +321 -0
  128. data/metasm/cpu/webasm/decompile.rb +386 -0
  129. data/metasm/cpu/webasm/encode.rb +104 -0
  130. data/metasm/cpu/webasm/main.rb +81 -0
  131. data/metasm/cpu/webasm/opcodes.rb +214 -0
  132. data/metasm/cpu/x86_64.rb +15 -0
  133. data/{lib/metasm → metasm/cpu}/x86_64/compile_c.rb +40 -25
  134. data/{lib/metasm → metasm/cpu}/x86_64/debug.rb +4 -4
  135. data/{lib/metasm → metasm/cpu}/x86_64/decode.rb +58 -15
  136. data/{lib/metasm → metasm/cpu}/x86_64/encode.rb +59 -28
  137. data/{lib/metasm → metasm/cpu}/x86_64/main.rb +18 -6
  138. data/metasm/cpu/x86_64/opcodes.rb +138 -0
  139. data/{lib/metasm → metasm/cpu}/x86_64/parse.rb +12 -4
  140. data/metasm/cpu/x86_64/render.rb +35 -0
  141. data/metasm/cpu/z80.rb +9 -0
  142. data/metasm/cpu/z80/decode.rb +286 -0
  143. data/metasm/cpu/z80/main.rb +67 -0
  144. data/metasm/cpu/z80/opcodes.rb +224 -0
  145. data/metasm/cpu/z80/render.rb +48 -0
  146. data/{lib/metasm/os/main.rb → metasm/debug.rb} +201 -407
  147. data/{lib/metasm → metasm}/decode.rb +104 -24
  148. data/{lib/metasm → metasm}/decompile.rb +804 -478
  149. data/{lib/metasm → metasm}/disassemble.rb +385 -170
  150. data/{lib/metasm → metasm}/disassemble_api.rb +684 -105
  151. data/{lib/metasm → metasm}/dynldr.rb +231 -138
  152. data/{lib/metasm → metasm}/encode.rb +20 -5
  153. data/{lib/metasm → metasm}/exe_format/a_out.rb +9 -6
  154. data/{lib/metasm → metasm}/exe_format/autoexe.rb +3 -0
  155. data/{lib/metasm → metasm}/exe_format/bflt.rb +57 -27
  156. data/{lib/metasm → metasm}/exe_format/coff.rb +35 -7
  157. data/{lib/metasm → metasm}/exe_format/coff_decode.rb +70 -23
  158. data/{lib/metasm → metasm}/exe_format/coff_encode.rb +24 -22
  159. data/{lib/metasm → metasm}/exe_format/dex.rb +26 -8
  160. data/{lib/metasm → metasm}/exe_format/dol.rb +1 -0
  161. data/{lib/metasm → metasm}/exe_format/elf.rb +108 -58
  162. data/{lib/metasm → metasm}/exe_format/elf_decode.rb +202 -36
  163. data/{lib/metasm → metasm}/exe_format/elf_encode.rb +126 -32
  164. data/metasm/exe_format/gb.rb +65 -0
  165. data/metasm/exe_format/javaclass.rb +424 -0
  166. data/{lib/metasm → metasm}/exe_format/macho.rb +218 -16
  167. data/{lib/metasm → metasm}/exe_format/main.rb +28 -3
  168. data/{lib/metasm → metasm}/exe_format/mz.rb +2 -0
  169. data/{lib/metasm → metasm}/exe_format/nds.rb +7 -4
  170. data/{lib/metasm → metasm}/exe_format/pe.rb +96 -11
  171. data/metasm/exe_format/pyc.rb +167 -0
  172. data/{lib/metasm → metasm}/exe_format/serialstruct.rb +67 -14
  173. data/{lib/metasm → metasm}/exe_format/shellcode.rb +7 -3
  174. data/metasm/exe_format/shellcode_rwx.rb +114 -0
  175. data/metasm/exe_format/swf.rb +205 -0
  176. data/metasm/exe_format/wasm.rb +402 -0
  177. data/{lib/metasm → metasm}/exe_format/xcoff.rb +7 -7
  178. data/metasm/exe_format/zip.rb +335 -0
  179. data/metasm/gui.rb +13 -0
  180. data/{lib/metasm → metasm}/gui/cstruct.rb +35 -41
  181. data/{lib/metasm → metasm}/gui/dasm_coverage.rb +11 -11
  182. data/{lib/metasm → metasm}/gui/dasm_decomp.rb +177 -114
  183. data/{lib/metasm → metasm}/gui/dasm_funcgraph.rb +0 -0
  184. data/metasm/gui/dasm_graph.rb +1754 -0
  185. data/{lib/metasm → metasm}/gui/dasm_hex.rb +16 -12
  186. data/{lib/metasm → metasm}/gui/dasm_listing.rb +43 -28
  187. data/{lib/metasm → metasm}/gui/dasm_main.rb +360 -77
  188. data/{lib/metasm → metasm}/gui/dasm_opcodes.rb +5 -19
  189. data/{lib/metasm → metasm}/gui/debug.rb +109 -34
  190. data/{lib/metasm → metasm}/gui/gtk.rb +174 -44
  191. data/{lib/metasm → metasm}/gui/qt.rb +14 -4
  192. data/{lib/metasm → metasm}/gui/win32.rb +180 -43
  193. data/{lib/metasm → metasm}/gui/x11.rb +59 -59
  194. data/{lib/metasm → metasm}/main.rb +421 -286
  195. data/metasm/os/emulator.rb +175 -0
  196. data/{lib/metasm/os/remote.rb → metasm/os/gdbremote.rb} +146 -54
  197. data/{lib/metasm → metasm}/os/gnu_exports.rb +1 -1
  198. data/{lib/metasm → metasm}/os/linux.rb +628 -151
  199. data/metasm/os/main.rb +335 -0
  200. data/{lib/metasm → metasm}/os/windows.rb +151 -58
  201. data/{lib/metasm → metasm}/os/windows_exports.rb +141 -0
  202. data/{lib/metasm → metasm}/parse.rb +49 -36
  203. data/{lib/metasm → metasm}/parse_c.rb +405 -246
  204. data/{lib/metasm → metasm}/preprocessor.rb +71 -41
  205. data/{lib/metasm → metasm}/render.rb +14 -38
  206. data/misc/hexdump.rb +4 -3
  207. data/misc/lint.rb +58 -0
  208. data/misc/objdiff.rb +4 -1
  209. data/misc/objscan.rb +1 -1
  210. data/misc/openrisc-parser.rb +79 -0
  211. data/misc/txt2html.rb +9 -7
  212. data/samples/bindiff.rb +3 -4
  213. data/samples/dasm-plugins/bindiff.rb +15 -0
  214. data/samples/dasm-plugins/bookmark.rb +133 -0
  215. data/samples/dasm-plugins/c_constants.rb +57 -0
  216. data/samples/dasm-plugins/colortheme_solarized.rb +125 -0
  217. data/samples/dasm-plugins/cppobj_funcall.rb +60 -0
  218. data/samples/dasm-plugins/dasm_all.rb +70 -0
  219. data/samples/dasm-plugins/demangle_cpp.rb +31 -0
  220. data/samples/dasm-plugins/deobfuscate.rb +251 -0
  221. data/samples/dasm-plugins/dump_text.rb +35 -0
  222. data/samples/dasm-plugins/export_graph_svg.rb +86 -0
  223. data/samples/dasm-plugins/findgadget.rb +75 -0
  224. data/samples/dasm-plugins/hl_opcode.rb +32 -0
  225. data/samples/dasm-plugins/hotfix_gtk_dbg.rb +19 -0
  226. data/samples/dasm-plugins/imm2off.rb +34 -0
  227. data/samples/dasm-plugins/match_libsigs.rb +93 -0
  228. data/samples/dasm-plugins/patch_file.rb +95 -0
  229. data/samples/dasm-plugins/scanfuncstart.rb +36 -0
  230. data/samples/dasm-plugins/scanxrefs.rb +29 -0
  231. data/samples/dasm-plugins/selfmodify.rb +197 -0
  232. data/samples/dasm-plugins/stringsxrefs.rb +28 -0
  233. data/samples/dasmnavig.rb +1 -1
  234. data/samples/dbg-apihook.rb +24 -9
  235. data/samples/dbg-plugins/heapscan.rb +283 -0
  236. data/samples/dbg-plugins/heapscan/compiled_heapscan_lin.c +155 -0
  237. data/samples/dbg-plugins/heapscan/compiled_heapscan_win.c +128 -0
  238. data/samples/dbg-plugins/heapscan/graphheap.rb +616 -0
  239. data/samples/dbg-plugins/heapscan/heapscan.rb +709 -0
  240. data/samples/dbg-plugins/heapscan/winheap.h +174 -0
  241. data/samples/dbg-plugins/heapscan/winheap7.h +307 -0
  242. data/samples/dbg-plugins/trace_func.rb +214 -0
  243. data/samples/disassemble-gui.rb +48 -7
  244. data/samples/disassemble.rb +31 -6
  245. data/samples/dump_upx.rb +24 -12
  246. data/samples/dynamic_ruby.rb +35 -27
  247. data/samples/elfencode.rb +15 -0
  248. data/samples/emubios.rb +251 -0
  249. data/samples/emudbg.rb +127 -0
  250. data/samples/exeencode.rb +6 -5
  251. data/samples/factorize-headers-peimports.rb +1 -1
  252. data/samples/lindebug.rb +186 -391
  253. data/samples/metasm-shell.rb +68 -57
  254. data/samples/peldr.rb +2 -2
  255. data/tests/all.rb +1 -1
  256. data/tests/arc.rb +26 -0
  257. data/tests/dynldr.rb +22 -4
  258. data/tests/expression.rb +57 -0
  259. data/tests/graph_layout.rb +285 -0
  260. data/tests/ia32.rb +80 -26
  261. data/tests/mcs51.rb +27 -0
  262. data/tests/mips.rb +10 -3
  263. data/tests/preprocessor.rb +18 -0
  264. data/tests/x86_64.rb +66 -18
  265. metadata +465 -219
  266. metadata.gz.sig +2 -0
  267. data/lib/metasm/arm/opcodes.rb +0 -177
  268. data/lib/metasm/gui.rb +0 -23
  269. data/lib/metasm/gui/dasm_graph.rb +0 -1354
  270. data/lib/metasm/ia32.rb +0 -14
  271. data/lib/metasm/ia32/opcodes.rb +0 -872
  272. data/lib/metasm/ppc/parse.rb +0 -52
  273. data/lib/metasm/x86_64.rb +0 -12
  274. data/lib/metasm/x86_64/opcodes.rb +0 -118
  275. data/samples/gdbclient.rb +0 -583
  276. data/samples/rubstop.rb +0 -399
@@ -9,31 +9,31 @@ module Metasm
9
9
  module Gui
10
10
  class XGui < DynLdr
11
11
  new_api_c <<EOS, 'libX11.so'
12
- #define KeyPressMask (1L<<0)
13
- #define KeyReleaseMask (1L<<1)
14
- #define ButtonPressMask (1L<<2)
15
- #define ButtonReleaseMask (1L<<3)
16
- #define EnterWindowMask (1L<<4)
17
- #define LeaveWindowMask (1L<<5)
18
- #define PointerMotionMask (1L<<6)
19
- #define PointerMotionHintMask (1L<<7)
20
- #define Button1MotionMask (1L<<8)
21
- #define Button2MotionMask (1L<<9)
22
- #define Button3MotionMask (1L<<10)
23
- #define Button4MotionMask (1L<<11)
24
- #define Button5MotionMask (1L<<12)
25
- #define ButtonMotionMask (1L<<13)
12
+ #define KeyPressMask (1L<<0)
13
+ #define KeyReleaseMask (1L<<1)
14
+ #define ButtonPressMask (1L<<2)
15
+ #define ButtonReleaseMask (1L<<3)
16
+ #define EnterWindowMask (1L<<4)
17
+ #define LeaveWindowMask (1L<<5)
18
+ #define PointerMotionMask (1L<<6)
19
+ #define PointerMotionHintMask (1L<<7)
20
+ #define Button1MotionMask (1L<<8)
21
+ #define Button2MotionMask (1L<<9)
22
+ #define Button3MotionMask (1L<<10)
23
+ #define Button4MotionMask (1L<<11)
24
+ #define Button5MotionMask (1L<<12)
25
+ #define ButtonMotionMask (1L<<13)
26
26
  #define KeymapStateMask (1L<<14)
27
- #define ExposureMask (1L<<15)
28
- #define VisibilityChangeMask (1L<<16)
29
- #define StructureNotifyMask (1L<<17)
30
- #define ResizeRedirectMask (1L<<18)
31
- #define SubstructureNotifyMask (1L<<19)
32
- #define SubstructureRedirectMask (1L<<20)
33
- #define FocusChangeMask (1L<<21)
34
- #define PropertyChangeMask (1L<<22)
35
- #define ColormapChangeMask (1L<<23)
36
- #define OwnerGrabButtonMask (1L<<24)
27
+ #define ExposureMask (1L<<15)
28
+ #define VisibilityChangeMask (1L<<16)
29
+ #define StructureNotifyMask (1L<<17)
30
+ #define ResizeRedirectMask (1L<<18)
31
+ #define SubstructureNotifyMask (1L<<19)
32
+ #define SubstructureRedirectMask (1L<<20)
33
+ #define FocusChangeMask (1L<<21)
34
+ #define PropertyChangeMask (1L<<22)
35
+ #define ColormapChangeMask (1L<<23)
36
+ #define OwnerGrabButtonMask (1L<<24)
37
37
 
38
38
  #define KeyPress 2
39
39
  #define KeyRelease 3
@@ -84,7 +84,7 @@ typedef struct _XGC *GC;
84
84
  typedef XID Pixmap;
85
85
  typedef XID Window;
86
86
 
87
- typedef
87
+ typedef
88
88
  struct {
89
89
  int type;
90
90
  unsigned long serial;
@@ -92,7 +92,7 @@ struct {
92
92
  Display *display;
93
93
  Window window;
94
94
  } XAnyEvent;
95
- typedef
95
+ typedef
96
96
  struct {
97
97
  int type;
98
98
  unsigned long serial;
@@ -110,7 +110,7 @@ struct {
110
110
  unsigned int button;
111
111
  int same_screen;
112
112
  } XButtonEvent;
113
- typedef
113
+ typedef
114
114
  struct {
115
115
  int type;
116
116
  unsigned long serial;
@@ -120,7 +120,7 @@ struct {
120
120
  Window window;
121
121
  int place;
122
122
  } XCirculateEvent;
123
- typedef
123
+ typedef
124
124
  struct {
125
125
  int type;
126
126
  unsigned long serial;
@@ -130,7 +130,7 @@ struct {
130
130
  Window window;
131
131
  int place;
132
132
  } XCirculateRequestEvent;
133
- typedef
133
+ typedef
134
134
  struct {
135
135
  int type;
136
136
  unsigned long serial;
@@ -146,7 +146,7 @@ struct {
146
146
  long l[5];
147
147
  } data;
148
148
  } XClientMessageEvent;
149
- typedef
149
+ typedef
150
150
  struct {
151
151
  int type;
152
152
  unsigned long serial;
@@ -157,7 +157,7 @@ struct {
157
157
  int new;
158
158
  int state;
159
159
  } XColormapEvent;
160
- typedef
160
+ typedef
161
161
  struct {
162
162
  int type;
163
163
  unsigned long serial;
@@ -173,7 +173,7 @@ struct {
173
173
  Window above;
174
174
  int override_redirect;
175
175
  } XConfigureEvent;
176
- typedef
176
+ typedef
177
177
  struct {
178
178
  int type;
179
179
  unsigned long serial;
@@ -190,7 +190,7 @@ struct {
190
190
  int detail;
191
191
  unsigned long value_mask;
192
192
  } XConfigureRequestEvent;
193
- typedef
193
+ typedef
194
194
  struct {
195
195
  int type;
196
196
  unsigned long serial;
@@ -205,7 +205,7 @@ struct {
205
205
  int border_width;
206
206
  int override_redirect;
207
207
  } XCreateWindowEvent;
208
- typedef
208
+ typedef
209
209
  struct {
210
210
  int type;
211
211
  unsigned long serial;
@@ -225,7 +225,7 @@ struct {
225
225
  int focus;
226
226
  unsigned int state;
227
227
  } XCrossingEvent;
228
- typedef
228
+ typedef
229
229
  struct {
230
230
  int type;
231
231
  unsigned long serial;
@@ -234,7 +234,7 @@ struct {
234
234
  Window event;
235
235
  Window window;
236
236
  } XDestroyWindowEvent;
237
- typedef
237
+ typedef
238
238
  struct {
239
239
  int type;
240
240
  Display *display;
@@ -244,7 +244,7 @@ struct {
244
244
  unsigned char request_code;
245
245
  unsigned char minor_code;
246
246
  } XErrorEvent;
247
- typedef
247
+ typedef
248
248
  struct {
249
249
  int type;
250
250
  unsigned long serial;
@@ -257,7 +257,7 @@ struct {
257
257
  int height;
258
258
  int count;
259
259
  } XExposeEvent;
260
- typedef
260
+ typedef
261
261
  struct {
262
262
  int type;
263
263
  unsigned long serial;
@@ -267,7 +267,7 @@ struct {
267
267
  int mode;
268
268
  int detail;
269
269
  } XFocusChangeEvent;
270
- typedef
270
+ typedef
271
271
  struct {
272
272
  int function;
273
273
  unsigned long plane_mask;
@@ -293,7 +293,7 @@ struct {
293
293
  int dash_offset;
294
294
  char dashes;
295
295
  } XGCValues;
296
- typedef
296
+ typedef
297
297
  struct {
298
298
  int type;
299
299
  unsigned long serial;
@@ -302,7 +302,7 @@ struct {
302
302
  int extension;
303
303
  int evtype;
304
304
  } XGenericEvent;
305
- typedef
305
+ typedef
306
306
  struct {
307
307
  int type;
308
308
  unsigned long serial;
@@ -313,7 +313,7 @@ struct {
313
313
  unsigned int cookie;
314
314
  void *data;
315
315
  } XGenericEventCookie;
316
- typedef
316
+ typedef
317
317
  struct {
318
318
  int type;
319
319
  unsigned long serial;
@@ -328,7 +328,7 @@ struct {
328
328
  int major_code;
329
329
  int minor_code;
330
330
  } XGraphicsExposeEvent;
331
- typedef
331
+ typedef
332
332
  struct {
333
333
  int type;
334
334
  unsigned long serial;
@@ -339,7 +339,7 @@ struct {
339
339
  int x;
340
340
  int y;
341
341
  } XGravityEvent;
342
- typedef
342
+ typedef
343
343
  struct {
344
344
  int type;
345
345
  unsigned long serial;
@@ -357,7 +357,7 @@ struct {
357
357
  unsigned int keycode;
358
358
  int same_screen;
359
359
  } XKeyEvent;
360
- typedef
360
+ typedef
361
361
  struct {
362
362
  int type;
363
363
  unsigned long serial;
@@ -366,7 +366,7 @@ struct {
366
366
  Window window;
367
367
  char key_vector[32];
368
368
  } XKeymapEvent;
369
- typedef
369
+ typedef
370
370
  struct {
371
371
  int type;
372
372
  unsigned long serial;
@@ -376,7 +376,7 @@ struct {
376
376
  Window window;
377
377
  int override_redirect;
378
378
  } XMapEvent;
379
- typedef
379
+ typedef
380
380
  struct {
381
381
  int type;
382
382
  unsigned long serial;
@@ -385,7 +385,7 @@ struct {
385
385
  Window parent;
386
386
  Window window;
387
387
  } XMapRequestEvent;
388
- typedef
388
+ typedef
389
389
  struct {
390
390
  int type;
391
391
  unsigned long serial;
@@ -396,7 +396,7 @@ struct {
396
396
  int first_keycode;
397
397
  int count;
398
398
  } XMappingEvent;
399
- typedef
399
+ typedef
400
400
  struct {
401
401
  int type;
402
402
  unsigned long serial;
@@ -414,7 +414,7 @@ struct {
414
414
  char is_hint;
415
415
  int same_screen;
416
416
  } XMotionEvent;
417
- typedef
417
+ typedef
418
418
  struct {
419
419
  int type;
420
420
  unsigned long serial;
@@ -424,7 +424,7 @@ struct {
424
424
  int major_code;
425
425
  int minor_code;
426
426
  } XNoExposeEvent;
427
- typedef
427
+ typedef
428
428
  struct {
429
429
  int type;
430
430
  unsigned long serial;
@@ -435,7 +435,7 @@ struct {
435
435
  Time time;
436
436
  int state;
437
437
  } XPropertyEvent;
438
- typedef
438
+ typedef
439
439
  struct {
440
440
  int type;
441
441
  unsigned long serial;
@@ -448,7 +448,7 @@ struct {
448
448
  int y;
449
449
  int override_redirect;
450
450
  } XReparentEvent;
451
- typedef
451
+ typedef
452
452
  struct {
453
453
  int type;
454
454
  unsigned long serial;
@@ -458,7 +458,7 @@ struct {
458
458
  int width;
459
459
  int height;
460
460
  } XResizeRequestEvent;
461
- typedef
461
+ typedef
462
462
  struct {
463
463
  int type;
464
464
  unsigned long serial;
@@ -468,7 +468,7 @@ struct {
468
468
  Atom selection;
469
469
  Time time;
470
470
  } XSelectionClearEvent;
471
- typedef
471
+ typedef
472
472
  struct {
473
473
  int type;
474
474
  unsigned long serial;
@@ -480,7 +480,7 @@ struct {
480
480
  Atom property;
481
481
  Time time;
482
482
  } XSelectionEvent;
483
- typedef
483
+ typedef
484
484
  struct {
485
485
  int type;
486
486
  unsigned long serial;
@@ -493,7 +493,7 @@ struct {
493
493
  Atom property;
494
494
  Time time;
495
495
  } XSelectionRequestEvent;
496
- typedef
496
+ typedef
497
497
  struct {
498
498
  int type;
499
499
  unsigned long serial;
@@ -503,7 +503,7 @@ struct {
503
503
  Window window;
504
504
  int from_configure;
505
505
  } XUnmapEvent;
506
- typedef
506
+ typedef
507
507
  struct {
508
508
  int type;
509
509
  unsigned long serial;
@@ -579,7 +579,7 @@ EOS
579
579
  def self.test
580
580
  d = xopendisplay(nil)
581
581
  s = xdefaultscreen(d)
582
- cmap = xdefaultcolormap(d, s)
582
+ #cmap = xdefaultcolormap(d, s)
583
583
  w = xcreatesimplewindow(d, xdefaultrootwindow(d), 0, 0, 28, 28, 0, xblackpixel(d, s), xblackpixel(d, s))
584
584
  xstorename(d, w, "lol")
585
585
  gc = xcreategc(d, w, 0, 0)
@@ -23,7 +23,7 @@ class CPU
23
23
  attr_accessor :valid_args, :valid_props, :fields_mask
24
24
  attr_accessor :endianness, :size
25
25
  attr_accessor :generate_PIC
26
-
26
+
27
27
  def opcode_list
28
28
  @opcode_list ||= init_opcode_list
29
29
  end
@@ -32,8 +32,8 @@ class CPU
32
32
  def initialize
33
33
  @fields_mask = {}
34
34
  @fields_shift= {}
35
- @valid_args = []
36
- @valid_props = [:setip, :saveip, :stopexec]
35
+ @valid_args = {}
36
+ @valid_props = { :setip => true, :saveip => true, :stopexec => true }
37
37
  @generate_PIC = true
38
38
  end
39
39
 
@@ -81,6 +81,17 @@ class CPU
81
81
  def shortname
82
82
  self.class.name.sub(/.*::/, '').downcase
83
83
  end
84
+
85
+ # some userinterface wants to hilight a word, return a regexp
86
+ # useful for register aliases
87
+ # the regexp will be enclosed in \b and should not contain captures
88
+ def gui_hilight_word_regexp(word)
89
+ Regexp.escape(word)
90
+ end
91
+
92
+ # returns true if the name is invalid as a label name (eg register name)
93
+ def check_reserved_name(name)
94
+ end
84
95
  end
85
96
 
86
97
  # generic CPU, with no instructions, just size/endianness
@@ -120,6 +131,15 @@ class Opcode
120
131
  def basename
121
132
  @name.sub(/\..*/, '')
122
133
  end
134
+
135
+ def dup
136
+ o = Opcode.new(@name.dup, @bin)
137
+ o.bin = @bin.dup if @bin.kind_of?(::Array)
138
+ o.args = @args.dup
139
+ o.fields = @fields.dup
140
+ o.props = @props.dup
141
+ o
142
+ end
123
143
  end
124
144
 
125
145
  # defines an attribute self.backtrace (array of filename/lineno)
@@ -287,7 +307,7 @@ class ExeFormat
287
307
  def new_label(base = '')
288
308
  base = base.dup.tr('^a-zA-Z0-9_', '_')
289
309
  # use %x instead of to_s(16) for negative values
290
- base = (base << '_uuid' << ('%08x' % base.object_id)).freeze if base.empty? or @unique_labels_cache[base]
310
+ base = (base << '_uuid' << ('%08x' % (base.object_id & 0xffff_ffff_ffff_ffff))).freeze if base.empty? or @unique_labels_cache[base]
291
311
  @unique_labels_cache[base] = true
292
312
  base
293
313
  end
@@ -307,12 +327,16 @@ end
307
327
  class ExpressionType
308
328
  def +(o) Expression[self, :+, o].reduce end
309
329
  def -(o) Expression[self, :-, o].reduce end
330
+ # if the expression is constrained, this holds the mask of the maximum value
331
+ # (eg int16 => 0xffff)
332
+ attr_accessor :max_bits_mask
310
333
  end
311
334
 
312
335
  # handle immediate values, and arbitrary arithmetic/logic expression involving variables
313
336
  # boolean values are treated as in C : true is 1, false is 0
314
337
  # TODO replace #type with #size => bits + #type => [:signed/:unsigned/:any/:floating]
315
338
  # TODO handle floats
339
+ # TODO ternary operator ?
316
340
  class Expression < ExpressionType
317
341
  INT_SIZE = {}
318
342
  INT_MIN = {}
@@ -341,7 +365,7 @@ class Expression < ExpressionType
341
365
  if not op
342
366
  raise ArgumentError, 'invalid Expression[nil]' if not l
343
367
  return l if l.kind_of? Expression
344
- if l.kind_of? ::Numeric and l < 0
368
+ if l.kind_of?(::Numeric) and l < 0
345
369
  r = -l
346
370
  op = :'-'
347
371
  else
@@ -354,17 +378,17 @@ class Expression < ExpressionType
354
378
  end
355
379
  l = nil
356
380
  else
357
- l = self[*l] if l.kind_of? ::Array
381
+ l = self[*l] if l.kind_of?(::Array)
358
382
  end
359
- r = self[*r] if r.kind_of? ::Array
383
+ r = self[*r] if r.kind_of?(::Array)
360
384
  new(op, r, l)
361
385
  end
362
386
 
363
387
  # checks if a given Expression/Integer is in the type range
364
388
  # returns true if it is, false if it overflows, and nil if cannot be determined (eg unresolved variable)
365
389
  def self.in_range?(val, type)
366
- val = val.reduce if val.kind_of? self
367
- return unless val.kind_of? ::Numeric
390
+ val = val.reduce if val.kind_of?(self)
391
+ return unless val.kind_of?(::Numeric)
368
392
 
369
393
  if INT_MIN[type]
370
394
  val == val.to_i and
@@ -374,8 +398,11 @@ class Expression < ExpressionType
374
398
 
375
399
  # casts an unsigned value to a two-complement signed if the sign bit is set
376
400
  def self.make_signed(val, bitlength)
377
- if val.kind_of? Integer
378
- val = val - (1 << bitlength) if val >> (bitlength - 1) == 1
401
+ case val
402
+ when Integer
403
+ val = val - (1 << bitlength) if val > 0 and val >> (bitlength - 1) == 1
404
+ when Expression
405
+ val = Expression[val, :-, [(1<<bitlength), :*, [[val, :>>, (bitlength-1)], :==, 1]]]
379
406
  end
380
407
  val
381
408
  end
@@ -390,8 +417,10 @@ class Expression < ExpressionType
390
417
  # basic constructor
391
418
  # XXX funny args order, you should use +Expression[]+ instead
392
419
  def initialize(op, rexpr, lexpr)
393
- raise ArgumentError, "Expression: invalid arg order: #{[lexpr, op, rexpr].inspect}" if not op.kind_of? ::Symbol
394
- @op, @lexpr, @rexpr = op, lexpr, rexpr
420
+ raise ArgumentError, "Expression: invalid arg order: #{[lexpr, op, rexpr].inspect}" if not op.kind_of?(::Symbol)
421
+ @op = op
422
+ @lexpr = lexpr
423
+ @rexpr = rexpr
395
424
  end
396
425
 
397
426
  # recursive check of equity using #==
@@ -415,20 +444,21 @@ class Expression < ExpressionType
415
444
  return binding[self].dup
416
445
  end
417
446
 
418
- l, r = @lexpr, @rexpr
447
+ l = @lexpr
448
+ r = @rexpr
419
449
  if l and binding[l]
420
- raise "internal error - bound #{l.inspect}" if l.kind_of? ::Numeric
450
+ raise "internal error - bound #{l.inspect}" if l.kind_of?(::Numeric)
421
451
  l = binding[l]
422
452
  elsif l.kind_of? ExpressionType
423
453
  l = l.bind(binding)
424
454
  end
425
455
  if r and binding[r]
426
- raise "internal error - bound #{r.inspect}" if r.kind_of? ::Numeric
456
+ raise "internal error - bound #{r.inspect}" if r.kind_of?(::Numeric)
427
457
  r = binding[r]
428
458
  elsif r.kind_of? ExpressionType
429
459
  r = r.bind(binding)
430
460
  end
431
- Expression[l, @op, r]
461
+ Expression.new(@op, r, l)
432
462
  end
433
463
 
434
464
  # bind in place (replace self.lexpr/self.rexpr with the binding value)
@@ -464,15 +494,13 @@ class Expression < ExpressionType
464
494
  # returns a simplified copy of self
465
495
  # can return an +Expression+ or a +Numeric+, may return self
466
496
  # see +reduce_rec+ for simplifications description
467
- # if given a block, it will temporarily overwrite the global @@reduce_lambda XXX THIS IS NOT THREADSAFE
468
- def reduce(&b)
469
- old_rp, @@reduce_lambda = @@reduce_lambda, b if b
470
- case e = reduce_rec
497
+ # if given a block, will use it instead of @@reduce_lambda
498
+ def reduce(&cb)
499
+ cb ||= @@reduce_lambda
500
+ case e = reduce_rec(cb)
471
501
  when Expression, Numeric; e
472
502
  else Expression[e]
473
503
  end
474
- ensure
475
- @@reduce_lambda = old_rp if b
476
504
  end
477
505
 
478
506
  # resolves logic operations (true || false, etc)
@@ -482,20 +510,23 @@ class Expression < ExpressionType
482
510
  # reduces addition of 0 and unary +
483
511
  # canonicalize additions: put variables in the lhs, descend addition tree in the rhs => (a + (b + (c + 12)))
484
512
  # make formal reduction if finds somewhere in addition tree (a) and (-a)
485
- def reduce_rec
486
- l = @lexpr.kind_of?(ExpressionType) ? @lexpr.reduce_rec : @lexpr
487
- r = @rexpr.kind_of?(ExpressionType) ? @rexpr.reduce_rec : @rexpr
513
+ def reduce_rec(cb = @@reduce_lambda)
514
+ l = @lexpr.kind_of?(ExpressionType) ? @lexpr.reduce_rec(cb) : @lexpr
515
+ r = @rexpr.kind_of?(ExpressionType) ? @rexpr.reduce_rec(cb) : @rexpr
488
516
 
489
- if @@reduce_lambda
490
- l = @@reduce_lambda[l] || l if not @lexpr.kind_of? Expression
491
- r = @@reduce_lambda[r] || r if not @rexpr.kind_of? Expression
517
+ if cb
518
+ l = cb[l] || l if l and not @lexpr.kind_of?(Expression)
519
+ r = cb[r] || r if r and not @rexpr.kind_of?(Expression)
492
520
  end
493
521
 
494
522
  v =
495
- if r.kind_of?(::Numeric) and (l == nil or l.kind_of?(::Numeric))
496
- # calculate numerics
497
- if [:'&&', :'||', :'>', :'<', :'>=', :'<=', :'==', :'!='].include?(@op)
498
- # bool expr
523
+ if r.kind_of?(::Numeric) and (not l or l.kind_of?(::Numeric))
524
+ case @op
525
+ when :+; l ? l + r : r
526
+ when :-; l ? l - r : -r
527
+ when :'!'; raise 'internal error' if l ; (r == 0) ? 1 : 0
528
+ when :'~'; raise 'internal error' if l ; ~r
529
+ when :'&&', :'||', :'>', :'<', :'>=', :'<=', :'==', :'!='
499
530
  raise 'internal error' if not l
500
531
  case @op
501
532
  when :'&&'; (l != 0) && (r != 0)
@@ -507,201 +538,25 @@ class Expression < ExpressionType
507
538
  when :'=='; l == r
508
539
  when :'!='; l != r
509
540
  end ? 1 : 0
510
- elsif not l
511
- case @op
512
- when :'!'; (r == 0) ? 1 : 0
513
- when :+; r
514
- when :-; -r
515
- when :~; ~r
516
- end
517
541
  else
518
- # use ruby evaluator
519
542
  l.send(@op, r)
520
543
  end
521
-
522
- elsif @op == :'&&'
523
- if l == 0 # shortcircuit eval
524
- 0
525
- elsif l == 1
526
- Expression[r, :'!=', 0].reduce_rec
527
- elsif r == 0
528
- 0 # XXX l could be a special ExprType with sideeffects ?
529
- end
530
- elsif @op == :'||'
531
- if l.kind_of? ::Numeric and l != 0 # shortcircuit eval
532
- 1
533
- elsif l == 0
534
- Expression[r, :'!=', 0].reduce_rec
535
- elsif r == 0
536
- Expression[l, :'!=', 0].reduce_rec
537
- end
538
- elsif @op == :>> or @op == :<<
539
- if l == 0; 0
540
- elsif r == 0; l
541
- elsif l.kind_of? Expression and l.op == @op
542
- Expression[l.lexpr, @op, [l.rexpr, :+, r]].reduce_rec
543
- # XXX (a >> 1) << 1 != a (lose low bit)
544
- # XXX (a << 1) >> 1 != a (with real cpus, lose high bit)
545
- # (a | b) << i
546
- elsif r.kind_of? Integer and l.kind_of? Expression and [:&, :|, :^].include? l.op
547
- Expression[[l.lexpr, @op, r], l.op, [l.rexpr, @op, r]].reduce_rec
548
- end
549
- elsif @op == :'!'
550
- if r.kind_of? Expression and op = {:'==' => :'!=', :'!=' => :'==', :< => :>=, :> => :<=, :<= => :>, :>= => :<}[r.op]
551
- Expression[r.lexpr, op, r.rexpr].reduce_rec
552
- end
553
- elsif @op == :==
554
- if l == r; 1
555
- elsif r == 0 and l.kind_of? Expression and op = {:'==' => :'!=', :'!=' => :'==', :< => :>=, :> => :<=, :<= => :>, :>= => :<}[l.op]
556
- Expression[l.lexpr, op, l.rexpr].reduce_rec
557
- elsif r == 1 and l.kind_of? Expression and op = {:'==' => :'!=', :'!=' => :'==', :< => :>=, :> => :<=, :<= => :>, :>= => :<}[l.op]
558
- l
559
- elsif r == 0 and l.kind_of? Expression and l.op == :+
560
- if l.rexpr.kind_of? Expression and l.rexpr.op == :- and not l.rexpr.lexpr
561
- Expression[l.lexpr, @op, l.rexpr.rexpr].reduce_rec
562
- elsif l.rexpr.kind_of? ::Integer
563
- Expression[l.lexpr, @op, -l.rexpr].reduce_rec
564
- end
565
- end
566
- elsif @op == :'!='
567
- if l == r; 0
568
- end
569
- elsif @op == :^
570
- if l == :unknown or r == :unknown; :unknown
571
- elsif l == 0; r
572
- elsif r == 0; l
573
- elsif l == r; 0
574
- elsif r == 1 and l.kind_of? Expression and [:'==', :'!=', :<, :>, :<=, :>=].include? l.op
575
- Expression[nil, :'!', l].reduce_rec
576
- elsif l.kind_of?(::Numeric)
577
- if r.kind_of? Expression and r.op == :^
578
- # 1^(x^y) => x^(y^1)
579
- Expression[r.lexpr, :^, [r.rexpr, :^, l]].reduce_rec
580
- else
581
- # 1^a => a^1
582
- Expression[r, :^, l].reduce_rec
583
- end
584
- elsif l.kind_of? Expression and l.op == :^
585
- # (a^b)^c => a^(b^c)
586
- Expression[l.lexpr, :^, [l.rexpr, :^, r]].reduce_rec
587
- elsif r.kind_of? Expression and r.op == :^
588
- if r.rexpr == l
589
- # a^(a^b) => b
590
- r.lexpr
591
- elsif r.lexpr == l
592
- # a^(b^a) => b
593
- r.rexpr
594
- else
595
- # a^(b^(c^(a^d))) => b^(a^(c^(a^d)))
596
- # XXX ugly..
597
- tr = r
598
- found = false
599
- while not found and tr.kind_of?(Expression) and tr.op == :^
600
- found = true if tr.lexpr == l or tr.rexpr == l
601
- tr = tr.rexpr
602
- end
603
- if found
604
- Expression[r.lexpr, :^, [l, :^, r.rexpr]].reduce_rec
605
- end
606
- end
607
- elsif l.kind_of?(Expression) and l.op == :& and l.rexpr.kind_of?(::Integer) and (l.rexpr & (l.rexpr+1)) == 0
608
- if r.kind_of?(::Integer) and r & l.rexpr == r
609
- # (a&0xfff)^12 => (a^12)&0xfff
610
- Expression[[l.lexpr, :^, r], :&, l.rexpr].reduce_rec
611
- elsif r.kind_of?(Expression) and r.op == :& and r.rexpr.kind_of?(::Integer) and r.rexpr == l.rexpr
612
- # (a&0xfff)^(b&0xfff) => (a^b)&0xfff
613
- Expression[[l.lexpr, :^, r.lexpr], :&, l.rexpr].reduce_rec
614
- end
615
- end
616
- elsif @op == :&
617
- if l == 0 or r == 0; 0
618
- elsif r == 1 and l.kind_of?(Expression) and [:'==', :'!=', :<, :>, :<=, :>=].include?(l.op)
619
- l
620
- elsif l == r; l
621
- elsif l.kind_of?(Integer); Expression[r, @op, l].reduce_rec
622
- elsif l.kind_of?(Expression) and l.op == @op; Expression[l.lexpr, @op, [l.rexpr, @op, r]].reduce_rec
623
- elsif l.kind_of?(Expression) and [:|, :^].include?(l.op) and r.kind_of?(Integer) and (l.op == :| or (r & (r+1)) != 0)
624
- # (a ^| b) & i => (a&i ^| b&i)
625
- Expression[[l.lexpr, :&, r], l.op, [l.rexpr, :&, r]].reduce_rec
626
- elsif r.kind_of?(::Integer) and l.kind_of?(Expression) and (r & (r+1)) == 0
627
- # foo & 0xffff
628
- reduce_rec_mod2(l, r)
629
- end
630
- elsif @op == :|
631
- if l == 0; r
632
- elsif r == 0; l
633
- elsif l == -1 or r == -1; -1
634
- elsif l == r; l
635
- elsif l.kind_of? Integer; Expression[r, @op, l].reduce_rec
636
- elsif l.kind_of? Expression and l.op == @op; Expression[l.lexpr, @op, [l.rexpr, @op, r]].reduce_rec
637
- end
638
- elsif @op == :*
639
- if l == 0 or r == 0; 0
640
- elsif l == 1; r
641
- elsif r == 1; l
642
- elsif r.kind_of? Integer; Expression[r, @op, l].reduce_rec
643
- elsif r.kind_of? Expression and r.op == @op; Expression[[l, @op, r.lexpr], @op, r.rexpr].reduce_rec
644
- elsif l.kind_of? Integer and r.kind_of? Expression and r.op == :* and r.lexpr.kind_of? Integer; Expression[l*r.lexpr, :*, r.rexpr].reduce_rec # XXX need & regsize..
645
- elsif l.kind_of? Integer and r.kind_of? Expression and r.op == :+ and r.rexpr.kind_of? Integer; Expression[[l, :*, r.lexpr], :+, l*r.rexpr].reduce_rec
646
- end
647
- elsif @op == :/
648
- if r == 0
649
- elsif r.kind_of? Integer and l.kind_of? Expression and l.op == :+ and l.rexpr.kind_of? Integer and l.rexpr % r == 0
650
- Expression[[l.lexpr, :/, r], :+, l.rexpr/r].reduce_rec
651
- elsif r.kind_of? Integer and l.kind_of? Expression and l.op == :* and l.lexpr % r == 0
652
- Expression[l.lexpr/r, :*, l.rexpr].reduce_rec
653
- end
654
- elsif @op == :-
655
- if l == :unknown or r == :unknown; :unknown
656
- elsif not l and r.kind_of? Expression and (r.op == :- or r.op == :+)
657
- if r.op == :- # no lexpr (reduced)
658
- # -(-x) => x
659
- r.rexpr
660
- else # :+ and lexpr (r is reduced)
661
- # -(a+b) => (-a)+(-b)
662
- Expression[[:-, r.lexpr], :+, [:-, r.rexpr]].reduce_rec
663
- end
664
- elsif l.kind_of? Expression and l.op == :+ and l.lexpr == r
665
- # shortcircuit for a common occurence [citation needed]
666
- # (a+b)-a
667
- l.rexpr
668
- elsif l
669
- # a-b => a+(-b)
670
- Expression[l, :+, [:-, r]].reduce_rec
671
- end
672
- elsif @op == :+
673
- if l == :unknown or r == :unknown; :unknown
674
- elsif not l; r # +x => x
675
- elsif r == 0; l # x+0 => x
676
- elsif l.kind_of?(::Numeric)
677
- if r.kind_of? Expression and r.op == :+
678
- # 1+(x+y) => x+(y+1)
679
- Expression[r.lexpr, :+, [r.rexpr, :+, l]].reduce_rec
680
- else
681
- # 1+a => a+1
682
- Expression[r, :+, l].reduce_rec
683
- end
684
- # (a+b)+foo => a+(b+foo)
685
- elsif l.kind_of? Expression and l.op == @op; Expression[l.lexpr, @op, [l.rexpr, @op, r]].reduce_rec
686
- elsif l.kind_of? Expression and r.kind_of? Expression and l.op == :% and r.op == :% and l.rexpr.kind_of?(::Integer) and l.rexpr == r.rexpr
687
- Expression[[l.lexpr, :+, r.lexpr], :%, l.rexpr].reduce_rec
688
- else
689
- reduce_rec_add(l, r)
690
- end
544
+ elsif rp = @@reduce_op[@op]
545
+ rp[self, l, r, cb]
691
546
  end
692
547
 
693
548
  ret = case v
694
549
  when nil
695
550
  # no dup if no new value
696
551
  (r == :unknown or l == :unknown) ? :unknown :
697
- ((r == @rexpr and l == @lexpr) ? self : Expression[l, @op, r])
552
+ ((r == @rexpr and l == @lexpr) ? self : Expression.new(@op, r, l))
698
553
  when Expression
699
554
  (v.lexpr == :unknown or v.rexpr == :unknown) ? :unknown : v
700
555
  else v
701
556
  end
702
- if @@reduce_lambda and ret.kind_of? ExpressionType and newret = @@reduce_lambda[ret] and newret != ret
703
- if newret.kind_of? ExpressionType
704
- ret = newret.reduce_rec
557
+ if cb and ret.kind_of?(ExpressionType) and newret = cb[ret] and newret != ret
558
+ if newret.kind_of?(ExpressionType)
559
+ ret = newret.reduce_rec(cb)
705
560
  else
706
561
  ret = newret
707
562
  end
@@ -709,71 +564,267 @@ class Expression < ExpressionType
709
564
  ret
710
565
  end
711
566
 
567
+ @@reduce_op = {
568
+ :+ => lambda { |e, l, r, cb| e.reduce_op_plus(l, r, cb) },
569
+ :- => lambda { |e, l, r, cb| e.reduce_op_minus(l, r, cb) },
570
+ :'&&' => lambda { |e, l, r, cb| e.reduce_op_andand(l, r, cb) },
571
+ :'||' => lambda { |e, l, r, cb| e.reduce_op_oror(l, r, cb) },
572
+ :>> => lambda { |e, l, r, cb| e.reduce_op_shr(l, r, cb) },
573
+ :<< => lambda { |e, l, r, cb| e.reduce_op_shl(l, r, cb) },
574
+ :'!' => lambda { |e, l, r, cb| e.reduce_op_not(l, r, cb) },
575
+ :== => lambda { |e, l, r, cb| e.reduce_op_eql(l, r, cb) },
576
+ :'!=' => lambda { |e, l, r, cb| e.reduce_op_neq(l, r, cb) },
577
+ :^ => lambda { |e, l, r, cb| e.reduce_op_xor(l, r, cb) },
578
+ :& => lambda { |e, l, r, cb| e.reduce_op_and(l, r, cb) },
579
+ :| => lambda { |e, l, r, cb| e.reduce_op_or(l, r, cb) },
580
+ :* => lambda { |e, l, r, cb| e.reduce_op_times(l, r, cb) },
581
+ :/ => lambda { |e, l, r, cb| e.reduce_op_div(l, r, cb) },
582
+ :% => lambda { |e, l, r, cb| e.reduce_op_mod(l, r, cb) },
583
+ }
584
+
585
+
586
+ def self.reduce_op
587
+ @@reduce_op
588
+ end
712
589
 
713
- # a+(b+(c+(-a))) => b+c+0
714
- # a+((-a)+(b+c)) => 0+b+c
715
- def reduce_rec_add(l, r)
716
- if l.kind_of? Expression and l.op == :- and not l.lexpr
717
- neg_l = l.rexpr
590
+ def reduce_op_plus(l, r, cb)
591
+ if not l; r # +x => x
592
+ elsif r == 0; l # x+0 => x
593
+ elsif l == :unknown or r == :unknown; :unknown
594
+ elsif l.kind_of?(::Numeric)
595
+ if r.kind_of? Expression and r.op == :+
596
+ # 1+(x+y) => x+(y+1)
597
+ Expression[r.lexpr, :+, [r.rexpr, :+, l]].reduce_rec(cb)
598
+ else
599
+ # 1+a => a+1
600
+ Expression[r, :+, l].reduce_rec(cb)
601
+ end
602
+ # (a+b)+foo => a+(b+foo)
603
+ elsif l.kind_of? Expression and l.op == :+; Expression[l.lexpr, :+, [l.rexpr, :+, r]].reduce_rec(cb)
604
+ elsif l.kind_of? Expression and r.kind_of? Expression and l.op == :% and r.op == :% and l.rexpr.kind_of?(::Integer) and l.rexpr == r.rexpr
605
+ Expression[[l.lexpr, :+, r.lexpr], :%, l.rexpr].reduce_rec(cb)
606
+ elsif l.kind_of? Expression and l.op == :- and not l.lexpr
607
+ reduce_rec_add_rec(r, l.rexpr, cb)
608
+ elsif l.kind_of? Expression and r.kind_of? Expression and l.op == :& and r.op == :& and l.rexpr.kind_of?(::Integer) and r.rexpr.kind_of?(::Integer) and l.rexpr & r.rexpr == 0
609
+ # (a&0xf0)+(b&0x0f) => (a&0xf0)|(b&0x0f)
610
+ Expression[l, :|, r].reduce_rec(cb)
718
611
  else
719
- neg_l = Expression[:-, l]
612
+ reduce_rec_add_rec(r, Expression.new(:-, l, nil), cb)
613
+ end
614
+ end
615
+
616
+ def reduce_rec_add_rec(cur, neg_l, cb)
617
+ if neg_l == cur
618
+ # -l found
619
+ 0
620
+ elsif cur.kind_of?(Expression) and cur.op == :+
621
+ # recurse
622
+ if newl = reduce_rec_add_rec(cur.lexpr, neg_l, cb)
623
+ Expression[newl, cur.op, cur.rexpr].reduce_rec(cb)
624
+ elsif newr = reduce_rec_add_rec(cur.rexpr, neg_l, cb)
625
+ Expression[cur.lexpr, cur.op, newr].reduce_rec(cb)
626
+ end
627
+ end
628
+ end
629
+
630
+ def reduce_op_minus(l, r, cb)
631
+ if l == :unknown or r == :unknown; :unknown
632
+ elsif not l and r.kind_of? Expression and (r.op == :- or r.op == :+)
633
+ if r.op == :- # no lexpr (reduced)
634
+ # -(-x) => x
635
+ r.rexpr
636
+ else # :+ and lexpr (r is reduced)
637
+ # -(a+b) => (-a)+(-b)
638
+ Expression.new(:+, Expression.new(:-, r.rexpr, nil), Expression.new(:-, r.lexpr, nil)).reduce_rec(cb)
639
+ end
640
+ elsif l.kind_of? Expression and l.op == :+ and l.lexpr == r
641
+ # shortcircuit for a common occurence [citation needed]
642
+ # (a+b)-a
643
+ l.rexpr
644
+ elsif l
645
+ # a-b => a+(-b)
646
+ Expression[l, :+, [:-, r]].reduce_rec(cb)
647
+ end
648
+ end
649
+
650
+ def reduce_op_andand(l, r, cb)
651
+ if l == 0 # shortcircuit eval
652
+ 0
653
+ elsif l == 1
654
+ Expression[r, :'!=', 0].reduce_rec(cb)
655
+ elsif r == 0
656
+ 0 # XXX l could be a special ExprType with sideeffects ?
720
657
  end
658
+ end
659
+
660
+ def reduce_op_oror(l, r, cb)
661
+ if l.kind_of?(::Numeric) and l != 0 # shortcircuit eval
662
+ 1
663
+ elsif l == 0
664
+ Expression[r, :'!=', 0].reduce_rec(cb)
665
+ elsif r == 0
666
+ Expression[l, :'!=', 0].reduce_rec(cb)
667
+ end
668
+ end
669
+
670
+ def reduce_op_shr(l, r, cb)
671
+ if l == 0; 0
672
+ elsif r == 0; l
673
+ elsif l.kind_of? Expression and l.op == :>>
674
+ Expression[l.lexpr, :>>, [l.rexpr, :+, r]].reduce_rec(cb)
675
+ elsif r.kind_of? Integer and l.kind_of? Expression and [:&, :|, :^].include? l.op
676
+ # (a | b) << i => (a<<i | b<<i)
677
+ Expression[[l.lexpr, :>>, r], l.op, [l.rexpr, :>>, r]].reduce_rec(cb)
678
+ end
679
+ end
721
680
 
722
- # recursive search & replace -lexpr by 0
723
- simplifier = lambda { |cur|
724
- if neg_l == cur
725
- # -l found
726
- 0
727
- elsif cur.kind_of? Expression and cur.op == :+
728
- # recurse
729
- if newl = simplifier[cur.lexpr]
730
- Expression[newl, cur.op, cur.rexpr].reduce_rec
731
- elsif newr = simplifier[cur.rexpr]
732
- Expression[cur.lexpr, cur.op, newr].reduce_rec
681
+ def reduce_op_shl(l, r, cb)
682
+ if l == 0; 0
683
+ elsif r == 0; l
684
+ elsif l.kind_of? Expression and l.op == :<<
685
+ Expression[l.lexpr, :<<, [l.rexpr, :+, r]].reduce_rec(cb)
686
+ elsif l.kind_of? Expression and l.op == :>> and r.kind_of? Integer and l.rexpr.kind_of? Integer
687
+ # (a >> 1) << 1 == a & 0xfffffe
688
+ if r == l.rexpr
689
+ Expression[l.lexpr, :&, (-1 << r)].reduce_rec(cb)
690
+ elsif r > l.rexpr
691
+ Expression[[l.lexpr, :<<, r-l.rexpr], :&, (-1 << r)].reduce_rec(cb)
692
+ else
693
+ Expression[[l.lexpr, :>>, l.rexpr-r], :&, (-1 << r)].reduce_rec(cb)
694
+ end
695
+ elsif r.kind_of?(::Integer) and l.kind_of?(Expression) and [:&, :|, :^].include?(l.op)
696
+ # (a | b) << i => (a<<i | b<<i)
697
+ Expression[[l.lexpr, :<<, r], l.op, [l.rexpr, :<<, r]].reduce_rec(cb)
698
+ end
699
+ end
700
+
701
+ NEG_OP = {:'==' => :'!=', :'!=' => :'==', :< => :>=, :> => :<=, :<= => :>, :>= => :<}
702
+
703
+ def reduce_op_not(l, r, cb)
704
+ if r.kind_of? Expression and nop = NEG_OP[r.op]
705
+ Expression[r.lexpr, nop, r.rexpr].reduce_rec(cb)
706
+ end
707
+ end
708
+
709
+ def reduce_op_eql(l, r, cb)
710
+ if l == r; 1
711
+ elsif r == 0 and l.kind_of? Expression and nop = NEG_OP[l.op]
712
+ Expression[l.lexpr, nop, l.rexpr].reduce_rec(cb)
713
+ elsif r == 1 and l.kind_of? Expression and NEG_OP[l.op]
714
+ l
715
+ elsif r == 0 and l.kind_of? Expression and l.op == :+
716
+ if l.rexpr.kind_of? Expression and l.rexpr.op == :- and not l.rexpr.lexpr
717
+ Expression[l.lexpr, :==, l.rexpr.rexpr].reduce_rec(cb)
718
+ elsif l.rexpr.kind_of?(::Integer)
719
+ Expression[l.lexpr, :==, -l.rexpr].reduce_rec(cb)
720
+ end
721
+ end
722
+ end
723
+
724
+ def reduce_op_neq(l, r, cb)
725
+ if l == r; 0
726
+ end
727
+ end
728
+
729
+ def reduce_op_xor(l, r, cb)
730
+ if l == :unknown or r == :unknown; :unknown
731
+ elsif l == 0; r
732
+ elsif r == 0; l
733
+ elsif l == r; 0
734
+ elsif r == 1 and l.kind_of? Expression and NEG_OP[l.op]
735
+ Expression[nil, :'!', l].reduce_rec(cb)
736
+ elsif l.kind_of?(::Numeric)
737
+ if r.kind_of? Expression and r.op == :^
738
+ # 1^(x^y) => x^(y^1)
739
+ Expression[r.lexpr, :^, [r.rexpr, :^, l]].reduce_rec(cb)
740
+ else
741
+ # 1^a => a^1
742
+ Expression[r, :^, l].reduce_rec(cb)
743
+ end
744
+ elsif l.kind_of? Expression and l.op == :^
745
+ # (a^b)^c => a^(b^c)
746
+ Expression[l.lexpr, :^, [l.rexpr, :^, r]].reduce_rec(cb)
747
+ elsif r.kind_of? Expression and r.op == :^
748
+ if r.rexpr == l
749
+ # a^(a^b) => b
750
+ r.lexpr
751
+ elsif r.lexpr == l
752
+ # a^(b^a) => b
753
+ r.rexpr
754
+ else
755
+ # a^(b^(c^(a^d))) => b^(a^(c^(a^d)))
756
+ # XXX ugly..
757
+ tr = r
758
+ found = false
759
+ while not found and tr.kind_of?(Expression) and tr.op == :^
760
+ found = true if tr.lexpr == l or tr.rexpr == l
761
+ tr = tr.rexpr
762
+ end
763
+ if found
764
+ Expression[r.lexpr, :^, [l, :^, r.rexpr]].reduce_rec(cb)
733
765
  end
734
766
  end
735
- }
767
+ elsif l.kind_of?(Expression) and l.op == :& and l.rexpr.kind_of?(::Integer) and (l.rexpr & (l.rexpr+1)) == 0
768
+ if r.kind_of?(::Integer) and r & l.rexpr == r
769
+ # (a&0xfff)^12 => (a^12)&0xfff
770
+ Expression[[l.lexpr, :^, r], :&, l.rexpr].reduce_rec(cb)
771
+ elsif r.kind_of?(Expression) and r.op == :& and r.rexpr.kind_of?(::Integer) and r.rexpr == l.rexpr
772
+ # (a&0xfff)^(b&0xfff) => (a^b)&0xfff
773
+ Expression[[l.lexpr, :^, r.lexpr], :&, l.rexpr].reduce_rec(cb)
774
+ end
775
+ end
776
+ end
736
777
 
737
- simplifier[r]
738
- end
739
-
740
- # expr & 0xffff
741
- def reduce_rec_mod2(e, mask)
742
- case e.op
743
- when :+, :^
744
- if e.lexpr.kind_of?(Expression) and e.lexpr.op == :& and
745
- e.lexpr.rexpr.kind_of?(::Integer) and e.lexpr.rexpr & mask == mask
746
- # ((a&m) + b) & m => (a+b) & m
747
- Expression[[e.lexpr.lexpr, e.op, e.rexpr], :&, mask].reduce_rec
748
- elsif e.rexpr.kind_of?(Expression) and e.rexpr.op == :& and
749
- e.rexpr.rexpr.kind_of?(::Integer) and e.rexpr.rexpr & mask == mask
750
- # (a + (b&m)) & m => (a+b) & m
751
- Expression[[e.lexpr, e.op, e.rexpr.lexpr], :&, mask].reduce_rec
778
+ def reduce_op_and(l, r, cb)
779
+ if l == 0 or r == 0; 0
780
+ elsif r == 1 and l.kind_of?(Expression) and [:'==', :'!=', :<, :>, :<=, :>=].include?(l.op)
781
+ l
782
+ elsif l == r; l
783
+ elsif l.kind_of?(Integer); Expression[r, :&, l].reduce_rec(cb)
784
+ elsif l.kind_of?(Expression) and l.op == :&; Expression[l.lexpr, :&, [l.rexpr, :&, r]].reduce_rec(cb)
785
+ elsif l.kind_of?(Expression) and [:|, :^].include?(l.op) and r.kind_of?(Integer) and (l.op == :| or (r & (r+1)) != 0)
786
+ # (a ^| b) & i => (a&i ^| b&i)
787
+ Expression[[l.lexpr, :&, r], l.op, [l.rexpr, :&, r]].reduce_rec(cb)
788
+ elsif r.kind_of?(::Integer) and l.kind_of?(ExpressionType) and r == l.max_bits_mask
789
+ l
790
+ elsif r.kind_of?(::Integer) and l.kind_of?(Expression) and (r & (r+1)) == 0
791
+ # foo & 0xffff
792
+ case l.op
793
+ when :+, :^
794
+ if l.lexpr.kind_of?(Expression) and l.lexpr.op == :& and
795
+ l.lexpr.rexpr.kind_of?(::Integer) and l.lexpr.rexpr & r == r
796
+ # ((a&m) + b) & m => (a+b) & m
797
+ Expression[[l.lexpr.lexpr, l.op, l.rexpr], :&, r].reduce_rec(cb)
798
+ elsif l.rexpr.kind_of?(Expression) and l.rexpr.op == :& and
799
+ l.rexpr.rexpr.kind_of?(::Integer) and l.rexpr.rexpr & r == r
800
+ # (a + (b&m)) & m => (a+b) & m
801
+ Expression[[l.lexpr, l.op, l.rexpr.lexpr], :&, r].reduce_rec(cb)
802
+ else
803
+ Expression[l, :&, r]
804
+ end
805
+ when :|
806
+ # rol/ror composition
807
+ reduce_rec_composerol(l, r, cb)
752
808
  else
753
- Expression[e, :&, mask]
809
+ Expression[l, :&, r]
754
810
  end
755
- when :|
756
- # rol/ror composition
757
- reduce_rec_composerol e, mask
758
- else
759
- Expression[e, :&, mask]
760
811
  end
761
812
  end
762
813
 
763
814
  # a check to see if an Expr is the composition of two rotations (rol eax, 4 ; rol eax, 6 => rol eax, 10)
764
815
  # this is a bit too ugly to stay in the main reduce_rec body.
765
- def reduce_rec_composerol(e, mask)
816
+ def reduce_rec_composerol(e, mask, cb)
766
817
  m = Expression[['var', :sh_op, 'amt'], :|, ['var', :inv_sh_op, 'inv_amt']]
767
818
  if vars = e.match(m, 'var', :sh_op, 'amt', :inv_sh_op, 'inv_amt') and vars[:sh_op] == {:>> => :<<, :<< => :>>}[vars[:inv_sh_op]] and
768
819
  ((vars['amt'].kind_of?(::Integer) and vars['inv_amt'].kind_of?(::Integer) and ampl = vars['amt'] + vars['inv_amt']) or
769
- (vars['amt'].kind_of? Expression and vars['amt'].op == :% and vars['amt'].rexpr.kind_of? ::Integer and
820
+ (vars['amt'].kind_of? Expression and vars['amt'].op == :% and vars['amt'].rexpr.kind_of?(::Integer) and
770
821
  vars['inv_amt'].kind_of? Expression and vars['inv_amt'].op == :% and vars['amt'].rexpr == vars['inv_amt'].rexpr and ampl = vars['amt'].rexpr)) and
771
822
  mask == (1<<ampl)-1 and vars['var'].kind_of? Expression and # it's a rotation
772
823
 
773
824
  vars['var'].op == :& and vars['var'].rexpr == mask and
774
825
  ivars = vars['var'].lexpr.match(m, 'var', :sh_op, 'amt', :inv_sh_op, 'inv_amt') and ivars[:sh_op] == {:>> => :<<, :<< => :>>}[ivars[:inv_sh_op]] and
775
826
  ((ivars['amt'].kind_of?(::Integer) and ivars['inv_amt'].kind_of?(::Integer) and ampl = ivars['amt'] + ivars['inv_amt']) or
776
- (ivars['amt'].kind_of? Expression and ivars['amt'].op == :% and ivars['amt'].rexpr.kind_of? ::Integer and
827
+ (ivars['amt'].kind_of? Expression and ivars['amt'].op == :% and ivars['amt'].rexpr.kind_of?(::Integer) and
777
828
  ivars['inv_amt'].kind_of? Expression and ivars['inv_amt'].op == :% and ivars['amt'].rexpr == ivars['inv_amt'].rexpr and ampl = ivars['amt'].rexpr))
778
829
  if ivars[:sh_op] != vars[:sh_op]
779
830
  # ensure the rotations are the same orientation
@@ -782,12 +833,54 @@ class Expression < ExpressionType
782
833
  end
783
834
  amt = Expression[[vars['amt'], :+, ivars['amt']], :%, ampl]
784
835
  invamt = Expression[[vars['inv_amt'], :+, ivars['inv_amt']], :%, ampl]
785
- Expression[[[[ivars['var'], :&, mask], vars[:sh_op], amt], :|, [[ivars['var'], :&, mask], vars[:inv_sh_op], invamt]], :&, mask].reduce_rec
836
+ Expression[[[[ivars['var'], :&, mask], vars[:sh_op], amt], :|, [[ivars['var'], :&, mask], vars[:inv_sh_op], invamt]], :&, mask].reduce_rec(cb)
786
837
  else
787
838
  Expression[e, :&, mask]
788
839
  end
789
840
  end
790
841
 
842
+ def reduce_op_or(l, r, cb)
843
+ if l == 0; r
844
+ elsif r == 0; l
845
+ elsif l == -1 or r == -1; -1
846
+ elsif l == r; l
847
+ elsif l.kind_of? Integer; Expression[r, :|, l].reduce_rec(cb)
848
+ elsif l.kind_of? Expression and l.op == :|
849
+ # (a|b)|c => a|(b|c)
850
+ Expression[l.lexpr, :|, [l.rexpr, :|, r]].reduce_rec(cb)
851
+ elsif l.kind_of? Expression and l.op == :& and r.kind_of? Expression and r.op == :& and l.lexpr == r.lexpr
852
+ # (a&b)|(a&c) => a&(b|c)
853
+ Expression[l.lexpr, :&, [l.rexpr, :|, r.rexpr]].reduce_rec(cb)
854
+ end
855
+ end
856
+
857
+ def reduce_op_times(l, r, cb)
858
+ if l == 0 or r == 0; 0
859
+ elsif l == 1; r
860
+ elsif r == 1; l
861
+ elsif r.kind_of? Integer; Expression[r, :*, l].reduce_rec(cb)
862
+ elsif r.kind_of? Expression and r.op == :*; Expression[[l, :*, r.lexpr], :*, r.rexpr].reduce_rec(cb)
863
+ elsif l.kind_of? Integer and r.kind_of? Expression and r.op == :* and r.lexpr.kind_of? Integer; Expression[l*r.lexpr, :*, r.rexpr].reduce_rec(cb) # XXX need & regsize..
864
+ elsif l.kind_of? Integer and r.kind_of? Expression and r.op == :+ and r.rexpr.kind_of? Integer; Expression[[l, :*, r.lexpr], :+, l*r.rexpr].reduce_rec(cb)
865
+ end
866
+ end
867
+
868
+ def reduce_op_div(l, r, cb)
869
+ if r == 0
870
+ elsif r.kind_of? Integer and l.kind_of? Expression and l.op == :+ and l.rexpr.kind_of? Integer and l.rexpr % r == 0
871
+ Expression[[l.lexpr, :/, r], :+, l.rexpr/r].reduce_rec(cb)
872
+ elsif r.kind_of? Integer and l.kind_of? Expression and l.op == :* and l.lexpr % r == 0
873
+ Expression[l.lexpr/r, :*, l.rexpr].reduce_rec(cb)
874
+ end
875
+ end
876
+
877
+ def reduce_op_mod(l, r, cb)
878
+ if r.kind_of?(Integer) and r != 0 and (r & (r-1) == 0)
879
+ Expression[l, :&, r-1].reduce_rec(cb)
880
+ end
881
+ end
882
+
883
+
791
884
  # a pattern-matching method
792
885
  # Expression[42, :+, 28].match(Expression['any', :+, 28], 'any') => {'any' => 42}
793
886
  # Expression[42, :+, 28].match(Expression['any', :+, 'any'], 'any') => false
@@ -803,7 +896,7 @@ class Expression < ExpressionType
803
896
  if targ and vars[targ]
804
897
  return false if exp != vars[targ]
805
898
  elsif targ and vars.has_key? targ
806
- return false if not vars[targ] = exp
899
+ vars[targ] = exp
807
900
  elsif targ.kind_of? ExpressionType
808
901
  return false if not exp.kind_of? ExpressionType or not exp.match_rec(targ, vars)
809
902
  else
@@ -816,24 +909,29 @@ class Expression < ExpressionType
816
909
  # returns the array of non-numeric members of the expression
817
910
  # if a variables appears 3 times, it will be present 3 times in the returned array
818
911
  def externals
819
- [@rexpr, @lexpr].inject([]) { |a, e|
912
+ a = []
913
+ [@rexpr, @lexpr].each { |e|
820
914
  case e
821
915
  when ExpressionType; a.concat e.externals
822
916
  when nil, ::Numeric; a
823
917
  else a << e
824
918
  end
825
919
  }
920
+ a
826
921
  end
827
922
 
828
923
  # returns the externals that appears in the expression, does not walk through other ExpressionType
829
- def expr_externals
830
- [@rexpr, @lexpr].inject([]) { |a, e|
924
+ def expr_externals(include_exprs=false)
925
+ a = []
926
+ [@rexpr, @lexpr].each { |e|
831
927
  case e
832
- when Expression; a.concat e.expr_externals
833
- when nil, ::Numeric, ExpressionType; a
928
+ when Expression; a.concat e.expr_externals(include_exprs)
929
+ when nil, ::Numeric; a
930
+ when ExpressionType; include_exprs ? a << e : a
834
931
  else a << e
835
932
  end
836
933
  }
934
+ a
837
935
  end
838
936
 
839
937
  def inspect
@@ -843,6 +941,26 @@ class Expression < ExpressionType
843
941
  Unknown = self[:unknown]
844
942
  end
845
943
 
944
+ # An Expression with a custom string representation
945
+ # used to show #define constants, struct offsets, func local vars, etc
946
+ class ExpressionString < ExpressionType
947
+ attr_accessor :expr, :str, :type, :hide_str
948
+ def reduce(&b); expr.reduce(&b); end
949
+ def reduce_rec(cb=@@reduce_lambda); expr.reduce_rec(cb); end
950
+ def bind(*a); expr.bind(*a); end
951
+ def externals; expr.externals; end
952
+ def expr_externals; expr.expr_externals; end
953
+ def match_rec(*a); expr.match_rec(*a); end
954
+ def max_bits_mask; expr.max_bits_mask; end
955
+ def initialize(expr, str, type=nil)
956
+ @expr = Expression[expr]
957
+ @str = str
958
+ @type = type
959
+ end
960
+ def render_str ; [str] ; end
961
+ def inspect ; "ExpressionString.new(#{@expr.inspect}, #{str.inspect}, #{type.inspect})" ; end
962
+ end
963
+
846
964
  # an EncodedData relocation, specifies a value to patch in
847
965
  class Relocation
848
966
  # the relocation value (an Expression)
@@ -855,7 +973,7 @@ class Relocation
855
973
  include Backtrace
856
974
 
857
975
  def initialize(target, type, endianness, backtrace = nil)
858
- raise ArgumentError, "bad args #{[target, type, endianness].inspect}" if not target.kind_of? Expression or not type.kind_of? ::Symbol or not endianness.kind_of? ::Symbol
976
+ raise ArgumentError, "bad args #{[target, type, endianness].inspect}" if not target.kind_of? Expression or not type.kind_of?(::Symbol) or not endianness.kind_of?(::Symbol)
859
977
  @target, @type, @endianness, @backtrace = target, type, endianness, backtrace
860
978
  end
861
979
 
@@ -889,8 +1007,15 @@ class EncodedData
889
1007
  attr_reader :ptr # custom writer
890
1008
  def ptr=(p) @ptr = @export[p] || p end
891
1009
 
1010
+ INITIAL_DATA = ''
1011
+ INITIAL_DATA.force_encoding('BINARY') if INITIAL_DATA.respond_to?(:force_encoding)
1012
+
892
1013
  # opts' keys in :reloc, :export, :virtsize, defaults to empty/empty/data.length
893
- def initialize(data = '', opts={})
1014
+ def initialize(data=INITIAL_DATA.dup, opts={})
1015
+ if data.respond_to?(:force_encoding) and data.encoding.name != 'ASCII-8BIT' and data.length > 0
1016
+ puts "Forcing edata.data.encoding = BINARY at", caller if $DEBUG
1017
+ data = data.dup.force_encoding('binary')
1018
+ end
894
1019
  @data = data
895
1020
  @reloc = opts[:reloc] || {}
896
1021
  @export = opts[:export] || {}
@@ -904,9 +1029,10 @@ class EncodedData
904
1029
  if set_inv or not @inv_export[off]
905
1030
  @inv_export[off] = label
906
1031
  end
1032
+ label
907
1033
  end
908
1034
 
909
- def del_export(label, off=@ptr)
1035
+ def del_export(label, off=@export[label])
910
1036
  @export.delete label
911
1037
  if e = @export.index(off)
912
1038
  @inv_export[off] = e
@@ -942,6 +1068,7 @@ class EncodedData
942
1068
  # if numeric, replace the raw data with the encoding of this value (+fill+s preceding data if needed) and remove the reloc
943
1069
  # if replace_target is true, the reloc target is replaced with its bound counterpart
944
1070
  def fixup_choice(binding, replace_target)
1071
+ return if binding.empty?
945
1072
  @reloc.keys.each { |off|
946
1073
  val = @reloc[off].target.bind(binding).reduce
947
1074
  if val.kind_of? Integer
@@ -973,13 +1100,15 @@ class EncodedData
973
1100
  return {} if not key
974
1101
  base = (@export[key] == 0 ? key : Expression[key, :-, @export[key]])
975
1102
  end
976
- @export.inject({}) { |binding, (n, o)| binding.update n => Expression.new(:+, o, base) }
1103
+ binding = {}
1104
+ @export.each { |n, o| binding.update n => Expression.new(:+, o, base) }
1105
+ binding
977
1106
  end
978
1107
 
979
1108
  # returns an array of variables that needs to be defined for a complete #fixup
980
1109
  # ie the list of externals for all relocations
981
- def reloc_externals
982
- @reloc.values.map { |r| r.target.externals }.flatten.uniq - @export.keys
1110
+ def reloc_externals(interns = @export.keys)
1111
+ @reloc.values.map { |r| r.target.externals }.flatten.uniq - interns
983
1112
  end
984
1113
 
985
1114
  # returns the offset where the relocation for target t is to be applied
@@ -1007,11 +1136,11 @@ class EncodedData
1007
1136
  ((val + len - 1) / len).to_i * len
1008
1137
  end
1009
1138
 
1010
- # concatenation of another +EncodedData+ (or nil/Fixnum/anything supporting String#<<)
1011
- def << other
1139
+ # concatenation of another +EncodedData+ (or nil/Integer/anything supporting String#<<)
1140
+ def <<(other)
1012
1141
  case other
1013
1142
  when nil
1014
- when ::Fixnum
1143
+ when ::Integer
1015
1144
  fill
1016
1145
  @data = @data.to_str if not @data.kind_of? String
1017
1146
  @data << other
@@ -1030,13 +1159,19 @@ class EncodedData
1030
1159
  other.inv_export.each { |k, v| @inv_export[@virtsize + k] = v }
1031
1160
  end
1032
1161
  if @data.empty?; @data = other.data.dup
1162
+ elsif other.empty?
1033
1163
  elsif not @data.kind_of?(String); @data = @data.to_str << other.data
1034
1164
  else @data << other.data
1035
1165
  end
1036
1166
  @virtsize += other.virtsize
1037
1167
  else
1038
1168
  fill
1169
+ if other.respond_to?(:force_encoding) and other.encoding.name != 'ASCII-8BIT' and other.length > 0
1170
+ puts "Forcing edata.data.encoding = BINARY at", caller if $DEBUG
1171
+ other = other.dup.force_encoding('binary')
1172
+ end
1039
1173
  if @data.empty?; @data = other.dup
1174
+ elsif other.empty?
1040
1175
  elsif not @data.kind_of?(String); @data = @data.to_str << other
1041
1176
  else @data << other
1042
1177
  end
@@ -1047,7 +1182,7 @@ class EncodedData
1047
1182
  end
1048
1183
 
1049
1184
  # equivalent to dup << other, filters out Integers & nil
1050
- def + other
1185
+ def +(other)
1051
1186
  raise ArgumentError if not other or other.kind_of?(Integer)
1052
1187
  dup << other
1053
1188
  end
@@ -1092,7 +1227,7 @@ class EncodedData
1092
1227
  val = len
1093
1228
  len = nil
1094
1229
  end
1095
- if not len and from.kind_of? ::Range
1230
+ if not len and from.kind_of?(::Range)
1096
1231
  b = from.begin
1097
1232
  e = from.end
1098
1233
  b = @export[b] if @export[b]
@@ -1104,14 +1239,14 @@ class EncodedData
1104
1239
  from = b
1105
1240
  end
1106
1241
  from = @export[from] || from
1107
- raise "invalid offset #{from}" if not from.kind_of? ::Integer
1242
+ raise "invalid offset #{from}" if not from.kind_of?(::Integer)
1108
1243
  from = from + @virtsize if from < 0
1109
1244
 
1110
1245
  if not len
1111
- val = val.chr if val.kind_of? ::Integer
1246
+ val = val.chr if val.kind_of?(::Integer)
1112
1247
  len = val.length
1113
1248
  end
1114
- raise "invalid slice length #{len}" if not len.kind_of? ::Integer or len < 0
1249
+ raise "invalid slice length #{len}" if not len.kind_of?(::Integer) or len < 0
1115
1250
 
1116
1251
  if from >= @virtsize
1117
1252
  len = 0
@@ -1170,24 +1305,24 @@ class EncodedData
1170
1305
  def pattern_scan(pat, chunksz=nil, margin=nil)
1171
1306
  chunksz ||= 4*1024*1024 # scan 4MB at a time
1172
1307
  margin ||= 65536 # add this much bytes at each chunk to find /pat/ over chunk boundaries
1173
- pat = Regexp.new(Regexp.escape(pat)) if pat.kind_of? ::String
1308
+ pat = Regexp.new(Regexp.escape(pat)) if pat.kind_of?(::String)
1174
1309
 
1175
1310
  found = []
1176
1311
  chunkoff = 0
1177
1312
  while chunkoff < @data.length
1178
1313
  chunk = @data[chunkoff, chunksz+margin].to_str
1179
1314
  off = 0
1180
- while match_off = (chunk[off..-1] =~ pat)
1181
- break if off+match_off >= chunksz # match fully in margin
1182
- match_addr = chunkoff + off + match_off
1315
+ while match = chunk[off..-1].match(pat)
1316
+ off += match.pre_match.length
1317
+ m_l = match[0].length
1318
+ break if off >= chunksz # match fully in margin
1319
+ match_addr = chunkoff + off
1183
1320
  found << match_addr if not block_given? or yield(match_addr)
1184
- off += match_off + 1
1185
- # XXX +1 or +lastmatch.length ?
1186
- # 'aaaabc'.pattern_scan(/a*bc/) will match 5 times here
1321
+ off += m_l
1187
1322
  end
1188
1323
  chunkoff += chunksz
1189
1324
  end
1190
- found
1325
+ found
1191
1326
  end
1192
1327
  end
1193
1328
  end