Skip to content

Commit 447e099

Browse files
rui314claude
andcommitted
Add hidden --use-android-relr-tags option
Pre-Android-12 (API 30 and earlier) bionic loaders predate the official ELF gABI assignment of DT_RELR/DT_RELRSZ/DT_RELRENT and use legacy OS-specific tag values DT_ANDROID_RELR (0x6fffe000), DT_ANDROID_RELRSZ (0x6fffe001), DT_ANDROID_RELRENT (0x6fffe003), and section type SHT_ANDROID_RELR (0x6fffff00). With --use-android-relr-tags, mold emits those instead of the standard ones so binaries linked with --pack-dyn-relocs=relr can be loaded on those older devices. The flag is undocumented (not listed in --help) since it's only relevant to shipping to legacy Android targets. #1544 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 128f790 commit 447e099

6 files changed

Lines changed: 63 additions & 6 deletions

File tree

src/cmdline.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1012,6 +1012,10 @@ std::vector<std::string> parse_nonpositional_args(Context<E> &ctx) {
10121012
read_z_flag("nopack-relative-relocs")) {
10131013
ctx.arg.pack_dyn_relocs_relr = false;
10141014
ctx.arg.pack_dyn_relocs_android = false;
1015+
} else if (read_flag("use-android-relr-tags")) {
1016+
ctx.arg.use_android_relr_tags = true;
1017+
} else if (read_flag("no-use-android-relr-tags")) {
1018+
ctx.arg.use_android_relr_tags = false;
10151019
} else if (read_arg("package-metadata")) {
10161020
ctx.arg.package_metadata = parse_package_metadata(ctx, arg);
10171021
} else if (read_flag("stats")) {

src/elf.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ enum : u32 {
8484
SHT_ANDROID_REL = 0x60000001,
8585
SHT_ANDROID_RELA = 0x60000002,
8686
SHT_LLVM_ADDRSIG = 0x6fff4c03,
87+
SHT_ANDROID_RELR = 0x6fffff00,
8788
SHT_GNU_HASH = 0x6ffffff6,
8889
SHT_GNU_VERDEF = 0x6ffffffd,
8990
SHT_GNU_VERNEED = 0x6ffffffe,
@@ -291,6 +292,9 @@ enum : u32 {
291292
DT_ANDROID_RELSZ = 0x60000010,
292293
DT_ANDROID_RELA = 0x60000011,
293294
DT_ANDROID_RELASZ = 0x60000012,
295+
DT_ANDROID_RELR = 0x6fffe000,
296+
DT_ANDROID_RELRSZ = 0x6fffe001,
297+
DT_ANDROID_RELRENT = 0x6fffe003,
294298
DT_GNU_HASH = 0x6ffffef5,
295299
DT_DEPAUDIT = 0x6ffffefb,
296300
DT_AUDIT = 0x6ffffefc,

src/mold.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -983,9 +983,9 @@ class RelDynSection : public Chunk<E> {
983983
template <typename E>
984984
class RelrDynSection : public Chunk<E> {
985985
public:
986-
RelrDynSection() {
986+
RelrDynSection(Context<E> &ctx) {
987987
this->name = ".relr.dyn";
988-
this->shdr.sh_type = SHT_RELR;
988+
this->shdr.sh_type = ctx.arg.use_android_relr_tags ? SHT_ANDROID_RELR : SHT_RELR;
989989
this->shdr.sh_flags = SHF_ALLOC;
990990
this->shdr.sh_entsize = sizeof(Word<E>);
991991
this->shdr.sh_addralign = sizeof(Word<E>);
@@ -2392,6 +2392,7 @@ struct Context {
23922392
bool suppress_warnings = false;
23932393
bool trace = false;
23942394
bool undefined_version = false;
2395+
bool use_android_relr_tags = false;
23952396
bool warn_common = false;
23962397
bool warn_once = false;
23972398
bool warn_textrel = false;

src/output-chunks.cc

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -698,9 +698,15 @@ static std::vector<Word<E>> create_dynamic_section(Context<E> &ctx) {
698698
}
699699

700700
if (ctx.relrdyn) {
701-
define(DT_RELR, ctx.relrdyn->shdr.sh_addr);
702-
define(DT_RELRSZ, ctx.relrdyn->shdr.sh_size);
703-
define(DT_RELRENT, ctx.relrdyn->shdr.sh_entsize);
701+
if (ctx.arg.use_android_relr_tags) {
702+
define(DT_ANDROID_RELR, ctx.relrdyn->shdr.sh_addr);
703+
define(DT_ANDROID_RELRSZ, ctx.relrdyn->shdr.sh_size);
704+
define(DT_ANDROID_RELRENT, ctx.relrdyn->shdr.sh_entsize);
705+
} else {
706+
define(DT_RELR, ctx.relrdyn->shdr.sh_addr);
707+
define(DT_RELRSZ, ctx.relrdyn->shdr.sh_size);
708+
define(DT_RELRENT, ctx.relrdyn->shdr.sh_entsize);
709+
}
704710
}
705711

706712
if (ctx.relplt->shdr.sh_size) {

src/passes.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ void create_synthetic_sections(Context<E> &ctx) {
143143
ctx.relplt = push(new RelPltSection<E>);
144144

145145
if (ctx.arg.pack_dyn_relocs_relr)
146-
ctx.relrdyn = push(new RelrDynSection<E>);
146+
ctx.relrdyn = push(new RelrDynSection<E>(ctx));
147147

148148
ctx.strtab = push(new StrtabSection<E>);
149149
ctx.plt = push(new PltSection<E>);

test/use-android-relr-tags.sh

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#!/bin/bash
2+
. $(dirname $0)/common.inc
3+
4+
cat <<EOF | $CC -o $t/a.o -fPIC -c -xc -
5+
#include <stdio.h>
6+
int main() {
7+
printf("Hello world\n");
8+
}
9+
EOF
10+
11+
# Probe whether the host toolchain can link a PIE; skip if not.
12+
$CC -o $t/probe $t/a.o -pie 2> /dev/null || skip
13+
14+
# Default: standard DT_RELR tags (35/36/37) and SHT_RELR (19).
15+
$CC -B. -o $t/exe1 $t/a.o -pie -Wl,--pack-dyn-relocs=relr
16+
readelf -SW $t/exe1 | grep -F .relr.dyn | grep -Ew 'RELR'
17+
readelf --dynamic $t/exe1 > $t/log1
18+
grep -Ew 'RELR|<unknown>: 24' $t/log1
19+
grep -Ew 'RELRSZ|<unknown>: 23' $t/log1
20+
grep -Ew 'RELRENT|<unknown>: 25' $t/log1
21+
22+
# --use-android-relr-tags: legacy DT_ANDROID_RELR* (in the OS-specific
23+
# range) and SHT_ANDROID_RELR section type, for compatibility with
24+
# pre-Android-12 loaders that don't recognize the standard tags.
25+
$CC -B. -o $t/exe2 $t/a.o -pie \
26+
-Wl,--pack-dyn-relocs=relr -Wl,--use-android-relr-tags
27+
readelf -SW $t/exe2 | grep -F .relr.dyn | grep -Ev '\bRELR\b'
28+
readelf --dynamic $t/exe2 > $t/log2
29+
grep -E '0x0*6fffe000\b' $t/log2
30+
grep -E '0x0*6fffe001\b' $t/log2
31+
grep -E '0x0*6fffe003\b' $t/log2
32+
# Make sure the standard tags are NOT emitted in this mode.
33+
not grep -Ew 'RELR|<unknown>: 24' $t/log2
34+
not grep -Ew 'RELRSZ|<unknown>: 23' $t/log2
35+
not grep -Ew 'RELRENT|<unknown>: 25' $t/log2
36+
37+
# --no-use-android-relr-tags reverts to the standard tags.
38+
$CC -B. -o $t/exe3 $t/a.o -pie \
39+
-Wl,--pack-dyn-relocs=relr \
40+
-Wl,--use-android-relr-tags -Wl,--no-use-android-relr-tags
41+
readelf --dynamic $t/exe3 > $t/log3
42+
grep -Ew 'RELR|<unknown>: 24' $t/log3

0 commit comments

Comments
 (0)