aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorKevin O'Connor <kevin@koconnor.net>2009-06-10 21:56:01 -0400
committerKevin O'Connor <kevin@koconnor.net>2009-06-10 21:56:01 -0400
commitc0693941fdb5118164a8161316fdf8e9ebb499d2 (patch)
tree4c2ed73a666bed4a8742453262c5899f77f7bfde /tools
parent0b04b78972939b8bf00c6b075b3592ea6b7dd643 (diff)
downloadseabios-c0693941fdb5118164a8161316fdf8e9ebb499d2.tar.gz
Do garbage collection of unused sections.
Implement -ffunction-sections and -fdata-sections in both 32bit and 16bit code. Make sure all sections have unique names (even asm and discarded sections). Enhance tools/layoutrom.py script to find all sections reachable from exported 16bit code - prune all other sections. Mark sections with "export" if they can be visible outside of code - these sections wont be dropped when pruning unused sections.
Diffstat (limited to 'tools')
-rwxr-xr-xtools/layoutrom.py168
1 files changed, 145 insertions, 23 deletions
diff --git a/tools/layoutrom.py b/tools/layoutrom.py
index 319111b6..7b2841f6 100755
--- a/tools/layoutrom.py
+++ b/tools/layoutrom.py
@@ -7,34 +7,19 @@
import sys
-def main():
- # Get output name
- outname = sys.argv[1]
-
- # Read in section names and sizes
- # sections = [(size, align, name), ...]
- sections = []
- for line in sys.stdin.readlines():
- try:
- idx, name, size, vma, lma, fileoff, align = line.split()
- if align[:3] != '2**':
- continue
- sections.append((int(size, 16), 2**int(align[3:]), name))
- except:
- pass
-
- doLayout(sections, outname)
def alignpos(pos, alignbytes):
mask = alignbytes - 1
return (pos + mask) & ~mask
-MAXPOS = 0x10000
-def outsection(file, name):
- file.write("*(%s)\n" % (name,))
+######################################################################
+# 16bit fixed address section fitting
+######################################################################
+
+MAXPOS = 0x10000
-def doLayout(sections, outname):
+def doLayout16(sections, outname):
textsections = []
rodatasections = []
datasections = []
@@ -151,7 +136,7 @@ def doLayout(sections, outname):
name = section[2]
if name == rodatasections[0][2]:
output.write("code16_rodata = . ;\n")
- outsection(output, name)
+ output.write("*(%s)\n" % (name,))
# Write fixed sections
for addr, section, extrasections in fixedsections:
@@ -159,7 +144,7 @@ def doLayout(sections, outname):
output.write(". = ( 0x%x - code16_start ) ;\n" % (addr,))
output.write("*(%s)\n" % (name,))
for extrasection in extrasections:
- outsection(output, extrasection[2])
+ output.write("*(%s)\n" % (extrasection[2],))
# Write trailer
output.write("""
@@ -168,5 +153,142 @@ def doLayout(sections, outname):
""")
+######################################################################
+# 32bit section outputting
+######################################################################
+
+def outsections(file, sections, prefix):
+ lp = len(prefix)
+ for size, align, name in sections:
+ if name[:lp] == prefix:
+ file.write("*(%s)\n" % (name,))
+
+def doLayout32(sections, outname):
+ output = open(outname, 'wb')
+ outsections(output, sections, '.text.')
+ output.write("code32_rodata = . ;\n")
+ outsections(output, sections, '.rodata')
+ outsections(output, sections, '.data.')
+ outsections(output, sections, '.bss.')
+
+
+######################################################################
+# Section garbage collection
+######################################################################
+
+def keepsection(name, pri, alt):
+ if name in pri[3]:
+ # Already kept - nothing to do.
+ return
+ pri[3].append(name)
+ relocs = pri[2].get(name)
+ if relocs is None:
+ return
+ # Keep all sections that this section points to
+ for symbol in relocs:
+ section = pri[1].get(symbol)
+ if section is not None and section[:9] != '.discard.':
+ keepsection(section, pri, alt)
+ continue
+ # Not in primary sections - it may be a cross 16/32 reference
+ section = alt[1].get(symbol)
+ if section is not None:
+ keepsection(section, alt, pri)
+
+def gc(info16, info32):
+ # pri = (sections, symbols, relocs, keep sections)
+ pri = (info16[0], info16[1], info16[2], [])
+ alt = (info32[0], info32[1], info32[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, pri, alt)
+ # Return sections found.
+ sections16 = []
+ for info in info16[0]:
+ size, align, section = info
+ if section not in pri[3]:
+# print "gc16", section
+ continue
+ sections16.append(info)
+ sections32 = []
+ for info in info32[0]:
+ size, align, section = info
+ if section not in alt[3]:
+# print "gc32", section
+ continue
+ sections32.append(info)
+ return sections16, sections32
+
+
+######################################################################
+# Startup and input parsing
+######################################################################
+
+# Read in output from objdump
+def parseObjDump(file):
+ # sections = [(size, align, section), ...]
+ sections = []
+ # symbols[symbol] = section
+ symbols = {}
+ # relocs[section] = [symbol, ...]
+ relocs = {}
+
+ state = None
+ for line in file.readlines():
+ line = line.rstrip()
+ if line == 'Sections:':
+ state = 'section'
+ continue
+ if line == 'SYMBOL TABLE:':
+ state = 'symbol'
+ continue
+ if line[:24] == 'RELOCATION RECORDS FOR [':
+ state = 'reloc'
+ relocsection = line[24:-2]
+ continue
+
+ if state == 'section':
+ try:
+ idx, name, size, vma, lma, fileoff, align = line.split()
+ if align[:3] != '2**':
+ continue
+ sections.append((int(size, 16), 2**int(align[3:]), name))
+ except:
+ pass
+ continue
+ if state == 'symbol':
+ try:
+ section, off, symbol = line[17:].split()
+ off = int(off, 16)
+ if '*' not in section:
+ symbols[symbol] = section
+ except:
+ pass
+ continue
+ if state == 'reloc':
+ try:
+ off, type, symbol = line.split()
+ off = int(off, 16)
+ relocs.setdefault(relocsection, []).append(symbol)
+ except:
+ pass
+ return sections, symbols, relocs
+
+def main():
+ # Get output name
+ in16, in32, out16, out32 = sys.argv[1:]
+
+ infile16 = open(in16, 'rb')
+ infile32 = open(in32, 'rb')
+
+ info16 = parseObjDump(infile16)
+ info32 = parseObjDump(infile32)
+
+ sections16, sections32 = gc(info16, info32)
+
+ doLayout16(sections16, out16)
+ doLayout32(sections32, out32)
+
if __name__ == '__main__':
main()