From 9e07fbf6411110b0f3e9b814a2e2bcac74c9eb88 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Mon, 10 Feb 2025 09:21:31 -0800 Subject: [PATCH] [ELF] --package-metadata: support %[0-9a-fA-F][0-9a-fA-F] (This application-specific option is probably not appropriate as a linker option (.o file offers more flexibility and decouples JSON verification from linkers). However, the option has gained some traction in Linux distributions, with support in GNU ld, gold, and mold.) GNU ld has supported percent-encoded bytes and extensions like `%[comma]` since November 2024. mold supports just percent-encoded bytes. To prepare for potential adoption by Ubuntu, let's support percent-encoded bytes. Link: https://sourceware.org/bugzilla/show_bug.cgi?id=32003 Link: https://bugs.launchpad.net/ubuntu/+source/dpkg/+bug/2071468 Pull Request: https://github.com/llvm/llvm-project/pull/126396 (cherry picked from commit 0a470a926481d370251731cb2dd897531756335f) --- lld/ELF/Config.h | 2 +- lld/ELF/Driver.cpp | 23 ++++++++++++++++++++++- lld/ELF/Options.td | 2 +- lld/docs/ld.lld.1 | 4 ++++ lld/test/ELF/package-metadata.s | 20 +++++++++++++++----- 5 files changed, 43 insertions(+), 8 deletions(-) diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h index c2aadb2cef520..98e52b52ea46a 100644 --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -407,7 +407,7 @@ struct Config { StringRef thinLTOJobs; unsigned timeTraceGranularity; int32_t splitStackAdjustSize; - StringRef packageMetadata; + SmallVector 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 index 9d0c992c1e851..2d8a5ade2fece 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -822,6 +822,26 @@ static ICFLevel getICF(opt::InputArgList &args) { return ICFLevel::All; } +static void parsePackageMetadata(Ctx &ctx, const opt::Arg &arg) { + unsigned c0, c1; + SmallVector decoded; + StringRef s = arg.getValue(); + for (size_t i = 0, e = s.size(); i != e; ++i) { + if (s[i] != '%') { + decoded.push_back(s[i]); + } else if (i + 2 < e && (c1 = hexDigitValue(s[i + 1])) != -1u && + (c0 = hexDigitValue(s[i + 2])) != -1u) { + decoded.push_back(uint8_t(c1 * 16 + c0)); + i += 2; + } else { + ErrAlways(ctx) << arg.getSpelling() << ": invalid % escape at byte " << i + << "; supports only %[0-9a-fA-F][0-9a-fA-F]"; + return; + } + } + ctx.arg.packageMetadata = std::move(decoded); +} + static StripPolicy getStrip(Ctx &ctx, opt::InputArgList &args) { if (args.hasArg(OPT_relocatable)) return StripPolicy::None; @@ -1383,7 +1403,8 @@ static void readConfigs(Ctx &ctx, opt::InputArgList &args) { ctx.arg.optimize = args::getInteger(args, OPT_O, 1); ctx.arg.orphanHandling = getOrphanHandling(ctx, args); ctx.arg.outputFile = args.getLastArgValue(OPT_o); - ctx.arg.packageMetadata = args.getLastArgValue(OPT_package_metadata); + if (auto *arg = args.getLastArg(OPT_package_metadata)) + parsePackageMetadata(ctx, *arg); ctx.arg.pie = args.hasFlag(OPT_pie, OPT_no_pie, false); ctx.arg.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 index c31875305952f..d9998176d0dd4 100644 --- a/lld/ELF/Options.td +++ b/lld/ELF/Options.td @@ -565,7 +565,7 @@ def z: JoinedOrSeparate<["-"], "z">, MetaVarName<"