[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
This commit is contained in:
Fangrui Song 2025-02-10 09:21:31 -08:00 committed by GitHub
parent 9e0077c921
commit 0a470a9264
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 43 additions and 8 deletions

View File

@ -411,7 +411,7 @@ struct Config {
StringRef thinLTOJobs;
unsigned timeTraceGranularity;
int32_t splitStackAdjustSize;
StringRef packageMetadata;
SmallVector<uint8_t, 0> packageMetadata;
// The following config options do not directly correspond to any
// particular command line options.

View File

@ -816,6 +816,26 @@ static ICFLevel getICF(opt::InputArgList &args) {
return ICFLevel::All;
}
static void parsePackageMetadata(Ctx &ctx, const opt::Arg &arg) {
unsigned c0, c1;
SmallVector<uint8_t, 0> 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;
@ -1425,7 +1445,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);

View File

@ -578,7 +578,7 @@ def z: JoinedOrSeparate<["-"], "z">, MetaVarName<"<option>">,
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">;
def package_metadata: JJ<"package-metadata=">, HelpText<"Emit a percent-encoded string to the .note.package section">;
// Aliases
def: Separate<["-"], "dT">, Alias<default_script>, HelpText<"Alias for --default-script">;

View File

@ -493,6 +493,10 @@ If
.Fl -use-android-relr-tags
is specified, use SHT_ANDROID_RELR instead of SHT_RELR.
.Pp
.It Fl -package-metadata
Emit a percent-encoded string to the
.Cm .note.package
section. For example, %25 decodes to a single %.
.It Fl -pic-veneer
Always generate position independent thunks.
.It Fl -pie , Fl -pic-executable

View File

@ -1,12 +1,15 @@
# REQUIRES: x86
# RUN: rm -rf %t && split-file %s %t && cd %t
# RUN: llvm-mc -filetype=obj -triple=x86_64 a.s -o a.o
# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o
# RUN: ld.lld a.o --package-metadata='{}'
# RUN: llvm-readelf -n a.out | FileCheck %s --check-prefixes=NOTE,FIRST
# RUN: ld.lld %t.o -o %t --package-metadata='{}'
# RUN: llvm-readelf -n %t | FileCheck %s --check-prefixes=NOTE,FIRST
# RUN: ld.lld a.o --package-metadata='{"abc":123}'
# RUN: llvm-readelf -n a.out | FileCheck %s --check-prefixes=NOTE,SECOND
# RUN: ld.lld %t.o -o %t --package-metadata='{"abc":123}'
# RUN: llvm-readelf -n %t | FileCheck %s --check-prefixes=NOTE,SECOND
# RUN: ld.lld a.o --package-metadata='%7b%22abc%22:123%7D'
# RUN: llvm-readelf -n a.out | FileCheck %s --check-prefixes=NOTE,SECOND
# NOTE: .note.package
# NOTE-NEXT: Owner
@ -14,6 +17,13 @@
# FIRST-NEXT: description data: 7b 7d 00
# SECOND-NEXT: description data: 7b 22 61 62 63 22 3a 31 32 33 7d 00
# RUN: not ld.lld a.o --package-metadata='%7b%' 2>&1 | FileCheck %s --check-prefix=ERR
# RUN: not ld.lld a.o --package-metadata='%7b%7' 2>&1 | FileCheck %s --check-prefix=ERR
# RUN: not ld.lld a.o --package-metadata='%7b%7g' 2>&1 | FileCheck %s --check-prefix=ERR
# ERR: error: --package-metadata=: invalid % escape at byte 3; supports only %[0-9a-fA-F][0-9a-fA-F]
#--- a.s
.globl _start
_start:
ret