evoasm 0.0.2.pre7

Sign up to get free protection for your applications and to get access to all the features.
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