diff options
author | Kevin O'Connor <kevin@koconnor.net> | 2009-06-10 21:56:01 -0400 |
---|---|---|
committer | Kevin O'Connor <kevin@koconnor.net> | 2009-06-10 21:56:01 -0400 |
commit | c0693941fdb5118164a8161316fdf8e9ebb499d2 (patch) | |
tree | 4c2ed73a666bed4a8742453262c5899f77f7bfde /tools | |
parent | 0b04b78972939b8bf00c6b075b3592ea6b7dd643 (diff) | |
download | seabios-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-x | tools/layoutrom.py | 168 |
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() |