diff --git a/asm/machosymtab.rb b/asm/machosymtab.rb index 1cb8263..329ec38 100644 --- a/asm/machosymtab.rb +++ b/asm/machosymtab.rb @@ -8,22 +8,12 @@ module Assembler include MachO - def const_offset - return 0x2000 - end - - def bss_offset - # TODO figure out how to calculate these, or how to let the linker do it! - # ... relocation tables perhaps? - return 0x2800 - end - - def make_symbols(vars, type, segnum) + def make_symbols(vars, base_addr, type, segnum) # Note: Sorting a Ruby hash gives an alist, e.g. [[, ], ...] # We can use map on it as if it were a hash so it works nicely. vars.sort { |a,b| a[1] <=> b[1] }. - map do |name, addr| - MachOSym.new(name, type, segnum, 0, addr) + map do |name, offset| + MachOSym.new(name, type, segnum, 0, base_addr + offset) end end @@ -31,11 +21,31 @@ module Assembler # TODO FIXME: # - the last var exported ends up after main somewhere... WTF?! # - All labels are exported. This should be changed and only functions exported! - symbols = make_symbols(@labels, N_SECT | N_EXT, 1) + # Functions (section #1, __text) - make_symbols(@consts, N_SECT, 2) + # Constants (section #2, __const) - make_symbols(@vars, N_SECT, 3) # Variables (section #3, __bss) + + section = 1 + + # Functions (section #1, __text) + symbols = make_symbols(@labels, text_offset, N_SECT | N_EXT, section) + section += 1 + + # Constants (section #2, __const) + if @consts.size > 0 + symbols += make_symbols(@consts, const_offset, N_SECT, section) + section += 1 + end + + # Variables (section #3, __bss) + if @vars.size > 0 + symbols += make_symbols(@vars, bss_offset, N_SECT, section) + end + return symbols end + + # this is fairly stupid but works + def bss_section + @consts.size > 0 ? 3 : 2 + end def nlist_ary symbols = {} @@ -53,10 +63,26 @@ module Assembler end def stab - # The empty strings result in a string that begins and ends with + # The empty strings result in a string that begins and ends with a null byte ['', all_symbols, ''].flatten.map { |sym| sym.to_s }.join("\0") end + def reloc(r_address, r_symbolnum=0, r_length=2, r_extern=0, r_pcrel=0, r_type=0) + r_info = (r_type << 28) | (r_extern << 27) | (r_length << 25) | + (r_pcrel << 24) | r_symbolnum + @reloc_info << RelocationInfo.new(r_address, r_info) + end + + def reloc_info + n = bss_section + @reloc_info.each {|r| r[:r_info] |= n} + end + + def calculate_offsets(text_size) + @const_offset = @text_offset + text_size + @bss_offset = @const_offset + @const_size + end + end end diff --git a/asm/symtab.rb b/asm/symtab.rb index c0b5100..da095d0 100644 --- a/asm/symtab.rb +++ b/asm/symtab.rb @@ -1,13 +1,22 @@ module Assembler - + + + # Abstract symbol table. + # + # Basically a big map of variable, constant, and label names to + # offsets within their respective sections. Final addresses are + # calculated from these offsets on the 2nd pass when we know where + # things will actually live in memory. + class Symtab - attr_reader :const_data, :bss_size + attr_accessor :text_offset, :bss_offset, :const_offset + attr_reader :const_data, :const_size, :bss_size, :reloc_info def initialize - @vars = {} # Map of variable names to addresses. (bss vars) - @consts = {} # Map of constant names to addresses. - @funcs = {} # map of function names to addresses. + @vars = {} # Map of variable names to offsets. (bss vars) + @consts = {} # Map of constant names to offsets. + @funcs = {} # map of function names to offsets. # Initial data to load into memory (data for __DATA segment). @const_data = '' @@ -18,15 +27,15 @@ module Assembler # Map names to locations. @labels = Hash.new {|h, key| raise "undefined label: #{key}"} @num_labels = 0 # Used to generate unique labels. - @num_labels_with_suffix = Hash.new(0) - end - - - #### - ## NB: Concrete subclasses must define methods named: - ## bss_offset, and const_offset - #### + @num_labels_with_suffix = Hash.new(0) + # Relocation info. Subclasses should define a reloc method. + @reloc_info = [] + + @text_offset = 0 + @bss_offset = 0 + @const_offset = 0 + end # Generate a unique label. def unique_label(suffix=nil) @@ -39,8 +48,8 @@ module Assembler return name end - def deflabel(name, addr) - @labels[name] = addr + def deflabel(name, offset) + @labels[name] = offset return name end @@ -63,27 +72,27 @@ module Assembler end - def defun(name, addr) - @funcs[name] = addr + def defun(name, offset) + @funcs[name] = offset end def var(name) - bss_offset + @vars[name] - end - - def var?(name) @vars[name] end + def var?(name) + @vars.has_key?(name) + end + def const(name) - const_offset + @consts[name] + @consts[name] end def const?(name) - @consts[name] + @consts.has_key?(name) end - + end end