blob: bf650822572cab6312b172fa565a169723eaa93d [file] [log] [blame]
# Copyright 2023 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import("../libc.gni")
llvm_libc_group("string") {
deps = [
":compat",
":mem",
":str",
]
# TODO(https://fxbug.dev/42053650): not yet using the llvm-libc versions of these
non_test_deps = [
"//zircon/third_party/ulib/musl/src/string:strerror_r",
"//zircon/third_party/ulib/musl/src/string:strsignal",
"//zircon/third_party/ulib/musl/src/string:strverscmp",
]
# TODO(https://fxbug.dev/42053650): but run their tests in preparation
testonly_deps = [ ":strsignalerror" ]
}
llvm_libc_source_set("mem") {
functions = [
"memccpy",
"memmem",
"mempcpy",
"memrchr",
]
deps = [
":memchr",
":memcmp",
":memcpy",
":memset",
]
}
unsanitized_funcs = [
"memcpy",
"memmove",
"memset",
]
# The compiler will turn code that looks like it implements these functions
# into calls to their standard names. It doesn't recognize that the internal
# implementation layers are going to be inlined into the public standard C
# function, so it just produces an infinite recursion (or a call via a PLT
# entry that hasn't been fixed up yet). Using `-fno-builtin-FUNCTION` for the
# particular functions works around this.
foreach(funcs,
[
[ "memchr" ],
[ "memcmp" ],
[
"memcpy",
"memmove",
],
[ "memset" ],
[ "strlen" ],
]) {
config("no-builtin-${funcs[0]}") {
visibility = [ ":*" ]
cflags = []
# TODO(https://fxbug.dev/42079782): gcc is not correctly honoring -fno-builtin-memmove,
# but -fno-builtin correctly suppresses the call to memmove.
if (funcs[0] == "memcpy" && is_gcc) {
cflags += [ "-fno-builtin" ]
}
foreach(func, funcs) {
cflags += [ "-fno-builtin-$func" ]
# TODO(https://fxbug.dev/42077425): The .weakref shenanigans in dynlink.c aren't
# compatible with full LTO and a memcpy defined in C++. This only affects
# riscv64 in practice, since others use assembly definitions regardless.
if ((func == "memcpy" || func == "memset") && !is_gcc &&
toolchain_environment == "user.basic") {
cflags += [
"-fno-lto",
"-fno-whole-program-vtables",
]
}
}
}
llvm_libc_source_set(funcs[0]) {
visibility = [ ":*" ]
functions = funcs
# Avoid self-referential libcalls.
configs = [ ":no-builtin-${funcs[0]}" ]
# These also need to stick to the basic machine ABI so that dynlink.c can
# use them early.
basic_abi = true
non_test_vars = {
# The user.basic environment doesn't export the symbols it defines.
# When building for export in libc.so, we want these compiled in the
# user.basic environment, but we also want to export names for them. At
# the same time, dynlink.c needs to use hidden symbols to access these
# so that it won't use PLT entries before they're ready. So compile
# them using an override for the "src/__support/common.h" internal
# header that redefines the implementation's LLVM_LIBC_FUNCTION macro to
# add extra aliases.
#
# Note this is plumbed directly as include_dirs in the source_set() so
# that it comes before all the include_dirs plumbs via configs. If this
# instead used non_test_deps to point at a group with public_configs
# pointing at a config(), then those include_dirs would come after all
# the ones from configs used to compile libc. This needs to preempt
# those, so it should come first as include_dirs et al directly in a
# target like source_set() do.
include_dirs = [ "mem-aliases-include" ]
if (funcs + unsanitized_funcs - unsanitized_funcs != funcs) {
defines = [ "LIBC_UNSANITIZED" ]
}
}
}
}
# These are the functions that are nonproblematic in any context.
llvm_libc_source_set("minimal-str") {
functions = [
"stpcpy",
"strchrnul",
"strcpy",
"strchr",
"strspn",
"strcat",
"strstr",
"strsep",
"strcspn",
"strncat",
"strlcat",
"strlcpy",
"strncmp",
"strrchr",
"strncpy",
"strcmp",
"strnlen",
"strpbrk",
"stpncpy",
]
deps = [
":mem",
":strlen",
]
}
llvm_libc_source_set("str") {
functions = [
"strcasecmp",
"strcasestr",
"strcoll",
"strxfrm",
"strdup",
"strncasecmp",
"strndup",
"strtok",
"strtok_r",
# TODO(https://fxbug.dev/42053650): the llvm-libc versions of these are problematic
#"strerror",
#"strerror_r",
#"strsignal",
]
deps = [ ":minimal-str" ]
}
llvm_libc_source_set("strsignalerror") {
visibility = [ ":*" ]
functions = [
"strerror",
"strerror_r",
"strsignal",
]
deps = [ ":StringUtil" ]
}
llvm_libc_source_set("StringUtil") {
visibility = [ ":*" ]
dir = "__support/StringUtil"
# This doesn't define any functions with tests of their own, but it's still
# an llvm_libc_source_set() to get the dual production and testonly targets.
# (There will also be an unused empty unittests subtarget.)
functions = []
public = [
"error_to_string.h",
"signal_to_string.h",
]
sources = [
"error_to_string.cpp",
"message_mapper.h",
"signal_to_string.cpp",
"tables/linux_extension_errors.h",
"tables/linux_extension_signals.h",
"tables/linux_platform_errors.h",
"tables/linux_platform_signals.h",
"tables/minimal_platform_errors.h",
"tables/minimal_platform_signals.h",
"tables/posix_errors.h",
"tables/posix_signals.h",
"tables/signal_table.h",
"tables/stdc_errors.h",
"tables/stdc_signals.h",
]
}
llvm_libc_source_set("compat") {
functions = [
"bcmp",
"bcopy",
"bzero",
"index",
"rindex",
]
deps = [ ":swab" ]
}
# This lives in libc/src/unistd upstream because it's declared in <unistd.h>
# but it's really a compat string function, so we include it here instead.
llvm_libc_source_set("swab") {
dir = "unistd"
functions = [ "swab" ]
}
# This provides an archive library of the universally safe string functions.
# When built outside the "user.libc" environment, these always define only
# hidden-visibility symbols and should be safe in any build environment.
static_library("hermetic") {
complete_static_lib = true
deps = [
":compat",
":minimal-str",
]
}