|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.