Best Python code snippet using fMBT_python
layoutrom.py
Source:layoutrom.py  
1#!/usr/bin/env python2# Script to analyze code and arrange ld sections.3#4# Copyright (C) 2008-2014  Kevin O'Connor <kevin@koconnor.net>5#6# This file may be distributed under the terms of the GNU GPLv3 license.7import operator8import sys9# LD script headers/trailers10COMMONHEADER = """11/* DO NOT EDIT!  This is an autogenerated file.  See scripts/layoutrom.py. */12OUTPUT_FORMAT("elf32-i386")13OUTPUT_ARCH("i386")14SECTIONS15{16"""17COMMONTRAILER = """18        /* Discard regular data sections to force a link error if19         * code attempts to access data not marked with VAR16 (or other20         * appropriate macro)21         */22        /DISCARD/ : {23                *(.text*) *(.data*) *(.bss*) *(.rodata*)24                *(COMMON) *(.discard*) *(.eh_frame) *(.note*)25                }26}27"""28######################################################################29# Determine section locations30######################################################################31# Align 'pos' up to 'alignbytes' offset32def alignpos(pos, alignbytes):33    mask = alignbytes - 134    return (pos + mask) & ~mask35# Align 'pos' down to 'alignbytes' offset36def aligndown(pos, alignbytes):37    mask = alignbytes - 138    return pos & ~mask39# Determine the final addresses for a list of sections that end at an40# address.41def setSectionsStart(sections, endaddr, minalign=1, segoffset=0):42    totspace = 043    for section in sections:44        minalign = max(minalign, section.align)45        totspace = alignpos(totspace, section.align) + section.size46    startaddr = int((endaddr - totspace) / minalign) * minalign47    curaddr = startaddr48    for section in sections:49        curaddr = alignpos(curaddr, section.align)50        section.finalloc = curaddr51        section.finalsegloc = curaddr - segoffset52        curaddr += section.size53    return startaddr, minalign54# The 16bit code can't exceed 64K of space.55BUILD_BIOS_ADDR = 0xf000056BUILD_BIOS_SIZE = 0x1000057BUILD_ROM_START = 0xc000058BUILD_LOWRAM_END = 0xa000059# Space to reserve in f-segment for dynamic allocations60BUILD_MIN_BIOSTABLE = 204861# Layout the 16bit code.  This ensures sections with fixed offset62# requirements are placed in the correct location.  It also places the63# 16bit code as high as possible in the f-segment.64def fitSections(sections, fillsections):65    # fixedsections = [(addr, section), ...]66    fixedsections = []67    for section in sections:68        if section.name.startswith('.fixedaddr.'):69            addr = int(section.name[11:], 16)70            section.finalloc = addr + BUILD_BIOS_ADDR71            section.finalsegloc = addr72            fixedsections.append((addr, section))73            if section.align != 1:74                print("Error: Fixed section %s has non-zero alignment (%d)" % (75                    section.name, section.align))76                sys.exit(1)77    fixedsections.sort(key=operator.itemgetter(0))78    firstfixed = fixedsections[0][0]79    # Find freespace in fixed address area80    # fixedAddr = [(freespace, section), ...]81    fixedAddr = []82    for i in range(len(fixedsections)):83        fixedsectioninfo = fixedsections[i]84        addr, section = fixedsectioninfo85        if i == len(fixedsections) - 1:86            nextaddr = BUILD_BIOS_SIZE87        else:88            nextaddr = fixedsections[i+1][0]89        avail = nextaddr - addr - section.size90        fixedAddr.append((avail, section))91    fixedAddr.sort(key=operator.itemgetter(0))92    # Attempt to fit other sections into fixed area93    canrelocate = [(section.size, section.align, section.name, section)94                   for section in fillsections]95    canrelocate.sort()96    canrelocate = [section for size, align, name, section in canrelocate]97    totalused = 098    for freespace, fixedsection in fixedAddr:99        addpos = fixedsection.finalsegloc + fixedsection.size100        totalused += fixedsection.size101        nextfixedaddr = addpos + freespace102#        print("Filling section %x uses %d, next=%x, available=%d" % (103#            fixedsection.finalloc, fixedsection.size, nextfixedaddr, freespace))104        while 1:105            canfit = None106            for fitsection in canrelocate:107                if addpos + fitsection.size > nextfixedaddr:108                    # Can't fit and nothing else will fit.109                    break110                fitnextaddr = alignpos(addpos, fitsection.align) + fitsection.size111#                print("Test %s - %x vs %x" % (112#                    fitsection.name, fitnextaddr, nextfixedaddr))113                if fitnextaddr > nextfixedaddr:114                    # This item can't fit.115                    continue116                canfit = (fitnextaddr, fitsection)117            if canfit is None:118                break119            # Found a section that can fit.120            fitnextaddr, fitsection = canfit121            canrelocate.remove(fitsection)122            fitsection.finalloc = addpos + BUILD_BIOS_ADDR123            fitsection.finalsegloc = addpos124            addpos = fitnextaddr125            totalused += fitsection.size126#            print("    Adding %s (size %d align %d) pos=%x avail=%d" % (127#                fitsection[2], fitsection[0], fitsection[1]128#                , fitnextaddr, nextfixedaddr - fitnextaddr))129    # Report stats130    total = BUILD_BIOS_SIZE-firstfixed131    slack = total - totalused132    print ("Fixed space: 0x%x-0x%x  total: %d  slack: %d"133           "  Percent slack: %.1f%%" % (134            firstfixed, BUILD_BIOS_SIZE, total, slack,135            (float(slack) / total) * 100.0))136    return firstfixed + BUILD_BIOS_ADDR137# Return the subset of sections with a given category138def getSectionsCategory(sections, category):139    return [section for section in sections if section.category == category]140# Return the subset of sections with a given fileid141def getSectionsFileid(sections, fileid):142    return [section for section in sections if section.fileid == fileid]143# Return the subset of sections with a given name prefix144def getSectionsPrefix(sections, prefix):145    return [section for section in sections146            if section.name.startswith(prefix)]147# The sections (and associated information) to be placed in output rom148class LayoutInfo:149    sections = None150    config = None151    genreloc = None152    sec32init_start = sec32init_end = sec32init_align = None153    sec32low_start = sec32low_end = None154    zonelow_base = final_sec32low_start = None155    zonefseg_start = zonefseg_end = None156    final_readonly_start = None157    varlowsyms = entrysym = None158# Determine final memory addresses for sections159def doLayout(sections, config, genreloc):160    li = LayoutInfo()161    li.config = config162    li.sections = sections163    li.genreloc = genreloc164    # Determine 16bit positions165    sections16 = getSectionsCategory(sections, '16')166    textsections = getSectionsPrefix(sections16, '.text.')167    rodatasections = getSectionsPrefix(sections16, '.rodata')168    datasections = getSectionsPrefix(sections16, '.data16.')169    fixedsections = getSectionsCategory(sections, 'fixed')170    firstfixed = fitSections(fixedsections, textsections)171    remsections = [s for s in textsections+rodatasections+datasections172                   if s.finalloc is None]173    sec16_start, sec16_align = setSectionsStart(174        remsections, firstfixed, segoffset=BUILD_BIOS_ADDR)175    # Determine 32seg positions176    sections32seg = getSectionsCategory(sections, '32seg')177    textsections = getSectionsPrefix(sections32seg, '.text.')178    rodatasections = getSectionsPrefix(sections32seg, '.rodata')179    datasections = getSectionsPrefix(sections32seg, '.data32seg.')180    sec32seg_start, sec32seg_align = setSectionsStart(181        textsections + rodatasections + datasections, sec16_start182        , segoffset=BUILD_BIOS_ADDR)183    # Determine 32bit "fseg memory" data positions184    sections32textfseg = getSectionsCategory(sections, '32textfseg')185    sec32textfseg_start, sec32textfseg_align = setSectionsStart(186        sections32textfseg, sec32seg_start, 16)187    sections32fseg = getSectionsCategory(sections, '32fseg')188    sec32fseg_start, sec32fseg_align = setSectionsStart(189        sections32fseg, sec32textfseg_start, 16190        , segoffset=BUILD_BIOS_ADDR)191    # Determine 32flat runtime positions192    sections32flat = getSectionsCategory(sections, '32flat')193    textsections = getSectionsPrefix(sections32flat, '.text.')194    rodatasections = getSectionsPrefix(sections32flat, '.rodata')195    datasections = getSectionsPrefix(sections32flat, '.data.')196    bsssections = getSectionsPrefix(sections32flat, '.bss.')197    sec32flat_start, sec32flat_align = setSectionsStart(198        textsections + rodatasections + datasections + bsssections199        , sec32fseg_start, 16)200    # Determine 32flat init positions201    sections32init = getSectionsCategory(sections, '32init')202    init32_textsections = getSectionsPrefix(sections32init, '.text.')203    init32_rodatasections = getSectionsPrefix(sections32init, '.rodata')204    init32_datasections = getSectionsPrefix(sections32init, '.data.')205    init32_bsssections = getSectionsPrefix(sections32init, '.bss.')206    sec32init_start, sec32init_align = setSectionsStart(207        init32_textsections + init32_rodatasections208        + init32_datasections + init32_bsssections209        , sec32flat_start, 16)210    # Determine location of ZoneFSeg memory.211    zonefseg_end = sec32flat_start212    if not genreloc:213        zonefseg_end = sec32init_start214    zonefseg_start = BUILD_BIOS_ADDR215    if zonefseg_start + BUILD_MIN_BIOSTABLE > zonefseg_end:216        # Not enough ZoneFSeg space - force a minimum space.217        zonefseg_end = sec32fseg_start218        zonefseg_start = zonefseg_end - BUILD_MIN_BIOSTABLE219        sec32flat_start, sec32flat_align = setSectionsStart(220            textsections + rodatasections + datasections + bsssections221            , zonefseg_start, 16)222        sec32init_start, sec32init_align = setSectionsStart(223            init32_textsections + init32_rodatasections224            + init32_datasections + init32_bsssections225            , sec32flat_start, 16)226    li.sec32init_start = sec32init_start227    li.sec32init_end = sec32flat_start228    li.sec32init_align = sec32init_align229    final_readonly_start = min(BUILD_BIOS_ADDR, sec32flat_start)230    if not genreloc:231        final_readonly_start = min(BUILD_BIOS_ADDR, sec32init_start)232    li.zonefseg_start = zonefseg_start233    li.zonefseg_end = zonefseg_end234    li.final_readonly_start = final_readonly_start235    # Determine "low memory" data positions236    sections32low = getSectionsCategory(sections, '32low')237    sec32low_end = sec32init_start238    if config.get('CONFIG_MALLOC_UPPERMEMORY'):239        final_sec32low_end = final_readonly_start240        zonelow_base = final_sec32low_end - 64*1024241        zonelow_base = max(BUILD_ROM_START, alignpos(zonelow_base, 2*1024))242    else:243        final_sec32low_end = BUILD_LOWRAM_END244        zonelow_base = final_sec32low_end - 64*1024245    relocdelta = final_sec32low_end - sec32low_end246    li.sec32low_start, sec32low_align = setSectionsStart(247        sections32low, sec32low_end, 16248        , segoffset=zonelow_base - relocdelta)249    li.sec32low_end = sec32low_end250    li.zonelow_base = zonelow_base251    li.final_sec32low_start = li.sec32low_start + relocdelta252    # Print statistics253    size16 = BUILD_BIOS_ADDR + BUILD_BIOS_SIZE - sec16_start254    size32seg = sec16_start - sec32seg_start255    size32textfseg = sec32seg_start - sec32textfseg_start256    size32fseg = sec32textfseg_start - sec32fseg_start257    size32flat = sec32fseg_start - sec32flat_start258    size32init = sec32flat_start - sec32init_start259    sizelow = li.sec32low_end - li.sec32low_start260    print("16bit size:           %d" % size16)261    print("32bit segmented size: %d" % size32seg)262    print("32bit flat size:      %d" % (size32flat + size32textfseg))263    print("32bit flat init size: %d" % size32init)264    print("Lowmem size:          %d" % sizelow)265    print("f-segment var size:   %d" % size32fseg)266    return li267######################################################################268# Linker script output269######################################################################270# Write LD script includes for the given cross references271def outXRefs(sections, useseg=0, exportsyms=[], forcedelta=0):272    xrefs = dict([(symbol.name, symbol) for symbol in exportsyms])273    out = ""274    for section in sections:275        for reloc in section.relocs:276            symbol = reloc.symbol277            if (symbol.section is not None278                and (symbol.section.fileid != section.fileid279                     or symbol.name != reloc.symbolname)):280                xrefs[reloc.symbolname] = symbol281    for symbolname, symbol in xrefs.items():282        loc = symbol.section.finalloc283        if useseg:284            loc = symbol.section.finalsegloc285        out += "%s = 0x%x ;\n" % (symbolname, loc + forcedelta + symbol.offset)286    return out287# Write LD script includes for the given sections288def outSections(sections, useseg=0):289    out = ""290    for section in sections:291        loc = section.finalloc292        if useseg:293            loc = section.finalsegloc294        out += "%s 0x%x : { *(%s) }\n" % (section.name, loc, section.name)295    return out296# Write LD script includes for the given sections using relative offsets297def outRelSections(sections, startsym, useseg=0):298    sections = [(section.finalloc, section) for section in sections299                if section.finalloc is not None]300    sections.sort(key=operator.itemgetter(0))301    out = ""302    for addr, section in sections:303        loc = section.finalloc304        if useseg:305            loc = section.finalsegloc306        out += ". = ( 0x%x - %s ) ;\n" % (loc, startsym)307        if section.name in ('.rodata.str1.1', '.rodata'):308            out += "_rodata%s = . ;\n" % (section.fileid,)309        out += "*%s.*(%s)\n" % (section.fileid, section.name)310    return out311# Build linker script output for a list of relocations.312def strRelocs(outname, outrel, relocs):313    relocs.sort()314    return ("        %s_start = ABSOLUTE(.) ;\n" % (outname,)315            + "".join(["LONG(0x%x - %s)\n" % (pos, outrel)316                       for pos in relocs])317            + "        %s_end = ABSOLUTE(.) ;\n" % (outname,))318# Find relocations to the given sections319def getRelocs(sections, tosection, type=None):320    return [section.finalloc + reloc.offset321            for section in sections322                for reloc in section.relocs323                    if (reloc.symbol.section in tosection324                        and (type is None or reloc.type == type))]325# Output the linker scripts for all required sections.326def writeLinkerScripts(li, out16, out32seg, out32flat):327    # Write 16bit linker script328    filesections16 = getSectionsFileid(li.sections, '16')329    out = outXRefs(filesections16, useseg=1) + """330    zonelow_base = 0x%x ;331    _zonelow_seg = 0x%x ;332%s333""" % (li.zonelow_base,334       int(li.zonelow_base / 16),335       outSections(filesections16, useseg=1))336    outfile = open(out16, 'w')337    outfile.write(COMMONHEADER + out + COMMONTRAILER)338    outfile.close()339    # Write 32seg linker script340    filesections32seg = getSectionsFileid(li.sections, '32seg')341    out = (outXRefs(filesections32seg, useseg=1)342           + outSections(filesections32seg, useseg=1))343    outfile = open(out32seg, 'w')344    outfile.write(COMMONHEADER + out + COMMONTRAILER)345    outfile.close()346    # Write 32flat linker script347    sec32all_start = li.sec32low_start348    relocstr = ""349    if li.genreloc:350        # Generate relocations351        initsections = dict([352            (s, 1) for s in getSectionsCategory(li.sections, '32init')])353        noninitsections = dict([(s, 1) for s in li.sections354                                if s not in initsections])355        absrelocs = getRelocs(initsections, initsections, type='R_386_32')356        relrelocs = getRelocs(initsections, noninitsections, type='R_386_PC32')357        initrelocs = getRelocs(noninitsections, initsections)358        relocstr = (strRelocs("_reloc_abs", "code32init_start", absrelocs)359                    + strRelocs("_reloc_rel", "code32init_start", relrelocs)360                    + strRelocs("_reloc_init", "code32flat_start", initrelocs))361        numrelocs = len(absrelocs + relrelocs + initrelocs)362        sec32all_start -= numrelocs * 4363    filesections32flat = getSectionsFileid(li.sections, '32flat')364    out = outXRefs([], exportsyms=li.varlowsyms365                   , forcedelta=li.final_sec32low_start-li.sec32low_start)366    multiboot_header = ""367    if li.config.get('CONFIG_MULTIBOOT'):368        multiboot_header = "LONG(0x1BADB002) LONG(0) LONG(-0x1BADB002)"369        sec32all_start -= 3 * 4370    sec32all_align = max([section.align for section in li.sections])371    sec32all_start = aligndown(sec32all_start, sec32all_align)372    out += outXRefs(filesections32flat, exportsyms=[li.entrysym]) + """373    _reloc_min_align = 0x%x ;374    zonefseg_start = 0x%x ;375    zonefseg_end = 0x%x ;376    zonelow_base = 0x%x ;377    final_varlow_start = 0x%x ;378    final_readonly_start = 0x%x ;379    varlow_start = 0x%x ;380    varlow_end = 0x%x ;381    code32init_start = 0x%x ;382    code32init_end = 0x%x ;383    code32flat_start = 0x%x ;384    .text code32flat_start : {385%s386%s387%s388        code32flat_end = ABSOLUTE(.) ;389    } :text390""" % (li.sec32init_align,391       li.zonefseg_start,392       li.zonefseg_end,393       li.zonelow_base,394       li.final_sec32low_start,395       li.final_readonly_start,396       li.sec32low_start,397       li.sec32low_end,398       li.sec32init_start,399       li.sec32init_end,400       sec32all_start,401       multiboot_header,402       relocstr,403       outRelSections(li.sections, 'code32flat_start'))404    out = COMMONHEADER + out + COMMONTRAILER + """405ENTRY(%s)406PHDRS407{408        text PT_LOAD AT ( code32flat_start ) ;409}410""" % (li.entrysym.name,)411    outfile = open(out32flat, 'w')412    outfile.write(out)413    outfile.close()414######################################################################415# Detection of unused sections and init sections416######################################################################417# Visit all sections reachable from a given set of start sections418def findReachable(anchorsections, checkreloc, data):419    anchorsections = dict([(section, []) for section in anchorsections])420    pending = list(anchorsections)421    while pending:422        section = pending.pop()423        for reloc in section.relocs:424            chain = anchorsections[section] + [section.name]425            if not checkreloc(reloc, section, data, chain):426                continue427            nextsection = reloc.symbol.section428            if nextsection not in anchorsections:429                anchorsections[nextsection] = chain430                pending.append(nextsection)431    return anchorsections432# Find "runtime" sections (ie, not init only sections).433def checkRuntime(reloc, rsection, data, chain):434    section = reloc.symbol.section435    if section is None or '.init.' in section.name:436        return 0437    if '.data.varinit.' in section.name:438        print("ERROR: %s is VARVERIFY32INIT but used from %s" % (439            section.name, chain))440        sys.exit(1)441    return 1442# Find and keep the section associated with a symbol (if available).443def checkKeepSym(reloc, syms, fileid, isxref):444    symbolname = reloc.symbolname445    mustbecfunc = symbolname.startswith('_cfunc')446    if mustbecfunc:447        symprefix = '_cfunc' + fileid + '_'448        if not symbolname.startswith(symprefix):449            return 0450        symbolname = symbolname[len(symprefix):]451    symbol = syms.get(symbolname)452    if (symbol is None or symbol.section is None453        or symbol.section.name.startswith('.discard.')):454        return 0455    isdestcfunc = (symbol.section.name.startswith('.text.')456                   and not symbol.section.name.startswith('.text.asm.'))457    if ((mustbecfunc and not isdestcfunc)458        or (not mustbecfunc and isdestcfunc and isxref)):459        return 0460    reloc.symbol = symbol461    return 1462# Resolve a relocation and check if it should be kept in the final binary.463def checkKeep(reloc, section, symbols, chain):464    ret = checkKeepSym(reloc, symbols[section.fileid], section.fileid, 0)465    if ret:466        return ret467    # Not in primary sections - it may be a cross 16/32 reference468    for fileid in ('16', '32seg', '32flat'):469        if fileid != section.fileid:470            ret = checkKeepSym(reloc, symbols[fileid], fileid, 1)471            if ret:472                return ret473    return 0474######################################################################475# Startup and input parsing476######################################################################477class Section:478    name = size = alignment = fileid = relocs = None479    finalloc = finalsegloc = category = None480class Reloc:481    offset = type = symbolname = symbol = None482class Symbol:483    name = offset = section = None484# Read in output from objdump485def parseObjDump(file, fileid):486    # sections = [section, ...]487    sections = []488    sectionmap = {}489    # symbols[symbolname] = symbol490    symbols = {}491    state = None492    for line in file.readlines():493        line = line.rstrip()494        if line == 'Sections:':495            state = 'section'496            continue497        if line == 'SYMBOL TABLE:':498            state = 'symbol'499            continue500        if line.startswith('RELOCATION RECORDS FOR ['):501            sectionname = line[24:-2]502            if sectionname.startswith('.debug_'):503                # Skip debugging sections (to reduce parsing time)504                state = None505                continue506            state = 'reloc'507            relocsection = sectionmap[sectionname]508            continue509        if state == 'section':510            try:511                idx, name, size, vma, lma, fileoff, align = line.split()512                if align[:3] != '2**':513                    continue514                section = Section()515                section.name = name516                section.size = int(size, 16)517                section.align = 2**int(align[3:])518                section.fileid = fileid519                section.relocs = []520                sections.append(section)521                sectionmap[name] = section522            except ValueError:523                pass524            continue525        if state == 'symbol':526            try:527                parts = line[17:].split()528                if len(parts) == 3:529                    sectionname, size, name = parts530                elif len(parts) == 4 and parts[2] == '.hidden':531                    sectionname, size, hidden, name = parts532                else:533                    continue534                symbol = Symbol()535                symbol.size = int(size, 16)536                symbol.offset = int(line[:8], 16)537                symbol.name = name538                symbol.section = sectionmap.get(sectionname)539                symbols[name] = symbol540            except ValueError:541                pass542            continue543        if state == 'reloc':544            try:545                off, type, symbolname = line.split()546                reloc = Reloc()547                reloc.offset = int(off, 16)548                reloc.type = type549                reloc.symbolname = symbolname550                reloc.symbol = symbols.get(symbolname)551                if reloc.symbol is None:552                    # Some binutils (2.20.1) give section name instead553                    # of a symbol - create a dummy symbol.554                    reloc.symbol = symbol = Symbol()555                    symbol.size = 0556                    symbol.offset = 0557                    symbol.name = symbolname558                    symbol.section = sectionmap.get(symbolname)559                    symbols[symbolname] = symbol560                relocsection.relocs.append(reloc)561            except ValueError:562                pass563    return sections, symbols564# Parser for constants in simple C header files.565def scanconfig(file):566    f = open(file, 'r')567    opts = {}568    for l in f.readlines():569        parts = l.split()570        if len(parts) != 3:571            continue572        if parts[0] != '#define':573            continue574        value = parts[2]575        if value.isdigit() or (value.startswith('0x') and value[2:].isdigit()):576            value = int(value, 0)577        opts[parts[1]] = value578    return opts579def main():580    # Get output name581    in16, in32seg, in32flat, cfgfile, out16, out32seg, out32flat = sys.argv[1:]582    # Read in the objdump information583    infile16 = open(in16, 'r')584    infile32seg = open(in32seg, 'r')585    infile32flat = open(in32flat, 'r')586    # infoX = (sections, symbols)587    info16 = parseObjDump(infile16, '16')588    info32seg = parseObjDump(infile32seg, '32seg')589    info32flat = parseObjDump(infile32flat, '32flat')590    # Read kconfig config file591    config = scanconfig(cfgfile)592    # Figure out which sections to keep.593    allsections = info16[0] + info32seg[0] + info32flat[0]594    symbols = {'16': info16[1], '32seg': info32seg[1], '32flat': info32flat[1]}595    if config.get('CONFIG_COREBOOT'):596        entrysym = symbols['16'].get('entry_elf')597    elif config.get('CONFIG_CSM'):598        entrysym = symbols['16'].get('entry_csm')599    else:600        entrysym = symbols['16'].get('reset_vector')601    anchorsections = [entrysym.section] + [602        section for section in allsections603        if section.name.startswith('.fixedaddr.')]604    keepsections = findReachable(anchorsections, checkKeep, symbols)605    sections = [section for section in allsections if section in keepsections]606    # Separate 32bit flat into runtime, init, and special variable parts607    anchorsections = [608        section for section in sections609        if ('.data.varlow.' in section.name or '.data.varfseg.' in section.name610            or '.fixedaddr.' in section.name or '.runtime.' in section.name)]611    runtimesections = findReachable(anchorsections, checkRuntime, None)612    for section in sections:613        if section.name.startswith('.data.varlow.'):614            section.category = '32low'615        elif section.name.startswith('.data.varfseg.'):616            section.category = '32fseg'617        elif section.name.startswith('.text.32fseg.'):618            section.category = '32textfseg'619        elif section.name.startswith('.fixedaddr.'):620            section.category = 'fixed'621        elif section.fileid == '32flat' and section not in runtimesections:622            section.category = '32init'623        else:624            section.category = section.fileid625    # Determine the final memory locations of each kept section.626    genreloc = '_reloc_abs_start' in symbols['32flat']627    li = doLayout(sections, config, genreloc)628    # Exported symbols629    li.varlowsyms = [symbol for symbol in symbols['32flat'].values()630                     if (symbol.section is not None631                         and symbol.section.finalloc is not None632                         and '.data.varlow.' in symbol.section.name633                         and symbol.name != symbol.section.name)]634    li.entrysym = entrysym635    # Write out linker script files.636    writeLinkerScripts(li, out16, out32seg, out32flat)637if __name__ == '__main__':...connect_cross_sections.py
Source:connect_cross_sections.py  
...8    9function: connect_cross_sections_without_indication(10    workspace, in_cross_sections, out_cross_sections_name, maximum_distance)11    12function: check_duplicated_cross_sections(in_cross_sections)13                14"""15import logging16import math17import time18import arcpy19from configuration.configure_logging import create_logger20from other.list_field_names import list_field_names21logger = logging.getLogger(__name__)22create_logger(logger)23def connect_cross_sections_with_indication(24            workspace, in_cross_sections, out_cross_sections_name, line_field,25            maximum_distance):26    """Connect the points from the cross sections to lines.27        28    An indication (e.g. a kilometer indication) is used as line field29    for the connection. If the named line_field is not avaiable, the30    function connect_cross_sections_without_indication is called. 31    Else, after connecting the cross sections, a field 'SECTIONID'32    and a field 'INTERMEDIATEID' are added to the output feature class.33    The SECTIONID begins with 1 and is incremented. The INTERMEDIATEID34    is set to 0.35    36    @param workspace (DEWorkspace):37        The workspace for results.38    @param in_cross_sections (DEFeatureClass): 39        The feature class with the cross sections points.40    @param out_cross_sections out_cross_sections (GPString): 41        The output feature class name.42    @param line_field (GPString): 43        The line fields name.44    @param maximum_distance (GPDouble):45        The maximum distance between points.46    47    @return out_cross_sections(DEFeatureClass): 48        The output cross section feature class.49    50    """ 51    logger.debug("Check if line_field '" + line_field +"' exists.")52    field_names = list_field_names(in_cross_sections)53        54    if line_field in field_names:    55        logger.debug("Start connecting cross sections to lines.")56        try:57            out_cross_sections = workspace + "/" + out_cross_sections_name58            arcpy.PointsToLine_management(59                in_cross_sections, out_cross_sections, line_field60                )61        except arcpy.ExecuteError:62            logger.warning(63                out_cross_sections + " already exists. Change output name: " 64                + out_cross_sections + time.strftime("%d%m%y_%H%M%S.")65                )66            out_cross_sections = (67                out_cross_sections + time.strftime("%d%m%y_%H%M%S")68                )69            arcpy.PointsToLine_management(70                in_cross_sections, out_cross_sections, line_field71                )72        logger.info("Connecting cross sections completed successfully.")73        logger.debug("Add a field SECTIONID.")74        field_name = "SECTIONID"75        field_type = "SHORT"76        arcpy.AddField_management(out_cross_sections, field_name, field_type)77        logger.info("Field SECTIONID added successfully.")78    79        logger.debug("Add a field INTERMEDIATEID.")80        field_name = "INTERMEDIATEID"81        arcpy.AddField_management(out_cross_sections, field_name, field_type)82        logger.info("Field INTERMEDIATEID added successfully.")83    84        logger.debug("Create cursor for allocating the IDs.")85        field_names = ["SECTIONID", "INTERMEDIATEID"]86        with arcpy.da.UpdateCursor(out_cross_sections, field_names) as cursor:87            i = 188            for row in cursor:89                row[0] = i90                row[1] = 091                cursor.updateRow(row)92                i = i + 193        logger.info(94            "Set SECTIONID successfully: " + str (i) + " cross sections "95            "exist. Set INTERMEDIATEID successfully to 0."96            )97        return out_cross_sections98    99    else:100        logger.warning(101            "Line_field '" + line_field + "' does not exist. Start function "102            "connect_cross_sections_without_indication."103            )104        out_cross_sections = connect_cross_sections_without_indication(105            workspace, in_cross_sections, out_cross_sections_name,106            maximum_distance107            )108        109        return out_cross_sections110    111def connect_cross_sections_without_indication(112            workspace, in_cross_sections, out_cross_sections_name,113            maximum_distance):114    """Connect the points from the cross sections to lines.115        116    The function arcpy.PointsToLine_management(in_features,117    out_features, line_field) needs a line_field to connect points which118    belong together. For this, a line_field is created in this function.119    Therefore a field 'SECTIONID' is added to the in_cross_section120    feature class. Then, the coordinates of the points are transfered121    into point_list with a cursor. After that, the distance between122    successive points is computed. If the distance is less than the 123    maximum_distance, the cursor sets the SECTIONID for the point to the124    current value (starts with 1). If the maximum_distance is greater than125    the distance, the next distance is not computed. The point after126    next and the following points with a distance less maximum_distance get127    a SECTIONID + 1. After computing all distances between successive 128    points in this way, the SECTIONID is used as line field for the129    connection. After connecting the cross sections, a field 130    'INTERMEDIATEID' is added to the output feature class and set to 0131    with a cursor. 132    133    @param workspace (DEWorkspace): 134        The workspace for results.135    @param in_cross_sections (DEFeatureClass): 136        The feature class with the cross sections points.137    @param out_cross_sections (GPString): 138        The output feature class name.139    @param maximum_distance (GPDouble): 140        The maximum distance between points.141    142    @return out_cross_sections(DEFeatureClass): 143        The output cross section feature class.144    145    """ 146    logger.debug("Add a field SECTIONID.")147    field_name = "SECTIONID"148    field_type = "SHORT"149    arcpy.AddField_management(in_cross_sections, field_name, field_type)150    logger.info("Field SECTIONID added successfully.")151    logger.debug("Transfer coordinates into list point_list.")152    point_list = []153    field_names = ["SHAPE@X", "SHAPE@Y", "SHAPE@Z", "SECTIONID"]154    with arcpy.da.UpdateCursor(in_cross_sections, field_names) as cursor:155        for row in cursor:    156            point_list.append([row[0], row[1], row[2]])157    logger.info(str(len(point_list)) + " points transferred into point_list.")158        159    cursor.reset()160    logger.debug("Start creating the line_field SECTIONID.")161    i = 0162    j = 1163    for row in cursor:164        if i < (len(point_list) - 1):165            distance = (166                math.sqrt(math.pow(point_list[i + 1][0] - point_list[i][0], 2) 167                + math.pow(point_list[i + 1][1] - point_list[i][1], 2)168                + math.pow(point_list[i + 1][2] - point_list[i][2], 2))169                )170        row[3] = j171        cursor.updateRow(row)172        if distance > maximum_distance:173            j = j + 1174        i = i + 1175    logger.info("Set SECTIONID successfully until " + str (j) + ".")176    logger.debug("Start connecting cross sections to lines.")177    try:178        out_cross_sections = workspace + "/" + out_cross_sections_name179        line_field = "SECTIONID"180        arcpy.PointsToLine_management(181            in_cross_sections, out_cross_sections, line_field182            )183    except arcpy.ExecuteError:184        logger.warning(185            out_cross_sections + " already exists. Change output name: " 186            + out_cross_sections + time.strftime("%d%m%y_%H%M%S.")187            )188        out_cross_sections = (189            out_cross_sections + time.strftime("%d%m%y_%H%M%S")190            )191        arcpy.PointsToLine_management(192            in_cross_sections, out_cross_sections, line_field193            )194    logger.info("Connecting cross sections completed successfully.")195    196    logger.debug("Add a field INTERMEDIATEID.")197    field_name = "INTERMEDIATEID"198    arcpy.AddField_management(out_cross_sections, field_name, field_type)199    logger.info("Field INTERMEDIATEID added successfully.") 200    logger.debug("Create cursor for allocating the IDs.")201    field_names = ["INTERMEDIATEID"] 202    with arcpy.da.UpdateCursor(out_cross_sections, field_names) as cursor:203        for row in cursor:204            row[0] = 0205            cursor.updateRow(row)206    logger.info("Set INTERMEDIATEID successfully to 0.")207    208    return out_cross_sections209def check_duplicated_cross_sections(in_cross_sections):210    """Check if duplicated cross sections exist and delete one of them.211    212    First, the total number of cross sections is counted. A feature213    layer is created to select successive cross sections. For the214    selected cross sections it is checked, if their center is in the 215    other cross section. In this case the number of selected layers is216    2, otherwise the number is 1. If the number is 2, one of the two 217    cross sections (the first) is deleted. Finally, it is checked if 218    this case occured at all. If this is true, the SECTIONID is 219    adjusted to the correct values.220    221    @param in_cross_sections (DEFeatureClass): 222        The feature class with the cross sections.223        ...sections.js
Source:sections.js  
1// (C) Copyright 2015 Martin Dougiamas2//3// Licensed under the Apache License, Version 2.0 (the "License");4// you may not use this file except in compliance with the License.5// You may obtain a copy of the License at6//7//     http://www.apache.org/licenses/LICENSE-2.08//9// Unless required by applicable law or agreed to in writing, software10// distributed under the License is distributed on an "AS IS" BASIS,11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.12// See the License for the specific language governing permissions and13// limitations under the License.14angular.module('mm.core.course')15/**16 * Sections view controller.17 *18 * @module mm.core.course19 * @ngdoc controller20 * @name mmCourseSectionsCtrl21 */22.controller('mmCourseSectionsCtrl', function($mmCourse, $mmUtil, $scope, $stateParams, $translate, $mmCourseHelper, $mmEvents,23            $mmSite, $mmCoursePrefetchDelegate, $mmCourses, $q, $ionicHistory, $ionicPlatform, mmCoreCourseAllSectionsId,24            mmCoreEventSectionStatusChanged, $state, $timeout, $mmCoursesDelegate, $controller) {25    var courseId = $stateParams.courseid,26        sectionId = $stateParams.sid,27        moduleId = $stateParams.moduleid,28        course = $stateParams.course ? angular.copy($stateParams.course) : false;29    $scope.courseId = courseId;30    $scope.sectionToLoad = 2; // Load "General" section by default.31    $scope.fullname = course.fullname || "";32    $scope.downloadSectionsEnabled = $mmCourseHelper.isDownloadSectionsEnabled();33    $scope.downloadSectionsIcon = getDownloadSectionIcon();34    $scope.sectionHasContent = $mmCourseHelper.sectionHasContent;35    $scope.courseActions = [];36    function loadSections(refresh) {37        var promise;38        if (course) {39            promise = $q.when();40        } else {41            // We don't have the course name, get it.42            promise = $mmCourses.getUserCourse(courseId).catch(function() {43                // Fail, maybe user isn't enrolled but he has capabilities to view it.44                return $mmCourses.getCourse(courseId);45            }).then(function(courseResponse) {46                course = courseResponse;47                return course.fullname;48            }).catch(function() {49                // Fail again, return generic value.50                return $translate.instant('mm.core.course');51            });52        }53        return promise.then(function(courseFullName) {54            if (courseFullName) {55                $scope.fullname = courseFullName;56            }57            // Load course actions in background.58            $mmCoursesDelegate.getNavHandlersForCourse(course, refresh, true).then(function(buttons) {59                $scope.courseActions = buttons.map(function(button) {60                    var newScope = $scope.$new();61                    $controller(button.controller, {$scope: newScope});62                    var buttonInfo = {63                            text: $translate.instant(newScope.title),64                            icon: newScope.icon || false,65                            priority: button.priority || false,66                            action: function() {67                                // Fake event (already prevented) to avoid errors on app.68                                var ev = document.createEvent("MouseEvent");69                                return newScope.action(ev, course);70                            }71                        };72                    newScope.$destroy();73                    return buttonInfo;74                });75            });76            // Get the sections.77            return $mmCourse.getSections(courseId, false, true).then(function(sections) {78                sections = sections.map(function(section) {79                    section.name = section.name.trim() || section.section;80                    return section;81                });82                // Add a fake first section (all sections).83                var result = [{84                    name: $translate.instant('mm.course.allsections'),85                    id: mmCoreCourseAllSectionsId86                }].concat(sections);87                $scope.sections = result;88                if ($scope.downloadSectionsEnabled) {89                    calculateSectionStatus(refresh);90                }91            });92        }).catch(function(error) {93            $mmUtil.showErrorModalDefault(error, 'mm.course.couldnotloadsections', true);94        });95    }96    $scope.toggleDownloadSections = function() {97        $scope.downloadSectionsEnabled = !$scope.downloadSectionsEnabled;98        $mmCourseHelper.setDownloadSectionsEnabled($scope.downloadSectionsEnabled);99        $scope.downloadSectionsIcon = getDownloadSectionIcon();100        if ($scope.downloadSectionsEnabled) {101            calculateSectionStatus(false);102        }103    };104    // Convenience function to calculate icon for the contextual menu.105    function getDownloadSectionIcon() {106        return $scope.downloadSectionsEnabled ? 'ion-android-checkbox-outline' : 'ion-android-checkbox-outline-blank';107    }108    // Calculate status of the sections. We don't return the promise because109    // we don't want to block the rendering of the sections.110    function calculateSectionStatus(refresh) {111        $mmCourseHelper.calculateSectionsStatus($scope.sections, $scope.courseId, true, refresh).catch(function() {112            // Ignore errors (shouldn't happen).113        }).then(function(downloadpromises) {114            // If we restored any download we'll recalculate the status once all of them have finished.115            if (downloadpromises && downloadpromises.length) {116                $mmUtil.allPromises(downloadpromises).catch(function() {117                    if (!$scope.$$destroyed) {118                        $mmUtil.showErrorModal('mm.course.errordownloadingsection', true);119                    }120                }).finally(function() {121                    if (!$scope.$$destroyed) {122                        // Recalculate the status.123                        $mmCourseHelper.calculateSectionsStatus($scope.sections, $scope.courseId, false);124                    }125                });126            }127        });128    }129    // Prefetch a section. The second parameter indicates if the prefetch was started manually (true)130    // or it was automatically started because all modules are being downloaded (false).131    function prefetch(section, manual) {132        $mmCourseHelper.prefetch(section, courseId, $scope.sections).catch(function() {133            // Don't show error message if scope is destroyed or it's an automatic download but we aren't in this state.134            if ($scope.$$destroyed) {135                return;136            }137            var current = $ionicHistory.currentStateName(),138                isCurrent = ($ionicPlatform.isTablet() && current == 'site.mm_course.mm_course-section') ||139                            (!$ionicPlatform.isTablet() && current == 'site.mm_course');140            if (!manual && !isCurrent) {141                return;142            }143            $mmUtil.showErrorModal('mm.course.errordownloadingsection', true);144        }).finally(function() {145            if (!$scope.$$destroyed) {146                // Recalculate the status.147                $mmCourseHelper.calculateSectionsStatus($scope.sections, courseId, false);148            }149        });150    }151    // Convenience function to autoload a section if sectionId param is set.152    function autoloadSection() {153        if (sectionId) {154            if ($ionicPlatform.isTablet()) {155                // Search the position of the section to load.156                angular.forEach($scope.sections, function(section, index) {157                    if (section.id == sectionId) {158                        $scope.sectionToLoad = index + 1;159                    }160                });161                // Set moduleId to pass it to the new state when the section is autoloaded. We unset it after this162                // to prevent autoloading the module when the user manually loads a section.163                $scope.moduleId = moduleId;164                $timeout(function() {165                    $scope.moduleId = null; // Unset moduleId when166                }, 500);167            } else {168                $state.go('site.mm_course-section', {169                    sectionid: sectionId,170                    cid: courseId,171                    mid: moduleId172                });173            }174        }175    }176    $scope.doRefresh = function() {177        var promises = [];178        promises.push($mmCourses.invalidateUserCourses());179        promises.push($mmCourse.invalidateSections(courseId));180        if ($scope.sections && $scope.downloadSectionsEnabled) {181            // Invalidate modules prefetch data.182            var modules = $mmCourseHelper.getSectionsModules($scope.sections);183            promises.push($mmCoursePrefetchDelegate.invalidateModules(modules, courseId));184        }185        promises.push($mmCoursesDelegate.clearAndInvalidateCoursesOptions(courseId));186        $q.all(promises).finally(function() {187            loadSections(true).finally(function() {188                $scope.$broadcast('scroll.refreshComplete');189            });190        });191    };192    $scope.prefetch = function(e, section) {193        e.preventDefault();194        e.stopPropagation();195        section.isCalculating = true;196        $mmCourseHelper.confirmDownloadSize(courseId, section, $scope.sections).then(function() {197            prefetch(section, true);198        }).finally(function() {199            section.isCalculating = false;200        });201    };202    loadSections().finally(function() {203        autoloadSection();204        $scope.sectionsLoaded = true;205    });206    // Listen for section status changes.207    var statusObserver = $mmEvents.on(mmCoreEventSectionStatusChanged, function(data) {208        if ($scope.downloadSectionsEnabled && $scope.sections && $scope.sections.length && data.siteid === $mmSite.getId() &&209                    !$scope.$$destroyed && data.sectionid) {210            // Check if the affected section is being downloaded. If so, we don't update section status211            // because it'll already be updated when the download finishes.212            if ($mmCoursePrefetchDelegate.isBeingDownloaded($mmCourseHelper.getSectionDownloadId({id: data.sectionid}))) {213                return;214            }215            // Recalculate the status.216            $mmCourseHelper.calculateSectionsStatus($scope.sections, courseId, false).then(function() {217                var section;218                angular.forEach($scope.sections, function(s) {219                    if (s.id === data.sectionid) {220                        section = s;221                    }222                });223                if (section) {224                    var downloadid = $mmCourseHelper.getSectionDownloadId(section);225                    if (section.isDownloading && !$mmCoursePrefetchDelegate.isBeingDownloaded(downloadid)) {226                        // All the modules are now downloading, set a download all promise.227                        prefetch(section, false);228                    }229                }230            });231        }232    });233    $scope.$on('$destroy', function() {234        statusObserver && statusObserver.off && statusObserver.off();235    });...section-config.test.js
Source:section-config.test.js  
1/**2 * Copyright © Magento, Inc. All rights reserved.3 * See COPYING.txt for license details.4 */5/* eslint max-nested-callbacks: 0 */6define(['squire'], function (Squire) {7    'use strict';8    var injector = new Squire(),9        obj;10    beforeEach(function (done) {11        // injector.mock(mocks);12        injector.require(['Magento_Customer/js/section-config'], function (Constr) {13            obj = Constr;14            done();15        });16    });17    afterEach(function () {18        try {19            injector.clean();20            injector.remove();21        } catch (e) {}22    });23    describe('Magento_Customer/js/section-config', function () {24        describe('"getAffectedSections" method', function () {25            it('Does not throw before component is initialized.', function () {26                expect(function () {27                    obj.getAffectedSections('http://localhost.com/path');28                }).not.toThrow();29            });30            it('Returns proper sections when URL contains base URL.', function () {31                obj['Magento_Customer/js/section-config']({32                    sections: {33                        'path': [34                            'section'35                        ]36                    },37                    baseUrls: [38                        'http://localhost.com/',39                        'https://localhost.com/'40                    ]41                });42                expect(obj.getAffectedSections('https://localhost.com/path')).toEqual(['section']);43            });44            it('Returns proper sections when glob pattern is used at the end.', function () {45                obj['Magento_Customer/js/section-config']({46                    sections: {47                        'path/*': [48                            'section'49                        ]50                    },51                    baseUrls: [52                        'http://localhost.com/',53                        'https://localhost.com/'54                    ]55                });56                expect(obj.getAffectedSections('https://localhost.com/path/subpath')).toEqual(['section']);57            });58            it('Returns proper sections when glob pattern is used inside.', function () {59                obj['Magento_Customer/js/section-config']({60                    sections: {61                        '*/subpath': [62                            'section'63                        ]64                    },65                    baseUrls: [66                        'http://localhost.com/',67                        'https://localhost.com/'68                    ]69                });70                expect(obj.getAffectedSections('https://localhost.com/path/subpath')).toEqual(['section']);71            });72            it('Strips "index.php" suffix from provided URL.', function () {73                obj['Magento_Customer/js/section-config']({74                    sections: {75                        'path': [76                            'section'77                        ]78                    },79                    baseUrls: [80                        'http://localhost.com/'81                    ]82                });83                expect(obj.getAffectedSections('http://localhost.com/path/index.php')).toEqual(['section']);84            });85            it('Adds sections for all URLs "*" to found ones.', function () {86                obj['Magento_Customer/js/section-config']({87                    sections: {88                        'path': [89                            'section'90                        ],91                        '*': [92                            'all'93                        ]94                    },95                    baseUrls: [96                        'http://localhost.com/'97                    ]98                });99                expect(obj.getAffectedSections('http://localhost.com/path')).toEqual(['section', 'all']);100            });101            it('Returns "*" sections for all URLs.', function () {102                obj['Magento_Customer/js/section-config']({103                    sections: {104                        '*': [105                            'all'106                        ]107                    },108                    baseUrls: [109                        'http://localhost.com/'110                    ]111                });112                expect(obj.getAffectedSections('http://localhost.com/path')).toEqual(['all']);113            });114            it('Ignores capitalization in parts of URL.', function () {115                obj['Magento_Customer/js/section-config']({116                    sections: {117                        'path': [118                            'section'119                        ]120                    },121                    baseUrls: [122                        'http://localhost.com/'123                    ]124                });125                expect(obj.getAffectedSections('http://localhost.com/PaTh')).toEqual(['section']);126            });127        });128        describe('"filterClientSideSections" method', function () {129            it('Does not throw before component is initialized.', function () {130                expect(function () {131                    obj.filterClientSideSections();132                }).not.toThrow();133            });134            it('Returns empty array when all sections are client side.', function () {135                var sections = ['test'];136                obj['Magento_Customer/js/section-config']({137                    clientSideSections: sections138                });139                expect(obj.filterClientSideSections(sections)).toEqual([]);140            });141            it('Filters out client side sections.', function () {142                var allSections = ['test', 'client'],143                    clientSections = ['client'];144                obj['Magento_Customer/js/section-config']({145                    clientSideSections: clientSections146                });147                expect(obj.filterClientSideSections(allSections)).toEqual(['test']);148            });149        });150        describe('"isClientSideSection" method', function () {151            it('Does not throw before component is initialized.', function () {152                expect(function () {153                    obj.isClientSideSection();154                }).not.toThrow();155            });156            it('Returns true if section is defined as client side.', function () {157                obj['Magento_Customer/js/section-config']({158                    clientSideSections: ['client']159                });160                expect(obj.isClientSideSection('client')).toBe(true);161            });162            it('Returns false if section is not defined as client side.', function () {163                obj['Magento_Customer/js/section-config']({164                    clientSideSections: ['client']165                });166                expect(obj.isClientSideSection('test')).toBe(false);167            });168            it('Returns false if section is not client side and sections are not defined.', function () {169                obj['Magento_Customer/js/section-config']({170                    clientSideSections: []171                });172                expect(obj.isClientSideSection('test')).toBe(false);173            });174        });175        describe('"getSectionNames" method', function () {176            it('Does not throw before component is initialized.', function () {177                expect(function () {178                    obj.getSectionNames();179                }).not.toThrow();180            });181            it('Returns defined section names.', function () {182                var sections = ['test'];183                obj['Magento_Customer/js/section-config']({184                    sectionNames: sections185                });186                expect(obj.getSectionNames()).toBe(sections);187            });188        });189    });...Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!
