Add OUTPUT_FORMAT linker script directive support.

This patch adds a support for OUTPUT_FORMAT linker script directive.
Since I'm not 100% confident with BFD names you can use in the directive
for all architectures, I added only a few in this patch. We can add
other names for other archtiectures later.

We still do not support triple-style OUTPUT_FORMAT directive, namely,
OUTPUT_FORMAT(bfdname, big, little). If you pass -EL (little endian)
or -EB (big endian) to the linker, GNU linkers pick up big or little
as a BFD name, correspondingly, so that you can use a single linker
script for bi-endian processor. I'm not sure if we really need to
support that, so I'll leave it alone for now.

Note that -m takes precedence over OUTPUT_FORAMT, but we always parse
a BFD name given to OUTPUT_FORMAT for error checking. You cannot write
an invalid name in the OUTPUT_FORMAT directive.

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

llvm-svn: 344952
This commit is contained in:
Rui Ueyama
2018-10-22 20:50:01 +00:00
parent 01cc58bfb0
commit ea8cd00a1d
5 changed files with 56 additions and 12 deletions

View File

@@ -94,6 +94,7 @@ private:
SortSectionPolicy readSortKind();
SymbolAssignment *readProvideHidden(bool Provide, bool Hidden);
SymbolAssignment *readAssignment(StringRef Tok);
std::pair<ELFKind, uint16_t> readBfdName();
void readSort();
Expr readAssert();
Expr readConstant();
@@ -382,10 +383,34 @@ void ScriptParser::readOutputArch() {
skip();
}
std::pair<ELFKind, uint16_t> ScriptParser::readBfdName() {
StringRef S = next();
if (S == "elf32-i386")
return {ELF32LEKind, EM_386};
if (S == "elf32-iamcu")
return {ELF32LEKind, EM_IAMCU};
if (S == "elf32-x86-64")
return {ELF32LEKind, EM_X86_64};
if (S == "elf64-littleaarch64")
return {ELF64LEKind, EM_AARCH64};
if (S == "elf64-x86-64")
return {ELF64LEKind, EM_X86_64};
setError("unknown output format name: " + S);
return {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();
std::pair<ELFKind, uint16_t> P = readBfdName();
if (Config->EKind == ELFNoneKind) {
Config->EKind = P.first;
Config->EMachine = P.second;
}
if (consume(")"))
return;
expect(",");