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-10-05 14:02:41 +03:00
|
|
|
#include "../output-file.h"
|
2021-09-08 13:02:38 +03:00
|
|
|
|
2021-09-13 12:15:34 +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>
|
2021-09-13 12:15:34 +03:00
|
|
|
#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-15 11:07:58 +03:00
|
|
|
auto add = [&](std::string_view name, u64 value = 0) {
|
|
|
|
Symbol *sym = intern(ctx, name);
|
2021-10-15 09:23:00 +03:00
|
|
|
sym->file = obj;
|
2021-10-15 11:07:58 +03:00
|
|
|
sym->value = value;
|
2021-10-15 09:23:00 +03:00
|
|
|
obj->syms.push_back(sym);
|
|
|
|
};
|
|
|
|
|
|
|
|
add("__dyld_private");
|
2021-10-15 11:07:58 +03:00
|
|
|
add("__mh_execute_header", PAGE_ZERO_SIZE);
|
|
|
|
|
|
|
|
obj->syms.push_back(intern(ctx, "dyld_stub_binder"));
|
2021-10-15 09:23:00 +03:00
|
|
|
}
|
|
|
|
|
2021-10-06 10:41:18 +03:00
|
|
|
static void add_section(Context &ctx, OutputSection &osec,
|
|
|
|
std::string_view segname, std::string_view sectname) {
|
|
|
|
for (ObjectFile *obj : ctx.objs) {
|
|
|
|
for (std::unique_ptr<InputSection> &sec : obj->sections) {
|
2021-10-06 11:16:02 +03:00
|
|
|
if (sec->hdr.segname == segname && sec->hdr.sectname == sectname) {
|
|
|
|
for (Subsection &subsec : sec->subsections)
|
|
|
|
osec.members.push_back(&subsec);
|
|
|
|
sec->osec = &osec;
|
2021-10-06 10:41:18 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-04 04:00:55 +03:00
|
|
|
static void create_synthetic_chunks(Context &ctx) {
|
2021-09-21 08:53:38 +03:00
|
|
|
ctx.segments.push_back(&ctx.text_seg);
|
|
|
|
ctx.segments.push_back(&ctx.data_const_seg);
|
|
|
|
ctx.segments.push_back(&ctx.data_seg);
|
|
|
|
ctx.segments.push_back(&ctx.linkedit_seg);
|
|
|
|
|
2021-10-04 04:00:55 +03:00
|
|
|
ctx.text_seg.chunks.push_back(&ctx.mach_hdr);
|
|
|
|
ctx.text_seg.chunks.push_back(&ctx.load_cmd);
|
2021-10-13 10:49:35 +03:00
|
|
|
ctx.text_seg.chunks.push_back(&ctx.padding);
|
|
|
|
|
|
|
|
ctx.padding.hdr.size = 14808;
|
2021-10-04 09:33:44 +03:00
|
|
|
|
2021-10-14 14:54:28 +03:00
|
|
|
ctx.text.hdr.attr = S_ATTR_PURE_INSTRUCTIONS | S_ATTR_SOME_INSTRUCTIONS;
|
|
|
|
ctx.text.hdr.p2align = 4;
|
|
|
|
add_section(ctx, ctx.text, "__TEXT", "__text");
|
|
|
|
ctx.text_seg.chunks.push_back(&ctx.text);
|
2021-10-06 10:53:20 +03:00
|
|
|
|
2021-10-04 04:00:55 +03:00
|
|
|
ctx.text_seg.chunks.push_back(&ctx.stubs);
|
|
|
|
ctx.text_seg.chunks.push_back(&ctx.stub_helper);
|
2021-10-06 10:53:20 +03:00
|
|
|
|
|
|
|
OutputSection *cstring = new OutputSection("__cstring");
|
|
|
|
cstring->hdr.type = S_CSTRING_LITERALS;
|
|
|
|
add_section(ctx, *cstring, "__TEXT", "__cstring");
|
|
|
|
ctx.text_seg.chunks.push_back(cstring);
|
|
|
|
|
2021-10-04 04:00:55 +03:00
|
|
|
ctx.text_seg.chunks.push_back(&ctx.unwind_info);
|
|
|
|
|
|
|
|
ctx.data_const_seg.chunks.push_back(&ctx.got);
|
|
|
|
|
|
|
|
ctx.data_seg.chunks.push_back(&ctx.lazy_symbol_ptr);
|
|
|
|
ctx.data_seg.chunks.push_back(&ctx.data);
|
|
|
|
|
|
|
|
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);
|
2021-09-15 15:00:14 +03:00
|
|
|
}
|
2021-09-13 15:59:20 +03:00
|
|
|
|
2021-09-20 16:04:41 +03:00
|
|
|
static void fill_symtab(Context &ctx) {
|
2021-10-23 16:15:03 +03:00
|
|
|
ctx.symtab.add(ctx, intern(ctx, "__dyld_private"), N_SECT, false, 8, 0x0);
|
|
|
|
ctx.symtab.add(ctx, intern(ctx, "__mh_execute_header"), N_SECT, true, 1, 0x10);
|
|
|
|
ctx.symtab.add(ctx, intern(ctx, "_hello"), N_SECT, true, 1, 0x0);
|
|
|
|
ctx.symtab.add(ctx, intern(ctx, "_main"), N_SECT, true, 1, 0x0);
|
|
|
|
ctx.symtab.add(ctx, intern(ctx, "_printf"), N_UNDF, true, 0, 0x100);
|
|
|
|
ctx.symtab.add(ctx, intern(ctx, "dyld_stub_binder"), N_UNDF, true, 0, 0x100);
|
2021-09-20 16:04:41 +03:00
|
|
|
}
|
|
|
|
|
2021-09-21 11:08:50 +03:00
|
|
|
static void export_symbols(Context &ctx) {
|
2021-10-23 15:01:35 +03:00
|
|
|
std::vector<Symbol *> syms;
|
|
|
|
|
|
|
|
for (DylibFile *dylib : ctx.dylibs)
|
|
|
|
for (Symbol *sym : dylib->syms)
|
|
|
|
if (sym->file == dylib && sym->needs_stub)
|
|
|
|
syms.push_back(sym);
|
|
|
|
|
|
|
|
for (Symbol *sym : syms)
|
2021-10-23 15:14:57 +03:00
|
|
|
ctx.stubs.add(ctx, sym);
|
2021-09-21 11:08:50 +03:00
|
|
|
}
|
|
|
|
|
2021-09-20 16:04:41 +03:00
|
|
|
static i64 assign_offsets(Context &ctx) {
|
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-09-17 14:09:50 +03:00
|
|
|
for (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-15 13:14:28 +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_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;
|
2021-10-23 11:07:17 +03:00
|
|
|
if (get_file_type(mf) == FileType::TAPI)
|
|
|
|
ctx.dylibs.push_back(DylibFile::create(ctx, mf));
|
2021-10-22 10:34:49 +03:00
|
|
|
} else {
|
2021-10-23 10:49:06 +03:00
|
|
|
MappedFile<Context> *mf = MappedFile<Context>::must_open(ctx, arg);
|
2021-10-23 11:07:17 +03:00
|
|
|
if (get_file_type(mf) == FileType::MACH_OBJ)
|
|
|
|
ctx.objs.push_back(ObjectFile::create(ctx, mf));
|
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-09-13 12:15:34 +03:00
|
|
|
}
|
|
|
|
|
2021-10-16 13:59:21 +03:00
|
|
|
if (argc > 1 && std::string_view(argv[1]) == "-yamltest") {
|
2021-10-18 15:39:52 +03:00
|
|
|
std::string path = "/Applications/Xcode.app/Contents/Developer/Platforms/"
|
|
|
|
"MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/lib/libSystem.tbd";
|
2021-10-23 04:44:20 +03:00
|
|
|
TextDylib tbd = parse_tbd(ctx, MappedFile<Context>::must_open(ctx, path));
|
|
|
|
SyncOut(ctx) << "tbd: uuid=" << tbd.uuid
|
|
|
|
<< " install_name=" << tbd.install_name
|
|
|
|
<< " current_version=" << tbd.current_version
|
|
|
|
<< " parent_umbrella=" << tbd.parent_umbrella;
|
2021-10-23 04:59:13 +03:00
|
|
|
for (std::string_view sym : tbd.exports)
|
|
|
|
SyncOut(ctx) << " sym=" << sym;
|
2021-10-16 14:22:19 +03:00
|
|
|
exit(0);
|
2021-10-16 13:59:21 +03:00
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
for (ObjectFile *obj : ctx.objs)
|
|
|
|
obj->priority = priority++;
|
|
|
|
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-04 11:57:16 +03:00
|
|
|
for (ObjectFile *obj : ctx.objs)
|
|
|
|
obj->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-05 16:17:14 +03:00
|
|
|
for (ObjectFile *obj : ctx.objs)
|
|
|
|
obj->resolve_symbols(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-04 04:00:55 +03:00
|
|
|
create_synthetic_chunks(ctx);
|
2021-10-23 15:01:35 +03:00
|
|
|
|
|
|
|
for (ObjectFile *obj : ctx.objs)
|
|
|
|
for (std::unique_ptr<InputSection> &sec : obj->sections)
|
|
|
|
sec->scan_relocations(ctx);
|
|
|
|
|
2021-10-03 11:49:33 +03:00
|
|
|
fill_symtab(ctx);
|
|
|
|
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-05 14:02:41 +03:00
|
|
|
ctx.output_file = open_output_file(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-03 11:49:33 +03:00
|
|
|
for (OutputSegment *seg : ctx.segments)
|
|
|
|
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);
|
|
|
|
return 0;
|
2021-09-08 13:02:38 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|