Skip to content

Commit

Permalink
[ELF][i386] Sort .ctors and .dtors sections
Browse files Browse the repository at this point in the history
  • Loading branch information
rui314 committed Apr 3, 2022
1 parent 4e10ee7 commit 392781a
Show file tree
Hide file tree
Showing 8 changed files with 47 additions and 10 deletions.
4 changes: 4 additions & 0 deletions elf/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -549,6 +549,10 @@ static int elf_main(int argc, char **argv) {
// a special rule. Sort them.
sort_init_fini(ctx);

// Likewise, .ctors and .dtors have to be sorted. They are rare
// because they are superceded by .init_array/.fini_array, though.
sort_ctor_dtor(ctx);

// Handle --shuffle-sections
if (ctx.arg.shuffle_sections != SHUFFLE_SECTIONS_NONE)
shuffle_sections(ctx);
Expand Down
1 change: 1 addition & 0 deletions elf/mold.h
Original file line number Diff line number Diff line change
Expand Up @@ -1277,6 +1277,7 @@ template <typename E> void print_dependencies_full(Context<E> &);
template <typename E> void write_repro_file(Context<E> &);
template <typename E> void check_duplicate_symbols(Context<E> &);
template <typename E> void sort_init_fini(Context<E> &);
template <typename E> void sort_ctor_dtor(Context<E> &);
template <typename E> void shuffle_sections(Context<E> &);
template <typename E> std::vector<Chunk<E> *>
collect_output_sections(Context<E> &);
Expand Down
1 change: 1 addition & 0 deletions elf/output-chunks.cc
Original file line number Diff line number Diff line change
Expand Up @@ -768,6 +768,7 @@ static std::string_view get_output_name(Context<E> &ctx, std::string_view name)
static std::string_view prefixes[] = {
".text.", ".data.rel.ro.", ".data.", ".rodata.", ".bss.rel.ro.", ".bss.",
".init_array.", ".fini_array.", ".tbss.", ".tdata.", ".gcc_except_table.",
".ctors.", ".dtors.",
};

for (std::string_view prefix : prefixes) {
Expand Down
43 changes: 41 additions & 2 deletions elf/passes.cc
Original file line number Diff line number Diff line change
Expand Up @@ -634,7 +634,7 @@ void sort_init_fini(Context<E> &ctx) {
Timer t(ctx, "sort_init_fini");

auto get_priority = [](InputSection<E> *isec) {
static std::regex re(R"(_array\.(\d+)$)", std::regex_constants::optimize);
static std::regex re(R"(\.(\d+)$)", std::regex_constants::optimize);
std::string name = isec->name().begin();
std::smatch m;
if (std::regex_search(name, m, re))
Expand All @@ -654,6 +654,43 @@ void sort_init_fini(Context<E> &ctx) {
}
}

template <typename E>
void sort_ctor_dtor(Context<E> &ctx) {
Timer t(ctx, "sort_ctor_dtor");

auto get_priority = [](InputSection<E> *isec) {
auto opts = std::regex_constants::optimize | std::regex_constants::ECMAScript;
static std::regex re1(R"((?:clang_rt\.)?crtbegin)", opts);
static std::regex re2(R"((?:clang_rt\.)?crtend)", opts);
static std::regex re3(R"(\.(\d+)$)", opts);

// crtbegin.o and crtend.o contain marker symbols such as
// __CTOR_LIST__ or __DTOR_LIST__. So they have to be at the
// beginning or end of the section.
std::smatch m;
if (std::regex_search(isec->file.filename, m, re1))
return -2;
if (std::regex_search(isec->file.filename, m, re2))
return 65536;

std::string name(isec->name());
if (std::regex_search(name, m, re3))
return std::stoi(m[1]);
return -1;
};

for (std::unique_ptr<OutputSection<E>> &osec : ctx.output_sections) {
if (osec->name == ".ctors" || osec->name == ".dtors") {
if (ctx.arg.shuffle_sections != SHUFFLE_SECTIONS_REVERSE)
std::reverse(osec->members.begin(), osec->members.end());

sort(osec->members, [&](InputSection<E> *a, InputSection<E> *b) {
return get_priority(a) < get_priority(b);
});
}
}
}

template <typename T>
static void shuffle(std::vector<T> &vec, u64 seed) {
if (vec.empty())
Expand Down Expand Up @@ -686,7 +723,8 @@ void shuffle_sections(Context<E> &ctx) {

auto is_eligible = [](OutputSection<E> &osec) {
return osec.name != ".init" && osec.name != ".fini" &&
osec.name != ".init_array" && osec.name != ".fini_array";
osec.name != ".init_array" && osec.name != ".fini_array" &&
osec.name != ".ctors" && osec.name != ".dtors";
};

switch (ctx.arg.shuffle_sections) {
Expand Down Expand Up @@ -1485,6 +1523,7 @@ void write_dependency_file(Context<E> &ctx) {
template void write_repro_file(Context<E> &); \
template void check_duplicate_symbols(Context<E> &); \
template void sort_init_fini(Context<E> &); \
template void sort_ctor_dtor(Context<E> &); \
template void shuffle_sections(Context<E> &); \
template std::vector<Chunk<E> *> collect_output_sections(Context<E> &); \
template void compute_section_sizes(Context<E> &); \
Expand Down
2 changes: 0 additions & 2 deletions test/elf/init-array-priorities.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ mold="$(pwd)/mold"
t=out/test/elf/$testname
mkdir -p $t

[ $MACHINE = i386 ] && { echo skipped; exit; }

# musl does not support GNU-style init/fini priorities
echo 'int main() {}' | $CC -o $t/exe -xc -
readelf --dynamic $t/exe | grep -q ld-musl && { echo skipped; exit; }
Expand Down
2 changes: 0 additions & 2 deletions test/elf/reverse-sections.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ mold="$(pwd)/mold"
t=out/test/elf/$testname
mkdir -p $t

[ $MACHINE = i386 ] && { echo skipped; exit; }

cat <<EOF | $CC -o $t/a.o -c -xc++ -
#include <iostream>
static struct Foo1 {
Expand Down
2 changes: 0 additions & 2 deletions test/elf/shuffle-sections-seed.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ mold="$(pwd)/mold"
t=out/test/elf/$testname
mkdir -p $t

[ $MACHINE = i386 ] && { echo skipped; exit; }

cat <<EOF | $CC -o $t/a.o -ffunction-sections -c -xc -
#include <stdio.h>
int main() {
Expand Down
2 changes: 0 additions & 2 deletions test/elf/shuffle-sections.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ mold="$(pwd)/mold"
t=out/test/elf/$testname
mkdir -p $t

[ $MACHINE = i386 ] && { echo skipped; exit; }

cat <<EOF | $CC -o $t/a.o -ffunction-sections -c -xc -
#include <stdio.h>
int main() {
Expand Down

0 comments on commit 392781a

Please sign in to comment.