-mpreferred-stack-boundary=2 -mrtd -freg-struct-return \
-ffreestanding -fwhole-program -fomit-frame-pointer \
-fno-delete-null-pointer-checks -Wno-strict-aliasing \
+ -ffunction-sections -fdata-sections \
-minline-all-stringops
COMMONCFLAGS += $(call cc-option,$(CC),-nopie,)
COMMONCFLAGS += $(call cc-option,$(CC),-fno-stack-protector,)
CFLAGS16INC = $(COMMONCFLAGS) -DMODE16=1 -fno-jump-tables -fno-defer-pop \
$(call cc-option,$(CC),-fno-tree-switch-conversion,) \
$(call cc-option,$(CC),--param large-stack-frame=4,)
-CFLAGS16INC += -ffunction-sections -fdata-sections
CFLAGS16 = $(CFLAGS16INC) -g
all: $(OUT) $(OUT)bios.bin
@echo " Linking (no relocs) $@"
$(Q)$(LD) -r -T $(OUT)rombios32.lds $< -o $@
-$(OUT)romlayout.lds: $(OUT)romlayout16.o
+$(OUT)romlayout16.lds $(OUT)romlayout32.lds: $(OUT)ccode32.o $(OUT)romlayout16.o
@echo " Building layout information $@"
- $(Q)$(OBJDUMP) -h $< | ./tools/layoutrom.py $@
+ $(Q)$(OBJDUMP) -thr $(OUT)ccode32.o > $(OUT)ccode32.o.objdump
+ $(Q)$(OBJDUMP) -thr $(OUT)romlayout16.o > $(OUT)romlayout16.o.objdump
+ $(Q)./tools/layoutrom.py $(OUT)romlayout16.o.objdump $(OUT)ccode32.o.objdump $(OUT)romlayout16.lds $(OUT)romlayout32.lds
-$(OUT)layout16.lds: $(OUT)romlayout.lds
+$(OUT)layout16.lds: $(OUT)romlayout16.lds
+$(OUT)rombios32.lds: $(OUT)romlayout32.lds
$(OUT)rom16.o: $(OUT)romlayout16.o $(OUT)rom32.o $(OUT)layout16.lds
@echo " Linking (no relocs) $@"
$(OUT)vgarom.o: $(OUT)vgalayout16.o $(OUT)vgalayout.lds
@echo " Linking $@"
- $(Q)$(LD) -T $(OUT)vgalayout.lds $(OUT)vgalayout16.o -o $@
+ $(Q)$(LD) --gc-sections -T $(OUT)vgalayout.lds $(OUT)vgalayout16.o -o $@
$(OUT)vgabios.bin.raw: $(OUT)vgarom.o
@echo " Extracting binary $@"
#define __VISIBLE __attribute__((externally_visible))
+#define UNIQSEC __FILE__ "." __stringify(__LINE__)
+
+#define __ASM(code) asm(".section .text.asm." UNIQSEC "\n\t" code)
+
#if MODE16 == 1
// Notes a function as externally visible in the 16bit code chunk.
# define VISIBLE16 __VISIBLE
// Notes a function as externally visible in the 32bit code chunk.
# define VISIBLE32
// Designate a variable as (only) visible to 16bit code.
-# define VAR16 __attribute__((section(".data16." __FILE__ "." __stringify(__LINE__))))
+# define VAR16 __section(".data16." UNIQSEC)
// Designate a variable as visible to both 32bit and 16bit code.
# define VAR16_32 VAR16 __VISIBLE
+// Designate a variable visible externally.
+# define VAR16EXPORT __section(".data16.export." UNIQSEC) __VISIBLE
// Designate a variable at a specific 16bit address
-# define VAR16FIXED(addr) __aligned(1) __VISIBLE __attribute__((section(".fixedaddr." __stringify(addr))))
+# define VAR16FIXED(addr) __aligned(1) __VISIBLE __section(".fixedaddr." __stringify(addr))
// Designate top-level assembler as 16bit only.
-# define ASM16(code) asm(".section .text.asm." __FILE__ "." __stringify(__LINE__) "\n\t" code)
+# define ASM16(code) __ASM(code)
+# define ASM32(code)
#else
# define VISIBLE16
# define VISIBLE32 __VISIBLE
-# define VAR16 __attribute__((section(".discard.var16")))
-# define VAR16_32 VAR16 __VISIBLE __attribute__((weak))
+# define VAR16 __section(".discard.var16." UNIQSEC)
+# define VAR16_32 VAR16 __VISIBLE __weak
+# define VAR16EXPORT VAR16_32
# define VAR16FIXED(addr) VAR16_32
# define ASM16(code)
+# define ASM32(code) __ASM(code)
#endif
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#define NULL ((void *)0)
+#define __weak __attribute__((weak))
+#define __section(S) __attribute__((section(S)))
+
#define PACKED __attribute__((packed))
#define __aligned(x) __attribute__((aligned(x)))
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 = []
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:
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("""
""")
+######################################################################
+# 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()