llvm.org GIT mirror llvm / b7abea0
X86_32: Large Symbol+Offset relocations. If the offset is more than 24-bits, it won't fit in a scattered relocation offset field, so we fall back to using a non-scattered relocation. rdar://12358909 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@164724 91177308-0d34-0410-b5e6-96231b3b80d8 Jim Grosbach 8 years ago
2 changed file(s) with 76 addition(s) and 8 deletion(s). Raw diff Collapse all Expand all
1010 #include "MCTargetDesc/X86MCTargetDesc.h"
1111 #include "llvm/MC/MCAssembler.h"
1212 #include "llvm/MC/MCAsmLayout.h"
13 #include "llvm/MC/MCContext.h"
1314 #include "llvm/MC/MCMachObjectWriter.h"
1415 #include "llvm/MC/MCSectionMachO.h"
1516 #include "llvm/MC/MCValue.h"
1617 #include "llvm/ADT/Twine.h"
1718 #include "llvm/Support/ErrorHandling.h"
19 #include "llvm/Support/Format.h"
1820 #include "llvm/Object/MachOFormat.h"
1921
2022 using namespace llvm;
2224
2325 namespace {
2426 class X86MachObjectWriter : public MCMachObjectTargetWriter {
25 void RecordScatteredRelocation(MachObjectWriter *Writer,
27 bool RecordScatteredRelocation(MachObjectWriter *Writer,
2628 const MCAssembler &Asm,
2729 const MCAsmLayout &Layout,
2830 const MCFragment *Fragment,
334336 Writer->addRelocation(Fragment->getParent(), MRE);
335337 }
336338
337 void X86MachObjectWriter::RecordScatteredRelocation(MachObjectWriter *Writer,
339 bool X86MachObjectWriter::RecordScatteredRelocation(MachObjectWriter *Writer,
338340 const MCAssembler &Asm,
339341 const MCAsmLayout &Layout,
340342 const MCFragment *Fragment,
380382 // Relocations are written out in reverse order, so the PAIR comes first.
381383 if (Type == macho::RIT_Difference ||
382384 Type == macho::RIT_Generic_LocalDifference) {
385 // If the offset is too large to fit in a scattered relocation,
386 // we're hosed. It's an unfortunate limitation of the MachO format.
387 if (FixupOffset > 0xffffff) {
388 char Buffer[32];
389 format("0x%x", FixupOffset).print(Buffer, sizeof(Buffer));
390 Asm.getContext().FatalError(Fixup.getLoc(),
391 Twine("Section too large, can't encode "
392 "r_address (") + Buffer +
393 ") into 24 bits of scattered "
394 "relocation entry.");
395 llvm_unreachable("fatal error returned?!");
396 }
397
383398 macho::RelocationEntry MRE;
384399 MRE.Word0 = ((0 << 0) |
385400 (macho::RIT_Pair << 24) |
388403 macho::RF_Scattered);
389404 MRE.Word1 = Value2;
390405 Writer->addRelocation(Fragment->getParent(), MRE);
406 } else {
407 // If the offset is more than 24-bits, it won't fit in a scattered
408 // relocation offset field, so we fall back to using a non-scattered
409 // relocation. This is a bit risky, as if the offset reaches out of
410 // the block and the linker is doing scattered loading on this
411 // symbol, things can go badly.
412 //
413 // Required for 'as' compatibility.
414 if (FixupOffset > 0xffffff)
415 return false;
391416 }
392417
393418 macho::RelocationEntry MRE;
398423 macho::RF_Scattered);
399424 MRE.Word1 = Value;
400425 Writer->addRelocation(Fragment->getParent(), MRE);
426 return true;
401427 }
402428
403429 void X86MachObjectWriter::RecordTLVPRelocation(MachObjectWriter *Writer,
468494 // If this is a difference or a defined symbol plus an offset, then we need a
469495 // scattered relocation entry. Differences always require scattered
470496 // relocations.
471 if (Target.getSymB())
472 return RecordScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup,
473 Target, Log2Size, FixedValue);
497 if (Target.getSymB()) {
498 RecordScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup,
499 Target, Log2Size, FixedValue);
500 return;
501 }
474502
475503 // Get the symbol data, if any.
476504 MCSymbolData *SD = 0;
482510 uint32_t Offset = Target.getConstant();
483511 if (IsPCRel)
484512 Offset += 1 << Log2Size;
485 if (Offset && SD && !Writer->doesSymbolRequireExternRelocation(SD))
486 return RecordScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup,
487 Target, Log2Size, FixedValue);
513 // Try to record the scattered relocation if needed. Fall back to non
514 // scattered if necessary (see comments in RecordScatteredRelocation()
515 // for details).
516 if (Offset && SD && !Writer->doesSymbolRequireExternRelocation(SD) &&
517 RecordScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup,
518 Target, Log2Size, FixedValue))
519 return;
488520
489521 // See .
490522 uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
0 // RUN: llvm-mc -triple i386-apple-darwin10 %s -filetype=obj -o - | macho-dump | FileCheck %s
1
2 .space 0x1ed280
3 .section __DATA,__const
4 .align 4
5 .space 0x5181020
6 _foo:
7 .long _bar
8 .long 0
9 .long _bar+8
10 .long _bar+24
11 .long 0
12 .long _bar+16
13
14 .zerofill __DATA,__bss,__dummy,0x5d780
15 .zerofill __DATA,__bss,_bar,48,4
16
17 // Normally scattered relocations are used for sym+offset expressions. When
18 // the value exceeds 24-bits, however, it's outside what MachO can encode,
19 // so the assembler falls back to non-scattered relocations.
20 // rdar://12358909
21
22 // CHECK: ('_relocations', [
23 // CHECK: # Relocation 0
24 // CHECK: (('word-0', 0x5181034),
25 // CHECK: ('word-1', 0x4000003)),
26 // CHECK: # Relocation 1
27 // CHECK: (('word-0', 0x518102c),
28 // CHECK: ('word-1', 0x4000003)),
29 // CHECK: # Relocation 2
30 // CHECK: (('word-0', 0x5181028),
31 // CHECK: ('word-1', 0x4000003)),
32 // CHECK: # Relocation 3
33 // CHECK: (('word-0', 0x5181020),
34 // CHECK: ('word-1', 0x4000003)),
35 // CHECK: ])