evoasm 0.0.2.pre7 → 0.1.0.pre2

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