evoasm 0.0.2.pre7 → 0.1.0.pre2

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 (168) hide show
  1. checksums.yaml +4 -4
  2. data/.gdbinit +41 -0
  3. data/.gitignore +1 -2
  4. data/.gitmodules +3 -0
  5. data/.rubocop.yml +8 -0
  6. data/Gemfile +4 -0
  7. data/LICENSE.md +660 -0
  8. data/Makefile +1 -1
  9. data/README.md +17 -9
  10. data/Rakefile +39 -107
  11. data/bin/gdb +1 -1
  12. data/bin/gdb_loop +4 -0
  13. data/docs/FindingInstructions.md +17 -0
  14. data/docs/JIT.md +14 -0
  15. data/docs/SymbolicRegression.md +102 -0
  16. data/docs/Visualization.md +29 -0
  17. data/docs/examples/bit_insts.rb +44 -0
  18. data/docs/examples/jit.rb +26 -0
  19. data/docs/examples/loss.gif +0 -0
  20. data/docs/examples/program.png +0 -0
  21. data/docs/examples/sym_reg.rb +64 -0
  22. data/docs/examples/vis.rb +38 -0
  23. data/evoasm.gemspec +21 -15
  24. data/ext/evoasm_ext/Rakefile +3 -0
  25. data/ext/evoasm_ext/compile.rake +35 -0
  26. data/ext/evoasm_ext/libevoasm/src/evoasm-alloc.c +226 -0
  27. data/ext/evoasm_ext/libevoasm/src/evoasm-alloc.h +84 -0
  28. data/ext/evoasm_ext/libevoasm/src/evoasm-arch.c +52 -0
  29. data/ext/evoasm_ext/libevoasm/src/evoasm-arch.h +101 -0
  30. data/ext/evoasm_ext/libevoasm/src/evoasm-bitmap.h +158 -0
  31. data/ext/evoasm_ext/libevoasm/src/evoasm-buf.c +204 -0
  32. data/ext/evoasm_ext/libevoasm/src/evoasm-buf.h +109 -0
  33. data/ext/evoasm_ext/libevoasm/src/evoasm-domain.c +124 -0
  34. data/ext/evoasm_ext/libevoasm/src/evoasm-domain.h +279 -0
  35. data/ext/evoasm_ext/libevoasm/src/evoasm-error.c +65 -0
  36. data/ext/evoasm_ext/libevoasm/src/evoasm-error.h +108 -0
  37. data/ext/evoasm_ext/{evoasm-log.c → libevoasm/src/evoasm-log.c} +36 -18
  38. data/ext/evoasm_ext/libevoasm/src/evoasm-log.h +93 -0
  39. data/ext/evoasm_ext/libevoasm/src/evoasm-param.c +22 -0
  40. data/ext/evoasm_ext/libevoasm/src/evoasm-param.h +33 -0
  41. data/ext/evoasm_ext/libevoasm/src/evoasm-pop-params.c +192 -0
  42. data/ext/evoasm_ext/libevoasm/src/evoasm-pop-params.h +60 -0
  43. data/ext/evoasm_ext/libevoasm/src/evoasm-pop.c +1323 -0
  44. data/ext/evoasm_ext/libevoasm/src/evoasm-pop.h +107 -0
  45. data/ext/evoasm_ext/libevoasm/src/evoasm-program-io.c +116 -0
  46. data/ext/evoasm_ext/libevoasm/src/evoasm-program-io.h +60 -0
  47. data/ext/evoasm_ext/libevoasm/src/evoasm-program.c +1827 -0
  48. data/ext/evoasm_ext/libevoasm/src/evoasm-program.h +167 -0
  49. data/ext/evoasm_ext/libevoasm/src/evoasm-rand.c +65 -0
  50. data/ext/evoasm_ext/libevoasm/src/evoasm-rand.h +76 -0
  51. data/ext/evoasm_ext/libevoasm/src/evoasm-signal.c +106 -0
  52. data/ext/evoasm_ext/libevoasm/src/evoasm-signal.h +58 -0
  53. data/ext/evoasm_ext/libevoasm/src/evoasm-util.h +112 -0
  54. data/ext/evoasm_ext/libevoasm/src/evoasm-x64.c +925 -0
  55. data/ext/evoasm_ext/libevoasm/src/evoasm-x64.h +277 -0
  56. data/ext/evoasm_ext/libevoasm/src/evoasm.c +28 -0
  57. data/ext/evoasm_ext/libevoasm/src/evoasm.h +35 -0
  58. data/ext/evoasm_ext/libevoasm/src/gen/evoasm-x64-enums.h +2077 -0
  59. data/ext/evoasm_ext/libevoasm/src/gen/evoasm-x64-insts.c +191203 -0
  60. data/ext/evoasm_ext/libevoasm/src/gen/evoasm-x64-insts.h +1713 -0
  61. data/ext/evoasm_ext/libevoasm/src/gen/evoasm-x64-misc.c +348 -0
  62. data/ext/evoasm_ext/libevoasm/src/gen/evoasm-x64-misc.h +93 -0
  63. data/ext/evoasm_ext/libevoasm/src/gen/evoasm-x64-params.c +51 -0
  64. data/ext/evoasm_ext/libevoasm/src/gen/evoasm-x64-params.h +509 -0
  65. data/lib/evoasm.rb +28 -11
  66. data/lib/evoasm/buffer.rb +105 -0
  67. data/lib/evoasm/capstone.rb +100 -0
  68. data/lib/evoasm/domain.rb +116 -0
  69. data/lib/evoasm/error.rb +37 -16
  70. data/lib/evoasm/exception_error.rb +19 -0
  71. data/lib/evoasm/ffi_ext.rb +53 -0
  72. data/lib/evoasm/libevoasm.rb +286 -0
  73. data/lib/evoasm/libevoasm/x64_enums.rb +1967 -0
  74. data/lib/evoasm/parameter.rb +20 -0
  75. data/lib/evoasm/population.rb +145 -0
  76. data/lib/evoasm/population/parameters.rb +227 -0
  77. data/lib/evoasm/population/plotter.rb +89 -0
  78. data/lib/evoasm/prng.rb +64 -0
  79. data/lib/evoasm/program.rb +195 -12
  80. data/lib/evoasm/program/io.rb +144 -0
  81. data/lib/evoasm/test.rb +8 -0
  82. data/lib/evoasm/version.rb +1 -1
  83. data/lib/evoasm/x64.rb +115 -0
  84. data/lib/evoasm/x64/cpu_state.rb +95 -0
  85. data/lib/evoasm/x64/instruction.rb +109 -0
  86. data/lib/evoasm/x64/operand.rb +156 -0
  87. data/lib/evoasm/x64/parameters.rb +211 -0
  88. data/test/helpers/population_helper.rb +128 -0
  89. data/test/helpers/test_helper.rb +1 -0
  90. data/test/helpers/x64_helper.rb +24 -0
  91. data/test/integration/bitwise_reverse_test.rb +41 -0
  92. data/test/integration/gcd_test.rb +52 -0
  93. data/test/integration/popcnt_test.rb +46 -0
  94. data/test/integration/sym_reg_test.rb +68 -0
  95. data/test/unit/evoasm/buffer_test.rb +48 -0
  96. data/test/unit/evoasm/capstone_test.rb +18 -0
  97. data/test/unit/evoasm/domain_test.rb +55 -0
  98. data/test/unit/evoasm/population/parameters_test.rb +106 -0
  99. data/test/unit/evoasm/population_test.rb +96 -0
  100. data/test/unit/evoasm/prng_test.rb +47 -0
  101. data/test/unit/evoasm/x64/cpu_state_test.rb +73 -0
  102. data/test/unit/evoasm/x64/encoding_test.rb +320 -0
  103. data/test/unit/evoasm/x64/instruction_access_test.rb +177 -0
  104. data/test/unit/evoasm/x64/instruction_encoding_test.rb +780 -0
  105. data/test/unit/evoasm/x64/instruction_test.rb +62 -0
  106. data/test/unit/evoasm/x64/parameters_test.rb +65 -0
  107. data/test/unit/evoasm/x64_test.rb +52 -0
  108. metadata +195 -89
  109. data/Gemfile.rake +0 -8
  110. data/Gemfile.rake.lock +0 -51
  111. data/LICENSE.txt +0 -373
  112. data/data/tables/README.md +0 -19
  113. data/data/tables/x64.csv +0 -1684
  114. data/data/templates/evoasm-x64.c.erb +0 -319
  115. data/data/templates/evoasm-x64.h.erb +0 -126
  116. data/examples/abs.yml +0 -20
  117. data/examples/popcnt.yml +0 -17
  118. data/examples/sym_reg.yml +0 -26
  119. data/exe/evoasm-search +0 -13
  120. data/ext/evoasm_ext/evoasm-alloc.c +0 -145
  121. data/ext/evoasm_ext/evoasm-alloc.h +0 -59
  122. data/ext/evoasm_ext/evoasm-arch.c +0 -44
  123. data/ext/evoasm_ext/evoasm-arch.h +0 -161
  124. data/ext/evoasm_ext/evoasm-bitmap.h +0 -114
  125. data/ext/evoasm_ext/evoasm-buf.c +0 -130
  126. data/ext/evoasm_ext/evoasm-buf.h +0 -47
  127. data/ext/evoasm_ext/evoasm-error.c +0 -31
  128. data/ext/evoasm_ext/evoasm-error.h +0 -75
  129. data/ext/evoasm_ext/evoasm-free-list.c.tmpl +0 -121
  130. data/ext/evoasm_ext/evoasm-free-list.h.tmpl +0 -86
  131. data/ext/evoasm_ext/evoasm-log.h +0 -69
  132. data/ext/evoasm_ext/evoasm-misc.c +0 -23
  133. data/ext/evoasm_ext/evoasm-misc.h +0 -282
  134. data/ext/evoasm_ext/evoasm-param.h +0 -37
  135. data/ext/evoasm_ext/evoasm-search.c +0 -2145
  136. data/ext/evoasm_ext/evoasm-search.h +0 -214
  137. data/ext/evoasm_ext/evoasm-util.h +0 -40
  138. data/ext/evoasm_ext/evoasm-x64.c +0 -275624
  139. data/ext/evoasm_ext/evoasm-x64.h +0 -5436
  140. data/ext/evoasm_ext/evoasm.c +0 -7
  141. data/ext/evoasm_ext/evoasm.h +0 -23
  142. data/ext/evoasm_ext/evoasm_ext.c +0 -1757
  143. data/ext/evoasm_ext/extconf.rb +0 -31
  144. data/lib/evoasm/cli.rb +0 -6
  145. data/lib/evoasm/cli/search.rb +0 -127
  146. data/lib/evoasm/core_ext.rb +0 -1
  147. data/lib/evoasm/core_ext/array.rb +0 -9
  148. data/lib/evoasm/core_ext/integer.rb +0 -10
  149. data/lib/evoasm/core_ext/kwstruct.rb +0 -13
  150. data/lib/evoasm/core_ext/range.rb +0 -5
  151. data/lib/evoasm/examples.rb +0 -27
  152. data/lib/evoasm/gen.rb +0 -8
  153. data/lib/evoasm/gen/enum.rb +0 -169
  154. data/lib/evoasm/gen/name_util.rb +0 -80
  155. data/lib/evoasm/gen/state.rb +0 -176
  156. data/lib/evoasm/gen/state_dsl.rb +0 -152
  157. data/lib/evoasm/gen/strio.rb +0 -27
  158. data/lib/evoasm/gen/translator.rb +0 -1102
  159. data/lib/evoasm/gen/version.rb +0 -5
  160. data/lib/evoasm/gen/x64.rb +0 -237
  161. data/lib/evoasm/gen/x64/funcs.rb +0 -495
  162. data/lib/evoasm/gen/x64/inst.rb +0 -781
  163. data/lib/evoasm/search.rb +0 -40
  164. data/lib/evoasm/tasks/gen_task.rb +0 -86
  165. data/lib/evoasm/tasks/template_task.rb +0 -52
  166. data/test/test_helper.rb +0 -1
  167. data/test/x64/test_helper.rb +0 -19
  168. data/test/x64/x64_test.rb +0 -87
@@ -0,0 +1,95 @@
1
+ require 'evoasm/x64'
2
+
3
+ module Evoasm
4
+ module X64
5
+ # Represents the CPU state (i.e. a snapshot of all registers)
6
+ # at a specific moment in time.
7
+ class CPUState < FFI::AutoPointer
8
+
9
+ # @!visibility private
10
+ def self.release(ptr)
11
+ Libevoasm.x64_cpu_state_destroy(ptr)
12
+ Libevoasm.x64_cpu_state_free(ptr)
13
+ end
14
+
15
+ # @param flags [Array<Symbol>]
16
+ def initialize(flags = [:rflags])
17
+ ptr = Libevoasm.x64_cpu_state_alloc
18
+ Libevoasm.x64_cpu_state_init ptr, Libevoasm.enum_type(:x64_cpu_state_flags).flags(flags, shift: false)
19
+ super(ptr)
20
+ end
21
+
22
+ # Sets the value of a register
23
+ # @param register [Symbol] register to set
24
+ # @param data [Array<Integer>, Integer] value as a single 64-bit integer or an array of multiple
25
+ # 64-bit integers (e.g. for vector registers)
26
+ # @return [void]
27
+ def []=(register, data)
28
+ data = Array(data)
29
+ ptr = FFI::MemoryPointer.new :uint64, data.size
30
+ ptr.write_array_of_uint64 data
31
+ Libevoasm.x64_cpu_state_set self, register, ptr, data.size
32
+ end
33
+
34
+ # Obtain the value of a register
35
+ # @param register [Symbol] the register
36
+ # @param word [Symbol] an optional word to mask the value (e.g. to obtain a subregister value)
37
+ # @return [Array<Integer>] the register's value as an array of 64-bit integers
38
+ def [](register, word = :none)
39
+ data_ptr = FFI::MemoryPointer.new :uint64, 16
40
+ data_len = Libevoasm.x64_cpu_state_get self, register, word, data_ptr, 16
41
+ data_ptr.read_array_of_uint64 data_len
42
+ end
43
+
44
+ # Clone this CPU state object
45
+ # @return [CPUState] the cloned object
46
+ def clone
47
+ cloned_cpu_state = self.class.new
48
+ Libevoasm.x64_cpu_state_clone self, cloned_cpu_state
49
+
50
+ cloned_cpu_state
51
+ end
52
+
53
+ # @!visibility private
54
+ def xor(other)
55
+ xored = self.class.new
56
+ Libevoasm.x64_cpu_state_xor self, other, xored
57
+ xored
58
+ end
59
+
60
+ # Converts this object into a hash
61
+ # @return [Hash] the hash
62
+ def to_h
63
+ X64.registers.each_with_object({}) do |register, hash|
64
+ hash[register] = self[register]
65
+ end
66
+ end
67
+
68
+ def get_rflags_flag(flag)
69
+ Libevoasm.x64_cpu_state_get_rflags_flag self, flag
70
+ end
71
+
72
+ # Emits machine code to store (save) the current CPU state
73
+ # into this object
74
+ # @param buffer [Buffer] the buffer to emit to
75
+ # @return [void]
76
+ # @raise [Error] if an error occurres
77
+ def emit_store(buffer)
78
+ unless Libevoasm.x64_cpu_state_emit_store self, buffer
79
+ raise Error.last
80
+ end
81
+ end
82
+
83
+ # Emits machine code to load (set) the current CPU state to
84
+ # the state of this object
85
+ # @param buffer [Buffer] the buffer to emit to
86
+ # @return [void]
87
+ # @raise [Error] if an error occurres
88
+ def emit_load(buffer)
89
+ unless Libevoasm.x64_cpu_state_emit_load self, buffer
90
+ raise Error.last
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,109 @@
1
+ require 'evoasm/parameter'
2
+
3
+ module Evoasm
4
+ module X64
5
+ # Represents an x86-64 instruction
6
+ class Instruction < FFI::Pointer
7
+ class Parameter < Evoasm::Parameter
8
+ # Returns the parameter's name
9
+ # @return [Symbol] the parameter name
10
+ def name
11
+ Libevoasm.enum_type(:x64_param_id).find id
12
+ end
13
+ end
14
+
15
+ # @return [Symbol] the instruction's name
16
+ attr_reader :name
17
+
18
+ # @!visibility private
19
+ def initialize(ptr, name)
20
+ super(ptr)
21
+ @name = name
22
+ end
23
+
24
+ # Gives a list of instruction mnemonics
25
+ # @return [Array<String>] mnemonics
26
+ def mnemonics
27
+ Libevoasm.x64_inst_get_mnem(self).split('/')
28
+ end
29
+
30
+ # Gives the preferred instruction mnemonic
31
+ # @return [String] the mnemonics
32
+ # @see #mnemonics
33
+ def mnemonic
34
+ mnemonics.first
35
+ end
36
+
37
+ # Gives the operand at the specified index
38
+ # @return [Operand] the operand
39
+ def operand(index)
40
+ Operand.new Libevoasm.x64_inst_get_operand(self, index), self
41
+ end
42
+
43
+ # Gives the instruction's operands
44
+ # @return [Array<Operand>] the operands
45
+ def operands
46
+ n_operands = Libevoasm.x64_inst_get_n_operands self
47
+ Array.new(n_operands) do |index|
48
+ operand index
49
+ end
50
+ end
51
+
52
+ # Gives this instruction's parameters
53
+ # @return [Array<Instruction::Parameter>] the parameters
54
+ def parameters
55
+ n_params = Libevoasm.x64_inst_get_n_params self
56
+ Array.new(n_params) do |param_index|
57
+ Parameter.new Libevoasm.x64_inst_get_param(self, param_index)
58
+ end
59
+ end
60
+
61
+ # Returns whether this instruction is encodable with the basic encoder
62
+ # @return [Bool]
63
+ def basic?
64
+ Libevoasm.x64_inst_is_basic(self)
65
+ end
66
+
67
+ # Encodes the instruciton with the given parameters
68
+ # @param parameters [X64::Parameters] parameters
69
+ # @param buffer [Buffer] the buffer to emit to
70
+ # @param basic [Bool] whether the basic encoder should be used
71
+ # @return [void]
72
+ def encode(parameters, buffer = nil, basic: false)
73
+ if basic && !basic?
74
+ raise ArgumentError, 'instruction does not support basic mode'
75
+ end
76
+
77
+ buf_ref = Libevoasm.buf_ref_alloc
78
+
79
+ if buffer
80
+ Libevoasm.buf_to_buf_ref buffer, buf_ref
81
+ else
82
+ data = FFI::MemoryPointer.new :uint8, 32
83
+ len_ptr = FFI::MemoryPointer.new :size_t, 1
84
+ Libevoasm.buf_ref_init buf_ref, data, len_ptr
85
+ end
86
+
87
+ parameters = Parameters.for(parameters, basic: basic)
88
+
89
+ success =
90
+ if basic
91
+ Libevoasm.x64_inst_enc_basic self, parameters, buf_ref
92
+ else
93
+ Libevoasm.x64_inst_enc self, parameters, buf_ref
94
+ end
95
+
96
+ Libevoasm.buf_ref_free buf_ref
97
+
98
+ if success
99
+ unless buffer
100
+ len = len_ptr.read_size_t
101
+ data.read_string len
102
+ end
103
+ else
104
+ raise Error.last
105
+ end
106
+ end
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,156 @@
1
+ module Evoasm
2
+ module X64
3
+ # Represents a formal instruction operand
4
+ class Operand < FFI::Pointer
5
+
6
+ # @return [X64::Instruction] the instruction this operand belongs to
7
+ attr_reader :instruction
8
+
9
+ # @!visibility private
10
+ def initialize(ptr, instruction)
11
+ super(ptr)
12
+ @instruction = instruction
13
+ end
14
+
15
+ # Gives the parameter affecting this operand
16
+ # @return [X64::Parameter] the parameter
17
+ def parameter
18
+ @instruction.parameters[Libevoasm.x64_operand_get_param_idx self]
19
+ end
20
+
21
+ # Returns whether this operand is read
22
+ def read?
23
+ Libevoasm.x64_operand_is_read self
24
+ end
25
+
26
+ # Returns whether this operand is written
27
+ def written?
28
+ Libevoasm.x64_operand_is_written self
29
+ end
30
+
31
+ # Returns whether this operand is possibliy written (e.g. in a conditional move instruction)
32
+ def maybe_written?
33
+ Libevoasm.x64_operand_is_maybe_written self
34
+ end
35
+
36
+ # Returns whether this operand is part of the instruction mnemonic
37
+ def mnemonic?
38
+ Libevoasm.x64_operand_is_mnem self
39
+ end
40
+
41
+ # Returns whether this operand is implicit
42
+ def implicit?
43
+ Libevoasm.x64_operand_is_implicit self
44
+ end
45
+
46
+ # Returns whether this operand is explicit
47
+ def explicit?
48
+ !implicit?
49
+ end
50
+
51
+ # Returns the operand type
52
+ # @return [:rm, :imm, :reg] the operand type
53
+ def type
54
+ Libevoasm.x64_operand_get_type self
55
+ end
56
+
57
+ # Returns the operand's register (e.g. if implicit) if available
58
+ # @return [Symbol, nil] the operand's register or nil if there is none
59
+ def register
60
+ if type == :rm || type == :reg
61
+ reg_id = Libevoasm.x64_operand_get_reg_id self
62
+ reg_id == :none ? nil : reg_id
63
+ else
64
+ nil
65
+ end
66
+ end
67
+
68
+ INVALID_IMMEDIATE = -1
69
+
70
+ # Returns the operand's immediate (e.g. if implicit) if available
71
+ # @return [Integer, nil] the operand's immediate or nil if there is none
72
+ def immediate
73
+ if type == :imm
74
+ imm = Libevoasm.x64_operand_get_imm self
75
+ imm == INVALID_IMMEDIATE ? nil : imm
76
+ else
77
+ nil
78
+ end
79
+ end
80
+
81
+ # Returns the operand's register type (e.g. if implicit) if available
82
+ # @return [Symbol, nil] the operand's register type or nil if there is none
83
+ def register_type
84
+ reg_type = Libevoasm.x64_operand_get_reg_type self
85
+ reg_type == :none ? nil : reg_type
86
+ end
87
+
88
+ # Gives the operand's size
89
+ # @return [Integer] the operand size in bits
90
+ def size
91
+ convert_size Libevoasm.x64_operand_get_size(self)
92
+ end
93
+
94
+ # Gives the operand's word
95
+ # @return [Symbol] the operand word
96
+ def word
97
+ Libevoasm.x64_operand_get_word(self)
98
+ end
99
+
100
+ # Returns the operand's register size
101
+ # @return [Integer, nil] the operand's registert size or nil if this operand does not hold a register
102
+ def register_size
103
+ if type == :rm || type == :reg
104
+ convert_size Libevoasm.x64_operand_get_reg_size(self)
105
+ else
106
+ nil
107
+ end
108
+ end
109
+
110
+ # Returns the operand's index register size (e.g. in VSIB instructions)
111
+ # @return [Integer, nil] the operand's index registert size or nil if this operand does not hold a index register
112
+ def index_register_size
113
+ if type == :vsib
114
+ convert_size Libevoasm.x64_operand_get_index_reg_size(self)
115
+ else
116
+ nil
117
+ end
118
+ end
119
+
120
+ # Returns the operand's memory size (e.g. in R/M instructions)
121
+ # @return [Integer, nil] the operand's memory size or nil if this operand is not a memory operand
122
+ def memory_size
123
+ if type == :rm || type == :mem || type == :vsib
124
+ convert_size Libevoasm.x64_operand_get_mem_size(self)
125
+ else
126
+ nil
127
+ end
128
+ end
129
+
130
+ private
131
+
132
+ def convert_size(size)
133
+ case size
134
+ when :'1' then
135
+ 1
136
+ when :'8' then
137
+ 8
138
+ when :'16' then
139
+ 16
140
+ when :'32' then
141
+ 32
142
+ when :'64' then
143
+ 64
144
+ when :'128' then
145
+ 128
146
+ when :'256' then
147
+ 256
148
+ when :'512' then
149
+ 512
150
+ else
151
+ nil
152
+ end
153
+ end
154
+ end
155
+ end
156
+ end
@@ -0,0 +1,211 @@
1
+ module Evoasm
2
+ module X64
3
+ # Represents x86-64 instruction parameters.
4
+ class Parameters < FFI::AutoPointer
5
+
6
+ # @!visibility private
7
+ def self.release(ptr)
8
+ if ptr.basic?
9
+ Libevoasm.x64_basic_params_free ptr
10
+ else
11
+ Libevoasm.x64_params_free ptr
12
+ end
13
+ end
14
+
15
+ # @!visibility private
16
+ def self.for(parameters, basic: false)
17
+ case parameters
18
+ when self
19
+ if basic && !parameters.basic?
20
+ raise ArgumentError, 'cannot convert non-basic parameters '\
21
+ 'to basic parameters'
22
+ end
23
+ parameters
24
+ when Hash
25
+ new parameters, basic: basic
26
+ else
27
+ raise ArgumentError, "cannot convert #{parameters.class} into parameter"
28
+ end
29
+ end
30
+
31
+ def inspect
32
+ fields = @param_id_enum_type.symbols[0..-2].map { |s| "#{s}:#{self[s]}" }.join(' ')
33
+ "#<#{self.class.inspect} #{fields}>"
34
+ end
35
+
36
+ # @param hash [Hash] a
37
+ # @param basic [Bool] whether to use the basic encoder
38
+ def initialize(hash = {}, basic: false)
39
+ if basic
40
+ ptr = Libevoasm.x64_basic_params_alloc
41
+ Libevoasm.x64_basic_params_init ptr
42
+ else
43
+ ptr = Libevoasm.x64_params_alloc
44
+ Libevoasm.x64_params_init ptr
45
+ end
46
+
47
+ @param_id_enum_type =
48
+ if basic
49
+ Libevoasm.enum_type(:x64_basic_param_id)
50
+ else
51
+ Libevoasm.enum_type(:x64_param_id)
52
+ end
53
+
54
+ @basic = basic
55
+ @disp_size_enum_type = Libevoasm.enum_type :x64_disp_size
56
+ @addr_size_enum_type = Libevoasm.enum_type :x64_addr_size
57
+ @scale_enum_type = Libevoasm.enum_type :x64_scale
58
+ @reg_id_enum_type = Libevoasm.enum_type :x64_reg_id
59
+
60
+ @type_map_enum_types = {
61
+ scale: @scale_enum_type,
62
+ addr_size: @addr_size_enum_type,
63
+ reg: @reg_id_enum_type
64
+ }
65
+
66
+ @type_map = {
67
+ scale: {
68
+ 1 => :scale1,
69
+ 2 => :scale2,
70
+ 4 => :scale4,
71
+ 8 => :scale8
72
+ },
73
+
74
+ addr_size: {
75
+ 32 => :addr_size32,
76
+ 64 => :addr_size64,
77
+ },
78
+
79
+ bool: {
80
+ true => 1,
81
+ false => 0
82
+ },
83
+
84
+ uint1: proc { |v| check_uint_range v, 1 },
85
+ int3: proc { |v| check_int_range v, 3 },
86
+ int4: proc { |v| check_int_range v, 4 },
87
+ int8: proc { |v| check_int_range v, 8 },
88
+ int32: proc { |v| check_int_range v, 32 },
89
+ int64: proc { |v| check_int_range v, 64 },
90
+ reg: proc { |v| @reg_id_enum_type[v] }
91
+ }
92
+
93
+ @inv_type_map = @type_map.map do |k, v|
94
+ if v.is_a? Hash
95
+ [k, v.invert]
96
+ else
97
+ [k, v]
98
+ end
99
+ end.to_h
100
+
101
+ @inv_type_map[:reg] = proc { |v| v }
102
+
103
+ super(ptr)
104
+
105
+ hash.each do |k, v|
106
+ self[k] = v
107
+ end
108
+ end
109
+
110
+ # Returns whether this parameters are for basic encodning
111
+ # @return [Bool]
112
+ def basic?
113
+ @basic
114
+ end
115
+
116
+ # @param parameter_name [Symbol] the parameter's name
117
+ # @return [Symbol, Integer] the parameter value
118
+ def [](parameter_name)
119
+ ffi_value =
120
+ if basic?
121
+ Libevoasm.x64_basic_params_get self, parameter_name_to_id(parameter_name)
122
+ else
123
+ Libevoasm.x64_params_get self, parameter_name_to_id(parameter_name)
124
+ end
125
+
126
+ ffi_value_to_value parameter_name, ffi_value
127
+ end
128
+
129
+ # Checks the existence of a parameter
130
+ # @param parameter_name [Symbol] the parameter name
131
+ # @return [Bool] whether the parameter exists or nor
132
+ def parameter?(parameter_name)
133
+ !@param_id_enum_type[parameter_name].nil?
134
+ end
135
+
136
+ # Set a parameter
137
+ # @param parameter_name [Symbol] the parameter's name
138
+ # @param value [Symbol, Integer] the parameter's value
139
+ # @return [void]
140
+ def []=(parameter_name, value)
141
+ ffi_value = value_to_ffi_value parameter_name, value
142
+ parameter_id = parameter_name_to_id(parameter_name)
143
+
144
+ if basic?
145
+ Libevoasm.x64_basic_params_set self, parameter_id, ffi_value
146
+ else
147
+ Libevoasm.x64_params_set self, parameter_id, ffi_value
148
+ end
149
+ end
150
+
151
+ private
152
+
153
+ def check_uint_range(value, bitsize)
154
+ min = 0
155
+ max = 2**bitsize - 1
156
+ raise ArgumentError, "#{value} exceeds value range #{min}..#{max}" if value < min || value > max
157
+
158
+ value
159
+ end
160
+
161
+ def check_int_range(value, bitsize)
162
+ min = -2**bitsize
163
+ max = -min - 1
164
+ raise ArgumentError, "#{value} exceeds value range #{min}..#{max}" if value < min || value > max
165
+
166
+ value
167
+ end
168
+
169
+ def parameter_type(parameter_name)
170
+ if basic?
171
+ Libevoasm.x64_basic_params_get_type(parameter_name)
172
+ else
173
+ Libevoasm.x64_params_get_type(parameter_name)
174
+ end
175
+ end
176
+
177
+ def value_to_ffi_value(parameter_name, parameter_value)
178
+ raise ArgumentError, 'value cannot be nil' if parameter_value.nil?
179
+
180
+ parameter_type = parameter_type parameter_name
181
+ ffi_value = @type_map[parameter_type][parameter_value]
182
+
183
+ if ffi_value.nil?
184
+ raise ArgumentError, "value #{parameter_value} is invalid for #{parameter_name}"
185
+ end
186
+
187
+ ffi_value
188
+ end
189
+
190
+ def ffi_value_to_value(parameter_name, ffi_value)
191
+ parameter_type = parameter_type parameter_name
192
+
193
+ if @type_map_enum_types.key? parameter_type
194
+ ffi_value = @type_map_enum_types[parameter_type][ffi_value]
195
+ end
196
+
197
+ @inv_type_map[parameter_type][ffi_value]
198
+ end
199
+
200
+ def parameter_name_to_id(symbol)
201
+ id = @param_id_enum_type[symbol]
202
+
203
+ if id.nil?
204
+ raise ArgumentError, "unknown parameter '#{symbol}'"
205
+ end
206
+
207
+ id
208
+ end
209
+ end
210
+ end
211
+ end