node/lib/metasm/metasm/disassemble_api.rb
def load(str)
		raise 'Not a metasm save file' if str[0, 12].chomp != 'Metasm.dasm'
		off = 12
		pp = Preprocessor.new
		app = AsmPreprocessor.new
		while off < str.length
			i = str.index("\n", off) || str.length
			type, len = str[off..i].chomp.split
			off = i+1
			data = str[off, len.to_i]
			off += len.to_i
			case type
			when nil, ''
			when 'binarypath'
				data = yield(type, data) if not File.exist? data and block_given?
				reinitialize AutoExe.decode_file(data)
				@program.disassembler = self
				@program.init_disassembler
			when 'cpu'
				cpuname, size, endianness = data.split
				cpu = Metasm.const_get(cpuname)
				raise 'invalid cpu' if not cpu < CPU
				cpu = cpu.new
				cpu.size = size.to_i
				cpu.endianness = endianness.to_sym
				reinitialize Shellcode.new(cpu)
				@program.disassembler = self
				@program.init_disassembler
				@sections.delete(0)	# rm empty section at 0, other real 'section' follow
			when 'section'
				info = data[0, data.index("\n") || data.length]
				data = data[info.length, data.length]
				pp.feed!(info)
				addr = Expression.parse(pp).reduce
				len = Expression.parse(pp).reduce
				edata = EncodedData.new(data.unpack('m*').first, :virtsize => len)
				add_section(addr, edata)
			when 'map'
				load_map data
			when 'decoded'
				data.each_line { |l|
					begin
						next if l !~ /^([^,]*),(\d*) ([^;]*)(?:; (.*))?/
						a, len, instr, cmt = $1, $2, $3, $4
						a = Expression.parse(pp.feed!(a)).reduce
						instr = @cpu.parse_instruction(app.feed!(instr))
						di = DecodedInstruction.new(instr, a)
						di.bin_length = len.to_i
						di.add_comment cmt if cmt
						@decoded[a] = di
					rescue
						puts "load: bad di #{l.inspect}" if $VERBOSE
					end
				}
			when 'blocks'
				data.each_line { |l|
					bla = l.chomp.split(';').map { |sl| sl.split(',') }
					begin
						a = Expression.parse(pp.feed!(bla.shift[0])).reduce
						b = InstructionBlock.new(a, get_section_at(a).to_a[0])
						bla.shift.each { |e|
							a = Expression.parse(pp.feed!(e)).reduce
							b.add_di(@decoded[a])
						}
						bla.zip([:to_normal, :to_subfuncret, :to_indirect, :from_normal, :from_subfuncret, :from_indirect]).each { |l_, s|
							b.send("#{s}=", l_.map { |e| Expression.parse(pp.feed!(e)).reduce }) if not l_.empty?
						}
					rescue
						puts "load: bad block #{l.inspect}" if $VERBOSE
					end
				}
			when 'funcs'
				data.each_line { |l|
					begin
						a, *r = l.split(',').map { |e| Expression.parse(pp.feed!(e)).reduce }
						@function[a] = DecodedFunction.new
						@function[a].return_address = r if not r.empty?
						@function[a].finalized = true
						# TODO
					rescue
						puts "load: bad function #{l.inspect} #$!" if $VERBOSE
					end
				}
			when 'comment'
				data.each_line { |l|
					begin
						a, c = l.split(' ', 2)
						a = Expression.parse(pp.feed!(a)).reduce
						@comment[a] ||= []
						@comment[a] |= [c]
					rescue
						puts "load: bad comment #{l.inspect} #$!" if $VERBOSE
					end
				}
			when 'c'
				begin
					# TODO parse_invalid_c, split per function, whatever
					parse_c('')
					@c_parser.allow_bad_c = true
					parse_c(data, 'savefile#c')
				rescue
					puts "load: bad C: #$!", $!.backtrace if $VERBOSE
				end
				@c_parser.readtok until @c_parser.eos? if @c_parser
			when 'xrefs'
				data.each_line { |l|
					begin
						a, t, len, o = l.chomp.split(',')
						case a
						when ':default'; a = :default
						when ':unknown'; a = Expression::Unknown
						else a = Expression.parse(pp.feed!(a)).reduce
						end
						t = (t.empty? ? nil : t.to_sym)
						len = (len != '' ? len.to_i : nil)
						o = (o.to_s != '' ? Expression.parse(pp.feed!(o)).reduce : nil)	# :default/:unknown ?
						add_xref(a, Xref.new(t, o, len))
					rescue
						puts "load: bad xref #{l.inspect} #$!" if $VERBOSE
					end
				}
			#when 'trace'
			else
				if block_given?
					yield(type, data)
				else
					puts "load: unsupported section #{type.inspect}" if $VERBOSE
				end
			end
		end
	end
# loads the dasm state from a savefile content
# will yield unknown segments / binarypath notfound
loads the dasm state from a savefile content
will yield unknown segments / binarypath notfound
loads the dasm state from a savefile content will yield unknown segments / binarypath notfound
def load(str)
		raise 'Not a metasm save file' if str[0, 12].chomp != 'Metasm.dasm'
		off = 12
		pp = Preprocessor.new
		app = AsmPreprocessor.new
		while off < str.length
			i = str.index("\n", off) || str.length
			type, len = str[off..i].chomp.split
			off = i+1
			data = str[off, len.to_i]
			off += len.to_i
			case type
			when nil, ''
			when 'binarypath'
				data = yield(type, data) if not File.exist? data and block_given?
				reinitialize AutoExe.decode_file(data)
				@program.disassembler = self
				@program.init_disassembler
			when 'cpu'
				cpuname, size, endianness = data.split
				cpu = Metasm.const_get(cpuname)
				raise 'invalid cpu' if not cpu < CPU
				cpu = cpu.new
				cpu.size = size.to_i
				cpu.endianness = endianness.to_sym
				reinitialize Shellcode.new(cpu)
				@program.disassembler = self
				@program.init_disassembler
				@sections.delete(0)	
			when 'section'
				info = data[0, data.index("\n") || data.length]
				data = data[info.length, data.length]
				pp.feed!(info)
				addr = Expression.parse(pp).reduce
				len = Expression.parse(pp).reduce
				edata = EncodedData.new(data.unpack('m*').first, :virtsize => len)
				add_section(addr, edata)
			when 'map'
				load_map data
			when 'decoded'
				data.each_line { |l|
					begin
						next if l !~ /^([^,]*),(\d*) ([^;]*)(?:; (.*))?/
						a, len, instr, cmt = $1, $2, $3, $4
						a = Expression.parse(pp.feed!(a)).reduce
						instr = @cpu.parse_instruction(app.feed!(instr))
						di = DecodedInstruction.new(instr, a)
						di.bin_length = len.to_i
						di.add_comment cmt if cmt
						@decoded[a] = di
					rescue
						puts "load: bad di #{l.inspect}" if $VERBOSE
					end
				}
			when 'blocks'
				data.each_line { |l|
					bla = l.chomp.split(';').map { |sl| sl.split(',') }
					begin
						a = Expression.parse(pp.feed!(bla.shift[0])).reduce
						b = InstructionBlock.new(a, get_section_at(a).to_a[0])
						bla.shift.each { |e|
							a = Expression.parse(pp.feed!(e)).reduce
							b.add_di(@decoded[a])
						}
						bla.zip([:to_normal, :to_subfuncret, :to_indirect, :from_normal, :from_subfuncret, :from_indirect]).each { |l_, s|
							b.send("#{s}=", l_.map { |e| Expression.parse(pp.feed!(e)).reduce }) if not l_.empty?
						}
					rescue
						puts "load: bad block #{l.inspect}" if $VERBOSE
					end
				}
			when 'funcs'
				data.each_line { |l|
					begin
						a, *r = l.split(',').map { |e| Expression.parse(pp.feed!(e)).reduce }
						@function[a] = DecodedFunction.new
						@function[a].return_address = r if not r.empty?
						@function[a].finalized = true
					rescue
						puts "load: bad function #{l.inspect} #$!" if $VERBOSE
					end
				}
			when 'comment'
				data.each_line { |l|
					begin
						a, c = l.split(' ', 2)
						a = Expression.parse(pp.feed!(a)).reduce
						@comment[a] ||= []
						@comment[a] |= [c]
					rescue
						puts "load: bad comment #{l.inspect} #$!" if $VERBOSE
					end
				}
			when 'c'
				begin
					 parse_invalid_c, split per function, whatever
					parse_c('')
					@c_parser.allow_bad_c = true
					parse_c(data, 'savefile#c')
				rescue
					puts "load: bad C: #$!", $!.backtrace if $VERBOSE
				end
				@c_parser.readtok until @c_parser.eos? if @c_parser
			when 'xrefs'
				data.each_line { |l|
					begin
						a, t, len, o = l.chomp.split(',')
						case a
						when ':default'; a = :default
						when ':unknown'; a = Expression::Unknown
						else a = Expression.parse(pp.feed!(a)).reduce
						end
						t = (t.empty? ? nil : t.to_sym)
						len = (len != '' ? len.to_i : nil)
						o = (o.to_s != '' ? Expression.parse(pp.feed!(o)).reduce : nil)	
						add_xref(a, Xref.new(t, o, len))
					rescue
						puts "load: bad xref #{l.inspect} #$!" if $VERBOSE
					end
				}
			else
				if block_given?
					yield(type, data)
				else
					puts "load: unsupported section #{type.inspect}" if $VERBOSE
				end
			end
		end
	end
def load ( str ) raise 'Not a metasm save file' if str [ 0 , 12 ] . chomp != 'Metasm.dasm' off = 12 pp = Preprocessor . new app = AsmPreprocessor . new while off < str . length i = str . index ( "\n" , off ) || str . length type , len = str [ off .. i ] . chomp . split off = i + 1 data = str [ off , len . to_i ] off += len . to_i case type when nil , '' when 'binarypath' data = yield ( type , data ) if not File . exist? data and block_given? reinitialize AutoExe . decode_file ( data ) @program . disassembler = self @program . init_disassembler when 'cpu' cpuname , size , endianness = data . split cpu = Metasm . const_get ( cpuname ) raise 'invalid cpu' if not cpu < CPU cpu = cpu . new cpu . size = size . to_i cpu . endianness = endianness . to_sym reinitialize Shellcode . new ( cpu ) @program . disassembler = self @program . init_disassembler @sections . delete ( 0 ) when 'section' info = data [ 0 , data . index ( "\n" ) || data . length ] data = data [ info . length , data . length ] pp . feed! ( info ) addr = Expression . parse ( pp ) . reduce len = Expression . parse ( pp ) . reduce edata = EncodedData . new ( data . unpack ( 'm*' ) . first , :virtsize => len ) add_section ( addr , edata ) when 'map' load_map data when 'decoded' data . each_line { | l | begin next if l !~ / ^([^,]*),( \d *) ([^;]*)(?:; (.*))? / a , len , instr , cmt = $1 , $2 , $3 , $4 a = Expression . parse ( pp . feed! ( a ) ) . reduce instr = @cpu . parse_instruction ( app . feed! ( instr ) ) di = DecodedInstruction . new ( instr , a ) di . bin_length = len . to_i di . add_comment cmt if cmt @decoded [ a ] = di rescue puts "load: bad di #{l.inspect}" if $VERBOSE end } when 'blocks' data . each_line { | l | bla = l . chomp . split ( ';' ) . map { | sl | sl . split ( ',' ) } begin a = Expression . parse ( pp . feed! ( bla . shift [ 0 ] ) ) . reduce b = InstructionBlock . new ( a , get_section_at ( a ) . to_a [ 0 ] ) bla . shift . each { | e | a = Expression . parse ( pp . feed! ( e ) ) . reduce b . add_di ( @decoded [ a ] ) } bla . zip ( [ :to_normal , :to_subfuncret , :to_indirect , :from_normal , :from_subfuncret , :from_indirect ] ) . each { | l_ , s | b . send ( "#{s}=" , l_ . map { | e | Expression . parse ( pp . feed! ( e ) ) . reduce } ) if not l_ . empty? } rescue puts "load: bad block #{l.inspect}" if $VERBOSE end } when 'funcs' data . each_line { | l | begin a , * r = l . split ( ',' ) . map { | e | Expression . parse ( pp . feed! ( e ) ) . reduce } @function [ a ] = DecodedFunction . new @function [ a ] . return_address = r if not r . empty? @function [ a ] . finalized = true rescue puts "load: bad function #{l.inspect} #$!" if $VERBOSE end } when 'comment' data . each_line { | l | begin a , c = l . split ( ' ' , 2 ) a = Expression . parse ( pp . feed! ( a ) ) . reduce @comment [ a ] ||= [ ] @comment [ a ] |= [ c ] rescue puts "load: bad comment #{l.inspect} #$!" if $VERBOSE end } when 'c' begin parse_c ( '' ) @c_parser . allow_bad_c = true parse_c ( data , 'savefile#c' ) rescue puts "load: bad C: #$!" , $! . backtrace if $VERBOSE end @c_parser . readtok until @c_parser . eos? if @c_parser when 'xrefs' data . each_line { | l | begin a , t , len , o = l . chomp . split ( ',' ) case a when ':default' ; a = :default when ':unknown' ; a = Expression :: Unknown else a = Expression . parse ( pp . feed! ( a ) ) . reduce end t = ( t . empty? ? nil : t . to_sym ) len = ( len != '' ? len . to_i : nil ) o = ( o . to_s != '' ? Expression . parse ( pp . feed! ( o ) ) . reduce : nil ) add_xref ( a , Xref . new ( t , o , len ) ) rescue puts "load: bad xref #{l.inspect} #$!" if $VERBOSE end } else if block_given? yield ( type , data ) else puts "load: unsupported section #{type.inspect}" if $VERBOSE end end end end
loads the dasm state from a savefile content
will yield unknown segments / binarypath notfound
loads the dasm state from a savefile content will yield unknown segments / binarypath notfound
# rm empty section at 0, other real 'section' follow # TODO # TODO parse_invalid_c, split per function, whatever # :default/:unknown ? #when 'trace'
str