diff --git a/llvm/test/tools/yaml2obj/ELF/emachine.yaml b/llvm/test/tools/yaml2obj/ELF/emachine.yaml --- a/llvm/test/tools/yaml2obj/ELF/emachine.yaml +++ b/llvm/test/tools/yaml2obj/ELF/emachine.yaml @@ -2,7 +2,7 @@ ## Test we can use an arbitrary value. -# RUN: yaml2obj --docnum=1 %s -o %t1 +# RUN: yaml2obj -D MACHINE=0x1234 %s -o %t1 # RUN: llvm-readelf %t1 --file-headers | FileCheck %s --check-prefix=UNKNOWN # UNKNOWN: Machine: 1234 @@ -12,44 +12,23 @@ Class: ELFCLASS64 Data: ELFDATA2MSB Type: ET_REL - Machine: 0x1234 + Machine: [[MACHINE]] ## Test we can't use a number that doesn't fit into 2 bytes. -# RUN: not yaml2obj --docnum=2 %s 2>&1 | FileCheck %s --check-prefix=ERR +# RUN: not yaml2obj -D MACHINE=0x12345 %s 2>&1 | FileCheck %s --check-prefix=ERR # ERR: error: out of range hex16 number ---- !ELF -FileHeader: - Class: ELFCLASS64 - Data: ELFDATA2MSB - Type: ET_REL - Machine: 0x12345 - ## Test we can use a known named constant. -# RUN: yaml2obj --docnum=3 %s -o %t3 +# RUN: yaml2obj -D MACHINE=EM_NONE %s -o %t3 # RUN: llvm-readelf %t3 --file-headers | FileCheck %s --check-prefix=NONE # NONE: Machine: None ---- !ELF -FileHeader: - Class: ELFCLASS64 - Data: ELFDATA2MSB - Type: ET_REL - Machine: EM_NONE - ## Test we can't use an unknown string constant. -# RUN: not yaml2obj --docnum=4 %s 2>&1 | FileCheck %s --check-prefix=ERR2 +# RUN: not yaml2obj -D MACHINE=EM_UNKNOWN_FOO %s 2>&1 | FileCheck %s --check-prefix=ERR2 # ERR2: error: invalid hex16 number - ---- !ELF -FileHeader: - Class: ELFCLASS64 - Data: ELFDATA2MSB - Type: ET_REL - Machine: EM_UNKNOWN_FOO diff --git a/llvm/test/tools/yaml2obj/preprocess.yaml b/llvm/test/tools/yaml2obj/preprocess.yaml new file mode 100644 --- /dev/null +++ b/llvm/test/tools/yaml2obj/preprocess.yaml @@ -0,0 +1,41 @@ +# RUN: yaml2obj -D NAME= %s | llvm-nm - | FileCheck --check-prefix=FBAR %s +# FBAR: U fbar + +# RUN: yaml2obj -D NAME=o %s | llvm-nm - | FileCheck --check-prefix=FOOBAR %s +# FOOBAR: U foobar + +# RUN: not yaml2obj -D NAME %s 2>&1 | FileCheck --check-prefix=ERR1 %s +# ERR1: error: bad override, missing field name: NAME + +# RUN: not yaml2obj -D =value %s 2>&1 | FileCheck --check-prefix=ERR2 %s +# ERR2: error: bad override, missing field name: =value + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Symbols: + - Name: f[[NAME]][[NAME]]bar + +## FileCheck uses [[ as a pattern. It cannot be used for [[ testing. +## Test that undefined patterns are not substituted. + +# RUN: yaml2obj --docnum=2 %s | llvm-nm --just-symbol-name --no-sort - > %t.nosubst +# RUN: echo -e 'a[[\n[[a\n[[a]\n[[a][[a]][[a]]' | cmp - %t.nosubst + +# RUN: yaml2obj --docnum=2 -D a=b %s | llvm-nm --just-symbol-name --no-sort - > %t.subst +# RUN: echo -e 'a[[\n[[a\n[[a]\n[[a]bb' | cmp - %t.subst + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Symbols: + - Name: "a[[" + - Name: "[[a" + - Name: "[[a]" + - Name: "[[a][[a]][[a]]" diff --git a/llvm/tools/yaml2obj/yaml2obj.cpp b/llvm/tools/yaml2obj/yaml2obj.cpp --- a/llvm/tools/yaml2obj/yaml2obj.cpp +++ b/llvm/tools/yaml2obj/yaml2obj.cpp @@ -31,6 +31,9 @@ static cl::opt Input(cl::Positional, cl::desc(""), cl::init("-")); +static cl::list + D("D", cl::desc("list of overridden fields: field=value")); + static cl::opt DocNum("docnum", cl::init(1), cl::desc("Read specified document from input (default = 1)")); @@ -38,6 +41,41 @@ static cl::opt OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename")); +static Optional preprocess(StringRef Buf, + yaml::ErrorHandler ErrHandler) { + DenseMap Substitution; + for (StringRef Define : D) { + StringRef F, V; + std::tie(F, V) = Define.split('='); + if (!Define.count('=') || F.empty()) { + ErrHandler("bad override, missing field name: " + Define); + return {}; + } + Substitution.try_emplace(F, V); + } + + std::string Preprocessed; + while (!Buf.empty()) { + if (Buf.startswith("[[")) { + size_t I = Buf.find("]]", 2); + if (I != size_t(-1)) { + StringRef Macro = Buf.substr(2, I - 2); + auto It = Substitution.find(Macro); + if (It != Substitution.end()) { + Preprocessed += It->second; + Buf = Buf.substr(I + 2); + continue; + } + } + } + + Preprocessed += Buf[0]; + Buf = Buf.substr(1); + } + + return Preprocessed; +} + int main(int argc, char **argv) { InitLLVM X(argc, argv); cl::ParseCommandLineOptions(argc, argv); @@ -57,12 +95,15 @@ return 1; } - ErrorOr> Buf = + ErrorOr> Buffer = MemoryBuffer::getFileOrSTDIN(Input); + if (!Buffer) + return 1; + + Optional Buf = preprocess(Buffer.get()->getBuffer(), ErrHandler); if (!Buf) return 1; - - yaml::Input YIn(Buf.get()->getBuffer()); + yaml::Input YIn(*Buf); if (!convertYAML(YIn, Out->os(), ErrHandler, DocNum)) return 1;