Module: HeapInfo::Helper::ClassMethods

Included in:
HeapInfo::Helper
Defined in:
lib/heapinfo/helper.rb

Overview

Define class methods here.

Constant Summary collapse

COLOR_CODE =

Color codes for pretty print.

{
  esc_m: "\e[0m",
  normal_s: "\e[38;5;209m", # red
  integer: "\e[38;5;153m", # light blue
  fatal: "\e[38;5;197m", # dark red
  bin: "\e[38;5;120m", # light green
  klass: "\e[38;5;155m",
  sym: "\e[38;5;230m"
}.freeze

Instance Method Summary collapse

Instance Method Details

#class_name(obj) ⇒ String

Retrieve pure class name(without module) of an object.

Examples:

# suppose obj is an instance of HeapInfo::Chunk
Helper.class_name(obj)#=> 'Chunk'

127
128
129
# File 'lib/heapinfo/helper.rb', line 127

def class_name(obj)
  obj.class.name.split('::').last || obj.class.name
end

#color(s, sev: nil) ⇒ String

Wrapper color codes for pretty inspect.


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

def color(s, sev: nil)
  s = s.to_s
  return s if @disable_color
  cc = COLOR_CODE
  color = if cc.key?(sev) then cc[sev]
          elsif integer?(s) then cc[:integer] # integers
          else cc[:normal_s] # normal string
          end
  "#{color}#{s.sub(cc[:esc_m], color)}#{cc[:esc_m]}"
end

#evaluate(formula, store: {}) ⇒ Integer

Safe-eval using dentaku.


151
152
153
154
155
# File 'lib/heapinfo/helper.rb', line 151

def evaluate(formula, store: {})
  calc = Dentaku::Calculator.new
  formula = formula.delete(':')
  calc.store(store).evaluate(formula)
end

#hex(num) ⇒ String

Convert number in hex format.

Examples:

HeapInfo::Helper.hex(1000) #=> '0x3e8'

115
116
117
118
# File 'lib/heapinfo/helper.rb', line 115

def hex(num)
  return format('0x%x', num) if num >= 0
  format('-0x%x', -num)
end

#integer?(str) ⇒ Boolean

For checking a string is actually an integer.

Examples:

Helper.integer? '1234'#=> true

Helper.integer? '0x1234'#=> true

Helper.integer? '0xheapoverflow'#=> false

141
142
143
144
145
# File 'lib/heapinfo/helper.rb', line 141

def integer?(str)
  true if Integer(str)
rescue ArgumentError, TypeError
  false
end

#parse_maps(content) ⇒ Array

Parse the contents of /proc/[pid]/maps.

Examples:

HeapInfo::Helper.parse_maps(<<EOS
  00400000-0040b000 r-xp 00000000 ca:01 271708                             /bin/cat
  00bc4000-00be5000 rw-p 00000000 00:00 0                                  [heap]
  7f2788315000-7f2788316000 r--p 00022000 ca:01 402319                     /lib/x86_64-linux-gnu/ld-2.19.so
  EOS
)
# [[0x400000, 0x40b000, 'r-xp', '/bin/cat'],
# [0xbc4000, 0xbe5000, 'rw-p', '[heap]'],
# [0x7f2788315000, 0x7f2788316000, 'r--p', '/lib/x86_64-linux-gnu/ld-2.19.so']]

49
50
51
52
53
54
55
56
57
# File 'lib/heapinfo/helper.rb', line 49

def parse_maps(content)
  lines = content.split("\n")
  lines.map do |line|
    s = line.scan(%r{^([0-9a-f]+)-([0-9a-f]+)\s([rwxp-]{4})[^/|\[]*([/|\[].+)$})[0]
    next nil if s.nil?
    s[0], s[1] = s[0, 2].map { |h| h.to_i(16) }
    s
  end.compact
end

#pidof(prog) ⇒ Integer

Get the process id from program name.

When multiple processes exist, the one with lastest start time would be returned.


26
27
28
29
30
31
32
33
# File 'lib/heapinfo/helper.rb', line 26

def pidof(prog)
  info = %x(ps -o pid=,lstart= --pid `pidof #{Shellwords.escape(prog)}` 2>/dev/null).lines.map do |l|
    pid, time = l.split(' ', 2)
    [Time.parse(time), pid.to_i]
  end
  return nil if info.empty? # process not exists yet
  info.max_by(&:first).last
end

#tempfile(name) ⇒ String

Get temp filename.


160
161
162
# File 'lib/heapinfo/helper.rb', line 160

def tempfile(name)
  Dir::Tmpname.create(name, HeapInfo::TMP_DIR) {}
end

#toggle_color(on: false) ⇒ void

This method returns an undefined value.

enable / disable the color function.


62
63
64
# File 'lib/heapinfo/helper.rb', line 62

def toggle_color(on: false)
  @disable_color = !on
end

#unpack(size_t, data) ⇒ Integer

Unpack strings to integer.

Like the p32 and p64 in pwntools.

Examples:

HeapInfo::Helper.unpack(4, "\x12\x34\x56\x78")# 0x78563412

HeapInfo::Helper.unpack(8, "\x12\x34\x56\x78\xfe\xeb\x90\x90")# 0x9090ebfe78563412

105
106
107
# File 'lib/heapinfo/helper.rb', line 105

def unpack(size_t, data)
  data.unpack(size_t == 4 ? 'L*' : 'Q*')[0]
end