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 916 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 864 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 857 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 897 def decode_longnames(m) @longnames = m.encoded end
decode_second_linker(m)
click to toggle source
# File metasm/exe_format/coff_decode.rb, line 878 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 859 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 858 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 903 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 453 def member(name) @members.find { |m| m.name == name } end
sizeof_half()
click to toggle source
# File metasm/exe_format/coff.rb, line 457 def sizeof_half ; 2 ; end
sizeof_word()
click to toggle source
# File metasm/exe_format/coff.rb, line 458 def sizeof_word ; 4 ; end