symbol table now uses offsets instead of absolute addresses

This commit is contained in:
Sami Samhuri 2010-01-19 23:22:40 -08:00
parent ce1f5bb4dc
commit 19d79c8836
2 changed files with 76 additions and 41 deletions

View file

@ -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. [[<key>, <value>], ...]
# 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,12 +21,32 @@ 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 = {}
strx = 1
@ -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

View file

@ -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 = ''
@ -19,15 +28,15 @@ module Assembler
@labels = Hash.new {|h, key| raise "undefined label: #{key}"}
@num_labels = 0 # Used to generate unique labels.
@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
####
## NB: Concrete subclasses must define methods named:
## bss_offset, and const_offset
####
# Generate a unique label.
def unique_label(suffix=nil)
@num_labels += 1
@ -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 const(name)
const_offset + @consts[name]
def var?(name)
@vars.has_key?(name)
end
def const?(name)
def const(name)
@consts[name]
end
def const?(name)
@consts.has_key?(name)
end
end
end