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