evoasm 0.0.2.pre7

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 (75) hide show
  1. checksums.yaml +7 -0
  2. data/.gemrelease +2 -0
  3. data/.gitignore +16 -0
  4. data/Gemfile +4 -0
  5. data/Gemfile.rake +8 -0
  6. data/Gemfile.rake.lock +51 -0
  7. data/LICENSE.txt +373 -0
  8. data/Makefile +6 -0
  9. data/README.md +43 -0
  10. data/Rakefile +128 -0
  11. data/bin/gdb +2 -0
  12. data/data/tables/README.md +19 -0
  13. data/data/tables/x64.csv +1684 -0
  14. data/data/templates/evoasm-x64.c.erb +319 -0
  15. data/data/templates/evoasm-x64.h.erb +126 -0
  16. data/evoasm.gemspec +30 -0
  17. data/examples/abs.yml +20 -0
  18. data/examples/popcnt.yml +17 -0
  19. data/examples/sym_reg.yml +26 -0
  20. data/exe/evoasm-search +13 -0
  21. data/ext/evoasm_ext/evoasm-alloc.c +145 -0
  22. data/ext/evoasm_ext/evoasm-alloc.h +59 -0
  23. data/ext/evoasm_ext/evoasm-arch.c +44 -0
  24. data/ext/evoasm_ext/evoasm-arch.h +161 -0
  25. data/ext/evoasm_ext/evoasm-bitmap.h +114 -0
  26. data/ext/evoasm_ext/evoasm-buf.c +130 -0
  27. data/ext/evoasm_ext/evoasm-buf.h +47 -0
  28. data/ext/evoasm_ext/evoasm-error.c +31 -0
  29. data/ext/evoasm_ext/evoasm-error.h +75 -0
  30. data/ext/evoasm_ext/evoasm-free-list.c.tmpl +121 -0
  31. data/ext/evoasm_ext/evoasm-free-list.h.tmpl +86 -0
  32. data/ext/evoasm_ext/evoasm-log.c +108 -0
  33. data/ext/evoasm_ext/evoasm-log.h +69 -0
  34. data/ext/evoasm_ext/evoasm-misc.c +23 -0
  35. data/ext/evoasm_ext/evoasm-misc.h +282 -0
  36. data/ext/evoasm_ext/evoasm-param.h +37 -0
  37. data/ext/evoasm_ext/evoasm-search.c +2145 -0
  38. data/ext/evoasm_ext/evoasm-search.h +214 -0
  39. data/ext/evoasm_ext/evoasm-util.h +40 -0
  40. data/ext/evoasm_ext/evoasm-x64.c +275624 -0
  41. data/ext/evoasm_ext/evoasm-x64.h +5436 -0
  42. data/ext/evoasm_ext/evoasm.c +7 -0
  43. data/ext/evoasm_ext/evoasm.h +23 -0
  44. data/ext/evoasm_ext/evoasm_ext.c +1757 -0
  45. data/ext/evoasm_ext/extconf.rb +31 -0
  46. data/lib/evoasm/cli/search.rb +127 -0
  47. data/lib/evoasm/cli.rb +6 -0
  48. data/lib/evoasm/core_ext/array.rb +9 -0
  49. data/lib/evoasm/core_ext/integer.rb +10 -0
  50. data/lib/evoasm/core_ext/kwstruct.rb +13 -0
  51. data/lib/evoasm/core_ext/range.rb +5 -0
  52. data/lib/evoasm/core_ext.rb +1 -0
  53. data/lib/evoasm/error.rb +20 -0
  54. data/lib/evoasm/examples.rb +27 -0
  55. data/lib/evoasm/gen/enum.rb +169 -0
  56. data/lib/evoasm/gen/name_util.rb +80 -0
  57. data/lib/evoasm/gen/state.rb +176 -0
  58. data/lib/evoasm/gen/state_dsl.rb +152 -0
  59. data/lib/evoasm/gen/strio.rb +27 -0
  60. data/lib/evoasm/gen/translator.rb +1102 -0
  61. data/lib/evoasm/gen/version.rb +5 -0
  62. data/lib/evoasm/gen/x64/funcs.rb +495 -0
  63. data/lib/evoasm/gen/x64/inst.rb +781 -0
  64. data/lib/evoasm/gen/x64.rb +237 -0
  65. data/lib/evoasm/gen.rb +8 -0
  66. data/lib/evoasm/program.rb +23 -0
  67. data/lib/evoasm/search.rb +40 -0
  68. data/lib/evoasm/tasks/gen_task.rb +86 -0
  69. data/lib/evoasm/tasks/template_task.rb +52 -0
  70. data/lib/evoasm/version.rb +3 -0
  71. data/lib/evoasm.rb +22 -0
  72. data/test/test_helper.rb +1 -0
  73. data/test/x64/test_helper.rb +19 -0
  74. data/test/x64/x64_test.rb +87 -0
  75. metadata +221 -0
@@ -0,0 +1,237 @@
1
+ module Evoasm::Gen
2
+ module X64
3
+ MNEM_BLACKLIST = %w()
4
+
5
+ # RFLAGS either not used at all
6
+ # or not read by any non-system instruction
7
+ IGNORED_RFLAGS = %i(RF VIF AC VM NT TF DF IF AF)
8
+
9
+ # Exception flag/mask bits. Mostly meant to be checked
10
+ # by the user, which we are not doing at the moment
11
+ IGNORED_MXCSR = %i(PE UE OE ME ZE DE IE PM UM OM ZM DM IM MM)
12
+ REGISTERS = {
13
+ ip: %i(IP),
14
+ rflags: %i(OF SF ZF PF CF),
15
+ mxcsr: %i(FZ RC DAZ),
16
+ gp: %i(A C D B SP BP SI DI 8 9 10 11 12 13 14 15),
17
+ mm: %i(MM0 MM1 MM2 MM3 MM4 MM5 MM6 MM7),
18
+ xmm: %i(XMM0 XMM1 XMM2 XMM3 XMM4 XMM5 XMM6 XMM7 XMM8 XMM9 XMM10 XMM11 XMM12 XMM13 XMM14 XMM15),
19
+ zmm: %i(ZMM16 ZMM17 ZMM18 ZMM19 ZMM20 ZMM21 ZMM22 ZMM23 ZMM24 ZMM25 ZMM26 ZMM27 ZMM28 ZMM29 ZMM30 ZMM31)
20
+ }
21
+
22
+ REGISTER_NAMES = REGISTERS.values.flatten
23
+
24
+ CPUID = {
25
+ [0x1, nil] => {
26
+ d: %i(
27
+ fpu
28
+ vme
29
+ de
30
+ pse
31
+ tsc
32
+ msr
33
+ pae
34
+ mce
35
+ cx8
36
+ apic
37
+ reserved
38
+ sep
39
+ mtrr
40
+ pge
41
+ mca
42
+ cmov
43
+ pat
44
+ pse36
45
+ psn
46
+ clfsh
47
+ reserved
48
+ ds
49
+ acpi
50
+ mmx
51
+ fxsr
52
+ sse
53
+ sse2
54
+ ss
55
+ htt
56
+ tm
57
+ ia64
58
+ pbe),
59
+ c: %i(
60
+ sse3
61
+ pclmulqdq
62
+ dtes64
63
+ monitor
64
+ ds_cpl
65
+ vmx
66
+ smx
67
+ est
68
+ tm2
69
+ ssse3
70
+ cnxt_id
71
+ sdbg
72
+ fma
73
+ cx16
74
+ xtpr
75
+ pdcm
76
+ reserved
77
+ pcid
78
+ dca
79
+ sse4_1
80
+ sse4_2
81
+ x2apic
82
+ movbe
83
+ popcnt
84
+ tsc_deadline
85
+ aes
86
+ xsave
87
+ osxsave
88
+ avx
89
+ f16c
90
+ rdrnd
91
+ hypervisor
92
+ )
93
+ },
94
+ [0x7, 0x0] => {
95
+ b: %i(
96
+ fsgsbase
97
+ IA32_TSC_ADJUST
98
+ sgx
99
+ bmi1
100
+ hle
101
+ avx2
102
+ reserved
103
+ smep
104
+ bmi2
105
+ erms
106
+ invpcid
107
+ rtm
108
+ pqm
109
+ FPU_CS_DS_DEPRECATED
110
+ mpx
111
+ pqe
112
+ avx512f
113
+ avx512dq
114
+ rdseed
115
+ adx
116
+ smap
117
+ avx512ifma
118
+ pcommit
119
+ clflushopt
120
+ clwb
121
+ avx512pf
122
+ avx512er
123
+ avx512cd
124
+ sha
125
+ avx512bw
126
+ avx512vl
127
+ ),
128
+
129
+ c: %i(
130
+ prefetchwt1
131
+ avx512vbmi
132
+ reserved
133
+ reserved
134
+ reserved
135
+ reserved
136
+ reserved
137
+ reserved
138
+ reserved
139
+ reserved
140
+ reserved
141
+ reserved
142
+ reserved
143
+ reserved
144
+ reserved
145
+ reserved
146
+ reserved
147
+ reserved
148
+ reserved
149
+ reserved
150
+ reserved
151
+ reserved
152
+ reserved
153
+ reserved
154
+ reserved
155
+ reserved
156
+ reserved
157
+ reserved
158
+ reserved
159
+ reserved
160
+ reserved
161
+ reserved
162
+ )
163
+ },
164
+
165
+ [0x80000001, nil] => {
166
+ d: %i(
167
+ fpu
168
+ vme
169
+ de
170
+ pse
171
+ tsc
172
+ msr
173
+ pae
174
+ mce
175
+ cx8
176
+ apic
177
+ reserved
178
+ syscall
179
+ mtrr
180
+ pge
181
+ mca
182
+ cmov
183
+ pat
184
+ pse36
185
+ reserved
186
+ mp
187
+ nx
188
+ reserved
189
+ mmxext
190
+ mmx
191
+ fxsr
192
+ fxsr_opt
193
+ pdpe1gb
194
+ rdtscp
195
+ reserved
196
+ lm
197
+ 3dnowext
198
+ 3dnow
199
+ ),
200
+
201
+ c: %i(
202
+ lahf_lm
203
+ cmp_legacy
204
+ svm
205
+ extapic
206
+ cr8_legacy
207
+ abm
208
+ sse4a
209
+ misalignsse
210
+ 3dnowprefetch
211
+ osvw
212
+ ibs
213
+ xop
214
+ skinit
215
+ wdt
216
+ reserved
217
+ lwp
218
+ fma4
219
+ tce
220
+ nodeid_msr
221
+ reserved
222
+ tbm
223
+ topoext
224
+ perfctr_core
225
+ perfctr_nb
226
+ reserved
227
+ dbx
228
+ perftsc
229
+ pcx_l2i
230
+ reserved
231
+ reserved
232
+ reserved
233
+ )
234
+ }
235
+ }
236
+ end
237
+ end
data/lib/evoasm/gen.rb ADDED
@@ -0,0 +1,8 @@
1
+ require 'evoasm/gen/version'
2
+
3
+ module Evoasm
4
+ module Gen
5
+ end
6
+ end
7
+
8
+ require 'evoasm/gen/generator'
@@ -0,0 +1,23 @@
1
+ require 'evoasm/search'
2
+
3
+ module Evoasm
4
+ class Program
5
+ include Search::Util
6
+
7
+ def run(*input_example)
8
+ run_all(input_example).first
9
+ end
10
+
11
+ def run_all(*input_examples)
12
+ input_examples, input_arity = flatten_examples input_examples
13
+ p input_examples, input_arity
14
+ a = __run__ input_examples, input_arity
15
+ p a
16
+ a
17
+ end
18
+
19
+ def disassemble(*args)
20
+ buffer.disassemble(*args)
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,40 @@
1
+ module Evoasm
2
+ class Search
3
+ module Util
4
+ def flatten_examples(examples)
5
+ arity = check_arity examples
6
+
7
+ [examples.flatten, arity]
8
+ end
9
+
10
+ def check_arity(examples)
11
+ arity = Array(examples.first).size
12
+ examples.each do |example|
13
+ example_arity = Array(example).size
14
+ if arity && arity != example_arity
15
+ raise ArgumentError, "invalid arity for example '#{example}'"\
16
+ " (#{example_arity} for #{arity})"
17
+ end
18
+ end
19
+ arity
20
+ end
21
+ end
22
+
23
+ DEFAULT_SEED = (1..64).to_a
24
+ def initialize(arch, examples:, instructions:, kernel_size:,
25
+ program_size:, population_size:, parameters:,
26
+ mutation_rate: 0.10, seed: DEFAULT_SEED, domains: {}, recur_limit: 0)
27
+
28
+ input_examples, output_examples = examples.keys, examples.values
29
+ input_examples, input_arity = flatten_examples input_examples
30
+ output_examples, output_arity = flatten_examples output_examples
31
+
32
+ __initialize__ input_examples, input_arity, output_examples, output_arity,
33
+ arch, population_size, kernel_size, program_size, instructions,
34
+ parameters, mutation_rate, seed, domains, recur_limit
35
+ end
36
+
37
+ include Util
38
+
39
+ end
40
+ end
@@ -0,0 +1,86 @@
1
+ require 'evoasm'
2
+ require 'evoasm/gen/state'
3
+ require 'evoasm/gen/translator'
4
+
5
+ require 'rake'
6
+
7
+ module Evoasm
8
+ module Tasks
9
+ class GenTask < Rake::TaskLib
10
+ include Evoasm::Gen
11
+
12
+ HEADER_N_LINES = 15
13
+ CSV_SEPARATOR = ','
14
+
15
+ attr_accessor :ruby_bindings
16
+ attr_reader :name, :archs
17
+
18
+ ALL_ARCHS = %i(x64)
19
+ X64_TABLE_FILENAME = File.join(Evoasm.data, 'tables', 'x64.csv')
20
+ ARCH_TABLES = {
21
+ x64: X64_TABLE_FILENAME
22
+ }
23
+
24
+ def initialize(name = 'evoasm:gen', &block)
25
+ @ruby_bindings = true
26
+ @name = name
27
+ @archs = ALL_ARCHS
28
+
29
+ block[self] if block
30
+
31
+ define
32
+ end
33
+
34
+ def define
35
+ namespace 'evoasm:gen' do
36
+ archs.each do |arch|
37
+ prereqs = [ARCH_TABLES[arch]]
38
+
39
+ prereqs << Translator.template_path(arch)
40
+ target_path = gen_path(Translator.target_filename(arch))
41
+
42
+ file target_path => prereqs do
43
+ puts "Translating"
44
+ insts = load_insts arch
45
+ translator = Translator.new(arch, insts, ruby: ruby_bindings)
46
+ translator.translate! do |filename, content|
47
+ File.write gen_path(filename), content
48
+ end
49
+ end
50
+
51
+ task "translate:#{arch}" => target_path
52
+ end
53
+
54
+ task 'translate' => archs.map { |arch| "translate:#{arch}" }
55
+ end
56
+
57
+ task name => 'gen:translate'
58
+ end
59
+
60
+ def gen_path(filename)
61
+ File.join Evoasm.root, 'ext', 'evoasm_ext', filename
62
+ end
63
+
64
+ def load_insts(arch)
65
+ send :"load_#{arch}_insts"
66
+ end
67
+
68
+ def load_x64_insts
69
+ require 'evoasm/gen/x64/inst'
70
+
71
+ rows = []
72
+ File.open X64_TABLE_FILENAME do |file|
73
+ file.each_line.with_index do |line, line_idx|
74
+ # header
75
+ next if line_idx == 0
76
+
77
+ row = line.split(CSV_SEPARATOR)
78
+ rows << row
79
+ end
80
+ end
81
+
82
+ Gen::X64::Inst.load(rows)
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,52 @@
1
+ require 'rake'
2
+ require 'yaml'
3
+
4
+ module Evoasm
5
+ module Tasks
6
+ class TemplateTask < Rake::TaskLib
7
+ attr_accessor :source
8
+ attr_accessor :target
9
+ attr_accessor :subs
10
+
11
+ class << self
12
+ attr_reader :all
13
+ end
14
+ @all = []
15
+
16
+ def initialize(&block)
17
+ block[self] if block
18
+ define
19
+ end
20
+
21
+ def define
22
+ srcs = Array(source).map { |f| ext_path f }
23
+ dsts = Array(target).map { |f| gen_path f }
24
+ srcs.zip(dsts).each do |src, dst|
25
+ file dst => src do
26
+ data = File.read src
27
+ subs.sort_by{|k, _| k.length }.reverse.each do |name, value|
28
+ data.gsub! "$#{name}", value.to_s
29
+ data.gsub! "$#{name.upcase}", value.to_s.upcase
30
+ p "$-#{name}"
31
+ data.gsub! "$-#{name}", value.to_s.gsub('_', '-')
32
+ end
33
+ File.write dst, data
34
+ end
35
+ self.class.all << dst
36
+ end
37
+ end
38
+
39
+ def ext_dir
40
+ File.join Evoasm.root, 'ext', 'evoasm_ext'
41
+ end
42
+
43
+ def ext_path(filename)
44
+ File.join ext_dir, filename
45
+ end
46
+
47
+ def gen_path(filename)
48
+ File.join ext_dir, 'gen', filename
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,3 @@
1
+ module Evoasm
2
+ VERSION = "0.0.2.pre7"
3
+ end
data/lib/evoasm.rb ADDED
@@ -0,0 +1,22 @@
1
+ require 'evoasm/version'
2
+ require 'evoasm/core_ext'
3
+
4
+ module Evoasm
5
+ def self.root
6
+ File.expand_path File.join(__dir__, '..')
7
+ end
8
+
9
+ def self.data
10
+ File.join root, 'data'
11
+ end
12
+ end
13
+
14
+ begin
15
+ require 'evoasm_ext'
16
+ rescue LoadError => e
17
+ p e
18
+ end
19
+
20
+ require 'evoasm/search'
21
+ require 'evoasm/program'
22
+ require 'evoasm/error'
@@ -0,0 +1 @@
1
+ require 'minitest/autorun'
@@ -0,0 +1,19 @@
1
+ require_relative '../test_helper'
2
+
3
+ require 'evoasm'
4
+
5
+ module MiniTest::Assertions
6
+ include Evoasm
7
+
8
+ def assert_disassembles_to(disasm, inst_name, **params)
9
+ assert_equal disasm,
10
+ Evoasm::X64.disassemble(@x64.encode(inst_name, params)).first
11
+ end
12
+
13
+ def assert_assembles_to(asm, inst_name, **params)
14
+ assert_equal asm, @x64.encode(inst_name, params)
15
+ end
16
+ end
17
+
18
+ Array.infect_an_assertion :assert_disassembles_to, :must_disassemble_to
19
+ Array.infect_an_assertion :assert_assembles_to, :must_assemble_to
@@ -0,0 +1,87 @@
1
+ require_relative 'test_helper'
2
+
3
+ class X64Test < Minitest::Test
4
+ def setup
5
+ @x64 = Evoasm::X64.new
6
+ @x64.encode :add_r32_rm32, reg0: :A, reg1: :B
7
+ end
8
+
9
+ def test_rm_reg_reg
10
+ assert_disassembles_to 'add rax, rbx', :add_r64_rm64,
11
+ reg0: :A, reg1: :B
12
+ assert_disassembles_to 'add r11, r12', :add_r64_rm64,
13
+ reg0: :R11, reg1: :R12
14
+ assert_disassembles_to 'add eax, ebx', :add_r32_rm32,
15
+ reg0: :A, reg1: :B
16
+ assert_disassembles_to 'add ax, bx', :add_r16_rm16,
17
+ reg0: :A, reg1: :B
18
+ end
19
+
20
+ def test_rm_reg_base
21
+ assert_disassembles_to 'add rax, qword ptr [rbx]', :add_r64_rm64,
22
+ reg0: :A, reg_base: :B
23
+ assert_disassembles_to 'add r11, qword ptr [r12]', :add_r64_rm64,
24
+ reg0: :R11, reg_base: :R12
25
+ assert_disassembles_to 'add eax, dword ptr [rbx]', :add_r32_rm32,
26
+ reg0: :A, reg_base: :B
27
+ assert_disassembles_to 'add ax, word ptr [rbx]', :add_r16_rm16,
28
+ reg0: :A, reg_base: :B
29
+
30
+ # reg1 should be ignored
31
+ assert_disassembles_to 'add eax, dword ptr [rbx]', :add_r32_rm32,
32
+ reg0: :A, reg1: :C, reg_base: :B
33
+ end
34
+
35
+ def test_rm_reg_base32
36
+ assert_disassembles_to 'add rax, dword ptr [ebx]', :add_r64_rm64,
37
+ reg0: :A, reg_base: :B, address_size: 32
38
+
39
+ assert_disassembles_to 'add eax, dword ptr [ebx]', :add_r32_rm32,
40
+ reg0: :A, reg_base: :B, address_size: 32
41
+ end
42
+
43
+ def test_rm_reg_sib
44
+ assert_disassembles_to 'add rax, qword ptr [rbx + rcx*4]', :add_r64_rm64,
45
+ reg0: :A, reg_base: :B, reg_index: :C, scale: 4
46
+ assert_disassembles_to 'add rax, qword ptr [rbx + rcx]', :add_r64_rm64,
47
+ reg0: :A, reg_base: :B, reg_index: :C, scale: 1
48
+ assert_disassembles_to 'add rax, qword ptr [rbx + rcx*8]', :add_r64_rm64,
49
+ reg0: :A, reg_base: :B, reg_index: :C, scale: 8
50
+
51
+ assert_disassembles_to 'add r10, qword ptr [r11 + r12*4]', :add_r64_rm64,
52
+ reg0: :R10, reg_base: :R11, reg_index: :R12, scale: 4
53
+
54
+ end
55
+
56
+ def test_mi
57
+ assert_disassembles_to 'add rax, 0xa', :add_rm64_imm8,
58
+ reg0: :A, imm0: 0xa
59
+
60
+ assert_disassembles_to 'add qword ptr [rax], 0xa', :add_rm64_imm8,
61
+ reg_base: :A, imm0: 0xa
62
+ end
63
+
64
+ def test_vex
65
+ assert_assembles_to "\xC5\xF5\xEC\xC2", :vpaddsb_ymm_ymm_ymmm256,
66
+ reg0: :XMM0, reg1: :XMM1, reg2: :XMM2, force_long_vex?: false
67
+ assert_assembles_to "\xC4\xE1u\xEC\xC2", :vpaddsb_ymm_ymm_ymmm256,
68
+ reg0: :XMM0, reg1: :XMM1, reg2: :XMM2, force_long_vex?: true
69
+ assert_disassembles_to 'vpaddsb ymm0, ymm1, ymm2', :vpaddsb_ymm_ymm_ymmm256,
70
+ reg0: :XMM0, reg1: :XMM1, reg2: :XMM2
71
+ assert_disassembles_to 'vpaddsb ymm0, ymm1, ymm2', :vpaddsb_ymm_ymm_ymmm256,
72
+ reg0: :XMM0, reg1: :XMM1, reg2: :XMM2, force_long_vex?: true
73
+
74
+ assert_assembles_to "\xC5\xF5\xEC\xC2", :vpaddsb_ymm_ymm_ymmm256,
75
+ reg0: :XMM0, reg1: :XMM1, reg2: :XMM2
76
+ assert_disassembles_to 'vpaddusb xmm0, xmm1, xmm2', :vpaddusb_xmm_xmm_xmmm128,
77
+ reg0: :XMM0, reg1: :XMM1, reg2: :XMM2
78
+ assert_assembles_to "\xC5\xF8\x5A\xCA", :vcvtps2pd_xmm_xmmm64,
79
+ reg0: :XMM1, reg1: :XMM2
80
+ assert_assembles_to "\xC5\xEA\x5A\xCB", :vcvtss2sd_xmm_xmm_xmmm32,
81
+ reg0: :XMM1, reg1: :XMM2, reg2: :XMM3
82
+
83
+ assert_assembles_to "\xC4\xE3\x79\x1D\xD1\x00", :vcvtps2ph_xmmm64_xmm_imm8,
84
+ reg0: :XMM1, reg1: :XMM2, imm0: 0x0
85
+ end
86
+
87
+ end