diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 2022-10-07 15:04:53 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 2022-10-07 15:04:53 +0000 |
commit | d84b2f71567c468b7f2769f79a0af1327195910f (patch) | |
tree | b6fad20e138e250832697afebcdb3a36fc9231f3 /gnu/llvm | |
parent | c7304b2b8d4c6bb3e2222fa3795e3ffd2c0eb2f3 (diff) |
In the linkers, collect objects in section "openbsd.mutable" and place
them into a page-aligned region in the bss, with the right markers for
kernel/ld.so to identify the region and skip making it immutable.
While here, fix readelf/objdump versions to show all of this.
ok miod kettenis
Diffstat (limited to 'gnu/llvm')
-rw-r--r-- | gnu/llvm/lld/ELF/ScriptParser.cpp | 373 | ||||
-rw-r--r-- | gnu/llvm/lld/ELF/Writer.cpp | 8 | ||||
-rw-r--r-- | gnu/llvm/llvm/include/llvm/BinaryFormat/ELF.h | 409 |
3 files changed, 533 insertions, 257 deletions
diff --git a/gnu/llvm/lld/ELF/ScriptParser.cpp b/gnu/llvm/lld/ELF/ScriptParser.cpp index fd8de3b54bd..a9b96e3c361 100644 --- a/gnu/llvm/lld/ELF/ScriptParser.cpp +++ b/gnu/llvm/lld/ELF/ScriptParser.cpp @@ -29,7 +29,10 @@ #include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/MathExtras.h" #include "llvm/Support/Path.h" +#include "llvm/Support/ScopedPrinter.h" +#include "llvm/Support/TimeProfiler.h" #include <cassert> #include <limits> #include <vector> @@ -37,9 +40,9 @@ using namespace llvm; using namespace llvm::ELF; using namespace llvm::support::endian; +using namespace lld; +using namespace lld::elf; -namespace lld { -namespace elf { namespace { class ScriptParser final : ScriptLexer { public: @@ -74,6 +77,7 @@ private: void readOutput(); void readOutputArch(); void readOutputFormat(); + void readOverwriteSections(); void readPhdrs(); void readRegionAlias(); void readSearchDir(); @@ -91,11 +95,15 @@ private: OutputSection *readOutputSectionDescription(StringRef outSec); std::vector<BaseCommand *> readOverlay(); std::vector<StringRef> readOutputSectionPhdrs(); + std::pair<uint64_t, uint64_t> readInputSectionFlags(); InputSectionDescription *readInputSectionDescription(StringRef tok); StringMatcher readFilePatterns(); std::vector<SectionPattern> readInputSectionsList(); - InputSectionDescription *readInputSectionRules(StringRef filePattern); + InputSectionDescription *readInputSectionRules(StringRef filePattern, + uint64_t withFlags, + uint64_t withoutFlags); unsigned readPhdrType(); + SortSectionPolicy peekSortKind(); SortSectionPolicy readSortKind(); SymbolAssignment *readProvideHidden(bool provide, bool hidden); SymbolAssignment *readAssignment(StringRef tok); @@ -104,7 +112,7 @@ private: Expr readConstant(); Expr getPageSize(); - uint64_t readMemoryAssignment(StringRef, StringRef, StringRef); + Expr readMemoryAssignment(StringRef, StringRef, StringRef); std::pair<uint32_t, uint32_t> readMemoryAttributes(); Expr combine(StringRef op, Expr l, Expr r); @@ -171,7 +179,6 @@ static ExprValue bitOr(ExprValue a, ExprValue b) { } void ScriptParser::readDynamicList() { - config->hasDynamicList = true; expect("{"); std::vector<SymbolVersion> locals; std::vector<SymbolVersion> globals; @@ -245,6 +252,8 @@ void ScriptParser::readLinkerScript() { readOutputArch(); } else if (tok == "OUTPUT_FORMAT") { readOutputFormat(); + } else if (tok == "OVERWRITE_SECTIONS") { + readOverwriteSections(); } else if (tok == "PHDRS") { readPhdrs(); } else if (tok == "REGION_ALIAS") { @@ -279,29 +288,48 @@ void ScriptParser::addFile(StringRef s) { if (isUnderSysroot && s.startswith("/")) { SmallString<128> pathData; StringRef path = (config->sysroot + s).toStringRef(pathData); - if (sys::fs::exists(path)) { + if (sys::fs::exists(path)) driver->addFile(saver.save(path), /*withLOption=*/false); - return; - } + else + setError("cannot find " + s + " inside " + config->sysroot); + return; } if (s.startswith("/")) { + // Case 1: s is an absolute path. Just open it. driver->addFile(s, /*withLOption=*/false); } else if (s.startswith("=")) { + // Case 2: relative to the sysroot. if (config->sysroot.empty()) driver->addFile(s.substr(1), /*withLOption=*/false); else driver->addFile(saver.save(config->sysroot + "/" + s.substr(1)), /*withLOption=*/false); } else if (s.startswith("-l")) { + // Case 3: search in the list of library paths. driver->addLibrary(s.substr(2)); - } else if (sys::fs::exists(s)) { - driver->addFile(s, /*withLOption=*/false); } else { - if (Optional<std::string> path = findFromSearchPaths(s)) - driver->addFile(saver.save(*path), /*withLOption=*/true); - else - setError("unable to find " + s); + // Case 4: s is a relative path. Search in the directory of the script file. + std::string filename = std::string(getCurrentMB().getBufferIdentifier()); + StringRef directory = sys::path::parent_path(filename); + if (!directory.empty()) { + SmallString<0> path(directory); + sys::path::append(path, s); + if (sys::fs::exists(path)) { + driver->addFile(path, /*withLOption=*/false); + return; + } + } + // Then search in the current working directory. + if (sys::fs::exists(s)) { + driver->addFile(s, /*withLOption=*/false); + } else { + // Finally, search in the list of library paths. + if (Optional<std::string> path = findFromSearchPaths(s)) + driver->addFile(saver.save(*path), /*withLOption=*/true); + else + setError("unable to find " + s); + } } } @@ -388,7 +416,9 @@ static std::pair<ELFKind, uint16_t> parseBfdName(StringRef s) { .Case("elf32-x86-64", {ELF32LEKind, EM_X86_64}) .Case("elf64-aarch64", {ELF64LEKind, EM_AARCH64}) .Case("elf64-littleaarch64", {ELF64LEKind, EM_AARCH64}) + .Case("elf64-bigaarch64", {ELF64BEKind, EM_AARCH64}) .Case("elf32-powerpc", {ELF32BEKind, EM_PPC}) + .Case("elf32-powerpcle", {ELF32LEKind, EM_PPC}) .Case("elf64-powerpc", {ELF64BEKind, EM_PPC64}) .Case("elf64-powerpcle", {ELF64LEKind, EM_PPC64}) .Case("elf64-x86-64", {ELF64LEKind, EM_X86_64}) @@ -400,32 +430,41 @@ static std::pair<ELFKind, uint16_t> parseBfdName(StringRef s) { .Case("elf64-tradlittlemips", {ELF64LEKind, EM_MIPS}) .Case("elf32-littleriscv", {ELF32LEKind, EM_RISCV}) .Case("elf64-littleriscv", {ELF64LEKind, EM_RISCV}) + .Case("elf64-sparc", {ELF64BEKind, EM_SPARCV9}) + .Case("elf32-msp430", {ELF32LEKind, EM_MSP430}) .Default({ELFNoneKind, EM_NONE}); } -// Parse OUTPUT_FORMAT(bfdname) or OUTPUT_FORMAT(bfdname, big, little). -// Currently we ignore big and little parameters. +// Parse OUTPUT_FORMAT(bfdname) or OUTPUT_FORMAT(default, big, little). Choose +// big if -EB is specified, little if -EL is specified, or default if neither is +// specified. void ScriptParser::readOutputFormat() { expect("("); - StringRef name = unquote(next()); - StringRef s = name; + StringRef s; + config->bfdname = unquote(next()); + if (!consume(")")) { + expect(","); + s = unquote(next()); + if (config->optEB) + config->bfdname = s; + expect(","); + s = unquote(next()); + if (config->optEL) + config->bfdname = s; + consume(")"); + } + s = config->bfdname; if (s.consume_back("-freebsd")) config->osabi = ELFOSABI_FREEBSD; std::tie(config->ekind, config->emachine) = parseBfdName(s); if (config->emachine == EM_NONE) - setError("unknown output format name: " + name); + setError("unknown output format name: " + config->bfdname); if (s == "elf32-ntradlittlemips" || s == "elf32-ntradbigmips") config->mipsN32Abi = true; - - if (consume(")")) - return; - expect(","); - skip(); - expect(","); - skip(); - expect(")"); + if (config->emachine == EM_MSP430) + config->osabi = ELFOSABI_STANDALONE; } void ScriptParser::readPhdrs() { @@ -518,14 +557,13 @@ std::vector<BaseCommand *> ScriptParser::readOverlay() { return v; } -void ScriptParser::readSections() { - script->hasSectionsCommand = true; - - // -no-rosegment is used to avoid placing read only non-executable sections in - // their own segment. We do the same if SECTIONS command is present in linker - // script. See comment for computeFlags(). - config->singleRoRx = true; +void ScriptParser::readOverwriteSections() { + expect("{"); + while (!errorCount() && !consume("}")) + script->overwriteSections.push_back(readOutputSectionDescription(next())); +} +void ScriptParser::readSections() { expect("{"); std::vector<BaseCommand *> v; while (!errorCount() && !consume("}")) { @@ -544,22 +582,26 @@ void ScriptParser::readSections() { else v.push_back(readOutputSectionDescription(tok)); } + script->sectionCommands.insert(script->sectionCommands.end(), v.begin(), + v.end()); - if (!atEOF() && consume("INSERT")) { - std::vector<BaseCommand *> *dest = nullptr; - if (consume("AFTER")) - dest = &script->insertAfterCommands[next()]; - else if (consume("BEFORE")) - dest = &script->insertBeforeCommands[next()]; - else - setError("expected AFTER/BEFORE, but got '" + next() + "'"); - if (dest) - dest->insert(dest->end(), v.begin(), v.end()); + if (atEOF() || !consume("INSERT")) { + script->hasSectionsCommand = true; return; } - script->sectionCommands.insert(script->sectionCommands.end(), v.begin(), - v.end()); + bool isAfter = false; + if (consume("AFTER")) + isAfter = true; + else if (!consume("BEFORE")) + setError("expected AFTER/BEFORE, but got '" + next() + "'"); + StringRef where = next(); + std::vector<StringRef> names; + for (BaseCommand *cmd : v) + if (auto *os = dyn_cast<OutputSection>(cmd)) + names.push_back(os->name); + if (!names.empty()) + script->insertCommands.push_back({std::move(names), isAfter, where}); } void ScriptParser::readTarget() { @@ -593,22 +635,27 @@ static int precedence(StringRef op) { } StringMatcher ScriptParser::readFilePatterns() { - std::vector<StringRef> v; + StringMatcher Matcher; + while (!errorCount() && !consume(")")) - v.push_back(next()); - return StringMatcher(v); + Matcher.addPattern(SingleStringMatcher(next())); + return Matcher; +} + +SortSectionPolicy ScriptParser::peekSortKind() { + return StringSwitch<SortSectionPolicy>(peek()) + .Cases("SORT", "SORT_BY_NAME", SortSectionPolicy::Name) + .Case("SORT_BY_ALIGNMENT", SortSectionPolicy::Alignment) + .Case("SORT_BY_INIT_PRIORITY", SortSectionPolicy::Priority) + .Case("SORT_NONE", SortSectionPolicy::None) + .Default(SortSectionPolicy::Default); } SortSectionPolicy ScriptParser::readSortKind() { - if (consume("SORT") || consume("SORT_BY_NAME")) - return SortSectionPolicy::Name; - if (consume("SORT_BY_ALIGNMENT")) - return SortSectionPolicy::Alignment; - if (consume("SORT_BY_INIT_PRIORITY")) - return SortSectionPolicy::Priority; - if (consume("SORT_NONE")) - return SortSectionPolicy::None; - return SortSectionPolicy::Default; + SortSectionPolicy ret = peekSortKind(); + if (ret != SortSectionPolicy::Default) + skip(); + return ret; } // Reads SECTIONS command contents in the following form: @@ -633,12 +680,16 @@ std::vector<SectionPattern> ScriptParser::readInputSectionsList() { excludeFilePat = readFilePatterns(); } - std::vector<StringRef> v; - while (!errorCount() && peek() != ")" && peek() != "EXCLUDE_FILE") - v.push_back(unquote(next())); + StringMatcher SectionMatcher; + // Break if the next token is ), EXCLUDE_FILE, or SORT*. + while (!errorCount() && peek() != ")" && peek() != "EXCLUDE_FILE" && + peekSortKind() == SortSectionPolicy::Default) + SectionMatcher.addPattern(unquote(next())); - if (!v.empty()) - ret.push_back({std::move(excludeFilePat), StringMatcher(v)}); + if (!SectionMatcher.empty()) + ret.push_back({std::move(excludeFilePat), std::move(SectionMatcher)}); + else if (excludeFilePat.empty()) + break; else setError("section pattern is expected"); } @@ -657,8 +708,10 @@ std::vector<SectionPattern> ScriptParser::readInputSectionsList() { // // <section-list> is parsed by readInputSectionsList(). InputSectionDescription * -ScriptParser::readInputSectionRules(StringRef filePattern) { - auto *cmd = make<InputSectionDescription>(filePattern); +ScriptParser::readInputSectionRules(StringRef filePattern, uint64_t withFlags, + uint64_t withoutFlags) { + auto *cmd = + make<InputSectionDescription>(filePattern, withFlags, withoutFlags); expect("("); while (!errorCount() && !consume(")")) { @@ -694,15 +747,23 @@ InputSectionDescription * ScriptParser::readInputSectionDescription(StringRef tok) { // Input section wildcard can be surrounded by KEEP. // https://sourceware.org/binutils/docs/ld/Input-Section-Keep.html#Input-Section-Keep + uint64_t withFlags = 0; + uint64_t withoutFlags = 0; if (tok == "KEEP") { expect("("); - StringRef filePattern = next(); - InputSectionDescription *cmd = readInputSectionRules(filePattern); + if (consume("INPUT_SECTION_FLAGS")) + std::tie(withFlags, withoutFlags) = readInputSectionFlags(); + InputSectionDescription *cmd = + readInputSectionRules(next(), withFlags, withoutFlags); expect(")"); script->keptSections.push_back(cmd); return cmd; } - return readInputSectionRules(tok); + if (tok == "INPUT_SECTION_FLAGS") { + std::tie(withFlags, withoutFlags) = readInputSectionFlags(); + tok = next(); + } + return readInputSectionRules(tok, withFlags, withoutFlags); } void ScriptParser::readSort() { @@ -737,6 +798,7 @@ bool ScriptParser::readSectionDirective(OutputSection *cmd, StringRef tok1, Stri expect("("); if (consume("NOLOAD")) { cmd->noload = true; + cmd->type = SHT_NOBITS; } else { skip(); // This is "COPY", "INFO" or "OVERLAY". cmd->nonAlloc = true; @@ -781,9 +843,14 @@ OutputSection *ScriptParser::readOverlaySectionDescription() { script->createOutputSection(next(), getCurrentLocation()); cmd->inOverlay = true; expect("{"); - while (!errorCount() && !consume("}")) - cmd->sectionCommands.push_back(readInputSectionRules(next())); - cmd->phdrs = readOutputSectionPhdrs(); + while (!errorCount() && !consume("}")) { + uint64_t withFlags = 0; + uint64_t withoutFlags = 0; + if (consume("INPUT_SECTION_FLAGS")) + std::tie(withFlags, withoutFlags) = readInputSectionFlags(); + cmd->sectionCommands.push_back( + readInputSectionRules(next(), withFlags, withoutFlags)); + } return cmd; } @@ -828,9 +895,9 @@ OutputSection *ScriptParser::readOutputSectionDescription(StringRef outSec) { // We handle the FILL command as an alias for =fillexp section attribute, // which is different from what GNU linkers do. // https://sourceware.org/binutils/docs/ld/Output-Section-Data.html - expect("("); + if (peek() != "(") + setError("( expected, but got " + peek()); cmd->filler = readFill(); - expect(")"); } else if (tok == "SORT") { readSort(); } else if (tok == "INCLUDE") { @@ -841,18 +908,21 @@ OutputSection *ScriptParser::readOutputSectionDescription(StringRef outSec) { // We have a file name and no input sections description. It is not a // commonly used syntax, but still acceptable. In that case, all sections // from the file will be included. + // FIXME: GNU ld permits INPUT_SECTION_FLAGS to be used here. We do not + // handle this case here as it will already have been matched by the + // case above. auto *isd = make<InputSectionDescription>(tok); - isd->sectionPatterns.push_back({{}, StringMatcher({"*"})}); + isd->sectionPatterns.push_back({{}, StringMatcher("*")}); cmd->sectionCommands.push_back(isd); } } if (consume(">")) - cmd->memoryRegionName = next(); + cmd->memoryRegionName = std::string(next()); if (consume("AT")) { expect(">"); - cmd->lmaRegionName = next(); + cmd->lmaRegionName = std::string(next()); } if (cmd->lmaExpr && !cmd->lmaRegionName.empty()) @@ -882,8 +952,11 @@ OutputSection *ScriptParser::readOutputSectionDescription(StringRef outSec) { // When reading a hexstring, ld.bfd handles it as a blob of arbitrary // size, while ld.gold always handles it as a 32-bit big-endian number. // We are compatible with ld.gold because it's easier to implement. +// Also, we require that expressions with operators must be wrapped into +// round brackets. We did it to resolve the ambiguity when parsing scripts like: +// SECTIONS { .foo : { ... } =120+3 /DISCARD/ : { ... } } std::array<uint8_t, 4> ScriptParser::readFill() { - uint64_t value = readExpr()().val; + uint64_t value = readPrimary()().val; if (value > UINT32_MAX) setError("filler expression result does not fit 32-bit: 0x" + Twine::utohexstr(value)); @@ -928,6 +1001,7 @@ SymbolAssignment *ScriptParser::readAssignment(StringRef tok) { } SymbolAssignment *ScriptParser::readSymbolAssignment(StringRef name) { + name = unquote(name); StringRef op = next(); assert(op == "=" || op == "+="); Expr e = readExpr(); @@ -1057,24 +1131,24 @@ Expr ScriptParser::readConstant() { static Optional<uint64_t> parseInt(StringRef tok) { // Hexadecimal uint64_t val; - if (tok.startswith_lower("0x")) { + if (tok.startswith_insensitive("0x")) { if (!to_integer(tok.substr(2), val, 16)) return None; return val; } - if (tok.endswith_lower("H")) { + if (tok.endswith_insensitive("H")) { if (!to_integer(tok.drop_back(), val, 16)) return None; return val; } // Decimal - if (tok.endswith_lower("K")) { + if (tok.endswith_insensitive("K")) { if (!to_integer(tok.drop_back(), val, 10)) return None; return val * 1024; } - if (tok.endswith_lower("M")) { + if (tok.endswith_insensitive("M")) { if (!to_integer(tok.drop_back(), val, 10)) return None; return val * 1024 * 1024; @@ -1102,6 +1176,63 @@ ByteCommand *ScriptParser::readByteCommand(StringRef tok) { return make<ByteCommand>(e, size, commandString); } +static llvm::Optional<uint64_t> parseFlag(StringRef tok) { + if (llvm::Optional<uint64_t> asInt = parseInt(tok)) + return asInt; +#define CASE_ENT(enum) #enum, ELF::enum + return StringSwitch<llvm::Optional<uint64_t>>(tok) + .Case(CASE_ENT(SHF_WRITE)) + .Case(CASE_ENT(SHF_ALLOC)) + .Case(CASE_ENT(SHF_EXECINSTR)) + .Case(CASE_ENT(SHF_MERGE)) + .Case(CASE_ENT(SHF_STRINGS)) + .Case(CASE_ENT(SHF_INFO_LINK)) + .Case(CASE_ENT(SHF_LINK_ORDER)) + .Case(CASE_ENT(SHF_OS_NONCONFORMING)) + .Case(CASE_ENT(SHF_GROUP)) + .Case(CASE_ENT(SHF_TLS)) + .Case(CASE_ENT(SHF_COMPRESSED)) + .Case(CASE_ENT(SHF_EXCLUDE)) + .Case(CASE_ENT(SHF_ARM_PURECODE)) + .Default(None); +#undef CASE_ENT +} + +// Reads the '(' <flags> ')' list of section flags in +// INPUT_SECTION_FLAGS '(' <flags> ')' in the +// following form: +// <flags> ::= <flag> +// | <flags> & flag +// <flag> ::= Recognized Flag Name, or Integer value of flag. +// If the first character of <flag> is a ! then this means without flag, +// otherwise with flag. +// Example: SHF_EXECINSTR & !SHF_WRITE means with flag SHF_EXECINSTR and +// without flag SHF_WRITE. +std::pair<uint64_t, uint64_t> ScriptParser::readInputSectionFlags() { + uint64_t withFlags = 0; + uint64_t withoutFlags = 0; + expect("("); + while (!errorCount()) { + StringRef tok = unquote(next()); + bool without = tok.consume_front("!"); + if (llvm::Optional<uint64_t> flag = parseFlag(tok)) { + if (without) + withoutFlags |= *flag; + else + withFlags |= *flag; + } else { + setError("unrecognised flag: " + tok); + } + if (consume(")")) + break; + if (!consume("&")) { + next(); + setError("expected & or )"); + } + } + return std::make_pair(withFlags, withoutFlags); +} + StringRef ScriptParser::readParenLiteral() { expect("("); bool orig = inExpr; @@ -1117,6 +1248,13 @@ static void checkIfExists(OutputSection *cmd, StringRef location) { error(location + ": undefined section " + cmd->name); } +static bool isValidSymbolName(StringRef s) { + auto valid = [](char c) { + return isAlnum(c) || c == '$' || c == '.' || c == '_'; + }; + return !s.empty() && !isDigit(s[0]) && llvm::all_of(s, valid); +} + Expr ScriptParser::readPrimary() { if (peek() == "(") return readParenExpr(); @@ -1213,8 +1351,11 @@ Expr ScriptParser::readPrimary() { return [=] { return alignTo(script->getDot(), e().getValue()); }; } if (tok == "DEFINED") { - StringRef name = readParenLiteral(); - return [=] { return symtab->find(name) ? 1 : 0; }; + StringRef name = unquote(readParenLiteral()); + return [=] { + Symbol *b = symtab->find(name); + return (b && b->isDefined()) ? 1 : 0; + }; } if (tok == "LENGTH") { StringRef name = readParenLiteral(); @@ -1222,7 +1363,7 @@ Expr ScriptParser::readPrimary() { setError("memory region not defined: " + name); return [] { return 0; }; } - return [=] { return script->memoryRegions[name]->length; }; + return script->memoryRegions[name]->length; } if (tok == "LOADADDR") { StringRef name = readParenLiteral(); @@ -1233,6 +1374,15 @@ Expr ScriptParser::readPrimary() { return cmd->getLMA(); }; } + if (tok == "LOG2CEIL") { + expect("("); + Expr a = readExpr(); + expect(")"); + return [=] { + // LOG2CEIL(0) is defined to be 0. + return llvm::Log2_64_Ceil(std::max(a().getValue(), UINT64_C(1))); + }; + } if (tok == "MAX" || tok == "MIN") { expect("("); Expr a = readExpr(); @@ -1249,7 +1399,7 @@ Expr ScriptParser::readPrimary() { setError("memory region not defined: " + name); return [] { return 0; }; } - return [=] { return script->memoryRegions[name]->origin; }; + return script->memoryRegions[name]->origin; } if (tok == "SEGMENT_START") { expect("("); @@ -1268,7 +1418,7 @@ Expr ScriptParser::readPrimary() { return [=] { return cmd->size; }; } if (tok == "SIZEOF_HEADERS") - return [=] { return getHeaderSize(); }; + return [=] { return elf::getHeaderSize(); }; // Tok is the dot. if (tok == ".") @@ -1279,7 +1429,8 @@ Expr ScriptParser::readPrimary() { return [=] { return *val; }; // Tok is a symbol name. - if (!isValidCIdentifier(tok)) + tok = unquote(tok); + if (!isValidSymbolName(tok)) setError("malformed number: " + tok); script->referencedSymbols.push_back(tok); return [=] { return script->getSymbolValue(tok, location); }; @@ -1327,6 +1478,7 @@ unsigned ScriptParser::readPhdrType() { .Case("PT_GNU_EH_FRAME", PT_GNU_EH_FRAME) .Case("PT_GNU_STACK", PT_GNU_STACK) .Case("PT_GNU_RELRO", PT_GNU_RELRO) + .Case("PT_OPENBSD_MUTABLE", PT_OPENBSD_MUTABLE) .Case("PT_OPENBSD_RANDOMIZE", PT_OPENBSD_RANDOMIZE) .Case("PT_OPENBSD_WXNEEDED", PT_OPENBSD_WXNEEDED) .Case("PT_OPENBSD_BOOTDATA", PT_OPENBSD_BOOTDATA) @@ -1345,9 +1497,9 @@ void ScriptParser::readAnonymousDeclaration() { std::vector<SymbolVersion> globals; std::tie(locals, globals) = readSymbols(); for (const SymbolVersion &pat : locals) - config->versionDefinitions[VER_NDX_LOCAL].patterns.push_back(pat); + config->versionDefinitions[VER_NDX_LOCAL].localPatterns.push_back(pat); for (const SymbolVersion &pat : globals) - config->versionDefinitions[VER_NDX_GLOBAL].patterns.push_back(pat); + config->versionDefinitions[VER_NDX_GLOBAL].nonLocalPatterns.push_back(pat); expect(";"); } @@ -1359,13 +1511,12 @@ void ScriptParser::readVersionDeclaration(StringRef verStr) { std::vector<SymbolVersion> locals; std::vector<SymbolVersion> globals; std::tie(locals, globals) = readSymbols(); - for (const SymbolVersion &pat : locals) - config->versionDefinitions[VER_NDX_LOCAL].patterns.push_back(pat); // Create a new version definition and add that to the global symbols. VersionDefinition ver; ver.name = verStr; - ver.patterns = globals; + ver.nonLocalPatterns = std::move(globals); + ver.localPatterns = std::move(locals); ver.id = config->versionDefinitions.size(); config->versionDefinitions.push_back(ver); @@ -1374,12 +1525,11 @@ void ScriptParser::readVersionDeclaration(StringRef verStr) { // as a parent. This version hierarchy is, probably against your // instinct, purely for hint; the runtime doesn't care about it // at all. In LLD, we simply ignore it. - if (peek() != ";") - skip(); - expect(";"); + if (next() != ";") + expect(";"); } -static bool hasWildcard(StringRef s) { +bool elf::hasWildcard(StringRef s) { return s.find_first_of("?*[") != StringRef::npos; } @@ -1440,14 +1590,14 @@ std::vector<SymbolVersion> ScriptParser::readVersionExtern() { return ret; } -uint64_t ScriptParser::readMemoryAssignment(StringRef s1, StringRef s2, - StringRef s3) { +Expr ScriptParser::readMemoryAssignment(StringRef s1, StringRef s2, + StringRef s3) { if (!consume(s1) && !consume(s2) && !consume(s3)) { setError("expected one of: " + s1 + ", " + s2 + ", or " + s3); - return 0; + return [] { return 0; }; } expect("="); - return readExpr()().getValue(); + return readExpr(); } // Parse the MEMORY command as specified in: @@ -1471,9 +1621,9 @@ void ScriptParser::readMemory() { } expect(":"); - uint64_t origin = readMemoryAssignment("ORIGIN", "org", "o"); + Expr origin = readMemoryAssignment("ORIGIN", "org", "o"); expect(","); - uint64_t length = readMemoryAssignment("LENGTH", "len", "l"); + Expr length = readMemoryAssignment("LENGTH", "len", "l"); // Add the memory region to the region map. MemoryRegion *mr = make<MemoryRegion>(tok, origin, length, flags, negFlags); @@ -1511,19 +1661,24 @@ std::pair<uint32_t, uint32_t> ScriptParser::readMemoryAttributes() { return {flags, negFlags}; } -void readLinkerScript(MemoryBufferRef mb) { +void elf::readLinkerScript(MemoryBufferRef mb) { + llvm::TimeTraceScope timeScope("Read linker script", + mb.getBufferIdentifier()); ScriptParser(mb).readLinkerScript(); } -void readVersionScript(MemoryBufferRef mb) { +void elf::readVersionScript(MemoryBufferRef mb) { + llvm::TimeTraceScope timeScope("Read version script", + mb.getBufferIdentifier()); ScriptParser(mb).readVersionScript(); } -void readDynamicList(MemoryBufferRef mb) { ScriptParser(mb).readDynamicList(); } +void elf::readDynamicList(MemoryBufferRef mb) { + llvm::TimeTraceScope timeScope("Read dynamic list", mb.getBufferIdentifier()); + ScriptParser(mb).readDynamicList(); +} -void readDefsym(StringRef name, MemoryBufferRef mb) { +void elf::readDefsym(StringRef name, MemoryBufferRef mb) { + llvm::TimeTraceScope timeScope("Read defsym input", name); ScriptParser(mb).readDefsym(name); } - -} // namespace elf -} // namespace lld diff --git a/gnu/llvm/lld/ELF/Writer.cpp b/gnu/llvm/lld/ELF/Writer.cpp index 9e6692b3709..8b5e4e294e8 100644 --- a/gnu/llvm/lld/ELF/Writer.cpp +++ b/gnu/llvm/lld/ELF/Writer.cpp @@ -146,7 +146,7 @@ StringRef elf::getOutputSectionName(const InputSectionBase *s) { {".text.", ".rodata.", ".data.rel.ro.", ".data.", ".bss.rel.ro.", ".bss.", ".init_array.", ".fini_array.", ".ctors.", ".dtors.", ".tbss.", ".gcc_except_table.", ".tdata.", ".ARM.exidx.", ".ARM.extab.", - ".openbsd.randomdata."}) + ".openbsd.randomdata.", ".openbsd.mutable." }) if (isSectionPrefix(v, s->name)) return v.drop_back(); @@ -2470,6 +2470,12 @@ std::vector<PhdrEntry *> Writer<ELFT>::createPhdrs(Partition &part) { addHdr(PT_GNU_EH_FRAME, part.ehFrameHdr->getParent()->getPhdrFlags()) ->add(part.ehFrameHdr->getParent()); + // PT_OPENBSD_MUTABLE is an OpenBSD-specific feature. That makes + // the dynamic linker fill the segment with zero data, like bss, but + // it can be treated differently. + if (OutputSection *cmd = findSection(".openbsd.mutable", partNo)) + addHdr(PT_OPENBSD_MUTABLE, cmd->getPhdrFlags())->add(cmd); + // PT_OPENBSD_RANDOMIZE is an OpenBSD-specific feature. That makes // the dynamic linker fill the segment with random data. if (OutputSection *cmd = findSection(".openbsd.randomdata", partNo)) diff --git a/gnu/llvm/llvm/include/llvm/BinaryFormat/ELF.h b/gnu/llvm/llvm/include/llvm/BinaryFormat/ELF.h index caab91da9c8..fa4139b88c2 100644 --- a/gnu/llvm/llvm/include/llvm/BinaryFormat/ELF.h +++ b/gnu/llvm/llvm/include/llvm/BinaryFormat/ELF.h @@ -19,8 +19,10 @@ #ifndef LLVM_BINARYFORMAT_ELF_H #define LLVM_BINARYFORMAT_ELF_H +#include "llvm/ADT/StringRef.h" #include <cstdint> #include <cstring> +#include <string> namespace llvm { namespace ELF { @@ -107,13 +109,17 @@ struct Elf64_Ehdr { unsigned char getDataEncoding() const { return e_ident[EI_DATA]; } }; -// File types +// File types. +// See current registered ELF types at: +// http://www.sco.com/developers/gabi/latest/ch4.eheader.html enum { ET_NONE = 0, // No file type ET_REL = 1, // Relocatable file ET_EXEC = 2, // Executable file ET_DYN = 3, // Shared object file ET_CORE = 4, // Core file + ET_LOOS = 0xfe00, // Beginning of operating system-specific codes + ET_HIOS = 0xfeff, // Operating system-specific ET_LOPROC = 0xff00, // Beginning of processor-specific codes ET_HIPROC = 0xffff // Processor-specific }; @@ -277,6 +283,7 @@ enum { EM_STM8 = 186, // STMicroeletronics STM8 8-bit microcontroller EM_TILE64 = 187, // Tilera TILE64 multicore architecture family EM_TILEPRO = 188, // Tilera TILEPro multicore architecture family + EM_MICROBLAZE = 189, // Xilinx MicroBlaze 32-bit RISC soft processor core EM_CUDA = 190, // NVIDIA CUDA architecture EM_TILEGX = 191, // Tilera TILE-Gx multicore architecture family EM_CLOUDSHIELD = 192, // CloudShield architecture family @@ -311,6 +318,8 @@ enum { EM_RISCV = 243, // RISC-V EM_LANAI = 244, // Lanai 32-bit processor EM_BPF = 247, // Linux kernel bpf virtual machine + EM_VE = 251, // NEC SX-Aurora VE + EM_CSKY = 252, // C-SKY 32-bit processor }; // Object file classes. @@ -358,6 +367,15 @@ enum { ELFOSABI_LAST_ARCH = 255 // Last Architecture-specific OS ABI }; +// AMDGPU OS ABI Version identification. +enum { + // ELFABIVERSION_AMDGPU_HSA_V1 does not exist because OS ABI identification + // was never defined for V1. + ELFABIVERSION_AMDGPU_HSA_V2 = 0, + ELFABIVERSION_AMDGPU_HSA_V3 = 1, + ELFABIVERSION_AMDGPU_HSA_V4 = 2 +}; + #define ELF_RELOC(name, value) name = value, // X86_64 relocations. @@ -393,12 +411,6 @@ static inline int64_t decodePPC64LocalEntryOffset(unsigned Other) { unsigned Val = (Other & STO_PPC64_LOCAL_MASK) >> STO_PPC64_LOCAL_BIT; return ((1 << Val) >> 2) << 2; } -static inline unsigned encodePPC64LocalEntryOffset(int64_t Offset) { - unsigned Val = - (Offset >= 4 * 4 ? (Offset >= 8 * 4 ? (Offset >= 16 * 4 ? 6 : 5) : 4) - : (Offset >= 2 * 4 ? 3 : (Offset >= 1 * 4 ? 2 : 0))); - return Val << STO_PPC64_LOCAL_BIT; -} // ELF Relocation types for PPC64 enum { @@ -410,6 +422,12 @@ enum { #include "ELFRelocs/AArch64.def" }; +// Special values for the st_other field in the symbol table entry for AArch64. +enum { + // Symbol may follow different calling convention than base PCS. + STO_AARCH64_VARIANT_PCS = 0x80 +}; + // ARM Specific e_flags enum : unsigned { EF_ARM_SOFT_FLOAT = 0x00000200U, // Legacy pre EABI_VER5 @@ -470,7 +488,12 @@ enum : unsigned { EF_AVR_ARCH_XMEGA4 = 104, EF_AVR_ARCH_XMEGA5 = 105, EF_AVR_ARCH_XMEGA6 = 106, - EF_AVR_ARCH_XMEGA7 = 107 + EF_AVR_ARCH_XMEGA7 = 107, + + EF_AVR_ARCH_MASK = 0x7f, // EF_AVR_ARCH_xxx selection mask + + EF_AVR_LINKRELAX_PREPARED = 0x80, // The file is prepared for linker + // relaxation to be applied }; // ELF Relocation types for AVR @@ -573,15 +596,18 @@ enum { // Hexagon-specific e_flags enum { // Object processor version flags, bits[11:0] - EF_HEXAGON_MACH_V2 = 0x00000001, // Hexagon V2 - EF_HEXAGON_MACH_V3 = 0x00000002, // Hexagon V3 - EF_HEXAGON_MACH_V4 = 0x00000003, // Hexagon V4 - EF_HEXAGON_MACH_V5 = 0x00000004, // Hexagon V5 - EF_HEXAGON_MACH_V55 = 0x00000005, // Hexagon V55 - EF_HEXAGON_MACH_V60 = 0x00000060, // Hexagon V60 - EF_HEXAGON_MACH_V62 = 0x00000062, // Hexagon V62 - EF_HEXAGON_MACH_V65 = 0x00000065, // Hexagon V65 - EF_HEXAGON_MACH_V66 = 0x00000066, // Hexagon V66 + EF_HEXAGON_MACH_V2 = 0x00000001, // Hexagon V2 + EF_HEXAGON_MACH_V3 = 0x00000002, // Hexagon V3 + EF_HEXAGON_MACH_V4 = 0x00000003, // Hexagon V4 + EF_HEXAGON_MACH_V5 = 0x00000004, // Hexagon V5 + EF_HEXAGON_MACH_V55 = 0x00000005, // Hexagon V55 + EF_HEXAGON_MACH_V60 = 0x00000060, // Hexagon V60 + EF_HEXAGON_MACH_V62 = 0x00000062, // Hexagon V62 + EF_HEXAGON_MACH_V65 = 0x00000065, // Hexagon V65 + EF_HEXAGON_MACH_V66 = 0x00000066, // Hexagon V66 + EF_HEXAGON_MACH_V67 = 0x00000067, // Hexagon V67 + EF_HEXAGON_MACH_V67T = 0x00008067, // Hexagon V67T + EF_HEXAGON_MACH_V68 = 0x00000068, // Hexagon V68 // Highest ISA version flags EF_HEXAGON_ISA_MACH = 0x00000000, // Same as specified in bits[11:0] @@ -595,6 +621,8 @@ enum { EF_HEXAGON_ISA_V62 = 0x00000062, // Hexagon V62 ISA EF_HEXAGON_ISA_V65 = 0x00000065, // Hexagon V65 ISA EF_HEXAGON_ISA_V66 = 0x00000066, // Hexagon V66 ISA + EF_HEXAGON_ISA_V67 = 0x00000067, // Hexagon V67 ISA + EF_HEXAGON_ISA_V68 = 0x00000068, // Hexagon V68 ISA }; // Hexagon-specific section indexes for common small data @@ -682,47 +710,96 @@ enum : unsigned { EF_AMDGPU_MACH_R600_LAST = EF_AMDGPU_MACH_R600_TURKS, // AMDGCN-based processors. - - // AMDGCN GFX6. - EF_AMDGPU_MACH_AMDGCN_GFX600 = 0x020, - EF_AMDGPU_MACH_AMDGCN_GFX601 = 0x021, - // AMDGCN GFX7. - EF_AMDGPU_MACH_AMDGCN_GFX700 = 0x022, - EF_AMDGPU_MACH_AMDGCN_GFX701 = 0x023, - EF_AMDGPU_MACH_AMDGCN_GFX702 = 0x024, - EF_AMDGPU_MACH_AMDGCN_GFX703 = 0x025, - EF_AMDGPU_MACH_AMDGCN_GFX704 = 0x026, - // AMDGCN GFX8. - EF_AMDGPU_MACH_AMDGCN_GFX801 = 0x028, - EF_AMDGPU_MACH_AMDGCN_GFX802 = 0x029, - EF_AMDGPU_MACH_AMDGCN_GFX803 = 0x02a, - EF_AMDGPU_MACH_AMDGCN_GFX810 = 0x02b, - // AMDGCN GFX9. - EF_AMDGPU_MACH_AMDGCN_GFX900 = 0x02c, - EF_AMDGPU_MACH_AMDGCN_GFX902 = 0x02d, - EF_AMDGPU_MACH_AMDGCN_GFX904 = 0x02e, - EF_AMDGPU_MACH_AMDGCN_GFX906 = 0x02f, - EF_AMDGPU_MACH_AMDGCN_GFX908 = 0x030, - EF_AMDGPU_MACH_AMDGCN_GFX909 = 0x031, - // AMDGCN GFX10. - EF_AMDGPU_MACH_AMDGCN_GFX1010 = 0x033, - EF_AMDGPU_MACH_AMDGCN_GFX1011 = 0x034, - EF_AMDGPU_MACH_AMDGCN_GFX1012 = 0x035, - - // Reserved for AMDGCN-based processors. - EF_AMDGPU_MACH_AMDGCN_RESERVED0 = 0x027, - EF_AMDGPU_MACH_AMDGCN_RESERVED1 = 0x032, + EF_AMDGPU_MACH_AMDGCN_GFX600 = 0x020, + EF_AMDGPU_MACH_AMDGCN_GFX601 = 0x021, + EF_AMDGPU_MACH_AMDGCN_GFX700 = 0x022, + EF_AMDGPU_MACH_AMDGCN_GFX701 = 0x023, + EF_AMDGPU_MACH_AMDGCN_GFX702 = 0x024, + EF_AMDGPU_MACH_AMDGCN_GFX703 = 0x025, + EF_AMDGPU_MACH_AMDGCN_GFX704 = 0x026, + EF_AMDGPU_MACH_AMDGCN_RESERVED_0X27 = 0x027, + EF_AMDGPU_MACH_AMDGCN_GFX801 = 0x028, + EF_AMDGPU_MACH_AMDGCN_GFX802 = 0x029, + EF_AMDGPU_MACH_AMDGCN_GFX803 = 0x02a, + EF_AMDGPU_MACH_AMDGCN_GFX810 = 0x02b, + EF_AMDGPU_MACH_AMDGCN_GFX900 = 0x02c, + EF_AMDGPU_MACH_AMDGCN_GFX902 = 0x02d, + EF_AMDGPU_MACH_AMDGCN_GFX904 = 0x02e, + EF_AMDGPU_MACH_AMDGCN_GFX906 = 0x02f, + EF_AMDGPU_MACH_AMDGCN_GFX908 = 0x030, + EF_AMDGPU_MACH_AMDGCN_GFX909 = 0x031, + EF_AMDGPU_MACH_AMDGCN_GFX90C = 0x032, + EF_AMDGPU_MACH_AMDGCN_GFX1010 = 0x033, + EF_AMDGPU_MACH_AMDGCN_GFX1011 = 0x034, + EF_AMDGPU_MACH_AMDGCN_GFX1012 = 0x035, + EF_AMDGPU_MACH_AMDGCN_GFX1030 = 0x036, + EF_AMDGPU_MACH_AMDGCN_GFX1031 = 0x037, + EF_AMDGPU_MACH_AMDGCN_GFX1032 = 0x038, + EF_AMDGPU_MACH_AMDGCN_GFX1033 = 0x039, + EF_AMDGPU_MACH_AMDGCN_GFX602 = 0x03a, + EF_AMDGPU_MACH_AMDGCN_GFX705 = 0x03b, + EF_AMDGPU_MACH_AMDGCN_GFX805 = 0x03c, + EF_AMDGPU_MACH_AMDGCN_GFX1035 = 0x03d, + EF_AMDGPU_MACH_AMDGCN_GFX1034 = 0x03e, + EF_AMDGPU_MACH_AMDGCN_GFX90A = 0x03f, + EF_AMDGPU_MACH_AMDGCN_RESERVED_0X40 = 0x040, + EF_AMDGPU_MACH_AMDGCN_RESERVED_0X41 = 0x041, + EF_AMDGPU_MACH_AMDGCN_GFX1013 = 0x042, + EF_AMDGPU_MACH_AMDGCN_RESERVED_0X43 = 0x043, + EF_AMDGPU_MACH_AMDGCN_RESERVED_0X44 = 0x044, + EF_AMDGPU_MACH_AMDGCN_RESERVED_0X45 = 0x045, // First/last AMDGCN-based processors. EF_AMDGPU_MACH_AMDGCN_FIRST = EF_AMDGPU_MACH_AMDGCN_GFX600, - EF_AMDGPU_MACH_AMDGCN_LAST = EF_AMDGPU_MACH_AMDGCN_GFX1012, + EF_AMDGPU_MACH_AMDGCN_LAST = EF_AMDGPU_MACH_AMDGCN_RESERVED_0X45, + + // Indicates if the "xnack" target feature is enabled for all code contained + // in the object. + // + // Only valid for ELFOSABI_AMDGPU_HSA and ELFABIVERSION_AMDGPU_HSA_V2. + EF_AMDGPU_FEATURE_XNACK_V2 = 0x01, + // Indicates if the trap handler is enabled for all code contained + // in the object. + // + // Only valid for ELFOSABI_AMDGPU_HSA and ELFABIVERSION_AMDGPU_HSA_V2. + EF_AMDGPU_FEATURE_TRAP_HANDLER_V2 = 0x02, // Indicates if the "xnack" target feature is enabled for all code contained // in the object. - EF_AMDGPU_XNACK = 0x100, - // Indicates if the "sram-ecc" target feature is enabled for all code + // + // Only valid for ELFOSABI_AMDGPU_HSA and ELFABIVERSION_AMDGPU_HSA_V3. + EF_AMDGPU_FEATURE_XNACK_V3 = 0x100, + // Indicates if the "sramecc" target feature is enabled for all code // contained in the object. - EF_AMDGPU_SRAM_ECC = 0x200, + // + // Only valid for ELFOSABI_AMDGPU_HSA and ELFABIVERSION_AMDGPU_HSA_V3. + EF_AMDGPU_FEATURE_SRAMECC_V3 = 0x200, + + // XNACK selection mask for EF_AMDGPU_FEATURE_XNACK_* values. + // + // Only valid for ELFOSABI_AMDGPU_HSA and ELFABIVERSION_AMDGPU_HSA_V4. + EF_AMDGPU_FEATURE_XNACK_V4 = 0x300, + // XNACK is not supported. + EF_AMDGPU_FEATURE_XNACK_UNSUPPORTED_V4 = 0x000, + // XNACK is any/default/unspecified. + EF_AMDGPU_FEATURE_XNACK_ANY_V4 = 0x100, + // XNACK is off. + EF_AMDGPU_FEATURE_XNACK_OFF_V4 = 0x200, + // XNACK is on. + EF_AMDGPU_FEATURE_XNACK_ON_V4 = 0x300, + + // SRAMECC selection mask for EF_AMDGPU_FEATURE_SRAMECC_* values. + // + // Only valid for ELFOSABI_AMDGPU_HSA and ELFABIVERSION_AMDGPU_HSA_V4. + EF_AMDGPU_FEATURE_SRAMECC_V4 = 0xc00, + // SRAMECC is not supported. + EF_AMDGPU_FEATURE_SRAMECC_UNSUPPORTED_V4 = 0x000, + // SRAMECC is any/default/unspecified. + EF_AMDGPU_FEATURE_SRAMECC_ANY_V4 = 0x400, + // SRAMECC is off. + EF_AMDGPU_FEATURE_SRAMECC_OFF_V4 = 0x800, + // SRAMECC is on. + EF_AMDGPU_FEATURE_SRAMECC_ON_V4 = 0xc00, }; // ELF Relocation types for AMDGPU @@ -735,6 +812,11 @@ enum { #include "ELFRelocs/BPF.def" }; +// ELF Relocation types for M68k +enum { +#include "ELFRelocs/M68k.def" +}; + // MSP430 specific e_flags enum : unsigned { EF_MSP430_MACH_MSP430x11 = 11, @@ -767,6 +849,17 @@ enum { #include "ELFRelocs/MSP430.def" }; +// ELF Relocation type for VE. +enum { +#include "ELFRelocs/VE.def" +}; + + +// ELF Relocation types for CSKY +enum { +#include "ELFRelocs/CSKY.def" +}; + #undef ELF_RELOC // Section header. @@ -813,50 +906,52 @@ enum { // Section types. enum : unsigned { - SHT_NULL = 0, // No associated section (inactive entry). - SHT_PROGBITS = 1, // Program-defined contents. - SHT_SYMTAB = 2, // Symbol table. - SHT_STRTAB = 3, // String table. - SHT_RELA = 4, // Relocation entries; explicit addends. - SHT_HASH = 5, // Symbol hash table. - SHT_DYNAMIC = 6, // Information for dynamic linking. - SHT_NOTE = 7, // Information about the file. - SHT_NOBITS = 8, // Data occupies no space in the file. - SHT_REL = 9, // Relocation entries; no explicit addends. - SHT_SHLIB = 10, // Reserved. - SHT_DYNSYM = 11, // Symbol table. - SHT_INIT_ARRAY = 14, // Pointers to initialization functions. - SHT_FINI_ARRAY = 15, // Pointers to termination functions. - SHT_PREINIT_ARRAY = 16, // Pointers to pre-init functions. - SHT_GROUP = 17, // Section group. - SHT_SYMTAB_SHNDX = 18, // Indices for SHN_XINDEX entries. + SHT_NULL = 0, // No associated section (inactive entry). + SHT_PROGBITS = 1, // Program-defined contents. + SHT_SYMTAB = 2, // Symbol table. + SHT_STRTAB = 3, // String table. + SHT_RELA = 4, // Relocation entries; explicit addends. + SHT_HASH = 5, // Symbol hash table. + SHT_DYNAMIC = 6, // Information for dynamic linking. + SHT_NOTE = 7, // Information about the file. + SHT_NOBITS = 8, // Data occupies no space in the file. + SHT_REL = 9, // Relocation entries; no explicit addends. + SHT_SHLIB = 10, // Reserved. + SHT_DYNSYM = 11, // Symbol table. + SHT_INIT_ARRAY = 14, // Pointers to initialization functions. + SHT_FINI_ARRAY = 15, // Pointers to termination functions. + SHT_PREINIT_ARRAY = 16, // Pointers to pre-init functions. + SHT_GROUP = 17, // Section group. + SHT_SYMTAB_SHNDX = 18, // Indices for SHN_XINDEX entries. // Experimental support for SHT_RELR sections. For details, see proposal // at https://groups.google.com/forum/#!topic/generic-abi/bX460iggiKg - SHT_RELR = 19, // Relocation entries; only offsets. - SHT_LOOS = 0x60000000, // Lowest operating system-specific type. + SHT_RELR = 19, // Relocation entries; only offsets. + SHT_LOOS = 0x60000000, // Lowest operating system-specific type. // Android packed relocation section types. // https://android.googlesource.com/platform/bionic/+/6f12bfece5dcc01325e0abba56a46b1bcf991c69/tools/relocation_packer/src/elf_file.cc#37 SHT_ANDROID_REL = 0x60000001, SHT_ANDROID_RELA = 0x60000002, SHT_LLVM_ODRTAB = 0x6fff4c00, // LLVM ODR table. SHT_LLVM_LINKER_OPTIONS = 0x6fff4c01, // LLVM Linker Options. - SHT_LLVM_CALL_GRAPH_PROFILE = 0x6fff4c02, // LLVM Call Graph Profile. SHT_LLVM_ADDRSIG = 0x6fff4c03, // List of address-significant symbols // for safe ICF. - SHT_LLVM_DEPENDENT_LIBRARIES = 0x6fff4c04, // LLVM Dependent Library Specifiers. - SHT_LLVM_SYMPART = 0x6fff4c05, // Symbol partition specification. - SHT_LLVM_PART_EHDR = 0x6fff4c06, // ELF header for loadable partition. - SHT_LLVM_PART_PHDR = 0x6fff4c07, // Phdrs for loadable partition. + SHT_LLVM_DEPENDENT_LIBRARIES = + 0x6fff4c04, // LLVM Dependent Library Specifiers. + SHT_LLVM_SYMPART = 0x6fff4c05, // Symbol partition specification. + SHT_LLVM_PART_EHDR = 0x6fff4c06, // ELF header for loadable partition. + SHT_LLVM_PART_PHDR = 0x6fff4c07, // Phdrs for loadable partition. + SHT_LLVM_BB_ADDR_MAP = 0x6fff4c08, // LLVM Basic Block Address Map. + SHT_LLVM_CALL_GRAPH_PROFILE = 0x6fff4c09, // LLVM Call Graph Profile. // Android's experimental support for SHT_RELR sections. // https://android.googlesource.com/platform/bionic/+/b7feec74547f84559a1467aca02708ff61346d2a/libc/include/elf.h#512 - SHT_ANDROID_RELR = 0x6fffff00, // Relocation entries; only offsets. - SHT_GNU_ATTRIBUTES = 0x6ffffff5, // Object attributes. - SHT_GNU_HASH = 0x6ffffff6, // GNU-style hash table. - SHT_GNU_verdef = 0x6ffffffd, // GNU version definitions. - SHT_GNU_verneed = 0x6ffffffe, // GNU version references. - SHT_GNU_versym = 0x6fffffff, // GNU symbol versions table. - SHT_HIOS = 0x6fffffff, // Highest operating system-specific type. - SHT_LOPROC = 0x70000000, // Lowest processor arch-specific type. + SHT_ANDROID_RELR = 0x6fffff00, // Relocation entries; only offsets. + SHT_GNU_ATTRIBUTES = 0x6ffffff5, // Object attributes. + SHT_GNU_HASH = 0x6ffffff6, // GNU-style hash table. + SHT_GNU_verdef = 0x6ffffffd, // GNU version definitions. + SHT_GNU_verneed = 0x6ffffffe, // GNU version references. + SHT_GNU_versym = 0x6fffffff, // GNU symbol versions table. + SHT_HIOS = 0x6fffffff, // Highest operating system-specific type. + SHT_LOPROC = 0x70000000, // Lowest processor arch-specific type. // Fixme: All this is duplicated in MCSectionELF. Why?? // Exception Index table SHT_ARM_EXIDX = 0x70000001U, @@ -866,20 +961,22 @@ enum : unsigned { SHT_ARM_ATTRIBUTES = 0x70000003U, SHT_ARM_DEBUGOVERLAY = 0x70000004U, SHT_ARM_OVERLAYSECTION = 0x70000005U, - SHT_HEX_ORDERED = 0x70000000, // Link editor is to sort the entries in - // this section based on their sizes - SHT_X86_64_UNWIND = 0x70000001, // Unwind information + SHT_HEX_ORDERED = 0x70000000, // Link editor is to sort the entries in + // this section based on their sizes + SHT_X86_64_UNWIND = 0x70000001, // Unwind information - SHT_MIPS_REGINFO = 0x70000006, // Register usage information - SHT_MIPS_OPTIONS = 0x7000000d, // General options - SHT_MIPS_DWARF = 0x7000001e, // DWARF debugging section. - SHT_MIPS_ABIFLAGS = 0x7000002a, // ABI information. + SHT_MIPS_REGINFO = 0x70000006, // Register usage information + SHT_MIPS_OPTIONS = 0x7000000d, // General options + SHT_MIPS_DWARF = 0x7000001e, // DWARF debugging section. + SHT_MIPS_ABIFLAGS = 0x7000002a, // ABI information. SHT_MSP430_ATTRIBUTES = 0x70000003U, - SHT_HIPROC = 0x7fffffff, // Highest processor arch-specific type. - SHT_LOUSER = 0x80000000, // Lowest type reserved for applications. - SHT_HIUSER = 0xffffffff // Highest type reserved for applications. + SHT_RISCV_ATTRIBUTES = 0x70000003U, + + SHT_HIPROC = 0x7fffffff, // Highest processor arch-specific type. + SHT_LOUSER = 0x80000000, // Lowest type reserved for applications. + SHT_HIUSER = 0xffffffff // Highest type reserved for applications. }; // Section flags. @@ -918,6 +1015,9 @@ enum : unsigned { // Identifies a section containing compressed data. SHF_COMPRESSED = 0x800U, + // This section should not be garbage collected by the linker. + SHF_GNU_RETAIN = 0x200000, + // This section is excluded from the final executable or shared library. SHF_EXCLUDE = 0x80000000U, @@ -1203,6 +1303,7 @@ enum { PT_GNU_RELRO = 0x6474e552, // Read-only after relocation. PT_GNU_PROPERTY = 0x6474e553, // .note.gnu.property notes sections. + PT_OPENBSD_MUTABLE = 0x65a3dbe5, // Like bss, but not immutable. PT_OPENBSD_RANDOMIZE = 0x65a3dbe6, // Fill with random data. PT_OPENBSD_WXNEEDED = 0x65a3dbe7, // Program does W^X violations. PT_OPENBSD_BOOTDATA = 0x65a41be6, // Section for boot arguments. @@ -1290,7 +1391,8 @@ enum { DF_1_NORELOC = 0x00400000, DF_1_SYMINTPOSE = 0x00800000, // Object has individual interposers. DF_1_GLOBAUDIT = 0x01000000, // Global auditing required. - DF_1_SINGLETON = 0x02000000 // Singleton symbols are used. + DF_1_SINGLETON = 0x02000000, // Singleton symbols are used. + DF_1_PIE = 0x08000000, // Object is a position-independent executable. }; // DT_MIPS_FLAGS values. @@ -1335,21 +1437,9 @@ enum { // ElfXX_VerNeed structure version (GNU versioning) enum { VER_NEED_NONE = 0, VER_NEED_CURRENT = 1 }; -// SHT_NOTE section types -enum { - NT_FREEBSD_THRMISC = 7, - NT_FREEBSD_PROCSTAT_PROC = 8, - NT_FREEBSD_PROCSTAT_FILES = 9, - NT_FREEBSD_PROCSTAT_VMMAP = 10, - NT_FREEBSD_PROCSTAT_GROUPS = 11, - NT_FREEBSD_PROCSTAT_UMASK = 12, - NT_FREEBSD_PROCSTAT_RLIMIT = 13, - NT_FREEBSD_PROCSTAT_OSREL = 14, - NT_FREEBSD_PROCSTAT_PSSTRINGS = 15, - NT_FREEBSD_PROCSTAT_AUXV = 16, -}; +// SHT_NOTE section types. -// Generic note types +// Generic note types. enum : unsigned { NT_VERSION = 1, NT_ARCH = 2, @@ -1357,7 +1447,7 @@ enum : unsigned { NT_GNU_BUILD_ATTRIBUTE_FUNC = 0x101, }; -// Core note types +// Core note types. enum : unsigned { NT_PRSTATUS = 1, NT_FPREGSET = 2, @@ -1422,7 +1512,7 @@ enum { NT_LLVM_HWASAN_GLOBALS = 3, }; -// GNU note types +// GNU note types. enum { NT_GNU_ABI_TAG = 1, NT_GNU_HWCAP = 2, @@ -1437,10 +1527,14 @@ enum : unsigned { GNU_PROPERTY_NO_COPY_ON_PROTECTED = 2, GNU_PROPERTY_AARCH64_FEATURE_1_AND = 0xc0000000, GNU_PROPERTY_X86_FEATURE_1_AND = 0xc0000002, - GNU_PROPERTY_X86_ISA_1_NEEDED = 0xc0008000, - GNU_PROPERTY_X86_FEATURE_2_NEEDED = 0xc0008001, - GNU_PROPERTY_X86_ISA_1_USED = 0xc0010000, - GNU_PROPERTY_X86_FEATURE_2_USED = 0xc0010001, + + GNU_PROPERTY_X86_UINT32_OR_LO = 0xc0008000, + GNU_PROPERTY_X86_FEATURE_2_NEEDED = GNU_PROPERTY_X86_UINT32_OR_LO + 1, + GNU_PROPERTY_X86_ISA_1_NEEDED = GNU_PROPERTY_X86_UINT32_OR_LO + 2, + + GNU_PROPERTY_X86_UINT32_OR_AND_LO = 0xc0010000, + GNU_PROPERTY_X86_FEATURE_2_USED = GNU_PROPERTY_X86_UINT32_OR_AND_LO + 1, + GNU_PROPERTY_X86_ISA_1_USED = GNU_PROPERTY_X86_UINT32_OR_AND_LO + 2, }; // aarch64 processor feature bits. @@ -1454,31 +1548,6 @@ enum : unsigned { GNU_PROPERTY_X86_FEATURE_1_IBT = 1 << 0, GNU_PROPERTY_X86_FEATURE_1_SHSTK = 1 << 1, - GNU_PROPERTY_X86_ISA_1_CMOV = 1 << 0, - GNU_PROPERTY_X86_ISA_1_SSE = 1 << 1, - GNU_PROPERTY_X86_ISA_1_SSE2 = 1 << 2, - GNU_PROPERTY_X86_ISA_1_SSE3 = 1 << 3, - GNU_PROPERTY_X86_ISA_1_SSSE3 = 1 << 4, - GNU_PROPERTY_X86_ISA_1_SSE4_1 = 1 << 5, - GNU_PROPERTY_X86_ISA_1_SSE4_2 = 1 << 6, - GNU_PROPERTY_X86_ISA_1_AVX = 1 << 7, - GNU_PROPERTY_X86_ISA_1_AVX2 = 1 << 8, - GNU_PROPERTY_X86_ISA_1_FMA = 1 << 9, - GNU_PROPERTY_X86_ISA_1_AVX512F = 1 << 10, - GNU_PROPERTY_X86_ISA_1_AVX512CD = 1 << 11, - GNU_PROPERTY_X86_ISA_1_AVX512ER = 1 << 12, - GNU_PROPERTY_X86_ISA_1_AVX512PF = 1 << 13, - GNU_PROPERTY_X86_ISA_1_AVX512VL = 1 << 14, - GNU_PROPERTY_X86_ISA_1_AVX512DQ = 1 << 15, - GNU_PROPERTY_X86_ISA_1_AVX512BW = 1 << 16, - GNU_PROPERTY_X86_ISA_1_AVX512_4FMAPS = 1 << 17, - GNU_PROPERTY_X86_ISA_1_AVX512_4VNNIW = 1 << 18, - GNU_PROPERTY_X86_ISA_1_AVX512_BITALG = 1 << 19, - GNU_PROPERTY_X86_ISA_1_AVX512_IFMA = 1 << 20, - GNU_PROPERTY_X86_ISA_1_AVX512_VBMI = 1 << 21, - GNU_PROPERTY_X86_ISA_1_AVX512_VBMI2 = 1 << 22, - GNU_PROPERTY_X86_ISA_1_AVX512_VNNI = 1 << 23, - GNU_PROPERTY_X86_FEATURE_2_X86 = 1 << 0, GNU_PROPERTY_X86_FEATURE_2_X87 = 1 << 1, GNU_PROPERTY_X86_FEATURE_2_MMX = 1 << 2, @@ -1489,6 +1558,43 @@ enum : unsigned { GNU_PROPERTY_X86_FEATURE_2_XSAVE = 1 << 7, GNU_PROPERTY_X86_FEATURE_2_XSAVEOPT = 1 << 8, GNU_PROPERTY_X86_FEATURE_2_XSAVEC = 1 << 9, + + GNU_PROPERTY_X86_ISA_1_BASELINE = 1 << 0, + GNU_PROPERTY_X86_ISA_1_V2 = 1 << 1, + GNU_PROPERTY_X86_ISA_1_V3 = 1 << 2, + GNU_PROPERTY_X86_ISA_1_V4 = 1 << 3, +}; + +// FreeBSD note types. +enum { + NT_FREEBSD_ABI_TAG = 1, + NT_FREEBSD_NOINIT_TAG = 2, + NT_FREEBSD_ARCH_TAG = 3, + NT_FREEBSD_FEATURE_CTL = 4, +}; + +// NT_FREEBSD_FEATURE_CTL values (see FreeBSD's sys/sys/elf_common.h). +enum { + NT_FREEBSD_FCTL_ASLR_DISABLE = 0x00000001, + NT_FREEBSD_FCTL_PROTMAX_DISABLE = 0x00000002, + NT_FREEBSD_FCTL_STKGAP_DISABLE = 0x00000004, + NT_FREEBSD_FCTL_WXNEEDED = 0x00000008, + NT_FREEBSD_FCTL_LA48 = 0x00000010, + NT_FREEBSD_FCTL_ASG_DISABLE = 0x00000020, +}; + +// FreeBSD core note types. +enum { + NT_FREEBSD_THRMISC = 7, + NT_FREEBSD_PROCSTAT_PROC = 8, + NT_FREEBSD_PROCSTAT_FILES = 9, + NT_FREEBSD_PROCSTAT_VMMAP = 10, + NT_FREEBSD_PROCSTAT_GROUPS = 11, + NT_FREEBSD_PROCSTAT_UMASK = 12, + NT_FREEBSD_PROCSTAT_RLIMIT = 13, + NT_FREEBSD_PROCSTAT_OSREL = 14, + NT_FREEBSD_PROCSTAT_PSSTRINGS = 15, + NT_FREEBSD_PROCSTAT_AUXV = 16, }; // AMDGPU-specific section indices. @@ -1496,15 +1602,18 @@ enum { SHN_AMDGPU_LDS = 0xff00, // Variable in LDS; symbol encoded like SHN_COMMON }; -// AMD specific notes. (Code Object V2) +// AMD vendor specific notes. (Code Object V2) enum { - // Note types with values between 0 and 9 (inclusive) are reserved. - NT_AMD_AMDGPU_HSA_METADATA = 10, - NT_AMD_AMDGPU_ISA = 11, - NT_AMD_AMDGPU_PAL_METADATA = 12 + NT_AMD_HSA_CODE_OBJECT_VERSION = 1, + NT_AMD_HSA_HSAIL = 2, + NT_AMD_HSA_ISA_VERSION = 3, + // Note types with values between 4 and 9 (inclusive) are reserved. + NT_AMD_HSA_METADATA = 10, + NT_AMD_HSA_ISA_NAME = 11, + NT_AMD_PAL_METADATA = 12 }; -// AMDGPU specific notes. (Code Object V3) +// AMDGPU vendor specific notes. (Code Object V3) enum { // Note types with values between 0 and 31 (inclusive) are reserved. NT_AMDGPU_METADATA = 32 @@ -1545,14 +1654,14 @@ struct Elf64_Chdr { Elf64_Xword ch_addralign; }; -// Node header for ELF32. +// Note header for ELF32. struct Elf32_Nhdr { Elf32_Word n_namesz; Elf32_Word n_descsz; Elf32_Word n_type; }; -// Node header for ELF64. +// Note header for ELF64. struct Elf64_Nhdr { Elf64_Word n_namesz; Elf64_Word n_descsz; @@ -1568,6 +1677,12 @@ enum { ELFCOMPRESS_HIPROC = 0x7fffffff // End of processor-specific. }; +/// Convert an architecture name into ELF's e_machine value. +uint16_t convertArchNameToEMachine(StringRef Arch); + +/// Convert an ELF's e_machine value into an architecture name. +StringRef convertEMachineToArchName(uint16_t EMachine); + } // end namespace ELF } // end namespace llvm |