1
1
mirror of https://github.com/rui314/mold.git synced 2024-09-21 09:57:18 +03:00
mold/macho/main.cc

268 lines
6.8 KiB
C++
Raw Normal View History

2021-09-08 13:02:38 +03:00
#include "mold.h"
2021-10-05 06:59:18 +03:00
#include "../archive-file.h"
2021-10-05 05:24:44 +03:00
#include "../cmdline.h"
2021-09-08 13:02:38 +03:00
#include <cstdlib>
#include <fcntl.h>
2021-09-14 07:12:43 +03:00
#include <iomanip>
2021-09-08 13:15:12 +03:00
#include <iostream>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
2021-09-08 13:15:12 +03:00
2021-09-08 13:02:38 +03:00
namespace mold::macho {
2021-10-15 09:23:00 +03:00
static void create_internal_file(Context &ctx) {
ObjectFile *obj = new ObjectFile;
ctx.obj_pool.push_back(std::unique_ptr<ObjectFile>(obj));
ctx.objs.push_back(obj);
2021-10-23 18:12:55 +03:00
auto add = [&](std::string_view name) {
2021-10-15 11:07:58 +03:00
Symbol *sym = intern(ctx, name);
2021-10-15 09:23:00 +03:00
sym->file = obj;
obj->syms.push_back(sym);
2021-10-23 18:12:55 +03:00
return sym;
2021-10-15 09:23:00 +03:00
};
2021-10-23 18:12:55 +03:00
add("__dyld_private");
Symbol *sym = add("__mh_execute_header");
sym->is_extern = true;
sym->referenced_dynamically = true;
sym->value = PAGE_ZERO_SIZE;
2021-10-15 09:23:00 +03:00
}
2021-11-01 07:39:07 +03:00
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;
}
2021-10-04 04:00:55 +03:00
static void create_synthetic_chunks(Context &ctx) {
2021-10-27 14:53:27 +03:00
for (ObjectFile *obj : ctx.objs) {
for (std::unique_ptr<InputSection> &isec : obj->sections) {
2021-10-29 10:07:40 +03:00
for (std::unique_ptr<Subsection> &subsec : isec->subsections)
2021-10-29 15:22:59 +03:00
isec->osec.add_subsec(subsec.get());
2021-10-27 14:53:27 +03:00
isec->osec.hdr.attr |= isec->hdr.attr;
}
}
2021-10-27 14:20:01 +03:00
2021-11-01 07:39:07 +03:00
for (Chunk *chunk : ctx.chunks) {
if (chunk != ctx.data && chunk->is_regular &&
((OutputSection *)chunk)->members.empty())
continue;
OutputSegment *seg =
OutputSegment::get_instance(ctx, chunk->hdr.get_segname());
seg->chunks.push_back(chunk);
}
for (std::unique_ptr<OutputSegment> &seg : ctx.segments)
sort(seg->chunks, compare_chunks);
2021-09-15 15:00:14 +03:00
}
2021-09-13 15:59:20 +03:00
2021-09-21 11:08:50 +03:00
static void export_symbols(Context &ctx) {
2021-10-24 14:54:26 +03:00
ctx.got.add(ctx, intern(ctx, "dyld_stub_binder"));
for (ObjectFile *file : ctx.objs)
for (Symbol *sym : file->syms)
if (sym->file == file && sym->flags & NEEDS_GOT)
ctx.got.add(ctx, sym);
for (DylibFile *file : ctx.dylibs) {
for (Symbol *sym : file->syms) {
if (sym->file == file)
if (sym->flags & NEEDS_STUB)
ctx.stubs.add(ctx, sym);
if (sym->flags & NEEDS_GOT)
ctx.got.add(ctx, sym);
}
}
2021-09-21 11:08:50 +03:00
}
static i64 assign_offsets(Context &ctx) {
2021-10-23 16:43:59 +03:00
i64 sect_idx = 1;
2021-10-30 09:16:55 +03:00
for (std::unique_ptr<OutputSegment> &seg : ctx.segments)
2021-10-23 16:43:59 +03:00
for (Chunk *chunk : seg->chunks)
if (!chunk->is_hidden)
chunk->sect_idx = sect_idx++;
2021-09-15 15:00:14 +03:00
i64 fileoff = 0;
2021-09-17 14:09:50 +03:00
i64 vmaddr = PAGE_ZERO_SIZE;
2021-09-16 16:23:18 +03:00
2021-10-30 09:16:55 +03:00
for (std::unique_ptr<OutputSegment> &seg : ctx.segments) {
2021-09-20 13:41:03 +03:00
seg->set_offset(ctx, fileoff, vmaddr);
2021-09-18 09:05:46 +03:00
fileoff += seg->cmd.filesize;
2021-09-17 14:09:50 +03:00
vmaddr += seg->cmd.vmsize;
2021-09-16 16:23:18 +03:00
}
2021-09-16 10:21:18 +03:00
return fileoff;
2021-09-13 15:59:20 +03:00
}
2021-10-15 11:07:58 +03:00
static void fix_synthetic_symbol_values(Context &ctx) {
2021-10-27 14:20:01 +03:00
intern(ctx, "__dyld_private")->value = ctx.data->hdr.addr;
2021-10-15 11:07:58 +03:00
}
2021-10-22 10:34:49 +03:00
MappedFile<Context> *find_library(Context &ctx, std::string name) {
for (std::string dir : ctx.arg.library_paths) {
for (std::string ext : {".tbd", ".dylib", ".a"}) {
2021-10-23 11:06:36 +03:00
std::string path =
path_clean(ctx.arg.syslibroot + dir + "/lib" + name + ext);
2021-10-22 10:34:49 +03:00
if (MappedFile<Context> *mf = MappedFile<Context>::open(ctx, path))
return mf;
}
}
return nullptr;
}
static void read_file(Context &ctx, MappedFile<Context> *mf) {
switch (get_file_type(mf)) {
case FileType::TAPI:
ctx.dylibs.push_back(DylibFile::create(ctx, mf));
break;
case FileType::MACH_OBJ:
ctx.objs.push_back(ObjectFile::create(ctx, mf, ""));
break;
case FileType::AR:
for (MappedFile<Context> *child : read_archive_members(ctx, mf))
if (get_file_type(child) == FileType::MACH_OBJ)
ctx.objs.push_back(ObjectFile::create(ctx, child, mf->name));
break;
default:
break;
}
}
2021-10-22 10:34:49 +03:00
static void read_input_files(Context &ctx, std::span<std::string> args) {
for (std::string &arg : args) {
if (arg.starts_with("-l")) {
MappedFile<Context> *mf = find_library(ctx, arg.substr(2));
if (!mf)
Fatal(ctx) << "library not found: " << arg;
read_file(ctx, mf);
2021-10-22 10:34:49 +03:00
} else {
read_file(ctx, MappedFile<Context>::must_open(ctx, arg));
2021-10-22 10:34:49 +03:00
}
}
}
2021-09-08 14:15:03 +03:00
int main(int argc, char **argv) {
2021-09-15 11:25:06 +03:00
Context ctx;
2021-10-03 12:36:49 +03:00
if (argc > 1 && std::string_view(argv[1]) == "-dump") {
2021-09-15 11:25:06 +03:00
if (argc != 3)
Fatal(ctx) << "usage: ld64.mold -dump <executable-name>\n";
dump_file(argv[2]);
exit(0);
}
2021-10-03 11:49:33 +03:00
ctx.cmdline_args = expand_response_files(ctx, argv);
2021-10-22 09:38:00 +03:00
std::vector<std::string> file_args;
2021-10-03 11:49:33 +03:00
parse_nonpositional_args(ctx, file_args);
2021-09-15 15:00:14 +03:00
2021-10-22 10:34:49 +03:00
read_input_files(ctx, file_args);
2021-10-03 14:14:05 +03:00
2021-10-23 05:40:47 +03:00
i64 priority = 1;
2021-10-28 09:07:39 +03:00
for (ObjectFile *file : ctx.objs)
file->priority = priority++;
2021-10-23 05:40:47 +03:00
for (DylibFile *dylib : ctx.dylibs)
dylib->priority = priority++;
2021-10-23 11:45:45 +03:00
for (i64 i = 0; i < ctx.dylibs.size(); i++)
2021-10-23 15:01:35 +03:00
ctx.dylibs[i]->dylib_idx = i + 1;
2021-10-23 11:45:45 +03:00
2021-10-28 09:07:39 +03:00
for (ObjectFile *file : ctx.objs)
file->parse(ctx);
2021-10-23 10:22:55 +03:00
for (DylibFile *dylib : ctx.dylibs)
dylib->parse(ctx);
2021-10-04 11:57:16 +03:00
2021-10-28 09:07:39 +03:00
for (ObjectFile *file : ctx.objs) {
if (file->archive_name.empty())
file->resolve_regular_symbols(ctx);
else
file->resolve_lazy_symbols(ctx);
}
2021-10-28 09:48:40 +03:00
std::vector<ObjectFile *> live_objs;
for (ObjectFile *file : ctx.objs)
if (file->is_alive)
live_objs.push_back(file);
for (i64 i = 0; i < live_objs.size(); i++)
append(live_objs, live_objs[i]->mark_live_objects(ctx));
2021-10-23 11:45:45 +03:00
for (DylibFile *dylib : ctx.dylibs)
2021-10-23 10:22:55 +03:00
dylib->resolve_symbols(ctx);
2021-10-23 11:06:36 +03:00
2021-10-15 09:23:00 +03:00
create_internal_file(ctx);
2021-10-28 14:35:26 +03:00
for (ObjectFile *file : ctx.objs)
file->convert_common_symbols(ctx);
2021-10-04 04:00:55 +03:00
create_synthetic_chunks(ctx);
2021-10-23 15:01:35 +03:00
2021-10-24 16:13:06 +03:00
for (i64 i = 0; i < ctx.segments.size(); i++)
ctx.segments[i]->seg_idx = i + 1;
2021-10-28 09:07:39 +03:00
for (ObjectFile *file : ctx.objs)
for (std::unique_ptr<InputSection> &sec : file->sections)
2021-10-23 15:01:35 +03:00
sec->scan_relocations(ctx);
2021-10-03 11:49:33 +03:00
export_symbols(ctx);
i64 output_size = assign_offsets(ctx);
2021-10-15 11:07:58 +03:00
fix_synthetic_symbol_values(ctx);
2021-09-13 13:07:15 +03:00
2021-10-26 07:53:48 +03:00
ctx.output_file = OutputFile::open(ctx, ctx.arg.output, output_size, 0777);
2021-10-03 11:49:33 +03:00
ctx.buf = ctx.output_file->buf;
2021-09-13 13:07:15 +03:00
2021-10-30 09:16:55 +03:00
for (std::unique_ptr<OutputSegment> &seg : ctx.segments)
2021-10-03 11:49:33 +03:00
seg->copy_buf(ctx);
2021-09-13 13:07:15 +03:00
2021-10-03 11:49:33 +03:00
ctx.output_file->close(ctx);
ctx.checkpoint();
2021-10-03 11:49:33 +03:00
return 0;
2021-09-08 13:02:38 +03:00
}
}