class Metasm::COFFArchive

the COFF archive file format maybe used in .lib files (they hold binary import information for libraries) used for unix .a static library files (with no 2nd linker and newline-separated longnames)

Attributes

first_linker[RW]
longnames[RW]
members[RW]
second_linker[RW]
signature[RW]

Public Instance Methods

decode() click to toggle source
# File metasm/exe_format/coff_decode.rb, line 918
def decode
        @encoded.ptr = 0
        @signature = @encoded.read(8)
        raise InvalidExeFormat, "Invalid COFF Archive signature #{@signature.inspect}" if @signature != "!<arch>\n"
        @members = []
        while @encoded.ptr < @encoded.virtsize
                @members << Member.decode(self)
        end
        @members.each { |m|
                case m.name
                when '/'; @first_linker ? decode_second_linker(m) : decode_first_linker(m)
                when '//'; decode_longnames(m)
                else break
                end
        }
        fixup_names
end
decode_first_linker(m) click to toggle source
# File metasm/exe_format/coff_decode.rb, line 866
def decode_first_linker(m)
        offsets = []
        names = []
        m.encoded.ptr = 0
        numsym = m.decode_word
        numsym.times { offsets << m.decode_word }
        numsym.times { names << decode_strz(m.encoded) }

        # names[42] is found in object at file offset offsets[42]
        # offsets are sorted by object index (all syms from 1st object, then 2nd etc)

        @first_linker = names.zip(offsets) #.inject({}) { |h, (n, o)| h.update n => o }
end
decode_half(edata = @encoded) click to toggle source
# File metasm/exe_format/coff_decode.rb, line 859
def decode_half(edata = @encoded) ; edata.decode_imm(:u16, :little) end
decode_longnames(m) click to toggle source
# File metasm/exe_format/coff_decode.rb, line 899
def decode_longnames(m)
        @longnames = m.encoded
end
decode_second_linker(m) click to toggle source
# File metasm/exe_format/coff_decode.rb, line 880
def decode_second_linker(m)
        names = []
        mboffsets = []
        indices = []
        m = @members[1]
        m.encoded.ptr = 0
        nummb = decode_word(m.encoded)
        nummb.times { mboffsets << decode_word(m.encoded) }
        numsym = decode_word(m.encoded)
        numsym.times { indices << decode_half(m.encoded) }
        numsym.times { names << decode_strz(m.encoded) }

        # names[42] is found in object at file offset mboffsets[indices[42]]
        # symbols sorted by symbol name (supposed to be more efficient, but no index into string table...)

        #names.zip(indices).inject({}) { |h, (n, i)| h.update n => mboffsets[i] }
        @second_linker = [names, mboffsets, indices]
end
decode_strz(edata = @encoded) click to toggle source
# File metasm/exe_format/coff_decode.rb, line 861
def decode_strz(edata = @encoded)
        i = edata.data.index(\0, edata.ptr) || edata.data.index(\n, edata.ptr) || (edata.length+1)
        edata.read(i+1-edata.ptr).chop
end
decode_word(edata = @encoded) click to toggle source
# File metasm/exe_format/coff_decode.rb, line 860
def decode_word(edata = @encoded) ; edata.decode_imm(:u32, :little) end
fixup_names() click to toggle source

set real name to archive members look it up in the name table member if needed, or just remove the trailing /

# File metasm/exe_format/coff_decode.rb, line 905
def fixup_names
        @members.each { |m|
                case m.name
                when '/'
                when '//'
                when /^\/(\d+)/
                        @longnames.ptr = $1.to_i
                        m.name = decode_strz(@longnames).chomp("/")
                else m.name.chomp! "/"
                end
        }
end
member(name) click to toggle source

return the 1st member whose name is name

# File metasm/exe_format/coff.rb, line 455
def member(name)
        @members.find { |m| m.name == name }
end
sizeof_half() click to toggle source
# File metasm/exe_format/coff.rb, line 459
def sizeof_half ; 2 ; end
sizeof_word() click to toggle source
# File metasm/exe_format/coff.rb, line 460
def sizeof_word ; 4 ; end