cc_library_static {
    name: "liblinker_malloc",
    defaults: ["linux_bionic_supported"],

    srcs: [
        "linker_allocator.cpp",
        "linker_memory.cpp",
    ],
    cflags: [
        "-Wall",
        "-Werror",
    ],

    // We need to access Bionic private headers in the linker.
    include_dirs: ["bionic/libc"],

    static_libs: ["libasync_safe"],
}

// This is used for bionic on (host) Linux to bootstrap our linker embedded into
// a binary.
//
// Host bionic binaries do not have a PT_INTERP section, instead this gets
// embedded as the entry point, and the linker is embedded as ELF sections in
// each binary. There's a linker script that sets all of that up (generated by
// extract_linker), and defines the extern symbols used in this file.
cc_object {
    name: "linker_wrapper",
    host_supported: true,
    device_supported: false,
    target: {
        linux_bionic: {
            enabled: true,
        },
        linux_glibc: {
            enabled: false,
        },
        darwin: {
            enabled: false,
        },
    },

    cflags: [
        "-fno-stack-protector",
        "-Wstrict-overflow=5",
        "-fvisibility=hidden",
        "-Wall",
        "-Wextra",
        "-Wno-unused",
        "-Werror",
    ],

    srcs: [
        "linker_wrapper.cpp",
    ],
    arch: {
        x86_64: {
            srcs: ["arch/x86_64/begin.S"],
        },
    },

    prefix_symbols: "__dlwrap_",

    // We need to access Bionic private headers in the linker.
    include_dirs: ["bionic/libc"],
}

cc_binary {
    defaults: ["linux_bionic_supported"],
    srcs: [
        "dlfcn.cpp",
        "linker.cpp",
        "linker_block_allocator.cpp",
        "linker_dlwarning.cpp",
        "linker_cfi.cpp",
        "linker_config.cpp",
        "linker_gdb_support.cpp",
        "linker_globals.cpp",
        "linker_libc_support.c",
        "linker_libcxx_support.cpp",
        "linker_main.cpp",
        "linker_namespaces.cpp",
        "linker_logger.cpp",
        "linker_mapped_file_fragment.cpp",
        "linker_phdr.cpp",
        "linker_sdk_versions.cpp",
        "linker_soinfo.cpp",
        "linker_utils.cpp",
        "rt.cpp",
    ],

    arch: {
        arm: {
            srcs: [
                "arch/arm/begin.S",
                "linker_exidx_static.c",
            ],

            cflags: ["-D__work_around_b_24465209__"],
            version_script: "linker.arm.map",
        },
        arm64: {
            srcs: ["arch/arm64/begin.S"],
            version_script: "linker.generic.map",
        },
        x86: {
            srcs: ["arch/x86/begin.S"],
            cflags: ["-D__work_around_b_24465209__"],
            version_script: "linker.generic.map",
        },
        x86_64: {
            srcs: ["arch/x86_64/begin.S"],
            version_script: "linker.generic.map",
        },
        mips: {
            srcs: [
                "arch/mips/begin.S",
                "linker_mips.cpp",
            ],
            version_script: "linker.generic.map",
        },
        mips64: {
            srcs: [
                "arch/mips64/begin.S",
                "linker_mips.cpp",
            ],
            version_script: "linker.generic.map",
        },
    },

    // We need to access Bionic private headers in the linker.
    include_dirs: ["bionic/libc"],

    // -shared is used to overwrite the -Bstatic and -static
    // flags triggered by LOCAL_FORCE_STATIC_EXECUTABLE.
    // This dynamic linker is actually a shared object linked with static libraries.
    ldflags: [
        "-shared",
        "-Wl,-Bsymbolic",
        "-Wl,--exclude-libs,ALL",
        "-Wl,-soname,ld-android.so",
    ],

    cflags: [
        "-fno-stack-protector",
        "-Wstrict-overflow=5",
        "-fvisibility=hidden",
        "-Wall",
        "-Wextra",
        "-Wunused",
        "-Werror",
    ],

    // TODO: split out the asflags.
    asflags: [
        "-fno-stack-protector",
        "-Wstrict-overflow=5",
        "-fvisibility=hidden",
        "-Wall",
        "-Wextra",
        "-Wunused",
        "-Werror",
    ],

    product_variables: {
        debuggable: {
            cppflags: ["-DUSE_LD_CONFIG_FILE"],
        },
    },

    cppflags: ["-Wold-style-cast"],

    // we are going to link libc++_static manually because
    // when stl is not set to "none" build system adds libdl
    // to the list of static libraries which needs to be
    // avoided in the case of building loader.
    stl: "none",

    // we don't want crtbegin.o (because we have begin.o), so unset it
    // just for this module
    nocrt: true,

    static_libs: [
        "libc_nomalloc",
        "libm",
        "libziparchive",
        "libutils",
        "libbase",
        "libz",

        "libasync_safe",

        "liblog",
        "libc++_static",

        // Important: The liblinker_malloc should be the last library in the list
        // to overwrite any other malloc implementations by other static libraries.
        "liblinker_malloc",
    ],
    static_executable: true,

    name: "linker",
    symlinks: ["linker_asan"],
    multilib: {
        lib64: {
            suffix: "64",
        },
    },
    target: {
        android: {
            static_libs: ["libdebuggerd_handler_fallback"],
        },
    },
    compile_multilib: "both",

    // Leave the symbols in the shared library so that stack unwinders can produce
    // meaningful name resolution.
    strip: {
        keep_symbols: true,
    },

    // Insert an extra objcopy step to add prefix to symbols. This is needed to prevent gdb
    // looking up symbols in the linker by mistake.
    prefix_symbols: "__dl_",
}

cc_library {
    // NOTE: --exclude-libs=libgcc.a makes sure that any symbols ld-android.so pulls from
    // libgcc.a are made static to ld-android.so.  This in turn ensures that libraries that
    // a) pull symbols from libgcc.a and b) depend on ld-android.so will not rely on ld-android.so
    // to provide those symbols, but will instead pull them from libgcc.a.  Specifically,
    // we use this property to make sure libc.so has its own copy of the code from
    // libgcc.a it uses.
    //
    // DO NOT REMOVE --exclude-libs!

    ldflags: ["-Wl,--exclude-libs=libgcc.a"],

    // for x86, exclude libgcc_eh.a for the same reasons as above
    arch: {
        arm: {
            version_script: "linker.arm.map",
        },
        arm64: {
            version_script: "linker.generic.map",
        },
        x86: {
            ldflags: ["-Wl,--exclude-libs=libgcc_eh.a"],
            version_script: "linker.generic.map",
        },
        x86_64: {
            ldflags: ["-Wl,--exclude-libs=libgcc_eh.a"],
            version_script: "linker.generic.map",
        },
        mips: {
            version_script: "linker.generic.map",
        },
        mips64: {
            version_script: "linker.generic.map",
        },
    },

    srcs: ["ld_android.cpp"],
    cflags: [
        "-Wall",
        "-Wextra",
        "-Wunused",
        "-Werror",
    ],
    stl: "none",

    name: "ld-android",
    defaults: ["linux_bionic_supported"],

    nocrt: true,
    system_shared_libs: [],

    sanitize: {
        never: true,
    },
}