diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2019-02-07 17:07:18 -0500 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2019-02-07 17:07:18 -0500 |
| commit | 3e08b3a4f89ee8e6102fcc67fc7e77c5e3eba104 (patch) | |
| tree | e45ce5ccef05c44a202de42901bb3513ac0b178b /deps/lld/ELF/ScriptParser.cpp | |
| parent | 91baa574a5f7224b48e4499a9db0c5283d800ec3 (diff) | |
| download | zig-3e08b3a4f89ee8e6102fcc67fc7e77c5e3eba104.tar.gz zig-3e08b3a4f89ee8e6102fcc67fc7e77c5e3eba104.zip | |
update embedded LLD to 8.0.0rc2
Diffstat (limited to 'deps/lld/ELF/ScriptParser.cpp')
| -rw-r--r-- | deps/lld/ELF/ScriptParser.cpp | 144 |
1 files changed, 108 insertions, 36 deletions
diff --git a/deps/lld/ELF/ScriptParser.cpp b/deps/lld/ELF/ScriptParser.cpp index ddb4a49a3e..7cce94659c 100644 --- a/deps/lld/ELF/ScriptParser.cpp +++ b/deps/lld/ELF/ScriptParser.cpp @@ -72,13 +72,15 @@ private: void readRegionAlias(); void readSearchDir(); void readSections(); + void readTarget(); void readVersion(); void readVersionScriptCommand(); SymbolAssignment *readSymbolAssignment(StringRef Name); ByteCommand *readByteCommand(StringRef Tok); - uint32_t readFill(); - uint32_t parseFill(StringRef Tok); + std::array<uint8_t, 4> readFill(); + std::array<uint8_t, 4> parseFill(StringRef Tok); + bool readSectionDirective(OutputSection *Cmd, StringRef Tok1, StringRef Tok2); void readSectionAddressType(OutputSection *Cmd); OutputSection *readOverlaySectionDescription(); OutputSection *readOutputSectionDescription(StringRef OutSec); @@ -255,6 +257,8 @@ void ScriptParser::readLinkerScript() { readSearchDir(); } else if (Tok == "SECTIONS") { readSections(); + } else if (Tok == "TARGET") { + readTarget(); } else if (Tok == "VERSION") { readVersion(); } else if (SymbolAssignment *Cmd = readAssignment(Tok)) { @@ -266,6 +270,8 @@ void ScriptParser::readLinkerScript() { } void ScriptParser::readDefsym(StringRef Name) { + if (errorCount()) + return; Expr E = readExpr(); if (!atEOF()) setError("EOF expected, but got " + next()); @@ -378,10 +384,42 @@ void ScriptParser::readOutputArch() { skip(); } +static std::pair<ELFKind, uint16_t> parseBfdName(StringRef S) { + return StringSwitch<std::pair<ELFKind, uint16_t>>(S) + .Case("elf32-i386", {ELF32LEKind, EM_386}) + .Case("elf32-iamcu", {ELF32LEKind, EM_IAMCU}) + .Case("elf32-littlearm", {ELF32LEKind, EM_ARM}) + .Case("elf32-x86-64", {ELF32LEKind, EM_X86_64}) + .Case("elf64-aarch64", {ELF64LEKind, EM_AARCH64}) + .Case("elf64-littleaarch64", {ELF64LEKind, EM_AARCH64}) + .Case("elf64-powerpc", {ELF64BEKind, EM_PPC64}) + .Case("elf64-powerpcle", {ELF64LEKind, EM_PPC64}) + .Case("elf64-x86-64", {ELF64LEKind, EM_X86_64}) + .Case("elf32-tradbigmips", {ELF32BEKind, EM_MIPS}) + .Case("elf32-ntradbigmips", {ELF32BEKind, EM_MIPS}) + .Case("elf32-tradlittlemips", {ELF32LEKind, EM_MIPS}) + .Case("elf32-ntradlittlemips", {ELF32LEKind, EM_MIPS}) + .Case("elf64-tradbigmips", {ELF64BEKind, EM_MIPS}) + .Case("elf64-tradlittlemips", {ELF64LEKind, EM_MIPS}) + .Default({ELFNoneKind, EM_NONE}); +} + +// Parse OUTPUT_FORMAT(bfdname) or OUTPUT_FORMAT(bfdname, big, little). +// Currently we ignore big and little parameters. void ScriptParser::readOutputFormat() { - // Error checking only for now. expect("("); - skip(); + + StringRef Name = unquote(next()); + StringRef S = Name; + 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); + if (S == "elf32-ntradlittlemips" || S == "elf32-ntradbigmips") + Config->MipsN32Abi = true; + if (consume(")")) return; expect(","); @@ -497,6 +535,9 @@ void ScriptParser::readSections() { for (BaseCommand *Cmd : readOverlay()) V.push_back(Cmd); continue; + } else if (Tok == "INCLUDE") { + readInclude(); + continue; } if (BaseCommand *Cmd = readAssignment(Tok)) @@ -522,6 +563,23 @@ void ScriptParser::readSections() { V.end()); } +void ScriptParser::readTarget() { + // TARGET(foo) is an alias for "--format foo". Unlike GNU linkers, + // we accept only a limited set of BFD names (i.e. "elf" or "binary") + // for --format. We recognize only /^elf/ and "binary" in the linker + // script as well. + expect("("); + StringRef Tok = next(); + expect(")"); + + if (Tok.startswith("elf")) + Config->FormatBinary = false; + else if (Tok == "binary") + Config->FormatBinary = true; + else + setError("unknown target: " + Tok); +} + static int precedence(StringRef Op) { return StringSwitch<int>(Op) .Cases("*", "/", "%", 8) @@ -672,13 +730,33 @@ Expr ScriptParser::readAssert() { // alias for =fillexp section attribute, which is different from // what GNU linkers do. // https://sourceware.org/binutils/docs/ld/Output-Section-Data.html -uint32_t ScriptParser::readFill() { +std::array<uint8_t, 4> ScriptParser::readFill() { expect("("); - uint32_t V = parseFill(next()); + std::array<uint8_t, 4> V = parseFill(next()); expect(")"); return V; } +// Tries to read the special directive for an output section definition which +// can be one of following: "(NOLOAD)", "(COPY)", "(INFO)" or "(OVERLAY)". +// Tok1 and Tok2 are next 2 tokens peeked. See comment for readSectionAddressType below. +bool ScriptParser::readSectionDirective(OutputSection *Cmd, StringRef Tok1, StringRef Tok2) { + if (Tok1 != "(") + return false; + if (Tok2 != "NOLOAD" && Tok2 != "COPY" && Tok2 != "INFO" && Tok2 != "OVERLAY") + return false; + + expect("("); + if (consume("NOLOAD")) { + Cmd->Noload = true; + } else { + skip(); // This is "COPY", "INFO" or "OVERLAY". + Cmd->NonAlloc = true; + } + expect(")"); + return true; +} + // Reads an expression and/or the special directive for an output // section definition. Directive is one of following: "(NOLOAD)", // "(COPY)", "(INFO)" or "(OVERLAY)". @@ -691,28 +769,12 @@ uint32_t ScriptParser::readFill() { // https://sourceware.org/binutils/docs/ld/Output-Section-Address.html // https://sourceware.org/binutils/docs/ld/Output-Section-Type.html void ScriptParser::readSectionAddressType(OutputSection *Cmd) { - if (consume("(")) { - if (consume("NOLOAD")) { - expect(")"); - Cmd->Noload = true; - return; - } - if (consume("COPY") || consume("INFO") || consume("OVERLAY")) { - expect(")"); - Cmd->NonAlloc = true; - return; - } - Cmd->AddrExpr = readExpr(); - expect(")"); - } else { - Cmd->AddrExpr = readExpr(); - } + if (readSectionDirective(Cmd, peek(), peek2())) + return; - if (consume("(")) { - expect("NOLOAD"); - expect(")"); - Cmd->Noload = true; - } + Cmd->AddrExpr = readExpr(); + if (peek() == "(" && !readSectionDirective(Cmd, "(", peek2())) + setError("unknown section directive: " + peek2()); } static Expr checkAlignment(Expr E, std::string &Loc) { @@ -778,10 +840,17 @@ OutputSection *ScriptParser::readOutputSectionDescription(StringRef OutSec) { Cmd->Filler = readFill(); } else if (Tok == "SORT") { readSort(); + } else if (Tok == "INCLUDE") { + readInclude(); } else if (peek() == "(") { Cmd->SectionCommands.push_back(readInputSectionDescription(Tok)); } else { - setError("unknown command " + Tok); + // 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. + auto *ISD = make<InputSectionDescription>(Tok); + ISD->SectionPatterns.push_back({{}, StringMatcher({"*"})}); + Cmd->SectionCommands.push_back(ISD); } } @@ -818,13 +887,13 @@ 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. -uint32_t ScriptParser::parseFill(StringRef Tok) { +std::array<uint8_t, 4> ScriptParser::parseFill(StringRef Tok) { uint32_t V = 0; if (!to_integer(Tok, V)) setError("invalid filler expression: " + Tok); - uint32_t Buf; - write32be(&Buf, V); + std::array<uint8_t, 4> Buf; + write32be(Buf.data(), V); return Buf; } @@ -1404,7 +1473,11 @@ uint64_t ScriptParser::readMemoryAssignment(StringRef S1, StringRef S2, void ScriptParser::readMemory() { expect("{"); while (!errorCount() && !consume("}")) { - StringRef Name = next(); + StringRef Tok = next(); + if (Tok == "INCLUDE") { + readInclude(); + continue; + } uint32_t Flags = 0; uint32_t NegFlags = 0; @@ -1419,10 +1492,9 @@ void ScriptParser::readMemory() { uint64_t Length = readMemoryAssignment("LENGTH", "len", "l"); // Add the memory region to the region map. - MemoryRegion *MR = - make<MemoryRegion>(Name, Origin, Length, Flags, NegFlags); - if (!Script->MemoryRegions.insert({Name, MR}).second) - setError("region '" + Name + "' already defined"); + MemoryRegion *MR = make<MemoryRegion>(Tok, Origin, Length, Flags, NegFlags); + if (!Script->MemoryRegions.insert({Tok, MR}).second) + setError("region '" + Tok + "' already defined"); } } |
