gdb 0.2.1 → 0.3.0

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