class Metasm::Bflt

BFLT is the binary flat format used by the uClinux from examining a v4 binary, it looks like the header is discarded and the file is mapped from 0x40 to memory address 0 (wrt relocations)

Constants

FLAGS
MAGIC

Attributes

data[RW]
endianness[RW]
got[RW]
header[RW]
reloc[RW]
text[RW]

Public Class Methods

new(cpu = nil) click to toggle source
Calls superclass method Metasm::ExeFormat.new
# File metasm/exe_format/bflt.rb, line 63
def initialize(cpu = nil)
        @endianness = cpu ? cpu.endianness : :little
        @header = Header.new
        @text = EncodedData.new
        @data = EncodedData.new
        super(cpu)
end

Public Instance Methods

assemble(*a) click to toggle source
# File metasm/exe_format/bflt.rb, line 191
def assemble(*a)
        parse(*a) if not a.empty?
        @text << assemble_sequence(@textsrc, @cpu)
        @textsrc.clear
        @data << assemble_sequence(@datasrc, @cpu)
        @datasrc.clear
        self
end
create_relocation_table() click to toggle source
# File metasm/exe_format/bflt.rb, line 148
def create_relocation_table
        @reloc = []
        mapaddr = new_label('mapaddr')
        binding = @text.binding(mapaddr).merge(@data.binding(mapaddr))
        [@text, @data].each { |section|
                base = 0x40  # XXX maybe 0 ?
                base = @header.data_start || base+@text.length if section == @data
                section.reloc.each { |o, r|
                        if r.endianness == @endianness and [:u32, :a32, :i32].include? r.type and
                                        Expression[r.target.bind(binding), :-, mapaddr].reduce.kind_of? ::Integer
                                @reloc << (base+o)
                        else
                                puts "bFLT: ignoring unsupported reloc #{r.inspect} at #{Expression[o]}" if $VERBOSE
                        end
                }
        }
end
decode() click to toggle source
# File metasm/exe_format/bflt.rb, line 77
def decode
        decode_header

        @text = @encoded[0x40...@header.data_start]
        @data = @encoded[@header.data_start...@header.data_end]
        @data.virtsize += @header.bss_end - @header.data_end

        if @header.flags.include?('GZIP')
                # TODO gzip
                raise 'bFLT decoder: gzip format not supported'
        end

        @reloc = []
        @encoded.ptr = @header.reloc_start
        @header.reloc_count.times { @reloc << decode_word }
        if @header.rev == 2
                @reloc.map! { |r| r & 0x3fff_ffff }
        end

        decode_interpret_relocs
end
decode_header() click to toggle source
# File metasm/exe_format/bflt.rb, line 71
def decode_header
        @encoded.ptr = 0
        @header.decode(self)
        @encoded.add_export(new_label('entrypoint'), @header.entry)
end
decode_interpret_relocs() click to toggle source
# File metasm/exe_format/bflt.rb, line 99
def decode_interpret_relocs
        textsz = @header.data_start-0x40
        @reloc.each { |r|
                # where the reloc is
                if r < textsz
                        section = @text
                        off = section.ptr = r
                else
                        section = @data
                        off = section.ptr = r-textsz
                end

                # what it points to
                target = decode_word(section)
                if target < textsz
                        target = label_at(@text, target, "xref_#{Expression[target]}")
                elsif target < @header.bss_end-0x40
                        target = label_at(@data, target-textsz, "xref_#{Expression[target]}")
                else
                        puts "out of bounds reloc target #{Expression[target]} at #{Expression[r]}" if $VERBOSE
                        next
                end

                section.reloc[off] = Relocation.new(Expression[target], :u32, @endianness)
        }
end
decode_word(edata = @encoded) click to toggle source
# File metasm/exe_format/bflt.rb, line 58
def decode_word(edata = @encoded) edata.decode_imm(:u32, @endianness) end
each_section() { |text, 0| ... } click to toggle source
# File metasm/exe_format/bflt.rb, line 204
def each_section
        yield @text, 0
        yield @data, @header.data_start - @header.entry
end
encode() click to toggle source
# File metasm/exe_format/bflt.rb, line 126
def encode
        create_relocation_table

        # TODO got, gzip
        if @header.flags.include? 'GZIP'
                puts "W: bFLT: clearing gzip flag" if $VERBOSE
                @header.flags.delete 'GZIP'
        end

        @encoded = EncodedData.new
        @encoded << @header.encode(self)

        binding = @text.binding(0x40).merge(@data.binding(@header.data_start))
        @encoded << @text << @data.data
        @encoded.fixup! binding
        @encoded.reloc.clear

        @relocs.each { |r| @encoded << encode_word(r) }

        @encoded.data
end
encode_word(w) click to toggle source
# File metasm/exe_format/bflt.rb, line 59
def encode_word(w) Expression[w].encode(:u32, @endianness) end
get_default_entrypoints() click to toggle source
# File metasm/exe_format/bflt.rb, line 200
def get_default_entrypoints
        ['entrypoint']
end
module_symbols() click to toggle source
# File metasm/exe_format/bflt.rb, line 215
def module_symbols
        ['entrypoint', @header.entry-0x40]
end
parse_init() click to toggle source
Calls superclass method Metasm::ExeFormat#parse_init
# File metasm/exe_format/bflt.rb, line 166
def parse_init
        @textsrc ||= []
        @datasrc ||= []
        @cursource ||= @textsrc
        super()
end
parse_parser_instruction(instr) click to toggle source
# File metasm/exe_format/bflt.rb, line 173
def parse_parser_instruction(instr)
        case instr.raw.downcase
        when '.text'; @cursource = @textsrc
        when '.data'; @cursource = @datasrc
        when '.entrypoint'
                # ".entrypoint <somelabel/expression>" or ".entrypoint" (here)
                @lexer.skip_space
                if tok = @lexer.nexttok and tok.type == :string
                        raise instr if not entrypoint = Expression.parse(@lexer)
                else
                        entrypoint = new_label('entrypoint')
                        @cursource << Label.new(entrypoint, instr.backtrace.dup)
                end
                @header.entry = entrypoint
        else super(instr)
        end
end
section_info() click to toggle source
# File metasm/exe_format/bflt.rb, line 209
def section_info
        [['.text', 0, @text.length, 'rx'],
         ['.data', @header.data_addr-0x40, @data.data.length, 'rw'],
         ['.bss',  @header.data_end-0x40,  @data.length-@data.data.length, 'rw']]
end
sizeof_word() click to toggle source
# File metasm/exe_format/bflt.rb, line 60
def sizeof_word ; 4 ; end