| # 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", |
| ] |
| } |