memory_io 0.2.0 → 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
  SHA256:
3
- metadata.gz: 3de5ed7bf7e1f8543bbb290ed472f008ed9d8f4c1af032a11831bd904378c11e
4
- data.tar.gz: e99b29afb7cdcc7941bb6249bbe453cea2cb3a6cb6eab72a8965bfa5ef9802e3
3
+ metadata.gz: 0f287dc7b3453557bbcda2f2ce09e03d779d0dbff69f8ef059069f03c76da427
4
+ data.tar.gz: a471ab55f6abd70783a220d0939cdd8f84231f59a533a6470a9f64119c184a41
5
5
  SHA512:
6
- metadata.gz: d4d3d9e60c649dd8d4e6f3c3dfe3bb777d2a7ffd2065699e3f86fef27f9ddf079b90acc7d7a5be244301d45ba46d9c713b950bbaa7a113843631287fb1e9653f
7
- data.tar.gz: 2246f04654d036e8df50440cf2c3d9ebe50933921f5720bf5f69308648ab34849d869b3969f581579dba8930ae1fbd0e5a1d6e27246900129cef39212e2876bf
6
+ metadata.gz: 959a45d2dcab5ced28be35f6988a6c6fadbd1fd6510e21747727f16e87cabddf23e951ffba71d8deec4baa1be440ce5bd79b1fe54e1bad66a17deb9185c54db9
7
+ data.tar.gz: a1fe1e032d09a53ce4611e2738255ac1444b5a0283e959606a1da232db28c9d0d42a7277977b17d2bb8fcfa476cc58c53368ad64fa970d0b7b91a5536e59e79e
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2017 david942j
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md CHANGED
@@ -1,8 +1,8 @@
1
- [![Build Status](https://travis-ci.org/david942j/memory_io.svg?branch=master)](https://travis-ci.org/david942j/memory_io)
2
1
  [![Gem Version](https://badge.fury.io/rb/memory_io.svg)](https://badge.fury.io/rb/memory_io)
3
- [![Maintainability](https://api.codeclimate.com/v1/badges/dc8da34c5a8ab0095530/maintainability)](https://codeclimate.com/github/david942j/memory_io/maintainability)
4
- [![Test Coverage](https://api.codeclimate.com/v1/badges/dc8da34c5a8ab0095530/test_coverage)](https://codeclimate.com/github/david942j/memory_io/test_coverage)
5
- [![Inline docs](https://inch-ci.org/github/david942j/memory_io.svg?branch=master)](https://inch-ci.org/github/david942j/memory_io)
2
+ [![Build Status](https://github.com/david942j/memory_io/workflows/build/badge.svg)](https://github.com/david942j/memory_io/actions)
3
+ [![Maintainability](https://qlty.sh/gh/david942j/projects/memory_io/maintainability.svg)](https://qlty.sh/gh/david942j/projects/memory_io)
4
+ [![Code Coverage](https://qlty.sh/gh/david942j/projects/memory_io/coverage.svg)](https://qlty.sh/gh/david942j/projects/memory_io)
5
+ [![Yard Docs](http://img.shields.io/badge/yard-docs-blue.svg)](https://www.rubydoc.info/github/david942j/memory_io/)
6
6
  [![MIT License](https://img.shields.io/badge/license-MIT-blue.svg)](http://choosealicense.com/licenses/mit/)
7
7
 
8
8
  # MemoryIO
@@ -14,8 +14,8 @@ Read/Write complicated structures in memory easily.
14
14
  I usually need to dump a structure, say `string` in C++, from memory for debugging.
15
15
  This is not hard if using gdb.
16
16
  However, gdb doesn't support writing Ruby scripts
17
- (unless you use [gdb-ruby](https://github.com/david942j/gdb-ruby), which has dependency of **MemoryIO**).
18
- So I create this repo and want to make the debug procedure much easier.
17
+ (unless you use [gdb-ruby](https://github.com/david942j/gdb-ruby), which has **MemoryIO** as its dependency).
18
+ So I created this projected to make the debug procedure much easier.
19
19
 
20
20
  This repository has two main goals:
21
21
 
@@ -25,16 +25,14 @@ This repository has two main goals:
25
25
  ## Why
26
26
 
27
27
  It's not hard to read/write a process's memory (simply open the file `/proc/$PID/mem`),
28
- but it still worth to wrap it.
28
+ but it's still worthy to make a utility.
29
29
 
30
- This repo also targets to collect all common structures, such as how to parse a C++/Rust/Python object from memory.
30
+ This project also targets to collect all common structures, such as how to parse a C++/Rust/Python object from memory.
31
31
  Therefore, **Pull Requests of adding new structures** are welcome :D
32
32
 
33
33
  ## Supported Platform
34
34
 
35
35
  - Linux
36
- - (TODO) Windows
37
- - (TODO) MacOS
38
36
 
39
37
  ## Implemented Structures
40
38
 
@@ -122,7 +120,7 @@ string
122
120
  require 'memory_io'
123
121
  process = MemoryIO.attach(`pidof victim`.to_i)
124
122
 
125
- # An example that read a chunk of pt-malloc.
123
+ # An example that reads a chunk of pt-malloc.
126
124
  read_chunk = lambda do |stream|
127
125
  _prev_size = stream.read(8)
128
126
  size = (stream.read(8).unpack('Q').first & -16) - 8
data/lib/memory_io/io.rb CHANGED
@@ -183,7 +183,7 @@ module MemoryIO
183
183
  # @api private
184
184
  def to_proc(as, rw)
185
185
  ret = as.respond_to?(rw) ? as.method(rw) : as
186
- ret = ret.respond_to?(:call) ? ret : MemoryIO::Types.get_proc(ret, rw)
186
+ ret = MemoryIO::Types.get_proc(ret, rw) unless ret.respond_to?(:call)
187
187
  raise ArgumentError, <<-EOERR.strip unless ret.respond_to?(:call)
188
188
 
189
189
  Invalid argument `as`: #{as.inspect}. It should be either a Proc or a supported type of MemoryIO::Types.
@@ -16,11 +16,6 @@ module MemoryIO
16
16
  #
17
17
  # @note
18
18
  # This class only supports procfs-based system. i.e. /proc is mounted and readable.
19
- #
20
- # @todo
21
- # Support MacOS
22
- # @todo
23
- # Support Windows
24
19
  def initialize(pid)
25
20
  @pid = pid
26
21
  @mem = "/proc/#{pid}/mem"
@@ -37,8 +37,8 @@ module MemoryIO
37
37
  private
38
38
 
39
39
  def unpack(str)
40
- val = str.unpack(@pack_str).first
41
- val -= (2**(@bytes * 8)) if @signed && val >= (2**(@bytes * 8 - 1))
40
+ val = str.unpack1(@pack_str)
41
+ val -= (2**(@bytes * 8)) if @signed && val >= (2**((@bytes * 8) - 1))
42
42
  val
43
43
  end
44
44
 
@@ -22,9 +22,7 @@ module MemoryIO
22
22
  # std::string uses inlined-buffer if string length isn't larger than {LOCAL_CAPACITY}.
23
23
  LOCAL_CAPACITY = 15
24
24
 
25
- attr_reader :data # @return [::String]
26
- attr_reader :capacity # @return [Integer]
27
- attr_reader :dataplus # @return [Integer]
25
+ attr_reader :data, :capacity, :dataplus # @return [::String] # @return [Integer] # @return [Integer]
28
26
 
29
27
  # Instantiate a {CPP::String} object.
30
28
  #
@@ -33,6 +31,7 @@ module MemoryIO
33
31
  # @param [Integer] dataplus
34
32
  # A pointer.
35
33
  def initialize(data, capacity, dataplus)
34
+ super()
36
35
  @data = data
37
36
  @capacity = capacity
38
37
  @dataplus = dataplus
@@ -57,15 +56,14 @@ module MemoryIO
57
56
  # Custom inspect view.
58
57
  #
59
58
  # @return [String]
60
- #
61
- # @todo
62
- # Let it be colorful in pry.
63
59
  def inspect
60
+ # rubocop:disable Lint/FormatParameterMismatch
64
61
  format("#<%s @data=%s, @capacity=%d, @dataplus=0x%0#{SIZE_T * 2}x>",
65
62
  self.class.name,
66
63
  data.inspect,
67
64
  capacity,
68
65
  dataplus)
66
+ # rubocop:enable Lint/FormatParameterMismatch
69
67
  end
70
68
 
71
69
  class << self
@@ -109,10 +107,10 @@ module MemoryIO
109
107
  write_size_t(stream, obj.length)
110
108
  pos = stream.pos
111
109
  if obj.length > LOCAL_CAPACITY
112
- keep_pos(stream, pos: obj.dataplus) { |s| s.write(obj.data + "\x00") }
110
+ keep_pos(stream, pos: obj.dataplus) { |s| s.write("#{obj.data}\u0000") }
113
111
  write_size_t(stream, obj.capacity)
114
112
  else
115
- stream.write(obj.data + "\x00")
113
+ stream.write("#{obj.data}\u0000")
116
114
  end
117
115
  stream.pos = pos + LOCAL_CAPACITY + 1
118
116
  end
@@ -23,8 +23,8 @@ module MemoryIO
23
23
  # @option [Thread::Backtrace::Location] caller
24
24
  # This option should present if and only if +object+ is a subclass of {Types::Type}.
25
25
  # @option [String] doc
26
- # Docstring.
27
- # Automatically parse from caller location if this parameter isn't present.
26
+ # Doc-string.
27
+ # Automatically parse from caller location if this parameter doesn't present.
28
28
  def initialize(object, keys, option = {})
29
29
  @obj = object
30
30
  @keys = keys
@@ -60,14 +60,14 @@ module MemoryIO
60
60
  str.strip!
61
61
  break unless str.start_with?('#')
62
62
 
63
- strings.unshift(str[2..-1] || '')
63
+ strings.unshift(str[2..] || '')
64
64
  end
65
65
  trim_docstring(strings)
66
66
  end
67
67
 
68
68
  def trim_docstring(strings)
69
69
  strings = strings.drop_while { |s| s.start_with?('@') }.take_while { |s| !s.start_with?('@') }
70
- strings.drop_while(&:empty?).reverse.drop_while(&:empty?).reverse.join("\n") + "\n"
70
+ "#{strings.drop_while(&:empty?).reverse.drop_while(&:empty?).reverse.join("\n")}\n"
71
71
  end
72
72
  end
73
73
  end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'ostruct'
4
-
5
3
  require 'memory_io/types/record'
6
4
  require 'memory_io/util'
7
5
 
@@ -123,7 +121,7 @@ module MemoryIO
123
121
  #
124
122
  # @see .find
125
123
  def register(object, option = {})
126
- @map ||= OpenStruct.new
124
+ @map ||= {}
127
125
  aliases = Array(option[:alias])
128
126
  reg_fail = ArgumentError.new(<<-EOS.strip)
129
127
  Register '#{object.inspect}' fails because another object with same name has been registered.
@@ -152,6 +150,7 @@ Specify an alias such as `register(MyClass, alias: :custom_alias_name)`.
152
150
  #
153
151
  # To record descendants.
154
152
  def inherited(klass)
153
+ super
155
154
  register(klass, caller: caller_locations(1, 1).first)
156
155
  end
157
156
 
@@ -3,7 +3,7 @@
3
3
  require 'memory_io/types/type'
4
4
  require 'memory_io/util'
5
5
 
6
- Dir.glob(File.join(__dir__, '**', '*.rb')).sort.each { |f| require f unless f == __FILE__ }
6
+ Dir.glob(File.join(__dir__, '**', '*.rb')).each { |f| require f unless f == __FILE__ }
7
7
 
8
8
  module MemoryIO
9
9
  # Module that includes multiple types.
@@ -33,7 +33,7 @@ module MemoryIO
33
33
  # #=> #<MemoryIO::Types::Number:0x000055ecc017a310 @bytes=8, @pack_str="Q", @signed=false>
34
34
  def find(name)
35
35
  obj = Types::Type.find(name)
36
- return obj.obj if obj
36
+ obj&.obj
37
37
  end
38
38
 
39
39
  # @api private
@@ -1,11 +1,35 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'ostruct'
4
3
  require 'dentaku'
5
4
 
6
5
  module MemoryIO
7
6
  # Defines utility methods.
8
7
  module Util
8
+ # A simple class to be returned for getting file permissions.
9
+ class FilePermission
10
+ attr_reader :readable, :writable
11
+ # Alias the two methods to fit Ruby's method naming convention.
12
+ alias readable? readable
13
+ alias writable? writable
14
+
15
+ def initialize(file)
16
+ stat = File.stat(file)
17
+ @readable = stat.readable_real?
18
+ @writable = stat.writable_real?
19
+ # we do a trick here because /proc/[pid]/mem might be marked as writeable but fails at sysopen.
20
+ begin
21
+ @readable && File.open(file, 'rb').close
22
+ rescue Errno::EACCES
23
+ @readable = false
24
+ end
25
+ begin
26
+ @writable && File.open(file, 'wb').close
27
+ rescue Errno::EACCES
28
+ @writable = false
29
+ end
30
+ end
31
+ end
32
+
9
33
  module_function
10
34
 
11
35
  # Convert input into snake-case.
@@ -39,26 +63,12 @@ module MemoryIO
39
63
  # @param [String] file
40
64
  # File name.
41
65
  #
42
- # @return [#readable?, #writable?, nil]
43
- # Struct with two boolean method.
44
- # +nil+ for file not exists or is inaccessible.
66
+ # @return [MemoryIO::Util::FilePermission?]
67
+ # +nil+ is returned if file does not exist or is inaccessible.
45
68
  def file_permission(file)
46
69
  return nil unless File.file?(file)
47
70
 
48
- stat = File.stat(file)
49
- # we do a trick here because /proc/[pid]/mem might be marked as readable but fails at sysopen.
50
- os = OpenStruct.new(readable?: stat.readable_real?, writable?: stat.writable_real?)
51
- begin
52
- os.readable? && File.open(file, 'rb').close
53
- rescue Errno::EACCES
54
- os[:readable?] = false
55
- end
56
- begin
57
- os.writable? && File.open(file, 'wb').close
58
- rescue Errno::EACCES
59
- os[:writable?] = false
60
- end
61
- os
71
+ FilePermission.new(file)
62
72
  end
63
73
 
64
74
  # Evaluate string safely.
@@ -97,7 +107,7 @@ module MemoryIO
97
107
  # Util.unpack("@\xE2\x01\x00")
98
108
  # #=> 123456
99
109
  def unpack(str)
100
- str.bytes.reverse.reduce(0) { |s, c| s * 256 + c }
110
+ str.bytes.reverse.reduce(0) { |s, c| (s * 256) + c }
101
111
  end
102
112
 
103
113
  # Pack an integer into +b+ bytes.
@@ -135,9 +145,13 @@ module MemoryIO
135
145
  # #=> 'libcrypto'
136
146
  # Util.trim_libname('not_a_so')
137
147
  # #=> 'not_a_so'
148
+ # Util.trim_libname('ld-linux-x86-64.so.2')
149
+ # #=> 'ld'
138
150
  def trim_libname(name)
151
+ return 'ld' if name.start_with?('ld-')
152
+
139
153
  type1 = '(-[\d.]+)?\.so$'
140
- type2 = '\.so.\d+[\d.]+$'
154
+ type2 = '\.so.[\.\d]+$'
141
155
  name.sub(/#{type1}|#{type2}/, '')
142
156
  end
143
157
  end
@@ -2,5 +2,5 @@
2
2
 
3
3
  module MemoryIO
4
4
  # Current gem version.
5
- VERSION = '0.2.0'
5
+ VERSION = '0.3.0'
6
6
  end
metadata CHANGED
@@ -1,29 +1,42 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: memory_io
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - david942j
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2020-03-07 00:00:00.000000000 Z
10
+ date: 2025-11-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: dentaku
15
14
  requirement: !ruby/object:Gem::Requirement
16
15
  requirements:
17
- - - ">="
16
+ - - "~>"
18
17
  - !ruby/object:Gem::Version
19
- version: 2.0.11
18
+ version: '3'
20
19
  type: :runtime
21
20
  prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - "~>"
24
+ - !ruby/object:Gem::Version
25
+ version: '3'
26
+ - !ruby/object:Gem::Dependency
27
+ name: ostruct
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '0.6'
33
+ type: :development
34
+ prerelease: false
22
35
  version_requirements: !ruby/object:Gem::Requirement
23
36
  requirements:
24
37
  - - ">="
25
38
  - !ruby/object:Gem::Version
26
- version: 2.0.11
39
+ version: '0.6'
27
40
  - !ruby/object:Gem::Dependency
28
41
  name: rake
29
42
  requirement: !ruby/object:Gem::Requirement
@@ -58,28 +71,28 @@ dependencies:
58
71
  requirements:
59
72
  - - "~>"
60
73
  - !ruby/object:Gem::Version
61
- version: '0.59'
74
+ version: '1'
62
75
  type: :development
63
76
  prerelease: false
64
77
  version_requirements: !ruby/object:Gem::Requirement
65
78
  requirements:
66
79
  - - "~>"
67
80
  - !ruby/object:Gem::Version
68
- version: '0.59'
81
+ version: '1'
69
82
  - !ruby/object:Gem::Dependency
70
83
  name: simplecov
71
84
  requirement: !ruby/object:Gem::Requirement
72
85
  requirements:
73
86
  - - "~>"
74
87
  - !ruby/object:Gem::Version
75
- version: '0.17'
88
+ version: '0.22'
76
89
  type: :development
77
90
  prerelease: false
78
91
  version_requirements: !ruby/object:Gem::Requirement
79
92
  requirements:
80
93
  - - "~>"
81
94
  - !ruby/object:Gem::Version
82
- version: '0.17'
95
+ version: '0.22'
83
96
  - !ruby/object:Gem::Dependency
84
97
  name: yard
85
98
  requirement: !ruby/object:Gem::Requirement
@@ -96,13 +109,14 @@ dependencies:
96
109
  version: '0.9'
97
110
  description: 'Read/Write complicated structures in memory easily.
98
111
 
99
- '
112
+ '
100
113
  email:
101
114
  - david942j@gmail.com
102
115
  executables: []
103
116
  extensions: []
104
117
  extra_rdoc_files: []
105
118
  files:
119
+ - LICENSE
106
120
  - README.md
107
121
  - lib/memory_io.rb
108
122
  - lib/memory_io/io.rb
@@ -118,8 +132,8 @@ files:
118
132
  homepage: https://github.com/david942j/memory_io
119
133
  licenses:
120
134
  - MIT
121
- metadata: {}
122
- post_install_message:
135
+ metadata:
136
+ rubygems_mfa_required: 'true'
123
137
  rdoc_options: []
124
138
  require_paths:
125
139
  - lib
@@ -127,15 +141,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
127
141
  requirements:
128
142
  - - ">="
129
143
  - !ruby/object:Gem::Version
130
- version: '2.3'
144
+ version: '3.2'
131
145
  required_rubygems_version: !ruby/object:Gem::Requirement
132
146
  requirements:
133
147
  - - ">="
134
148
  - !ruby/object:Gem::Version
135
149
  version: '0'
136
150
  requirements: []
137
- rubygems_version: 3.0.3
138
- signing_key:
151
+ rubygems_version: 3.6.2
139
152
  specification_version: 4
140
153
  summary: memory_io
141
154
  test_files: []