Class: ELFTools::Structs::ELFStruct

Inherits:
BinData::Record
  • Object
show all
Defined in:
lib/elftools/structs.rb

Overview

The base structure to define common methods.

Constant Summary collapse

CHOICE_SIZE_T =

DRY. Many fields have different type in different arch.

proc do |t = 'uint'|
  { selection: :elf_class, choices: { 32 => :"#{t}32", 64 => :"#{t}64" }, copy_on_change: true }
end

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#elf_classInteger

Returns 32 or 64.

Returns:

  • (Integer)

    32 or 64.



18
19
20
# File 'lib/elftools/structs.rb', line 18

def elf_class
  @elf_class
end

#offsetInteger

Returns The file offset of this header.

Returns:

  • (Integer)

    The file offset of this header.



19
20
21
# File 'lib/elftools/structs.rb', line 19

def offset
  @offset
end

Class Method Details

.new(*args) ⇒ Object

Hooks the constructor.

BinData::Record doesn’t allow us to override #initialize, so we hack new here.



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/elftools/structs.rb', line 34

def new(*args)
  # XXX: The better implementation is +new(*args, **kwargs)+, but we can't do this unless bindata changed
  # lib/bindata/dsl.rb#override_new_in_class to invoke +new+ with both +args+ and +kwargs+.
  kwargs = args.last.is_a?(Hash) ? args.last : {}
  offset = kwargs.delete(:offset)
  super.tap do |obj|
    obj.offset = offset
    obj.field_names.each do |f|
      m = "#{f}=".to_sym
      old_method = obj.singleton_method(m)
      obj.singleton_class.send(:undef_method, m)
      obj.define_singleton_method(m) do |val|
        org = obj.send(f)
        obj.patches[org.abs_offset] = ELFStruct.pack(val, org.num_bytes)
        old_method.call(val)
      end
    end
  end
end

.pack(val, bytes) ⇒ String

Packs an integer to string.

Parameters:

  • val (Integer)
  • bytes (Integer)

Returns:

  • (String)

Raises:

  • (ArgumentError)


64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/elftools/structs.rb', line 64

def pack(val, bytes)
  raise ArgumentError, "Not supported assign type #{val.class}" unless val.is_a?(Integer)

  number = val & ((1 << (8 * bytes)) - 1)
  out = []
  bytes.times do
    out << (number & 0xff)
    number >>= 8
  end
  out = out.pack('C*')
  self_endian == :little ? out : out.reverse
end

.self_endian:little, :big

Gets the endianness of current class.

Returns:

  • (:little, :big)

    The endianness.



56
57
58
# File 'lib/elftools/structs.rb', line 56

def self_endian
  bindata_name[-2..] == 'be' ? :big : :little
end

Instance Method Details

#patchesHash{Integer => Integer}

Records which fields have been patched.

Returns:

  • (Hash{Integer => Integer})

    Patches.



23
24
25
# File 'lib/elftools/structs.rb', line 23

def patches
  @patches ||= {}
end