Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 803547d

Browse files
committedFeb 17, 2022
[ELF][LTO] Move LTO to the symbol resolution pass
ELF object files returned by do_lto() may contain unforeseen undefined symbols, so we can't call that function after the symbol resolution pass because it can cause undefined symbol errors.
1 parent a3f2a5c commit 803547d

File tree

3 files changed

+44
-32
lines changed

3 files changed

+44
-32
lines changed
 

‎elf/lto.cc

-6
Original file line numberDiff line numberDiff line change
@@ -538,12 +538,6 @@ void do_lto(Context<E> &ctx) {
538538
assert(phase == 1);
539539
phase = 2;
540540

541-
// Compute import/export information early because `get_symbols`
542-
// function needs them.
543-
apply_version_script(ctx);
544-
parse_symbol_version(ctx);
545-
compute_import_export(ctx);
546-
547541
// Set `referenced_by_regular_obj` bit.
548542
for (ObjectFile<E> *file : ctx.objs) {
549543
if (file->is_lto_obj)

‎elf/main.cc

-4
Original file line numberDiff line numberDiff line change
@@ -469,10 +469,6 @@ static int elf_main(int argc, char **argv) {
469469
// included to the final output.
470470
resolve_symbols(ctx);
471471

472-
// Do LTO
473-
if (ctx.has_lto_object)
474-
do_lto(ctx);
475-
476472
// Resolve mergeable section pieces to merge them.
477473
register_section_pieces(ctx);
478474

‎elf/passes.cc

+44-22
Original file line numberDiff line numberDiff line change
@@ -77,39 +77,61 @@ void create_synthetic_sections(Context<E> &ctx) {
7777
}
7878

7979
template <typename E>
80-
void resolve_symbols(Context<E> &ctx) {
81-
Timer t(ctx, "resolve_symbols");
82-
83-
std::vector<InputFile<E> *> files;
84-
append(files, ctx.objs);
85-
append(files, ctx.dsos);
86-
87-
// Register symbols
88-
tbb::parallel_for_each(files, [&](InputFile<E> *file) {
89-
file->resolve_symbols(ctx);
90-
});
91-
92-
// Mark reachable objects to decide which files to include
93-
// into an output.
94-
std::vector<InputFile<E> *> live_set = files;
95-
std::erase_if(live_set, [](InputFile<E> *file) { return !file->is_alive; });
96-
80+
static void mark_live_objects(Context<E> &ctx) {
9781
auto mark_symbol = [&](std::string_view name) {
9882
if (InputFile<E> *file = get_symbol(ctx, name)->file)
99-
if (!file->is_alive.exchange(true))
100-
live_set.push_back(file);
83+
file->is_alive = true;
10184
};
10285

10386
for (std::string_view name : ctx.arg.undefined)
10487
mark_symbol(name);
10588
for (std::string_view name : ctx.arg.require_defined)
10689
mark_symbol(name);
10790

108-
tbb::parallel_for_each(live_set, [&](InputFile<E> *file,
109-
tbb::feeder<InputFile<E> *> &feeder) {
110-
file->mark_live_objects(ctx, [&](InputFile<E> *obj) { feeder.add(obj); });
91+
auto mark_file = [&](InputFile<E> *file, tbb::feeder<InputFile<E> *> &feeder) {
92+
if (file->is_alive)
93+
file->mark_live_objects(ctx, [&](InputFile<E> *obj) { feeder.add(obj); });
94+
};
95+
96+
tbb::parallel_for_each(ctx.objs, mark_file);
97+
tbb::parallel_for_each(ctx.dsos, mark_file);
98+
}
99+
100+
template <typename E>
101+
void resolve_symbols(Context<E> &ctx) {
102+
Timer t(ctx, "resolve_symbols");
103+
104+
// Register symbols
105+
tbb::parallel_for_each(ctx.objs, [&](InputFile<E> *file) {
106+
file->resolve_symbols(ctx);
111107
});
112108

109+
tbb::parallel_for_each(ctx.dsos, [&](InputFile<E> *file) {
110+
file->resolve_symbols(ctx);
111+
});
112+
113+
// Do link-time optimization. We pass all IR object files to the
114+
// compiler backend to compile them into a few ELF object files.
115+
if (ctx.has_lto_object) {
116+
Timer t(ctx, "do_lto");
117+
118+
// The compiler backend needs to know how symbols are resolved,
119+
// so compute symbolvisibility, import/export bits, etc early.
120+
mark_live_objects(ctx);
121+
apply_version_script(ctx);
122+
parse_symbol_version(ctx);
123+
compute_import_export(ctx);
124+
do_lto(ctx);
125+
}
126+
127+
// Mark reachable objects to decide which files to include into an output.
128+
// This also merges symbol visibility.
129+
mark_live_objects(ctx);
130+
131+
std::vector<InputFile<E> *> files;
132+
append(files, ctx.objs);
133+
append(files, ctx.dsos);
134+
113135
// Remove symbols of eliminated files.
114136
tbb::parallel_for_each(files, [&](InputFile<E> *file) {
115137
if (!file->is_alive)

0 commit comments

Comments
 (0)
Please sign in to comment.