heapinfo 0.0.5 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
[![Build Status](https://travis-ci.org/david942j/heapinfo.svg?branch=master)](https://travis-ci.org/david942j/heapinfo)
|
2
|
+
![](http://ruby-gem-downloads-badge.herokuapp.com/heapinfo?type=total)
|
2
3
|
[![Code Climate](https://codeclimate.com/github/david942j/heapinfo/badges/gpa.svg)](https://codeclimate.com/github/david942j/heapinfo)
|
3
4
|
[![Issue Count](https://codeclimate.com/github/david942j/heapinfo/badges/issue_count.svg)](https://codeclimate.com/github/david942j/heapinfo)
|
4
5
|
[![Test Coverage](https://codeclimate.com/github/david942j/heapinfo/badges/coverage.svg)](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")
|