mirror of
https://github.com/rui314/mold.git
synced 2024-11-14 07:18:42 +03:00
[Mach-O] wip
This commit is contained in:
parent
ec5c85dcc7
commit
3c297c2254
@ -32,6 +32,54 @@ static void create_internal_file(Context &ctx) {
|
||||
sym->value = PAGE_ZERO_SIZE;
|
||||
}
|
||||
|
||||
static bool compare_chunks(const Chunk *a, const Chunk *b) {
|
||||
assert(a->hdr.get_segname() == b->hdr.get_segname());
|
||||
|
||||
if ((a->hdr.type == S_ZEROFILL) != (b->hdr.type == S_ZEROFILL))
|
||||
return a->hdr.type != S_ZEROFILL;
|
||||
|
||||
static const std::string_view rank[] = {
|
||||
// __TEXT
|
||||
"__mach_header",
|
||||
"__text",
|
||||
"__stubs",
|
||||
"__stub_helper",
|
||||
"__cstring",
|
||||
"__unwind_info",
|
||||
// __DATA_CONST
|
||||
"__got",
|
||||
// __DATA
|
||||
"__la_symbol_ptr"
|
||||
"__data",
|
||||
"__common",
|
||||
"__bss",
|
||||
// __LINKEDIT
|
||||
"__rebase",
|
||||
"__binding",
|
||||
"__lazy_binding",
|
||||
"__export",
|
||||
"__func_starts",
|
||||
"__symbol_table",
|
||||
"__ind_sym_tab",
|
||||
"__string_table",
|
||||
};
|
||||
|
||||
auto get_rank = [](const Chunk *chunk) -> i64 {
|
||||
std::string_view name = chunk->hdr.get_sectname();
|
||||
i64 i = 0;
|
||||
for (; i < sizeof(rank) / sizeof(rank[0]); i++)
|
||||
if (name == rank[i])
|
||||
return i;
|
||||
return INT_MAX;
|
||||
};
|
||||
|
||||
i64 ra = get_rank(a);
|
||||
i64 rb = get_rank(b);
|
||||
if (ra == INT_MAX && rb == INT_MAX)
|
||||
return a->hdr.get_sectname() < b->hdr.get_sectname();
|
||||
return ra < rb;
|
||||
}
|
||||
|
||||
static void create_synthetic_chunks(Context &ctx) {
|
||||
for (ObjectFile *obj : ctx.objs) {
|
||||
for (std::unique_ptr<InputSection> &isec : obj->sections) {
|
||||
@ -41,31 +89,18 @@ static void create_synthetic_chunks(Context &ctx) {
|
||||
}
|
||||
}
|
||||
|
||||
ctx.text_seg->chunks.push_back(&ctx.mach_hdr);
|
||||
ctx.text_seg->chunks.push_back(ctx.text);
|
||||
ctx.text_seg->chunks.push_back(&ctx.stubs);
|
||||
ctx.text_seg->chunks.push_back(&ctx.stub_helper);
|
||||
ctx.text_seg->chunks.push_back(ctx.cstring);
|
||||
ctx.text_seg->chunks.push_back(&ctx.unwind_info);
|
||||
for (Chunk *chunk : ctx.chunks) {
|
||||
if (chunk != ctx.data && chunk->is_regular &&
|
||||
((OutputSection *)chunk)->members.empty())
|
||||
continue;
|
||||
|
||||
ctx.data_const_seg->chunks.push_back(&ctx.got);
|
||||
OutputSegment *seg =
|
||||
OutputSegment::get_instance(ctx, chunk->hdr.get_segname());
|
||||
seg->chunks.push_back(chunk);
|
||||
}
|
||||
|
||||
ctx.data_seg->chunks.push_back(&ctx.lazy_symbol_ptr);
|
||||
ctx.data_seg->chunks.push_back(ctx.data);
|
||||
|
||||
if (!ctx.common->members.empty())
|
||||
ctx.data_seg->chunks.push_back(ctx.common);
|
||||
if (!ctx.bss->members.empty())
|
||||
ctx.data_seg->chunks.push_back(ctx.bss);
|
||||
|
||||
ctx.linkedit_seg->chunks.push_back(&ctx.rebase);
|
||||
ctx.linkedit_seg->chunks.push_back(&ctx.bind);
|
||||
ctx.linkedit_seg->chunks.push_back(&ctx.lazy_bind);
|
||||
ctx.linkedit_seg->chunks.push_back(&ctx.export_);
|
||||
ctx.linkedit_seg->chunks.push_back(&ctx.function_starts);
|
||||
ctx.linkedit_seg->chunks.push_back(&ctx.symtab);
|
||||
ctx.linkedit_seg->chunks.push_back(&ctx.indir_symtab);
|
||||
ctx.linkedit_seg->chunks.push_back(&ctx.strtab);
|
||||
for (std::unique_ptr<OutputSegment> &seg : ctx.segments)
|
||||
sort(seg->chunks, compare_chunks);
|
||||
}
|
||||
|
||||
static void export_symbols(Context &ctx) {
|
||||
|
93
macho/mold.h
93
macho/mold.h
@ -211,11 +211,7 @@ private:
|
||||
|
||||
class Chunk {
|
||||
public:
|
||||
Chunk(std::string_view segname, std::string_view sectname) {
|
||||
hdr.set_segname(segname);
|
||||
hdr.set_sectname(sectname);
|
||||
}
|
||||
|
||||
inline Chunk(Context &ctx, std::string_view segname, std::string_view sectname);
|
||||
virtual ~Chunk() = default;
|
||||
virtual void compute_size(Context &ctx) {};
|
||||
virtual void copy_buf(Context &ctx) {}
|
||||
@ -226,9 +222,11 @@ public:
|
||||
bool is_regular = false;
|
||||
};
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const Chunk &chunk);
|
||||
|
||||
class OutputMachHeader : public Chunk {
|
||||
public:
|
||||
OutputMachHeader() : Chunk("__TEXT", "__mach_header") {
|
||||
OutputMachHeader(Context &ctx) : Chunk(ctx, "__TEXT", "__mach_header") {
|
||||
is_hidden = true;
|
||||
}
|
||||
|
||||
@ -241,8 +239,8 @@ public:
|
||||
static OutputSection *
|
||||
get_instance(Context &ctx, std::string_view segname, std::string_view sectname);
|
||||
|
||||
OutputSection(std::string_view segname, std::string_view sectname)
|
||||
: Chunk(segname, sectname) {
|
||||
OutputSection(Context &ctx, std::string_view segname, std::string_view sectname)
|
||||
: Chunk(ctx, segname, sectname) {
|
||||
is_regular = true;
|
||||
}
|
||||
|
||||
@ -274,7 +272,8 @@ private:
|
||||
|
||||
class OutputRebaseSection : public Chunk {
|
||||
public:
|
||||
OutputRebaseSection() : Chunk("__LINKEDIT", "__rebase") {
|
||||
OutputRebaseSection(Context &ctx)
|
||||
: Chunk(ctx, "__LINKEDIT", "__rebase") {
|
||||
is_hidden = true;
|
||||
}
|
||||
|
||||
@ -303,7 +302,8 @@ private:
|
||||
|
||||
class OutputBindSection : public Chunk {
|
||||
public:
|
||||
OutputBindSection() : Chunk("__LINKEDIT", "__binding") {
|
||||
OutputBindSection(Context &ctx)
|
||||
: Chunk(ctx, "__LINKEDIT", "__binding") {
|
||||
is_hidden = true;
|
||||
}
|
||||
|
||||
@ -315,7 +315,8 @@ public:
|
||||
|
||||
class OutputLazyBindSection : public Chunk {
|
||||
public:
|
||||
OutputLazyBindSection() : Chunk("__LINKEDIT", "__lazy_binding") {
|
||||
OutputLazyBindSection(Context &ctx)
|
||||
: Chunk(ctx, "__LINKEDIT", "__lazy_binding") {
|
||||
is_hidden = true;
|
||||
}
|
||||
|
||||
@ -363,7 +364,8 @@ private:
|
||||
|
||||
class OutputExportSection : public Chunk {
|
||||
public:
|
||||
OutputExportSection() : Chunk("__LINKEDIT", "__export") {
|
||||
OutputExportSection(Context &ctx)
|
||||
: Chunk(ctx, "__LINKEDIT", "__export") {
|
||||
is_hidden = true;
|
||||
}
|
||||
|
||||
@ -376,7 +378,8 @@ private:
|
||||
|
||||
class OutputFunctionStartsSection : public Chunk {
|
||||
public:
|
||||
OutputFunctionStartsSection() : Chunk("__LINKEDIT", "__func_starts") {
|
||||
OutputFunctionStartsSection(Context &ctx)
|
||||
: Chunk(ctx, "__LINKEDIT", "__func_starts") {
|
||||
is_hidden = true;
|
||||
}
|
||||
|
||||
@ -388,7 +391,8 @@ public:
|
||||
|
||||
class OutputSymtabSection : public Chunk {
|
||||
public:
|
||||
OutputSymtabSection() : Chunk("__LINKEDIT", "__symbol_table") {
|
||||
OutputSymtabSection(Context &ctx)
|
||||
: Chunk(ctx, "__LINKEDIT", "__symbol_table") {
|
||||
is_hidden = true;
|
||||
hdr.p2align = __builtin_ctz(8);
|
||||
}
|
||||
@ -408,7 +412,8 @@ public:
|
||||
|
||||
class OutputStrtabSection : public Chunk {
|
||||
public:
|
||||
OutputStrtabSection() : Chunk("__LINKEDIT", "__string_table") {
|
||||
OutputStrtabSection(Context &ctx)
|
||||
: Chunk(ctx, "__LINKEDIT", "__string_table") {
|
||||
is_hidden = true;
|
||||
hdr.p2align = __builtin_ctz(8);
|
||||
}
|
||||
@ -422,7 +427,8 @@ public:
|
||||
|
||||
class OutputIndirectSymtabSection : public Chunk {
|
||||
public:
|
||||
OutputIndirectSymtabSection() : Chunk("__LINKEDIT", "__ind_sym_tab") {
|
||||
OutputIndirectSymtabSection(Context &ctx)
|
||||
: Chunk(ctx, "__LINKEDIT", "__ind_sym_tab") {
|
||||
is_hidden = true;
|
||||
}
|
||||
|
||||
@ -442,8 +448,7 @@ public:
|
||||
|
||||
class StubsSection : public Chunk {
|
||||
public:
|
||||
StubsSection();
|
||||
|
||||
StubsSection(Context &ctx);
|
||||
void add(Context &ctx, Symbol *sym);
|
||||
void copy_buf(Context &ctx) override;
|
||||
|
||||
@ -455,7 +460,7 @@ public:
|
||||
|
||||
class StubHelperSection : public Chunk {
|
||||
public:
|
||||
StubHelperSection();
|
||||
StubHelperSection(Context &ctx);
|
||||
void copy_buf(Context &ctx) override;
|
||||
|
||||
static constexpr i64 HEADER_SIZE = 16;
|
||||
@ -479,7 +484,7 @@ private:
|
||||
|
||||
class UnwindInfoSection : public Chunk {
|
||||
public:
|
||||
UnwindInfoSection();
|
||||
UnwindInfoSection(Context &ctx);
|
||||
void compute_size(Context &ctx) override;
|
||||
void copy_buf(Context &ctx) override;
|
||||
|
||||
@ -488,7 +493,7 @@ public:
|
||||
|
||||
class GotSection : public Chunk {
|
||||
public:
|
||||
GotSection();
|
||||
GotSection(Context &ctx);
|
||||
void add(Context &ctx, Symbol *sym);
|
||||
void copy_buf(Context &ctx) override;
|
||||
|
||||
@ -499,7 +504,7 @@ public:
|
||||
|
||||
class LazySymbolPtrSection : public Chunk {
|
||||
public:
|
||||
LazySymbolPtrSection();
|
||||
LazySymbolPtrSection(Context &ctx);
|
||||
void copy_buf(Context &ctx) override;
|
||||
|
||||
static constexpr i64 ENTRY_SIZE = 8;
|
||||
@ -657,23 +662,23 @@ struct Context {
|
||||
OutputSegment *linkedit_seg = nullptr;
|
||||
|
||||
std::vector<std::unique_ptr<OutputSegment>> segments;
|
||||
std::vector<std::unique_ptr<Chunk>> chunks;
|
||||
std::vector<Chunk *> chunks;
|
||||
|
||||
OutputMachHeader mach_hdr;
|
||||
StubsSection stubs;
|
||||
StubHelperSection stub_helper;
|
||||
UnwindInfoSection unwind_info;
|
||||
GotSection got;
|
||||
LazySymbolPtrSection lazy_symbol_ptr;
|
||||
OutputMachHeader mach_hdr{*this};
|
||||
StubsSection stubs{*this};
|
||||
StubHelperSection stub_helper{*this};
|
||||
UnwindInfoSection unwind_info{*this};
|
||||
GotSection got{*this};
|
||||
LazySymbolPtrSection lazy_symbol_ptr{*this};
|
||||
|
||||
OutputRebaseSection rebase;
|
||||
OutputBindSection bind;
|
||||
OutputLazyBindSection lazy_bind;
|
||||
OutputExportSection export_;
|
||||
OutputFunctionStartsSection function_starts;
|
||||
OutputSymtabSection symtab;
|
||||
OutputIndirectSymtabSection indir_symtab;
|
||||
OutputStrtabSection strtab;
|
||||
OutputRebaseSection rebase{*this};
|
||||
OutputBindSection bind{*this};
|
||||
OutputLazyBindSection lazy_bind{*this};
|
||||
OutputExportSection export_{*this};
|
||||
OutputFunctionStartsSection function_starts{*this};
|
||||
OutputSymtabSection symtab{*this};
|
||||
OutputIndirectSymtabSection indir_symtab{*this};
|
||||
OutputStrtabSection strtab{*this};
|
||||
|
||||
OutputSection *text = nullptr;
|
||||
OutputSection *data = nullptr;
|
||||
@ -688,10 +693,6 @@ int main(int argc, char **argv);
|
||||
// Inline functions
|
||||
//
|
||||
|
||||
u64 UnwindRecord::get_func_addr(Context &ctx) const {
|
||||
return subsec->addr + offset;
|
||||
}
|
||||
|
||||
u64 Symbol::get_addr(Context &ctx) const {
|
||||
if (subsec)
|
||||
return subsec->addr + value;
|
||||
@ -716,4 +717,14 @@ inline std::ostream &operator<<(std::ostream &out, const Symbol &sym) {
|
||||
return out;
|
||||
}
|
||||
|
||||
Chunk::Chunk(Context &ctx, std::string_view segname, std::string_view sectname) {
|
||||
ctx.chunks.push_back(this);
|
||||
hdr.set_segname(segname);
|
||||
hdr.set_sectname(sectname);
|
||||
}
|
||||
|
||||
u64 UnwindRecord::get_func_addr(Context &ctx) const {
|
||||
return subsec->addr + offset;
|
||||
}
|
||||
|
||||
} // namespace mold::macho
|
||||
|
@ -4,6 +4,11 @@
|
||||
|
||||
namespace mold::macho {
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, const Chunk &chunk) {
|
||||
out << chunk.hdr.get_segname() << "," << chunk.hdr.get_sectname();
|
||||
return out;
|
||||
}
|
||||
|
||||
static std::vector<u8> create_page_zero_cmd(Context &ctx) {
|
||||
std::vector<u8> buf(sizeof(SegmentCommand));
|
||||
SegmentCommand &cmd = *(SegmentCommand *)buf.data();
|
||||
@ -245,12 +250,12 @@ OutputSection::get_instance(Context &ctx, std::string_view segname,
|
||||
static std::shared_mutex mu;
|
||||
|
||||
auto find = [&]() -> OutputSection * {
|
||||
for (std::unique_ptr<Chunk> &chunk : ctx.chunks) {
|
||||
for (Chunk *chunk : ctx.chunks) {
|
||||
if (chunk->hdr.get_segname() == segname &&
|
||||
chunk->hdr.get_sectname() == sectname) {
|
||||
if (!chunk->is_regular)
|
||||
Fatal(ctx) << ": reserved name is used: " << segname << "," << sectname;
|
||||
return (OutputSection *)chunk.get();
|
||||
return (OutputSection *)chunk;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
@ -266,9 +271,7 @@ OutputSection::get_instance(Context &ctx, std::string_view segname,
|
||||
if (OutputSection *osec = find())
|
||||
return osec;
|
||||
|
||||
OutputSection *osec = new OutputSection(segname, sectname);
|
||||
ctx.chunks.push_back(std::unique_ptr<Chunk>(osec));
|
||||
return osec;
|
||||
return new OutputSection(ctx, segname, sectname);
|
||||
}
|
||||
|
||||
void OutputSection::compute_size(Context &ctx) {
|
||||
@ -794,8 +797,8 @@ void OutputIndirectSymtabSection::copy_buf(Context &ctx) {
|
||||
buf[ent.sym->stub_idx] = ent.symtab_idx;
|
||||
}
|
||||
|
||||
StubsSection::StubsSection() : Chunk("__LINKEDIT", "__stubs") {
|
||||
hdr.set_sectname("__stubs");
|
||||
StubsSection::StubsSection(Context &ctx)
|
||||
: Chunk(ctx, "__TEXT", "__stubs") {
|
||||
hdr.p2align = __builtin_ctz(2);
|
||||
hdr.type = S_SYMBOL_STUBS;
|
||||
hdr.attr = S_ATTR_SOME_INSTRUCTIONS | S_ATTR_PURE_INSTRUCTIONS;
|
||||
@ -832,8 +835,8 @@ void StubsSection::copy_buf(Context &ctx) {
|
||||
}
|
||||
}
|
||||
|
||||
StubHelperSection::StubHelperSection() : Chunk("__LINKEDIT", "__stub_helper") {
|
||||
hdr.set_sectname("__stub_helper");
|
||||
StubHelperSection::StubHelperSection(Context &ctx)
|
||||
: Chunk(ctx, "__TEXT", "__stub_helper") {
|
||||
hdr.p2align = __builtin_ctz(4);
|
||||
hdr.attr = S_ATTR_SOME_INSTRUCTIONS | S_ATTR_PURE_INSTRUCTIONS;
|
||||
}
|
||||
@ -870,8 +873,8 @@ void StubHelperSection::copy_buf(Context &ctx) {
|
||||
}
|
||||
}
|
||||
|
||||
UnwindInfoSection::UnwindInfoSection() : Chunk("__LINKEDIT", "__unwind_info") {
|
||||
hdr.set_sectname("__unwind_info");
|
||||
UnwindInfoSection::UnwindInfoSection(Context &ctx)
|
||||
: Chunk(ctx, "__TEXT", "__unwind_info") {
|
||||
hdr.p2align = __builtin_ctz(4);
|
||||
hdr.size = contents.size();
|
||||
}
|
||||
@ -1024,8 +1027,7 @@ void UnwindInfoSection::copy_buf(Context &ctx) {
|
||||
write_vector(ctx.buf + hdr.offset, contents);
|
||||
}
|
||||
|
||||
GotSection::GotSection() : Chunk("__LINKEDIT", "__got") {
|
||||
hdr.set_sectname("__got");
|
||||
GotSection::GotSection(Context &ctx) : Chunk(ctx, "__DATA_CONST", "__got") {
|
||||
hdr.p2align = __builtin_ctz(8);
|
||||
hdr.type = S_NON_LAZY_SYMBOL_POINTERS;
|
||||
}
|
||||
@ -1044,9 +1046,8 @@ void GotSection::copy_buf(Context &ctx) {
|
||||
buf[i] = syms[i]->get_addr(ctx);
|
||||
}
|
||||
|
||||
LazySymbolPtrSection::LazySymbolPtrSection()
|
||||
: Chunk("__LINKEDIT", "__la_symbol_ptr") {
|
||||
hdr.set_sectname("__la_symbol_ptr");
|
||||
LazySymbolPtrSection::LazySymbolPtrSection(Context &ctx)
|
||||
: Chunk(ctx, "__DATA", "__la_symbol_ptr") {
|
||||
hdr.p2align = __builtin_ctz(8);
|
||||
hdr.type = S_LAZY_SYMBOL_POINTERS;
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ int main() {
|
||||
}
|
||||
EOF
|
||||
|
||||
clang++ -fuse-ld=$mold -o $t/exe $t/c.o $t/c.a
|
||||
clang++ -fuse-ld=$mold -o $t/exe $t/d.o $t/c.a
|
||||
$t/exe | grep -q 'Hello world'
|
||||
|
||||
otool -tv $t/exe | grep -q '^_hello:'
|
||||
|
Loading…
Reference in New Issue
Block a user