asmrepl 1.1.0 → 1.2.0
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.
- checksums.yaml +4 -4
- data/lib/asmrepl/assembler.rb +5 -1
- data/lib/asmrepl/disasm.rb +24 -0
- data/lib/asmrepl/linux.rb +15 -75
- data/lib/asmrepl/macos.rb +31 -86
- data/lib/asmrepl/repl.rb +30 -6
- data/lib/asmrepl/thread_state.rb +108 -0
- data/lib/asmrepl/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4b7a42ce7b9651305349e0f3aa6eafe88755a7f5bce4224ea0fab31c7169a0cd
|
4
|
+
data.tar.gz: 95ef6c4ebe42d82341782e5014b21237f6ba436ce3b296041aec59c4fdc8ba38
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: affb18c181d063ddf30f48006d980753573ca797f51d49e51e231cb6fbc9a4ffc4ec0204e806b02c5df895426cdae04185cbe12f605ee755d4ec35529879954e
|
7
|
+
data.tar.gz: bdfa0987327ef236a1e4a9fd991e00d864bac78e7408185f1c94ec93cb04b20fe82bc7336a214422b1067bbc02a12c8ac69ac132cf4cf842653f9e7e1d45ed8c
|
data/lib/asmrepl/assembler.rb
CHANGED
@@ -11,7 +11,11 @@ module ASMREPL
|
|
11
11
|
l = if possibles.any? { |form| form.operands[1].type == n.to_s }
|
12
12
|
fisk.lit(n)
|
13
13
|
else
|
14
|
-
|
14
|
+
if r.size == 64
|
15
|
+
fisk.imm32(n)
|
16
|
+
else
|
17
|
+
fisk.imm(n)
|
18
|
+
end
|
15
19
|
end
|
16
20
|
fisk.gen_with_insn insn, [r, l]
|
17
21
|
in [:command, [:instruction, insn], [:register, r], [:register, r2]]
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require "crabstone"
|
2
|
+
|
3
|
+
class Crabstone::Binding::Instruction
|
4
|
+
class << self
|
5
|
+
alias :old_release :release
|
6
|
+
end
|
7
|
+
|
8
|
+
# Squelch error in crabstone
|
9
|
+
def self.release obj
|
10
|
+
nil
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
module ASMREPL
|
15
|
+
module Disasm
|
16
|
+
def self.disasm buffer
|
17
|
+
binary = buffer.memory[0, buffer.pos]
|
18
|
+
cs = Crabstone::Disassembler.new(Crabstone::ARCH_X86, Crabstone::MODE_64)
|
19
|
+
cs.disasm(binary, buffer.memory.to_i).each {|i|
|
20
|
+
puts "%s %s" % [i.mnemonic, i.op_str]
|
21
|
+
}
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/lib/asmrepl/linux.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require "fisk/helpers"
|
2
|
+
require "asmrepl/thread_state"
|
2
3
|
|
3
4
|
module ASMREPL
|
4
5
|
module Linux
|
@@ -44,13 +45,13 @@ module ASMREPL
|
|
44
45
|
|
45
46
|
# x86_64-linux-gnu/sys/ptrace.h
|
46
47
|
PTRACE_GETREGS = 12
|
48
|
+
PTRACE_SETREGS = 13
|
47
49
|
|
48
50
|
def self.traceme
|
49
51
|
raise unless ptrace(PTRACE_TRACEME, 0, 0, 0).zero?
|
50
52
|
end
|
51
53
|
|
52
|
-
|
53
|
-
fields = (<<-eostruct).scan(/int ([^;]*);/).flatten
|
54
|
+
fields = (<<-eostruct).scan(/int ([^;]*);/).flatten
|
54
55
|
struct user_regs_struct
|
55
56
|
{
|
56
57
|
__extension__ unsigned long long int r15;
|
@@ -81,82 +82,15 @@ struct user_regs_struct
|
|
81
82
|
__extension__ unsigned long long int fs;
|
82
83
|
__extension__ unsigned long long int gs;
|
83
84
|
};
|
84
|
-
|
85
|
-
fields.each_with_index do |field, i|
|
86
|
-
define_method(field) do
|
87
|
-
to_ptr[Fiddle::SIZEOF_INT64_T * i, Fiddle::SIZEOF_INT64_T].unpack1("l!")
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
define_singleton_method(:sizeof) do
|
92
|
-
fields.length * Fiddle::SIZEOF_INT64_T
|
93
|
-
end
|
94
|
-
|
95
|
-
def [] name
|
96
|
-
idx = fields.index(name)
|
97
|
-
return unless idx
|
98
|
-
to_ptr[Fiddle::SIZEOF_INT64_T * idx, Fiddle::SIZEOF_INT64_T].unpack1("l!")
|
99
|
-
end
|
100
|
-
|
101
|
-
def self.malloc
|
102
|
-
new Fiddle::Pointer.malloc sizeof
|
103
|
-
end
|
104
|
-
|
105
|
-
attr_reader :to_ptr
|
106
|
-
|
107
|
-
def initialize buffer
|
108
|
-
@to_ptr = buffer
|
109
|
-
end
|
85
|
+
eostruct
|
110
86
|
|
111
|
-
|
112
|
-
|
113
|
-
end
|
114
|
-
|
115
|
-
def to_s
|
116
|
-
buf = ""
|
117
|
-
fields.first(8).zip(fields.drop(8).first(8)).each do |l, r|
|
118
|
-
buf << "#{l.ljust(3)} #{sprintf("%#018x", send(l))}"
|
119
|
-
buf << " "
|
120
|
-
buf << "#{r.ljust(3)} #{sprintf("%#018x", send(r))}\n"
|
121
|
-
end
|
87
|
+
class ThreadState < ASMREPL::ThreadState.build(fields)
|
88
|
+
private
|
122
89
|
|
123
|
-
|
90
|
+
def read_flags; eflags; end
|
124
91
|
|
125
|
-
|
126
|
-
|
127
|
-
end
|
128
|
-
buf
|
129
|
-
end
|
130
|
-
|
131
|
-
FLAGS = [
|
132
|
-
['CF', 'Carry Flag'],
|
133
|
-
[nil, 'Reserved'],
|
134
|
-
['PF', 'Parity Flag'],
|
135
|
-
[nil, 'Reserved'],
|
136
|
-
['AF', 'Adjust Flag'],
|
137
|
-
[nil, 'Reserved'],
|
138
|
-
['ZF', 'Zero Flag'],
|
139
|
-
['SF', 'Sign Flag'],
|
140
|
-
['TF', 'Trap Flag'],
|
141
|
-
['IF', 'Interrupt Enable Flag'],
|
142
|
-
['DF', 'Direction Flag'],
|
143
|
-
['OF', 'Overflow Flag'],
|
144
|
-
['IOPL_H', 'I/O privilege level High bit'],
|
145
|
-
['IOPL_L', 'I/O privilege level Low bit'],
|
146
|
-
['NT', 'Nested Task Flag'],
|
147
|
-
[nil, 'Reserved'],
|
148
|
-
]
|
149
|
-
|
150
|
-
def flags
|
151
|
-
flags = eflags
|
152
|
-
f = []
|
153
|
-
FLAGS.each do |abbrv, _|
|
154
|
-
if abbrv && flags & 1 == 1
|
155
|
-
f << abbrv
|
156
|
-
end
|
157
|
-
flags >>= 1
|
158
|
-
end
|
159
|
-
f
|
92
|
+
def other_registers
|
93
|
+
super - ["orig_rax"]
|
160
94
|
end
|
161
95
|
end
|
162
96
|
|
@@ -176,6 +110,12 @@ struct user_regs_struct
|
|
176
110
|
state
|
177
111
|
end
|
178
112
|
|
113
|
+
def state= state
|
114
|
+
raise unless Linux.ptrace(PTRACE_SETREGS, @pid, 0, state).zero?
|
115
|
+
|
116
|
+
state
|
117
|
+
end
|
118
|
+
|
179
119
|
def continue
|
180
120
|
unless Linux.ptrace(Linux::PTRACE_CONT, @pid, 1, 0).zero?
|
181
121
|
raise
|
data/lib/asmrepl/macos.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require "fisk/helpers"
|
2
|
+
require "asmrepl/thread_state"
|
2
3
|
|
3
4
|
module ASMREPL
|
4
5
|
module MacOS
|
@@ -26,6 +27,7 @@ module ASMREPL
|
|
26
27
|
make_function "task_for_pid", [TYPE_VOIDP, TYPE_INT, TYPE_VOIDP], TYPE_INT
|
27
28
|
make_function "task_threads", [TYPE_VOIDP, TYPE_VOIDP, TYPE_VOIDP], TYPE_INT
|
28
29
|
make_function "thread_get_state", [TYPE_VOIDP, TYPE_INT, TYPE_VOIDP, TYPE_VOIDP], TYPE_INT
|
30
|
+
make_function "thread_set_state", [TYPE_VOIDP, TYPE_INT, TYPE_VOIDP, TYPE_INT], TYPE_INT
|
29
31
|
make_function "mmap", [TYPE_VOIDP,
|
30
32
|
TYPE_SIZE_T,
|
31
33
|
TYPE_INT,
|
@@ -47,8 +49,7 @@ module ASMREPL
|
|
47
49
|
raise unless ptrace(PT_TRACE_ME, 0, 0, 0).zero?
|
48
50
|
end
|
49
51
|
|
50
|
-
|
51
|
-
fields = (<<-eostruct).scan(/uint64_t ([^;]*);/).flatten
|
52
|
+
fields = (<<-eostruct).scan(/uint64_t ([^;]*);/).flatten
|
52
53
|
struct x86_thread_state64_t {
|
53
54
|
uint64_t rax;
|
54
55
|
uint64_t rbx;
|
@@ -72,83 +73,12 @@ struct x86_thread_state64_t {
|
|
72
73
|
uint64_t fs;
|
73
74
|
uint64_t gs;
|
74
75
|
}
|
75
|
-
|
76
|
-
fields.each_with_index do |field, i|
|
77
|
-
define_method(field) do
|
78
|
-
to_ptr[Fiddle::SIZEOF_INT64_T * i, Fiddle::SIZEOF_INT64_T].unpack1("l!")
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
define_singleton_method(:sizeof) do
|
83
|
-
fields.length * Fiddle::SIZEOF_INT64_T
|
84
|
-
end
|
85
|
-
|
86
|
-
def [] name
|
87
|
-
idx = fields.index(name)
|
88
|
-
return unless idx
|
89
|
-
to_ptr[Fiddle::SIZEOF_INT64_T * idx, Fiddle::SIZEOF_INT64_T].unpack1("l!")
|
90
|
-
end
|
91
|
-
|
92
|
-
def self.malloc
|
93
|
-
new Fiddle::Pointer.malloc sizeof
|
94
|
-
end
|
76
|
+
eostruct
|
95
77
|
|
96
|
-
|
78
|
+
class ThreadState < ASMREPL::ThreadState.build(fields)
|
79
|
+
private
|
97
80
|
|
98
|
-
def
|
99
|
-
@to_ptr = buffer
|
100
|
-
end
|
101
|
-
|
102
|
-
define_method(:fields) do
|
103
|
-
fields
|
104
|
-
end
|
105
|
-
|
106
|
-
def to_s
|
107
|
-
buf = ""
|
108
|
-
fields.first(8).zip(fields.drop(8).first(8)).each do |l, r|
|
109
|
-
buf << "#{l.ljust(3)} #{sprintf("%#018x", send(l))}"
|
110
|
-
buf << " "
|
111
|
-
buf << "#{r.ljust(3)} #{sprintf("%#018x", send(r))}\n"
|
112
|
-
end
|
113
|
-
|
114
|
-
buf << "\n"
|
115
|
-
|
116
|
-
fields.drop(16).each do |reg|
|
117
|
-
buf << "#{reg.ljust(6)} #{sprintf("%#018x", send(reg))}\n"
|
118
|
-
end
|
119
|
-
buf
|
120
|
-
end
|
121
|
-
|
122
|
-
FLAGS = [
|
123
|
-
['CF', 'Carry Flag'],
|
124
|
-
[nil, 'Reserved'],
|
125
|
-
['PF', 'Parity Flag'],
|
126
|
-
[nil, 'Reserved'],
|
127
|
-
['AF', 'Adjust Flag'],
|
128
|
-
[nil, 'Reserved'],
|
129
|
-
['ZF', 'Zero Flag'],
|
130
|
-
['SF', 'Sign Flag'],
|
131
|
-
['TF', 'Trap Flag'],
|
132
|
-
['IF', 'Interrupt Enable Flag'],
|
133
|
-
['DF', 'Direction Flag'],
|
134
|
-
['OF', 'Overflow Flag'],
|
135
|
-
['IOPL_H', 'I/O privilege level High bit'],
|
136
|
-
['IOPL_L', 'I/O privilege level Low bit'],
|
137
|
-
['NT', 'Nested Task Flag'],
|
138
|
-
[nil, 'Reserved'],
|
139
|
-
]
|
140
|
-
|
141
|
-
def flags
|
142
|
-
flags = rflags
|
143
|
-
f = []
|
144
|
-
FLAGS.each do |abbrv, _|
|
145
|
-
if abbrv && flags & 1 == 1
|
146
|
-
f << abbrv
|
147
|
-
end
|
148
|
-
flags >>= 1
|
149
|
-
end
|
150
|
-
f
|
151
|
-
end
|
81
|
+
def read_flags; rflags; end
|
152
82
|
end
|
153
83
|
|
154
84
|
PT_TRACE_ME = 0
|
@@ -176,9 +106,30 @@ struct x86_thread_state64_t {
|
|
176
106
|
end
|
177
107
|
|
178
108
|
def state
|
179
|
-
|
180
|
-
|
109
|
+
3.times do
|
110
|
+
# Probably should use this for something
|
111
|
+
# count = thread_count[0]
|
112
|
+
|
113
|
+
# I can't remember what header I found this in, but it's from a macOS header
|
114
|
+
# :sweat-smile:
|
115
|
+
x86_THREAD_STATE64_COUNT = ThreadState.sizeof / Fiddle::SIZEOF_INT
|
116
|
+
|
117
|
+
# Same here
|
118
|
+
x86_THREAD_STATE64 = 4
|
119
|
+
|
120
|
+
state_count = Fiddle::Pointer.malloc(Fiddle::SIZEOF_INT64_T)
|
121
|
+
state_count[0, Fiddle::SIZEOF_INT64_T] = [x86_THREAD_STATE64_COUNT].pack("l!")
|
181
122
|
|
123
|
+
state = ThreadState.malloc
|
124
|
+
if MacOS.thread_get_state(@thread, x86_THREAD_STATE64, state, state_count).zero?
|
125
|
+
return state
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
raise "Couldn't get CPU state"
|
130
|
+
end
|
131
|
+
|
132
|
+
def state= new_state
|
182
133
|
# I can't remember what header I found this in, but it's from a macOS header
|
183
134
|
# :sweat-smile:
|
184
135
|
x86_THREAD_STATE64_COUNT = ThreadState.sizeof / Fiddle::SIZEOF_INT
|
@@ -186,13 +137,7 @@ struct x86_thread_state64_t {
|
|
186
137
|
# Same here
|
187
138
|
x86_THREAD_STATE64 = 4
|
188
139
|
|
189
|
-
|
190
|
-
state_count[0, Fiddle::SIZEOF_INT64_T] = [x86_THREAD_STATE64_COUNT].pack("l!")
|
191
|
-
|
192
|
-
state = ThreadState.malloc
|
193
|
-
raise unless MacOS.thread_get_state(@thread, x86_THREAD_STATE64, state, state_count).zero?
|
194
|
-
|
195
|
-
state
|
140
|
+
raise unless MacOS.thread_set_state(@thread, x86_THREAD_STATE64, new_state, x86_THREAD_STATE64_COUNT).zero?
|
196
141
|
end
|
197
142
|
|
198
143
|
def continue
|
data/lib/asmrepl/repl.rb
CHANGED
@@ -9,6 +9,8 @@ else
|
|
9
9
|
end
|
10
10
|
|
11
11
|
module ASMREPL
|
12
|
+
MAXINT = 0xFFFFFFFFFFFFFFFF
|
13
|
+
|
12
14
|
class REPL
|
13
15
|
include Fiddle
|
14
16
|
|
@@ -43,9 +45,9 @@ module ASMREPL
|
|
43
45
|
|
44
46
|
if last_state[field] != state[field]
|
45
47
|
print "#{field.ljust(6)} "
|
46
|
-
print sprintf("%#018x", last_state[field])
|
48
|
+
print sprintf("%#018x", last_state[field] & MAXINT)
|
47
49
|
print " => "
|
48
|
-
puts bold(sprintf("%#018x", state[field]))
|
50
|
+
puts bold(sprintf("%#018x", state[field] & MAXINT))
|
49
51
|
end
|
50
52
|
end
|
51
53
|
|
@@ -83,18 +85,21 @@ module ASMREPL
|
|
83
85
|
last_state = state
|
84
86
|
end
|
85
87
|
|
86
|
-
# Move the JIT buffer to the current instruction pointer
|
87
|
-
pos = (state.rip - @buffer.memory.to_i)
|
88
|
-
@buffer.seek pos
|
89
88
|
use_history = true
|
90
89
|
begin
|
91
90
|
loop do
|
92
91
|
cmd = nil
|
93
92
|
prompt = sprintf("(rip %#018x)> ", state.rip)
|
94
93
|
text = Reline.readmultiline(prompt, use_history) do |multiline_input|
|
95
|
-
|
94
|
+
case multiline_input
|
95
|
+
when /\Adisasm\Z/
|
96
|
+
cmd = :disasm
|
97
|
+
when /\A\s*(\w+)\s*\Z/
|
96
98
|
register = $1
|
97
99
|
cmd = [:read, register]
|
100
|
+
when /\A\s*(\w+)\s*=\s*(\d+)\Z/
|
101
|
+
register = $1
|
102
|
+
cmd = [:write, register, $2.to_i]
|
98
103
|
else
|
99
104
|
cmd = :run
|
100
105
|
end
|
@@ -102,6 +107,15 @@ module ASMREPL
|
|
102
107
|
end
|
103
108
|
|
104
109
|
case cmd
|
110
|
+
in :disasm
|
111
|
+
# disassembles the JIT buffer. This is just for development,
|
112
|
+
# I don't want to make a hard dependency on crabstone right now.
|
113
|
+
# If you want to use this, install crabstone
|
114
|
+
begin
|
115
|
+
require "asmrepl/disasm"
|
116
|
+
ASMREPL::Disasm.disasm @buffer
|
117
|
+
rescue
|
118
|
+
end
|
105
119
|
in :run
|
106
120
|
break if text.chomp.empty?
|
107
121
|
begin
|
@@ -113,13 +127,23 @@ module ASMREPL
|
|
113
127
|
|
114
128
|
begin
|
115
129
|
binary = @assembler.assemble parser_result
|
130
|
+
|
131
|
+
# Move the JIT buffer to the current instruction pointer, but
|
132
|
+
# rewind RIP so that we write over the int3
|
133
|
+
pos = (state.rip - @buffer.memory.to_i - 1)
|
134
|
+
@buffer.seek pos
|
116
135
|
binary.bytes.each { |byte| @buffer.putc byte }
|
136
|
+
state.rip -= 1
|
137
|
+
tracer.state = state
|
117
138
|
rescue Fisk::Errors::InvalidInstructionError => e
|
118
139
|
# Print an error message when the instruction is invalid
|
119
140
|
puts e.message
|
120
141
|
next
|
121
142
|
end
|
122
143
|
break
|
144
|
+
in [:write, reg, val]
|
145
|
+
state[reg] = val
|
146
|
+
tracer.state = state
|
123
147
|
in [:read, "cpu"]
|
124
148
|
display_state state
|
125
149
|
in [:read, reg]
|
@@ -0,0 +1,108 @@
|
|
1
|
+
require "fiddle"
|
2
|
+
|
3
|
+
module ASMREPL
|
4
|
+
class ThreadState
|
5
|
+
def self.sizeof
|
6
|
+
fields.length * Fiddle::SIZEOF_INT64_T
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.malloc
|
10
|
+
new Fiddle::Pointer.malloc sizeof
|
11
|
+
end
|
12
|
+
|
13
|
+
FLAGS = [
|
14
|
+
['CF', 'Carry Flag'],
|
15
|
+
[nil, 'Reserved'],
|
16
|
+
['PF', 'Parity Flag'],
|
17
|
+
[nil, 'Reserved'],
|
18
|
+
['AF', 'Adjust Flag'],
|
19
|
+
[nil, 'Reserved'],
|
20
|
+
['ZF', 'Zero Flag'],
|
21
|
+
['SF', 'Sign Flag'],
|
22
|
+
['TF', 'Trap Flag'],
|
23
|
+
['IF', 'Interrupt Enable Flag'],
|
24
|
+
['DF', 'Direction Flag'],
|
25
|
+
['OF', 'Overflow Flag'],
|
26
|
+
['IOPL_H', 'I/O privilege level High bit'],
|
27
|
+
['IOPL_L', 'I/O privilege level Low bit'],
|
28
|
+
['NT', 'Nested Task Flag'],
|
29
|
+
[nil, 'Reserved'],
|
30
|
+
]
|
31
|
+
|
32
|
+
attr_reader :to_ptr
|
33
|
+
|
34
|
+
def initialize buffer
|
35
|
+
@to_ptr = buffer
|
36
|
+
end
|
37
|
+
|
38
|
+
def [] name
|
39
|
+
idx = fields.index(name)
|
40
|
+
return unless idx
|
41
|
+
to_ptr[Fiddle::SIZEOF_INT64_T * idx, Fiddle::SIZEOF_INT64_T].unpack1("l!")
|
42
|
+
end
|
43
|
+
|
44
|
+
def []= name, val
|
45
|
+
idx = fields.index(name)
|
46
|
+
return unless idx
|
47
|
+
to_ptr[Fiddle::SIZEOF_INT64_T * idx, Fiddle::SIZEOF_INT64_T] = [val].pack("l!")
|
48
|
+
end
|
49
|
+
|
50
|
+
def flags
|
51
|
+
flags = read_flags
|
52
|
+
f = []
|
53
|
+
FLAGS.each do |abbrv, _|
|
54
|
+
if abbrv && flags & 1 == 1
|
55
|
+
f << abbrv
|
56
|
+
end
|
57
|
+
flags >>= 1
|
58
|
+
end
|
59
|
+
f
|
60
|
+
end
|
61
|
+
|
62
|
+
def to_s
|
63
|
+
buf = ""
|
64
|
+
display_registers.first(8).zip(display_registers.drop(8)).each do |l, r|
|
65
|
+
buf << "#{l.ljust(3)} #{sprintf("%#018x", self[l] & MAXINT)}"
|
66
|
+
buf << " "
|
67
|
+
buf << "#{r.ljust(3)} #{sprintf("%#018x", self[r] & MAXINT)}\n"
|
68
|
+
end
|
69
|
+
|
70
|
+
buf << "\n"
|
71
|
+
|
72
|
+
other_registers.each do |reg|
|
73
|
+
buf << "#{reg.ljust(7)} #{sprintf("%#018x", self[reg] & MAXINT)}\n"
|
74
|
+
end
|
75
|
+
buf
|
76
|
+
end
|
77
|
+
|
78
|
+
def display_registers
|
79
|
+
%w{ rax rbx rcx rdx rdi rsi rbp rsp r8 r9 r10 r11 r12 r13 r14 r15 }
|
80
|
+
end
|
81
|
+
|
82
|
+
def other_registers
|
83
|
+
fields - display_registers
|
84
|
+
end
|
85
|
+
|
86
|
+
def self.build fields
|
87
|
+
Class.new(ThreadState) do
|
88
|
+
define_method(:fields) do
|
89
|
+
fields
|
90
|
+
end
|
91
|
+
|
92
|
+
define_singleton_method(:fields) do
|
93
|
+
fields
|
94
|
+
end
|
95
|
+
|
96
|
+
fields.each_with_index do |field, i|
|
97
|
+
define_method(field) do
|
98
|
+
to_ptr[Fiddle::SIZEOF_INT64_T * i, Fiddle::SIZEOF_INT64_T].unpack1("l!")
|
99
|
+
end
|
100
|
+
|
101
|
+
define_method("#{field}=") do |v|
|
102
|
+
to_ptr[Fiddle::SIZEOF_INT64_T * i, Fiddle::SIZEOF_INT64_T] = [v].pack("l!")
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
data/lib/asmrepl/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: asmrepl
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aaron Patterson
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-12-
|
11
|
+
date: 2021-12-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: minitest
|
@@ -83,12 +83,14 @@ files:
|
|
83
83
|
- bin/asmrepl
|
84
84
|
- lib/asmrepl.rb
|
85
85
|
- lib/asmrepl/assembler.rb
|
86
|
+
- lib/asmrepl/disasm.rb
|
86
87
|
- lib/asmrepl/linux.rb
|
87
88
|
- lib/asmrepl/macos.rb
|
88
89
|
- lib/asmrepl/parser.rb
|
89
90
|
- lib/asmrepl/parser.tab.rb
|
90
91
|
- lib/asmrepl/parser.y
|
91
92
|
- lib/asmrepl/repl.rb
|
93
|
+
- lib/asmrepl/thread_state.rb
|
92
94
|
- lib/asmrepl/version.rb
|
93
95
|
- test/asmrepl_test.rb
|
94
96
|
- test/helper.rb
|