diff --git a/lib/MC/ELFObjectWriter.cpp b/lib/MC/ELFObjectWriter.cpp index a80e7b6b08a..1890da72e0e 100644 --- a/lib/MC/ELFObjectWriter.cpp +++ b/lib/MC/ELFObjectWriter.cpp @@ -500,11 +500,22 @@ void ELFObjectWriterImpl::WriteSymbolTable(MCDataFragment *F, } } -static const MCSymbolData *getAtom(const MCSymbolData &SD) { - if (!SD.getFragment()) - return 0; +static bool ShouldRelocOnSymbol(const MCSymbolData &SD, + const MCValue &Target) { + const MCSymbol &Symbol = SD.getSymbol(); + if (Symbol.isUndefined()) + return true; - return SD.getFragment()->getAtom(); + const MCSectionELF &Section = + static_cast(Symbol.getSection()); + + if (Section.getFlags() & MCSectionELF::SHF_MERGE) + return Target.getConstant() != 0; + + if (SD.isExternal()) + return true; + + return false; } // FIXME: this is currently X86/X86_64 only @@ -522,48 +533,30 @@ void ELFObjectWriterImpl::RecordRelocation(const MCAssembler &Asm, if (!Target.isAbsolute()) { const MCSymbol *Symbol = &Target.getSymA()->getSymbol(); MCSymbolData &SD = Asm.getSymbolData(*Symbol); - const MCSymbolData *Base = getAtom(SD); MCFragment *F = SD.getFragment(); - // Avoid relocations for cases like jumps and calls in the same file. + // Check that this case has already been fully resolved before we get + // here. if (Symbol->isDefined() && !SD.isExternal() && IsPCRel && &Fragment->getParent()->getSection() == &Symbol->getSection()) { - uint64_t FixupAddr = Layout.getFragmentAddress(Fragment) + Fixup.getOffset(); - FixedValue = Layout.getSymbolAddress(&SD) + Target.getConstant() - FixupAddr; + llvm_unreachable("We don't need a relocation in this case."); return; } - if (Base) { - if (Base != &SD) { - Index = F->getParent()->getOrdinal() + LocalSymbolData.size() + 1; + bool RelocOnSymbol = ShouldRelocOnSymbol(SD, Target); + if (!RelocOnSymbol) { + Index = F->getParent()->getOrdinal() + LocalSymbolData.size() + 1; - MCSectionData *FSD = F->getParent(); - // Offset of the symbol in the section - Value += Layout.getSymbolAddress(&SD) - Layout.getSectionAddress(FSD); - } else - Index = getSymbolIndexInSymbolTable(Asm, Symbol); - Addend = Value; - // Compensate for the addend on i386. - if (Is64Bit) - Value = 0; - } else { - if (F) { - // Index of the section in .symtab against this symbol - // is being relocated + 2 (empty section + abs. symbols). - Index = F->getParent()->getOrdinal() + LocalSymbolData.size() + 1; - - MCSectionData *FSD = F->getParent(); - // Offset of the symbol in the section - Value += Layout.getSymbolAddress(&SD) - Layout.getSectionAddress(FSD); - } else { - Index = getSymbolIndexInSymbolTable(Asm, Symbol); - } - Addend = Value; - // Compensate for the addend on i386. - if (Is64Bit) - Value = 0; - } + MCSectionData *FSD = F->getParent(); + // Offset of the symbol in the section + Value += Layout.getSymbolAddress(&SD) - Layout.getSectionAddress(FSD); + } else + Index = getSymbolIndexInSymbolTable(Asm, Symbol); + Addend = Value; + // Compensate for the addend on i386. + if (Is64Bit) + Value = 0; } FixedValue = Value; diff --git a/test/MC/ELF/basic-elf.ll b/test/MC/ELF/basic-elf.ll index b9be0678a71..f130ced7bbb 100644 --- a/test/MC/ELF/basic-elf.ll +++ b/test/MC/ELF/basic-elf.ll @@ -101,7 +101,7 @@ declare i32 @puts(i8* nocapture) nounwind ; 64: # Relocation 2 ; 64: (('r_offset', 15) ; 64: ('r_type', 10) -; 64: ('r_addend', 0) +; 64: ('r_addend', 6) ; 64: ), ; 64: # Relocation 3 ; 64: (('r_offset', 20) diff --git a/test/MC/ELF/relocation.s b/test/MC/ELF/relocation.s index a8f4e5f29d3..45c863e6de5 100644 --- a/test/MC/ELF/relocation.s +++ b/test/MC/ELF/relocation.s @@ -10,39 +10,48 @@ bar: movq bar, %rdx // R_X86_64_32S .long bar // R_X86_64_32 +// CHECK: # Section 1 +// CHECK: (('sh_name', 1) # '.text' + +// CHECK: # Symbol 2 +// CHECK: (('st_name', 0) # '' +// CHECK: ('st_bind', 0) +// CHECK ('st_type', 3) +// CHECK: ('st_other', 0) +// CHECK: ('st_shndx', 1) // CHECK: # Relocation 0 // CHECK-NEXT: (('r_offset', 1) -// CHECK-NEXT: ('r_sym', +// CHECK-NEXT: ('r_sym', 2) // CHECK-NEXT: ('r_type', 10) // CHECK-NEXT: ('r_addend', // CHECK: # Relocation 1 // CHECK-NEXT: (('r_offset', 8) -// CHECK-NEXT: ('r_sym', +// CHECK-NEXT: ('r_sym', 2) // CHECK-NEXT: ('r_type', 11) // CHECK-NEXT: ('r_addend', // CHECK: # Relocation 2 // CHECK-NEXT: (('r_offset', 19) -// CHECK-NEXT: ('r_sym', +// CHECK-NEXT: ('r_sym', 2) // CHECK-NEXT: ('r_type', 11) // CHECK-NEXT: ('r_addend', // CHECK: # Relocation 3 // CHECK-NEXT: (('r_offset', 26) -// CHECK-NEXT: ('r_sym', +// CHECK-NEXT: ('r_sym', 2) // CHECK-NEXT: ('r_type', 11) // CHECK-NEXT: ('r_addend', // CHECK: # Relocation 4 // CHECK-NEXT: (('r_offset', 34) -// CHECK-NEXT: ('r_sym', +// CHECK-NEXT: ('r_sym', 2) // CHECK-NEXT: ('r_type', 11) // CHECK-NEXT: ('r_addend', // CHECK: # Relocation 5 // CHECK-NEXT: (('r_offset', 38) -// CHECK-NEXT: ('r_sym', +// CHECK-NEXT: ('r_sym', 2) // CHECK-NEXT: ('r_type', 10) // CHECK-NEXT: ('r_addend',