blob: 319111b6b9b101b7880e3459cbf231066b194aa5 [file] [log] [blame]
Kevin O'Connor202024a2009-01-17 10:41:28 -05001#!/usr/bin/env python
2# Script to arrange sections to ensure fixed offsets.
3#
4# Copyright (C) 2008 Kevin O'Connor <kevin@koconnor.net>
5#
6# This file may be distributed under the terms of the GNU GPLv3 license.
7
8import sys
9
10def main():
Kevin O'Connor711ddc62009-01-17 15:17:34 -050011 # Get output name
12 outname = sys.argv[1]
Kevin O'Connor202024a2009-01-17 10:41:28 -050013
Kevin O'Connor711ddc62009-01-17 15:17:34 -050014 # Read in section names and sizes
15 # sections = [(size, align, name), ...]
Kevin O'Connor202024a2009-01-17 10:41:28 -050016 sections = []
17 for line in sys.stdin.readlines():
18 try:
19 idx, name, size, vma, lma, fileoff, align = line.split()
20 if align[:3] != '2**':
21 continue
Kevin O'Connor711ddc62009-01-17 15:17:34 -050022 sections.append((int(size, 16), 2**int(align[3:]), name))
Kevin O'Connor202024a2009-01-17 10:41:28 -050023 except:
24 pass
25
Kevin O'Connor711ddc62009-01-17 15:17:34 -050026 doLayout(sections, outname)
27
28def alignpos(pos, alignbytes):
29 mask = alignbytes - 1
30 return (pos + mask) & ~mask
31
Kevin O'Connordb802ad2009-01-17 19:35:10 -050032MAXPOS = 0x10000
33
Kevin O'Connorb1a0d3a2009-05-23 17:49:44 -040034def outsection(file, name):
35 file.write("*(%s)\n" % (name,))
36
Kevin O'Connor711ddc62009-01-17 15:17:34 -050037def doLayout(sections, outname):
Kevin O'Connor202024a2009-01-17 10:41:28 -050038 textsections = []
39 rodatasections = []
40 datasections = []
Kevin O'Connor711ddc62009-01-17 15:17:34 -050041 # fixedsections = [(addr, sectioninfo, extasectionslist), ...]
42 fixedsections = []
43 # canrelocate = [(sectioninfo, list), ...]
44 canrelocate = []
Kevin O'Connor202024a2009-01-17 10:41:28 -050045
46 # Find desired sections.
47 for section in sections:
Kevin O'Connor711ddc62009-01-17 15:17:34 -050048 size, align, name = section
Kevin O'Connor202024a2009-01-17 10:41:28 -050049 if name[:11] == '.fixedaddr.':
50 addr = int(name[11:], 16)
Kevin O'Connor711ddc62009-01-17 15:17:34 -050051 fixedsections.append((addr, section, []))
52 if align != 1:
53 print "Error: Fixed section %s has non-zero alignment (%d)" % (
54 name, align)
55 sys.exit(1)
Kevin O'Connor202024a2009-01-17 10:41:28 -050056 if name[:6] == '.text.':
57 textsections.append(section)
Kevin O'Connor711ddc62009-01-17 15:17:34 -050058 canrelocate.append((section, textsections))
Kevin O'Connor202024a2009-01-17 10:41:28 -050059 if name[:17] == '.rodata.__func__.' or name == '.rodata.str1.1':
60 rodatasections.append(section)
Kevin O'Connor711ddc62009-01-17 15:17:34 -050061 #canrelocate.append((section, rodatasections))
Kevin O'Connor202024a2009-01-17 10:41:28 -050062 if name[:8] == '.data16.':
63 datasections.append(section)
Kevin O'Connor711ddc62009-01-17 15:17:34 -050064 #canrelocate.append((section, datasections))
65
66 # Find freespace in fixed address area
67 fixedsections.sort()
68 # fixedAddr = [(freespace, sectioninfo), ...]
69 fixedAddr = []
70 for i in range(len(fixedsections)):
71 fixedsectioninfo = fixedsections[i]
72 addr, section, extrasectionslist = fixedsectioninfo
73 if i == len(fixedsections) - 1:
Kevin O'Connordb802ad2009-01-17 19:35:10 -050074 nextaddr = MAXPOS
Kevin O'Connor711ddc62009-01-17 15:17:34 -050075 else:
76 nextaddr = fixedsections[i+1][0]
77 avail = nextaddr - addr - section[0]
78 fixedAddr.append((avail, fixedsectioninfo))
79
80 # Attempt to fit other sections into fixed area
81 fixedAddr.sort()
82 canrelocate.sort()
Kevin O'Connor76f0bed2009-01-19 13:00:42 -050083 totalused = 0
Kevin O'Connor711ddc62009-01-17 15:17:34 -050084 for freespace, fixedsectioninfo in fixedAddr:
85 fixedaddr, fixedsection, extrasections = fixedsectioninfo
86 addpos = fixedaddr + fixedsection[0]
Kevin O'Connor76f0bed2009-01-19 13:00:42 -050087 totalused += fixedsection[0]
Kevin O'Connor711ddc62009-01-17 15:17:34 -050088 nextfixedaddr = addpos + freespace
89# print "Filling section %x uses %d, next=%x, available=%d" % (
90# fixedaddr, fixedsection[0], nextfixedaddr, freespace)
91 while 1:
92 canfit = None
93 for fixedaddrinfo in canrelocate:
94 fitsection, inlist = fixedaddrinfo
Kevin O'Connordb802ad2009-01-17 19:35:10 -050095 fitsize, fitalign, fitname = fitsection
96 if addpos + fitsize > nextfixedaddr:
97 # Can't fit and nothing else will fit.
Kevin O'Connor711ddc62009-01-17 15:17:34 -050098 break
Kevin O'Connordb802ad2009-01-17 19:35:10 -050099 fitnextaddr = alignpos(addpos, fitalign) + fitsize
100# print "Test %s - %x vs %x" % (
101# fitname, fitnextaddr, nextfixedaddr)
102 if fitnextaddr > nextfixedaddr:
103 # This item can't fit.
104 continue
Kevin O'Connor711ddc62009-01-17 15:17:34 -0500105 canfit = (fitnextaddr, fixedaddrinfo)
106 if canfit is None:
107 break
108 # Found a section that can fit.
109 fitnextaddr, fixedaddrinfo = canfit
110 canrelocate.remove(fixedaddrinfo)
111 fitsection, inlist = fixedaddrinfo
112 inlist.remove(fitsection)
113 extrasections.append(fitsection)
114 addpos = fitnextaddr
Kevin O'Connor76f0bed2009-01-19 13:00:42 -0500115 totalused += fitsection[0]
116# print " Adding %s (size %d align %d) pos=%x avail=%d" % (
117# fitsection[2], fitsection[0], fitsection[1]
118# , fitnextaddr, nextfixedaddr - fitnextaddr)
Kevin O'Connordb802ad2009-01-17 19:35:10 -0500119 firstfixed = fixedsections[0][0]
Kevin O'Connorb1a0d3a2009-05-23 17:49:44 -0400120
121 # Find overall start position
122 restalign = 0
123 restspace = 0
124 restsections = []
125 for section in textsections + rodatasections + datasections:
126 size, align, name = section
127 if align > restalign:
128 restalign = align
129 restspace = alignpos(restspace, align) + size
130 restsections.append(section)
131 startrest = (firstfixed - restspace) / restalign * restalign
132
133 # Report stats
Kevin O'Connordb802ad2009-01-17 19:35:10 -0500134 total = MAXPOS-firstfixed
Kevin O'Connorb1a0d3a2009-05-23 17:49:44 -0400135 slack = total - totalused
136 print ("Fixed space: 0x%x-0x%x total: %d slack: %d"
137 " Percent slack: %.1f%%" % (
138 firstfixed, MAXPOS, total, slack,
139 (float(slack) / total) * 100.0))
140
141 # Write header
142 output = open(outname, 'wb')
143 output.write("""
144 .text16 0x%x : {
145 code16_start = ABSOLUTE(.) ;
146 freespace_end = . ;
147""" % startrest)
Kevin O'Connordb802ad2009-01-17 19:35:10 -0500148
Kevin O'Connor202024a2009-01-17 10:41:28 -0500149 # Write regular sections
Kevin O'Connorb1a0d3a2009-05-23 17:49:44 -0400150 for section in restsections:
Kevin O'Connor711ddc62009-01-17 15:17:34 -0500151 name = section[2]
Kevin O'Connorb1a0d3a2009-05-23 17:49:44 -0400152 if name == rodatasections[0][2]:
153 output.write("code16_rodata = . ;\n")
154 outsection(output, name)
Kevin O'Connor202024a2009-01-17 10:41:28 -0500155
156 # Write fixed sections
Kevin O'Connor711ddc62009-01-17 15:17:34 -0500157 for addr, section, extrasections in fixedsections:
158 name = section[2]
159 output.write(". = ( 0x%x - code16_start ) ;\n" % (addr,))
Kevin O'Connor711ddc62009-01-17 15:17:34 -0500160 output.write("*(%s)\n" % (name,))
161 for extrasection in extrasections:
Kevin O'Connorb1a0d3a2009-05-23 17:49:44 -0400162 outsection(output, extrasection[2])
163
164 # Write trailer
165 output.write("""
166 code16_end = ABSOLUTE(.) ;
167 }
168""")
169
Kevin O'Connor202024a2009-01-17 10:41:28 -0500170
171if __name__ == '__main__':
172 main()