From 0dfbce4eedffcf2254bd64939a389007ccbb3430 Mon Sep 17 00:00:00 2001 From: inglorion Date: Sun, 1 Dec 2013 05:43:17 +0000 Subject: [PATCH] reject programs that export symbols after they have been used --- lib/voodoo/code_generator.rb | 11 ++++++++ lib/voodoo/generators/arm_gas_generator.rb | 10 +++---- lib/voodoo/generators/common_code_generator.rb | 31 +++++++++++++++++----- lib/voodoo/generators/nasm_generator.rb | 3 +-- test/export-after-use.err | 1 + .../{import-after-use.voo => export-after-use.voo} | 12 +++++---- test/import-after-use.voo | 3 ++- test/test | 3 +++ 8 files changed, 54 insertions(+), 20 deletions(-) create mode 100644 test/export-after-use.err copy test/{import-after-use.voo => export-after-use.voo} (61%) diff --git a/lib/voodoo/code_generator.rb b/lib/voodoo/code_generator.rb index ab8c1d6..4c20513 100644 --- a/lib/voodoo/code_generator.rb +++ b/lib/voodoo/code_generator.rb @@ -70,6 +70,17 @@ module Voodoo class Error < Voodoo::Error end + # Error raised when a symbol is exported after it has been used. + class SymbolsExportedAfterUseError < Error + def initialize symbols + @symbols = symbols + super("Symbols exported after they have been used: " + + symbols.to_a.join(" ")) + end + + attr_reader :symbols + end + # Error raised when a symbol is imported after it has been used. class SymbolsImportedAfterUseError < Error def initialize symbols diff --git a/lib/voodoo/generators/arm_gas_generator.rb b/lib/voodoo/generators/arm_gas_generator.rb index 5971c6a..ceb3812 100644 --- a/lib/voodoo/generators/arm_gas_generator.rb +++ b/lib/voodoo/generators/arm_gas_generator.rb @@ -337,6 +337,11 @@ module Voodoo @constants = [] end + # Declares symbols to be exported. + def emit_export *symbols + symbols.each { |sym| emit ".globl #{sym}\n" } + end + # Emit function prologue. def emit_function_prologue formals = [], nlocals = 0 # Calculate the number of arguments we were passed in @@ -542,11 +547,6 @@ module Voodoo end end - # Export symbols from the current section - def export *symbols - symbols.each { |sym| emit ".globl #{sym}\n" } - end - # Load byte from _base_ + _offset_ into _register_ def get_byte base, offset, register # If base is an integer, but offset isn't, swap them diff --git a/lib/voodoo/generators/common_code_generator.rb b/lib/voodoo/generators/common_code_generator.rb index eef60a9..b2fc6e0 100644 --- a/lib/voodoo/generators/common_code_generator.rb +++ b/lib/voodoo/generators/common_code_generator.rb @@ -315,11 +315,21 @@ module Voodoo # Declares that the given symbols are to be externally visible. # Requires subclasses to implement emit_export. def export *symbols - if real_section_name(section) == ".data" - @relocated_symbols.merge symbols + used_earlier = symbols_used_unrelocated symbols + # Exporting symbols after they have been used is not allowed. + error = nil + unless used_earlier.empty? + error = CodeGenerator::SymbolsExportedAfterUseError.new(used_earlier) + end + begin + if real_section_name(section) == ".data" + @relocated_symbols.merge symbols + end + @symbol_tracker.use *symbols + emit_export *symbols + ensure + raise error unless error == nil end - @symbol_tracker.use *symbols - emit_export *symbols end # Adds a function to the current section. @@ -342,15 +352,14 @@ module Voodoo # so targets where code is required for imports will want to override # emit_import. def import *symbols - new_symbols = Set.new(symbols) - @relocated_symbols - used_earlier = @symbol_tracker.used_but_undefined_symbols & new_symbols + used_earlier = symbols_used_unrelocated symbols # Importing symbols after they have been used is not allowed. error = nil unless used_earlier.empty? error = CodeGenerator::SymbolsImportedAfterUseError.new(used_earlier) end begin - @relocated_symbols.merge new_symbols + @relocated_symbols.merge symbols @symbol_tracker.define *symbols emit_import *symbols ensure @@ -741,5 +750,13 @@ module Voodoo end max end + + # Given symbols, returns the set of symbols among those that + # have been used without relocation. + def symbols_used_unrelocated symbols + symbols_set = symbols.kind_of?(Set) ? symbols : Set.new(symbols) + new_symbols = symbols_set - @relocated_symbols + @symbol_tracker.used_symbols & new_symbols + end end end diff --git a/lib/voodoo/generators/nasm_generator.rb b/lib/voodoo/generators/nasm_generator.rb index cd13d74..bea95e9 100644 --- a/lib/voodoo/generators/nasm_generator.rb +++ b/lib/voodoo/generators/nasm_generator.rb @@ -35,12 +35,11 @@ module Voodoo # # Export symbols from the current section - def export *symbols + def emit_export *symbols case real_section_name(section) when ".text" symbols.each { |sym| emit "global #{sym}:function\n" } else - @relocated_symbols.merge symbols symbols.each { |sym| emit "global #{sym}:data #{sym}.end-#{sym}\n" } end end diff --git a/test/export-after-use.err b/test/export-after-use.err new file mode 100644 index 0000000..530b7a3 --- /dev/null +++ b/test/export-after-use.err @@ -0,0 +1 @@ +Symbols exported after they have been used: msg diff --git a/test/import-after-use.voo b/test/export-after-use.voo similarity index 61% copy from test/import-after-use.voo copy to test/export-after-use.voo index 3122520..b83b588 100644 --- a/test/import-after-use.voo +++ b/test/export-after-use.voo @@ -1,9 +1,8 @@ -# Imports a symbol after it has been used. Compilers should reject this program. - -section data -msg: string "FAIL\x00" +# Exports a symbol after it has been used. +# Implementations should reject this program. section functions +import puts export main align @@ -13,4 +12,7 @@ function argc argv return 0 end function -import puts +section data +msg: string "FAIL\x00" + +export msg diff --git a/test/import-after-use.voo b/test/import-after-use.voo index 3122520..e2414bf 100644 --- a/test/import-after-use.voo +++ b/test/import-after-use.voo @@ -1,4 +1,5 @@ -# Imports a symbol after it has been used. Compilers should reject this program. +# Imports a symbol after it has been used. +# Implementations should reject this program. section data msg: string "FAIL\x00" diff --git a/test/test b/test/test index d2d769a..2e00d4f 100755 --- a/test/test +++ b/test/test @@ -27,6 +27,9 @@ add_test 'features', '../bin/voodooc -a i386 --features', `cat features.out` add_test 'help', '../bin/voodooc --help', `cat help.out` +add_test('export-after-use', '../bin/voodooc export-after-use.voo', '', + :expected_status => 1, :expected_errors => `cat export-after-use.err`) + add_test('import-after-use', '../bin/voodooc import-after-use.voo', '', :expected_status => 1, :expected_errors => `cat import-after-use.err`) -- 2.11.4.GIT