2 # Script to arrange sections to ensure fixed offsets.
4 # Copyright (C) 2008 Kevin O'Connor <kevin@koconnor.net>
6 # This file may be distributed under the terms of the GNU GPLv3 license.
14 # Read in section names and sizes
15 # sections = [(size, align, name), ...]
17 for line in sys.stdin.readlines():
19 idx, name, size, vma, lma, fileoff, align = line.split()
20 if align[:3] != '2**':
22 sections.append((int(size, 16), 2**int(align[3:]), name))
26 doLayout(sections, outname)
28 def alignpos(pos, alignbytes):
30 return (pos + mask) & ~mask
34 def outsection(file, name):
35 file.write("*(%s)\n" % (name,))
37 def doLayout(sections, outname):
41 # fixedsections = [(addr, sectioninfo, extasectionslist), ...]
43 # canrelocate = [(sectioninfo, list), ...]
46 # Find desired sections.
47 for section in sections:
48 size, align, name = section
49 if name[:11] == '.fixedaddr.':
50 addr = int(name[11:], 16)
51 fixedsections.append((addr, section, []))
53 print "Error: Fixed section %s has non-zero alignment (%d)" % (
56 if name[:6] == '.text.':
57 textsections.append(section)
58 canrelocate.append((section, textsections))
59 if name[:17] == '.rodata.__func__.' or name == '.rodata.str1.1':
60 rodatasections.append(section)
61 #canrelocate.append((section, rodatasections))
62 if name[:8] == '.data16.':
63 datasections.append(section)
64 #canrelocate.append((section, datasections))
66 # Find freespace in fixed address area
68 # fixedAddr = [(freespace, sectioninfo), ...]
70 for i in range(len(fixedsections)):
71 fixedsectioninfo = fixedsections[i]
72 addr, section, extrasectionslist = fixedsectioninfo
73 if i == len(fixedsections) - 1:
76 nextaddr = fixedsections[i+1][0]
77 avail = nextaddr - addr - section[0]
78 fixedAddr.append((avail, fixedsectioninfo))
80 # Attempt to fit other sections into fixed area
84 for freespace, fixedsectioninfo in fixedAddr:
85 fixedaddr, fixedsection, extrasections = fixedsectioninfo
86 addpos = fixedaddr + fixedsection[0]
87 totalused += fixedsection[0]
88 nextfixedaddr = addpos + freespace
89 # print "Filling section %x uses %d, next=%x, available=%d" % (
90 # fixedaddr, fixedsection[0], nextfixedaddr, freespace)
93 for fixedaddrinfo in canrelocate:
94 fitsection, inlist = fixedaddrinfo
95 fitsize, fitalign, fitname = fitsection
96 if addpos + fitsize > nextfixedaddr:
97 # Can't fit and nothing else will fit.
99 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.
105 canfit = (fitnextaddr, fixedaddrinfo)
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)
115 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)
119 firstfixed = fixedsections[0][0]
121 # Find overall start position
125 for section in textsections + rodatasections + datasections:
126 size, align, name = section
127 if align > restalign:
129 restspace = alignpos(restspace, align) + size
130 restsections.append(section)
131 startrest = (firstfixed - restspace) / restalign * restalign
134 total = MAXPOS-firstfixed
135 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))
142 output = open(outname, 'wb')
145 code16_start = ABSOLUTE(.) ;
149 # Write regular sections
150 for section in restsections:
152 if name == rodatasections[0][2]:
153 output.write("code16_rodata = . ;\n")
154 outsection(output, name)
156 # Write fixed sections
157 for addr, section, extrasections in fixedsections:
159 output.write(". = ( 0x%x - code16_start ) ;\n" % (addr,))
160 output.write("*(%s)\n" % (name,))
161 for extrasection in extrasections:
162 outsection(output, extrasection[2])
166 code16_end = ABSOLUTE(.) ;
171 if __name__ == '__main__':