Annotation of qemu/roms/seabios/tools/layoutrom.py, revision 1.1.1.4

1.1       root        1: #!/usr/bin/env python
                      2: # Script to analyze code and arrange ld sections.
                      3: #
1.1.1.4 ! root        4: # Copyright (C) 2008-2010  Kevin O'Connor <[email protected]>
1.1       root        5: #
                      6: # This file may be distributed under the terms of the GNU GPLv3 license.
                      7: 
                      8: import sys
                      9: 
                     10: # LD script headers/trailers
                     11: COMMONHEADER = """
                     12: /* DO NOT EDIT!  This is an autogenerated file.  See tools/layoutrom.py. */
                     13: OUTPUT_FORMAT("elf32-i386")
                     14: OUTPUT_ARCH("i386")
                     15: SECTIONS
                     16: {
                     17: """
                     18: COMMONTRAILER = """
1.1.1.3   root       19: 
                     20:         /* Discard regular data sections to force a link error if
                     21:          * code attempts to access data not marked with VAR16 (or other
                     22:          * appropriate macro)
                     23:          */
                     24:         /DISCARD/ : {
                     25:                 *(.text*) *(.data*) *(.bss*) *(.rodata*)
                     26:                 *(COMMON) *(.discard*) *(.eh_frame)
                     27:                 }
1.1       root       28: }
                     29: """
                     30: 
                     31: 
                     32: ######################################################################
1.1.1.3   root       33: # Determine section locations
1.1       root       34: ######################################################################
                     35: 
1.1.1.3   root       36: # Align 'pos' to 'alignbytes' offset
                     37: def alignpos(pos, alignbytes):
                     38:     mask = alignbytes - 1
                     39:     return (pos + mask) & ~mask
                     40: 
                     41: # Determine the final addresses for a list of sections that end at an
1.1       root       42: # address.
1.1.1.4 ! root       43: def setSectionsStart(sections, endaddr, minalign=1):
1.1       root       44:     totspace = 0
1.1.1.4 ! root       45:     for section in sections:
        !            46:         if section.align > minalign:
        !            47:             minalign = section.align
        !            48:         totspace = alignpos(totspace, section.align) + section.size
1.1.1.3   root       49:     startaddr = (endaddr - totspace) / minalign * minalign
                     50:     curaddr = startaddr
                     51:     # out = [(addr, sectioninfo), ...]
                     52:     out = []
1.1.1.4 ! root       53:     for section in sections:
        !            54:         curaddr = alignpos(curaddr, section.align)
        !            55:         section.finalloc = curaddr
        !            56:         curaddr += section.size
        !            57:     return startaddr
1.1       root       58: 
                     59: # The 16bit code can't exceed 64K of space.
1.1.1.3   root       60: BUILD_BIOS_ADDR = 0xf0000
                     61: BUILD_BIOS_SIZE = 0x10000
1.1       root       62: 
                     63: # Layout the 16bit code.  This ensures sections with fixed offset
                     64: # requirements are placed in the correct location.  It also places the
                     65: # 16bit code as high as possible in the f-segment.
1.1.1.3   root       66: def fitSections(sections, fillsections):
1.1.1.4 ! root       67:     # fixedsections = [(addr, section), ...]
1.1       root       68:     fixedsections = []
1.1.1.4 ! root       69:     for section in sections:
        !            70:         if section.name.startswith('.fixedaddr.'):
        !            71:             addr = int(section.name[11:], 16)
        !            72:             section.finalloc = addr
        !            73:             fixedsections.append((addr, section))
        !            74:             if section.align != 1:
1.1       root       75:                 print "Error: Fixed section %s has non-zero alignment (%d)" % (
1.1.1.4 ! root       76:                     section.name, section.align)
1.1       root       77:                 sys.exit(1)
1.1.1.4 ! root       78:     fixedsections.sort()
        !            79:     firstfixed = fixedsections[0][0]
1.1       root       80: 
                     81:     # Find freespace in fixed address area
1.1.1.4 ! root       82:     # fixedAddr = [(freespace, section), ...]
1.1       root       83:     fixedAddr = []
                     84:     for i in range(len(fixedsections)):
                     85:         fixedsectioninfo = fixedsections[i]
1.1.1.3   root       86:         addr, section = fixedsectioninfo
1.1       root       87:         if i == len(fixedsections) - 1:
1.1.1.3   root       88:             nextaddr = BUILD_BIOS_SIZE
1.1       root       89:         else:
                     90:             nextaddr = fixedsections[i+1][0]
1.1.1.4 ! root       91:         avail = nextaddr - addr - section.size
        !            92:         fixedAddr.append((avail, section))
        !            93:     fixedAddr.sort()
1.1       root       94: 
                     95:     # Attempt to fit other sections into fixed area
1.1.1.4 ! root       96:     canrelocate = [(section.size, section.align, section.name, section)
        !            97:                    for section in fillsections]
1.1       root       98:     canrelocate.sort()
1.1.1.4 ! root       99:     canrelocate = [section for size, align, name, section in canrelocate]
1.1       root      100:     totalused = 0
1.1.1.4 ! root      101:     for freespace, fixedsection in fixedAddr:
        !           102:         addpos = fixedsection.finalloc + fixedsection.size
        !           103:         totalused += fixedsection.size
1.1       root      104:         nextfixedaddr = addpos + freespace
                    105: #        print "Filling section %x uses %d, next=%x, available=%d" % (
1.1.1.4 ! root      106: #            fixedsection.finalloc, fixedsection.size, nextfixedaddr, freespace)
1.1       root      107:         while 1:
                    108:             canfit = None
1.1.1.3   root      109:             for fitsection in canrelocate:
1.1.1.4 ! root      110:                 if addpos + fitsection.size > nextfixedaddr:
1.1       root      111:                     # Can't fit and nothing else will fit.
                    112:                     break
1.1.1.4 ! root      113:                 fitnextaddr = alignpos(addpos, fitsection.align) + fitsection.size
1.1       root      114: #                print "Test %s - %x vs %x" % (
1.1.1.4 ! root      115: #                    fitsection.name, fitnextaddr, nextfixedaddr)
1.1       root      116:                 if fitnextaddr > nextfixedaddr:
                    117:                     # This item can't fit.
                    118:                     continue
1.1.1.3   root      119:                 canfit = (fitnextaddr, fitsection)
1.1       root      120:             if canfit is None:
                    121:                 break
                    122:             # Found a section that can fit.
1.1.1.3   root      123:             fitnextaddr, fitsection = canfit
                    124:             canrelocate.remove(fitsection)
1.1.1.4 ! root      125:             fitsection.finalloc = addpos
1.1       root      126:             addpos = fitnextaddr
1.1.1.4 ! root      127:             totalused += fitsection.size
1.1       root      128: #            print "    Adding %s (size %d align %d) pos=%x avail=%d" % (
                    129: #                fitsection[2], fitsection[0], fitsection[1]
                    130: #                , fitnextaddr, nextfixedaddr - fitnextaddr)
                    131: 
                    132:     # Report stats
1.1.1.3   root      133:     total = BUILD_BIOS_SIZE-firstfixed
1.1       root      134:     slack = total - totalused
                    135:     print ("Fixed space: 0x%x-0x%x  total: %d  slack: %d"
                    136:            "  Percent slack: %.1f%%" % (
1.1.1.3   root      137:             firstfixed, BUILD_BIOS_SIZE, total, slack,
1.1       root      138:             (float(slack) / total) * 100.0))
                    139: 
1.1.1.4 ! root      140:     return firstfixed
1.1       root      141: 
1.1.1.4 ! root      142: # Return the subset of sections with a given name prefix
        !           143: def getSectionsPrefix(sections, category, prefix):
        !           144:     return [section for section in sections
        !           145:             if section.category == category and section.name.startswith(prefix)]
        !           146: 
        !           147: def doLayout(sections):
1.1.1.3   root      148:     # Determine 16bit positions
1.1.1.4 ! root      149:     textsections = getSectionsPrefix(sections, '16', '.text.')
        !           150:     rodatasections = (getSectionsPrefix(sections, '16', '.rodata.str1.1')
        !           151:                       + getSectionsPrefix(sections, '16', '.rodata.__func__.'))
        !           152:     datasections = getSectionsPrefix(sections, '16', '.data16.')
        !           153:     fixedsections = getSectionsPrefix(sections, '16', '.fixedaddr.')
        !           154: 
        !           155:     firstfixed = fitSections(fixedsections, textsections)
        !           156:     remsections = [s for s in textsections+rodatasections+datasections
        !           157:                    if s.finalloc is None]
        !           158:     code16_start = setSectionsStart(remsections, firstfixed)
1.1.1.3   root      159: 
                    160:     # Determine 32seg positions
1.1.1.4 ! root      161:     textsections = getSectionsPrefix(sections, '32seg', '.text.')
        !           162:     rodatasections = (getSectionsPrefix(sections, '32seg', '.rodata.str1.1')
        !           163:                       +getSectionsPrefix(sections, '32seg', '.rodata.__func__.'))
        !           164:     datasections = getSectionsPrefix(sections, '32seg', '.data32seg.')
1.1.1.3   root      165: 
1.1.1.4 ! root      166:     code32seg_start = setSectionsStart(
1.1.1.3   root      167:         textsections + rodatasections + datasections, code16_start)
                    168: 
1.1.1.4 ! root      169:     # Determine 32flat runtime positions
        !           170:     textsections = getSectionsPrefix(sections, '32flat', '.text.')
        !           171:     rodatasections = getSectionsPrefix(sections, '32flat', '.rodata')
        !           172:     datasections = getSectionsPrefix(sections, '32flat', '.data.')
        !           173:     bsssections = getSectionsPrefix(sections, '32flat', '.bss.')
1.1.1.3   root      174: 
1.1.1.4 ! root      175:     code32flat_start = setSectionsStart(
1.1.1.3   root      176:         textsections + rodatasections + datasections + bsssections
                    177:         , code32seg_start + BUILD_BIOS_ADDR, 16)
                    178: 
1.1.1.4 ! root      179:     # Determine 32flat init positions
        !           180:     textsections = getSectionsPrefix(sections, '32init', '.text.')
        !           181:     rodatasections = getSectionsPrefix(sections, '32init', '.rodata')
        !           182:     datasections = getSectionsPrefix(sections, '32init', '.data.')
        !           183:     bsssections = getSectionsPrefix(sections, '32init', '.bss.')
        !           184: 
        !           185:     code32init_start = setSectionsStart(
        !           186:         textsections + rodatasections + datasections + bsssections
        !           187:         , code32flat_start, 16)
        !           188: 
1.1.1.3   root      189:     # Print statistics
                    190:     size16 = BUILD_BIOS_SIZE - code16_start
                    191:     size32seg = code16_start - code32seg_start
                    192:     size32flat = code32seg_start + BUILD_BIOS_ADDR - code32flat_start
1.1.1.4 ! root      193:     size32init = code32flat_start - code32init_start
1.1.1.3   root      194:     print "16bit size:           %d" % size16
                    195:     print "32bit segmented size: %d" % size32seg
                    196:     print "32bit flat size:      %d" % size32flat
1.1.1.4 ! root      197:     print "32bit flat init size: %d" % size32init
1.1       root      198: 
                    199: 
                    200: ######################################################################
1.1.1.3   root      201: # Linker script output
1.1       root      202: ######################################################################
                    203: 
1.1.1.3   root      204: # Write LD script includes for the given cross references
1.1.1.4 ! root      205: def outXRefs(sections):
        !           206:     xrefs = {}
1.1.1.3   root      207:     out = ""
1.1.1.4 ! root      208:     for section in sections:
        !           209:         for reloc in section.relocs:
        !           210:             symbol = reloc.symbol
        !           211:             if (symbol.section is None
        !           212:                 or (symbol.section.fileid == section.fileid
        !           213:                     and symbol.name == reloc.symbolname)
        !           214:                 or reloc.symbolname in xrefs):
        !           215:                 continue
        !           216:             xrefs[reloc.symbolname] = 1
        !           217:             addr = symbol.section.finalloc + symbol.offset
        !           218:             if (section.fileid == '32flat'
        !           219:                 and symbol.section.fileid in ('16', '32seg')):
        !           220:                 addr += BUILD_BIOS_ADDR
        !           221:             out += "%s = 0x%x ;\n" % (reloc.symbolname, addr)
1.1.1.3   root      222:     return out
                    223: 
                    224: # Write LD script includes for the given sections using relative offsets
1.1.1.4 ! root      225: def outRelSections(sections, startsym):
1.1.1.3   root      226:     out = ""
1.1.1.4 ! root      227:     for section in sections:
        !           228:         out += ". = ( 0x%x - %s ) ;\n" % (section.finalloc, startsym)
        !           229:         if section.name == '.rodata.str1.1':
1.1.1.3   root      230:             out += "_rodata = . ;\n"
1.1.1.4 ! root      231:         out += "*(%s)\n" % (section.name,)
1.1       root      232:     return out
                    233: 
1.1.1.4 ! root      234: def getSectionsFile(sections, fileid, defaddr=0):
        !           235:     sections = [(section.finalloc, section)
        !           236:                 for section in sections if section.fileid == fileid]
        !           237:     sections.sort()
        !           238:     sections = [section for addr, section in sections]
        !           239:     pos = defaddr
        !           240:     if sections:
        !           241:         pos = sections[0].finalloc
        !           242:     return sections, pos
1.1.1.3   root      243: 
1.1.1.4 ! root      244: # Layout the 32bit segmented code.  This places the code as high as possible.
        !           245: def writeLinkerScripts(sections, entrysym, genreloc, out16, out32seg, out32flat):
1.1.1.3   root      246:     # Write 16bit linker script
1.1.1.4 ! root      247:     sections16, code16_start = getSectionsFile(sections, '16')
1.1.1.3   root      248:     output = open(out16, 'wb')
1.1.1.4 ! root      249:     output.write(COMMONHEADER + outXRefs(sections16) + """
1.1.1.3   root      250:     code16_start = 0x%x ;
                    251:     .text16 code16_start : {
                    252: """ % (code16_start)
1.1.1.4 ! root      253:                  + outRelSections(sections16, 'code16_start')
1.1.1.3   root      254:                  + """
                    255:     }
                    256: """
                    257:                  + COMMONTRAILER)
                    258:     output.close()
                    259: 
                    260:     # Write 32seg linker script
1.1.1.4 ! root      261:     sections32seg, code32seg_start = getSectionsFile(
        !           262:         sections, '32seg', code16_start)
1.1.1.3   root      263:     output = open(out32seg, 'wb')
1.1.1.4 ! root      264:     output.write(COMMONHEADER + outXRefs(sections32seg) + """
1.1.1.3   root      265:     code32seg_start = 0x%x ;
                    266:     .text32seg code32seg_start : {
                    267: """ % (code32seg_start)
1.1.1.4 ! root      268:                  + outRelSections(sections32seg, 'code32seg_start')
1.1.1.3   root      269:                  + """
                    270:     }
                    271: """
                    272:                  + COMMONTRAILER)
                    273:     output.close()
                    274: 
                    275:     # Write 32flat linker script
1.1.1.4 ! root      276:     sections32flat, code32flat_start = getSectionsFile(
        !           277:         sections, '32flat', code32seg_start)
        !           278:     relocstr = ""
        !           279:     relocminalign = 0
        !           280:     if genreloc:
        !           281:         # Generate relocations
        !           282:         relocstr, size, relocminalign = genRelocs(sections)
        !           283:         code32flat_start -= size
1.1.1.3   root      284:     output = open(out32flat, 'wb')
                    285:     output.write(COMMONHEADER
1.1.1.4 ! root      286:                  + outXRefs(sections32flat) + """
        !           287:     %s = 0x%x ;
        !           288:     _reloc_min_align = 0x%x ;
1.1.1.3   root      289:     code32flat_start = 0x%x ;
                    290:     .text code32flat_start : {
1.1.1.4 ! root      291: """ % (entrysym.name,
        !           292:        entrysym.section.finalloc + entrysym.offset + BUILD_BIOS_ADDR,
        !           293:        relocminalign, code32flat_start)
        !           294:                  + relocstr
        !           295:                  + """
        !           296:         code32init_start = ABSOLUTE(.) ;
        !           297: """
        !           298:                  + outRelSections(getSectionsPrefix(sections32flat, '32init', '')
        !           299:                                   , 'code32flat_start')
        !           300:                  + """
        !           301:         code32init_end = ABSOLUTE(.) ;
        !           302: """
        !           303:                  + outRelSections(getSectionsPrefix(sections32flat, '32flat', '')
        !           304:                                   , 'code32flat_start')
1.1.1.3   root      305:                  + """
                    306:         . = ( 0x%x - code32flat_start ) ;
                    307:         *(.text32seg)
                    308:         . = ( 0x%x - code32flat_start ) ;
                    309:         *(.text16)
                    310:         code32flat_end = ABSOLUTE(.) ;
                    311:     } :text
                    312: """ % (code32seg_start + BUILD_BIOS_ADDR, code16_start + BUILD_BIOS_ADDR)
                    313:                  + COMMONTRAILER
                    314:                  + """
1.1.1.4 ! root      315: ENTRY(%s)
1.1.1.3   root      316: PHDRS
                    317: {
                    318:         text PT_LOAD AT ( code32flat_start ) ;
                    319: }
1.1.1.4 ! root      320: """ % (entrysym.name,))
1.1.1.3   root      321:     output.close()
1.1       root      322: 
                    323: 
                    324: ######################################################################
1.1.1.4 ! root      325: # Detection of init code
        !           326: ######################################################################
        !           327: 
        !           328: # Determine init section relocations
        !           329: def genRelocs(sections):
        !           330:     absrelocs = []
        !           331:     relrelocs = []
        !           332:     initrelocs = []
        !           333:     minalign = 16
        !           334:     for section in sections:
        !           335:         if section.category == '32init' and section.align > minalign:
        !           336:             minalign = section.align
        !           337:         for reloc in section.relocs:
        !           338:             symbol = reloc.symbol
        !           339:             if symbol.section is None:
        !           340:                 continue
        !           341:             relocpos = section.finalloc + reloc.offset
        !           342:             if (reloc.type == 'R_386_32' and section.category == '32init'
        !           343:                 and symbol.section.category == '32init'):
        !           344:                 # Absolute relocation
        !           345:                 absrelocs.append(relocpos)
        !           346:             elif (reloc.type == 'R_386_PC32' and section.category == '32init'
        !           347:                   and symbol.section.category != '32init'):
        !           348:                 # Relative relocation
        !           349:                 relrelocs.append(relocpos)
        !           350:             elif (section.category != '32init'
        !           351:                   and symbol.section.category == '32init'):
        !           352:                 # Relocation to the init section
        !           353:                 if section.fileid in ('16', '32seg'):
        !           354:                     relocpos += BUILD_BIOS_ADDR
        !           355:                 initrelocs.append(relocpos)
        !           356:     absrelocs.sort()
        !           357:     relrelocs.sort()
        !           358:     initrelocs.sort()
        !           359:     out = ("        _reloc_abs_start = ABSOLUTE(.) ;\n"
        !           360:            + "".join(["LONG(0x%x - code32init_start)\n" % (pos,)
        !           361:                       for pos in absrelocs])
        !           362:            + "        _reloc_abs_end = ABSOLUTE(.) ;\n"
        !           363:            + "        _reloc_rel_start = ABSOLUTE(.) ;\n"
        !           364:            + "".join(["LONG(0x%x - code32init_start)\n" % (pos,)
        !           365:                       for pos in relrelocs])
        !           366:            + "        _reloc_rel_end = ABSOLUTE(.) ;\n"
        !           367:            + "        _reloc_init_start = ABSOLUTE(.) ;\n"
        !           368:            + "".join(["LONG(0x%x - code32flat_start)\n" % (pos,)
        !           369:                       for pos in initrelocs])
        !           370:            + "        _reloc_init_end = ABSOLUTE(.) ;\n")
        !           371:     return out, len(absrelocs + relrelocs + initrelocs) * 4, minalign
        !           372: 
        !           373: def markRuntime(section, sections):
        !           374:     if (section is None or not section.keep or section.category is not None
        !           375:         or '.init.' in section.name or section.fileid != '32flat'):
        !           376:         return
        !           377:     section.category = '32flat'
        !           378:     # Recursively mark all sections this section points to
        !           379:     for reloc in section.relocs:
        !           380:         markRuntime(reloc.symbol.section, sections)
        !           381: 
        !           382: def findInit(sections):
        !           383:     # Recursively find and mark all "runtime" sections.
        !           384:     for section in sections:
        !           385:         if '.runtime.' in section.name or '.export.' in section.name:
        !           386:             markRuntime(section, sections)
        !           387:     for section in sections:
        !           388:         if section.category is not None:
        !           389:             continue
        !           390:         if section.fileid == '32flat':
        !           391:             section.category = '32init'
        !           392:         else:
        !           393:             section.category = section.fileid
        !           394: 
        !           395: 
        !           396: ######################################################################
1.1       root      397: # Section garbage collection
                    398: ######################################################################
                    399: 
1.1.1.4 ! root      400: CFUNCPREFIX = [('_cfunc16_', 0), ('_cfunc32seg_', 1), ('_cfunc32flat_', 2)]
        !           401: 
1.1.1.2   root      402: # Find and keep the section associated with a symbol (if available).
1.1.1.4 ! root      403: def keepsymbol(reloc, infos, pos, isxref):
        !           404:     symbolname = reloc.symbolname
        !           405:     mustbecfunc = 0
        !           406:     for symprefix, needpos in CFUNCPREFIX:
        !           407:         if symbolname.startswith(symprefix):
        !           408:             if needpos != pos:
        !           409:                 return -1
        !           410:             symbolname = symbolname[len(symprefix):]
        !           411:             mustbecfunc = 1
        !           412:             break
        !           413:     symbol = infos[pos][1].get(symbolname)
        !           414:     if (symbol is None or symbol.section is None
        !           415:         or symbol.section.name.startswith('.discard.')):
1.1.1.2   root      416:         return -1
1.1.1.4 ! root      417:     isdestcfunc = (symbol.section.name.startswith('.text.')
        !           418:                    and not symbol.section.name.startswith('.text.asm.'))
        !           419:     if ((mustbecfunc and not isdestcfunc)
        !           420:         or (not mustbecfunc and isdestcfunc and isxref)):
        !           421:         return -1
        !           422: 
        !           423:     reloc.symbol = symbol
        !           424:     keepsection(symbol.section, infos, pos)
1.1.1.2   root      425:     return 0
                    426: 
1.1       root      427: # Note required section, and recursively set all referenced sections
                    428: # as required.
1.1.1.4 ! root      429: def keepsection(section, infos, pos=0):
        !           430:     if section.keep:
1.1       root      431:         # Already kept - nothing to do.
                    432:         return
1.1.1.4 ! root      433:     section.keep = 1
1.1       root      434:     # Keep all sections that this section points to
1.1.1.4 ! root      435:     for reloc in section.relocs:
        !           436:         ret = keepsymbol(reloc, infos, pos, 0)
1.1.1.2   root      437:         if not ret:
1.1       root      438:             continue
                    439:         # Not in primary sections - it may be a cross 16/32 reference
1.1.1.4 ! root      440:         ret = keepsymbol(reloc, infos, (pos+1)%3, 1)
1.1.1.2   root      441:         if not ret:
                    442:             continue
1.1.1.4 ! root      443:         ret = keepsymbol(reloc, infos, (pos+2)%3, 1)
1.1.1.2   root      444:         if not ret:
                    445:             continue
1.1       root      446: 
                    447: # Determine which sections are actually referenced and need to be
                    448: # placed into the output file.
1.1.1.2   root      449: def gc(info16, info32seg, info32flat):
1.1.1.4 ! root      450:     # infos = ((sections16, symbols16), (sect32seg, sym32seg)
        !           451:     #          , (sect32flat, sym32flat))
        !           452:     infos = (info16, info32seg, info32flat)
1.1       root      453:     # Start by keeping sections that are globally visible.
1.1.1.4 ! root      454:     for section in info16[0]:
        !           455:         if section.name.startswith('.fixedaddr.') or '.export.' in section.name:
1.1.1.2   root      456:             keepsection(section, infos)
1.1.1.4 ! root      457:     return [section for section in info16[0]+info32seg[0]+info32flat[0]
        !           458:             if section.keep]
1.1       root      459: 
                    460: 
                    461: ######################################################################
                    462: # Startup and input parsing
                    463: ######################################################################
                    464: 
1.1.1.4 ! root      465: class Section:
        !           466:     name = size = alignment = fileid = relocs = None
        !           467:     finalloc = category = keep = None
        !           468: class Reloc:
        !           469:     offset = type = symbolname = symbol = None
        !           470: class Symbol:
        !           471:     name = offset = section = None
        !           472: 
1.1       root      473: # Read in output from objdump
1.1.1.4 ! root      474: def parseObjDump(file, fileid):
        !           475:     # sections = [section, ...]
1.1       root      476:     sections = []
1.1.1.4 ! root      477:     sectionmap = {}
        !           478:     # symbols[symbolname] = symbol
1.1       root      479:     symbols = {}
                    480: 
                    481:     state = None
                    482:     for line in file.readlines():
                    483:         line = line.rstrip()
                    484:         if line == 'Sections:':
                    485:             state = 'section'
                    486:             continue
                    487:         if line == 'SYMBOL TABLE:':
                    488:             state = 'symbol'
                    489:             continue
1.1.1.4 ! root      490:         if line.startswith('RELOCATION RECORDS FOR ['):
        !           491:             sectionname = line[24:-2]
        !           492:             if sectionname.startswith('.debug_'):
        !           493:                 # Skip debugging sections (to reduce parsing time)
        !           494:                 state = None
        !           495:                 continue
1.1       root      496:             state = 'reloc'
1.1.1.4 ! root      497:             relocsection = sectionmap[sectionname]
1.1       root      498:             continue
                    499: 
                    500:         if state == 'section':
                    501:             try:
                    502:                 idx, name, size, vma, lma, fileoff, align = line.split()
                    503:                 if align[:3] != '2**':
                    504:                     continue
1.1.1.4 ! root      505:                 section = Section()
        !           506:                 section.name = name
        !           507:                 section.size = int(size, 16)
        !           508:                 section.align = 2**int(align[3:])
        !           509:                 section.fileid = fileid
        !           510:                 section.relocs = []
        !           511:                 sections.append(section)
        !           512:                 sectionmap[name] = section
        !           513:             except ValueError:
1.1       root      514:                 pass
                    515:             continue
                    516:         if state == 'symbol':
                    517:             try:
1.1.1.4 ! root      518:                 sectionname, size, name = line[17:].split()
        !           519:                 symbol = Symbol()
        !           520:                 symbol.size = int(size, 16)
        !           521:                 symbol.offset = int(line[:8], 16)
        !           522:                 symbol.name = name
        !           523:                 symbol.section = sectionmap.get(sectionname)
        !           524:                 symbols[name] = symbol
        !           525:             except ValueError:
1.1       root      526:                 pass
                    527:             continue
                    528:         if state == 'reloc':
                    529:             try:
1.1.1.4 ! root      530:                 off, type, symbolname = line.split()
        !           531:                 reloc = Reloc()
        !           532:                 reloc.offset = int(off, 16)
        !           533:                 reloc.type = type
        !           534:                 reloc.symbolname = symbolname
        !           535:                 reloc.symbol = symbols.get(symbolname)
        !           536:                 if reloc.symbol is None:
        !           537:                     # Some binutils (2.20.1) give section name instead
        !           538:                     # of a symbol - create a dummy symbol.
        !           539:                     reloc.symbol = symbol = Symbol()
        !           540:                     symbol.size = 0
        !           541:                     symbol.offset = 0
        !           542:                     symbol.name = symbolname
        !           543:                     symbol.section = sectionmap.get(symbolname)
        !           544:                     symbols[symbolname] = symbol
        !           545:                 relocsection.relocs.append(reloc)
        !           546:             except ValueError:
1.1       root      547:                 pass
1.1.1.4 ! root      548:     return sections, symbols
1.1       root      549: 
                    550: def main():
                    551:     # Get output name
1.1.1.2   root      552:     in16, in32seg, in32flat, out16, out32seg, out32flat = sys.argv[1:]
1.1       root      553: 
1.1.1.3   root      554:     # Read in the objdump information
1.1       root      555:     infile16 = open(in16, 'rb')
1.1.1.2   root      556:     infile32seg = open(in32seg, 'rb')
                    557:     infile32flat = open(in32flat, 'rb')
1.1       root      558: 
1.1.1.4 ! root      559:     # infoX = (sections, symbols)
        !           560:     info16 = parseObjDump(infile16, '16')
        !           561:     info32seg = parseObjDump(infile32seg, '32seg')
        !           562:     info32flat = parseObjDump(infile32flat, '32flat')
1.1       root      563: 
1.1.1.3   root      564:     # Figure out which sections to keep.
1.1.1.4 ! root      565:     sections = gc(info16, info32seg, info32flat)
        !           566: 
        !           567:     # Separate 32bit flat into runtime and init parts
        !           568:     findInit(sections)
1.1.1.3   root      569: 
                    570:     # Determine the final memory locations of each kept section.
1.1.1.4 ! root      571:     doLayout(sections)
1.1.1.3   root      572: 
                    573:     # Write out linker script files.
1.1.1.4 ! root      574:     entrysym = info16[1]['post32']
        !           575:     genreloc = '_reloc_abs_start' in info32flat[1]
        !           576:     writeLinkerScripts(sections, entrysym, genreloc, out16, out32seg, out32flat)
1.1       root      577: 
                    578: if __name__ == '__main__':
                    579:     main()

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.