224 changes: 112 additions & 112 deletions lld/ELF/MapFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,65 +39,65 @@ using namespace lld::elf;

using SymbolMapTy = DenseMap<const SectionBase *, SmallVector<Defined *, 4>>;

static const std::string Indent8 = " "; // 8 spaces
static const std::string Indent16 = " "; // 16 spaces
static const std::string indent8 = " "; // 8 spaces
static const std::string indent16 = " "; // 16 spaces

// Print out the first three columns of a line.
static void writeHeader(raw_ostream &OS, uint64_t VMA, uint64_t LMA,
uint64_t Size, uint64_t Align) {
if (Config->Is64)
OS << format("%16llx %16llx %8llx %5lld ", VMA, LMA, Size, Align);
static void writeHeader(raw_ostream &os, uint64_t vma, uint64_t lma,
uint64_t size, uint64_t align) {
if (config->is64)
os << format("%16llx %16llx %8llx %5lld ", vma, lma, size, align);
else
OS << format("%8llx %8llx %8llx %5lld ", VMA, LMA, Size, Align);
os << format("%8llx %8llx %8llx %5lld ", vma, lma, size, align);
}

// Returns a list of all symbols that we want to print out.
static std::vector<Defined *> getSymbols() {
std::vector<Defined *> V;
for (InputFile *File : ObjectFiles)
for (Symbol *B : File->getSymbols())
if (auto *DR = dyn_cast<Defined>(B))
if (!DR->isSection() && DR->Section && DR->Section->isLive() &&
(DR->File == File || DR->NeedsPltAddr || DR->Section->Bss))
V.push_back(DR);
return V;
std::vector<Defined *> v;
for (InputFile *file : objectFiles)
for (Symbol *b : file->getSymbols())
if (auto *dr = dyn_cast<Defined>(b))
if (!dr->isSection() && dr->section && dr->section->isLive() &&
(dr->file == file || dr->needsPltAddr || dr->section->bss))
v.push_back(dr);
return v;
}

// Returns a map from sections to their symbols.
static SymbolMapTy getSectionSyms(ArrayRef<Defined *> Syms) {
SymbolMapTy Ret;
for (Defined *DR : Syms)
Ret[DR->Section].push_back(DR);
static SymbolMapTy getSectionSyms(ArrayRef<Defined *> syms) {
SymbolMapTy ret;
for (Defined *dr : syms)
ret[dr->section].push_back(dr);

// Sort symbols by address. We want to print out symbols in the
// order in the output file rather than the order they appeared
// in the input files.
for (auto &It : Ret)
llvm::stable_sort(It.second, [](Defined *A, Defined *B) {
return A->getVA() < B->getVA();
for (auto &it : ret)
llvm::stable_sort(it.second, [](Defined *a, Defined *b) {
return a->getVA() < b->getVA();
});
return Ret;
return ret;
}

// Construct a map from symbols to their stringified representations.
// Demangling symbols (which is what toString() does) is slow, so
// we do that in batch using parallel-for.
static DenseMap<Symbol *, std::string>
getSymbolStrings(ArrayRef<Defined *> Syms) {
std::vector<std::string> Str(Syms.size());
parallelForEachN(0, Syms.size(), [&](size_t I) {
raw_string_ostream OS(Str[I]);
OutputSection *OSec = Syms[I]->getOutputSection();
uint64_t VMA = Syms[I]->getVA();
uint64_t LMA = OSec ? OSec->getLMA() + VMA - OSec->getVA(0) : 0;
writeHeader(OS, VMA, LMA, Syms[I]->getSize(), 1);
OS << Indent16 << toString(*Syms[I]);
getSymbolStrings(ArrayRef<Defined *> syms) {
std::vector<std::string> str(syms.size());
parallelForEachN(0, syms.size(), [&](size_t i) {
raw_string_ostream os(str[i]);
OutputSection *osec = syms[i]->getOutputSection();
uint64_t vma = syms[i]->getVA();
uint64_t lma = osec ? osec->getLMA() + vma - osec->getVA(0) : 0;
writeHeader(os, vma, lma, syms[i]->getSize(), 1);
os << indent16 << toString(*syms[i]);
});

DenseMap<Symbol *, std::string> Ret;
for (size_t I = 0, E = Syms.size(); I < E; ++I)
Ret[Syms[I]] = std::move(Str[I]);
return Ret;
DenseMap<Symbol *, std::string> ret;
for (size_t i = 0, e = syms.size(); i < e; ++i)
ret[syms[i]] = std::move(str[i]);
return ret;
}

// Print .eh_frame contents. Since the section consists of EhSectionPieces,
Expand All @@ -106,115 +106,115 @@ getSymbolStrings(ArrayRef<Defined *> Syms) {
// .eh_frame tend to contain a lot of section pieces that are contiguous
// both in input file and output file. Such pieces are squashed before
// being displayed to make output compact.
static void printEhFrame(raw_ostream &OS, const EhFrameSection *Sec) {
std::vector<EhSectionPiece> Pieces;
static void printEhFrame(raw_ostream &os, const EhFrameSection *sec) {
std::vector<EhSectionPiece> pieces;

auto Add = [&](const EhSectionPiece &P) {
auto add = [&](const EhSectionPiece &p) {
// If P is adjacent to Last, squash the two.
if (!Pieces.empty()) {
EhSectionPiece &Last = Pieces.back();
if (Last.Sec == P.Sec && Last.InputOff + Last.Size == P.InputOff &&
Last.OutputOff + Last.Size == P.OutputOff) {
Last.Size += P.Size;
if (!pieces.empty()) {
EhSectionPiece &last = pieces.back();
if (last.sec == p.sec && last.inputOff + last.size == p.inputOff &&
last.outputOff + last.size == p.outputOff) {
last.size += p.size;
return;
}
}
Pieces.push_back(P);
pieces.push_back(p);
};

// Gather section pieces.
for (const CieRecord *Rec : Sec->getCieRecords()) {
Add(*Rec->Cie);
for (const EhSectionPiece *Fde : Rec->Fdes)
Add(*Fde);
for (const CieRecord *rec : sec->getCieRecords()) {
add(*rec->cie);
for (const EhSectionPiece *fde : rec->fdes)
add(*fde);
}

// Print out section pieces.
const OutputSection *OSec = Sec->getOutputSection();
for (EhSectionPiece &P : Pieces) {
writeHeader(OS, OSec->Addr + P.OutputOff, OSec->getLMA() + P.OutputOff,
P.Size, 1);
OS << Indent8 << toString(P.Sec->File) << ":(" << P.Sec->Name << "+0x"
<< Twine::utohexstr(P.InputOff) + ")\n";
const OutputSection *osec = sec->getOutputSection();
for (EhSectionPiece &p : pieces) {
writeHeader(os, osec->addr + p.outputOff, osec->getLMA() + p.outputOff,
p.size, 1);
os << indent8 << toString(p.sec->file) << ":(" << p.sec->name << "+0x"
<< Twine::utohexstr(p.inputOff) + ")\n";
}
}

void elf::writeMapFile() {
if (Config->MapFile.empty())
if (config->mapFile.empty())
return;

// Open a map file for writing.
std::error_code EC;
raw_fd_ostream OS(Config->MapFile, EC, sys::fs::F_None);
if (EC) {
error("cannot open " + Config->MapFile + ": " + EC.message());
std::error_code ec;
raw_fd_ostream os(config->mapFile, ec, sys::fs::F_None);
if (ec) {
error("cannot open " + config->mapFile + ": " + ec.message());
return;
}

// Collect symbol info that we want to print out.
std::vector<Defined *> Syms = getSymbols();
SymbolMapTy SectionSyms = getSectionSyms(Syms);
DenseMap<Symbol *, std::string> SymStr = getSymbolStrings(Syms);
std::vector<Defined *> syms = getSymbols();
SymbolMapTy sectionSyms = getSectionSyms(syms);
DenseMap<Symbol *, std::string> symStr = getSymbolStrings(syms);

// Print out the header line.
int W = Config->Is64 ? 16 : 8;
OS << right_justify("VMA", W) << ' ' << right_justify("LMA", W)
int w = config->is64 ? 16 : 8;
os << right_justify("VMA", w) << ' ' << right_justify("LMA", w)
<< " Size Align Out In Symbol\n";

OutputSection* OSec = nullptr;
for (BaseCommand *Base : Script->SectionCommands) {
if (auto *Cmd = dyn_cast<SymbolAssignment>(Base)) {
if (Cmd->Provide && !Cmd->Sym)
OutputSection* osec = nullptr;
for (BaseCommand *base : script->sectionCommands) {
if (auto *cmd = dyn_cast<SymbolAssignment>(base)) {
if (cmd->provide && !cmd->sym)
continue;
uint64_t LMA = OSec ? OSec->getLMA() + Cmd->Addr - OSec->getVA(0) : 0;
writeHeader(OS, Cmd->Addr, LMA, Cmd->Size, 1);
OS << Cmd->CommandString << '\n';
uint64_t lma = osec ? osec->getLMA() + cmd->addr - osec->getVA(0) : 0;
writeHeader(os, cmd->addr, lma, cmd->size, 1);
os << cmd->commandString << '\n';
continue;
}

OSec = cast<OutputSection>(Base);
writeHeader(OS, OSec->Addr, OSec->getLMA(), OSec->Size, OSec->Alignment);
OS << OSec->Name << '\n';
osec = cast<OutputSection>(base);
writeHeader(os, osec->addr, osec->getLMA(), osec->size, osec->alignment);
os << osec->name << '\n';

// Dump symbols for each input section.
for (BaseCommand *Base : OSec->SectionCommands) {
if (auto *ISD = dyn_cast<InputSectionDescription>(Base)) {
for (InputSection *IS : ISD->Sections) {
if (auto *EhSec = dyn_cast<EhFrameSection>(IS)) {
printEhFrame(OS, EhSec);
for (BaseCommand *base : osec->sectionCommands) {
if (auto *isd = dyn_cast<InputSectionDescription>(base)) {
for (InputSection *isec : isd->sections) {
if (auto *ehSec = dyn_cast<EhFrameSection>(isec)) {
printEhFrame(os, ehSec);
continue;
}

writeHeader(OS, IS->getVA(0), OSec->getLMA() + IS->getOffset(0),
IS->getSize(), IS->Alignment);
OS << Indent8 << toString(IS) << '\n';
for (Symbol *Sym : SectionSyms[IS])
OS << SymStr[Sym] << '\n';
writeHeader(os, isec->getVA(0), osec->getLMA() + isec->getOffset(0),
isec->getSize(), isec->alignment);
os << indent8 << toString(isec) << '\n';
for (Symbol *sym : sectionSyms[isec])
os << symStr[sym] << '\n';
}
continue;
}

if (auto *Cmd = dyn_cast<ByteCommand>(Base)) {
writeHeader(OS, OSec->Addr + Cmd->Offset, OSec->getLMA() + Cmd->Offset,
Cmd->Size, 1);
OS << Indent8 << Cmd->CommandString << '\n';
if (auto *cmd = dyn_cast<ByteCommand>(base)) {
writeHeader(os, osec->addr + cmd->offset, osec->getLMA() + cmd->offset,
cmd->size, 1);
os << indent8 << cmd->commandString << '\n';
continue;
}

if (auto *Cmd = dyn_cast<SymbolAssignment>(Base)) {
if (Cmd->Provide && !Cmd->Sym)
if (auto *cmd = dyn_cast<SymbolAssignment>(base)) {
if (cmd->provide && !cmd->sym)
continue;
writeHeader(OS, Cmd->Addr, OSec->getLMA() + Cmd->Addr - OSec->getVA(0),
Cmd->Size, 1);
OS << Indent8 << Cmd->CommandString << '\n';
writeHeader(os, cmd->addr, osec->getLMA() + cmd->addr - osec->getVA(0),
cmd->size, 1);
os << indent8 << cmd->commandString << '\n';
continue;
}
}
}
}

static void print(StringRef A, StringRef B) {
outs() << left_justify(A, 49) << " " << B << "\n";
static void print(StringRef a, StringRef b) {
outs() << left_justify(a, 49) << " " << b << "\n";
}

// Output a cross reference table to stdout. This is for --cref.
Expand All @@ -229,18 +229,18 @@ static void print(StringRef A, StringRef B) {
// In this case, strlen is defined by libc.so.6 and used by other two
// files.
void elf::writeCrossReferenceTable() {
if (!Config->Cref)
if (!config->cref)
return;

// Collect symbols and files.
MapVector<Symbol *, SetVector<InputFile *>> Map;
for (InputFile *File : ObjectFiles) {
for (Symbol *Sym : File->getSymbols()) {
if (isa<SharedSymbol>(Sym))
Map[Sym].insert(File);
if (auto *D = dyn_cast<Defined>(Sym))
if (!D->isLocal() && (!D->Section || D->Section->isLive()))
Map[D].insert(File);
MapVector<Symbol *, SetVector<InputFile *>> map;
for (InputFile *file : objectFiles) {
for (Symbol *sym : file->getSymbols()) {
if (isa<SharedSymbol>(sym))
map[sym].insert(file);
if (auto *d = dyn_cast<Defined>(sym))
if (!d->isLocal() && (!d->section || d->section->isLive()))
map[d].insert(file);
}
}

Expand All @@ -249,13 +249,13 @@ void elf::writeCrossReferenceTable() {
print("Symbol", "File");

// Print out a table.
for (auto KV : Map) {
Symbol *Sym = KV.first;
SetVector<InputFile *> &Files = KV.second;
for (auto kv : map) {
Symbol *sym = kv.first;
SetVector<InputFile *> &files = kv.second;

print(toString(*Sym), toString(Sym->File));
for (InputFile *File : Files)
if (File != Sym->File)
print("", toString(File));
print(toString(*sym), toString(sym->file));
for (InputFile *file : files)
if (file != sym->file)
print("", toString(file));
}
}
242 changes: 121 additions & 121 deletions lld/ELF/MarkLive.cpp

Large diffs are not rendered by default.

410 changes: 205 additions & 205 deletions lld/ELF/OutputSections.cpp

Large diffs are not rendered by default.

98 changes: 49 additions & 49 deletions lld/ELF/OutputSections.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,19 +31,19 @@ class InputSectionBase;
// non-overlapping file offsets and VAs.
class OutputSection final : public BaseCommand, public SectionBase {
public:
OutputSection(StringRef Name, uint32_t Type, uint64_t Flags);
OutputSection(StringRef name, uint32_t type, uint64_t flags);

static bool classof(const SectionBase *S) {
return S->kind() == SectionBase::Output;
static bool classof(const SectionBase *s) {
return s->kind() == SectionBase::Output;
}

static bool classof(const BaseCommand *C);
static bool classof(const BaseCommand *c);

uint64_t getLMA() const { return PtLoad ? Addr + PtLoad->LMAOffset : Addr; }
template <typename ELFT> void writeHeaderTo(typename ELFT::Shdr *SHdr);
uint64_t getLMA() const { return ptLoad ? addr + ptLoad->lmaOffset : addr; }
template <typename ELFT> void writeHeaderTo(typename ELFT::Shdr *sHdr);

uint32_t SectionIndex = UINT32_MAX;
unsigned SortRank;
uint32_t sectionIndex = UINT32_MAX;
unsigned sortRank;

uint32_t getPhdrFlags() const;

Expand All @@ -54,82 +54,82 @@ class OutputSection final : public BaseCommand, public SectionBase {
// section offset we use the following formula: Off = Off_first + VA -
// VA_first, where Off_first and VA_first is file offset and VA of first
// section in PT_LOAD.
PhdrEntry *PtLoad = nullptr;
PhdrEntry *ptLoad = nullptr;

// Pointer to a relocation section for this section. Usually nullptr because
// we consume relocations, but if --emit-relocs is specified (which is rare),
// it may have a non-null value.
OutputSection *RelocationSection = nullptr;
OutputSection *relocationSection = nullptr;

// Initially this field is the number of InputSections that have been added to
// the OutputSection so far. Later on, after a call to assignAddresses, it
// corresponds to the Elf_Shdr member.
uint64_t Size = 0;
uint64_t size = 0;

// The following fields correspond to Elf_Shdr members.
uint64_t Offset = 0;
uint64_t Addr = 0;
uint32_t ShName = 0;
uint64_t offset = 0;
uint64_t addr = 0;
uint32_t shName = 0;

void addSection(InputSection *IS);
void addSection(InputSection *isec);

// The following members are normally only used in linker scripts.
MemoryRegion *MemRegion = nullptr;
MemoryRegion *LMARegion = nullptr;
Expr AddrExpr;
Expr AlignExpr;
Expr LMAExpr;
Expr SubalignExpr;
std::vector<BaseCommand *> SectionCommands;
std::vector<StringRef> Phdrs;
llvm::Optional<std::array<uint8_t, 4>> Filler;
ConstraintKind Constraint = ConstraintKind::NoConstraint;
std::string Location;
std::string MemoryRegionName;
std::string LMARegionName;
bool NonAlloc = false;
bool Noload = false;
bool ExpressionsUseSymbols = false;
bool UsedInExpression = false;
bool InOverlay = false;
MemoryRegion *memRegion = nullptr;
MemoryRegion *lmaRegion = nullptr;
Expr addrExpr;
Expr alignExpr;
Expr lmaExpr;
Expr subalignExpr;
std::vector<BaseCommand *> sectionCommands;
std::vector<StringRef> phdrs;
llvm::Optional<std::array<uint8_t, 4>> filler;
ConstraintKind constraint = ConstraintKind::NoConstraint;
std::string location;
std::string memoryRegionName;
std::string lmaRegionName;
bool nonAlloc = false;
bool noload = false;
bool expressionsUseSymbols = false;
bool usedInExpression = false;
bool inOverlay = false;

// Tracks whether the section has ever had an input section added to it, even
// if the section was later removed (e.g. because it is a synthetic section
// that wasn't needed). This is needed for orphan placement.
bool HasInputSections = false;
bool hasInputSections = false;

void finalize();
template <class ELFT> void writeTo(uint8_t *Buf);
template <class ELFT> void writeTo(uint8_t *buf);
template <class ELFT> void maybeCompress();

void sort(llvm::function_ref<int(InputSectionBase *S)> Order);
void sort(llvm::function_ref<int(InputSectionBase *s)> order);
void sortInitFini();
void sortCtorsDtors();

private:
// Used for implementation of --compress-debug-sections option.
std::vector<uint8_t> ZDebugHeader;
llvm::SmallVector<char, 1> CompressedData;
std::vector<uint8_t> zDebugHeader;
llvm::SmallVector<char, 1> compressedData;

std::array<uint8_t, 4> getFiller();
};

int getPriority(StringRef S);
int getPriority(StringRef s);

std::vector<InputSection *> getInputSections(OutputSection* OS);
std::vector<InputSection *> getInputSections(OutputSection* os);

// All output sections that are handled by the linker specially are
// globally accessible. Writer initializes them, so don't use them
// until Writer is initialized.
struct Out {
static uint8_t *BufferStart;
static uint8_t First;
static PhdrEntry *TlsPhdr;
static OutputSection *ElfHeader;
static OutputSection *ProgramHeaders;
static OutputSection *PreinitArray;
static OutputSection *InitArray;
static OutputSection *FiniArray;
static uint8_t *bufferStart;
static uint8_t first;
static PhdrEntry *tlsPhdr;
static OutputSection *elfHeader;
static OutputSection *programHeaders;
static OutputSection *preinitArray;
static OutputSection *initArray;
static OutputSection *finiArray;
};

} // namespace elf
Expand All @@ -140,7 +140,7 @@ namespace elf {

uint64_t getHeaderSize();

extern std::vector<OutputSection *> OutputSections;
extern std::vector<OutputSection *> outputSections;
} // namespace elf
} // namespace lld

Expand Down
1,300 changes: 650 additions & 650 deletions lld/ELF/Relocations.cpp

Large diffs are not rendered by default.

50 changes: 25 additions & 25 deletions lld/ELF/Relocations.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,11 +102,11 @@ enum RelExpr {

// Architecture-neutral representation of relocation.
struct Relocation {
RelExpr Expr;
RelType Type;
uint64_t Offset;
int64_t Addend;
Symbol *Sym;
RelExpr expr;
RelType type;
uint64_t offset;
int64_t addend;
Symbol *sym;
};

// This function writes undefined symbol diagnostics to an internal buffer.
Expand All @@ -125,57 +125,57 @@ struct InputSectionDescription;
class ThunkCreator {
public:
// Return true if Thunks have been added to OutputSections
bool createThunks(ArrayRef<OutputSection *> OutputSections);
bool createThunks(ArrayRef<OutputSection *> outputSections);

// The number of completed passes of createThunks this permits us
// to do one time initialization on Pass 0 and put a limit on the
// number of times it can be called to prevent infinite loops.
uint32_t Pass = 0;
uint32_t pass = 0;

private:
void mergeThunks(ArrayRef<OutputSection *> OutputSections);
void mergeThunks(ArrayRef<OutputSection *> outputSections);

ThunkSection *getISDThunkSec(OutputSection *OS, InputSection *IS,
InputSectionDescription *ISD, uint32_t Type,
uint64_t Src);
ThunkSection *getISDThunkSec(OutputSection *os, InputSection *isec,
InputSectionDescription *isd, uint32_t type,
uint64_t src);

ThunkSection *getISThunkSec(InputSection *IS);
ThunkSection *getISThunkSec(InputSection *isec);

void createInitialThunkSections(ArrayRef<OutputSection *> OutputSections);
void createInitialThunkSections(ArrayRef<OutputSection *> outputSections);

std::pair<Thunk *, bool> getThunk(InputSection *IS, Relocation &Rel,
uint64_t Src);
std::pair<Thunk *, bool> getThunk(InputSection *isec, Relocation &rel,
uint64_t src);

ThunkSection *addThunkSection(OutputSection *OS, InputSectionDescription *,
uint64_t Off);
ThunkSection *addThunkSection(OutputSection *os, InputSectionDescription *,
uint64_t off);

bool normalizeExistingThunk(Relocation &Rel, uint64_t Src);
bool normalizeExistingThunk(Relocation &rel, uint64_t src);

// Record all the available Thunks for a Symbol
llvm::DenseMap<std::pair<SectionBase *, uint64_t>, std::vector<Thunk *>>
ThunkedSymbolsBySection;
llvm::DenseMap<Symbol *, std::vector<Thunk *>> ThunkedSymbols;
thunkedSymbolsBySection;
llvm::DenseMap<Symbol *, std::vector<Thunk *>> thunkedSymbols;

// Find a Thunk from the Thunks symbol definition, we can use this to find
// the Thunk from a relocation to the Thunks symbol definition.
llvm::DenseMap<Symbol *, Thunk *> Thunks;
llvm::DenseMap<Symbol *, Thunk *> thunks;

// Track InputSections that have an inline ThunkSection placed in front
// an inline ThunkSection may have control fall through to the section below
// so we need to make sure that there is only one of them.
// The Mips LA25 Thunk is an example of an inline ThunkSection.
llvm::DenseMap<InputSection *, ThunkSection *> ThunkedSections;
llvm::DenseMap<InputSection *, ThunkSection *> thunkedSections;
};

// Return a int64_t to make sure we get the sign extension out of the way as
// early as possible.
template <class ELFT>
static inline int64_t getAddend(const typename ELFT::Rel &Rel) {
static inline int64_t getAddend(const typename ELFT::Rel &rel) {
return 0;
}
template <class ELFT>
static inline int64_t getAddend(const typename ELFT::Rela &Rel) {
return Rel.r_addend;
static inline int64_t getAddend(const typename ELFT::Rela &rel) {
return rel.r_addend;
}
} // namespace elf
} // namespace lld
Expand Down
214 changes: 107 additions & 107 deletions lld/ELF/ScriptLexer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,169 +41,169 @@ using namespace lld::elf;

// Returns a whole line containing the current token.
StringRef ScriptLexer::getLine() {
StringRef S = getCurrentMB().getBuffer();
StringRef Tok = Tokens[Pos - 1];
StringRef s = getCurrentMB().getBuffer();
StringRef tok = tokens[pos - 1];

size_t Pos = S.rfind('\n', Tok.data() - S.data());
if (Pos != StringRef::npos)
S = S.substr(Pos + 1);
return S.substr(0, S.find_first_of("\r\n"));
size_t pos = s.rfind('\n', tok.data() - s.data());
if (pos != StringRef::npos)
s = s.substr(pos + 1);
return s.substr(0, s.find_first_of("\r\n"));
}

// Returns 1-based line number of the current token.
size_t ScriptLexer::getLineNumber() {
StringRef S = getCurrentMB().getBuffer();
StringRef Tok = Tokens[Pos - 1];
return S.substr(0, Tok.data() - S.data()).count('\n') + 1;
StringRef s = getCurrentMB().getBuffer();
StringRef tok = tokens[pos - 1];
return s.substr(0, tok.data() - s.data()).count('\n') + 1;
}

// Returns 0-based column number of the current token.
size_t ScriptLexer::getColumnNumber() {
StringRef Tok = Tokens[Pos - 1];
return Tok.data() - getLine().data();
StringRef tok = tokens[pos - 1];
return tok.data() - getLine().data();
}

std::string ScriptLexer::getCurrentLocation() {
std::string Filename = getCurrentMB().getBufferIdentifier();
return (Filename + ":" + Twine(getLineNumber())).str();
std::string filename = getCurrentMB().getBufferIdentifier();
return (filename + ":" + Twine(getLineNumber())).str();
}

ScriptLexer::ScriptLexer(MemoryBufferRef MB) { tokenize(MB); }
ScriptLexer::ScriptLexer(MemoryBufferRef mb) { tokenize(mb); }

// We don't want to record cascading errors. Keep only the first one.
void ScriptLexer::setError(const Twine &Msg) {
void ScriptLexer::setError(const Twine &msg) {
if (errorCount())
return;

std::string S = (getCurrentLocation() + ": " + Msg).str();
if (Pos)
S += "\n>>> " + getLine().str() + "\n>>> " +
std::string s = (getCurrentLocation() + ": " + msg).str();
if (pos)
s += "\n>>> " + getLine().str() + "\n>>> " +
std::string(getColumnNumber(), ' ') + "^";
error(S);
error(s);
}

// Split S into linker script tokens.
void ScriptLexer::tokenize(MemoryBufferRef MB) {
std::vector<StringRef> Vec;
MBs.push_back(MB);
StringRef S = MB.getBuffer();
StringRef Begin = S;
void ScriptLexer::tokenize(MemoryBufferRef mb) {
std::vector<StringRef> vec;
mbs.push_back(mb);
StringRef s = mb.getBuffer();
StringRef begin = s;

for (;;) {
S = skipSpace(S);
if (S.empty())
s = skipSpace(s);
if (s.empty())
break;

// Quoted token. Note that double-quote characters are parts of a token
// because, in a glob match context, only unquoted tokens are interpreted
// as glob patterns. Double-quoted tokens are literal patterns in that
// context.
if (S.startswith("\"")) {
size_t E = S.find("\"", 1);
if (E == StringRef::npos) {
StringRef Filename = MB.getBufferIdentifier();
size_t Lineno = Begin.substr(0, S.data() - Begin.data()).count('\n');
error(Filename + ":" + Twine(Lineno + 1) + ": unclosed quote");
if (s.startswith("\"")) {
size_t e = s.find("\"", 1);
if (e == StringRef::npos) {
StringRef filename = mb.getBufferIdentifier();
size_t lineno = begin.substr(0, s.data() - begin.data()).count('\n');
error(filename + ":" + Twine(lineno + 1) + ": unclosed quote");
return;
}

Vec.push_back(S.take_front(E + 1));
S = S.substr(E + 1);
vec.push_back(s.take_front(e + 1));
s = s.substr(e + 1);
continue;
}

// ">foo" is parsed to ">" and "foo", but ">>" is parsed to ">>".
// "|", "||", "&" and "&&" are different operators.
if (S.startswith("<<") || S.startswith("<=") || S.startswith(">>") ||
S.startswith(">=") || S.startswith("||") || S.startswith("&&")) {
Vec.push_back(S.substr(0, 2));
S = S.substr(2);
if (s.startswith("<<") || s.startswith("<=") || s.startswith(">>") ||
s.startswith(">=") || s.startswith("||") || s.startswith("&&")) {
vec.push_back(s.substr(0, 2));
s = s.substr(2);
continue;
}

// Unquoted token. This is more relaxed than tokens in C-like language,
// so that you can write "file-name.cpp" as one bare token, for example.
size_t Pos = S.find_first_not_of(
size_t pos = s.find_first_not_of(
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
"0123456789_.$/\\~=+[]*?-!^:");

// A character that cannot start a word (which is usually a
// punctuation) forms a single character token.
if (Pos == 0)
Pos = 1;
Vec.push_back(S.substr(0, Pos));
S = S.substr(Pos);
if (pos == 0)
pos = 1;
vec.push_back(s.substr(0, pos));
s = s.substr(pos);
}

Tokens.insert(Tokens.begin() + Pos, Vec.begin(), Vec.end());
tokens.insert(tokens.begin() + pos, vec.begin(), vec.end());
}

// Skip leading whitespace characters or comments.
StringRef ScriptLexer::skipSpace(StringRef S) {
StringRef ScriptLexer::skipSpace(StringRef s) {
for (;;) {
if (S.startswith("/*")) {
size_t E = S.find("*/", 2);
if (E == StringRef::npos) {
if (s.startswith("/*")) {
size_t e = s.find("*/", 2);
if (e == StringRef::npos) {
error("unclosed comment in a linker script");
return "";
}
S = S.substr(E + 2);
s = s.substr(e + 2);
continue;
}
if (S.startswith("#")) {
size_t E = S.find('\n', 1);
if (E == StringRef::npos)
E = S.size() - 1;
S = S.substr(E + 1);
if (s.startswith("#")) {
size_t e = s.find('\n', 1);
if (e == StringRef::npos)
e = s.size() - 1;
s = s.substr(e + 1);
continue;
}
size_t Size = S.size();
S = S.ltrim();
if (S.size() == Size)
return S;
size_t size = s.size();
s = s.ltrim();
if (s.size() == size)
return s;
}
}

// An erroneous token is handled as if it were the last token before EOF.
bool ScriptLexer::atEOF() { return errorCount() || Tokens.size() == Pos; }
bool ScriptLexer::atEOF() { return errorCount() || tokens.size() == pos; }

// Split a given string as an expression.
// This function returns "3", "*" and "5" for "3*5" for example.
static std::vector<StringRef> tokenizeExpr(StringRef S) {
StringRef Ops = "+-*/:!~=<>"; // List of operators
static std::vector<StringRef> tokenizeExpr(StringRef s) {
StringRef ops = "+-*/:!~=<>"; // List of operators

// Quoted strings are literal strings, so we don't want to split it.
if (S.startswith("\""))
return {S};
if (s.startswith("\""))
return {s};

// Split S with operators as separators.
std::vector<StringRef> Ret;
while (!S.empty()) {
size_t E = S.find_first_of(Ops);
std::vector<StringRef> ret;
while (!s.empty()) {
size_t e = s.find_first_of(ops);

// No need to split if there is no operator.
if (E == StringRef::npos) {
Ret.push_back(S);
if (e == StringRef::npos) {
ret.push_back(s);
break;
}

// Get a token before the opreator.
if (E != 0)
Ret.push_back(S.substr(0, E));
if (e != 0)
ret.push_back(s.substr(0, e));

// Get the operator as a token.
// Keep !=, ==, >=, <=, << and >> operators as a single tokens.
if (S.substr(E).startswith("!=") || S.substr(E).startswith("==") ||
S.substr(E).startswith(">=") || S.substr(E).startswith("<=") ||
S.substr(E).startswith("<<") || S.substr(E).startswith(">>")) {
Ret.push_back(S.substr(E, 2));
S = S.substr(E + 2);
if (s.substr(e).startswith("!=") || s.substr(e).startswith("==") ||
s.substr(e).startswith(">=") || s.substr(e).startswith("<=") ||
s.substr(e).startswith("<<") || s.substr(e).startswith(">>")) {
ret.push_back(s.substr(e, 2));
s = s.substr(e + 2);
} else {
Ret.push_back(S.substr(E, 1));
S = S.substr(E + 1);
ret.push_back(s.substr(e, 1));
s = s.substr(e + 1);
}
}
return Ret;
return ret;
}

// In contexts where expressions are expected, the lexer should apply
Expand All @@ -216,14 +216,14 @@ static std::vector<StringRef> tokenizeExpr(StringRef S) {
//
// This function may split the current token into multiple tokens.
void ScriptLexer::maybeSplitExpr() {
if (!InExpr || errorCount() || atEOF())
if (!inExpr || errorCount() || atEOF())
return;

std::vector<StringRef> V = tokenizeExpr(Tokens[Pos]);
if (V.size() == 1)
std::vector<StringRef> v = tokenizeExpr(tokens[pos]);
if (v.size() == 1)
return;
Tokens.erase(Tokens.begin() + Pos);
Tokens.insert(Tokens.begin() + Pos, V.begin(), V.end());
tokens.erase(tokens.begin() + pos);
tokens.insert(tokens.begin() + pos, v.begin(), v.end());
}

StringRef ScriptLexer::next() {
Expand All @@ -235,66 +235,66 @@ StringRef ScriptLexer::next() {
setError("unexpected EOF");
return "";
}
return Tokens[Pos++];
return tokens[pos++];
}

StringRef ScriptLexer::peek() {
StringRef Tok = next();
StringRef tok = next();
if (errorCount())
return "";
Pos = Pos - 1;
return Tok;
pos = pos - 1;
return tok;
}

StringRef ScriptLexer::peek2() {
skip();
StringRef Tok = next();
StringRef tok = next();
if (errorCount())
return "";
Pos = Pos - 2;
return Tok;
pos = pos - 2;
return tok;
}

bool ScriptLexer::consume(StringRef Tok) {
if (peek() == Tok) {
bool ScriptLexer::consume(StringRef tok) {
if (peek() == tok) {
skip();
return true;
}
return false;
}

// Consumes Tok followed by ":". Space is allowed between Tok and ":".
bool ScriptLexer::consumeLabel(StringRef Tok) {
if (consume((Tok + ":").str()))
bool ScriptLexer::consumeLabel(StringRef tok) {
if (consume((tok + ":").str()))
return true;
if (Tokens.size() >= Pos + 2 && Tokens[Pos] == Tok &&
Tokens[Pos + 1] == ":") {
Pos += 2;
if (tokens.size() >= pos + 2 && tokens[pos] == tok &&
tokens[pos + 1] == ":") {
pos += 2;
return true;
}
return false;
}

void ScriptLexer::skip() { (void)next(); }

void ScriptLexer::expect(StringRef Expect) {
void ScriptLexer::expect(StringRef expect) {
if (errorCount())
return;
StringRef Tok = next();
if (Tok != Expect)
setError(Expect + " expected, but got " + Tok);
StringRef tok = next();
if (tok != expect)
setError(expect + " expected, but got " + tok);
}

// Returns true if S encloses T.
static bool encloses(StringRef S, StringRef T) {
return S.bytes_begin() <= T.bytes_begin() && T.bytes_end() <= S.bytes_end();
static bool encloses(StringRef s, StringRef t) {
return s.bytes_begin() <= t.bytes_begin() && t.bytes_end() <= s.bytes_end();
}

MemoryBufferRef ScriptLexer::getCurrentMB() {
// Find input buffer containing the current token.
assert(!MBs.empty() && Pos > 0);
for (MemoryBufferRef MB : MBs)
if (encloses(MB.getBuffer(), Tokens[Pos - 1]))
return MB;
assert(!mbs.empty() && pos > 0);
for (MemoryBufferRef mb : mbs)
if (encloses(mb.getBuffer(), tokens[pos - 1]))
return mb;
llvm_unreachable("getCurrentMB: failed to find a token");
}
22 changes: 11 additions & 11 deletions lld/ELF/ScriptLexer.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,25 +20,25 @@ namespace elf {

class ScriptLexer {
public:
explicit ScriptLexer(MemoryBufferRef MB);
explicit ScriptLexer(MemoryBufferRef mb);

void setError(const Twine &Msg);
void tokenize(MemoryBufferRef MB);
static StringRef skipSpace(StringRef S);
void setError(const Twine &msg);
void tokenize(MemoryBufferRef mb);
static StringRef skipSpace(StringRef s);
bool atEOF();
StringRef next();
StringRef peek();
StringRef peek2();
void skip();
bool consume(StringRef Tok);
void expect(StringRef Expect);
bool consumeLabel(StringRef Tok);
bool consume(StringRef tok);
void expect(StringRef expect);
bool consumeLabel(StringRef tok);
std::string getCurrentLocation();

std::vector<MemoryBufferRef> MBs;
std::vector<StringRef> Tokens;
bool InExpr = false;
size_t Pos = 0;
std::vector<MemoryBufferRef> mbs;
std::vector<StringRef> tokens;
bool inExpr = false;
size_t pos = 0;

private:
void maybeSplitExpr();
Expand Down
1,218 changes: 609 additions & 609 deletions lld/ELF/ScriptParser.cpp

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions lld/ELF/ScriptParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@ namespace elf {

// Parses a linker script. Calling this function updates
// Config and ScriptConfig.
void readLinkerScript(MemoryBufferRef MB);
void readLinkerScript(MemoryBufferRef mb);

// Parses a version script.
void readVersionScript(MemoryBufferRef MB);
void readVersionScript(MemoryBufferRef mb);

void readDynamicList(MemoryBufferRef MB);
void readDynamicList(MemoryBufferRef mb);

// Parses the defsym expression.
void readDefsym(StringRef Name, MemoryBufferRef MB);
void readDefsym(StringRef name, MemoryBufferRef mb);

} // namespace elf
} // namespace lld
Expand Down
230 changes: 115 additions & 115 deletions lld/ELF/SymbolTable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,73 +30,73 @@ using namespace llvm::ELF;
using namespace lld;
using namespace lld::elf;

SymbolTable *elf::Symtab;
SymbolTable *elf::symtab;

void SymbolTable::wrap(Symbol *Sym, Symbol *Real, Symbol *Wrap) {
void SymbolTable::wrap(Symbol *sym, Symbol *real, Symbol *wrap) {
// Swap symbols as instructed by -wrap.
int &Idx1 = SymMap[CachedHashStringRef(Sym->getName())];
int &Idx2 = SymMap[CachedHashStringRef(Real->getName())];
int &Idx3 = SymMap[CachedHashStringRef(Wrap->getName())];
int &idx1 = symMap[CachedHashStringRef(sym->getName())];
int &idx2 = symMap[CachedHashStringRef(real->getName())];
int &idx3 = symMap[CachedHashStringRef(wrap->getName())];

Idx2 = Idx1;
Idx1 = Idx3;
idx2 = idx1;
idx1 = idx3;

// Now renaming is complete. No one refers Real symbol. We could leave
// Real as-is, but if Real is written to the symbol table, that may
// contain irrelevant values. So, we copy all values from Sym to Real.
StringRef S = Real->getName();
memcpy(Real, Sym, sizeof(SymbolUnion));
Real->setName(S);
StringRef s = real->getName();
memcpy(real, sym, sizeof(SymbolUnion));
real->setName(s);
}

// Find an existing symbol or create a new one.
Symbol *SymbolTable::insert(StringRef Name) {
Symbol *SymbolTable::insert(StringRef name) {
// <name>@@<version> means the symbol is the default version. In that
// case <name>@@<version> will be used to resolve references to <name>.
//
// Since this is a hot path, the following string search code is
// optimized for speed. StringRef::find(char) is much faster than
// StringRef::find(StringRef).
size_t Pos = Name.find('@');
if (Pos != StringRef::npos && Pos + 1 < Name.size() && Name[Pos + 1] == '@')
Name = Name.take_front(Pos);

auto P = SymMap.insert({CachedHashStringRef(Name), (int)SymVector.size()});
int &SymIndex = P.first->second;
bool IsNew = P.second;

if (!IsNew)
return SymVector[SymIndex];

Symbol *Sym = reinterpret_cast<Symbol *>(make<SymbolUnion>());
SymVector.push_back(Sym);

Sym->setName(Name);
Sym->SymbolKind = Symbol::PlaceholderKind;
Sym->VersionId = Config->DefaultSymbolVersion;
Sym->Visibility = STV_DEFAULT;
Sym->IsUsedInRegularObj = false;
Sym->ExportDynamic = false;
Sym->CanInline = true;
Sym->ScriptDefined = false;
Sym->Partition = 1;
return Sym;
size_t pos = name.find('@');
if (pos != StringRef::npos && pos + 1 < name.size() && name[pos + 1] == '@')
name = name.take_front(pos);

auto p = symMap.insert({CachedHashStringRef(name), (int)symVector.size()});
int &symIndex = p.first->second;
bool isNew = p.second;

if (!isNew)
return symVector[symIndex];

Symbol *sym = reinterpret_cast<Symbol *>(make<SymbolUnion>());
symVector.push_back(sym);

sym->setName(name);
sym->symbolKind = Symbol::PlaceholderKind;
sym->versionId = config->defaultSymbolVersion;
sym->visibility = STV_DEFAULT;
sym->isUsedInRegularObj = false;
sym->exportDynamic = false;
sym->canInline = true;
sym->scriptDefined = false;
sym->partition = 1;
return sym;
}

Symbol *SymbolTable::addSymbol(const Symbol &New) {
Symbol *Sym = Symtab->insert(New.getName());
Sym->resolve(New);
return Sym;
Symbol *sym = symtab->insert(New.getName());
sym->resolve(New);
return sym;
}

Symbol *SymbolTable::find(StringRef Name) {
auto It = SymMap.find(CachedHashStringRef(Name));
if (It == SymMap.end())
Symbol *SymbolTable::find(StringRef name) {
auto it = symMap.find(CachedHashStringRef(name));
if (it == symMap.end())
return nullptr;
Symbol *Sym = SymVector[It->second];
if (Sym->isPlaceholder())
Symbol *sym = symVector[it->second];
if (sym->isPlaceholder())
return nullptr;
return Sym;
return sym;
}

// Initialize DemangledSyms with a map from demangled symbols to symbol
Expand All @@ -113,119 +113,119 @@ Symbol *SymbolTable::find(StringRef Name) {
// So, if "extern C++" feature is used, we need to demangle all known
// symbols.
StringMap<std::vector<Symbol *>> &SymbolTable::getDemangledSyms() {
if (!DemangledSyms) {
DemangledSyms.emplace();
for (Symbol *Sym : SymVector) {
if (!Sym->isDefined() && !Sym->isCommon())
if (!demangledSyms) {
demangledSyms.emplace();
for (Symbol *sym : symVector) {
if (!sym->isDefined() && !sym->isCommon())
continue;
if (Optional<std::string> S = demangleItanium(Sym->getName()))
(*DemangledSyms)[*S].push_back(Sym);
if (Optional<std::string> s = demangleItanium(sym->getName()))
(*demangledSyms)[*s].push_back(sym);
else
(*DemangledSyms)[Sym->getName()].push_back(Sym);
(*demangledSyms)[sym->getName()].push_back(sym);
}
}
return *DemangledSyms;
return *demangledSyms;
}

std::vector<Symbol *> SymbolTable::findByVersion(SymbolVersion Ver) {
if (Ver.IsExternCpp)
return getDemangledSyms().lookup(Ver.Name);
if (Symbol *B = find(Ver.Name))
if (B->isDefined() || B->isCommon())
return {B};
std::vector<Symbol *> SymbolTable::findByVersion(SymbolVersion ver) {
if (ver.isExternCpp)
return getDemangledSyms().lookup(ver.name);
if (Symbol *b = find(ver.name))
if (b->isDefined() || b->isCommon())
return {b};
return {};
}

std::vector<Symbol *> SymbolTable::findAllByVersion(SymbolVersion Ver) {
std::vector<Symbol *> Res;
StringMatcher M(Ver.Name);
std::vector<Symbol *> SymbolTable::findAllByVersion(SymbolVersion ver) {
std::vector<Symbol *> res;
StringMatcher m(ver.name);

if (Ver.IsExternCpp) {
for (auto &P : getDemangledSyms())
if (M.match(P.first()))
Res.insert(Res.end(), P.second.begin(), P.second.end());
return Res;
if (ver.isExternCpp) {
for (auto &p : getDemangledSyms())
if (m.match(p.first()))
res.insert(res.end(), p.second.begin(), p.second.end());
return res;
}

for (Symbol *Sym : SymVector)
if ((Sym->isDefined() || Sym->isCommon()) && M.match(Sym->getName()))
Res.push_back(Sym);
return Res;
for (Symbol *sym : symVector)
if ((sym->isDefined() || sym->isCommon()) && m.match(sym->getName()))
res.push_back(sym);
return res;
}

// If there's only one anonymous version definition in a version
// script file, the script does not actually define any symbol version,
// but just specifies symbols visibilities.
void SymbolTable::handleAnonymousVersion() {
for (SymbolVersion &Ver : Config->VersionScriptGlobals)
assignExactVersion(Ver, VER_NDX_GLOBAL, "global");
for (SymbolVersion &Ver : Config->VersionScriptGlobals)
assignWildcardVersion(Ver, VER_NDX_GLOBAL);
for (SymbolVersion &Ver : Config->VersionScriptLocals)
assignExactVersion(Ver, VER_NDX_LOCAL, "local");
for (SymbolVersion &Ver : Config->VersionScriptLocals)
assignWildcardVersion(Ver, VER_NDX_LOCAL);
for (SymbolVersion &ver : config->versionScriptGlobals)
assignExactVersion(ver, VER_NDX_GLOBAL, "global");
for (SymbolVersion &ver : config->versionScriptGlobals)
assignWildcardVersion(ver, VER_NDX_GLOBAL);
for (SymbolVersion &ver : config->versionScriptLocals)
assignExactVersion(ver, VER_NDX_LOCAL, "local");
for (SymbolVersion &ver : config->versionScriptLocals)
assignWildcardVersion(ver, VER_NDX_LOCAL);
}

// Handles -dynamic-list.
void SymbolTable::handleDynamicList() {
for (SymbolVersion &Ver : Config->DynamicList) {
std::vector<Symbol *> Syms;
if (Ver.HasWildcard)
Syms = findAllByVersion(Ver);
for (SymbolVersion &ver : config->dynamicList) {
std::vector<Symbol *> syms;
if (ver.hasWildcard)
syms = findAllByVersion(ver);
else
Syms = findByVersion(Ver);
syms = findByVersion(ver);

for (Symbol *B : Syms) {
if (!Config->Shared)
B->ExportDynamic = true;
else if (B->includeInDynsym())
B->IsPreemptible = true;
for (Symbol *b : syms) {
if (!config->shared)
b->exportDynamic = true;
else if (b->includeInDynsym())
b->isPreemptible = true;
}
}
}

// Set symbol versions to symbols. This function handles patterns
// containing no wildcard characters.
void SymbolTable::assignExactVersion(SymbolVersion Ver, uint16_t VersionId,
StringRef VersionName) {
if (Ver.HasWildcard)
void SymbolTable::assignExactVersion(SymbolVersion ver, uint16_t versionId,
StringRef versionName) {
if (ver.hasWildcard)
return;

// Get a list of symbols which we need to assign the version to.
std::vector<Symbol *> Syms = findByVersion(Ver);
if (Syms.empty()) {
if (!Config->UndefinedVersion)
error("version script assignment of '" + VersionName + "' to symbol '" +
Ver.Name + "' failed: symbol not defined");
std::vector<Symbol *> syms = findByVersion(ver);
if (syms.empty()) {
if (!config->undefinedVersion)
error("version script assignment of '" + versionName + "' to symbol '" +
ver.name + "' failed: symbol not defined");
return;
}

// Assign the version.
for (Symbol *Sym : Syms) {
for (Symbol *sym : syms) {
// Skip symbols containing version info because symbol versions
// specified by symbol names take precedence over version scripts.
// See parseSymbolVersion().
if (Sym->getName().contains('@'))
if (sym->getName().contains('@'))
continue;

if (Sym->VersionId != Config->DefaultSymbolVersion &&
Sym->VersionId != VersionId)
error("duplicate symbol '" + Ver.Name + "' in version script");
Sym->VersionId = VersionId;
if (sym->versionId != config->defaultSymbolVersion &&
sym->versionId != versionId)
error("duplicate symbol '" + ver.name + "' in version script");
sym->versionId = versionId;
}
}

void SymbolTable::assignWildcardVersion(SymbolVersion Ver, uint16_t VersionId) {
if (!Ver.HasWildcard)
void SymbolTable::assignWildcardVersion(SymbolVersion ver, uint16_t versionId) {
if (!ver.hasWildcard)
return;

// Exact matching takes precendence over fuzzy matching,
// so we set a version to a symbol only if no version has been assigned
// to the symbol. This behavior is compatible with GNU.
for (Symbol *B : findAllByVersion(Ver))
if (B->VersionId == Config->DefaultSymbolVersion)
B->VersionId = VersionId;
for (Symbol *b : findAllByVersion(ver))
if (b->versionId == config->defaultSymbolVersion)
b->versionId = versionId;
}

// This function processes version scripts by updating VersionId
Expand All @@ -241,21 +241,21 @@ void SymbolTable::scanVersionScript() {

// First, we assign versions to exact matching symbols,
// i.e. version definitions not containing any glob meta-characters.
for (VersionDefinition &V : Config->VersionDefinitions)
for (SymbolVersion &Ver : V.Globals)
assignExactVersion(Ver, V.Id, V.Name);
for (VersionDefinition &v : config->versionDefinitions)
for (SymbolVersion &ver : v.globals)
assignExactVersion(ver, v.id, v.name);

// Next, we assign versions to fuzzy matching symbols,
// i.e. version definitions containing glob meta-characters.
// Note that because the last match takes precedence over previous matches,
// we iterate over the definitions in the reverse order.
for (VersionDefinition &V : llvm::reverse(Config->VersionDefinitions))
for (SymbolVersion &Ver : V.Globals)
assignWildcardVersion(Ver, V.Id);
for (VersionDefinition &v : llvm::reverse(config->versionDefinitions))
for (SymbolVersion &ver : v.globals)
assignWildcardVersion(ver, v.id);

// Symbol themselves might know their versions because symbols
// can contain versions in the form of <name>@<version>.
// Let them parse and update their names to exclude version suffix.
for (Symbol *Sym : SymVector)
Sym->parseSymbolVersion();
for (Symbol *sym : symVector)
sym->parseSymbolVersion();
}
36 changes: 18 additions & 18 deletions lld/ELF/SymbolTable.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,41 +33,41 @@ namespace elf {
// is one add* function per symbol type.
class SymbolTable {
public:
void wrap(Symbol *Sym, Symbol *Real, Symbol *Wrap);
void wrap(Symbol *sym, Symbol *real, Symbol *wrap);

void forEachSymbol(llvm::function_ref<void(Symbol *)> Fn) {
for (Symbol *Sym : SymVector)
if (!Sym->isPlaceholder())
Fn(Sym);
void forEachSymbol(llvm::function_ref<void(Symbol *)> fn) {
for (Symbol *sym : symVector)
if (!sym->isPlaceholder())
fn(sym);
}

Symbol *insert(StringRef Name);
Symbol *insert(StringRef name);

Symbol *addSymbol(const Symbol &New);

void scanVersionScript();

Symbol *find(StringRef Name);
Symbol *find(StringRef name);

void handleDynamicList();

// Set of .so files to not link the same shared object file more than once.
llvm::DenseMap<StringRef, SharedFile *> SoNames;
llvm::DenseMap<StringRef, SharedFile *> soNames;

// Comdat groups define "link once" sections. If two comdat groups have the
// same name, only one of them is linked, and the other is ignored. This map
// is used to uniquify them.
llvm::DenseMap<llvm::CachedHashStringRef, const InputFile *> ComdatGroups;
llvm::DenseMap<llvm::CachedHashStringRef, const InputFile *> comdatGroups;

private:
std::vector<Symbol *> findByVersion(SymbolVersion Ver);
std::vector<Symbol *> findAllByVersion(SymbolVersion Ver);
std::vector<Symbol *> findByVersion(SymbolVersion ver);
std::vector<Symbol *> findAllByVersion(SymbolVersion ver);

llvm::StringMap<std::vector<Symbol *>> &getDemangledSyms();
void handleAnonymousVersion();
void assignExactVersion(SymbolVersion Ver, uint16_t VersionId,
StringRef VersionName);
void assignWildcardVersion(SymbolVersion Ver, uint16_t VersionId);
void assignExactVersion(SymbolVersion ver, uint16_t versionId,
StringRef versionName);
void assignWildcardVersion(SymbolVersion ver, uint16_t versionId);

// The order the global symbols are in is not defined. We can use an arbitrary
// order, but it has to be reproducible. That is true even when cross linking.
Expand All @@ -76,17 +76,17 @@ class SymbolTable {
// but a bit inefficient.
// FIXME: Experiment with passing in a custom hashing or sorting the symbols
// once symbol resolution is finished.
llvm::DenseMap<llvm::CachedHashStringRef, int> SymMap;
std::vector<Symbol *> SymVector;
llvm::DenseMap<llvm::CachedHashStringRef, int> symMap;
std::vector<Symbol *> symVector;

// A map from demangled symbol names to their symbol objects.
// This mapping is 1:N because two symbols with different versions
// can have the same name. We use this map to handle "extern C++ {}"
// directive in version scripts.
llvm::Optional<llvm::StringMap<std::vector<Symbol *>>> DemangledSyms;
llvm::Optional<llvm::StringMap<std::vector<Symbol *>>> demangledSyms;
};

extern SymbolTable *Symtab;
extern SymbolTable *symtab;

} // namespace elf
} // namespace lld
Expand Down
506 changes: 253 additions & 253 deletions lld/ELF/Symbols.cpp

Large diffs are not rendered by default.

326 changes: 163 additions & 163 deletions lld/ELF/Symbols.h

Large diffs are not rendered by default.

3,346 changes: 1,673 additions & 1,673 deletions lld/ELF/SyntheticSections.cpp

Large diffs are not rendered by default.

692 changes: 346 additions & 346 deletions lld/ELF/SyntheticSections.h

Large diffs are not rendered by default.

90 changes: 45 additions & 45 deletions lld/ELF/Target.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,17 @@ using namespace llvm::ELF;
using namespace lld;
using namespace lld::elf;

const TargetInfo *elf::Target;
const TargetInfo *elf::target;

std::string lld::toString(RelType Type) {
StringRef S = getELFRelocationTypeName(elf::Config->EMachine, Type);
if (S == "Unknown")
return ("Unknown (" + Twine(Type) + ")").str();
return S;
std::string lld::toString(RelType type) {
StringRef s = getELFRelocationTypeName(elf::config->emachine, type);
if (s == "Unknown")
return ("Unknown (" + Twine(type) + ")").str();
return s;
}

TargetInfo *elf::getTarget() {
switch (Config->EMachine) {
switch (config->emachine) {
case EM_386:
case EM_IAMCU:
return getX86TargetInfo();
Expand All @@ -62,7 +62,7 @@ TargetInfo *elf::getTarget() {
case EM_HEXAGON:
return getHexagonTargetInfo();
case EM_MIPS:
switch (Config->EKind) {
switch (config->ekind) {
case ELF32LEKind:
return getMipsTargetInfo<ELF32LE>();
case ELF32BEKind:
Expand Down Expand Up @@ -90,92 +90,92 @@ TargetInfo *elf::getTarget() {
llvm_unreachable("unknown target machine");
}

template <class ELFT> static ErrorPlace getErrPlace(const uint8_t *Loc) {
for (InputSectionBase *D : InputSections) {
auto *IS = cast<InputSection>(D);
if (!IS->getParent())
template <class ELFT> static ErrorPlace getErrPlace(const uint8_t *loc) {
for (InputSectionBase *d : inputSections) {
auto *isec = cast<InputSection>(d);
if (!isec->getParent())
continue;

uint8_t *ISLoc = Out::BufferStart + IS->getParent()->Offset + IS->OutSecOff;
if (ISLoc <= Loc && Loc < ISLoc + IS->getSize())
return {IS, IS->template getLocation<ELFT>(Loc - ISLoc) + ": "};
uint8_t *isecLoc = Out::bufferStart + isec->getParent()->offset + isec->outSecOff;
if (isecLoc <= loc && loc < isecLoc + isec->getSize())
return {isec, isec->template getLocation<ELFT>(loc - isecLoc) + ": "};
}
return {};
}

ErrorPlace elf::getErrorPlace(const uint8_t *Loc) {
switch (Config->EKind) {
ErrorPlace elf::getErrorPlace(const uint8_t *loc) {
switch (config->ekind) {
case ELF32LEKind:
return getErrPlace<ELF32LE>(Loc);
return getErrPlace<ELF32LE>(loc);
case ELF32BEKind:
return getErrPlace<ELF32BE>(Loc);
return getErrPlace<ELF32BE>(loc);
case ELF64LEKind:
return getErrPlace<ELF64LE>(Loc);
return getErrPlace<ELF64LE>(loc);
case ELF64BEKind:
return getErrPlace<ELF64BE>(Loc);
return getErrPlace<ELF64BE>(loc);
default:
llvm_unreachable("unknown ELF type");
}
}

TargetInfo::~TargetInfo() {}

int64_t TargetInfo::getImplicitAddend(const uint8_t *Buf, RelType Type) const {
int64_t TargetInfo::getImplicitAddend(const uint8_t *buf, RelType type) const {
return 0;
}

bool TargetInfo::usesOnlyLowPageBits(RelType Type) const { return false; }
bool TargetInfo::usesOnlyLowPageBits(RelType type) const { return false; }

bool TargetInfo::needsThunk(RelExpr Expr, RelType Type, const InputFile *File,
uint64_t BranchAddr, const Symbol &S) const {
bool TargetInfo::needsThunk(RelExpr expr, RelType type, const InputFile *file,
uint64_t branchAddr, const Symbol &s) const {
return false;
}

bool TargetInfo::adjustPrologueForCrossSplitStack(uint8_t *Loc, uint8_t *End,
uint8_t StOther) const {
bool TargetInfo::adjustPrologueForCrossSplitStack(uint8_t *loc, uint8_t *end,
uint8_t stOther) const {
llvm_unreachable("Target doesn't support split stacks.");
}

bool TargetInfo::inBranchRange(RelType Type, uint64_t Src, uint64_t Dst) const {
bool TargetInfo::inBranchRange(RelType type, uint64_t src, uint64_t dst) const {
return true;
}

void TargetInfo::writeIgotPlt(uint8_t *Buf, const Symbol &S) const {
writeGotPlt(Buf, S);
void TargetInfo::writeIgotPlt(uint8_t *buf, const Symbol &s) const {
writeGotPlt(buf, s);
}

RelExpr TargetInfo::adjustRelaxExpr(RelType Type, const uint8_t *Data,
RelExpr Expr) const {
return Expr;
RelExpr TargetInfo::adjustRelaxExpr(RelType type, const uint8_t *data,
RelExpr expr) const {
return expr;
}

void TargetInfo::relaxGot(uint8_t *Loc, RelType Type, uint64_t Val) const {
void TargetInfo::relaxGot(uint8_t *loc, RelType type, uint64_t val) const {
llvm_unreachable("Should not have claimed to be relaxable");
}

void TargetInfo::relaxTlsGdToLe(uint8_t *Loc, RelType Type,
uint64_t Val) const {
void TargetInfo::relaxTlsGdToLe(uint8_t *loc, RelType type,
uint64_t val) const {
llvm_unreachable("Should not have claimed to be relaxable");
}

void TargetInfo::relaxTlsGdToIe(uint8_t *Loc, RelType Type,
uint64_t Val) const {
void TargetInfo::relaxTlsGdToIe(uint8_t *loc, RelType type,
uint64_t val) const {
llvm_unreachable("Should not have claimed to be relaxable");
}

void TargetInfo::relaxTlsIeToLe(uint8_t *Loc, RelType Type,
uint64_t Val) const {
void TargetInfo::relaxTlsIeToLe(uint8_t *loc, RelType type,
uint64_t val) const {
llvm_unreachable("Should not have claimed to be relaxable");
}

void TargetInfo::relaxTlsLdToLe(uint8_t *Loc, RelType Type,
uint64_t Val) const {
void TargetInfo::relaxTlsLdToLe(uint8_t *loc, RelType type,
uint64_t val) const {
llvm_unreachable("Should not have claimed to be relaxable");
}

uint64_t TargetInfo::getImageBase() const {
// Use -image-base if set. Fall back to the target default if not.
if (Config->ImageBase)
return *Config->ImageBase;
return Config->Pic ? 0 : DefaultImageBase;
if (config->imageBase)
return *config->imageBase;
return config->isPic ? 0 : defaultImageBase;
}
210 changes: 105 additions & 105 deletions lld/ELF/Target.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
#include <array>

namespace lld {
std::string toString(elf::RelType Type);
std::string toString(elf::RelType type);

namespace elf {
class Defined;
Expand All @@ -26,39 +26,39 @@ class Symbol;
class TargetInfo {
public:
virtual uint32_t calcEFlags() const { return 0; }
virtual RelExpr getRelExpr(RelType Type, const Symbol &S,
const uint8_t *Loc) const = 0;
virtual RelType getDynRel(RelType Type) const { return 0; }
virtual void writeGotPltHeader(uint8_t *Buf) const {}
virtual void writeGotHeader(uint8_t *Buf) const {}
virtual void writeGotPlt(uint8_t *Buf, const Symbol &S) const {};
virtual void writeIgotPlt(uint8_t *Buf, const Symbol &S) const;
virtual int64_t getImplicitAddend(const uint8_t *Buf, RelType Type) const;
virtual int getTlsGdRelaxSkip(RelType Type) const { return 1; }
virtual RelExpr getRelExpr(RelType type, const Symbol &s,
const uint8_t *loc) const = 0;
virtual RelType getDynRel(RelType type) const { return 0; }
virtual void writeGotPltHeader(uint8_t *buf) const {}
virtual void writeGotHeader(uint8_t *buf) const {}
virtual void writeGotPlt(uint8_t *buf, const Symbol &s) const {};
virtual void writeIgotPlt(uint8_t *buf, const Symbol &s) const;
virtual int64_t getImplicitAddend(const uint8_t *buf, RelType type) const;
virtual int getTlsGdRelaxSkip(RelType type) const { return 1; }

// If lazy binding is supported, the first entry of the PLT has code
// to call the dynamic linker to resolve PLT entries the first time
// they are called. This function writes that code.
virtual void writePltHeader(uint8_t *Buf) const {}
virtual void writePltHeader(uint8_t *buf) const {}

virtual void writePlt(uint8_t *Buf, uint64_t GotEntryAddr,
uint64_t PltEntryAddr, int32_t Index,
unsigned RelOff) const {}
virtual void addPltHeaderSymbols(InputSection &IS) const {}
virtual void addPltSymbols(InputSection &IS, uint64_t Off) const {}
virtual void writePlt(uint8_t *buf, uint64_t gotEntryAddr,
uint64_t pltEntryAddr, int32_t index,
unsigned relOff) const {}
virtual void addPltHeaderSymbols(InputSection &isec) const {}
virtual void addPltSymbols(InputSection &isec, uint64_t off) const {}

// Returns true if a relocation only uses the low bits of a value such that
// all those bits are in the same page. For example, if the relocation
// only uses the low 12 bits in a system with 4k pages. If this is true, the
// bits will always have the same value at runtime and we don't have to emit
// a dynamic relocation.
virtual bool usesOnlyLowPageBits(RelType Type) const;
virtual bool usesOnlyLowPageBits(RelType type) const;

// Decide whether a Thunk is needed for the relocation from File
// targeting S.
virtual bool needsThunk(RelExpr Expr, RelType RelocType,
const InputFile *File, uint64_t BranchAddr,
const Symbol &S) const;
virtual bool needsThunk(RelExpr expr, RelType relocType,
const InputFile *file, uint64_t branchAddr,
const Symbol &s) const;

// On systems with range extensions we place collections of Thunks at
// regular spacings that enable the majority of branches reach the Thunks.
Expand All @@ -70,71 +70,71 @@ class TargetInfo {
// to do the right thing. See https://gcc.gnu.org/wiki/SplitStacks.
// The symbols st_other flags are needed on PowerPC64 for determining the
// offset to the split-stack prologue.
virtual bool adjustPrologueForCrossSplitStack(uint8_t *Loc, uint8_t *End,
uint8_t StOther) const;
virtual bool adjustPrologueForCrossSplitStack(uint8_t *loc, uint8_t *end,
uint8_t stOther) const;

// Return true if we can reach Dst from Src with Relocation RelocType
virtual bool inBranchRange(RelType Type, uint64_t Src,
uint64_t Dst) const;
virtual bool inBranchRange(RelType type, uint64_t src,
uint64_t dst) const;

virtual void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const = 0;
virtual void relocateOne(uint8_t *loc, RelType type, uint64_t val) const = 0;

virtual ~TargetInfo();

unsigned DefaultCommonPageSize = 4096;
unsigned DefaultMaxPageSize = 4096;
unsigned defaultCommonPageSize = 4096;
unsigned defaultMaxPageSize = 4096;

uint64_t getImageBase() const;

// True if _GLOBAL_OFFSET_TABLE_ is relative to .got.plt, false if .got.
bool GotBaseSymInGotPlt = true;

RelType CopyRel;
RelType GotRel;
RelType NoneRel;
RelType PltRel;
RelType RelativeRel;
RelType IRelativeRel;
RelType SymbolicRel;
RelType TlsDescRel;
RelType TlsGotRel;
RelType TlsModuleIndexRel;
RelType TlsOffsetRel;
unsigned PltEntrySize;
unsigned PltHeaderSize;
bool gotBaseSymInGotPlt = true;

RelType copyRel;
RelType gotRel;
RelType noneRel;
RelType pltRel;
RelType relativeRel;
RelType iRelativeRel;
RelType symbolicRel;
RelType tlsDescRel;
RelType tlsGotRel;
RelType tlsModuleIndexRel;
RelType tlsOffsetRel;
unsigned pltEntrySize;
unsigned pltHeaderSize;

// At least on x86_64 positions 1 and 2 are used by the first plt entry
// to support lazy loading.
unsigned GotPltHeaderEntriesNum = 3;
unsigned gotPltHeaderEntriesNum = 3;

// On PPC ELF V2 abi, the first entry in the .got is the .TOC.
unsigned GotHeaderEntriesNum = 0;
unsigned gotHeaderEntriesNum = 0;

bool NeedsThunks = false;
bool needsThunks = false;

// A 4-byte field corresponding to one or more trap instructions, used to pad
// executable OutputSections.
std::array<uint8_t, 4> TrapInstr;
std::array<uint8_t, 4> trapInstr;

// If a target needs to rewrite calls to __morestack to instead call
// __morestack_non_split when a split-stack enabled caller calls a
// non-split-stack callee this will return true. Otherwise returns false.
bool NeedsMoreStackNonSplit = true;
bool needsMoreStackNonSplit = true;

virtual RelExpr adjustRelaxExpr(RelType Type, const uint8_t *Data,
RelExpr Expr) const;
virtual void relaxGot(uint8_t *Loc, RelType Type, uint64_t Val) const;
virtual void relaxTlsGdToIe(uint8_t *Loc, RelType Type, uint64_t Val) const;
virtual void relaxTlsGdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const;
virtual void relaxTlsIeToLe(uint8_t *Loc, RelType Type, uint64_t Val) const;
virtual void relaxTlsLdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const;
virtual RelExpr adjustRelaxExpr(RelType type, const uint8_t *data,
RelExpr expr) const;
virtual void relaxGot(uint8_t *loc, RelType type, uint64_t val) const;
virtual void relaxTlsGdToIe(uint8_t *loc, RelType type, uint64_t val) const;
virtual void relaxTlsGdToLe(uint8_t *loc, RelType type, uint64_t val) const;
virtual void relaxTlsIeToLe(uint8_t *loc, RelType type, uint64_t val) const;
virtual void relaxTlsLdToLe(uint8_t *loc, RelType type, uint64_t val) const;

protected:
// On FreeBSD x86_64 the first page cannot be mmaped.
// On Linux that is controled by vm.mmap_min_addr. At least on some x86_64
// installs that is 65536, so the first 15 pages cannot be used.
// Given that, the smallest value that can be used in here is 0x10000.
uint64_t DefaultImageBase = 0x10000;
uint64_t defaultImageBase = 0x10000;
};

TargetInfo *getAArch64TargetInfo();
Expand All @@ -152,22 +152,22 @@ TargetInfo *getX86_64TargetInfo();
template <class ELFT> TargetInfo *getMipsTargetInfo();

struct ErrorPlace {
InputSectionBase *IS;
std::string Loc;
InputSectionBase *isec;
std::string loc;
};

// Returns input section and corresponding source string for the given location.
ErrorPlace getErrorPlace(const uint8_t *Loc);
ErrorPlace getErrorPlace(const uint8_t *loc);

static inline std::string getErrorLocation(const uint8_t *Loc) {
return getErrorPlace(Loc).Loc;
static inline std::string getErrorLocation(const uint8_t *loc) {
return getErrorPlace(loc).loc;
}

void writePPC32GlinkSection(uint8_t *Buf, size_t NumEntries);
void writePPC32GlinkSection(uint8_t *buf, size_t numEntries);

bool tryRelaxPPC64TocIndirection(RelType Type, const Relocation &Rel,
uint8_t *BufLoc);
unsigned getPPCDFormOp(unsigned SecondaryOp);
bool tryRelaxPPC64TocIndirection(RelType type, const Relocation &rel,
uint8_t *bufLoc);
unsigned getPPCDFormOp(unsigned secondaryOp);

// In the PowerPC64 Elf V2 abi a function can have 2 entry points. The first
// is a global entry point (GEP) which typically is used to initialize the TOC
Expand All @@ -176,84 +176,84 @@ unsigned getPPCDFormOp(unsigned SecondaryOp);
// offset between GEP and LEP is encoded in a function's st_other flags.
// This function will return the offset (in bytes) from the global entry-point
// to the local entry-point.
unsigned getPPC64GlobalEntryToLocalEntryOffset(uint8_t StOther);
unsigned getPPC64GlobalEntryToLocalEntryOffset(uint8_t stOther);

// Returns true if a relocation is a small code model relocation that accesses
// the .toc section.
bool isPPC64SmallCodeModelTocReloc(RelType Type);
bool isPPC64SmallCodeModelTocReloc(RelType type);

uint64_t getPPC64TocBase();
uint64_t getAArch64Page(uint64_t Expr);
uint64_t getAArch64Page(uint64_t expr);

extern const TargetInfo *Target;
extern const TargetInfo *target;
TargetInfo *getTarget();

template <class ELFT> bool isMipsPIC(const Defined *Sym);
template <class ELFT> bool isMipsPIC(const Defined *sym);

static inline void reportRangeError(uint8_t *Loc, RelType Type, const Twine &V,
int64_t Min, uint64_t Max) {
ErrorPlace ErrPlace = getErrorPlace(Loc);
StringRef Hint;
if (ErrPlace.IS && ErrPlace.IS->Name.startswith(".debug"))
Hint = "; consider recompiling with -fdebug-types-section to reduce size "
static inline void reportRangeError(uint8_t *loc, RelType type, const Twine &v,
int64_t min, uint64_t max) {
ErrorPlace errPlace = getErrorPlace(loc);
StringRef hint;
if (errPlace.isec && errPlace.isec->name.startswith(".debug"))
hint = "; consider recompiling with -fdebug-types-section to reduce size "
"of debug sections";

errorOrWarn(ErrPlace.Loc + "relocation " + lld::toString(Type) +
" out of range: " + V.str() + " is not in [" + Twine(Min).str() +
", " + Twine(Max).str() + "]" + Hint);
errorOrWarn(errPlace.loc + "relocation " + lld::toString(type) +
" out of range: " + v.str() + " is not in [" + Twine(min).str() +
", " + Twine(max).str() + "]" + hint);
}

// Make sure that V can be represented as an N bit signed integer.
inline void checkInt(uint8_t *Loc, int64_t V, int N, RelType Type) {
if (V != llvm::SignExtend64(V, N))
reportRangeError(Loc, Type, Twine(V), llvm::minIntN(N), llvm::maxIntN(N));
inline void checkInt(uint8_t *loc, int64_t v, int n, RelType type) {
if (v != llvm::SignExtend64(v, n))
reportRangeError(loc, type, Twine(v), llvm::minIntN(n), llvm::maxIntN(n));
}

// Make sure that V can be represented as an N bit unsigned integer.
inline void checkUInt(uint8_t *Loc, uint64_t V, int N, RelType Type) {
if ((V >> N) != 0)
reportRangeError(Loc, Type, Twine(V), 0, llvm::maxUIntN(N));
inline void checkUInt(uint8_t *loc, uint64_t v, int n, RelType type) {
if ((v >> n) != 0)
reportRangeError(loc, type, Twine(v), 0, llvm::maxUIntN(n));
}

// Make sure that V can be represented as an N bit signed or unsigned integer.
inline void checkIntUInt(uint8_t *Loc, uint64_t V, int N, RelType Type) {
inline void checkIntUInt(uint8_t *loc, uint64_t v, int n, RelType type) {
// For the error message we should cast V to a signed integer so that error
// messages show a small negative value rather than an extremely large one
if (V != (uint64_t)llvm::SignExtend64(V, N) && (V >> N) != 0)
reportRangeError(Loc, Type, Twine((int64_t)V), llvm::minIntN(N),
llvm::maxUIntN(N));
if (v != (uint64_t)llvm::SignExtend64(v, n) && (v >> n) != 0)
reportRangeError(loc, type, Twine((int64_t)v), llvm::minIntN(n),
llvm::maxUIntN(n));
}

inline void checkAlignment(uint8_t *Loc, uint64_t V, int N, RelType Type) {
if ((V & (N - 1)) != 0)
error(getErrorLocation(Loc) + "improper alignment for relocation " +
lld::toString(Type) + ": 0x" + llvm::utohexstr(V) +
" is not aligned to " + Twine(N) + " bytes");
inline void checkAlignment(uint8_t *loc, uint64_t v, int n, RelType type) {
if ((v & (n - 1)) != 0)
error(getErrorLocation(loc) + "improper alignment for relocation " +
lld::toString(type) + ": 0x" + llvm::utohexstr(v) +
" is not aligned to " + Twine(n) + " bytes");
}

// Endianness-aware read/write.
inline uint16_t read16(const void *P) {
return llvm::support::endian::read16(P, Config->Endianness);
inline uint16_t read16(const void *p) {
return llvm::support::endian::read16(p, config->endianness);
}

inline uint32_t read32(const void *P) {
return llvm::support::endian::read32(P, Config->Endianness);
inline uint32_t read32(const void *p) {
return llvm::support::endian::read32(p, config->endianness);
}

inline uint64_t read64(const void *P) {
return llvm::support::endian::read64(P, Config->Endianness);
inline uint64_t read64(const void *p) {
return llvm::support::endian::read64(p, config->endianness);
}

inline void write16(void *P, uint16_t V) {
llvm::support::endian::write16(P, V, Config->Endianness);
inline void write16(void *p, uint16_t v) {
llvm::support::endian::write16(p, v, config->endianness);
}

inline void write32(void *P, uint32_t V) {
llvm::support::endian::write32(P, V, Config->Endianness);
inline void write32(void *p, uint32_t v) {
llvm::support::endian::write32(p, v, config->endianness);
}

inline void write64(void *P, uint64_t V) {
llvm::support::endian::write64(P, V, Config->Endianness);
inline void write64(void *p, uint64_t v) {
llvm::support::endian::write64(p, v, config->endianness);
}
} // namespace elf
} // namespace lld
Expand Down
808 changes: 404 additions & 404 deletions lld/ELF/Thunks.cpp

Large diffs are not rendered by default.

24 changes: 12 additions & 12 deletions lld/ELF/Thunks.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,20 @@ class ThunkSection;
// Thunks are assigned to synthetic ThunkSections
class Thunk {
public:
Thunk(Symbol &Destination);
Thunk(Symbol &destination);
virtual ~Thunk();

virtual uint32_t size() = 0;
virtual void writeTo(uint8_t *Buf) = 0;
virtual void writeTo(uint8_t *buf) = 0;

// All Thunks must define at least one symbol, known as the thunk target
// symbol, so that we can redirect relocations to it. The thunk may define
// additional symbols, but these are never targets for relocations.
virtual void addSymbols(ThunkSection &IS) = 0;
virtual void addSymbols(ThunkSection &isec) = 0;

void setOffset(uint64_t Offset);
Defined *addSymbol(StringRef Name, uint8_t Type, uint64_t Value,
InputSectionBase &Section);
void setOffset(uint64_t offset);
Defined *addSymbol(StringRef name, uint8_t type, uint64_t value,
InputSectionBase &section);

// Some Thunks must be placed immediately before their Target as they elide
// a branch and fall through to the first Symbol in the Target.
Expand All @@ -53,19 +53,19 @@ class Thunk {
return true;
}

Defined *getThunkTargetSym() const { return Syms[0]; }
Defined *getThunkTargetSym() const { return syms[0]; }

// The alignment requirement for this Thunk, defaults to the size of the
// typical code section alignment.
Symbol &Destination;
llvm::SmallVector<Defined *, 3> Syms;
uint64_t Offset = 0;
uint32_t Alignment = 4;
Symbol &destination;
llvm::SmallVector<Defined *, 3> syms;
uint64_t offset = 0;
uint32_t alignment = 4;
};

// For a Relocation to symbol S create a Thunk to be added to a synthetic
// ThunkSection.
Thunk *addThunk(const InputSection &IS, Relocation &Rel);
Thunk *addThunk(const InputSection &isec, Relocation &rel);

} // namespace elf
} // namespace lld
Expand Down
2,274 changes: 1,137 additions & 1,137 deletions lld/ELF/Writer.cpp

Large diffs are not rendered by default.

20 changes: 10 additions & 10 deletions lld/ELF/Writer.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ template <class ELFT> void writeResult();
// Each contains type, access flags and range of output sections that will be
// placed in it.
struct PhdrEntry {
PhdrEntry(unsigned Type, unsigned Flags) : p_type(Type), p_flags(Flags) {}
void add(OutputSection *Sec);
PhdrEntry(unsigned type, unsigned flags) : p_type(type), p_flags(flags) {}
void add(OutputSection *sec);

uint64_t p_paddr = 0;
uint64_t p_vaddr = 0;
Expand All @@ -37,22 +37,22 @@ struct PhdrEntry {
uint32_t p_type = 0;
uint32_t p_flags = 0;

OutputSection *FirstSec = nullptr;
OutputSection *LastSec = nullptr;
bool HasLMA = false;
OutputSection *firstSec = nullptr;
OutputSection *lastSec = nullptr;
bool hasLMA = false;

uint64_t LMAOffset = 0;
uint64_t lmaOffset = 0;
};

void addReservedSymbols();
llvm::StringRef getOutputSectionName(const InputSectionBase *S);
llvm::StringRef getOutputSectionName(const InputSectionBase *s);

template <class ELFT> uint32_t calcMipsEFlags();

uint8_t getMipsFpAbiFlag(uint8_t OldFlag, uint8_t NewFlag,
llvm::StringRef FileName);
uint8_t getMipsFpAbiFlag(uint8_t oldFlag, uint8_t newFlag,
llvm::StringRef fileName);

bool isMipsN32Abi(const InputFile *F);
bool isMipsN32Abi(const InputFile *f);
bool isMicroMips();
bool isMipsR6();
} // namespace elf
Expand Down