class OdinFlex::MachO

Constants

HEADER_MAGIC

Attributes

start_pos[R]

Public Class Methods

is_macho?(io) click to toggle source
# File lib/odinflex/mach-o.rb, line 5
def self.is_macho? io
  pos = io.pos
  header = io.read(8).unpack1 'L'
  header == HEADER_MAGIC
ensure
  io.seek pos, IO::SEEK_SET
end
new(fd) click to toggle source
# File lib/odinflex/mach-o.rb, line 15
def initialize fd
  @fd        = fd
  @start_pos = @fd.pos
end

Public Instance Methods

dsym?() click to toggle source
# File lib/odinflex/mach-o.rb, line 474
def dsym?
  header.dsym_file?
end
each() { |h| ... } click to toggle source
# File lib/odinflex/mach-o.rb, line 478
def each
  h = header

  yield h

  @fd.seek @start_pos + Header::SIZEOF, IO::SEEK_SET

  next_pos = @fd.pos

  h.ncmds.times do |i|
    @fd.seek next_pos, IO::SEEK_SET

    cmd, size = @fd.read(2 * 4).unpack('LL')

    case cmd
    when LC_SEGMENT_64::VALUE
      lc = LC_SEGMENT_64.from_offset(next_pos, @fd)
      yield lc
      lc.nsects.times do
        args = @fd.read(32 + (2 * 8) + (8 * 4)).unpack('A16A16QQL8')
        yield Section.new(@fd, start_pos, *args)
      end
    when LC_FUNCTION_STARTS::VALUE
      yield LC_FUNCTION_STARTS.from_offset(next_pos, @fd)
    when LC_DATA_IN_CODE::VALUE
      yield LC_DATA_IN_CODE.from_offset(next_pos, @fd)
    when LC_BUILD_VERSION::VALUE
      yield LC_BUILD_VERSION.from_offset(next_pos, @fd)
    when LC_LOAD_DYLIB::VALUE
      yield LC_LOAD_DYLIB.from_offset(next_pos, @fd)
    when LC_LOAD_DYLINKER::VALUE
      yield LC_LOAD_DYLINKER.from_offset(next_pos, @fd)
    when LC_SOURCE_VERSION::VALUE
      yield LC_SOURCE_VERSION.from_offset(next_pos, @fd)
    when LC_SYMTAB::VALUE
      yield LC_SYMTAB.from_offset(next_pos, @fd)
    when LC_DYSYMTAB::VALUE
      yield LC_DYSYMTAB.from_offset(next_pos, @fd)
    when LC_UUID::VALUE
      yield LC_UUID.from_offset(next_pos, @fd)
    else
      # Just skip stuff we don't know about
      if $DEBUG
        puts "Unknown command #{cmd}"
      end
    end

    next_pos += size
  end
end
executable?() click to toggle source
# File lib/odinflex/mach-o.rb, line 466
def executable?
  header.executable_file?
end
find_section(name) click to toggle source
# File lib/odinflex/mach-o.rb, line 529
def find_section name
  find { |thing| thing.section? && thing.sectname == name }
end
header() click to toggle source
# File lib/odinflex/mach-o.rb, line 543
def header
  @fd.seek @start_pos, IO::SEEK_SET
  header = Header.new(*@fd.read(Header::SIZEOF).unpack('L8'))
  # I don't want to deal with endianness
  raise 'not supported' unless header.magic == HEADER_MAGIC
  header
end
object?() click to toggle source
# File lib/odinflex/mach-o.rb, line 470
def object?
  header.object_file?
end
read(section) click to toggle source
# File lib/odinflex/mach-o.rb, line 533
def read section
  save_pos do
    @fd.seek @start_pos + section.offset, IO::SEEK_SET
    data = @fd.read(section.size)
    data.bytes.each_slice(16) do |list|
      p list.map { |x| sprintf("%02x", x) }.join ' '
    end
  end
end

Private Instance Methods

save_pos() { || ... } click to toggle source
# File lib/odinflex/mach-o.rb, line 553
def save_pos
  pos = @fd.pos
  yield
ensure
  @fd.seek pos, IO::SEEK_SET
end