diff --git a/lib/std/c/linux.zig b/lib/std/c/linux.zig index b3b3cbdde7..8936d2ab5a 100644 --- a/lib/std/c/linux.zig +++ b/lib/std/c/linux.zig @@ -1,9 +1,19 @@ +const builtin = @import("builtin"); const std = @import("../std.zig"); const maxInt = std.math.maxInt; usingnamespace std.c; -extern "c" fn __errno_location() *c_int; -pub const _errno = __errno_location; +pub const _errno = switch (builtin.abi) { + .android => struct { + extern "c" var __errno: c_int; + fn getErrno() *c_int { + return &__errno; + } + }.getErrno, + else => struct { + extern "c" fn __errno_location() *c_int; + }.__errno_location, +}; pub const MAP_FAILED = @intToPtr(*c_void, maxInt(usize)); diff --git a/src/link.cpp b/src/link.cpp index 41fb2ca415..07258943ca 100644 --- a/src/link.cpp +++ b/src/link.cpp @@ -1653,6 +1653,10 @@ static void construct_linker_job_elf(LinkJob *lj) { soname = buf_sprintf("lib%s.so.%" ZIG_PRI_usize, buf_ptr(g->root_out_name), g->version_major); } + if (target_requires_pie(g->zig_target) && !is_dyn_lib) { + lj->args.append("-pie"); + } + lj->args.append("-o"); lj->args.append(buf_ptr(&g->output_file_path)); @@ -1660,8 +1664,14 @@ static void construct_linker_job_elf(LinkJob *lj) { const char *crt1o; if (g->zig_target->os == OsNetBSD) { crt1o = "crt0.o"; + } else if (target_is_android(g->zig_target)) { + crt1o = "crtbegin_dynamic.o"; } else if (!g->have_dynamic_link) { - crt1o = "crt1.o"; + if (target_is_android(g->zig_target)) { + crt1o = "crtbegin.o"; + } else { + crt1o = "crt1.o"; + } } else { crt1o = "Scrt1.o"; } @@ -1768,21 +1778,27 @@ static void construct_linker_job_elf(LinkJob *lj) { if (!g->have_dynamic_link) { lj->args.append("--start-group"); lj->args.append("-lgcc"); - lj->args.append("-lgcc_eh"); + if (!target_is_android(g->zig_target)) { + lj->args.append("-lgcc_eh"); + } lj->args.append("-lc"); lj->args.append("-lm"); lj->args.append("--end-group"); } else { lj->args.append("-lgcc"); - lj->args.append("--as-needed"); - lj->args.append("-lgcc_s"); - lj->args.append("--no-as-needed"); + if (!target_is_android(g->zig_target)) { + lj->args.append("--as-needed"); + lj->args.append("-lgcc_s"); + lj->args.append("--no-as-needed"); + } lj->args.append("-lc"); lj->args.append("-lm"); lj->args.append("-lgcc"); - lj->args.append("--as-needed"); - lj->args.append("-lgcc_s"); - lj->args.append("--no-as-needed"); + if (!target_is_android(g->zig_target)) { + lj->args.append("--as-needed"); + lj->args.append("-lgcc_s"); + lj->args.append("--no-as-needed"); + } } if (g->zig_target->os == OsFreeBSD) { @@ -1805,7 +1821,9 @@ static void construct_linker_job_elf(LinkJob *lj) { } // crt end - if (lj->link_in_crt && target_libc_needs_crti_crtn(g->zig_target)) { + if (target_is_android(g->zig_target) && g->have_dynamic_link) { + lj->args.append(get_libc_crt_file(g, "crtend_android.o")); + } else if (lj->link_in_crt && target_libc_needs_crti_crtn(g->zig_target)) { lj->args.append(get_libc_crt_file(g, "crtn.o")); } diff --git a/src/target.cpp b/src/target.cpp index 3f7bd75011..e2d0874945 100644 --- a/src/target.cpp +++ b/src/target.cpp @@ -1590,10 +1590,14 @@ bool target_supports_stack_probing(const ZigTarget *target) { bool target_requires_pic(const ZigTarget *target, bool linking_libc) { // This function returns whether non-pic code is completely invalid on the given target. - return target->os == OsWindows || target->os == OsUefi || target_os_requires_libc(target->os) || + return target_is_android(target) || target->os == OsWindows || target->os == OsUefi || target_os_requires_libc(target->os) || (linking_libc && target_is_glibc(target)); } +bool target_requires_pie(const ZigTarget *target) { + return target_is_android(target); +} + bool target_is_glibc(const ZigTarget *target) { return target->os == OsLinux && target_abi_is_gnu(target->abi); } @@ -1876,7 +1880,7 @@ bool target_supports_libunwind(const ZigTarget *target) { } bool target_libc_needs_crti_crtn(const ZigTarget *target) { - if (target->arch == ZigLLVM_riscv32 || target->arch == ZigLLVM_riscv64) { + if (target->arch == ZigLLVM_riscv32 || target->arch == ZigLLVM_riscv64 || target_is_android(target)) { return false; } return true; diff --git a/src/target.hpp b/src/target.hpp index c157b40011..c5c285a8db 100644 --- a/src/target.hpp +++ b/src/target.hpp @@ -182,6 +182,7 @@ const char *target_libc_generic_name(const ZigTarget *target); bool target_is_libc_lib_name(const ZigTarget *target, const char *name); bool target_supports_fpic(const ZigTarget *target); bool target_requires_pic(const ZigTarget *target, bool linking_libc); +bool target_requires_pie(const ZigTarget *target); bool target_abi_is_gnu(ZigLLVM_EnvironmentType abi); bool target_abi_is_musl(ZigLLVM_EnvironmentType abi); bool target_is_glibc(const ZigTarget *target);