Module: ELFTools::Util::ClassMethods

Included in:
ELFTools::Util
Defined in:
lib/elftools/util.rb

Overview

Class methods.

Instance Method Summary collapse

Instance Method Details

#align(num, bit) ⇒ Integer

Round up the number to be multiple of 2**bit.

Examples:

align(10, 1) #=> 10
align(10, 2) #=> 12
align(10, 3) #=> 16
align(10, 4) #=> 16
align(10, 5) #=> 32

Parameters:

  • num (Integer)

    Number to be rounded-up.

  • bit (Integer)

    How many bit to be aligned.

Returns:

  • (Integer)

    See examples.



24
25
26
27
28
29
# File 'lib/elftools/util.rb', line 24

def align(num, bit)
  n = 2**bit
  return num if (num % n).zero?

  (num + n) & ~(n - 1)
end

#cstring(stream, offset) ⇒ String

Read from stream until reach a null-byte.

The stream is left just past the null-byte.

Examples:

Util.cstring(File.open('/bin/cat'), 0)
#=> "\x7FELF\x02\x01\x01"

Parameters:

  • stream (#pos=, #read)

    Streaming object.

  • offset (Integer)

    Start from here.

Returns:

  • (String)

    Result string will never contain null byte.



88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/elftools/util.rb', line 88

def cstring(stream, offset)
  stream.pos = offset
  ret = +''
  loop do
    chunk = stream.read(CSTRING_CHUNK)
    return nil if chunk.nil? # reach EOF

    stop = chunk.index("\x00")
    if stop
      stream.pos = offset + ret.bytesize + stop + 1
      return ret << chunk.byteslice(0, stop)
    end

    ret << chunk
  end
end

#fits!(value, bits, name) ⇒ Integer

Checks a value is one the bits recording it can hold.

Several of the values a file records share a byte with others, so a value too large for its bits would be written over its neighbours instead of being rejected.

Examples:

Util.fits!(16, 4, 'Symbol binding')
#=> ArgumentError: Symbol binding must be in 0..15, got 16

Parameters:

  • value (Integer)

    The value.

  • bits (Integer)

    How many bits record it.

  • name (String)

    What the value is, for the error to name.

Returns:

  • (Integer)

    The value.

Raises:

  • (ArgumentError)

    If the bits cannot hold it.



44
45
46
47
48
49
# File 'lib/elftools/util.rb', line 44

def fits!(value, bits, name)
  highest = (1 << bits) - 1
  return value if value.is_a?(Integer) && value.between?(0, highest)

  raise ArgumentError, format('%s must be in 0..%d, got %p', name, highest, value)
end

#select_by_type(enum, type) ⇒ Array<Object>

Select objects from enumerator with .type property equals to type.

Different from naive Array#select is this method will yield block whenever find a desired object.

This method is used to simplify the same logic in methods ELFFile#sections_by_type, ELFFile#segments_by_type, etc.

Parameters:

  • enum (Enumerator)

    An enumerator for further select.

  • type (Object)

    The type you want.

Returns:

  • (Array<Object>)

    The return value will be objects in enum with attribute .type equals to type.



118
119
120
121
122
123
124
125
# File 'lib/elftools/util.rb', line 118

def select_by_type(enum, type)
  enum.select do |obj|
    if obj.type == type
      yield obj if block_given?
      true
    end
  end
end

#to_constant(mod, val) ⇒ Integer

Fetch the correct value from module mod.

See ELFFile#segment_by_type for how to use this method.

Parameters:

  • mod (Module)

    The module defined constant numbers.

  • val (Integer, Symbol, String)

    Desired value.

Returns:

  • (Integer)

    Currently this method always return a value from Constants.

Raises:

  • (ArgumentError)


61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/elftools/util.rb', line 61

def to_constant(mod, val)
  # Ignore the outest name.
  module_name = mod.name.sub('ELFTools::', '')
  # if val is an integer, check if exists in mod
  if val.is_a?(Integer)
    return val if values_of(mod).key?(val)

    raise ArgumentError, "No constants in #{module_name} is #{val}"
  end
  val = val.to_s.upcase
  prefix = module_name.split('::')[-1]
  val = "#{prefix}_#{val}" unless val.start_with?(prefix)
  value = constants_of(mod)[val]
  raise ArgumentError, "No constants in #{module_name} named \"#{val}\"" if value.nil?

  value
end