Skip to content

Commit

Permalink
Support -z rodynamic
Browse files Browse the repository at this point in the history
LLVM lld supports the flag.

Fixes #1253
  • Loading branch information
rui314 committed May 5, 2024
1 parent 7b2cb47 commit 9a233df
Show file tree
Hide file tree
Showing 6 changed files with 40 additions and 6 deletions.
3 changes: 3 additions & 0 deletions docs/mold.md
Original file line number Diff line number Diff line change
Expand Up @@ -714,6 +714,9 @@ but as `-o magic`.
`.text.exit` as separate sections in the final binary instead of merging
them as `.text`.

* `-z rodynamic`
Make the `.dynamic` section read-only.

* `-z relro`, `-z norelro`:
Some sections such as `.dynamic` have to be writable only during an
executable or a shared library file is being loaded to memory. Once the
Expand Down
3 changes: 3 additions & 0 deletions elf/cmdline.cc
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ inline const char helpmsg[] = R"(
-z stack-size=VALUE Set the size of the stack segment
-z relro Make some sections read-only after relocation (default)
-z norelro
-z rodynamic Make the .dynamic section read-only
-z text Report error if DT_TEXTREL is set
-z notext
-z textoff
Expand Down Expand Up @@ -1008,6 +1009,8 @@ std::vector<std::string> parse_nonpositional_args(Context<E> &ctx) {
ctx.arg.z_sectionheader = false;
} else if (read_z_flag("rewrite-endbr")) {
ctx.arg.z_rewrite_endbr = true;
} else if (read_z_flag("rodynamic")) {
ctx.arg.z_rodynamic = true;
} else if (read_flag("no-undefined")) {
ctx.arg.z_defs = true;
} else if (read_flag("nmagic")) {
Expand Down
13 changes: 10 additions & 3 deletions elf/mold.h
Original file line number Diff line number Diff line change
Expand Up @@ -690,13 +690,19 @@ class DynstrSection : public Chunk<E> {
template <typename E>
class DynamicSection : public Chunk<E> {
public:
DynamicSection() {
DynamicSection(Context<E> &ctx) {
this->name = ".dynamic";
this->is_relro = true;
this->shdr.sh_type = SHT_DYNAMIC;
this->shdr.sh_flags = SHF_ALLOC | SHF_WRITE;
this->shdr.sh_addralign = sizeof(Word<E>);
this->shdr.sh_entsize = sizeof(ElfDyn<E>);

if (ctx.arg.z_rodynamic) {
this->shdr.sh_flags = SHF_ALLOC;
this->is_relro = false;
} else {
this->shdr.sh_flags = SHF_ALLOC | SHF_WRITE;
this->is_relro = true;
}
}

void update_shdr(Context<E> &ctx) override;
Expand Down Expand Up @@ -1754,6 +1760,7 @@ struct Context {
bool z_origin = false;
bool z_relro = true;
bool z_rewrite_endbr = false;
bool z_rodynamic = false;
bool z_sectionheader = true;
bool z_shstk = false;
bool z_start_stop_visibility_protected = false;
Expand Down
4 changes: 2 additions & 2 deletions elf/output-chunks.cc
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ static std::vector<ElfPhdr<E>> create_phdr(Context<E> &ctx) {

// Add PT_DYNAMIC
if (ctx.dynamic && ctx.dynamic->shdr.sh_size)
define(PT_DYNAMIC, PF_R | PF_W, ctx.dynamic);
define(PT_DYNAMIC, to_phdr_flags(ctx, ctx.dynamic), ctx.dynamic);

// Add PT_GNU_EH_FRAME
if (ctx.eh_frame_hdr)
Expand Down Expand Up @@ -841,7 +841,7 @@ static std::vector<Word<E>> create_dynamic_section(Context<E> &ctx) {

// GDB needs a DT_DEBUG entry in an executable to store a word-size
// data for its own purpose. Its content is not important.
if (!ctx.arg.shared)
if (!ctx.arg.shared && !ctx.arg.z_rodynamic)
define(DT_DEBUG, 0);

define(DT_NULL, 0);
Expand Down
2 changes: 1 addition & 1 deletion elf/passes.cc
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ void create_synthetic_sections(Context<E> &ctx) {
ctx.eh_frame_reloc = push(new EhFrameRelocSection<E>);

if (ctx.arg.shared || !ctx.dsos.empty() || ctx.arg.pie) {
ctx.dynamic = push(new DynamicSection<E>);
ctx.dynamic = push(new DynamicSection<E>(ctx));

// If .dynamic exists, .dynsym and .dynstr must exist as well
// since .dynamic refers to them.
Expand Down
21 changes: 21 additions & 0 deletions test/elf/z-rodynamic.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!/bin/bash
. $(dirname $0)/common.inc

# Executables built with `-z rodynamic` crash on qemu-user for
# PowerPC for some reason.
[[ $MACHINE = ppc* ]] && skip

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

$CC -B. -o $t/exe1 $t/a.o
readelf -WS $t/exe1 | grep -q '\.dynamic.* WA '
$QEMU $t/exe1 | grep -q 'Hello world'

$CC -B. -o $t/exe2 $t/a.o -Wl,-z,rodynamic
readelf -WS $t/exe2 | grep -q '\.dynamic.* A '
$QEMU $t/exe2 | grep -q 'Hello world'

0 comments on commit 9a233df

Please sign in to comment.