heapinfo 0.0.5 → 0.1.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/README.md +1 -0
- data/lib/heapinfo.rb +8 -8
- data/lib/heapinfo/arena.rb +47 -45
- data/lib/heapinfo/cache.rb +12 -13
- data/lib/heapinfo/chunk.rb +23 -23
- data/lib/heapinfo/chunks.rb +16 -5
- data/lib/heapinfo/dumper.rb +55 -44
- data/lib/heapinfo/ext/string.rb +2 -2
- data/lib/heapinfo/glibc/error.rb +2 -1
- data/lib/heapinfo/glibc/free.rb +29 -16
- data/lib/heapinfo/glibc/glibc.rb +5 -1
- data/lib/heapinfo/glibc/helper.rb +9 -6
- data/lib/heapinfo/helper.rb +22 -26
- data/lib/heapinfo/libc.rb +18 -17
- data/lib/heapinfo/nil.rb +14 -8
- data/lib/heapinfo/process.rb +34 -25
- data/lib/heapinfo/process_info.rb +15 -14
- data/lib/heapinfo/segment.rb +10 -9
- data/lib/heapinfo/tools/get_arena.c +0 -1
- data/lib/heapinfo/version.rb +1 -1
- metadata +75 -31
- data/spec/cache_spec.rb +0 -46
- data/spec/chunk_spec.rb +0 -40
- data/spec/chunks_spec.rb +0 -25
- data/spec/dumper_spec.rb +0 -105
- data/spec/files/32bit_maps +0 -23
- data/spec/files/64bit_maps +0 -29
- data/spec/files/victim.cpp +0 -33
- data/spec/helper_spec.rb +0 -73
- data/spec/libc_spec.rb +0 -75
- data/spec/nil_spec.rb +0 -15
- data/spec/process_spec.rb +0 -201
- data/spec/spec_helper.rb +0 -98
- data/spec/string_spec.rb +0 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bb558249510b9c160a5f0f699d702a17b1189624
|
4
|
+
data.tar.gz: dacc4780724a2254d8137a23d2f920734db9034d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8fce3e42275b5895a2bec83dbe31d216d1d5a7506905e4d0e527f449c4418f9af00d6f9133d8b1074bb293e7a33ac0557833539562d68dd7a7cfc22d04404885
|
7
|
+
data.tar.gz: 1d036055d53f75e3d9639af6274682b29f5d8f6b275d4644d2619fa29ce4bbed559871ea9caf4b72c66fe81a82dcf4bd0496de239fd88b807df8b50757790ef5
|
data/README.md
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
[](https://travis-ci.org/david942j/heapinfo)
|
2
|
+

|
2
3
|
[](https://codeclimate.com/github/david942j/heapinfo)
|
3
4
|
[](https://codeclimate.com/github/david942j/heapinfo)
|
4
5
|
[](https://codeclimate.com/github/david942j/heapinfo/coverage)
|
data/lib/heapinfo.rb
CHANGED
@@ -11,12 +11,13 @@ require 'fileutils'
|
|
11
11
|
module HeapInfo
|
12
12
|
# Directory for writing some tmp files when working,
|
13
13
|
# make sure /tmp is writable
|
14
|
-
TMP_DIR = '/tmp/.heapinfo'
|
15
|
-
FileUtils.mkdir_p
|
14
|
+
TMP_DIR = '/tmp/.heapinfo'.freeze
|
15
|
+
FileUtils.mkdir_p(TMP_DIR)
|
16
16
|
|
17
|
-
# Entry point for using HeapInfo.
|
18
|
-
# Show segments info of the process after loaded
|
19
|
-
# @param [String, Fixnum] prog
|
17
|
+
# Entry point for using {HeapInfo}.
|
18
|
+
# Show segments info of the process after loaded.
|
19
|
+
# @param [String, Fixnum] prog
|
20
|
+
# The program name of victim. If a number is given, seem as pid (useful when multi-processes exist).
|
20
21
|
# @param [Hash] options Give library's file name.
|
21
22
|
# @option options [String, Regexp] :libc file name of glibc, default is <tt>/libc[^\w]/</tt>
|
22
23
|
# @option options [String, Regexp] :ld file name of dynamic linker/loader, default is <tt>/\/ld-.+\.so/</tt>
|
@@ -34,7 +35,7 @@ module HeapInfo
|
|
34
35
|
# # => "/lib/x86_64-linux-gnu/libc-2.19.so"
|
35
36
|
# p h.ld.name
|
36
37
|
# # => "/lib/x86_64-linux-gnu/ld-2.19.so"
|
37
|
-
#
|
38
|
+
#
|
38
39
|
# @example
|
39
40
|
# h = heapinfo(27605, libc: 'libc.so.6', ld: 'ld-linux-x86-64.so.2')
|
40
41
|
# # pid 27605 is run by custom loader
|
@@ -53,9 +54,8 @@ end
|
|
53
54
|
# @return [HeapInfo::Process]
|
54
55
|
# @param [Mixed] args see #HeapInfo::heapinfo for more information
|
55
56
|
def heapinfo(*args)
|
56
|
-
::HeapInfo
|
57
|
+
::HeapInfo.heapinfo(*args)
|
57
58
|
end
|
58
|
-
|
59
59
|
|
60
60
|
require 'heapinfo/helper'
|
61
61
|
require 'heapinfo/nil'
|
data/lib/heapinfo/arena.rb
CHANGED
@@ -11,34 +11,36 @@ module HeapInfo
|
|
11
11
|
attr_reader :unsorted_bin
|
12
12
|
# @return [Array<HeapInfo::Smallbin>] Smallbins in an array.
|
13
13
|
attr_reader :smallbin
|
14
|
-
# @return [Integer] The
|
14
|
+
# @return [Integer] The +system_mem+ in arena.
|
15
15
|
attr_reader :system_mem
|
16
16
|
# attr_reader :largebin, :last_remainder
|
17
17
|
|
18
|
-
# Instantiate a
|
18
|
+
# Instantiate a {HeapInfo::Arena} object.
|
19
19
|
#
|
20
20
|
# @param [Integer] base Base address of arena.
|
21
21
|
# @param [Integer] size_t Either 8 or 4
|
22
22
|
# @param [Proc] dumper For dump more data
|
23
23
|
def initialize(base, size_t, dumper)
|
24
|
-
@base
|
24
|
+
@base = base
|
25
|
+
@size_t = size_t
|
26
|
+
@dumper = dumper
|
25
27
|
reload!
|
26
28
|
end
|
27
29
|
|
28
30
|
# Refresh all attributes.
|
29
|
-
# Retrive data using
|
31
|
+
# Retrive data using +@dumper+, load bins, top chunk etc.
|
30
32
|
# @return [HeapInfo::Arena] self
|
31
33
|
def reload!
|
32
34
|
top_ptr_offset = @base + 8 + size_t * 10
|
33
35
|
top_ptr = Helper.unpack(size_t, @dumper.call(top_ptr_offset, size_t))
|
34
36
|
@fastbin = []
|
35
|
-
return self if top_ptr
|
37
|
+
return self if top_ptr.zero? # arena not init yet
|
36
38
|
@top_chunk = Chunk.new size_t, top_ptr, @dumper
|
37
39
|
@last_remainder = Chunk.new size_t, top_ptr_offset + 8, @dumper
|
38
40
|
# this offset diff after 2.23
|
39
|
-
@system_mem = 2
|
41
|
+
@system_mem = Array.new(2) do |off|
|
40
42
|
Helper.unpack(size_t, @dumper.call(top_ptr_offset + 258 * size_t + 16 + off * size_t, size_t))
|
41
|
-
end.find { |val| val >= 0x21000
|
43
|
+
end.find { |val| val >= 0x21000 && (val & 0xfff).zero? }
|
42
44
|
@fastbin = Array.new(7) do |idx|
|
43
45
|
f = Fastbin.new(size_t, @base + 8 - size_t * 2 + size_t * idx, @dumper, head: true)
|
44
46
|
f.index = idx
|
@@ -67,7 +69,8 @@ module HeapInfo
|
|
67
69
|
res
|
68
70
|
end
|
69
71
|
|
70
|
-
|
72
|
+
private
|
73
|
+
|
71
74
|
attr_reader :size_t
|
72
75
|
end
|
73
76
|
|
@@ -77,10 +80,10 @@ module HeapInfo
|
|
77
80
|
attr_reader :fd
|
78
81
|
# @return [Integer] index
|
79
82
|
attr_accessor :index
|
80
|
-
|
81
|
-
# Instantiate a
|
83
|
+
|
84
|
+
# Instantiate a {HeapInfo::Fastbin} object.
|
82
85
|
#
|
83
|
-
# @param [Mixed] args See
|
86
|
+
# @param [Mixed] args See {HeapInfo::Chunk} for more information.
|
84
87
|
def initialize(*args)
|
85
88
|
super
|
86
89
|
@fd = Helper.unpack(size_t, @data[0, @size_t])
|
@@ -95,7 +98,9 @@ module HeapInfo
|
|
95
98
|
# For pretty inspect.
|
96
99
|
# @return [String] Title with color codes.
|
97
100
|
def title
|
98
|
-
|
101
|
+
class_name = Helper.color(Helper.class_name(self), sev: :bin)
|
102
|
+
size_str = index.nil? ? nil : "[#{Helper.color(format('%#x', idx_to_size))}]"
|
103
|
+
"#{class_name}#{size_str}: "
|
99
104
|
end
|
100
105
|
|
101
106
|
# Pretty inspect.
|
@@ -104,15 +109,15 @@ module HeapInfo
|
|
104
109
|
title + list.map do |ptr|
|
105
110
|
next "(#{ptr})\n" if ptr.is_a? Symbol
|
106
111
|
next " => (nil)\n" if ptr.nil?
|
107
|
-
|
112
|
+
format(' => %s', Helper.color(format('%#x', ptr)))
|
108
113
|
end.join
|
109
114
|
end
|
110
115
|
|
111
|
-
# @return [Array<Integer, Symbol, NilClass>] single link list of
|
116
|
+
# @return [Array<Integer, Symbol, NilClass>] single link list of +fd+ chain.
|
112
117
|
# Last element will be:
|
113
|
-
# -
|
114
|
-
# -
|
115
|
-
# -
|
118
|
+
# - +:loop+ if loop detectded
|
119
|
+
# - +:invalid+ invalid address detected
|
120
|
+
# - +nil+ end with zero address (normal case)
|
116
121
|
def list
|
117
122
|
dup = {}
|
118
123
|
ptr = @fd
|
@@ -127,19 +132,20 @@ module HeapInfo
|
|
127
132
|
ret << nil
|
128
133
|
end
|
129
134
|
|
130
|
-
# @param [Integer] ptr Get the
|
131
|
-
# @return [Integer] The
|
135
|
+
# @param [Integer] ptr Get the +fd+ value of chunk at +ptr+.
|
136
|
+
# @return [Integer] The +fd+.
|
132
137
|
def fd_of(ptr)
|
133
138
|
addr_of(ptr, 2)
|
134
139
|
end
|
135
140
|
|
136
|
-
# @param [Integer] ptr Get the
|
137
|
-
# @return [Integer] The
|
141
|
+
# @param [Integer] ptr Get the +bk+ value of chunk at +ptr+.
|
142
|
+
# @return [Integer] The +bk+.
|
138
143
|
def bk_of(ptr)
|
139
144
|
addr_of(ptr, 3)
|
140
145
|
end
|
141
146
|
|
142
|
-
|
147
|
+
private
|
148
|
+
|
143
149
|
def addr_of(ptr, offset)
|
144
150
|
t = dump(ptr + size_t * offset, size_t)
|
145
151
|
return nil if t.nil?
|
@@ -152,63 +158,60 @@ module HeapInfo
|
|
152
158
|
# @return [Integer]
|
153
159
|
attr_reader :bk
|
154
160
|
|
155
|
-
# Instantiate a
|
161
|
+
# Instantiate a {HeapInfo::UnsortedBin} object.
|
156
162
|
#
|
157
|
-
# @param [Mixed] args See
|
163
|
+
# @param [Mixed] args See {HeapInfo::Chunk} for more information.
|
158
164
|
def initialize(*args)
|
159
165
|
super
|
160
166
|
@bk = Helper.unpack(size_t, @data[@size_t, @size_t])
|
161
167
|
end
|
162
168
|
|
163
|
-
# @
|
169
|
+
# @param [Integer] size
|
170
|
+
# At most expand size. For +size = 2+, the expand list would be +bk, bk, bin, fd, fd+.
|
164
171
|
# @return [String] unsorted bin layouts wrapper with color codes.
|
165
172
|
def inspect(size: 2)
|
166
173
|
list = link_list(size)
|
167
|
-
return '' if list.size <= 1
|
174
|
+
return '' if list.size <= 1 && Helper.class_name(self) != 'UnsortedBin' # bad..
|
168
175
|
title + pretty_list(list) + "\n"
|
169
176
|
end
|
170
177
|
|
171
178
|
# Wrapper the double-linked list with color codes.
|
172
|
-
# @param [Array<Integer>] list The list from
|
179
|
+
# @param [Array<Integer>] list The list from +#link_list+.
|
173
180
|
# @return [String] Wrapper with color codes.
|
174
181
|
def pretty_list(list)
|
175
182
|
center = nil
|
176
183
|
list.map.with_index do |c, idx|
|
177
|
-
next center = Helper.color(
|
184
|
+
next center = Helper.color('[self]', sev: :bin) if c == @base
|
185
|
+
color_c = Helper.color(format('%#x', c))
|
178
186
|
fwd = fd_of(c)
|
179
|
-
next "
|
187
|
+
next "#{color_c}(invalid)" if fwd.nil? # invalid c
|
180
188
|
bck = bk_of(c)
|
181
189
|
if center.nil? # bk side
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
])
|
186
|
-
else #fd side
|
187
|
-
next Helper.color("%s%s" % [
|
188
|
-
bck == list[idx-1] ? nil : "(%#x)" % bck,
|
189
|
-
Helper.color("%#x" % c),
|
190
|
-
])
|
190
|
+
Helper.color(format('%s%s', color_c, fwd == list[idx + 1] ? nil : format('(%#x)', fwd)))
|
191
|
+
else # fd side
|
192
|
+
Helper.color(format('%s%s', bck == list[idx - 1] ? nil : format('(%#x)', bck), color_c))
|
191
193
|
end
|
192
|
-
end.join(
|
194
|
+
end.join(' === ')
|
193
195
|
end
|
194
196
|
|
195
197
|
# Return the double link list with bin in the center.
|
196
198
|
#
|
197
|
-
# The list will like
|
198
|
-
# @param [Integer] expand_size
|
199
|
+
# The list will like +[..., bk of bk, bk of bin, bin, fd of bin, fd of fd, ...]+.
|
200
|
+
# @param [Integer] expand_size
|
201
|
+
# At most expand size. For +size = 2+, the expand list would be +bk, bk, bin, fd, fd+.
|
199
202
|
# @return [Array<Integer>] The linked list.
|
200
203
|
def link_list(expand_size)
|
201
204
|
list = [@base]
|
202
205
|
# fd
|
203
|
-
work =
|
206
|
+
work = proc do |ptr, nxt, append|
|
204
207
|
sz = 0
|
205
208
|
dup = {}
|
206
|
-
while ptr != @base
|
209
|
+
while ptr != @base && sz < expand_size
|
207
210
|
append.call ptr
|
208
211
|
break if ptr.nil? # invalid pointer
|
209
212
|
break if dup[ptr] # looped
|
210
213
|
dup[ptr] = true
|
211
|
-
ptr =
|
214
|
+
ptr = send(nxt, ptr)
|
212
215
|
sz += 1
|
213
216
|
end
|
214
217
|
end
|
@@ -220,7 +223,6 @@ module HeapInfo
|
|
220
223
|
|
221
224
|
# Class for record smallbin type chunk.
|
222
225
|
class Smallbin < UnsortedBin
|
223
|
-
|
224
226
|
# Mapping index of smallbin to chunk size.
|
225
227
|
# @return [Integer] size
|
226
228
|
def idx_to_size
|
data/lib/heapinfo/cache.rb
CHANGED
@@ -1,9 +1,8 @@
|
|
1
1
|
require 'digest'
|
2
2
|
module HeapInfo
|
3
|
-
|
4
3
|
# Self implment file-base cache manager.
|
5
4
|
#
|
6
|
-
# Values are recorded in files based on <tt>Marshal</tt
|
5
|
+
# Values are recorded in files based on <tt>Marshal</tt>.
|
7
6
|
module Cache
|
8
7
|
# Directory for caching files.
|
9
8
|
# e.g. HeapInfo will record main_arena_offset for glibc(s)
|
@@ -24,8 +23,8 @@ module HeapInfo
|
|
24
23
|
# @return [Boolean] true
|
25
24
|
def self.write(key, value)
|
26
25
|
filepath = realpath key
|
27
|
-
FileUtils.mkdir_p(File.dirname
|
28
|
-
IO.binwrite(filepath, Marshal
|
26
|
+
FileUtils.mkdir_p(File.dirname(filepath))
|
27
|
+
IO.binwrite(filepath, Marshal.dump(value))
|
29
28
|
true
|
30
29
|
end
|
31
30
|
|
@@ -35,8 +34,8 @@ module HeapInfo
|
|
35
34
|
# @return [Object, NilClass] value that recorded, return <tt>nil</tt> when cache miss.
|
36
35
|
def self.read(key)
|
37
36
|
filepath = realpath key
|
38
|
-
return unless File.file?
|
39
|
-
Marshal
|
37
|
+
return unless File.file?(filepath)
|
38
|
+
Marshal.load(IO.binread(filepath))
|
40
39
|
rescue
|
41
40
|
nil # handle if file content invalid
|
42
41
|
end
|
@@ -44,24 +43,24 @@ module HeapInfo
|
|
44
43
|
# @param [String] key
|
45
44
|
# @return [String] Prepend with <tt>CACHE_DIR</tt>
|
46
45
|
def self.realpath(key)
|
47
|
-
raise ArgumentError
|
46
|
+
raise ArgumentError, 'Invalid key(file path)' if key =~ %r{[^\w/]}
|
48
47
|
File.join(CACHE_DIR, key)
|
49
48
|
end
|
50
49
|
|
51
|
-
# @return [
|
52
|
-
def self.
|
50
|
+
# @return [void]
|
51
|
+
def self.init
|
53
52
|
FileUtils.mkdir_p(CACHE_DIR)
|
54
53
|
rescue
|
55
54
|
# To prevent ~/ is not writable.
|
56
|
-
|
57
|
-
|
55
|
+
send(:remove_const, :CACHE_DIR)
|
56
|
+
const_set(:CACHE_DIR, File.join(HeapInfo::TMP_DIR, '.cache/heapinfo'))
|
58
57
|
end
|
59
58
|
|
60
59
|
# Clear the cache directory.
|
61
|
-
# @return [
|
60
|
+
# @return [void]
|
62
61
|
def self.clear_all
|
63
62
|
FileUtils.rm_rf CACHE_DIR
|
64
63
|
end
|
65
|
-
|
64
|
+
init
|
66
65
|
end
|
67
66
|
end
|
data/lib/heapinfo/chunk.rb
CHANGED
@@ -10,24 +10,24 @@ module HeapInfo
|
|
10
10
|
# @return [Integer] Base address of this chunk
|
11
11
|
attr_reader :base
|
12
12
|
|
13
|
-
# Instantiate a
|
13
|
+
# Instantiate a {HeapInfo::Chunk} object
|
14
14
|
#
|
15
15
|
# @param [Integer] size_t 4 or 8
|
16
16
|
# @param [Integer] base Start address of this chunk
|
17
17
|
# @param [Proc] dumper For dump more information of this chunk
|
18
|
-
# @param [Boolean] head
|
18
|
+
# @param [Boolean] head
|
19
|
+
# For specific if is fake chunk in +arena+.
|
20
|
+
# If +head+ is +true+, will not load +size+ and +prev_size+ (since it's meaningless)
|
19
21
|
# @example
|
20
|
-
# HeapInfo::Chunk.new 8, 0x602000, ->(addr, len) { [0,0x21, 0xda4a].pack(
|
22
|
+
# HeapInfo::Chunk.new 8, 0x602000, ->(addr, len) { [0,0x21, 0xda4a].pack('Q*')[addr-0x602000, len] }
|
21
23
|
# # create a chunk with chunk size 0x21
|
22
24
|
def initialize(size_t, base, dumper, head: false)
|
23
|
-
raise ArgumentError
|
24
|
-
self.class.send(:define_method, :dump){|*args| dumper.call(*args)}
|
25
|
+
raise ArgumentError, 'size_t can be either 4 or 8' unless [4, 8].include?(size_t)
|
26
|
+
self.class.send(:define_method, :dump) { |*args| dumper.call(*args) }
|
25
27
|
@size_t = size_t
|
26
28
|
@base = base
|
27
29
|
sz = dump(@base, size_t * 2)
|
28
|
-
if head # no need to read size if is bin
|
29
|
-
return @data = dump(@base + size_t * 2, size_t * 4)
|
30
|
-
end
|
30
|
+
return @data = dump(@base + size_t * 2, size_t * 4) if head # no need to read size if is bin
|
31
31
|
@prev_size = Helper.unpack(size_t, sz[0, size_t])
|
32
32
|
@size = Helper.unpack(size_t, sz[size_t..-1])
|
33
33
|
r_size = [size - size_t * 2, size_t * 4].min # don't read too much data
|
@@ -35,14 +35,14 @@ module HeapInfo
|
|
35
35
|
@data = dump(@base + size_t * 2, r_size)
|
36
36
|
end
|
37
37
|
|
38
|
-
# Hook
|
38
|
+
# Hook +#to_s+ for pretty printing
|
39
39
|
# @return [String]
|
40
40
|
def to_s
|
41
|
-
ret = Helper.color("#<%s:%#x>\n"
|
42
|
-
"flags = [#{flags.map{|f|Helper.color(":#{f}", sev: :sym)}.join(',')}]\n"
|
43
|
-
"size = #{Helper.color
|
44
|
-
ret += "prev_size = #{Helper.color
|
45
|
-
ret += "data = #{Helper.color
|
41
|
+
ret = Helper.color(format("#<%s:%#x>\n", self.class.to_s, @base), sev: :klass)
|
42
|
+
ret += "flags = [#{flags.map { |f| Helper.color(":#{f}", sev: :sym) }.join(',')}]\n"
|
43
|
+
ret += "size = #{Helper.color(format('%#x', size))} (#{bintype})\n"
|
44
|
+
ret += "prev_size = #{Helper.color(format('%#x', @prev_size))}\n" unless flags.include? :prev_inuse
|
45
|
+
ret += "data = #{Helper.color(@data.inspect)}#{'...' if @data.length < size - size_t * 2}\n"
|
46
46
|
ret
|
47
47
|
end
|
48
48
|
|
@@ -55,29 +55,29 @@ module HeapInfo
|
|
55
55
|
def flags
|
56
56
|
mask = @size - size
|
57
57
|
flag = []
|
58
|
-
flag << :non_main_arena unless mask & 4
|
59
|
-
flag << :mmapped unless mask & 2
|
60
|
-
flag << :prev_inuse unless mask & 1
|
58
|
+
flag << :non_main_arena unless (mask & 4).zero?
|
59
|
+
flag << :mmapped unless (mask & 2).zero?
|
60
|
+
flag << :prev_inuse unless (mask & 1).zero?
|
61
61
|
flag
|
62
62
|
end
|
63
63
|
|
64
64
|
# Ask if chunk not belongs to main arena.
|
65
65
|
#
|
66
|
-
# @return [Boolean]
|
66
|
+
# @return [Boolean] +true|false+ if chunk not belongs to main arena
|
67
67
|
def non_main_arena?
|
68
68
|
flags.include? :non_main_arena
|
69
69
|
end
|
70
70
|
|
71
71
|
# Ask if chunk is mmapped.
|
72
72
|
#
|
73
|
-
# @return [Boolean]
|
73
|
+
# @return [Boolean] +true|false+ if chunk is mmapped
|
74
74
|
def mmapped?
|
75
75
|
flags.include? :mmapped
|
76
76
|
end
|
77
77
|
|
78
78
|
# Ask if chunk has set the prev-inuse bit.
|
79
79
|
#
|
80
|
-
# @return [Boolean]
|
80
|
+
# @return [Boolean] +true|false+ if the +prev_inuse+ bit has been set
|
81
81
|
def prev_inuse?
|
82
82
|
flags.include? :prev_inuse
|
83
83
|
end
|
@@ -89,7 +89,7 @@ module HeapInfo
|
|
89
89
|
end
|
90
90
|
|
91
91
|
# Bin type of this chunk
|
92
|
-
# @return [Symbol] Bin type is simply determined according to
|
92
|
+
# @return [Symbol] Bin type is simply determined according to +#size+
|
93
93
|
# @example
|
94
94
|
# [c.size, c.size_t]
|
95
95
|
# # => [80, 8]
|
@@ -110,8 +110,8 @@ module HeapInfo
|
|
110
110
|
return :unknown if sz < @size_t * 4
|
111
111
|
return :fast if sz <= @size_t * 16
|
112
112
|
return :small if sz <= @size_t * 0x7e
|
113
|
-
return :large if sz <= @size_t * 0x3ffe # is this correct?
|
114
|
-
|
113
|
+
return :large if sz <= @size_t * 0x3ffe # is this correct?
|
114
|
+
:mmap
|
115
115
|
end
|
116
116
|
end
|
117
117
|
end
|
data/lib/heapinfo/chunks.rb
CHANGED
@@ -1,17 +1,28 @@
|
|
1
1
|
module HeapInfo
|
2
2
|
# Self-defined array for collecting chunk(s)
|
3
3
|
class Chunks
|
4
|
-
|
4
|
+
include Enumerable
|
5
|
+
# Instantiate a <tt>HeapInfo::Chunks</tt> object.
|
5
6
|
def initialize
|
6
7
|
@chunks = []
|
7
8
|
end
|
8
9
|
|
9
|
-
|
10
|
-
|
11
|
-
@chunks
|
10
|
+
# @return [void]
|
11
|
+
def <<(val)
|
12
|
+
@chunks << val
|
12
13
|
end
|
13
14
|
|
14
|
-
#
|
15
|
+
# @return [Integer]
|
16
|
+
def size
|
17
|
+
@chunks.size
|
18
|
+
end
|
19
|
+
|
20
|
+
# @return [void]
|
21
|
+
def each(&block)
|
22
|
+
@chunks.each(&block)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Hook +#to_s+ for pretty printing.
|
15
26
|
# @return [String]
|
16
27
|
def to_s
|
17
28
|
@chunks.map(&:to_s).join("\n")
|