[lld] r250432 - ELF2: Implement __start_SECNAME and __stop_SECNAME.
Rui Ueyama via llvm-commits
llvm-commits at lists.llvm.org
Thu Oct 15 10:11:03 PDT 2015
Author: ruiu
Date: Thu Oct 15 12:11:03 2015
New Revision: 250432
URL: http://llvm.org/viewvc/llvm-project?rev=250432&view=rev
Log:
ELF2: Implement __start_SECNAME and __stop_SECNAME.
If a section name is valid as a C identifier (which is rare because of
the leading '.'), linkers are expected to define __start_<secname> and
__stop_<secname> symbols. They are at beginning and end of the section,
respectively. This is not requested by the ELF standard, but GNU ld and
gold provide this feature.
Added:
lld/trunk/test/elf2/startstop.s
Modified:
lld/trunk/ELF/SymbolTable.cpp
lld/trunk/ELF/SymbolTable.h
lld/trunk/ELF/Writer.cpp
Modified: lld/trunk/ELF/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.cpp?rev=250432&r1=250431&r2=250432&view=diff
==============================================================================
--- lld/trunk/ELF/SymbolTable.cpp (original)
+++ lld/trunk/ELF/SymbolTable.cpp Thu Oct 15 12:11:03 2015
@@ -88,6 +88,12 @@ template <class ELFT> void SymbolTable<E
resolve(Sym);
}
+template <class ELFT> bool SymbolTable<ELFT>::isUndefined(StringRef Name) {
+ if (SymbolBody *Sym = find(Name))
+ return Sym->isUndefined();
+ return false;
+}
+
template <class ELFT>
void SymbolTable<ELFT>::addELFFile(ELFFileBase<ELFT> *File) {
if (auto *O = dyn_cast<ObjectFile<ELFT>>(File))
Modified: lld/trunk/ELF/SymbolTable.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.h?rev=250432&r1=250431&r2=250432&view=diff
==============================================================================
--- lld/trunk/ELF/SymbolTable.h (original)
+++ lld/trunk/ELF/SymbolTable.h Thu Oct 15 12:11:03 2015
@@ -54,6 +54,7 @@ public:
OutputSectionBase<ELFT::Is64Bits> &Section,
typename llvm::object::ELFFile<ELFT>::uintX_t Value);
void addIgnoredSym(StringRef Name);
+ bool isUndefined(StringRef Name);
void scanShlibUndefined();
private:
Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=250432&r1=250431&r2=250432&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Thu Oct 15 12:11:03 2015
@@ -16,6 +16,7 @@
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/FileOutputBuffer.h"
+#include "llvm/Support/StringSaver.h"
using namespace llvm;
using namespace llvm::ELF;
@@ -70,9 +71,11 @@ private:
std::unique_ptr<llvm::FileOutputBuffer> Buffer;
SpecificBumpPtrAllocator<OutputSection<ELFT>> SecAlloc;
+ BumpPtrAllocator Alloc;
std::vector<OutputSectionBase<ELFT::Is64Bits> *> OutputSections;
unsigned getNumSections() const { return OutputSections.size() + 1; }
+ void addStartStopSymbols(OutputSection<ELFT> *Sec);
void setPhdr(Elf_Phdr *PH, uint32_t Type, uint32_t Flags, uintX_t FileOff,
uintX_t VA, uintX_t Align);
void copyPhdr(Elf_Phdr *PH, OutputSectionBase<ELFT::Is64Bits> *From);
@@ -400,6 +403,8 @@ template <class ELFT> void Writer<ELFT>:
if (!isOutputDynamic())
Symtab.addIgnoredSym("__tls_get_addr");
+ std::vector<OutputSection<ELFT> *> RegularSections;
+
for (const std::unique_ptr<ObjectFile<ELFT>> &F : Symtab.getObjectFiles()) {
for (InputSection<ELFT> *C : F->getSections()) {
if (!C || C == &InputSection<ELFT>::Discarded)
@@ -413,12 +418,16 @@ template <class ELFT> void Writer<ELFT>:
Sec = new (SecAlloc.Allocate())
OutputSection<ELFT>(Key.Name, Key.Type, Key.Flags);
OutputSections.push_back(Sec);
+ RegularSections.push_back(Sec);
}
Sec->addSection(C);
scanRelocs(*C);
}
}
+ for (OutputSection<ELFT> *Sec : RegularSections)
+ addStartStopSymbols(Sec);
+
Out<ELFT>::Dynamic->PreInitArraySec =
Map.lookup({".preinit_array", SHT_PREINIT_ARRAY, SHF_WRITE | SHF_ALLOC});
Out<ELFT>::Dynamic->InitArraySec =
@@ -501,6 +510,38 @@ template <class ELFT> void Writer<ELFT>:
Out<ELFT>::Opd = Map.lookup({".opd", SHT_PROGBITS, SHF_WRITE | SHF_ALLOC});
}
+static bool isAlpha(char C) {
+ return ('a' <= C && C <= 'z') || ('A' <= C && C <= 'Z') || C == '_';
+}
+
+static bool isAlnum(char C) { return isAlpha(C) || ('0' <= C && C <= '9'); }
+
+// Returns true if S is valid as a C language identifier.
+static bool isValidCIdentifier(StringRef S) {
+ if (S.empty() || !isAlpha(S[0]))
+ return false;
+ return std::all_of(S.begin() + 1, S.end(), isAlnum);
+}
+
+// If a section name is valid as a C identifier (which is rare because of
+// the leading '.'), linkers are expected to define __start_<secname> and
+// __stop_<secname> symbols. They are at beginning and end of the section,
+// respectively. This is not requested by the ELF standard, but GNU ld and
+// gold provide the feature, and used by many programs.
+template <class ELFT>
+void Writer<ELFT>::addStartStopSymbols(OutputSection<ELFT> *Sec) {
+ StringRef S = Sec->getName();
+ if (!isValidCIdentifier(S))
+ return;
+ StringSaver Saver(Alloc);
+ StringRef Start = Saver.save("__start_" + S);
+ StringRef Stop = Saver.save("__stop_" + S);
+ if (Symtab.isUndefined(Start))
+ Symtab.addSyntheticSym(Start, *Sec, 0);
+ if (Symtab.isUndefined(Stop))
+ Symtab.addSyntheticSym(Stop, *Sec, Sec->getSize());
+}
+
template <class ELFT>
static bool needsPhdr(OutputSectionBase<ELFT::Is64Bits> *Sec) {
return Sec->getFlags() & SHF_ALLOC;
Added: lld/trunk/test/elf2/startstop.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/startstop.s?rev=250432&view=auto
==============================================================================
--- lld/trunk/test/elf2/startstop.s (added)
+++ lld/trunk/test/elf2/startstop.s Thu Oct 15 12:11:03 2015
@@ -0,0 +1,54 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+// RUN: ld.lld2 %t -o %tout
+// RUN: llvm-objdump -d %tout | FileCheck -check-prefix=DISASM %s
+// RUN: llvm-readobj -symbols %tout | FileCheck -check-prefix=SYMBOL %s
+
+// DISASM: _start:
+// DISASM: 11000: e8 0a 00 00 00 callq 10
+// DISASM: 11005: e8 08 00 00 00 callq 8
+// DISASM: 1100a: e8 03 00 00 00 callq 3
+// DISASM: Disassembly of section foo:
+// DISASM: __start_foo:
+// DISASM: 1100f: 90 nop
+// DISASM: 11010: 90 nop
+// DISASM: 11011: 90 nop
+// DISASM: Disassembly of section bar:
+// DISASM: __start_bar:
+// DISASM: 11012: 90 nop
+// DISASM: 11013: 90 nop
+// DISASM: 11014: 90 nop
+
+// SYMBOL: Symbol {
+// SYMBOL: Name: __start_bar
+// SYMBOL: Value: 0x11012
+// SYMBOL: Section: bar
+// SYMBOL: }
+// SYMBOL-NOT: Section: __stop_bar
+// SYMBOL: Symbol {
+// SYMBOL: Name: __start_foo
+// SYMBOL: Value: 0x1100F
+// SYMBOL: Section: foo
+// SYMBOL: }
+// SYMBOL: Symbol {
+// SYMBOL: Name: __stop_foo
+// SYMBOL: Value: 0x11012
+// SYMBOL: Section: foo (0x2)
+// SYMBOL: }
+
+.global _start
+.text
+_start:
+ call __start_foo
+ call __stop_foo
+ call __start_bar
+
+.section foo,"ax"
+ nop
+ nop
+ nop
+
+.section bar,"ax"
+ nop
+ nop
+ nop
More information about the llvm-commits
mailing list