[SeaBIOS] [PATCH] Simplify build by manually resolving external symbols in layoutrom.py.

Kevin O'Connor kevin at koconnor.net
Sat May 1 18:19:10 CEST 2010


Enhance tools/layoutrom.py to explicitly set those symbols that
resolve to a different code chunk (eg, 16, 32seg, 32flat).  This
eliminates the need to link the code chunks multiple times.

This patch reduces the dependency on binutils behavior and makes the
build simpler to understand.
---
 Makefile               |   27 ++--
 src/rombios.lds.S      |   34 ----
 src/rombios16.lds.S    |   21 ---
 src/rombios32seg.lds.S |   18 --
 tools/checkrom.py      |   29 ++--
 tools/checkstack.py    |    2 +-
 tools/layoutrom.py     |  401 ++++++++++++++++++++++++++----------------------
 7 files changed, 241 insertions(+), 291 deletions(-)
 delete mode 100644 src/rombios.lds.S
 delete mode 100644 src/rombios16.lds.S
 delete mode 100644 src/rombios32seg.lds.S

diff --git a/Makefile b/Makefile
index 90d7072..327a1bf 100644
--- a/Makefile
+++ b/Makefile
@@ -100,6 +100,9 @@ endef
 endif
 endif
 
+%.strip.o: %.o
+	@echo "  Stripping $@"
+	$(Q)$(STRIP) $< -o $@
 
 $(OUT)%.s: %.c
 	@echo "  Compiling to assembler $@"
@@ -135,27 +138,17 @@ $(OUT)romlayout16.lds $(OUT)romlayout32seg.lds $(OUT)romlayout32flat.lds $(OUT)c
 	$(Q)./tools/layoutrom.py $(OUT)code16.o.objdump $(OUT)code32seg.o.objdump $(OUT)code32flat.o.objdump $(OUT)romlayout16.lds $(OUT)romlayout32seg.lds $(OUT)romlayout32flat.lds
 
 
-$(OUT)rom16.o: $(OUT)code16.o $(OUT)rom32flat.o $(OUT)romlayout16.lds
-	@echo "  Linking (no relocs) $@"
-	$(Q)$(LD) -r -T $(OUT)romlayout16.lds $< -o $@
+$(OUT)rom16.o: $(OUT)code16.o $(OUT)romlayout16.lds
+	@echo "  Linking $@"
+	$(Q)$(LD) -T $(OUT)romlayout16.lds $< -o $@
 
 $(OUT)rom32seg.o: $(OUT)code32seg.o $(OUT)romlayout32seg.lds
-	@echo "  Linking (no relocs) $@"
-	$(Q)$(LD) -r -T $(OUT)romlayout32seg.lds $< -o $@
-
-$(OUT)rom32flat.o: $(OUT)code32flat.o $(OUT)romlayout32flat.lds
-	@echo "  Linking (no relocs) $@"
-	$(Q)$(LD) -r -T $(OUT)romlayout32flat.lds $< -o $@
+	@echo "  Linking $@"
+	$(Q)$(LD) -T $(OUT)romlayout32seg.lds $< -o $@
 
-$(OUT)rom.o: $(OUT)rom16.o $(OUT)rom32seg.o $(OUT)rom32flat.o $(OUT)rombios16.lds  $(OUT)rombios32seg.lds $(OUT)rombios.lds
+$(OUT)rom.o: $(OUT)rom16.strip.o $(OUT)rom32seg.strip.o $(OUT)code32flat.o $(OUT)romlayout32flat.lds
 	@echo "  Linking $@"
-	$(Q)$(LD) -T $(OUT)rombios16.lds $(OUT)rom16.o -R $(OUT)rom32seg.o -R $(OUT)rom32flat.o -o $(OUT)rom16.reloc.o
-	$(Q)$(STRIP) $(OUT)rom16.reloc.o -o $(OUT)rom16.final.o
-	$(Q)$(OBJCOPY) --adjust-vma 0xf0000 $(OUT)rom16.o $(OUT)rom16.moved.o
-	$(Q)$(LD) -T $(OUT)rombios32seg.lds $(OUT)rom32seg.o -R $(OUT)rom16.o -R $(OUT)rom32flat.o -o $(OUT)rom32seg.reloc.o
-	$(Q)$(STRIP) $(OUT)rom32seg.reloc.o -o $(OUT)rom32seg.final.o
-	$(Q)$(OBJCOPY) --adjust-vma 0xf0000 $(OUT)rom32seg.o $(OUT)rom32seg.moved.o
-	$(Q)$(LD) -T $(OUT)rombios.lds $(OUT)rom16.final.o $(OUT)rom32seg.final.o $(OUT)rom32flat.o -R $(OUT)rom16.moved.o -R $(OUT)rom32seg.moved.o -o $@
+	$(Q)$(LD) -T $(OUT)romlayout32flat.lds $(OUT)rom16.strip.o $(OUT)rom32seg.strip.o $(OUT)code32flat.o -o $@
 
 $(OUT)bios.bin.elf $(OUT)bios.bin: $(OUT)rom.o tools/checkrom.py
 	@echo "  Prepping $@"
diff --git a/src/rombios.lds.S b/src/rombios.lds.S
deleted file mode 100644
index 4cbc15a..0000000
--- a/src/rombios.lds.S
+++ /dev/null
@@ -1,34 +0,0 @@
-// Linker definitions for merging 16 and 32 bit code
-//
-// Copyright (C) 2008,2009  Kevin O'Connor <kevin at koconnor.net>
-//
-// This file may be distributed under the terms of the GNU LGPLv3 license.
-
-#include "config.h" // BUILD_BIOS_ADDR
-
-OUTPUT_FORMAT("elf32-i386")
-OUTPUT_ARCH("i386")
-ENTRY(post32)
-PHDRS
-{
-        text PT_LOAD AT ( code32flat_start ) ;
-}
-SECTIONS
-{
-        .text code32flat_start : {
-                *(.text32flat)
-
-                . = code32seg_start + BUILD_BIOS_ADDR - code32flat_start ;
-                *(.text32seg)
-
-                . = data16_start + BUILD_BIOS_ADDR - code32flat_start ;
-                *(.data16)
-                . = text16_start + BUILD_BIOS_ADDR - code32flat_start ;
-                *(.text16)
-                final_text16_end = . ;
-                } :text
-        /DISCARD/ : {
-                *(.text*) *(.data*) *(.bss*) *(.rodata*)
-                *(COMMON) *(.discard*) *(.eh_frame)
-                }
-}
diff --git a/src/rombios16.lds.S b/src/rombios16.lds.S
deleted file mode 100644
index 6d382f0..0000000
--- a/src/rombios16.lds.S
+++ /dev/null
@@ -1,21 +0,0 @@
-// Linker definitions for 16bit code
-//
-// Copyright (C) 2008,2009  Kevin O'Connor <kevin at koconnor.net>
-//
-// This file may be distributed under the terms of the GNU LGPLv3 license.
-
-OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
-OUTPUT_ARCH("i386")
-PHDRS
-{
-}
-SECTIONS
-{
-        .data16 data16_start : {
-                *(.data16)
-                }
-        .text16 text16_start : {
-                *(.text16)
-                }
-        /DISCARD/ : { *(.discard*) }
-}
diff --git a/src/rombios32seg.lds.S b/src/rombios32seg.lds.S
deleted file mode 100644
index 377f4e7..0000000
--- a/src/rombios32seg.lds.S
+++ /dev/null
@@ -1,18 +0,0 @@
-// Linker definitions for 32bit segmented code
-//
-// Copyright (C) 2009  Kevin O'Connor <kevin at koconnor.net>
-//
-// This file may be distributed under the terms of the GNU LGPLv3 license.
-
-OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
-OUTPUT_ARCH("i386")
-PHDRS
-{
-}
-SECTIONS
-{
-        .text32seg code32seg_start : {
-                *(.text32seg)
-        }
-        /DISCARD/ : { *(.discard*) }
-}
diff --git a/tools/checkrom.py b/tools/checkrom.py
index 5c9600f..039010d 100755
--- a/tools/checkrom.py
+++ b/tools/checkrom.py
@@ -29,34 +29,27 @@ def main():
         finalsize = 128*1024
 
     # Sanity checks
-    c16e = syms['text16_end'] + 0xf0000
-    f16e = syms['final_text16_end']
-    if c16e != f16e:
-        print "Error!  16bit code moved during linking (0x%x vs 0x%x)" % (
-            c16e, f16e)
+    start = syms['code32flat_start']
+    end = syms['code32flat_end']
+    expend = layoutrom.BUILD_BIOS_ADDR + layoutrom.BUILD_BIOS_SIZE
+    if end != expend:
+        print "Error!  Code does not end at 0x%x (got 0x%x)" % (
+            expend, end)
         sys.exit(1)
     if datasize > finalsize:
         print "Error!  Code is too big (0x%x vs 0x%x)" % (
             datasize, finalsize)
         sys.exit(1)
-    actualdatasize = f16e - syms['code32flat_start']
-    if datasize != actualdatasize:
+    expdatasize = end - start
+    if datasize != expdatasize:
         print "Error!  Unknown extra data (0x%x vs 0x%x)" % (
-            datasize, actualdatasize)
+            datasize, expdatasize)
         sys.exit(1)
 
     # Print statistics
-    sizefree = syms['freespace_end'] - syms['freespace_start']
-    size16 = syms['text16_end'] - syms['data16_start']
-    size32seg = syms['code32seg_end'] - syms['code32seg_start']
-    size32flat = syms['code32flat_end'] - syms['code32flat_start']
-    totalc = size16+size32seg+size32flat
-    print "16bit size:           %d" % size16
-    print "32bit segmented size: %d" % size32seg
-    print "32bit flat size:      %d" % size32flat
     print "Total size: %d  Free space: %d  Percent used: %.1f%% (%dKiB rom)" % (
-        totalc, sizefree + finalsize - datasize
-        , (totalc / float(finalsize)) * 100.0
+        datasize, finalsize - datasize
+        , (datasize / float(finalsize)) * 100.0
         , finalsize / 1024)
 
     # Write final file
diff --git a/tools/checkstack.py b/tools/checkstack.py
index 84bd778..54ea3e9 100755
--- a/tools/checkstack.py
+++ b/tools/checkstack.py
@@ -7,7 +7,7 @@
 # This file may be distributed under the terms of the GNU GPLv3 license.
 
 # Usage:
-#   objdump -m i386 -M i8086 -M suffix -d out/rom16.reloc.o | tools/checkstack.py
+#   objdump -m i386 -M i8086 -M suffix -d out/rom16.o | tools/checkstack.py
 
 import sys
 import re
diff --git a/tools/layoutrom.py b/tools/layoutrom.py
index d0ca9a6..5f8c368 100755
--- a/tools/layoutrom.py
+++ b/tools/layoutrom.py
@@ -7,11 +7,6 @@
 
 import sys
 
-# Align 'pos' to 'alignbytes' offset
-def alignpos(pos, alignbytes):
-    mask = alignbytes - 1
-    return (pos + mask) & ~mask
-
 # LD script headers/trailers
 COMMONHEADER = """
 /* DO NOT EDIT!  This is an autogenerated file.  See tools/layoutrom.py. */
@@ -21,15 +16,29 @@ SECTIONS
 {
 """
 COMMONTRAILER = """
+
+        /* Discard regular data sections to force a link error if
+         * code attempts to access data not marked with VAR16 (or other
+         * appropriate macro)
+         */
+        /DISCARD/ : {
+                *(.text*) *(.data*) *(.bss*) *(.rodata*)
+                *(COMMON) *(.discard*) *(.eh_frame)
+                }
 }
 """
 
 
 ######################################################################
-# 16bit fixed address section fitting
+# Determine section locations
 ######################################################################
 
-# Get the maximum start position for a list of sections that end at an
+# Align 'pos' to 'alignbytes' offset
+def alignpos(pos, alignbytes):
+    mask = alignbytes - 1
+    return (pos + mask) & ~mask
+
+# Determine the final addresses for a list of sections that end at an
 # address.
 def getSectionsStart(sections, endaddr, minalign=1):
     totspace = 0
@@ -37,47 +46,46 @@ def getSectionsStart(sections, endaddr, minalign=1):
         if align > minalign:
             minalign = align
         totspace = alignpos(totspace, align) + size
-    return (endaddr - totspace) / minalign * minalign
+    startaddr = (endaddr - totspace) / minalign * minalign
+    curaddr = startaddr
+    # out = [(addr, sectioninfo), ...]
+    out = []
+    for sectioninfo in sections:
+        size, align, name = sectioninfo
+        curaddr = alignpos(curaddr, align)
+        out.append((curaddr, sectioninfo))
+        curaddr += size
+    return out, startaddr
 
-# Write LD script includes for the given sections
-def outSections(file, sections):
+# Return the subset of sections with a given name prefix
+def getSectionsPrefix(sections, prefix):
+    lp = len(prefix)
+    out = []
     for size, align, name in sections:
-        file.write("*(%s)\n" % (name,))
+        if name[:lp] == prefix:
+            out.append((size, align, name))
+    return out
 
 # The 16bit code can't exceed 64K of space.
-MAXPOS = 64*1024
+BUILD_BIOS_ADDR = 0xf0000
+BUILD_BIOS_SIZE = 0x10000
 
 # Layout the 16bit code.  This ensures sections with fixed offset
 # requirements are placed in the correct location.  It also places the
 # 16bit code as high as possible in the f-segment.
-def doLayout16(sections, outname):
-    textsections = []
-    rodatasections = []
-    datasections = []
-    # fixedsections = [(addr, sectioninfo, extasectionslist), ...]
+def fitSections(sections, fillsections):
+    canrelocate = list(fillsections)
+    # fixedsections = [(addr, sectioninfo), ...]
     fixedsections = []
-    # canrelocate = [(sectioninfo, list), ...]
-    canrelocate = []
-
-    # Find desired sections.
-    for section in sections:
-        size, align, name = section
+    for sectioninfo in sections:
+        size, align, name = sectioninfo
         if name[:11] == '.fixedaddr.':
             addr = int(name[11:], 16)
-            fixedsections.append((addr, section, []))
+            fixedsections.append((addr, sectioninfo))
             if align != 1:
                 print "Error: Fixed section %s has non-zero alignment (%d)" % (
                     name, align)
                 sys.exit(1)
-        if name[:6] == '.text.':
-            textsections.append(section)
-            canrelocate.append((section, textsections))
-        if name[:17] == '.rodata.__func__.' or name == '.rodata.str1.1':
-            rodatasections.append(section)
-            #canrelocate.append((section, rodatasections))
-        if name[:8] == '.data16.':
-            datasections.append(section)
-            #canrelocate.append((section, datasections))
 
     # Find freespace in fixed address area
     fixedsections.sort()
@@ -85,20 +93,21 @@ def doLayout16(sections, outname):
     fixedAddr = []
     for i in range(len(fixedsections)):
         fixedsectioninfo = fixedsections[i]
-        addr, section, extrasectionslist = fixedsectioninfo
+        addr, section = fixedsectioninfo
         if i == len(fixedsections) - 1:
-            nextaddr = MAXPOS
+            nextaddr = BUILD_BIOS_SIZE
         else:
             nextaddr = fixedsections[i+1][0]
         avail = nextaddr - addr - section[0]
         fixedAddr.append((avail, fixedsectioninfo))
 
     # Attempt to fit other sections into fixed area
+    extrasections = []
     fixedAddr.sort()
     canrelocate.sort()
     totalused = 0
     for freespace, fixedsectioninfo in fixedAddr:
-        fixedaddr, fixedsection, extrasections = fixedsectioninfo
+        fixedaddr, fixedsection = fixedsectioninfo
         addpos = fixedaddr + fixedsection[0]
         totalused += fixedsection[0]
         nextfixedaddr = addpos + freespace
@@ -106,8 +115,7 @@ def doLayout16(sections, outname):
 #            fixedaddr, fixedsection[0], nextfixedaddr, freespace)
         while 1:
             canfit = None
-            for fixedaddrinfo in canrelocate:
-                fitsection, inlist = fixedaddrinfo
+            for fitsection in canrelocate:
                 fitsize, fitalign, fitname = fitsection
                 if addpos + fitsize > nextfixedaddr:
                     # Can't fit and nothing else will fit.
@@ -118,15 +126,13 @@ def doLayout16(sections, outname):
                 if fitnextaddr > nextfixedaddr:
                     # This item can't fit.
                     continue
-                canfit = (fitnextaddr, fixedaddrinfo)
+                canfit = (fitnextaddr, fitsection)
             if canfit is None:
                 break
             # Found a section that can fit.
-            fitnextaddr, fixedaddrinfo = canfit
-            canrelocate.remove(fixedaddrinfo)
-            fitsection, inlist = fixedaddrinfo
-            inlist.remove(fitsection)
-            extrasections.append(fitsection)
+            fitnextaddr, fitsection = canfit
+            canrelocate.remove(fitsection)
+            extrasections.append((addpos, fitsection))
             addpos = fitnextaddr
             totalused += fitsection[0]
 #            print "    Adding %s (size %d align %d) pos=%x avail=%d" % (
@@ -135,150 +141,166 @@ def doLayout16(sections, outname):
     firstfixed = fixedsections[0][0]
 
     # Report stats
-    total = MAXPOS-firstfixed
+    total = BUILD_BIOS_SIZE-firstfixed
     slack = total - totalused
     print ("Fixed space: 0x%x-0x%x  total: %d  slack: %d"
            "  Percent slack: %.1f%%" % (
-            firstfixed, MAXPOS, total, slack,
+            firstfixed, BUILD_BIOS_SIZE, total, slack,
             (float(slack) / total) * 100.0))
 
-    # Find start positions
-    text16_start = getSectionsStart(textsections, firstfixed)
-    data16_start = getSectionsStart(rodatasections + datasections, text16_start)
-
-    # Write header and regular sections
-    output = open(outname, 'wb')
-    output.write(COMMONHEADER + """
-        data16_start = 0x%x ;
-        .data16 data16_start : {
-""" % data16_start)
-    outSections(output, datasections)
-    output.write("code16_rodata = . ;\n")
-    outSections(output, rodatasections)
-    output.write("""
-        }
-
-        text16_start = 0x%x ;
-        .text16 text16_start : {
-""" % text16_start)
-    outSections(output, textsections)
-
-    # Write fixed sections
-    for addr, section, extrasections in fixedsections:
-        name = section[2]
-        output.write(". = ( 0x%x - text16_start ) ;\n" % (addr,))
-        output.write("*(%s)\n" % (name,))
-        for extrasection in extrasections:
-            output.write("*(%s)\n" % (extrasection[2],))
-
-    # Write trailer
-    output.write("""
-                text16_end = ABSOLUTE(.) ;
-        }
-
-        /* Discard regular data sections to force a link error if
-         * 16bit code attempts to access data not marked with VAR16
-         */
-        /DISCARD/ : { *(.text*) *(.rodata*) *(.data*) *(.bss*) *(COMMON) }
-""" + COMMONTRAILER)
-
-    return data16_start
+    return fixedsections + extrasections, firstfixed
+
+def doLayout(sections16, sections32seg, sections32flat):
+    # Determine 16bit positions
+    textsections = getSectionsPrefix(sections16, '.text.')
+    rodatasections = (getSectionsPrefix(sections16, '.rodata.str1.1')
+                      + getSectionsPrefix(sections16, '.rodata.__func__.'))
+    datasections = getSectionsPrefix(sections16, '.data16.')
+    fixedsections = getSectionsPrefix(sections16, '.fixedaddr.')
+
+    locs16fixed, firstfixed = fitSections(fixedsections, textsections)
+    prunesections = [i[1] for i in locs16fixed]
+    remsections = [i for i in textsections+rodatasections+datasections
+                   if i not in prunesections]
+    locs16, code16_start = getSectionsStart(remsections, firstfixed)
+    locs16 = locs16 + locs16fixed
+    locs16.sort()
+
+    # Determine 32seg positions
+    textsections = getSectionsPrefix(sections32seg, '.text.')
+    rodatasections = (getSectionsPrefix(sections32seg, '.rodata.str1.1')
+                      + getSectionsPrefix(sections32seg, '.rodata.__func__.'))
+    datasections = getSectionsPrefix(sections32seg, '.data32seg.')
+
+    locs32seg, code32seg_start = getSectionsStart(
+        textsections + rodatasections + datasections, code16_start)
+
+    # Determine 32flat positions
+    textsections = getSectionsPrefix(sections32flat, '.text.')
+    rodatasections = getSectionsPrefix(sections32flat, '.rodata')
+    datasections = getSectionsPrefix(sections32flat, '.data.')
+    bsssections = getSectionsPrefix(sections32flat, '.bss.')
+
+    locs32flat, code32flat_start = getSectionsStart(
+        textsections + rodatasections + datasections + bsssections
+        , code32seg_start + BUILD_BIOS_ADDR, 16)
+
+    # Print statistics
+    size16 = BUILD_BIOS_SIZE - code16_start
+    size32seg = code16_start - code32seg_start
+    size32flat = code32seg_start + BUILD_BIOS_ADDR - code32flat_start
+    print "16bit size:           %d" % size16
+    print "32bit segmented size: %d" % size32seg
+    print "32bit flat size:      %d" % size32flat
+
+    return locs16, locs32seg, locs32flat
 
 
 ######################################################################
-# 32bit section outputting
+# Linker script output
 ######################################################################
 
-# Return the subset of sections with a given name prefix
-def getSectionsPrefix(sections, prefix):
-    lp = len(prefix)
-    out = []
-    for size, align, name in sections:
-        if name[:lp] == prefix:
-            out.append((size, align, name))
+# Write LD script includes for the given cross references
+def outXRefs(xrefs, finallocs, delta=0):
+    out = ""
+    for symbol, (fileid, section, addr) in xrefs.items():
+        if fileid < 2:
+            addr += delta
+        out += "%s = 0x%x ;\n" % (symbol, finallocs[(fileid, section)] + addr)
+    return out
+
+# Write LD script includes for the given sections using relative offsets
+def outRelSections(locs, startsym):
+    out = ""
+    for addr, sectioninfo in locs:
+        size, align, name = sectioninfo
+        out += ". = ( 0x%x - %s ) ;\n" % (addr, startsym)
+        if name == '.rodata.str1.1':
+            out += "_rodata = . ;\n"
+        out += "*(%s)\n" % (name,)
     return out
 
 # Layout the 32bit segmented code.  This places the code as high as possible.
-def doLayout32seg(sections, outname, endat):
-    # Find sections to output
-    textsections = getSectionsPrefix(sections, '.text.')
-    rodatasections = (getSectionsPrefix(sections, '.rodata.str1.1')
-                      + getSectionsPrefix(sections, '.rodata.__func__.'))
-    datasections = getSectionsPrefix(sections, '.data32seg.')
-    startat = getSectionsStart(
-        textsections + rodatasections + datasections, endat)
-
-    # Write sections
-    output = open(outname, 'wb')
-    output.write(COMMONHEADER + """
-        code32seg_start = 0x%x ;
-        .text32seg code32seg_start : {
-                freespace_end = . ;
-""" % startat)
-
-    outSections(output, textsections)
-    output.write("code32seg_rodata = . ;\n")
-    outSections(output, rodatasections)
-    outSections(output, datasections)
-
-    output.write("""
-                code32seg_end = ABSOLUTE(.) ;
-        }
-        /DISCARD/ : { *(.text*) *(.rodata*) *(.data*) *(.bss*) *(COMMON) }
-""" + COMMONTRAILER)
-    return startat
-
-# Layout the 32bit flat code.  This places the code as high as possible.
-def doLayout32flat(sections, outname, endat):
-    endat += 0xf0000
-    # Find sections to output
-    textsections = getSectionsPrefix(sections, '.text.')
-    rodatasections = getSectionsPrefix(sections, '.rodata')
-    datasections = getSectionsPrefix(sections, '.data.')
-    bsssections = getSectionsPrefix(sections, '.bss.')
-    startat = getSectionsStart(
-        textsections + rodatasections + datasections + bsssections, endat, 512)
-
-    # Write sections
-    output = open(outname, 'wb')
-    output.write(COMMONHEADER + """
-        code32flat_start = 0x%x ;
-        .text32flat code32flat_start : {
-""" % startat)
-
-    outSections(output, textsections)
-    output.write("code32_rodata = . ;\n")
-    outSections(output, rodatasections)
-    outSections(output, datasections)
-    outSections(output, bsssections)
-
-    output.write("""
-                freespace_start = . ;
-                code32flat_end = ABSOLUTE(.) ;
-        }
-""" + COMMONTRAILER)
-    return startat
+def writeLinkerScripts(locs16, locs32seg, locs32flat
+                       , xref16, xref32seg, xref32flat
+                       , out16, out32seg, out32flat):
+    # Index to final location for each section
+    # finallocs[(fileid, section)] = addr
+    finallocs = {}
+    for fileid, locs in ((0, locs16), (1, locs32seg), (2, locs32flat)):
+        for addr, sectioninfo in locs:
+            finallocs[(fileid, sectioninfo[2])] = addr
+
+    # Write 16bit linker script
+    code16_start = locs16[0][0]
+    output = open(out16, 'wb')
+    output.write(COMMONHEADER + outXRefs(xref16, finallocs) + """
+    code16_start = 0x%x ;
+    .text16 code16_start : {
+""" % (code16_start)
+                 + outRelSections(locs16, 'code16_start')
+                 + """
+    }
+"""
+                 + COMMONTRAILER)
+    output.close()
+
+    # Write 32seg linker script
+    code32seg_start = code16_start
+    if locs32seg:
+        code32seg_start = locs32seg[0][0]
+    output = open(out32seg, 'wb')
+    output.write(COMMONHEADER + outXRefs(xref32seg, finallocs) + """
+    code32seg_start = 0x%x ;
+    .text32seg code32seg_start : {
+""" % (code32seg_start)
+                 + outRelSections(locs32seg, 'code32seg_start')
+                 + """
+    }
+"""
+                 + COMMONTRAILER)
+    output.close()
+
+    # Write 32flat linker script
+    output = open(out32flat, 'wb')
+    output.write(COMMONHEADER
+                 + outXRefs(xref32flat, finallocs, BUILD_BIOS_ADDR) + """
+    code32flat_start = 0x%x ;
+    .text code32flat_start : {
+""" % (locs32flat[0][0])
+                 + outRelSections(locs32flat, 'code32flat_start')
+                 + """
+        . = ( 0x%x - code32flat_start ) ;
+        *(.text32seg)
+        . = ( 0x%x - code32flat_start ) ;
+        *(.text16)
+        code32flat_end = ABSOLUTE(.) ;
+    } :text
+""" % (code32seg_start + BUILD_BIOS_ADDR, code16_start + BUILD_BIOS_ADDR)
+                 + COMMONTRAILER
+                 + """
+ENTRY(post32)
+PHDRS
+{
+        text PT_LOAD AT ( code32flat_start ) ;
+}
+""")
+    output.close()
 
 
 ######################################################################
 # Section garbage collection
 ######################################################################
 
-def getSectionsList(info, names):
-    out = []
-    for i in info[0]:
-        size, align, section = i
-        if section not in names:
-#            print "gc", section
-            continue
-        out.append(i)
-    return out
-
 # Find and keep the section associated with a symbol (if available).
-def keepsymbol(symbol, infos, pos):
+def keepsymbol(symbol, infos, pos, callerpos=None):
     addr, section = infos[pos][1].get(symbol, (None, None))
     if section is None or '*' in section or section[:9] == '.discard.':
         return -1
+    if callerpos is not None and symbol not in infos[callerpos][4]:
+        # This symbol reference is a cross section reference (an xref).
+        # xref[symbol] = (fileid, section, addr)
+        infos[callerpos][4][symbol] = (pos, section, addr)
     keepsection(section, infos, pos)
     return 0
 
@@ -298,29 +320,34 @@ def keepsection(name, infos, pos=0):
         if not ret:
             continue
         # Not in primary sections - it may be a cross 16/32 reference
-        ret = keepsymbol(symbol, infos, (pos+1)%3)
+        ret = keepsymbol(symbol, infos, (pos+1)%3, pos)
         if not ret:
             continue
-        ret = keepsymbol(symbol, infos, (pos+2)%3)
+        ret = keepsymbol(symbol, infos, (pos+2)%3, pos)
         if not ret:
             continue
 
+# Return a list of kept sections.
+def getSectionsList(sections, names):
+    return [i for i in sections if i[2] in names]
+
 # Determine which sections are actually referenced and need to be
 # placed into the output file.
 def gc(info16, info32seg, info32flat):
-    # infos = ((sections, symbols, relocs, keep sections), ...)
-    infos = ((info16[0], info16[1], info16[2], []),
-             (info32seg[0], info32seg[1], info32seg[2], []),
-             (info32flat[0], info32flat[1], info32flat[2], []))
+    # infos = ((sections, symbols, relocs, keep sections, xrefs), ...)
+    infos = ((info16[0], info16[1], info16[2], [], {}),
+             (info32seg[0], info32seg[1], info32seg[2], [], {}),
+             (info32flat[0], info32flat[1], info32flat[2], [], {}))
     # Start by keeping sections that are globally visible.
     for size, align, section in info16[0]:
         if section[:11] == '.fixedaddr.' or '.export.' in section:
             keepsection(section, infos)
+    keepsymbol('post32', infos, 0, 2)
     # Return sections found.
-    sections16 = getSectionsList(info16, infos[0][3])
-    sections32seg = getSectionsList(info32seg, infos[1][3])
-    sections32flat = getSectionsList(info32flat, infos[2][3])
-    return sections16, sections32seg, sections32flat
+    keep16 = getSectionsList(info16[0], infos[0][3]), infos[0][4]
+    keep32seg = getSectionsList(info32seg[0], infos[1][3]), infos[1][4]
+    keep32flat = getSectionsList(info32flat[0], infos[2][3]), infos[2][4]
+    return keep16, keep32seg, keep32flat
 
 
 ######################################################################
@@ -331,7 +358,7 @@ def gc(info16, info32seg, info32flat):
 def parseObjDump(file):
     # sections = [(size, align, section), ...]
     sections = []
-    # symbols[symbol] = section
+    # symbols[symbol] = (addr, section)
     symbols = {}
     # relocs[section] = [symbol, ...]
     relocs = {}
@@ -361,8 +388,8 @@ def parseObjDump(file):
             continue
         if state == 'symbol':
             try:
-                section, off, symbol = line[17:].split()
-                off = int(off, 16)
+                section, size, symbol = line[17:].split()
+                size = int(size, 16)
                 addr = int(line[:8], 16)
                 symbols[symbol] = addr, section
             except:
@@ -381,19 +408,29 @@ def main():
     # Get output name
     in16, in32seg, in32flat, out16, out32seg, out32flat = sys.argv[1:]
 
+    # Read in the objdump information
     infile16 = open(in16, 'rb')
     infile32seg = open(in32seg, 'rb')
     infile32flat = open(in32flat, 'rb')
 
+    # infoX = (sections, symbols, relocs)
     info16 = parseObjDump(infile16)
     info32seg = parseObjDump(infile32seg)
     info32flat = parseObjDump(infile32flat)
 
-    sections16, sections32seg, sections32flat = gc(info16, info32seg, info32flat)
+    # Figure out which sections to keep.
+    # keepX = (sections, xrefs)
+    keep16, keep32seg, keep32flat = gc(info16, info32seg, info32flat)
+
+    # Determine the final memory locations of each kept section.
+    # locsX = [(addr, sectioninfo), ...]
+    locs16, locs32seg, locs32flat = doLayout(
+        keep16[0], keep32seg[0], keep32flat[0])
 
-    start16 = doLayout16(sections16, out16)
-    start32seg = doLayout32seg(sections32seg, out32seg, start16)
-    doLayout32flat(sections32flat, out32flat, start32seg)
+    # Write out linker script files.
+    writeLinkerScripts(locs16, locs32seg, locs32flat
+                       , keep16[1], keep32seg[1], keep32flat[1]
+                       , out16, out32seg, out32flat)
 
 if __name__ == '__main__':
     main()
-- 
1.6.6.1




More information about the SeaBIOS mailing list