forked from OSchip/llvm-project
				
			Don't create dynamic relocations when its known what the got points to.
llvm-svn: 249485
This commit is contained in:
		
							parent
							
								
									dcfba33481
								
							
						
					
					
						commit
						a662738e02
					
				| 
						 | 
				
			
			@ -14,6 +14,7 @@
 | 
			
		|||
 | 
			
		||||
using namespace llvm;
 | 
			
		||||
using namespace llvm::object;
 | 
			
		||||
using namespace llvm::support::endian;
 | 
			
		||||
using namespace llvm::ELF;
 | 
			
		||||
 | 
			
		||||
using namespace lld;
 | 
			
		||||
| 
						 | 
				
			
			@ -29,10 +30,11 @@ OutputSectionBase<Is64Bits>::OutputSectionBase(StringRef Name, uint32_t sh_type,
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
template <class ELFT>
 | 
			
		||||
GotSection<ELFT>::GotSection()
 | 
			
		||||
GotSection<ELFT>::GotSection(const OutputSection<ELFT> &BssSec)
 | 
			
		||||
    : OutputSectionBase<ELFT::Is64Bits>(".got", llvm::ELF::SHT_PROGBITS,
 | 
			
		||||
                                        llvm::ELF::SHF_ALLOC |
 | 
			
		||||
                                            llvm::ELF::SHF_WRITE) {
 | 
			
		||||
                                            llvm::ELF::SHF_WRITE),
 | 
			
		||||
      BssSec(BssSec) {
 | 
			
		||||
  this->Header.sh_addralign = this->getAddrSize();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -47,6 +49,16 @@ GotSection<ELFT>::getEntryAddr(const SymbolBody &B) const {
 | 
			
		|||
  return this->getVA() + B.getGotIndex() * this->getAddrSize();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class ELFT> void GotSection<ELFT>::writeTo(uint8_t *Buf) {
 | 
			
		||||
  for (const SymbolBody *B : Entries) {
 | 
			
		||||
    if (canBePreempted(B))
 | 
			
		||||
      continue; // The dynamic linker will take care of it.
 | 
			
		||||
    uintX_t VA = getSymVA(*B, BssSec);
 | 
			
		||||
    write<uintX_t, ELFT::TargetEndianness, sizeof(uintX_t)>(Buf, VA);
 | 
			
		||||
    Buf += sizeof(uintX_t);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class ELFT>
 | 
			
		||||
PltSection<ELFT>::PltSection(const GotSection<ELFT> &GotSec)
 | 
			
		||||
    : OutputSectionBase<ELFT::Is64Bits>(".plt", llvm::ELF::SHT_PROGBITS,
 | 
			
		||||
| 
						 | 
				
			
			@ -399,6 +411,16 @@ lld::elf2::getLocalSymVA(const typename ELFFile<ELFT>::Elf_Sym *Sym,
 | 
			
		|||
  return Out->getVA() + Section->getOutputSectionOff() + Sym->st_value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool lld::elf2::canBePreempted(const SymbolBody *Body) {
 | 
			
		||||
  if (!Body)
 | 
			
		||||
    return false;
 | 
			
		||||
  if (Body->isShared() || Body->isUndefined())
 | 
			
		||||
    return true;
 | 
			
		||||
  if (!Config->Shared)
 | 
			
		||||
    return false;
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class ELFT> void OutputSection<ELFT>::writeTo(uint8_t *Buf) {
 | 
			
		||||
  for (InputSection<ELFT> *C : Sections)
 | 
			
		||||
    C->writeTo(Buf, BssSec, PltSec, GotSec);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -40,7 +40,7 @@ template <class ELFT>
 | 
			
		|||
typename llvm::object::ELFFile<ELFT>::uintX_t
 | 
			
		||||
getLocalSymVA(const typename llvm::object::ELFFile<ELFT>::Elf_Sym *Sym,
 | 
			
		||||
              const ObjectFile<ELFT> &File);
 | 
			
		||||
 | 
			
		||||
bool canBePreempted(const SymbolBody *Body);
 | 
			
		||||
template <class ELFT> bool includeInSymtab(const SymbolBody &B);
 | 
			
		||||
 | 
			
		||||
bool includeInDynamicSymtab(const SymbolBody &B);
 | 
			
		||||
| 
						 | 
				
			
			@ -103,17 +103,18 @@ class GotSection final : public OutputSectionBase<ELFT::Is64Bits> {
 | 
			
		|||
  typedef typename Base::uintX_t uintX_t;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
  GotSection();
 | 
			
		||||
  GotSection(const OutputSection<ELFT> &BssSec);
 | 
			
		||||
  void finalize() override {
 | 
			
		||||
    this->Header.sh_size = Entries.size() * this->getAddrSize();
 | 
			
		||||
  }
 | 
			
		||||
  void writeTo(uint8_t *Buf) override {}
 | 
			
		||||
  void writeTo(uint8_t *Buf) override;
 | 
			
		||||
  void addEntry(SymbolBody *Sym);
 | 
			
		||||
  bool empty() const { return Entries.empty(); }
 | 
			
		||||
  uintX_t getEntryAddr(const SymbolBody &B) const;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
  std::vector<const SymbolBody *> Entries;
 | 
			
		||||
  const OutputSection<ELFT> &BssSec;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class ELFT>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -85,7 +85,7 @@ public:
 | 
			
		|||
  Writer(SymbolTable *T)
 | 
			
		||||
      : SymTabSec(*T, StrTabSec, BssSec), DynSymSec(*T, DynStrSec, BssSec),
 | 
			
		||||
        RelaDynSec(DynSymSec, GotSec, BssSec, T->shouldUseRela()),
 | 
			
		||||
        PltSec(GotSec), HashSec(DynSymSec),
 | 
			
		||||
        GotSec(BssSec), PltSec(GotSec), HashSec(DynSymSec),
 | 
			
		||||
        DynamicSec(*T, HashSec, RelaDynSec, BssSec),
 | 
			
		||||
        BssSec(PltSec, GotSec, BssSec, ".bss", SHT_NOBITS,
 | 
			
		||||
               SHF_ALLOC | SHF_WRITE) {}
 | 
			
		||||
| 
						 | 
				
			
			@ -230,19 +230,15 @@ void Writer<ELFT>::scanRelocs(
 | 
			
		|||
        if (Body->isInGot())
 | 
			
		||||
          continue;
 | 
			
		||||
        GotSec.addEntry(Body);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    if (canBePreempted(Body)) {
 | 
			
		||||
      Body->setUsedInDynamicReloc();
 | 
			
		||||
      RelaDynSec.addReloc({C, RI});
 | 
			
		||||
        continue;
 | 
			
		||||
      }
 | 
			
		||||
      if (Body->isShared()) {
 | 
			
		||||
        Body->setUsedInDynamicReloc();
 | 
			
		||||
    } else if (Config->Shared && !Target->isRelRelative(Type)) {
 | 
			
		||||
      RelaDynSec.addReloc({C, RI});
 | 
			
		||||
        continue;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
    if (Config->Shared && !Target->isRelRelative(Type))
 | 
			
		||||
      RelaDynSec.addReloc({C, RI});
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class ELFT>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,40 @@
 | 
			
		|||
// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
 | 
			
		||||
// RUN: lld -flavor gnu2 %t.o -o %t
 | 
			
		||||
// RUN: llvm-readobj -s -r -section-data %t | FileCheck %s
 | 
			
		||||
// RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s
 | 
			
		||||
 | 
			
		||||
        .globl _start
 | 
			
		||||
_start:
 | 
			
		||||
	call foo@gotpcrel
 | 
			
		||||
 | 
			
		||||
        .global foo
 | 
			
		||||
foo:
 | 
			
		||||
        nop
 | 
			
		||||
 | 
			
		||||
// 0x12000 - 0x11000 - 5 = 4091
 | 
			
		||||
// DISASM:      _start:
 | 
			
		||||
// DISASM-NEXT:   11000: {{.*}} callq 4091
 | 
			
		||||
 | 
			
		||||
// DISASM:      foo:
 | 
			
		||||
// DISASM-NEXT:   11005: {{.*}} nop
 | 
			
		||||
 | 
			
		||||
// CHECK:      Name: .got
 | 
			
		||||
// CHECK-NEXT: Type: SHT_PROGBITS
 | 
			
		||||
// CHECK-NEXT: Flags [
 | 
			
		||||
// CHECK-NEXT:   SHF_ALLOC
 | 
			
		||||
// CHECK-NEXT:   SHF_WRITE
 | 
			
		||||
// CHECK-NEXT: ]
 | 
			
		||||
// CHECK-NEXT: Address: 0x12000
 | 
			
		||||
// CHECK-NEXT: Offset:
 | 
			
		||||
// CHECK-NEXT: Size: 8
 | 
			
		||||
// CHECK-NEXT: Link: 0
 | 
			
		||||
// CHECK-NEXT: Info: 0
 | 
			
		||||
// CHECK-NEXT: AddressAlignment: 8
 | 
			
		||||
// CHECK-NEXT: EntrySize: 0
 | 
			
		||||
// CHECK-NEXT: SectionData (
 | 
			
		||||
// 0x11005 in little endian
 | 
			
		||||
// CHECK-NEXT:   0000: 05100100 00000000                    |........|
 | 
			
		||||
// CHECK-NEXT: )
 | 
			
		||||
 | 
			
		||||
// CHECK:      Relocations [
 | 
			
		||||
// CHECK-NEXT: ]
 | 
			
		||||
		Loading…
	
		Reference in New Issue