Skip to content

Commit

Permalink
[ELF] Support --package-metadata
Browse files Browse the repository at this point in the history
Fixes #505
  • Loading branch information
rui314 committed May 26, 2022
1 parent 7730cb3 commit e9f6715
Show file tree
Hide file tree
Showing 7 changed files with 76 additions and 0 deletions.
8 changes: 8 additions & 0 deletions docs/mold.1
Original file line number Diff line number Diff line change
Expand Up @@ -646,6 +646,14 @@ to run executables or shared libraries linked with
.Fl -pack-dyn-relocs=relr ,
and only ChromeOS, Android and Fuchsia support it as of now in 2022.
.Pp
.It -package-metadata Ns = Ns string
Embed
.Ar string
to a .note.package section. This option in intended to be used by a \
package management command such as
.Cm rpm
to embed metadata regarding a package to each executable file.
.Pp
.It Fl -perf
Print performance statistics.
.Pp
Expand Down
3 changes: 3 additions & 0 deletions elf/cmdline.cc
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ static const char helpmsg[] = R"(
--oformat=binary Omit ELF, section and program headers
--pack-dyn-relocs=[relr,none]
Pack dynamic relocations
--package-metadata=STRING Set a given string to .note.package
--perf Print performance statistics
--pie, --pic-executable Create a position independent executable
--no-pie, --no-pic-executable
Expand Down Expand Up @@ -619,6 +620,8 @@ std::vector<std::string> parse_nonpositional_args(Context<E> &ctx) {
ctx.arg.pack_dyn_relocs_relr = true;
} else if (read_flag("pack-dyn-relocs=none")) {
ctx.arg.pack_dyn_relocs_relr = false;
} else if (read_arg("package-metadata")) {
ctx.arg.package_metadata = arg;
} else if (read_flag("stats")) {
ctx.arg.stats = true;
Counter::enabled = true;
Expand Down
1 change: 1 addition & 0 deletions elf/elf.h
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ static constexpr u32 NT_GNU_HWCAP = 2;
static constexpr u32 NT_GNU_BUILD_ID = 3;
static constexpr u32 NT_GNU_GOLD_VERSION = 4;
static constexpr u32 NT_GNU_PROPERTY_TYPE_0 = 5;
static constexpr u32 NT_FDO_PACKAGING_METADATA = 0xcafe1a7e;

static constexpr u32 GNU_PROPERTY_AARCH64_FEATURE_1_AND = 0xc0000000;
static constexpr u32 GNU_PROPERTY_X86_FEATURE_1_AND = 0xc0000002;
Expand Down
16 changes: 16 additions & 0 deletions elf/mold.h
Original file line number Diff line number Diff line change
Expand Up @@ -873,6 +873,20 @@ class BuildIdSection : public Chunk<E> {
static constexpr i64 HEADER_SIZE = 16;
};

template <typename E>
class NotePackageSection : public Chunk<E> {
public:
NotePackageSection() {
this->name = ".note.package";
this->shdr.sh_type = SHT_NOTE;
this->shdr.sh_flags = SHF_ALLOC;
this->shdr.sh_addralign = 4;
}

void update_shdr(Context<E> &ctx) override;
void copy_buf(Context<E> &ctx) override;
};

template <typename E>
class NotePropertySection : public Chunk<E> {
public:
Expand Down Expand Up @@ -1609,6 +1623,7 @@ struct Context {
std::string fini = "_fini";
std::string init = "_init";
std::string output = "a.out";
std::string package_metadata;
std::string plugin;
std::string rpaths;
std::string soname;
Expand Down Expand Up @@ -1718,6 +1733,7 @@ struct Context {
std::unique_ptr<VerneedSection<E>> verneed;
std::unique_ptr<VerdefSection<E>> verdef;
std::unique_ptr<BuildIdSection<E>> buildid;
std::unique_ptr<NotePackageSection<E>> note_package;
std::unique_ptr<NotePropertySection<E>> note_property;
std::unique_ptr<GdbIndexSection<E>> gdb_index;
std::unique_ptr<ThumbToArmSection> thumb_to_arm;
Expand Down
21 changes: 21 additions & 0 deletions elf/output-chunks.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2025,6 +2025,26 @@ void BuildIdSection<E>::write_buildid(Context<E> &ctx) {
}
}

template <typename E>
void NotePackageSection<E>::update_shdr(Context<E> &ctx) {
if (!ctx.arg.package_metadata.empty()) {
// +17 is for the header and the NUL terminator
this->shdr.sh_size = align_to(ctx.arg.package_metadata.size() + 17, 4);
}
}

template <typename E>
void NotePackageSection<E>::copy_buf(Context<E> &ctx) {
u32 *buf = (u32 *)(ctx.buf + this->shdr.sh_offset);
memset(buf, 0, this->shdr.sh_size);

buf[0] = 4; // Name size
buf[1] = this->shdr.sh_size - 16; // Content size
buf[2] = NT_FDO_PACKAGING_METADATA; // Type
memcpy(buf + 3, "FDO", 4); // Name
write_string(buf + 4, ctx.arg.package_metadata); // Content
}

template <typename E>
void NotePropertySection<E>::update_shdr(Context<E> &ctx) {
features = -1;
Expand Down Expand Up @@ -2557,6 +2577,7 @@ void RelocSection<E>::copy_buf(Context<E> &ctx) {
template class VerneedSection<E>; \
template class VerdefSection<E>; \
template class BuildIdSection<E>; \
template class NotePackageSection<E>; \
template class NotePropertySection<E>; \
template class GdbIndexSection<E>; \
template class GabiCompressedSection<E>; \
Expand Down
1 change: 1 addition & 0 deletions elf/passes.cc
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ void create_synthetic_sections(Context<E> &ctx) {

ctx.versym = push(new VersymSection<E>);
ctx.verneed = push(new VerneedSection<E>);
ctx.note_package = push(new NotePackageSection<E>);
ctx.note_property = push(new NotePropertySection<E>);

if constexpr (std::is_same_v<E, ARM32>) {
Expand Down
26 changes: 26 additions & 0 deletions test/elf/package-metadata.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#!/bin/bash
export LC_ALL=C
set -e
CC="${CC:-cc}"
CXX="${CXX:-c++}"
GCC="${GCC:-gcc}"
GXX="${GXX:-g++}"
OBJDUMP="${OBJDUMP:-objdump}"
MACHINE="${MACHINE:-$(uname -m)}"
testname=$(basename "$0" .sh)
echo -n "Testing $testname ... "
cd "$(dirname "$0")"/../..
t=out/test/elf/$testname
mkdir -p $t

cat <<EOF | $CC -o $t/a.o -c -xc -
#include <stdio.h>
int main() {
printf("Hello world\n");
}
EOF

$CC -B. -o $t/exe $t/a.o -Wl,-package-metadata='{"foo":"bar"}'
readelf -x .note.package $t/exe | fgrep -q '{"foo":"bar"}'

This comment was marked as resolved.

Copy link
@bluca

bluca May 26, 2022

note that this won't work if binutils/readelf doesn't know how to pretty-print the FDO note. With older versions the output looks like:

Displaying notes found in: .note.package
  Owner                Data size 	Description
  FDO                  0x00000010	Unknown note type: (0xcafe1a7e)
   description data: 7b 22 66 6f 6f 22 3a 22 62 61 72 22 7d 00 00 00

This comment has been minimized.

Copy link
@rui314

rui314 May 26, 2022

Author Owner

To workaround that issue, I used -x.


echo OK

0 comments on commit e9f6715

Please sign in to comment.