Annotation of GNUtools/cctools/as/layout.c, revision 1.1.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.