mirror of
https://github.com/rui314/mold.git
synced 2024-09-21 09:57:18 +03:00
112 lines
2.7 KiB
C++
112 lines
2.7 KiB
C++
#include "mold.h"
|
|
|
|
namespace mold::macho {
|
|
|
|
template <typename E>
|
|
static std::vector<Subsection<E> *> collect_root_set(Context<E> &ctx) {
|
|
std::vector<Subsection<E> *> rootset;
|
|
|
|
auto mark = [&](Symbol<E> *sym) {
|
|
if (sym && sym->subsec)
|
|
rootset.push_back(sym->subsec);
|
|
};
|
|
|
|
mark(intern(ctx, ctx.arg.entry));
|
|
|
|
if (ctx.output_type == MH_DYLIB || ctx.output_type == MH_BUNDLE)
|
|
for (ObjectFile<E> *file : ctx.objs)
|
|
for (Symbol<E> *sym : file->syms)
|
|
if (sym->file == file && sym->is_extern)
|
|
mark(sym);
|
|
|
|
return rootset;
|
|
}
|
|
|
|
template <typename E>
|
|
static void visit(Context<E> &ctx, Subsection<E> &subsec) {
|
|
if (subsec.is_alive.exchange(true))
|
|
return;
|
|
|
|
for (Relocation<E> &rel : subsec.get_rels()) {
|
|
if (rel.sym) {
|
|
if (rel.sym->subsec)
|
|
visit(ctx, *rel.sym->subsec);
|
|
} else {
|
|
visit(ctx, *rel.subsec);
|
|
}
|
|
}
|
|
|
|
for (UnwindRecord<E> &rec : subsec.get_unwind_records()) {
|
|
rec.is_alive = true;
|
|
visit(ctx, *rec.subsec);
|
|
if (rec.lsda)
|
|
visit(ctx, *rec.lsda);
|
|
if (Symbol<E> *sym = rec.personality; sym && sym->subsec)
|
|
visit(ctx, *sym->subsec);
|
|
}
|
|
}
|
|
|
|
template <typename E>
|
|
static bool refers_live_subsection(Subsection<E> &subsec) {
|
|
for (Relocation<E> &rel : subsec.get_rels()) {
|
|
if (rel.sym) {
|
|
if (!rel.sym->subsec || rel.sym->subsec->is_alive)
|
|
return true;
|
|
} else {
|
|
if (rel.subsec->is_alive)
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
template <typename E>
|
|
static void mark(Context<E> &ctx, const std::vector<Subsection<E> *> &rootset) {
|
|
for (Subsection<E> *subsec : rootset)
|
|
visit(ctx, *subsec);
|
|
|
|
bool repeat;
|
|
do {
|
|
repeat = false;
|
|
for (ObjectFile<E> *file : ctx.objs) {
|
|
for (std::unique_ptr<Subsection<E>> &subsec : file->subsections) {
|
|
if ((subsec->isec.hdr.attr & S_ATTR_LIVE_SUPPORT) &&
|
|
!subsec->is_alive &&
|
|
refers_live_subsection(*subsec)) {
|
|
visit(ctx, *subsec);
|
|
repeat = true;
|
|
}
|
|
}
|
|
}
|
|
} while (repeat);
|
|
}
|
|
|
|
template <typename E>
|
|
static void sweep(Context<E> &ctx) {
|
|
for (ObjectFile<E> *file : ctx.objs) {
|
|
erase(file->subsections, [](const std::unique_ptr<Subsection<E>> &subsec) {
|
|
return !subsec->is_alive;
|
|
});
|
|
}
|
|
|
|
for (ObjectFile<E> *file : ctx.objs)
|
|
for (Symbol<E> *&sym : file->syms)
|
|
if (sym->file == file && sym->subsec && !sym->subsec->is_alive)
|
|
sym = nullptr;
|
|
}
|
|
|
|
template <typename E>
|
|
void dead_strip(Context<E> &ctx) {
|
|
std::vector<Subsection<E> *> rootset = collect_root_set(ctx);
|
|
mark(ctx, rootset);
|
|
sweep(ctx);
|
|
}
|
|
|
|
#define INSTANTIATE(E) \
|
|
template void dead_strip(Context<E> &)
|
|
|
|
INSTANTIATE(ARM64);
|
|
INSTANTIATE(X86_64);
|
|
|
|
} // namespace mold::macho
|