Class: HeapInfo::ProcessInfo

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

Overview

For Process to record basic process information.

Process has a process_info object iff the process exists (pid not nil). Mainly records segments’ base.

Constant Summary collapse

EXPORT =

Methods to be transparent to process. e.g. process.libc alias to process.info.libc.

i[libc ld heap program elf stack bits auxv].freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(process) ⇒ ProcessInfo

Instantiate a HeapInfo::ProcessInfo object.

Parameters:



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/heapinfo/process_info.rb', line 39

def initialize(process)
  @pid = process.pid
  options = process.instance_variable_get(:@options)
  maps = load_maps
  @bits = bits_of(Helper.exe_of(@pid))
  @program = Segment.find(maps, File.readlink("/proc/#{@pid}/exe"))
  # well.. stack is a strange case because it will grow in runtime..
  # should i detect stack base growing..?
  @stack = Segment.find(maps, '[stack]')
  @auxv = parse_auxv(Helper.auxv_of(@pid))
  ld_seg = maps.find { |m| m[0] == @auxv[:ld_base] } # nil if static-linked elf
  @ld = ld_seg.nil? ? Nil.new : Segment.new(@auxv[:ld_base], ld_seg.last)
  @libc = Libc.find(
    maps, match_maps(maps, options[:libc]),
    bits: @bits,
    ld_name: @ld.name,
    dumper: ->(*args) { process.dump(*args) },
    method_heap: method(:heap)
  )
end

Instance Attribute Details

#auxvHash{Symbol => Integer} (readonly)

Returns The parsed auxv hash.

Examples:

auxv
#=> {:ld_base => 4152033280, :random => 4294374299}

Returns:

  • (Hash{Symbol => Integer})

    The parsed auxv hash.



33
34
35
# File 'lib/heapinfo/process_info.rb', line 33

def auxv
  @auxv
end

#bitsInteger (readonly)

Returns 32 or 64.

Returns:

  • (Integer)

    32 or 64.



20
21
22
# File 'lib/heapinfo/process_info.rb', line 20

def bits
  @bits
end

#ldHeapInfo::Segment (readonly)

Returns:



28
29
30
# File 'lib/heapinfo/process_info.rb', line 28

def ld
  @ld
end

#libcHeapInfo::Libc (readonly)

Returns:



26
27
28
# File 'lib/heapinfo/process_info.rb', line 26

def libc
  @libc
end

#programHeapInfo::Segment (readonly) Also known as: elf

Returns:



22
23
24
# File 'lib/heapinfo/process_info.rb', line 22

def program
  @program
end

#stackHeapInfo::Segment (readonly)

Returns:



24
25
26
# File 'lib/heapinfo/process_info.rb', line 24

def stack
  @stack
end

Instance Method Details

#heapHeapInfo::Segment

Heap will not be mmapped if the process not use heap yet, so create a lazy loading method. Will re-read maps when heap segment not found yet.

Special handling here because heap might not be initialized in the beginning.

Returns:



66
67
68
# File 'lib/heapinfo/process_info.rb', line 66

def heap
  @heap ||= Segment.find(load_maps, '[heap]')
end

#segmentsHash{Symbol => Segment}

Return segemnts load currently.

Returns:

  • (Hash{Symbol => Segment})

    The segments in hash format.



72
73
74
75
76
77
# File 'lib/heapinfo/process_info.rb', line 72

def segments
  EXPORT.map do |sym|
    seg = __send__(sym)
    [sym, seg] if seg.is_a?(Segment)
  end.compact.to_h
end

#to_segment(sym) ⇒ HeapInfo::Segment?

Convert symbol to segment.

Returns:



83
84
85
86
87
88
# File 'lib/heapinfo/process_info.rb', line 83

def to_segment(sym)
  return nil unless EXPORT.include?(sym)
  seg = __send__(sym)
  return nil unless seg.is_a?(Segment)
  seg
end