From 7c5ea75431f158dfca56453463ea4dd564ac8eac Mon Sep 17 00:00:00 2001 From: robert Date: Thu, 17 Nov 2022 12:24:02 +0000 Subject: [PATCH] add .gnu.warning.SYMBOL support to ld.lld(1) to display the warnings in these sections like ld.bfd(1) e.g: add.c(add.o:(add)): warning: sprintf() is often misused, please use snprintf() add.c(add.o:(add)): warning: strcpy() is almost always misused, please use strlcpy() add.c(add.o:(add)): warning: strcat() is almost always misused, please use strlcat() ok deraadt@ --- gnu/llvm/lld/ELF/InputFiles.cpp | 31 +++++++++++++++++++++++++++++++ gnu/llvm/lld/ELF/InputFiles.h | 2 ++ gnu/llvm/lld/ELF/Relocations.cpp | 14 ++++++++++++++ gnu/llvm/lld/ELF/SymbolTable.cpp | 1 + gnu/llvm/lld/ELF/Symbols.h | 8 +++++++- 5 files changed, 55 insertions(+), 1 deletion(-) diff --git a/gnu/llvm/lld/ELF/InputFiles.cpp b/gnu/llvm/lld/ELF/InputFiles.cpp index ab65571887d..75652403e1d 100644 --- a/gnu/llvm/lld/ELF/InputFiles.cpp +++ b/gnu/llvm/lld/ELF/InputFiles.cpp @@ -52,6 +52,8 @@ std::vector elf::sharedFiles; std::unique_ptr elf::tar; +DenseMap elf::gnuWarnings; + // Returns "", "foo.a(bar.o)" or "baz.o". std::string lld::toString(const InputFile *f) { if (!f) @@ -66,6 +68,17 @@ std::string lld::toString(const InputFile *f) { return f->toStringCache; } +// .gnu.warning.SYMBOL are treated as warning symbols for the given symbol +void lld::parseGNUWarning(StringRef name, ArrayRef data, size_t size) { + if (!name.empty() && name.startswith(".gnu.warning.")) { + StringRef wsym = name.substr(13); + StringRef s(data.begin()); + StringRef wng(s.substr(0, size)); + symtab->insert(wsym)->gwarn = true; + gnuWarnings.insert({wsym, wng}); + } +} + static ELFKind getELFKind(MemoryBufferRef mb, StringRef archiveName) { unsigned char size; unsigned char endian; @@ -647,6 +660,14 @@ void ObjFile::initializeSections(bool ignoreComdats) { case SHT_RELA: case SHT_NULL: break; + case SHT_PROGBITS: { + this->sections[i] = createInputSection(sec); + StringRef name = CHECK(obj.getSectionName(sec, this->sectionStringTable), this); + ArrayRef data = + CHECK(obj.template getSectionContentsAsArray(sec), this); + parseGNUWarning(name, data, sec.sh_size); + } + break; default: this->sections[i] = createInputSection(sec); } @@ -1450,6 +1471,9 @@ template void SharedFile::parse() { const ELFFile obj = this->getObj(); ArrayRef sections = CHECK(obj.sections(), this); + StringRef sectionStringTable = + CHECK(obj.getSectionStringTable(sections), this); + const Elf_Shdr *versymSec = nullptr; const Elf_Shdr *verdefSec = nullptr; const Elf_Shdr *verneedSec = nullptr; @@ -1472,6 +1496,13 @@ template void SharedFile::parse() { case SHT_GNU_verneed: verneedSec = &sec; break; + case SHT_PROGBITS: { + StringRef name = CHECK(obj.getSectionName(sec, sectionStringTable), this); + ArrayRef data = + CHECK(obj.template getSectionContentsAsArray(sec), this); + parseGNUWarning(name, data, sec.sh_size); + break; + } } } diff --git a/gnu/llvm/lld/ELF/InputFiles.h b/gnu/llvm/lld/ELF/InputFiles.h index bd72cfcdd05..4d64a6551d0 100644 --- a/gnu/llvm/lld/ELF/InputFiles.h +++ b/gnu/llvm/lld/ELF/InputFiles.h @@ -37,6 +37,8 @@ class DWARFCache; // Returns "", "foo.a(bar.o)" or "baz.o". std::string toString(const elf::InputFile *f); +void parseGNUWarning(StringRef name, ArrayRef data, size_t size); + namespace elf { using llvm::object::Archive; diff --git a/gnu/llvm/lld/ELF/Relocations.cpp b/gnu/llvm/lld/ELF/Relocations.cpp index bf576752c54..114780e0f9a 100644 --- a/gnu/llvm/lld/ELF/Relocations.cpp +++ b/gnu/llvm/lld/ELF/Relocations.cpp @@ -954,6 +954,18 @@ template void elf::reportUndefinedSymbols() { undefs.clear(); } +static void reportGNUWarning(Symbol &sym, InputSectionBase &sec, + uint64_t offset) { + if (sym.gwarn) { + StringRef gnuWarning = gnuWarnings.lookup(sym.getName()); + // report first occurance only + sym.gwarn = false; + if (!gnuWarning.empty()) + message(sec.getSrcMsg(sym, offset) + "(" + sec.getObjMsg(offset) + + "): warning: " + gnuWarning); + } +} + // Report an undefined symbol if necessary. // Returns true if the undefined symbol will produce an error message. static bool maybeReportUndefined(Symbol &sym, InputSectionBase &sec, @@ -1327,6 +1339,8 @@ static void scanReloc(InputSectionBase &sec, OffsetGetter &getOffset, RelTy *&i, if (symIndex != 0 && maybeReportUndefined(sym, sec, rel.r_offset)) return; + reportGNUWarning(sym, sec, rel.r_offset); + const uint8_t *relocatedAddr = sec.data().begin() + rel.r_offset; RelExpr expr = target->getRelExpr(type, sym, relocatedAddr); diff --git a/gnu/llvm/lld/ELF/SymbolTable.cpp b/gnu/llvm/lld/ELF/SymbolTable.cpp index 22e6b4f9289..da1684a91ee 100644 --- a/gnu/llvm/lld/ELF/SymbolTable.cpp +++ b/gnu/llvm/lld/ELF/SymbolTable.cpp @@ -90,6 +90,7 @@ Symbol *SymbolTable::insert(StringRef name) { sym->canInline = true; sym->referenced = false; sym->traced = false; + sym->gwarn = false; sym->scriptDefined = false; sym->partition = 1; return sym; diff --git a/gnu/llvm/lld/ELF/Symbols.h b/gnu/llvm/lld/ELF/Symbols.h index d4a589ee600..3a4f851a7d4 100644 --- a/gnu/llvm/lld/ELF/Symbols.h +++ b/gnu/llvm/lld/ELF/Symbols.h @@ -142,6 +142,9 @@ public: // True if this symbol is specified by --trace-symbol option. uint8_t traced : 1; + // True if the .gnu.warning.SYMBOL is set for the symbol + uint8_t gwarn : 1; + inline void replace(const Symbol &newSym); bool includeInDynsym() const; @@ -247,7 +250,7 @@ protected: type(type), stOther(stOther), symbolKind(k), visibility(stOther & 3), isUsedInRegularObj(!file || file->kind() == InputFile::ObjKind), exportDynamic(isExportDynamic(k, visibility)), inDynamicList(false), - canInline(false), referenced(false), traced(false), needsPltAddr(false), + canInline(false), referenced(false), traced(false), gwarn(false), needsPltAddr(false), isInIplt(false), gotInIgot(false), isPreemptible(false), used(!config->gcSections), needsTocRestore(false), scriptDefined(false) {} @@ -560,6 +563,7 @@ void Symbol::replace(const Symbol &newSym) { canInline = old.canInline; referenced = old.referenced; traced = old.traced; + gwarn = old.gwarn; isPreemptible = old.isPreemptible; scriptDefined = old.scriptDefined; partition = old.partition; @@ -579,6 +583,8 @@ void maybeWarnUnorderableSymbol(const Symbol *sym); bool computeIsPreemptible(const Symbol &sym); void reportBackrefs(); +extern llvm::DenseMap gnuWarnings; + // A mapping from a symbol to an InputFile referencing it backward. Used by // --warn-backrefs. extern llvm::DenseMap