mirror of
https://github.com/rui314/mold.git
synced 2024-09-21 01:47:11 +03:00
[Mach-O] Implement -dead_strip
This commit is contained in:
parent
d0138a404d
commit
433666a470
@ -2,7 +2,58 @@
|
||||
|
||||
namespace mold::macho {
|
||||
|
||||
static std::vector<Subsection *> collect_root_set(Context &ctx) {
|
||||
std::vector<Subsection *> rootset;
|
||||
|
||||
if (Symbol *sym = intern(ctx, ctx.arg.entry))
|
||||
if (sym->subsec)
|
||||
rootset.push_back(sym->subsec);
|
||||
|
||||
for (ObjectFile *file : ctx.objs)
|
||||
for (std::unique_ptr<Subsection> &subsec : file->subsections)
|
||||
if (subsec->isec.hdr.match("__TEXT", "__eh_frame") ||
|
||||
subsec->isec.hdr.match("__TEXT", "__gcc_except_tab"))
|
||||
rootset.push_back(subsec.get());
|
||||
|
||||
return rootset;
|
||||
}
|
||||
|
||||
static void visit(Context &ctx, Subsection &subsec) {
|
||||
if (subsec.is_visited.exchange(true))
|
||||
return;
|
||||
|
||||
for (Relocation &rel : subsec.get_rels()) {
|
||||
if (rel.sym) {
|
||||
if (rel.sym->subsec)
|
||||
visit(ctx, *rel.sym->subsec);
|
||||
} else {
|
||||
visit(ctx, *rel.subsec);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void mark(Context &ctx, std::span<Subsection *> rootset) {
|
||||
for (Subsection *subsec : rootset)
|
||||
visit(ctx, *subsec);
|
||||
}
|
||||
|
||||
static void sweep(Context &ctx) {
|
||||
for (ObjectFile *file : ctx.objs) {
|
||||
erase(file->subsections, [](const std::unique_ptr<Subsection> &subsec) {
|
||||
return !subsec->is_visited;
|
||||
});
|
||||
}
|
||||
|
||||
for (ObjectFile *file : ctx.objs)
|
||||
for (Symbol *&sym : file->syms)
|
||||
if (sym->file == file && sym->subsec && !sym->subsec->is_visited)
|
||||
sym = nullptr;
|
||||
}
|
||||
|
||||
void dead_strip(Context &ctx) {
|
||||
std::vector<Subsection *> rootset = collect_root_set(ctx);
|
||||
mark(ctx, rootset);
|
||||
sweep(ctx);
|
||||
}
|
||||
|
||||
} // namespace mold::macho
|
||||
|
@ -379,7 +379,7 @@ struct MachSection {
|
||||
return {sectname, strnlen(sectname, sizeof(sectname))};
|
||||
}
|
||||
|
||||
bool match(std::string_view segname, std::string_view sectname) {
|
||||
bool match(std::string_view segname, std::string_view sectname) const {
|
||||
return get_segname() == segname && get_sectname() == sectname;
|
||||
}
|
||||
|
||||
|
@ -140,7 +140,7 @@ static void export_symbols(Context &ctx) {
|
||||
|
||||
for (ObjectFile *file : ctx.objs) {
|
||||
for (Symbol *sym : file->syms) {
|
||||
if (sym->file == file) {
|
||||
if (sym && sym->file == file) {
|
||||
if (sym->flags & NEEDS_GOT)
|
||||
ctx.got.add(ctx, sym);
|
||||
if (sym->flags & NEEDS_THREAD_PTR)
|
||||
@ -151,6 +151,9 @@ static void export_symbols(Context &ctx) {
|
||||
|
||||
for (DylibFile *file : ctx.dylibs) {
|
||||
for (Symbol *sym : file->syms) {
|
||||
if (!sym)
|
||||
continue;
|
||||
|
||||
if (sym->file == file)
|
||||
if (sym->flags & NEEDS_STUB)
|
||||
ctx.stubs.add(ctx, sym);
|
||||
|
@ -177,6 +177,7 @@ public:
|
||||
u32 nunwind = 0;
|
||||
u32 raddr = -1;
|
||||
u16 p2align = 0;
|
||||
std::atomic_bool is_visited = false;
|
||||
};
|
||||
|
||||
//
|
||||
|
@ -443,11 +443,11 @@ void ObjectFile::convert_common_symbols(Context &ctx) {
|
||||
|
||||
void ObjectFile::check_duplicate_symbols(Context &ctx) {
|
||||
for (i64 i = 0; i < syms.size(); i++) {
|
||||
Symbol &sym = *syms[i];
|
||||
Symbol *sym = syms[i];
|
||||
MachSym &msym = mach_syms[i];
|
||||
if (!msym.is_undef() && !msym.is_common() && sym.file != this)
|
||||
Error(ctx) << "duplicate symbol: " << *this << ": " << *sym.file
|
||||
<< ": " << sym;
|
||||
if (sym && !msym.is_undef() && !msym.is_common() && sym->file != this)
|
||||
Error(ctx) << "duplicate symbol: " << *this << ": " << *sym->file
|
||||
<< ": " << *sym;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -723,7 +723,7 @@ void ExportEncoder::write_trie(u8 *start, TrieNode &node) {
|
||||
void OutputExportSection::compute_size(Context &ctx) {
|
||||
for (ObjectFile *file : ctx.objs)
|
||||
for (Symbol *sym : file->syms)
|
||||
if (sym->is_extern && sym->file == file)
|
||||
if (sym && sym->is_extern && sym->file == file)
|
||||
enc.add(sym->name, 0, sym->get_addr(ctx) - PAGE_ZERO_SIZE);
|
||||
|
||||
hdr.size = align_to(enc.finish(), 8);
|
||||
@ -736,9 +736,10 @@ void OutputExportSection::copy_buf(Context &ctx) {
|
||||
void OutputFunctionStartsSection::compute_size(Context &ctx) {
|
||||
std::vector<u64> addrs;
|
||||
|
||||
for (ObjectFile *obj : ctx.objs)
|
||||
for (Symbol *sym : obj->syms)
|
||||
if (sym->file == obj && sym->subsec && &sym->subsec->isec.osec == ctx.text)
|
||||
for (ObjectFile *file : ctx.objs)
|
||||
for (Symbol *sym : file->syms)
|
||||
if (sym && sym->file == file && sym->subsec &&
|
||||
&sym->subsec->isec.osec == ctx.text)
|
||||
addrs.push_back(sym->get_addr(ctx));
|
||||
|
||||
std::sort(addrs.begin(), addrs.end());
|
||||
@ -762,16 +763,16 @@ void OutputFunctionStartsSection::copy_buf(Context &ctx) {
|
||||
}
|
||||
|
||||
void OutputSymtabSection::compute_size(Context &ctx) {
|
||||
for (ObjectFile *obj : ctx.objs)
|
||||
for (Symbol *sym : obj->syms)
|
||||
if (sym->file == obj)
|
||||
for (ObjectFile *file : ctx.objs)
|
||||
for (Symbol *sym : file->syms)
|
||||
if (sym && sym->file == file)
|
||||
globals.push_back({sym, ctx.strtab.add_string(sym->name)});
|
||||
|
||||
i64 idx = globals.size();
|
||||
|
||||
for (DylibFile *dylib : ctx.dylibs) {
|
||||
for (Symbol *sym : dylib->syms) {
|
||||
if (sym->file == dylib) {
|
||||
if (sym && sym->file == dylib) {
|
||||
if (sym->stub_idx != -1 || sym->got_idx != -1) {
|
||||
undefs.push_back({sym, ctx.strtab.add_string(sym->name)});
|
||||
|
||||
|
@ -27,5 +27,8 @@ EOF
|
||||
|
||||
clang -fuse-ld=$mold -o $t/exe $t/a.o -Wl,-dead_strip
|
||||
$t/exe | grep -q 'Hello world'
|
||||
otool -tVj $t/exe > $t/log
|
||||
grep -q 'hello:' $t/log
|
||||
! grep -q 'howdy:' $t/log || false
|
||||
|
||||
echo OK
|
||||
|
Loading…
Reference in New Issue
Block a user