Class: HeapInfo::Dumper Private

Inherits:
Object
  • Object
show all
Defined in:
lib/heapinfo/dumper.rb

Overview

This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.

Class for memory dump relation works

Constant Summary collapse

DUMP_BYTES =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Default dump length

8

Instance Method Summary collapse

Constructor Details

#initialize(mem_filename, &block) ⇒ Dumper

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Instantiate a HeapInfo::Dumper object

Parameters:

  • mem_filename (String)

    The filename that can be access for dump. Should be /proc/[pid]/mem.

  • block (Proc)

    Use for get segment info. See #base_len_of for more information.



21
22
23
24
25
# File 'lib/heapinfo/dumper.rb', line 21

def initialize(mem_filename, &block)
  @filename = mem_filename
  @info = block || ->(*) { HeapInfo::Nil.instance }
  need_permission unless dumpable?
end

Instance Method Details

#base_of(arg) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Get the base address given the address calculation annotation.

Examples:

base_of(123) #=> 123
base_of(:heap) #=> 0x603000 # assume heap base @ 0x603000
base_of('heap+0x30') #=> 0x603030
base_of('elf+0x3*2-1') #=> 0x400005

Parameters:

  • arg (Integer, Symbol, String)

    The base address, see examples.



149
150
151
# File 'lib/heapinfo/dumper.rb', line 149

def base_of(arg)
  base_len_of(arg)[0]
end

#cstring(address) ⇒ String

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Dump data from address until reach null-byte.

Returns:

  • (String)


83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/heapinfo/dumper.rb', line 83

def cstring(address)
  base = base_of(address)
  len = 1
  cur = +''
  loop do
    cur << (dump(base + len - 1, len) || '')
    break if cur.index("\x00")

    len <<= 1
    return cur if cur.size != len - 1 # reached undumpable memory
  end
  cur[0, cur.index("\x00")]
end

#dump(*args) ⇒ String?

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

A helper for Process to dump memory.

Examples:

p dump(:elf, 4)
#=> "\x7fELF"

Parameters:

  • args (Mixed)

    The use input commands, see examples of Process#dump.

Returns:

  • (String, nil)

    Dump results. If error happend, nil is returned.



33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/heapinfo/dumper.rb', line 33

def dump(*args)
  return need_permission unless dumpable?

  base, len = base_len_of(*args)
  file = mem_f
  file.pos = base
  mem = file.readpartial(len)
  file.close
  mem
rescue => e # rubocop:disable Style/RescueStandardError
  raise e if e.is_a? ArgumentError

  nil
end

#dump_chunks(*args) ⇒ HeapInfo::Chunks

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Return the dump result as chunks. see Chunks and Chunk for more information.

Note: Same as #dump, need permission of attaching another process.

Parameters:

  • args (Mixed)

    Same as arguments of #dump.

Returns:



54
55
56
57
# File 'lib/heapinfo/dumper.rb', line 54

def dump_chunks(*args)
  base = base_of(args.first)
  dump(*args).to_chunks(bits: @info[:bits], base: base)
end

#find(pattern, from, length, rel) ⇒ Integer?

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Search a specific value/string/regexp in memory. #find only return the first matched address.

Examples:

find(/E.F/, :elf, false)
#=> 4194305
find(0x4141414141414141, 'heap+0x10', 0x1000, false)
#=> 6291472
find('/bin/sh', :libc, true)
#=> 1622391 # 0x18c177

Parameters:

  • pattern (Integer, String, Regexp)

    The desired search pattern, can be value(+Integer+), string, or regular expression.

  • from (Integer, String, Symbol)

    Start address for searching, can be segment(+Symbol+) or segments with offset. See examples for more information.

  • length (Integer)

    The length limit for searching.

  • rel (Boolean)

    Return relative or absolute.

Returns:

  • (Integer, nil)

    The first matched address, nil is returned when no such pattern found.



114
115
116
117
118
119
120
121
122
123
124
# File 'lib/heapinfo/dumper.rb', line 114

def find(pattern, from, length, rel)
  from = base_of(from)
  length = 1 << 40 if length.is_a? Symbol
  ret = case pattern
        when Integer then find_integer(pattern, from, length)
        when String then find_string(pattern, from, length)
        when Regexp then find_regexp(pattern, from, length)
        end
  ret -= from if ret && rel
  ret
end

#scan(pattern, from, length) ⇒ Array<Integer>

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns:

  • (Array<Integer>)


127
128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/heapinfo/dumper.rb', line 127

def scan(pattern, from, length)
  from = base_of(from)
  cur = from
  result = []
  loop do
    addr = find(pattern, cur, length, false)
    break if addr.nil?

    result << addr - from
    cur = addr + @match_length
  end
  result
end

#x(count, address) ⇒ void

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

This method returns an undefined value.

Show dump results like in gdb's command x.

Details are in Process#x.

Examples:

x 3, 0x400000
# 0x400000:       0x00010102464c457f      0x0000000000000000
# 0x400010:       0x00000001003e0002

Parameters:

  • count (Integer)

    The number of result need to dump.

  • address (Symbol, String, Integer)

    The base address to be dumped.



69
70
71
72
73
74
75
76
77
78
# File 'lib/heapinfo/dumper.rb', line 69

def x(count, address)
  base = base_of(address)
  commands = [address, count * size_t]
  res = dump(*commands).unpack(size_t == 4 ? 'L*' : 'Q*')
  str = res.group_by.with_index { |_, i| i / (16 / size_t) }.map do |round, values|
    Helper.hex(base + round * 16) + ":\t" +
      values.map { |v| Helper.color(format("0x%0#{size_t * 2}x", v)) }.join("\t")
  end.join("\n")
  puts str
end