aboutsummaryrefslogtreecommitdiff
path: root/src/link.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/link.cpp')
-rw-r--r--src/link.cpp88
1 files changed, 84 insertions, 4 deletions
diff --git a/src/link.cpp b/src/link.cpp
index 6a626a2460..326fe99ce8 100644
--- a/src/link.cpp
+++ b/src/link.cpp
@@ -62,14 +62,22 @@ static const char *build_libc_object(CodeGen *parent_gen, const char *name, CFil
return buf_ptr(&child_gen->output_file_path);
}
-static const char *path_from_libc(CodeGen *g, const char *subpath) {
- Buf *libc_dir = buf_alloc();
- os_path_join(g->zig_lib_dir, buf_create_from_str("libc"), libc_dir);
+static const char *path_from_zig_lib(CodeGen *g, const char *dir, const char *subpath) {
+ Buf *dir1 = buf_alloc();
+ os_path_join(g->zig_lib_dir, buf_create_from_str(dir), dir1);
Buf *result = buf_alloc();
- os_path_join(libc_dir, buf_create_from_str(subpath), result);
+ os_path_join(dir1, buf_create_from_str(subpath), result);
return buf_ptr(result);
}
+static const char *path_from_libc(CodeGen *g, const char *subpath) {
+ return path_from_zig_lib(g, "libc", subpath);
+}
+
+static const char *path_from_libunwind(CodeGen *g, const char *subpath) {
+ return path_from_zig_lib(g, "libunwind", subpath);
+}
+
static const char *build_dummy_so(CodeGen *parent, const char *name, size_t major_version) {
Buf *glibc_dummy_root_src = buf_sprintf("%s" OS_SEP "libc" OS_SEP "dummy" OS_SEP "%s.zig",
buf_ptr(parent->zig_lib_dir), name);
@@ -81,6 +89,70 @@ static const char *build_dummy_so(CodeGen *parent, const char *name, size_t majo
return buf_ptr(&child_gen->output_file_path);
}
+static const char *build_libunwind(CodeGen *parent) {
+ CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr);
+ codegen_set_out_name(child_gen, buf_create_from_str("unwind"));
+ child_gen->is_static = true;
+ LinkLib *new_link_lib = codegen_add_link_lib(child_gen, buf_create_from_str("c"));
+ new_link_lib->provided_explicitly = false;
+ enum SrcKind {
+ SrcCpp,
+ SrcC,
+ SrcAsm,
+ };
+ static const struct {
+ const char *path;
+ SrcKind kind;
+ } unwind_src[] = {
+ {"src" OS_SEP "libunwind.cpp", SrcCpp},
+ {"src" OS_SEP "Unwind-EHABI.cpp", SrcCpp},
+ {"src" OS_SEP "Unwind-seh.cpp", SrcCpp},
+
+ {"src" OS_SEP "UnwindLevel1.c", SrcC},
+ {"src" OS_SEP "UnwindLevel1-gcc-ext.c", SrcC},
+ {"src" OS_SEP "Unwind-sjlj.c", SrcC},
+
+ {"src" OS_SEP "UnwindRegistersRestore.S", SrcAsm},
+ {"src" OS_SEP "UnwindRegistersSave.S", SrcAsm},
+ };
+ ZigList<CFile *> c_source_files = {0};
+ for (size_t i = 0; i < array_length(unwind_src); i += 1) {
+ CFile *c_file = allocate<CFile>(1);
+ c_file->source_path = path_from_libunwind(parent, unwind_src[i].path);
+ switch (unwind_src[i].kind) {
+ case SrcC:
+ c_file->args.append("-std=c99");
+ break;
+ case SrcCpp:
+ c_file->args.append("-fno-rtti");
+ c_file->args.append("-I");
+ c_file->args.append(path_from_zig_lib(parent, "libcxx", "include"));
+ break;
+ case SrcAsm:
+ break;
+ }
+ c_file->args.append("-I");
+ c_file->args.append(path_from_libunwind(parent, "include"));
+ c_file->args.append("-fPIC");
+ c_file->args.append("-D_LIBUNWIND_DISABLE_VISIBILITY_ANNOTATIONS");
+ if (parent->zig_target->is_native) {
+ c_file->args.append("-D_LIBUNWIND_IS_NATIVE_ONLY");
+ }
+ if (parent->build_mode == BuildModeDebug) {
+ c_file->args.append("-D_DEBUG");
+ } else {
+ c_file->args.append("-NDEBUG");
+ }
+ if (parent->is_single_threaded) {
+ c_file->args.append("-D_LIBUNWIND_HAS_NO_THREADS");
+ }
+ c_source_files.append(c_file);
+ }
+ child_gen->c_source_files = c_source_files;
+ codegen_build_and_link(child_gen);
+ return buf_ptr(&child_gen->output_file_path);
+}
+
static const char *get_libc_crt_file(CodeGen *parent, const char *file) {
if (parent->libc == nullptr && target_is_glibc(parent)) {
if (strcmp(file, "crti.o") == 0) {
@@ -611,6 +683,7 @@ static void construct_linker_job_elf(LinkJob *lj) {
lj->args.append("-lgcc_s");
lj->args.append("--no-as-needed");
} else if (target_is_glibc(g)) {
+ lj->args.append(build_libunwind(g));
lj->args.append(get_libc_crt_file(g, "libc.so.6")); // this is our dummy so file
lj->args.append(get_libc_crt_file(g, "libc_nonshared.a"));
} else {
@@ -1192,6 +1265,13 @@ void codegen_link(CodeGen *g) {
}
ZigLLVM_OSType os_type = get_llvm_os_type(g->zig_target->os);
codegen_add_time_event(g, "LLVM Link");
+ if (g->verbose_link) {
+ fprintf(stderr, "ar rcs %s", buf_ptr(&g->output_file_path));
+ for (size_t i = 0; i < g->link_objects.length; i += 1) {
+ fprintf(stderr, " %s", (const char *)buf_ptr(g->link_objects.at(i)));
+ }
+ fprintf(stderr, "\n");
+ }
if (ZigLLVMWriteArchive(buf_ptr(&g->output_file_path), file_names.items, file_names.length, os_type)) {
fprintf(stderr, "Unable to write archive '%s'\n", buf_ptr(&g->output_file_path));
exit(1);