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:



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

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.instance : 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.



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

def auxv
  @auxv
end

#bitsInteger (readonly)

Returns 32 or 64.

Returns:

  • (Integer)

    32 or 64.



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

def bits
  @bits
end

#ldHeapInfo::Segment (readonly)

Returns:



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

def ld
  @ld
end

#libcHeapInfo::Libc (readonly)

Returns:



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

def libc
  @libc
end

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

Returns:



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

def program
  @program
end

#stackHeapInfo::Segment (readonly)

Returns:



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

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:



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

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

#segmentsHash{Symbol => Segment}

Return currently loaded segments.

Returns:

  • (Hash{Symbol => Segment})

    The segments in hash format.



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

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:



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

def to_segment(sym)
  return nil unless EXPORT.include?(sym)

  seg = __send__(sym)
  return nil unless seg.is_a?(Segment)

  seg
end