Class: OdinFlex::MachO

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/odinflex/mach-o.rb

Defined Under Namespace

Modules: SectionTypes Classes: Command, Header, LC_BUILD_VERSION, LC_DATA_IN_CODE, LC_DYSYMTAB, LC_FUNCTION_STARTS, LC_LOAD_DYLIB, LC_LOAD_DYLINKER, LC_SEGMENT_64, LC_SOURCE_VERSION, LC_SYMTAB, LC_UNIXTHREAD, LC_UUID, LC_VERSION_MIN_MACOSX, Section

Constant Summary collapse

HEADER_MAGIC =
0xfeedfacf

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(fd) ⇒ MachO

Returns a new instance of MachO.



15
16
17
18
# File 'lib/odinflex/mach-o.rb', line 15

def initialize fd
  @fd        = fd
  @start_pos = @fd.pos
end

Instance Attribute Details

#start_posObject (readonly)

Returns the value of attribute start_pos.



13
14
15
# File 'lib/odinflex/mach-o.rb', line 13

def start_pos
  @start_pos
end

Class Method Details

.is_macho?(io) ⇒ Boolean

Returns:

  • (Boolean)


5
6
7
8
9
10
11
# 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

Instance Method Details

#dsym?Boolean

Returns:

  • (Boolean)


474
475
476
# File 'lib/odinflex/mach-o.rb', line 474

def dsym?
  header.dsym_file?
end

#each {|h| ... } ⇒ Object

Yields:

  • (h)


478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
# 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?Boolean

Returns:

  • (Boolean)


466
467
468
# File 'lib/odinflex/mach-o.rb', line 466

def executable?
  header.executable_file?
end

#find_section(name) ⇒ Object



529
530
531
# File 'lib/odinflex/mach-o.rb', line 529

def find_section name
  find { |thing| thing.section? && thing.sectname == name }
end

#headerObject



543
544
545
546
547
548
549
# 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?Boolean

Returns:

  • (Boolean)


470
471
472
# File 'lib/odinflex/mach-o.rb', line 470

def object?
  header.object_file?
end

#read(section) ⇒ Object



533
534
535
536
537
538
539
540
541
# 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