return firstfixed
# Return the subset of sections with a given name prefix
-def getSectionsPrefix(sections, fileid, prefix):
+def getSectionsPrefix(sections, category, prefix):
return [section for section in sections
- if section.fileid == fileid and section.name.startswith(prefix)]
+ if section.category == category and section.name.startswith(prefix)]
def doLayout(sections):
# Determine 16bit positions
textsections + rodatasections + datasections + bsssections
, code32seg_start + BUILD_BIOS_ADDR, 16)
+ # Determine 32flat init positions
+ textsections = getSectionsPrefix(sections, '32init', '.text.')
+ rodatasections = getSectionsPrefix(sections, '32init', '.rodata')
+ datasections = getSectionsPrefix(sections, '32init', '.data.')
+ bsssections = getSectionsPrefix(sections, '32init', '.bss.')
+
+ code32init_start = setSectionsStart(
+ textsections + rodatasections + datasections + bsssections
+ , code32flat_start, 16)
+
# Print statistics
size16 = BUILD_BIOS_SIZE - code16_start
size32seg = code16_start - code32seg_start
size32flat = code32seg_start + BUILD_BIOS_ADDR - code32flat_start
+ size32init = code32flat_start - code32init_start
print "16bit size: %d" % size16
print "32bit segmented size: %d" % size32seg
print "32bit flat size: %d" % size32flat
+ print "32bit flat init size: %d" % size32init
######################################################################
for reloc in section.relocs:
symbol = reloc.symbol
if (symbol.section is None
- or symbol.section.fileid == section.fileid
- or symbol.name in xrefs):
+ or (symbol.section.fileid == section.fileid
+ and symbol.name == reloc.symbolname)
+ or reloc.symbolname in xrefs):
continue
- xrefs[symbol.name] = 1
+ xrefs[reloc.symbolname] = 1
addr = symbol.section.finalloc + symbol.offset
if (section.fileid == '32flat'
and symbol.section.fileid in ('16', '32seg')):
addr += BUILD_BIOS_ADDR
- out += "%s = 0x%x ;\n" % (symbol.name, addr)
+ out += "%s = 0x%x ;\n" % (reloc.symbolname, addr)
return out
# Write LD script includes for the given sections using relative offsets
return sections, pos
# Layout the 32bit segmented code. This places the code as high as possible.
-def writeLinkerScripts(sections, entrysym, out16, out32seg, out32flat):
+def writeLinkerScripts(sections, entrysym, genreloc, out16, out32seg, out32flat):
# Write 16bit linker script
sections16, code16_start = getSectionsFile(sections, '16')
output = open(out16, 'wb')
# Write 32flat linker script
sections32flat, code32flat_start = getSectionsFile(
sections, '32flat', code32seg_start)
+ relocstr = ""
+ relocminalign = 0
+ if genreloc:
+ # Generate relocations
+ relocstr, size, relocminalign = genRelocs(sections)
+ code32flat_start -= size
output = open(out32flat, 'wb')
output.write(COMMONHEADER
+ outXRefs(sections32flat) + """
%s = 0x%x ;
+ _reloc_min_align = 0x%x ;
code32flat_start = 0x%x ;
.text code32flat_start : {
""" % (entrysym.name,
entrysym.section.finalloc + entrysym.offset + BUILD_BIOS_ADDR,
- code32flat_start)
+ relocminalign, code32flat_start)
+ + relocstr
+ + """
+ code32init_start = ABSOLUTE(.) ;
+"""
+ + outRelSections(getSectionsPrefix(sections32flat, '32init', '')
+ , 'code32flat_start')
+ + """
+ code32init_end = ABSOLUTE(.) ;
+"""
+ outRelSections(getSectionsPrefix(sections32flat, '32flat', '')
, 'code32flat_start')
+ """
output.close()
+######################################################################
+# Detection of init code
+######################################################################
+
+# Determine init section relocations
+def genRelocs(sections):
+ absrelocs = []
+ relrelocs = []
+ initrelocs = []
+ minalign = 16
+ for section in sections:
+ if section.category == '32init' and section.align > minalign:
+ minalign = section.align
+ for reloc in section.relocs:
+ symbol = reloc.symbol
+ if symbol.section is None:
+ continue
+ relocpos = section.finalloc + reloc.offset
+ if (reloc.type == 'R_386_32' and section.category == '32init'
+ and symbol.section.category == '32init'):
+ # Absolute relocation
+ absrelocs.append(relocpos)
+ elif (reloc.type == 'R_386_PC32' and section.category == '32init'
+ and symbol.section.category != '32init'):
+ # Relative relocation
+ relrelocs.append(relocpos)
+ elif (section.category != '32init'
+ and symbol.section.category == '32init'):
+ # Relocation to the init section
+ if section.fileid in ('16', '32seg'):
+ relocpos += BUILD_BIOS_ADDR
+ initrelocs.append(relocpos)
+ absrelocs.sort()
+ relrelocs.sort()
+ initrelocs.sort()
+ out = (" _reloc_abs_start = ABSOLUTE(.) ;\n"
+ + "".join(["LONG(0x%x - code32init_start)\n" % (pos,)
+ for pos in absrelocs])
+ + " _reloc_abs_end = ABSOLUTE(.) ;\n"
+ + " _reloc_rel_start = ABSOLUTE(.) ;\n"
+ + "".join(["LONG(0x%x - code32init_start)\n" % (pos,)
+ for pos in relrelocs])
+ + " _reloc_rel_end = ABSOLUTE(.) ;\n"
+ + " _reloc_init_start = ABSOLUTE(.) ;\n"
+ + "".join(["LONG(0x%x - code32flat_start)\n" % (pos,)
+ for pos in initrelocs])
+ + " _reloc_init_end = ABSOLUTE(.) ;\n")
+ return out, len(absrelocs + relrelocs + initrelocs) * 4, minalign
+
+def markRuntime(section, sections):
+ if (section is None or not section.keep or section.category is not None
+ or '.init.' in section.name or section.fileid != '32flat'):
+ return
+ section.category = '32flat'
+ # Recursively mark all sections this section points to
+ for reloc in section.relocs:
+ markRuntime(reloc.symbol.section, sections)
+
+def findInit(sections):
+ # Recursively find and mark all "runtime" sections.
+ for section in sections:
+ if '.runtime.' in section.name or '.export.' in section.name:
+ markRuntime(section, sections)
+ for section in sections:
+ if section.category is not None:
+ continue
+ if section.fileid == '32flat':
+ section.category = '32init'
+ else:
+ section.category = section.fileid
+
+
######################################################################
# Section garbage collection
######################################################################
+CFUNCPREFIX = [('_cfunc16_', 0), ('_cfunc32seg_', 1), ('_cfunc32flat_', 2)]
+
# Find and keep the section associated with a symbol (if available).
-def keepsymbol(reloc, infos, pos):
- symbolname = reloc.symbol.name
+def keepsymbol(reloc, infos, pos, isxref):
+ symbolname = reloc.symbolname
+ mustbecfunc = 0
+ for symprefix, needpos in CFUNCPREFIX:
+ if symbolname.startswith(symprefix):
+ if needpos != pos:
+ return -1
+ symbolname = symbolname[len(symprefix):]
+ mustbecfunc = 1
+ break
symbol = infos[pos][1].get(symbolname)
if (symbol is None or symbol.section is None
or symbol.section.name.startswith('.discard.')):
return -1
+ isdestcfunc = (symbol.section.name.startswith('.text.')
+ and not symbol.section.name.startswith('.text.asm.'))
+ if ((mustbecfunc and not isdestcfunc)
+ or (not mustbecfunc and isdestcfunc and isxref)):
+ return -1
+
reloc.symbol = symbol
keepsection(symbol.section, infos, pos)
return 0
section.keep = 1
# Keep all sections that this section points to
for reloc in section.relocs:
- ret = keepsymbol(reloc, infos, pos)
+ ret = keepsymbol(reloc, infos, pos, 0)
if not ret:
continue
# Not in primary sections - it may be a cross 16/32 reference
- ret = keepsymbol(reloc, infos, (pos+1)%3)
+ ret = keepsymbol(reloc, infos, (pos+1)%3, 1)
if not ret:
continue
- ret = keepsymbol(reloc, infos, (pos+2)%3)
+ ret = keepsymbol(reloc, infos, (pos+2)%3, 1)
if not ret:
continue
class Section:
name = size = alignment = fileid = relocs = None
- finalloc = keep = None
+ finalloc = category = keep = None
class Reloc:
- offset = type = symbol = None
+ offset = type = symbolname = symbol = None
class Symbol:
name = offset = section = None
reloc = Reloc()
reloc.offset = int(off, 16)
reloc.type = type
- reloc.symbol = symbols[symbolname]
+ reloc.symbolname = symbolname
+ reloc.symbol = symbols.get(symbolname)
+ if reloc.symbol is None:
+ # Some binutils (2.20.1) give section name instead
+ # of a symbol - create a dummy symbol.
+ reloc.symbol = symbol = Symbol()
+ symbol.size = 0
+ symbol.offset = 0
+ symbol.name = symbolname
+ symbol.section = sectionmap.get(symbolname)
+ symbols[symbolname] = symbol
relocsection.relocs.append(reloc)
except ValueError:
pass
# Figure out which sections to keep.
sections = gc(info16, info32seg, info32flat)
+ # Separate 32bit flat into runtime and init parts
+ findInit(sections)
+
# Determine the final memory locations of each kept section.
- # locsX = [(addr, sectioninfo), ...]
doLayout(sections)
# Write out linker script files.
- entrysym = info16[1]['post32']
- writeLinkerScripts(sections, entrysym, out16, out32seg, out32flat)
+ entrysym = info16[1]['entry_elf']
+ genreloc = '_reloc_abs_start' in info32flat[1]
+ writeLinkerScripts(sections, entrysym, genreloc, out16, out32seg, out32flat)
if __name__ == '__main__':
main()