diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -291,6 +291,7 @@ StringRef thinLTOJobs; unsigned timeTraceGranularity; int32_t splitStackAdjustSize; + StringRef packageMetadata; // The following config options do not directly correspond to any // particular command line options. diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -1146,6 +1146,7 @@ config->optimize = args::getInteger(args, OPT_O, 1); config->orphanHandling = getOrphanHandling(args); config->outputFile = args.getLastArgValue(OPT_o); + config->packageMetadata = args.getLastArgValue(OPT_package_metadata); config->pie = args.hasFlag(OPT_pie, OPT_no_pie, false); config->printIcfSections = args.hasFlag(OPT_print_icf_sections, OPT_no_print_icf_sections, false); diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td --- a/lld/ELF/Options.td +++ b/lld/ELF/Options.td @@ -503,6 +503,8 @@ def visual_studio_diagnostics_format : FF<"vs-diagnostics">, HelpText<"Format diagnostics for Visual Studio compatibility">; +def package_metadata: JJ<"package-metadata=">, HelpText<"Emit package metadata note">; + // Aliases def: Separate<["-"], "f">, Alias, HelpText<"Alias for --auxiliary">; def: F<"call_shared">, Alias, HelpText<"Alias for --Bdynamic">; diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h --- a/lld/ELF/SyntheticSections.h +++ b/lld/ELF/SyntheticSections.h @@ -1176,6 +1176,15 @@ size_t getSize() const override; }; +class PackageMetadataNote : public SyntheticSection { +public: + PackageMetadataNote() + : SyntheticSection(llvm::ELF::SHF_ALLOC, llvm::ELF::SHT_NOTE, + /*alignment=*/4, ".note.package") {} + void writeTo(uint8_t *buf) override; + size_t getSize() const override; +}; + InputSection *createInterpSection(); MergeInputSection *createCommentSection(); template void splitSections(); @@ -1208,6 +1217,7 @@ std::unique_ptr gnuHashTab; std::unique_ptr hashTab; std::unique_ptr memtagAndroidNote; + std::unique_ptr packageMetadataNote; std::unique_ptr relaDyn; std::unique_ptr relrDyn; std::unique_ptr verDef; diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -3876,6 +3876,20 @@ /*descsz=*/sizeof(uint32_t); } +void PackageMetadataNote::writeTo(uint8_t *buf) { + write32(buf, 4); + write32(buf + 4, config->packageMetadata.size() + 1); + write32(buf + 8, FDO_PACKAGING_METADATA); + memcpy(buf + 12, "FDO", 4); + memcpy(buf + 16, config->packageMetadata.data(), + config->packageMetadata.size()); +} + +size_t PackageMetadataNote::getSize() const { + return sizeof(llvm::ELF::Elf64_Nhdr) + 4 + + alignTo(config->packageMetadata.size() + 1, 4); +} + InStruct elf::in; std::vector elf::partitions; diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -405,6 +405,11 @@ part.armExidx = std::make_unique(); add(*part.armExidx); } + + if (!config->packageMetadata.empty()) { + part.packageMetadataNote = std::make_unique(); + add(*part.packageMetadataNote); + } } if (partitions.size() != 1) { diff --git a/lld/docs/ReleaseNotes.rst b/lld/docs/ReleaseNotes.rst --- a/lld/docs/ReleaseNotes.rst +++ b/lld/docs/ReleaseNotes.rst @@ -25,6 +25,8 @@ ELF Improvements ---------------- +* ``--package-metadata=`` has been added to create package metadata notes + (`D131439 `_) Breaking changes ---------------- diff --git a/lld/test/ELF/package-metadata.s b/lld/test/ELF/package-metadata.s new file mode 100644 --- /dev/null +++ b/lld/test/ELF/package-metadata.s @@ -0,0 +1,19 @@ +# REQUIRES: x86 + +# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o + +# RUN: ld.lld %t.o -o %t --package-metadata='{}' +# RUN: llvm-readelf -n %t | FileCheck %s --check-prefixes=NOTE,FIRST + +# RUN: ld.lld %t.o -o %t --package-metadata='{"abc":123}' +# RUN: llvm-readelf -n %t | FileCheck %s --check-prefixes=NOTE,SECOND + +# NOTE: .note.package +# NOTE-NEXT: Owner +# NOTE-NEXT: FDO 0x{{.*}} Unknown note type: (0xcafe1a7e) +# FIRST-NEXT: description data: 7b 7d 00 +# SECOND-NEXT: description data: 7b 22 61 62 63 22 3a 31 32 33 7d 00 + +.globl _start +_start: + ret diff --git a/llvm/include/llvm/BinaryFormat/ELF.h b/llvm/include/llvm/BinaryFormat/ELF.h --- a/llvm/include/llvm/BinaryFormat/ELF.h +++ b/llvm/include/llvm/BinaryFormat/ELF.h @@ -1598,6 +1598,7 @@ NT_GNU_BUILD_ID = 3, NT_GNU_GOLD_VERSION = 4, NT_GNU_PROPERTY_TYPE_0 = 5, + FDO_PACKAGING_METADATA = 0xcafe1a7e, }; // Android note types.