Define toString() as a generic function to get a string for error message.

We have different functions to stringize objects to construct
error messages. For InputFile, we have getFilename, and for
InputSection, we have getName. You had to memorize them.

I think this is the case where the function overloading comes in handy.

This patch defines toString() functions that are overloaded for all these
types, so that you just call it in error().

Differential Revision: https://reviews.llvm.org/D27030

llvm-svn: 287787
This commit is contained in:
Rui Ueyama 2016-11-23 18:07:33 +00:00
parent a6ee9fd642
commit 3fc0f7e54f
12 changed files with 66 additions and 58 deletions

View File

@ -81,8 +81,7 @@ lld::elf::readCuList(InputSection<ELFT> *DebugInfoSec) {
Dwarf.reset(new DWARFContextInMemory(*Obj.get()));
if (!Dwarf) {
error(getFilename(DebugInfoSec->getFile()) +
": error creating DWARF context");
error(toString(DebugInfoSec->getFile()) + ": error creating DWARF context");
return {};
}

View File

@ -95,7 +95,7 @@ std::string elf::ObjectFile<ELFT>::getLineInfo(InputSectionBase<ELFT> *S,
}
// Returns "(internal)", "foo.a(bar.o)" or "baz.o".
std::string elf::getFilename(const InputFile *F) {
std::string elf::toString(const InputFile *F) {
if (!F)
return "(internal)";
if (!F->ArchiveName.empty())
@ -132,7 +132,7 @@ void ELFFileBase<ELFT>::initSymtab(ArrayRef<Elf_Shdr> Sections,
FirstNonLocal = Symtab->sh_info;
Symbols = check(getObj().symbols(Symtab));
if (FirstNonLocal == 0 || FirstNonLocal > Symbols.size())
fatal(getFilename(this) + ": invalid sh_info in symbol table");
fatal(toString(this) + ": invalid sh_info in symbol table");
StringTable = check(getObj().getStringTableForSymtab(*Symtab, Sections));
}
@ -189,7 +189,7 @@ elf::ObjectFile<ELFT>::getShtGroupEntries(const Elf_Shdr &Sec) {
ArrayRef<Elf_Word> Entries =
check(Obj.template getSectionContentsAsArray<Elf_Word>(&Sec));
if (Entries.empty() || Entries[0] != GRP_COMDAT)
fatal(getFilename(this) + ": unsupported SHT_GROUP format");
fatal(toString(this) + ": unsupported SHT_GROUP format");
return Entries.slice(1);
}
@ -225,14 +225,14 @@ bool elf::ObjectFile<ELFT>::shouldMerge(const Elf_Shdr &Sec) {
if (EntSize == 0)
return false;
if (Sec.sh_size % EntSize)
fatal(getFilename(this) +
fatal(toString(this) +
": SHF_MERGE section size must be a multiple of sh_entsize");
uintX_t Flags = Sec.sh_flags;
if (!(Flags & SHF_MERGE))
return false;
if (Flags & SHF_WRITE)
fatal(getFilename(this) + ": writable SHF_MERGE section is not supported");
fatal(toString(this) + ": writable SHF_MERGE section is not supported");
// Don't try to merge if the alignment is larger than the sh_entsize and this
// is not SHF_STRINGS.
@ -277,7 +277,7 @@ void elf::ObjectFile<ELFT>::initializeSections(
continue;
for (uint32_t SecIndex : getShtGroupEntries(Sec)) {
if (SecIndex >= Size)
fatal(getFilename(this) + ": invalid section index in group: " +
fatal(toString(this) + ": invalid section index in group: " +
Twine(SecIndex));
Sections[SecIndex] = &InputSection<ELFT>::Discarded;
}
@ -299,7 +299,7 @@ void elf::ObjectFile<ELFT>::initializeSections(
// have a SHF_LINK_ORDER dependency, this is identified by the sh_link.
if (Sec.sh_flags & SHF_LINK_ORDER) {
if (Sec.sh_link >= Sections.size())
fatal(getFilename(this) + ": invalid sh_link index: " +
fatal(toString(this) + ": invalid sh_link index: " +
Twine(Sec.sh_link));
auto *IS = cast<InputSection<ELFT>>(Sections[Sec.sh_link]);
IS->DependentSection = Sections[I];
@ -312,8 +312,7 @@ InputSectionBase<ELFT> *
elf::ObjectFile<ELFT>::getRelocTarget(const Elf_Shdr &Sec) {
uint32_t Idx = Sec.sh_info;
if (Idx >= Sections.size())
fatal(getFilename(this) + ": invalid relocated section index: " +
Twine(Idx));
fatal(toString(this) + ": invalid relocated section index: " + Twine(Idx));
InputSectionBase<ELFT> *Target = Sections[Idx];
// Strictly speaking, a relocation section must be included in the
@ -323,7 +322,7 @@ elf::ObjectFile<ELFT>::getRelocTarget(const Elf_Shdr &Sec) {
return nullptr;
if (!Target)
fatal(getFilename(this) + ": unsupported relocation reference");
fatal(toString(this) + ": unsupported relocation reference");
return Target;
}
@ -353,10 +352,10 @@ elf::ObjectFile<ELFT>::createInputSection(const Elf_Shdr &Sec,
if (!Target)
return nullptr;
if (Target->FirstRelocation)
fatal(getFilename(this) +
fatal(toString(this) +
": multiple relocation sections to one section are not supported");
if (!isa<InputSection<ELFT>>(Target) && !isa<EhInputSection<ELFT>>(Target))
fatal(getFilename(this) +
fatal(toString(this) +
": relocations pointing to SHF_MERGE are not supported");
size_t NumRelocations;
@ -414,7 +413,7 @@ InputSectionBase<ELFT> *
elf::ObjectFile<ELFT>::getSection(const Elf_Sym &Sym) const {
uint32_t Index = this->getSectionIndex(Sym);
if (Index >= Sections.size())
fatal(getFilename(this) + ": invalid section index: " + Twine(Index));
fatal(toString(this) + ": invalid section index: " + Twine(Index));
InputSectionBase<ELFT> *S = Sections[Index];
// We found that GNU assembler 2.17.50 [FreeBSD] 2007-07-03 could
@ -426,7 +425,7 @@ elf::ObjectFile<ELFT>::getSection(const Elf_Sym &Sym) const {
if (Index == 0 || Sym.getType() == STT_SECTION ||
Sym.getType() == STT_NOTYPE)
return nullptr;
fatal(getFilename(this) + ": invalid section index: " + Twine(Index));
fatal(toString(this) + ": invalid section index: " + Twine(Index));
}
if (S == &InputSection<ELFT>::Discarded)
@ -444,7 +443,7 @@ SymbolBody *elf::ObjectFile<ELFT>::createSymbolBody(const Elf_Sym *Sym) {
SourceFile = check(Sym->getName(this->StringTable));
if (this->StringTable.size() <= Sym->st_name)
fatal(getFilename(this) + ": invalid symbol name offset");
fatal(toString(this) + ": invalid symbol name offset");
const char *Name = this->StringTable.data() + Sym->st_name;
if (Sym->st_shndx == SHN_UNDEF)
@ -466,7 +465,7 @@ SymbolBody *elf::ObjectFile<ELFT>::createSymbolBody(const Elf_Sym *Sym) {
->body();
case SHN_COMMON:
if (Value == 0 || Value >= UINT32_MAX)
fatal(getFilename(this) + ": common symbol '" + Name +
fatal(toString(this) + ": common symbol '" + Name +
"' has invalid alignment: " + Twine(Value));
return elf::Symtab<ELFT>::X
->addCommon(Name, Size, Value, Binding, StOther, Type, this)
@ -475,7 +474,7 @@ SymbolBody *elf::ObjectFile<ELFT>::createSymbolBody(const Elf_Sym *Sym) {
switch (Binding) {
default:
fatal(getFilename(this) + ": unexpected binding: " + Twine(Binding));
fatal(toString(this) + ": unexpected binding: " + Twine(Binding));
case STB_GLOBAL:
case STB_WEAK:
case STB_GNU_UNIQUE:
@ -577,12 +576,12 @@ template <class ELFT> void SharedFile<ELFT>::parseSoName() {
ArrayRef<Elf_Dyn> Arr =
check(Obj.template getSectionContentsAsArray<Elf_Dyn>(DynamicSec),
getFilename(this) + ": getSectionContentsAsArray failed");
toString(this) + ": getSectionContentsAsArray failed");
for (const Elf_Dyn &Dyn : Arr) {
if (Dyn.d_tag == DT_SONAME) {
uintX_t Val = Dyn.getVal();
if (Val >= this->StringTable.size())
fatal(getFilename(this) + ": invalid DT_SONAME entry");
fatal(toString(this) + ": invalid DT_SONAME entry");
SoName = StringRef(this->StringTable.data() + Val);
return;
}

View File

@ -85,7 +85,7 @@ private:
};
// Returns "(internal)", "foo.a(bar.o)" or "baz.o".
std::string getFilename(const InputFile *F);
std::string toString(const InputFile *F);
template <typename ELFT> class ELFFileBase : public InputFile {
public:
@ -150,7 +150,7 @@ public:
SymbolBody &getSymbolBody(uint32_t SymbolIndex) const {
if (SymbolIndex >= SymbolBodies.size())
fatal(getFilename(this) + ": invalid symbol index");
fatal(toString(this) + ": invalid symbol index");
return *SymbolBodies[SymbolIndex];
}

View File

@ -32,6 +32,12 @@ using namespace llvm::support::endian;
using namespace lld;
using namespace lld::elf;
// Returns a string to construct an error message.
template <class ELFT>
std::string elf::toString(const InputSectionBase<ELFT> *Sec) {
return (Sec->getFile()->getName() + ":(" + Sec->Name + ")").str();
}
template <class ELFT>
static ArrayRef<uint8_t> getSectionContents(elf::ObjectFile<ELFT> *File,
const typename ELFT::Shdr *Hdr) {
@ -65,13 +71,13 @@ InputSectionBase<ELFT>::InputSectionBase(elf::ObjectFile<ELFT> *File,
// no alignment constraits.
uint64_t V = std::max<uint64_t>(Addralign, 1);
if (!isPowerOf2_64(V))
fatal(getFilename(File) + ": section sh_addralign is not a power of 2");
fatal(toString(File) + ": section sh_addralign is not a power of 2");
// We reject object files having insanely large alignments even though
// they are allowed by the spec. I think 4GB is a reasonable limitation.
// We might want to relax this in the future.
if (V > UINT32_MAX)
fatal(getFilename(File) + ": section sh_addralign is too large");
fatal(toString(File) + ": section sh_addralign is too large");
Alignment = V;
}
@ -128,10 +134,10 @@ std::pair<ArrayRef<uint8_t>, uint64_t>
InputSectionBase<ELFT>::getElfCompressedData(ArrayRef<uint8_t> Data) {
// Compressed section with Elf_Chdr is the ELF standard.
if (Data.size() < sizeof(Elf_Chdr))
fatal(getName(this) + ": corrupted compressed section");
fatal(toString(this) + ": corrupted compressed section");
auto *Hdr = reinterpret_cast<const Elf_Chdr *>(Data.data());
if (Hdr->ch_type != ELFCOMPRESS_ZLIB)
fatal(getName(this) + ": unsupported compression type");
fatal(toString(this) + ": unsupported compression type");
return {Data.slice(sizeof(*Hdr)), Hdr->ch_size};
}
@ -147,16 +153,16 @@ InputSectionBase<ELFT>::getRawCompressedData(ArrayRef<uint8_t> Data) {
};
if (Data.size() < sizeof(ZlibHeader))
fatal(getName(this) + ": corrupted compressed section");
fatal(toString(this) + ": corrupted compressed section");
auto *Hdr = reinterpret_cast<const ZlibHeader *>(Data.data());
if (memcmp(Hdr->Magic, "ZLIB", 4))
fatal(getName(this) + ": broken ZLIB-compressed section");
fatal(toString(this) + ": broken ZLIB-compressed section");
return {Data.slice(sizeof(*Hdr)), read64be(Hdr->Size)};
}
template <class ELFT> void InputSectionBase<ELFT>::uncompress() {
if (!zlib::isAvailable())
fatal(getName(this) +
fatal(toString(this) +
": build lld with zlib to enable compressed sections support");
// This section is compressed. Here we decompress it. Ideally, all
@ -175,7 +181,7 @@ template <class ELFT> void InputSectionBase<ELFT>::uncompress() {
// Uncompress Buf.
char *OutputBuf = BAlloc.Allocate<char>(Size);
if (zlib::uncompress(toStringRef(Buf), OutputBuf, Size) != zlib::StatusOK)
fatal(getName(this) + ": error while uncompressing section");
fatal(toString(this) + ": error while uncompressing section");
Data = ArrayRef<uint8_t>((uint8_t *)OutputBuf, Size);
}
@ -667,7 +673,7 @@ MergeInputSection<ELFT>::splitStrings(ArrayRef<uint8_t> Data, size_t EntSize) {
while (!Data.empty()) {
size_t End = findNull(Data, EntSize);
if (End == StringRef::npos)
fatal(getName(this) + ": string is not null terminated");
fatal(toString(this) + ": string is not null terminated");
size_t Size = End + EntSize;
V.emplace_back(Off, !IsAlloca);
Hashes.push_back(hash_value(toStringRef(Data.slice(0, Size))));
@ -753,7 +759,7 @@ const SectionPiece *
MergeInputSection<ELFT>::getSectionPiece(uintX_t Offset) const {
uintX_t Size = this->Data.size();
if (Offset >= Size)
fatal(getName(this) + ": entry is past the end of the section");
fatal(toString(this) + ": entry is past the end of the section");
// Find the element this offset points to.
auto I = fastUpperBound(

View File

@ -300,6 +300,8 @@ private:
template <class ELFT> InputSection<ELFT> InputSection<ELFT>::Discarded;
template <class ELFT> std::string toString(const InputSectionBase<ELFT> *);
} // namespace elf
} // namespace lld

View File

@ -271,8 +271,8 @@ static int32_t findMipsPairedAddend(const uint8_t *Buf, const uint8_t *BufLoc,
return ((read32<E>(BufLoc) & 0xffff) << 16) +
readSignedLo16<E>(Buf + RI->r_offset);
}
warn("can't find matching " + getRelName(Type) + " relocation for " +
getRelName(Rel->getType(Config->Mips64EL)));
warn("can't find matching " + toString(Type) + " relocation for " +
toString(Rel->getType(Config->Mips64EL)));
return 0;
}
@ -343,9 +343,9 @@ static bool isStaticLinkTimeConstant(RelExpr E, uint32_t Type,
if (AbsVal && RelE) {
if (Body.isUndefined() && !Body.isLocal() && Body.symbol()->isWeak())
return true;
error(getLocation(S, RelOff) + ": relocation " + getRelName(Type) +
error(getLocation(S, RelOff) + ": relocation " + toString(Type) +
" cannot refer to absolute symbol '" + Body.getName() +
"' defined in " + getFilename(Body.File));
"' defined in " + toString(Body.File));
return true;
}
@ -445,15 +445,15 @@ static RelExpr adjustExpr(const elf::ObjectFile<ELFT> &File, SymbolBody &Body,
if (Config->Shared || (Config->Pic && !isRelExpr(Expr))) {
StringRef Name = Body.getName();
error(getLocation(S, RelOff) + ": can't create dynamic relocation " +
getRelName(Type) + " against " +
toString(Type) + " against " +
((Name.empty() ? "local symbol in readonly segment"
: "symbol '" + Name + "'")) +
" defined in " + getFilename(Body.File));
" defined in " + toString(Body.File));
return Expr;
}
if (Body.getVisibility() != STV_DEFAULT) {
error(getLocation(S, RelOff) + ": cannot preempt symbol '" +
Body.getName() + "' defined in " + getFilename(Body.File));
Body.getName() + "' defined in " + toString(Body.File));
return Expr;
}
if (Body.isObject()) {
@ -487,7 +487,7 @@ static RelExpr adjustExpr(const elf::ObjectFile<ELFT> &File, SymbolBody &Body,
Body.NeedsCopyOrPltAddr = true;
return toPlt(Expr);
}
error("symbol '" + Body.getName() + "' defined in " + getFilename(Body.File) +
error("symbol '" + Body.getName() + "' defined in " + toString(Body.File) +
" is missing type");
return Expr;
@ -548,7 +548,7 @@ std::string getLocation(InputSectionBase<ELFT> &S, typename ELFT::uint Offset) {
// missing, we use an actual filename.
std::string SrcFile = File->SourceFile;
if (SrcFile.empty())
SrcFile = getFilename(File);
SrcFile = toString(File);
// Find a symbol at a given location.
DefinedRegular<ELFT> *Encl = getSymbolAt(&S, Offset);

View File

@ -74,7 +74,7 @@ template <class ELFT> void SymbolTable<ELFT>::addFile(InputFile *File) {
}
if (Config->Trace)
outs() << getFilename(File) << "\n";
outs() << toString(File) << "\n";
// .so file
if (auto *F = dyn_cast<SharedFile<ELFT>>(File)) {
@ -207,7 +207,7 @@ std::pair<Symbol *, bool> SymbolTable<ELFT>::insert(StringRef Name) {
// Used to construct an error message.
static std::string conflictMsg(SymbolBody *Existing, InputFile *NewFile) {
return "'" + maybeDemangle(Existing->getName()) + "' in " +
getFilename(Existing->File) + " and " + getFilename(NewFile);
toString(Existing->File) + " and " + toString(NewFile);
}
// Find an existing symbol or create and insert a new one, then apply the given

View File

@ -64,7 +64,7 @@ static typename ELFT::uint getSymVA(const SymbolBody &Body,
uintX_t VA = (SC->OutSec ? SC->OutSec->Addr : 0) + SC->getOffset(Offset);
if (D.isTls() && !Config->Relocatable) {
if (!Out<ELFT>::TlsPhdr)
fatal(getFilename(D.File) +
fatal(toString(D.File) +
" has a STT_TLS symbol but doesn't have a PT_TLS section");
return VA - Out<ELFT>::TlsPhdr->p_vaddr;
}
@ -307,7 +307,7 @@ bool Symbol::includeInDynsym() const {
// Print out a log message for --trace-symbol.
void elf::printTraceSymbol(Symbol *Sym) {
SymbolBody *B = Sym->body();
outs() << getFilename(B->File);
outs() << toString(B->File);
if (B->isUndefined())
outs() << ": reference to ";

View File

@ -134,7 +134,7 @@ MipsAbiFlagsSection<ELFT> *MipsAbiFlagsSection<ELFT>::create() {
Sec->Live = false;
Create = true;
std::string Filename = getFilename(Sec->getFile());
std::string Filename = toString(Sec->getFile());
if (Sec->Data.size() != sizeof(Elf_Mips_ABIFlags)) {
error(Filename + ": invalid size of .MIPS.abiflags section");
return nullptr;
@ -196,7 +196,7 @@ MipsOptionsSection<ELFT> *MipsOptionsSection<ELFT>::create() {
Sec->Live = false;
Create = true;
std::string Filename = getFilename(Sec->getFile());
std::string Filename = toString(Sec->getFile());
ArrayRef<uint8_t> D = Sec->Data;
while (!D.empty()) {
@ -253,12 +253,12 @@ MipsReginfoSection<ELFT> *MipsReginfoSection<ELFT>::create() {
Create = true;
if (Sec->Data.size() != sizeof(Elf_Mips_RegInfo)) {
error(getFilename(Sec->getFile()) + ": invalid size of .reginfo section");
error(toString(Sec->getFile()) + ": invalid size of .reginfo section");
return nullptr;
}
auto *R = reinterpret_cast<const Elf_Mips_RegInfo *>(Sec->Data.data());
if (Config->Relocatable && R->ri_gp_value)
error(getFilename(Sec->getFile()) + ": unsupported non-zero ri_gp_value");
error(toString(Sec->getFile()) + ": unsupported non-zero ri_gp_value");
Reginfo.ri_gprmask |= R->ri_gprmask;
Sec->getFile()->MipsGp0 = R->ri_gp_value;

View File

@ -51,32 +51,32 @@ TargetInfo *Target;
static void or32le(uint8_t *P, int32_t V) { write32le(P, read32le(P) | V); }
static void or32be(uint8_t *P, int32_t V) { write32be(P, read32be(P) | V); }
StringRef getRelName(uint32_t Type) {
std::string toString(uint32_t Type) {
return getELFRelocationTypeName(Config->EMachine, Type);
}
template <unsigned N> static void checkInt(int64_t V, uint32_t Type) {
if (!isInt<N>(V))
error("relocation " + getRelName(Type) + " out of range");
error("relocation " + toString(Type) + " out of range");
}
template <unsigned N> static void checkUInt(uint64_t V, uint32_t Type) {
if (!isUInt<N>(V))
error("relocation " + getRelName(Type) + " out of range");
error("relocation " + toString(Type) + " out of range");
}
template <unsigned N> static void checkIntUInt(uint64_t V, uint32_t Type) {
if (!isInt<N>(V) && !isUInt<N>(V))
error("relocation " + getRelName(Type) + " out of range");
error("relocation " + toString(Type) + " out of range");
}
template <unsigned N> static void checkAlignment(uint64_t V, uint32_t Type) {
if ((V & (N - 1)) != 0)
error("improper alignment for relocation " + getRelName(Type));
error("improper alignment for relocation " + toString(Type));
}
static void errorDynRel(uint32_t Type) {
error("relocation " + getRelName(Type) +
error("relocation " + toString(Type) +
" cannot be used against shared object; recompile with -fPIC.");
}

View File

@ -102,7 +102,7 @@ public:
virtual void relaxTlsLdToLe(uint8_t *Loc, uint32_t Type, uint64_t Val) const;
};
StringRef getRelName(uint32_t Type);
std::string toString(uint32_t RelType);
uint64_t getPPC64TocBase();
const unsigned MipsGPOffset = 0x7ff0;

View File

@ -376,14 +376,16 @@ template <class ELFT> void Writer<ELFT>::copyLocalSymbols() {
for (elf::ObjectFile<ELFT> *F : Symtab<ELFT>::X->getObjectFiles()) {
for (SymbolBody *B : F->getLocalSymbols()) {
if (!B->IsLocal)
fatal(getFilename(F) +
fatal(toString(F) +
": broken object: getLocalSymbols returns a non-local symbol");
auto *DR = dyn_cast<DefinedRegular<ELFT>>(B);
// No reason to keep local undefined symbol in symtab.
if (!DR)
continue;
if (!includeInSymtab<ELFT>(*B))
continue;
InputSectionBase<ELFT> *Sec = DR->Section;
if (!shouldKeepInSymtab<ELFT>(Sec, B->getName(), *B))
continue;