Skip to content

Commit 0a470a9

Browse files
authored
[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: llvm#126396
1 parent 9e0077c commit 0a470a9

File tree

5 files changed

+43
-8
lines changed

5 files changed

+43
-8
lines changed

lld/ELF/Config.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,7 @@ struct Config {
411411
StringRef thinLTOJobs;
412412
unsigned timeTraceGranularity;
413413
int32_t splitStackAdjustSize;
414-
StringRef packageMetadata;
414+
SmallVector<uint8_t, 0> packageMetadata;
415415

416416
// The following config options do not directly correspond to any
417417
// particular command line options.

lld/ELF/Driver.cpp

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -816,6 +816,26 @@ static ICFLevel getICF(opt::InputArgList &args) {
816816
return ICFLevel::All;
817817
}
818818

819+
static void parsePackageMetadata(Ctx &ctx, const opt::Arg &arg) {
820+
unsigned c0, c1;
821+
SmallVector<uint8_t, 0> decoded;
822+
StringRef s = arg.getValue();
823+
for (size_t i = 0, e = s.size(); i != e; ++i) {
824+
if (s[i] != '%') {
825+
decoded.push_back(s[i]);
826+
} else if (i + 2 < e && (c1 = hexDigitValue(s[i + 1])) != -1u &&
827+
(c0 = hexDigitValue(s[i + 2])) != -1u) {
828+
decoded.push_back(uint8_t(c1 * 16 + c0));
829+
i += 2;
830+
} else {
831+
ErrAlways(ctx) << arg.getSpelling() << ": invalid % escape at byte " << i
832+
<< "; supports only %[0-9a-fA-F][0-9a-fA-F]";
833+
return;
834+
}
835+
}
836+
ctx.arg.packageMetadata = std::move(decoded);
837+
}
838+
819839
static StripPolicy getStrip(Ctx &ctx, opt::InputArgList &args) {
820840
if (args.hasArg(OPT_relocatable))
821841
return StripPolicy::None;
@@ -1425,7 +1445,8 @@ static void readConfigs(Ctx &ctx, opt::InputArgList &args) {
14251445
ctx.arg.optimize = args::getInteger(args, OPT_O, 1);
14261446
ctx.arg.orphanHandling = getOrphanHandling(ctx, args);
14271447
ctx.arg.outputFile = args.getLastArgValue(OPT_o);
1428-
ctx.arg.packageMetadata = args.getLastArgValue(OPT_package_metadata);
1448+
if (auto *arg = args.getLastArg(OPT_package_metadata))
1449+
parsePackageMetadata(ctx, *arg);
14291450
ctx.arg.pie = args.hasFlag(OPT_pie, OPT_no_pie, false);
14301451
ctx.arg.printIcfSections =
14311452
args.hasFlag(OPT_print_icf_sections, OPT_no_print_icf_sections, false);

lld/ELF/Options.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -578,7 +578,7 @@ def z: JoinedOrSeparate<["-"], "z">, MetaVarName<"<option>">,
578578
def visual_studio_diagnostics_format : FF<"vs-diagnostics">,
579579
HelpText<"Format diagnostics for Visual Studio compatibility">;
580580

581-
def package_metadata: JJ<"package-metadata=">, HelpText<"Emit package metadata note">;
581+
def package_metadata: JJ<"package-metadata=">, HelpText<"Emit a percent-encoded string to the .note.package section">;
582582

583583
// Aliases
584584
def: Separate<["-"], "dT">, Alias<default_script>, HelpText<"Alias for --default-script">;

lld/docs/ld.lld.1

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -493,6 +493,10 @@ If
493493
.Fl -use-android-relr-tags
494494
is specified, use SHT_ANDROID_RELR instead of SHT_RELR.
495495
.Pp
496+
.It Fl -package-metadata
497+
Emit a percent-encoded string to the
498+
.Cm .note.package
499+
section. For example, %25 decodes to a single %.
496500
.It Fl -pic-veneer
497501
Always generate position independent thunks.
498502
.It Fl -pie , Fl -pic-executable

lld/test/ELF/package-metadata.s

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,29 @@
11
# REQUIRES: x86
2+
# RUN: rm -rf %t && split-file %s %t && cd %t
3+
# RUN: llvm-mc -filetype=obj -triple=x86_64 a.s -o a.o
24

3-
# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o
5+
# RUN: ld.lld a.o --package-metadata='{}'
6+
# RUN: llvm-readelf -n a.out | FileCheck %s --check-prefixes=NOTE,FIRST
47

5-
# RUN: ld.lld %t.o -o %t --package-metadata='{}'
6-
# RUN: llvm-readelf -n %t | FileCheck %s --check-prefixes=NOTE,FIRST
8+
# RUN: ld.lld a.o --package-metadata='{"abc":123}'
9+
# RUN: llvm-readelf -n a.out | FileCheck %s --check-prefixes=NOTE,SECOND
710

8-
# RUN: ld.lld %t.o -o %t --package-metadata='{"abc":123}'
9-
# RUN: llvm-readelf -n %t | FileCheck %s --check-prefixes=NOTE,SECOND
11+
# RUN: ld.lld a.o --package-metadata='%7b%22abc%22:123%7D'
12+
# RUN: llvm-readelf -n a.out | FileCheck %s --check-prefixes=NOTE,SECOND
1013

1114
# NOTE: .note.package
1215
# NOTE-NEXT: Owner
1316
# NOTE-NEXT: FDO 0x{{.*}} Unknown note type: (0xcafe1a7e)
1417
# FIRST-NEXT: description data: 7b 7d 00
1518
# SECOND-NEXT: description data: 7b 22 61 62 63 22 3a 31 32 33 7d 00
1619

20+
# RUN: not ld.lld a.o --package-metadata='%7b%' 2>&1 | FileCheck %s --check-prefix=ERR
21+
# RUN: not ld.lld a.o --package-metadata='%7b%7' 2>&1 | FileCheck %s --check-prefix=ERR
22+
# RUN: not ld.lld a.o --package-metadata='%7b%7g' 2>&1 | FileCheck %s --check-prefix=ERR
23+
24+
# ERR: error: --package-metadata=: invalid % escape at byte 3; supports only %[0-9a-fA-F][0-9a-fA-F]
25+
26+
#--- a.s
1727
.globl _start
1828
_start:
1929
ret

0 commit comments

Comments
 (0)