gdb 0.2.1 → 0.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: de69fa7d5ddc398f6e0bdd176061f23bd650acba
4
- data.tar.gz: 5d86b5bafafa5d321226633751375a3faf9513fd
3
+ metadata.gz: 465e52470a227ee794a0ad1cbc6e643b6e7892d6
4
+ data.tar.gz: 377b2acb9be71480b63999833ea24247dcceba1e
5
5
  SHA512:
6
- metadata.gz: 0a534be09b10af62159decf1793bad3c977680b9885bd4de3af3c70211d6319d3fde4720e1079d26f83e57dc2518af2f8b3ac9c0f7fac7454715705069f25d43
7
- data.tar.gz: 40b8085db8abb15a5d2564b6fc4d43c185ccf21d9fa799f93e48dbb669289a2dbdb34aaf254c963351c16ce93beacf0c7badc188e3a6afbeece41bb12cc59401
6
+ metadata.gz: efbff6edff5a76a1774bb4a5ba2300885cce78ff783730270fef4f0d5b8b1503539efa626f6cd56a220f4a9ccc0a2646c96eaa6d0392e7ff64511f9ef143f39b
7
+ data.tar.gz: b91c6d713bc611fefcfa1898097ccfa402e18220f737f39ab1de6ee830603c760283a6a761ba7c745a4001255b316ccf8a9945df327781a7208335308d84ade0
data/README.md CHANGED
@@ -104,8 +104,8 @@ gdb.run('-c "echo cat"')
104
104
  rdi = gdb.reg(:rdi)
105
105
  #=> 3
106
106
  rsi = gdb.reg(:rsi)
107
- argv = gdb.readm(rsi, rdi, as: :uint64)
108
- argv.map{ |c|'0x%x' % c }
107
+ argv = gdb.readm(rsi, rdi, as: :u64)
108
+ argv.map { |c| '0x%x' % c }
109
109
  #=> ['0x7fffffffe61b', '0x7fffffffe625', '0x7fffffffe628']
110
110
 
111
111
  # 3. overwrite argv[2]'s 'cat' to 'FAT'
@@ -1,11 +1,11 @@
1
1
  require 'io/console'
2
+ require 'memory_io'
2
3
  require 'pty'
3
4
  require 'readline'
4
5
 
5
6
  require 'gdb/eval_context'
6
7
  require 'gdb/gdb_error'
7
8
  require 'gdb/tube/tube'
8
- require 'gdb/type_io'
9
9
 
10
10
  module GDB
11
11
  # For launching a gdb process.
@@ -156,19 +156,35 @@ module GDB
156
156
 
157
157
  # Read current process's memory.
158
158
  #
159
- # See {TypeIO#read} for details.
159
+ # @param [Integer, String] addr
160
+ # Address to start to read.
161
+ # +addr+ can be a string like 'heap+0x10'.
162
+ # Supported variables are names in /proc/$pid/maps such as +heap/libc/stack/ld+.
160
163
  #
161
- # @param [Mixed] args
162
- # See {TypeIO#read}.
164
+ # @param [Integer] num_elements
165
+ # Number of elements to read.
166
+ # If +num_elements+ equals to 1, an object read will be returned.
167
+ # Otherwise, an array with size +num_elements+ will be returned.
163
168
  #
164
- # @return [Object]
165
- # See {TypeIO#read}.
169
+ # @option [Symbol, Class] as
170
+ # Types that supported by [MemoryIO](https://github.com/david942j/memory_io).
171
+ #
172
+ # @return [Object, Array<Object>]
173
+ # Return types are decided by value of +num_elements+ and option +as+.
166
174
  #
167
175
  # @yieldparam [IO] io
168
- # See {TypeIO#read}.
176
+ # The +IO+ object that points to +addr+,
177
+ # read from it.
169
178
  #
170
179
  # @yieldreturn [Object]
171
- # See {TypeIO#read}.
180
+ # Whatever you read from +io+.
181
+ #
182
+ # @example
183
+ # gdb = GDB::GDB.new('spec/binaries/amd64.elf')
184
+ # gdb.break('main')
185
+ # gdb.run
186
+ # gdb.read_memory('amd64.elf', 4)
187
+ # #=> "\x7fELF"
172
188
  #
173
189
  # @example
174
190
  # # example of fetching argv
@@ -179,41 +195,47 @@ module GDB
179
195
  # #=> "\x7fELF"
180
196
  # argc = gdb.register(:rdi)
181
197
  # #=> 4
182
- # args = gdb.read_memory(gdb.register(:rsi), argc, as: :uint64)
198
+ # args = gdb.read_memory(gdb.register(:rsi), argc, as: :u64)
183
199
  # Array.new(3) do |i|
184
200
  # gdb.read_memory(args[i + 1], 1) do |m|
185
201
  # str = ''
186
- # str << m.read(1) until str.end_with?("\x00")
202
+ # loop do
203
+ # c = m.read(1)
204
+ # break if c == "\x00"
205
+ # str << c
206
+ # end
187
207
  # str
188
208
  # end
189
209
  # end
190
- # #=> ["pusheen\x00", "the\x00", "cat\x00"]
210
+ # #=> ["pusheen", "the", "cat"]
191
211
  #
192
- # # or, use our build-in types listed in {TypeIO::TYPES}
193
- # gdb.read_memory(args[1], 3, as: :cstring)
194
- # #=> ["pusheen\x00", "the\x00", "cat\x00"]
195
- def read_memory(*args, &block)
212
+ # # or, use our build-in types of gem +memory_io+.
213
+ # gdb.read_memory(args[1], 3, as: :c_str)
214
+ # #=> ["pusheen", "the", "cat"]
215
+ def read_memory(addr, num_elements, options = {}, &block)
196
216
  check_alive! # this would set @pid
197
- File.open("/proc/#{@pid}/mem", 'rb') do |f|
198
- ::GDB::TypeIO.new(f).read(*args, &block)
199
- end
217
+ options[:as] = block if block_given?
218
+ MemoryIO.attach(@pid).read(addr, num_elements, **options)
200
219
  end
201
220
  alias readm read_memory
202
221
 
203
- # Write a string to process at specific address.
222
+ # Write an object to process at specific address.
204
223
  #
205
- # @param [Integer] addr
224
+ # @param [Integer, String] addr
206
225
  # Target address.
207
- # @param [String] str
208
- # String to be written.
226
+ # +addr+ can be a string like 'heap+0x10'.
227
+ # Supported variables are names in +/proc/$pid/maps+ such as +heap/libc/stack/ld+.
228
+ # @param [Objects, Array<Objects>] objects
229
+ # Objects to be written.
209
230
  #
210
- # @return [Integer]
211
- # Bytes written.
212
- def write_memory(addr, str)
231
+ # @option [Symbol, Class] as
232
+ # See {#read_memory}.
233
+ #
234
+ # @return [void]
235
+ def write_memory(addr, objects, options = {}, &block)
213
236
  check_alive! # this would set @pid
214
- File.open("/proc/#{@pid}/mem", 'wb') do |f|
215
- ::GDB::TypeIO.new(f).write(addr, str)
216
- end
237
+ options[:as] = block if block_given?
238
+ MemoryIO.attach(@pid).write(addr, objects, **options)
217
239
  end
218
240
  alias writem write_memory
219
241
 
@@ -251,7 +273,7 @@ module GDB
251
273
 
252
274
  # Raise {GDBError} if process is not running.
253
275
  #
254
- # @return [nil]
276
+ # @return [void]
255
277
  def check_alive!
256
278
  raise GDBError, 'Process is not running' unless alive?
257
279
  end
@@ -1,4 +1,4 @@
1
1
  module GDB
2
2
  # The current version of GDB.
3
- VERSION = '0.2.1'.freeze
3
+ VERSION = '0.3.0'.freeze
4
4
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gdb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - david942j
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-10-14 00:00:00.000000000 Z
11
+ date: 2018-01-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pry
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0.11'
27
+ - !ruby/object:Gem::Dependency
28
+ name: memory_io
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 0.1.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 0.1.0
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: codeclimate-test-reporter
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -44,42 +58,42 @@ dependencies:
44
58
  requirements:
45
59
  - - "~>"
46
60
  - !ruby/object:Gem::Version
47
- version: '12.1'
61
+ version: '12.3'
48
62
  type: :development
49
63
  prerelease: false
50
64
  version_requirements: !ruby/object:Gem::Requirement
51
65
  requirements:
52
66
  - - "~>"
53
67
  - !ruby/object:Gem::Version
54
- version: '12.1'
68
+ version: '12.3'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: rspec
57
71
  requirement: !ruby/object:Gem::Requirement
58
72
  requirements:
59
73
  - - "~>"
60
74
  - !ruby/object:Gem::Version
61
- version: '3.5'
75
+ version: '3.7'
62
76
  type: :development
63
77
  prerelease: false
64
78
  version_requirements: !ruby/object:Gem::Requirement
65
79
  requirements:
66
80
  - - "~>"
67
81
  - !ruby/object:Gem::Version
68
- version: '3.5'
82
+ version: '3.7'
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: rubocop
71
85
  requirement: !ruby/object:Gem::Requirement
72
86
  requirements:
73
87
  - - "~>"
74
88
  - !ruby/object:Gem::Version
75
- version: '0.49'
89
+ version: '0.52'
76
90
  type: :development
77
91
  prerelease: false
78
92
  version_requirements: !ruby/object:Gem::Requirement
79
93
  requirements:
80
94
  - - "~>"
81
95
  - !ruby/object:Gem::Version
82
- version: '0.49'
96
+ version: '0.52'
83
97
  - !ruby/object:Gem::Dependency
84
98
  name: simplecov
85
99
  requirement: !ruby/object:Gem::Requirement
@@ -127,7 +141,6 @@ files:
127
141
  - lib/gdb/scripts/gdbinit.py
128
142
  - lib/gdb/tube/buffer.rb
129
143
  - lib/gdb/tube/tube.rb
130
- - lib/gdb/type_io.rb
131
144
  - lib/gdb/version.rb
132
145
  homepage: https://github.com/david942j/gdb-ruby
133
146
  licenses:
@@ -149,7 +162,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
149
162
  version: '0'
150
163
  requirements: []
151
164
  rubyforge_project:
152
- rubygems_version: 2.5.2
165
+ rubygems_version: 2.6.14
153
166
  signing_key:
154
167
  specification_version: 4
155
168
  summary: GDB Ruby-binding and Ruby command in GDB
@@ -1,148 +0,0 @@
1
- module GDB
2
- # Support read / write custom defined tpyes.
3
- class TypeIO
4
- class << self
5
- # Read a little endian integer.
6
- #
7
- # @param [#read] io
8
- # @param [Integer] byte
9
- # @param [:signed, :unsigned] sign
10
- # Signed or unsigned integer.
11
- #
12
- # @return [Integer]
13
- # The read integer.
14
- #
15
- # @example
16
- # read_integer(StringIO.new("\x80"), 1, :signed)
17
- # #=> -128
18
- def read_integer(io, byte, sign)
19
- str = io.read(byte).reverse # little endian
20
- val = str.bytes.reduce(0) { |sum, b| sum * 256 + b }
21
- if sign == :signed && val >= (1 << (8 * byte - 1))
22
- val -= 1 << (8 * byte)
23
- end
24
- val
25
- end
26
-
27
- # Read until +needle+ appears.
28
- #
29
- # @param [IO] io
30
- # @param [String] needle
31
- #
32
- # @return [String]
33
- def read_until(io, needle)
34
- str = ''
35
- str << io.read(1) until str.end_with?(needle)
36
- str
37
- end
38
- end
39
-
40
- # Supported built-in types.
41
- TYPES = {
42
- string: nil, # will be special handled
43
-
44
- cstring: ->(io) { TypeIO.read_until(io, "\x00") }, # read a null-terminated string.
45
-
46
- int8: ->(io) { TypeIO.read_integer(io, 1, :signed) },
47
- int16: ->(io) { TypeIO.read_integer(io, 2, :signed) },
48
- int32: ->(io) { TypeIO.read_integer(io, 4, :signed) },
49
- int64: ->(io) { TypeIO.read_integer(io, 8, :signed) },
50
- int128: ->(io) { TypeIO.read_integer(io, 16, :signed) },
51
-
52
- uint8: ->(io) { TypeIO.read_integer(io, 1, :unsigned) },
53
- uint16: ->(io) { TypeIO.read_integer(io, 2, :unsigned) },
54
- uint32: ->(io) { TypeIO.read_integer(io, 4, :unsigned) },
55
- uint64: ->(io) { TypeIO.read_integer(io, 8, :unsigned) },
56
- uint128: ->(io) { TypeIO.read_integer(io, 16, :unsigned) },
57
-
58
- float: ->(io) { io.read(4).unpack('F').first },
59
- double: ->(io) { io.read(8).unpack('D').first }
60
- }.freeze
61
-
62
- # Instantiate a {TypeIO} object.
63
- #
64
- # @param [IO, #pos=, #read, #write] io
65
- # The IO file.
66
- def initialize(io)
67
- @io = io.binmode
68
- end
69
-
70
- # Read data at specific address and cast into desired type.
71
- #
72
- # @param [Integer] addr
73
- # Address to be read.
74
- #
75
- # @param [Integer] size
76
- # Number of data to be read. See parameter +as+ for details.
77
- #
78
- # @param [Symbol] as
79
- # The needed returned type.
80
- # Note that the total bytes be read will be +size * sizeof(as)+.
81
- # For example, if +as+ equals +:int32+, +size * 4+ bytes would be read,
82
- # and returned type is array of 32 bits signed integers.
83
- #
84
- # Supported types are listed in {TypeIO::TYPES}, all integer-like types
85
- # are seen as little endian. If you need big endian or other fashion things, pass a block
86
- # instead of using parameter +as+.
87
- #
88
- # @yieldparam [IO] io
89
- # If block is given, the parameter +as+ would be ignored.
90
- # Block would be invoked +size+ times, and the returned object would be collected into
91
- # one array and returned.
92
- #
93
- # This is convenient for reading non-stable size objects, e.g. c++'s string object.
94
- # See examples for clearer usage.
95
- #
96
- # @yieldreturn [Object]
97
- # Whatever object you like.
98
- #
99
- # @return [String, Object, Array<Object>]
100
- # If +as+ equals to +:string+, the string with length +size+ would be returned.
101
- # Otherwise, array of objects would be returned.
102
- # An exception is when +size+ equals to 1, the read object would be returned
103
- # instead of create an array with only one element.
104
- #
105
- # @example
106
- # io = TypeIO.new(StringIO.new("AAAA"))
107
- # io.read(0, 3)
108
- # #=> "AAA"
109
- # io.read(0, 1, as: :uint32)
110
- # #=> 1094795585 # 0x41414141
111
- #
112
- # io = TypeIO.new(StringIO.new("\xef\xbe\xad\xde"))
113
- # io.read(0, 4, as: :int8)
114
- # #=> [-17, -66, -83, -34]
115
- #
116
- # io = TypeIO.new(StringIO.new("\x04ABCD\x03AAA\x00\x04meow"))
117
- # io.read(0, 4) do |m|
118
- # len = m.read(1).ord
119
- # m.read(len)
120
- # end
121
- # #=> ['ABCD', 'AAA', '', 'meow']
122
- def read(addr, size, as: :string)
123
- @io.pos = addr
124
- if block_given?
125
- return yield @io if size == 1
126
- Array.new(size) { yield @io }
127
- else
128
- raise ArgumentError, "Unsupported types #{as.inspect}" unless TYPES.key?(as)
129
- return @io.read(size) if as == :string
130
- read(addr, size, &TYPES[as])
131
- end
132
- end
133
-
134
- # Write a string at specific address.
135
- #
136
- # @param [Integer] addr
137
- # Target address.
138
- # @param [String] str
139
- # String to be written.
140
- #
141
- # @return [Integer]
142
- # Bytes written.
143
- def write(addr, str)
144
- @io.pos = addr
145
- @io.write(str)
146
- end
147
- end
148
- end