Annotation of GNUtools/cctools/as/layout.c, revision 1.1

1.1     ! root        1: /* layout.c (was part of write.c in original GAS version)
        !             2:    Copyright (C) 1986,1987 Free Software Foundation, Inc.
        !             3: 
        !             4: This file is part of GAS, the GNU Assembler.
        !             5: 
        !             6: GAS is free software; you can redistribute it and/or modify
        !             7: it under the terms of the GNU General Public License as published by
        !             8: the Free Software Foundation; either version 1, or (at your option)
        !             9: any later version.
        !            10: 
        !            11: GAS is distributed in the hope that it will be useful,
        !            12: but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        !            14: GNU General Public License for more details.
        !            15: 
        !            16: You should have received a copy of the GNU General Public License
        !            17: along with GAS; see the file COPYING.  If not, write to
        !            18: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
        !            19: 
        !            20: #include <stdlib.h>
        !            21: #include <string.h>
        !            22: #include "stuff/round.h"
        !            23: #include "as.h"
        !            24: #include "sections.h"
        !            25: #include "frags.h"
        !            26: #include "symbols.h"
        !            27: #include "fixes.h"
        !            28: #include "messages.h"
        !            29: #include "expr.h"
        !            30: #include "md.h"
        !            31: #include "obstack.h"
        !            32: 
        !            33: static void fixup_section(
        !            34:     fixS *fixP,
        !            35:     int nsect);
        !            36: static void relax_section(
        !            37:     struct frag *section_frag_root,
        !            38:     int nsect);
        !            39: static relax_addressT relax_align(
        !            40:     relax_addressT address,
        !            41:     long alignment);
        !            42: static int is_down_range(
        !            43:     struct frag *f1,
        !            44:     struct frag *f2);
        !            45: 
        !            46: /*
        !            47:  * layout_addresses() is called after all the assembly code has been read and
        !            48:  * fragments, symbols and fixups have been created.  This routine sets the
        !            49:  * address of the fragments and symbols.  Then it does the fixups of the frags
        !            50:  * and prepares the fixes so relocation entries can be created from them.
        !            51:  */
        !            52: void
        !            53: layout_addresses(
        !            54: void)
        !            55: {
        !            56:     struct frchain *frchainP;
        !            57:     fragS *fragP;
        !            58:     relax_addressT slide, tmp;
        !            59:     symbolS *symbolP;
        !            60: 
        !            61:        if(frchain_root == NULL)
        !            62:            return;
        !            63: 
        !            64:        /*
        !            65:         * If there is any current frag close it off.
        !            66:         */
        !            67:        if(frag_now != NULL && frag_now->fr_fix == 0){
        !            68:            frag_now->fr_fix = obstack_next_free(&frags) -
        !            69:                               frag_now->fr_literal;
        !            70:            frag_wane(frag_now);
        !            71:        }
        !            72: 
        !            73:        /*
        !            74:         * For every section, add a last ".fill 0" frag that will later be used
        !            75:         * as the ending address of that section.
        !            76:         */
        !            77:        for(frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next){
        !            78:            /*
        !            79:             * We must do the obstack_finish(), so the next object we put on
        !            80:             * obstack frags will not appear to start at the fr_literal of the
        !            81:             * current frag.  Also, it ensures that the next object will begin
        !            82:             * on a address that is aligned correctly for the engine that runs
        !            83:             * the assembler.
        !            84:             */
        !            85:            obstack_finish(&frags);
        !            86: 
        !            87:            /*
        !            88:             * Make a fresh frag for the last frag.
        !            89:             */
        !            90:            frag_now = (fragS *)obstack_alloc(&frags, SIZEOF_STRUCT_FRAG);
        !            91:            memset(frag_now, '\0', SIZEOF_STRUCT_FRAG);
        !            92:            frag_now->fr_next = NULL;
        !            93:            obstack_finish(&frags);
        !            94: 
        !            95:            /*
        !            96:             * Append the new frag to current frchain.
        !            97:             */
        !            98:            frchainP->frch_last->fr_next = frag_now;
        !            99:            frchainP->frch_last = frag_now;
        !           100:            frag_wane(frag_now);
        !           101: 
        !           102:        }
        !           103: 
        !           104:        /*
        !           105:         * Now set the relitive addresses of frags within the section by
        !           106:         * relaxing each section.  That is all sections will start at address
        !           107:         * zero and addresses of the frags in that section will increase from
        !           108:         * there.
        !           109:         */
        !           110:        for(frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next){
        !           111:            if((frchainP->frch_section.flags & SECTION_TYPE) == S_ZEROFILL)
        !           112:                continue;
        !           113:            /*
        !           114:             * This is done so in case md_estimate_size_before_relax() (called
        !           115:             * by relax_section) wants to make fixSs they are for this
        !           116:             * section.
        !           117:             */
        !           118:            frchain_now = frchainP;
        !           119: 
        !           120:            relax_section(frchainP->frch_root, frchainP->frch_nsect);
        !           121:        }
        !           122: 
        !           123:        /*
        !           124:         * Now set the absolute addresses of all frags by sliding the frags in
        !           125:         * each non-zerofill section by the address ranges taken up by the
        !           126:         * sections before it.
        !           127:         */ 
        !           128:        slide = 0;
        !           129:        for(frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next){
        !           130:            if((frchainP->frch_section.flags & SECTION_TYPE) == S_ZEROFILL)
        !           131:                continue;
        !           132:            slide = round(slide, 1 << frchainP->frch_section.align);
        !           133:            tmp = frchainP->frch_last->fr_address;
        !           134:            if(slide != 0){
        !           135:                for(fragP = frchainP->frch_root; fragP; fragP = fragP->fr_next){
        !           136:                    fragP->fr_address += slide;
        !           137:                }
        !           138:            }
        !           139:            slide += tmp;
        !           140:        }
        !           141:        /*
        !           142:         * Now with the non-zerofill section addresses set set all of the
        !           143:         * addresses of the zerofill sections.  Comming in the fr_address is
        !           144:         * the size of the section and going out it is the start address.  This
        !           145:         * will make layout_symbols() work out naturally.  The only funky thing
        !           146:         * is that section numbers do not end up in address order.
        !           147:         */
        !           148:        for(frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next){
        !           149:            if((frchainP->frch_section.flags & SECTION_TYPE) != S_ZEROFILL)
        !           150:                continue;
        !           151:            slide = round(slide, 1 << frchainP->frch_section.align);
        !           152: 
        !           153:            tmp = frchainP->frch_root->fr_address;
        !           154:            frchainP->frch_root->fr_address = slide;
        !           155:            frchainP->frch_last->fr_address = tmp + slide;
        !           156:            slide += tmp;
        !           157:        }
        !           158: 
        !           159:        /*
        !           160:         * Set the symbol addresses based on there frag's address.
        !           161:         * First forward references are handled.
        !           162:         */
        !           163:        for(symbolP = symbol_rootP; symbolP; symbolP = symbolP->sy_next){
        !           164:            if(symbolP->sy_forward != NULL){
        !           165:                if(symbolP->sy_nlist.n_type & N_STAB)
        !           166:                    symbolP->sy_other = symbolP->sy_forward->sy_other;
        !           167:                symbolP->sy_value += symbolP->sy_forward->sy_value +
        !           168:                                     symbolP->sy_forward->sy_frag->fr_address;
        !           169:                symbolP->sy_forward = 0;
        !           170:            }
        !           171:        }
        !           172:        for(symbolP = symbol_rootP; symbolP; symbolP = symbolP->sy_next){
        !           173:            symbolP->sy_value += symbolP->sy_frag->fr_address;
        !           174:        }
        !           175: 
        !           176:        /*
        !           177:         * At this point the addresses of frags now reflect addresses we use in 
        !           178:         * the object file and the symbol values are correct.
        !           179:         * Scan the frags, converting any ".org"s and ".align"s to ".fill"s.
        !           180:         * Also converting any machine-dependent frags using md_convert_frag();
        !           181:         */
        !           182:        for(frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next){
        !           183:            /*
        !           184:             * This is done so any fixes created by md_convert_frag() are for
        !           185:             * this section.
        !           186:             */
        !           187:            frchain_now = frchainP;
        !           188: 
        !           189:            for(fragP = frchainP->frch_root; fragP; fragP = fragP->fr_next){
        !           190:                switch(fragP->fr_type){
        !           191:                case rs_align:
        !           192:                case rs_org:
        !           193:                    fragP->fr_type = rs_fill;
        !           194:                    know(fragP->fr_var == 1);
        !           195:                    know(fragP->fr_next != NULL);
        !           196:                    fragP->fr_offset = fragP->fr_next->fr_address -
        !           197:                                       fragP->fr_address -
        !           198:                                       fragP->fr_fix;
        !           199:                    break;
        !           200: 
        !           201:                case rs_fill:
        !           202:                    break;
        !           203: 
        !           204:                case rs_machine_dependent:
        !           205:                    md_convert_frag(fragP);
        !           206:                    /*
        !           207:                     * After md_convert_frag, we make the frag into a ".fill 0"
        !           208:                     * md_convert_frag() should set up any fixSs and constants
        !           209:                     * required.
        !           210:                     */
        !           211:                    frag_wane(fragP);
        !           212:                    break;
        !           213: 
        !           214:                default:
        !           215:                    BAD_CASE(fragP->fr_type);
        !           216:                    break;
        !           217:                }
        !           218:            }
        !           219:        }
        !           220: 
        !           221:        /*
        !           222:         * For each section do the fixups for the frags.
        !           223:         */
        !           224:        for(frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next){
        !           225:            fixup_section(frchainP->frch_fix_root, frchainP->frch_nsect);
        !           226:        }
        !           227: }
        !           228: 
        !           229: /*
        !           230:  * fixup_section() does the fixups of the frags and prepares the fixes so
        !           231:  * relocation entries can be created from them.  The fixups cause the contents
        !           232:  * of the frag to have the value for the fixup expression.  A fix structure that
        !           233:  * ends up with a non NULL fx_addsy will have a relocation entry created for it.
        !           234:  */
        !           235: static
        !           236: void
        !           237: fixup_section(
        !           238: fixS *fixP,
        !           239: int nsect)
        !           240: {
        !           241:     symbolS *add_symbolP;
        !           242:     symbolS *sub_symbolP;
        !           243:     long value;
        !           244:     int size;
        !           245:     char *place;
        !           246:     long where;
        !           247:     char pcrel;
        !           248:     fragS *fragP;
        !           249:     int        add_symbol_N_TYPE;
        !           250:     int        add_symbol_nsect;
        !           251: 
        !           252:        /*
        !           253:         * The general fix expression is "fx_addsy - fx_subsy + fx_offset".
        !           254:         * The goal is to put the result of this expression into the frag at
        !           255:         * "place" for size "size".  The value of the expression is calculated
        !           256:         * in the variable "value" and starts with just the fx_offset.
        !           257:         */
        !           258:        for( ; fixP != NULL; fixP = fixP->fx_next){
        !           259:            fragP       = fixP->fx_frag;
        !           260:            know(fragP);
        !           261:            where       = fixP->fx_where;
        !           262:            place       = fragP->fr_literal + where;
        !           263:            size        = fixP->fx_size;
        !           264:            add_symbolP = fixP->fx_addsy;
        !           265:            sub_symbolP = fixP->fx_subsy;
        !           266:            value       = fixP->fx_offset;
        !           267:            pcrel       = fixP->fx_pcrel;
        !           268: 
        !           269:            add_symbol_N_TYPE = 0;
        !           270:            add_symbol_nsect = 0;
        !           271: 
        !           272:            if(add_symbolP != NULL){
        !           273:                add_symbol_N_TYPE = add_symbolP->sy_type & N_TYPE;
        !           274:                if(add_symbol_N_TYPE == N_SECT)
        !           275:                    add_symbol_nsect = add_symbolP->sy_other;
        !           276:            }
        !           277: 
        !           278:            /*
        !           279:             * Is there a subtract symbol?
        !           280:             */
        !           281:            if(sub_symbolP){
        !           282:                /* is it just -sym ? */
        !           283:                if(add_symbolP == NULL){
        !           284:                    if(sub_symbolP->sy_type != N_ABS)
        !           285:                        as_warn("Negative of non-absolute symbol %s",
        !           286:                                sub_symbolP->sy_name);
        !           287:                    value -= sub_symbolP->sy_value;
        !           288:                    fixP->fx_subsy = NULL;
        !           289:                }
        !           290:                /*
        !           291:                 * There are both an add symbol and a subtract symbol at this
        !           292:                 * point.
        !           293:                 *
        !           294:                 * If both symbols are absolute then just calculate the
        !           295:                 * value of the fix expression and no relocation entry will be
        !           296:                 * needed.
        !           297:                 */
        !           298:                else if((sub_symbolP->sy_type & N_TYPE) == N_ABS &&
        !           299:                        (add_symbolP->sy_type & N_TYPE) == N_ABS){
        !           300:                    value += add_symbolP->sy_value - sub_symbolP->sy_value;
        !           301:                    add_symbolP = NULL;
        !           302:                    fixP->fx_addsy = NULL; /* no relocation entry */
        !           303:                    fixP->fx_subsy = NULL;
        !           304:                }
        !           305:                /*
        !           306:                 * If both symbols are defined in a section then calculate the
        !           307:                 * value of the fix expression and let a section difference
        !           308:                 * relocation entry be created.
        !           309:                 */
        !           310:                else if((sub_symbolP->sy_type & N_TYPE) == N_SECT &&
        !           311:                        (add_symbolP->sy_type & N_TYPE) == N_SECT){
        !           312:                    /*
        !           313:                     * If we are allowed to use the new features that are
        !           314:                     * incompatible with 3.2 then just calculate the value and
        !           315:                     * let this create a SECTDIFF relocation type.
        !           316:                     */
        !           317:                    if(flagseen['k']){
        !           318:                        value += add_symbolP->sy_value - sub_symbolP->sy_value;
        !           319:                        goto down;
        !           320:                    }
        !           321:                    else{
        !           322:                        /*
        !           323:                         * This logic works only if the two symbols can't later
        !           324:                         * be separated by scattered loading.  To make sure that
        !           325:                         * this can't happen we would have to make sure all
        !           326:                         * symbols associated with addresses between these two
        !           327:                         * symbols including the add symbol are of the Lx form
        !           328:                         * and the -L flag is not see so they will not appear
        !           329:                         * in the output (if they are not in the output then the
        !           330:                         * link editor can't separate the chain of frags by
        !           331:                         * scattered loading).  Since this code does not make
        !           332:                         * sure of this it is broken.  But this is a known bug
        !           333:                         * in the NeXT 3.2 and earilier releases so this code is
        !           334:                         * if'ed !flagseen['k'] and will make it compatable with
        !           335:                         * 3.2 and previous releases.
        !           336:                         */
        !           337:                        if(sub_symbolP->sy_other == add_symbolP->sy_other){
        !           338:                            value += add_symbolP->sy_value -
        !           339:                                     sub_symbolP->sy_value;
        !           340:                            add_symbolP = NULL;
        !           341:                            fixP->fx_addsy = NULL; /* no relocation entry */
        !           342:                            fixP->fx_subsy = NULL;
        !           343:                        }
        !           344:                        else{
        !           345:                            as_warn("Can't emit reloc {- symbol \"%s\"} @ file "
        !           346:                                    "address %ld.", sub_symbolP->sy_name,
        !           347:                                    fragP->fr_address + where);
        !           348:                        }
        !           349:                    }
        !           350:                }
        !           351:                /*
        !           352:                 * If the subtract symbol is absolute subtract it's value from
        !           353:                 * the fix expression and let a relocation entry get created
        !           354:                 * that is not a section difference type.
        !           355:                 */
        !           356:                else if(sub_symbolP->sy_type == N_ABS){
        !           357:                    value -= sub_symbolP->sy_value;
        !           358:                    fixP->fx_subsy = NULL; /* no SECTDIFF relocation entry */
        !           359:                }
        !           360:                /*
        !           361:                 * At this point we have something we can't generate a
        !           362:                 * relocation entry for (two undefined symbols, etc.).
        !           363:                 */
        !           364:                else{
        !           365:                     as_warn("Can't emit reloc {- symbol \"%s\"} @ file "
        !           366:                             "address %ld.", sub_symbolP->sy_name,
        !           367:                             fragP->fr_address + where);
        !           368:                }
        !           369:            }
        !           370: 
        !           371:            /*
        !           372:             * If a there is an add symbol in the fixup expression then add
        !           373:             * the symbol value into the fixup expression's value.
        !           374:             */
        !           375:            if(add_symbolP){
        !           376:                /*
        !           377:                 * If this symbol is in this section and is pc-relative and we
        !           378:                 * do not want to force a pc-relative relocation entry (to
        !           379:                 * support scattered loading) then just calculate the value.
        !           380:                 */
        !           381:                if(add_symbol_nsect == nsect &&
        !           382:                   pcrel && !(fixP->fx_pcrel_reloc)){
        !           383:                    /*
        !           384:                     * This fixup was made when the symbol's section was
        !           385:                     * unknown, but it is now in this section. So we know how
        !           386:                     * to do the address without relocation.
        !           387:                     */
        !           388:                    value += add_symbolP->sy_value;
        !           389:                    value -= size + where + fragP->fr_address;
        !           390:                    pcrel = 0;  /* Lie. Don't want further pcrel processing. */
        !           391:                    fixP->fx_addsy = NULL; /* No relocations please. */
        !           392:                    /*
        !           393:                     * It would be nice to check that the address does not
        !           394:                     * overflow.
        !           395:                     * I didn't do this check because:
        !           396:                     * +  It is machine dependent in the general case (eg 32032)
        !           397:                     * +  Compiler output will never need this checking, so why
        !           398:                     *    slow down the usual case?
        !           399:                     */
        !           400:                }
        !           401:                else{
        !           402:                    switch(add_symbol_N_TYPE){
        !           403:                    case N_ABS:
        !           404:                        value += add_symbolP->sy_value;
        !           405:                        fixP->fx_addsy = NULL; /* no relocation entry */
        !           406:                        add_symbolP = NULL;
        !           407:                        break;
        !           408:                        
        !           409:                    case N_SECT:
        !           410:                        value += add_symbolP->sy_value;
        !           411:                        break;
        !           412:                        
        !           413:                    case N_UNDF:
        !           414:                        break;
        !           415:                        
        !           416:                    default:
        !           417:                        BAD_CASE(add_symbol_N_TYPE);
        !           418:                        break;
        !           419:                    }
        !           420:                }
        !           421:            }
        !           422: down:
        !           423:            /*
        !           424:             * If the fixup expression is pc-relative then the value of the pc
        !           425:             * will be added to the expression when the machine executes the
        !           426:             * the instruction so we adjust the fixup expression's value by
        !           427:             * subtracting off the pc value (where) and adjust for insn size.
        !           428:             */
        !           429:            if(pcrel){
        !           430:                value -= size + where + fragP->fr_address;
        !           431:                if(add_symbolP == NULL){
        !           432:                    fixP->fx_addsy = &abs_symbol; /* force relocation entry */
        !           433:                }
        !           434:            }
        !           435: 
        !           436:            if((size == 1 && (value & 0xffffff00) &&
        !           437:                            ((value & 0xffffff80) != 0xffffff80)) ||
        !           438:               (size == 2 && (value & 0xffff8000) &&
        !           439:                            ((value & 0xffff8000) != 0xffff8000)))
        !           440:                as_warn("Fixup of %ld too large for field width of %d",
        !           441:                        value, size);
        !           442: 
        !           443:            /*
        !           444:             * Now place the fix expression's value in the place for the size.
        !           445:             * And save the fix expression's value to be used when creating
        !           446:             * a relocation entry if required.
        !           447:             */
        !           448:            md_number_to_imm(place, value, size, fixP, nsect);
        !           449:            fixP->fx_value = value;
        !           450:        }
        !           451: }
        !           452: 
        !           453: 
        !           454: /*
        !           455:  * relax_section() here we set the fr_address values in the frags.
        !           456:  * After this, all frags in this segment have addresses that are correct
        !           457:  * relative to the section (that is the section starts at address zero).
        !           458:  * After all of the sections have been processed by this call and their sizes
        !           459:  * are know then they can be slid to their final address.
        !           460:  */
        !           461: static
        !           462: void
        !           463: relax_section(
        !           464: struct frag *frag_root,
        !           465: int nsect)
        !           466: {
        !           467:     struct frag *fragP;
        !           468:     relax_addressT address;
        !           469: 
        !           470:     long stretch; /* May be any size, 0 or negative. */
        !           471:                  /* Cumulative number of addresses we have */
        !           472:                  /* relaxed this pass. */
        !           473:                  /* We may have relaxed more than one address. */
        !           474:     long stretched;  /* Have we stretched on this pass? */
        !           475:                    /* This is 'cuz stretch may be zero, when,
        !           476:                       in fact some piece of code grew, and
        !           477:                       another shrank.  If a branch instruction
        !           478:                       doesn't fit anymore, we need another pass */
        !           479: 
        !           480:     const relax_typeS *this_type;
        !           481:     const relax_typeS *start_type;
        !           482:     relax_substateT next_state;
        !           483:     relax_substateT this_state;
        !           484: 
        !           485:     long growth;
        !           486:     long was_address;
        !           487:     long offset;
        !           488:     symbolS *symbolP;
        !           489:     long target;
        !           490:     long after;
        !           491:     long aim;
        !           492: 
        !           493:        growth = 0;
        !           494: 
        !           495:        /*
        !           496:         * For each frag in segment count and store (a 1st guess of) fr_address.
        !           497:         */
        !           498:        address = 0;
        !           499:        for(fragP = frag_root; fragP != NULL; fragP = fragP->fr_next){
        !           500:            fragP->fr_address = address;
        !           501:            address += fragP->fr_fix;
        !           502:            switch(fragP->fr_type){
        !           503:            case rs_fill:
        !           504:                address += fragP->fr_offset * fragP->fr_var;
        !           505:                break;
        !           506: 
        !           507:            case rs_align:
        !           508:                address += relax_align(address, fragP->fr_offset);
        !           509:                break;
        !           510: 
        !           511:            case rs_org:
        !           512:                /*
        !           513:                 * Assume .org is nugatory. It will grow with 1st relax.
        !           514:                 */
        !           515:                break;
        !           516: 
        !           517:            case rs_machine_dependent:
        !           518:                address += md_estimate_size_before_relax(fragP, nsect);
        !           519:                break;
        !           520: 
        !           521:            default:
        !           522:                BAD_CASE(fragP->fr_type);
        !           523:                break;
        !           524:            }
        !           525:        }
        !           526: 
        !           527:        /*
        !           528:         * Do relax().
        !           529:         * Make repeated passes over the chain of frags allowing each frag to
        !           530:         * grow if needed.  On each pass each frag's address is incremented by
        !           531:         * the accumulated growth, kept in stretched.  Passes are continued 
        !           532:         * until there is no stretch on the previous pass.
        !           533:         */
        !           534:        do{
        !           535:            stretch = 0;
        !           536:            stretched = 0;
        !           537:            for(fragP = frag_root; fragP != NULL; fragP = fragP->fr_next){
        !           538:                was_address = fragP->fr_address;
        !           539:                fragP->fr_address += stretch;
        !           540:                address = fragP->fr_address;
        !           541:                symbolP = fragP->fr_symbol;
        !           542:                offset = fragP->fr_offset;
        !           543:                switch(fragP->fr_type){
        !           544:                case rs_fill:   /* .fill never relaxes. */
        !           545:                    growth = 0;
        !           546:                    break;
        !           547: 
        !           548:                case rs_align:
        !           549:                    growth = relax_align((relax_addressT)
        !           550:                                         (address + fragP->fr_fix), offset) -
        !           551:                             relax_align((relax_addressT)
        !           552:                                         (was_address + fragP->fr_fix), offset);
        !           553:                    break;
        !           554: 
        !           555:                case rs_org:
        !           556:                    target = offset;
        !           557:                    if(symbolP != NULL){
        !           558:                        know(((symbolP->sy_type & N_TYPE) == N_ABS) ||
        !           559:                             ((symbolP->sy_type & N_TYPE) == N_SECT));
        !           560:                        know(symbolP->sy_frag);
        !           561:                        know((symbolP->sy_type & N_TYPE) != N_ABS ||
        !           562:                             symbolP->sy_frag == &zero_address_frag );
        !           563:                        target += symbolP->sy_value +
        !           564:                                  symbolP->sy_frag->fr_address;
        !           565:                    }
        !           566:                    know(fragP->fr_next);
        !           567:                    after = fragP->fr_next->fr_address;
        !           568:                    /*
        !           569:                     * Growth may be negative, but variable part of frag cannot
        !           570:                     * have < 0 chars. That is, we can't .org backwards.
        !           571:                     */
        !           572:                    growth = ((target - after ) > 0) ? (target - after) : 0;
        !           573: 
        !           574:                    growth -= stretch;  /* This is an absolute growth factor */
        !           575:                    break;
        !           576: 
        !           577:                case rs_machine_dependent:
        !           578:                    this_state = fragP->fr_subtype;
        !           579:                    this_type = md_relax_table + this_state;
        !           580:                    start_type = this_type;
        !           581: 
        !           582:                    target = offset;
        !           583:                    if(symbolP){
        !           584:                        know(((symbolP->sy_type & N_TYPE) == N_ABS) ||
        !           585:                             ((symbolP->sy_type & N_TYPE) == N_SECT));
        !           586:                        know(symbolP->sy_frag);
        !           587:                        know((symbolP->sy_type & N_TYPE) != N_ABS ||
        !           588:                             symbolP->sy_frag == &zero_address_frag);
        !           589: 
        !           590:                        target += symbolP->sy_value +
        !           591:                                  symbolP->sy_frag->fr_address;
        !           592:                        /*
        !           593:                         * If frag has yet to be reached on this pass,
        !           594:                         * assume it will move by STRETCH just as we did.
        !           595:                         * If this is not so, it will be because some frag
        !           596:                         * between grows, and that will force another pass.
        !           597:                         */
        !           598:                        if(symbolP->sy_frag->fr_address >= was_address &&
        !           599:                           is_down_range(fragP, symbolP->sy_frag))
        !           600:                            target += stretch;
        !           601:                    }
        !           602:                    aim = target - address - fragP->fr_fix;
        !           603:                    if(aim < 0){
        !           604:                        /* Look backwards. */
        !           605:                        for(next_state = this_type->rlx_more; next_state; ){
        !           606:                            if(aim >= this_type->rlx_backward)
        !           607:                                next_state = 0;
        !           608:                            else{       /* Grow to next state. */
        !           609:                                this_state = next_state;
        !           610:                                this_type = md_relax_table + this_state;
        !           611:                                next_state = this_type->rlx_more;
        !           612:                            }
        !           613:                        }
        !           614:                    }
        !           615:                    else{
        !           616:                        /* Look forwards. */
        !           617:                        for(next_state = this_type->rlx_more; next_state; ){
        !           618:                            if(aim <= this_type->rlx_forward)
        !           619:                                next_state = 0;
        !           620:                            else{       /* Grow to next state. */
        !           621:                                this_state = next_state;
        !           622:                                this_type = md_relax_table + this_state;
        !           623:                                next_state = this_type->rlx_more;
        !           624:                            }
        !           625:                        }
        !           626:                    }
        !           627:                    if((growth = this_type->rlx_length -start_type->rlx_length))
        !           628:                          fragP->fr_subtype = this_state;
        !           629:                    break;
        !           630: 
        !           631:                  default:
        !           632:                      BAD_CASE(fragP->fr_type);
        !           633:                      break;
        !           634:                }
        !           635:                if(growth) {
        !           636:                    stretch += growth;
        !           637:                    stretched++;
        !           638:                }
        !           639:            }                   /* For each frag in the segment. */
        !           640:        }while(stretched);      /* Until nothing further to relax. */
        !           641: 
        !           642:        /*
        !           643:         * We now have valid fr_address'es for each frag.  All fr_address's
        !           644:         * are correct, relative to their own section.  We have made all the
        !           645:         * fixS for this section that will be made.
        !           646:         */
        !           647: }
        !           648: 
        !           649: /*
        !           650:  * Relax_align. Advance location counter to next address that has 'alignment'
        !           651:  * lowest order bits all 0s.
        !           652:  */
        !           653: static
        !           654: relax_addressT         /* How many addresses does the .align take? */
        !           655: relax_align(
        !           656: relax_addressT address, /* Address now. */
        !           657: long alignment)                /* Alignment (binary). */
        !           658: {
        !           659:     relax_addressT mask;
        !           660:     relax_addressT new_address;
        !           661: 
        !           662:        mask = ~ ( (~0) << alignment );
        !           663:        new_address = (address + mask) & (~ mask);
        !           664:        return(new_address - address);
        !           665: }
        !           666: 
        !           667: /*
        !           668:  * is_down_range() is used in relax_section() to determine it one fragment is
        !           669:  * after another to know if it will also be moved if the first is moved.
        !           670:  */
        !           671: static
        !           672: int
        !           673: is_down_range(
        !           674: struct frag *f1,
        !           675: struct frag *f2)
        !           676: {
        !           677:        while(f1){
        !           678:            if(f1->fr_next == f2)
        !           679:                return(1);
        !           680:            f1 = f1->fr_next;
        !           681:        }
        !           682:        return(0);
        !           683: }

unix.superglobalmegacorp.com

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