From 113b349af58ff6b3cf9a36ea553d6bfabb8e66bc Mon Sep 17 00:00:00 2001 From: Torsten Ruger Date: Sat, 31 Dec 2016 18:46:17 +0200 Subject: [PATCH] unlinking the objects collection from the machine passing it around instead --- lib/elf/object_writer.rb | 9 +++++--- lib/register/assembler.rb | 41 ++++++++++++++++++----------------- lib/register/collector.rb | 3 ++- lib/register/machine.rb | 3 +-- test/elf/test_hello.rb | 4 ++-- test/elf/test_zero.rb | 6 ++--- test/register/test_machine.rb | 4 ++-- 7 files changed, 37 insertions(+), 33 deletions(-) diff --git a/lib/elf/object_writer.rb b/lib/elf/object_writer.rb index cb8f0e4a..011211d4 100644 --- a/lib/elf/object_writer.rb +++ b/lib/elf/object_writer.rb @@ -7,7 +7,10 @@ require_relative 'string_table_section' module Elf class ObjectWriter - def initialize(target = Elf::Constants::TARGET_ARM ) + def initialize( machine , objects ) + @machine = machine + @objects = objects + target = Elf::Constants::TARGET_ARM @object = Elf::ObjectFile.new(target) sym_strtab = Elf::StringTableSection.new(".strtab") @object.add_section sym_strtab @@ -17,7 +20,7 @@ module Elf @text = Elf::TextSection.new(".text") @object.add_section @text - assembler = Register::Assembler.new(Register.machine) + assembler = Register::Assembler.new(@machine , @objects) set_text assembler.write_as_string # for debug add labels for labels @@ -29,7 +32,7 @@ module Elf end end - Register.machine.objects.each do |id,slot| + @objects.each do |id,slot| next if slot.is_a?(Parfait::BinaryCode) if( slot.respond_to? :sof_reference_name ) label = "#{slot.sof_reference_name}" diff --git a/lib/register/assembler.rb b/lib/register/assembler.rb index 4def3ffb..5b4fa51a 100644 --- a/lib/register/assembler.rb +++ b/lib/register/assembler.rb @@ -15,8 +15,9 @@ module Register MARKER = 0xA51AF00D - def initialize machine + def initialize( machine , objects) @machine = machine + @objects = objects @load_at = 0x8054 # this is linux/arm end @@ -24,13 +25,14 @@ module Register at = 0 #need the initial jump at 0 and then functions @machine.init.set_position(0) - at = assemble_objects + at = @machine.init.byte_length + at = assemble_objects( at ) # and then everything code - asseble_code_from( at ) + asseble_code_from( at ) end def asseble_code_from( at ) - @machine.objects.each do |id , objekt| + @objects.each do |id , objekt| next unless objekt.is_a? Parfait::TypedMethod log.debug "CODE1 #{objekt.name}" binary = objekt.binary @@ -44,11 +46,10 @@ module Register at end - def assemble_objects - at = @machine.init.byte_length + def assemble_objects( at) at += 8 # thats the padding # want to have the objects first in the executable - @machine.objects.each do | id , objekt| + @objects.each do | id , objekt| next if objekt.is_a? Register::Label # will get assembled as method.instructions next if objekt.is_a? Parfait::BinaryCode objekt.set_position at @@ -81,7 +82,7 @@ module Register # debugging loop accesses all positions to force an error if it's not set def try_write_debug - all = @machine.objects.values.sort{|a,b| a.position <=> b.position} + all = @objects.values.sort{|a,b| a.position <=> b.position} all.each do |objekt| next if objekt.is_a?(Register::Label) log.debug "Linked #{objekt.class}(#{objekt.object_id}) at #{objekt.position} / #{objekt.padded_length}" @@ -91,19 +92,19 @@ module Register def try_write_create_binary # first we need to create the binary code for the methods - @machine.objects.each do |id , objekt| + @objects.each do |id , objekt| next unless objekt.is_a? Parfait::TypedMethod assemble_binary_method(objekt) end @stream = StringIO.new @machine.init.assemble( @stream ) 8.times do - @stream.write_uint8(0) + @stream.write_unsigned_int_8(0) end end def try_write_objects # then the objects , not code yet - @machine.objects.each do | id, objekt| + @objects.each do | id, objekt| next if objekt.is_a? Parfait::BinaryCode next if objekt.is_a? Register::Label # ignore write_any( objekt ) @@ -112,7 +113,7 @@ module Register def try_write_method # then write the methods to file - @machine.objects.each do |id, objekt| + @objects.each do |id, objekt| next unless objekt.is_a? Parfait::BinaryCode write_any( objekt ) end @@ -187,7 +188,7 @@ module Register def write_object_check(object) log.debug "Write object #{object.class} #{object.inspect}" - unless @machine.objects.has_key? object.object_id + unless @objects.has_key? object.object_id raise "Object(#{object.object_id}) not linked #{object.inspect}" end end @@ -204,7 +205,7 @@ module Register end def write_object_variables(object) - @stream.write_sint32( MARKER ) + @stream.write_signed_int_32( MARKER ) written = 0 # compensate for the "secrect" marker object.get_instance_variables.each do |var| inst = object.get_instance_variable(var) @@ -230,9 +231,9 @@ module Register end def write_checked_string(string, str) - @stream.write_sint32( MARKER ) + @stream.write_signed_int_32( MARKER ) write_ref_for( string.get_type ) #ref - @stream.write_sint32( str.length ) #int + @stream.write_signed_int_32( str.length ) #int @stream.write str pad_after(str.length + 8 ) # type , length *4 == 12 log.debug "String (#{string.length}) stream #{@stream.length}" @@ -249,11 +250,11 @@ module Register def write_ref_for object case object when nil - @stream.write_sint32(0) + @stream.write_signed_int_32(0) when Fixnum - @stream.write_sint32(object) + @stream.write_signed_int_32(object) else - @stream.write_sint32(object.position + @load_at) + @stream.write_signed_int_32(object.position + @load_at) end end @@ -262,7 +263,7 @@ module Register before = stream_position pad = padding_for(length) - 4 # four is for the MARKER we write pad.times do - @stream.write_uint8(0) + @stream.write_unsigned_int_8(0) end after = stream_position log.debug "padded #{length} with #{pad} stream #{before}/#{after}" diff --git a/lib/register/collector.rb b/lib/register/collector.rb index 8b6ab581..1c65fcd4 100644 --- a/lib/register/collector.rb +++ b/lib/register/collector.rb @@ -3,9 +3,10 @@ module Register # collect anything that is in the space but and reachable from init module Collector def collect_space - @objects.clear + @objects = {} keep Parfait.object_space , 0 constants.each {|obj| keep(obj,0)} + @objects end def keep( object , depth ) diff --git a/lib/register/machine.rb b/lib/register/machine.rb index 3296beae..34f85b63 100644 --- a/lib/register/machine.rb +++ b/lib/register/machine.rb @@ -17,11 +17,10 @@ module Register log_level :info def initialize - @objects = {} @booted = false @constants = [] end - attr_reader :constants , :init , :objects , :booted + attr_reader :constants , :init , :booted # idea being that later method missing could catch translate_xxx and translate to target xxx # now we just instantiate ArmTranslater and pass instructions diff --git a/test/elf/test_hello.rb b/test/elf/test_hello.rb index 9f626bd7..a2c7dd81 100644 --- a/test/elf/test_hello.rb +++ b/test/elf/test_hello.rb @@ -6,9 +6,9 @@ class HelloTest < MiniTest::Test def check machine = Register.machine.boot Typed.compile( @input ) - machine.collect_space + objects = machine.collect_space machine.translate_arm - writer = Elf::ObjectWriter.new + writer = Elf::ObjectWriter.new(machine , objects ) writer.save "test/hello.o" end diff --git a/test/elf/test_zero.rb b/test/elf/test_zero.rb index 62453f90..b27984c8 100644 --- a/test/elf/test_zero.rb +++ b/test/elf/test_zero.rb @@ -10,7 +10,7 @@ class TestZeroCode < MiniTest::Test type.remove_method(method) unless keeper(method) end end - @machine.collect_space + @objects = @machine.collect_space end def keeper name name == :main or name == :__init__ @@ -19,13 +19,13 @@ class TestZeroCode < MiniTest::Test def test_empty_translate assert_equal 2 , @space.collect_methods.length @machine.translate_arm - writer = Elf::ObjectWriter.new + writer = Elf::ObjectWriter.new(@machine , @objects ) writer.save "test/zero.o" end def test_methods_match_objects assert_equal 2 , @space.collect_methods.length - @machine.objects.each do |id , objekt| + @objects.each do |id , objekt| next unless objekt.is_a? Parfait::TypedMethod assert keeper(objekt.name) , "CODE1 #{objekt.name}" end diff --git a/test/register/test_machine.rb b/test/register/test_machine.rb index 9210e5d1..c61f36b6 100644 --- a/test/register/test_machine.rb +++ b/test/register/test_machine.rb @@ -8,8 +8,8 @@ module Register end def test_collect_all_types - @machine.collect_space - @machine.objects.each do |id, objekt| + objects = @machine.collect_space + objects.each do |id, objekt| next unless objekt.is_a?( Parfait::Type ) assert Parfait.object_space.get_type_for( objekt.hash ) , objekt.hash end