diff --git a/cmdline.cc b/cmdline.cc index a836cf0b..d9454916 100644 --- a/cmdline.cc +++ b/cmdline.cc @@ -372,6 +372,8 @@ void parse_nonpositional_args(Context &ctx, ctx.arg.z_delete = false; } else if (read_z_flag(args, "nocopyreloc")) { ctx.arg.z_copyreloc = false; + } else if (read_z_flag(args, "initfirst")) { + ctx.arg.z_initfirst = true; } else if (read_flag(args, "no-undefined")) { ctx.arg.z_defs = true; } else if (read_flag(args, "fatal-warnings")) { diff --git a/elf.h b/elf.h index 664359c3..5f63ef9e 100644 --- a/elf.h +++ b/elf.h @@ -182,6 +182,7 @@ static constexpr u32 DF_STATIC_TLS = 0x10; static constexpr u32 DF_1_NOW = 0x00000001; static constexpr u32 DF_1_NODELETE = 0x00000008; +static constexpr u32 DF_1_INITFIRST = 0x00000020; static constexpr u32 DF_1_NOOPEN = 0x00000040; static constexpr u32 DF_1_PIE = 0x08000000; diff --git a/mold.h b/mold.h index 790e6b93..74b02fbc 100644 --- a/mold.h +++ b/mold.h @@ -1273,6 +1273,7 @@ struct Context { bool z_delete = true; bool z_dlopen = true; bool z_execstack = false; + bool z_initfirst = false; bool z_now = false; bool z_relro = true; i16 default_version = VER_NDX_GLOBAL; diff --git a/output_chunks.cc b/output_chunks.cc index 803c8718..2a5528ef 100644 --- a/output_chunks.cc +++ b/output_chunks.cc @@ -480,6 +480,8 @@ static std::vector create_dynamic_section(Context &ctx) { flags1 |= DF_1_NOOPEN; if (!ctx.arg.z_delete) flags1 |= DF_1_NODELETE; + if (ctx.arg.z_initfirst) + flags1 |= DF_1_INITFIRST; if (ctx.has_gottp_rel) flags |= DF_STATIC_TLS; diff --git a/test/initfirst.sh b/test/initfirst.sh new file mode 100755 index 00000000..ce63a394 --- /dev/null +++ b/test/initfirst.sh @@ -0,0 +1,19 @@ +#!/bin/bash +set -e +cd $(dirname $0) +echo -n "Testing $(basename -s .sh $0) ... " +t=$(pwd)/tmp/$(basename -s .sh $0) +mkdir -p $t + +cat < + +void foo() { + printf("Hello world\n"); +} +EOF + +clang -fuse-ld=`pwd`/../mold -shared -o $t/b.so $t/a.o -Wl,-z,initfirst +readelf --dynamic $t/b.so | grep -q 'Flags: INITFIRST' + +echo OK