diff --git a/include/phasar/Utils/LibrarySummary.h b/include/phasar/Utils/LibrarySummary.h new file mode 100644 index 0000000000..348ce0eedd --- /dev/null +++ b/include/phasar/Utils/LibrarySummary.h @@ -0,0 +1,27 @@ +/****************************************************************************** + * Copyright (c) 2025 Fabian Schiebel. + * All rights reserved. This program and the accompanying materials are made + * available under the terms of LICENSE.txt. + * + * Contributors: + * Fabian Schiebel and others + *****************************************************************************/ + +#ifndef PHASAR_UTILS_LIBRARY_SUMMARY_H +#define PHASAR_UTILS_LIBRARY_SUMMARY_H + +#include "llvm/ADT/StringRef.h" + +namespace psr { + +/// Checks, whether a function with the given (mangled) name is known to be a +/// heap-allocating function, similar to malloc. +[[nodiscard]] bool isHeapAllocatingFunction(llvm::StringRef FName) noexcept; + +/// Checks whether a function with the given (mangled) name is known to always +/// return the same pointer +[[nodiscard]] bool isSingletonReturningFunction(llvm::StringRef FName) noexcept; + +} // namespace psr + +#endif // PHASAR_UTILS_LIBRARY_SUMMARY_H diff --git a/lib/PhasarLLVM/Utils/LLVMShorthands.cpp b/lib/PhasarLLVM/Utils/LLVMShorthands.cpp index 99f8095137..2b8fac6aa3 100644 --- a/lib/PhasarLLVM/Utils/LLVMShorthands.cpp +++ b/lib/PhasarLLVM/Utils/LLVMShorthands.cpp @@ -17,11 +17,11 @@ #include "phasar/PhasarLLVM/Utils/LLVMShorthands.h" #include "phasar/Config/Configuration.h" +#include "phasar/Utils/LibrarySummary.h" #include "phasar/Utils/Utilities.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringRef.h" -#include "llvm/ADT/StringSwitch.h" #include "llvm/Bitcode/BitcodeReader.h" #include "llvm/Bitcode/BitcodeWriter.h" #include "llvm/IR/Constants.h" @@ -67,9 +67,14 @@ bool psr::isAllocaInstOrHeapAllocaFunction(const llvm::Value *V) noexcept { } bool psr::isHeapAllocatingFunction(const llvm::Function *Fun) noexcept { - return llvm::StringSwitch(Fun->getName()) - .Cases("_Znwm", "_Znam", "_ZnwPv", "malloc", "calloc", "realloc", true) - .Default(false); + auto FunName = Fun->getName(); + + if (FunName == "realloc") { + // For backwards compatibility. We should treat realloc specially. + return true; + } + + return isHeapAllocatingFunction(FunName); } // For C-style polymorphism we need to check whether a callee candidate would diff --git a/lib/Utils/LibrarySummary.cpp b/lib/Utils/LibrarySummary.cpp new file mode 100644 index 0000000000..b6850eb4df --- /dev/null +++ b/lib/Utils/LibrarySummary.cpp @@ -0,0 +1,160 @@ +#include "phasar/Utils/LibrarySummary.h" + +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/StringRef.h" + +static constexpr llvm::StringLiteral HeapAllocatingFunNames[] = { + // Also see SVF's extapi.c + + // C functions: + "malloc", + "calloc", + "fopen", + "fopen64", + "fdopen", + "readdir64", + "tmpvoid64", + "zmalloc", + "gzdopen", + "iconv_open", + "lalloc", + "lalloc_clear", + "nhalloc", + "oballoc", + "popen", + "pthread_getspecific", + "readdir", + "safe_calloc", + "safe_malloc", + "safecalloc", + "safemalloc", + "setmntent", + "shmat", + "__sysv_signal", + "signal", + "tempnam", + "tmpvoid", + "xcalloc", + "xmalloc", + "xnmalloc", + "xcharalloc", + "xinmalloc", + "xizalloc", + "xzalloc", + "xpalloc", + "xicalloc", + "icalloc", + "imalloc", + "_gl_alloc_nomem", + "aligned_alloc", + "memalign", + "valloc", + "mmap64", + "XSetLocaleModifiers", + "__strdup", + "xmemdup", + "crypt", + "ctime", + "dlerror", + "dlopen", + "gai_strerror", + "gcry_cipher_algo_name", + "svfgcry_md_algo_name_", + "getenv", + "getlogin", + "getpass", + "gnutls_strerror", + "gpg_strerror", + "gzerror", + "inet_ntoa", + "initscr", + "llvm_stacksave", + "mmap", + "newwin", + "nl_langinfo", + "opendir", + "sbrk", + "strdup", + "xstrdup", + "strerror", + "strsignal", + "textdomain", + "tgetstr", + "tigetstr", + "tmpnam", + "ttyname", + "tzalloc", + + // C++ functions: + "_Znwm", + "_Znam", + "_Znwj", + "_Znaj", + "_ZnwmRKSt9nothrow_t", + "_ZnamRKSt9nothrow_t", + "_ZnwmSt11align_val_t", + "_ZnamSt11align_val_t", + "_ZnwmSt11align_val_tRKSt9nothrow_t", + "_ZnamSt11align_val_tRKSt9nothrow_t", + "__cxa_allocate_exception", +}; + +static constexpr llvm::StringLiteral SingletonReturningFunctions[] = { + "__ctype_b_loc", + "__ctype_tolower_loc", + "__ctype_toupper_loc", + "__errno_location", + "__h_errno_location", + "__res_state", + "asctime", + "bindtextdomain", + "bind_textdomain_codeset", + "dcgettext", + "dgettext", + "dngettext", + "getgrgid", + "getgrnam", + "gethostbyaddr", + "gethostbyname", + "gethostbyname2", + "getmntent", + "getprotobyname", + "getprotobynumber", + "getpwent", + "getpwnam", + "getpwuid", + "getservbyname", + "getservbyport", + "getspnam", + "gettext", + "gmtime", + "gnu_get_libc_version", + "gnutls_check_version", + "localeconv", + "localtime", + "ngettext", + "pango_cairo_font_map_get_default", + "re_comp", + "setlocale", + "tgoto", + "tparm", + "zError", +}; + +bool psr::isHeapAllocatingFunction(llvm::StringRef FName) noexcept { + // Note: For a performance comparison of different search strategies, see + // https://quick-bench.com/q/lNjDT6z-M-L08h372fbCfYjwM64 + + static const llvm::DenseSet HAFs( + std::begin(HeapAllocatingFunNames), std::end(HeapAllocatingFunNames)); + + return HAFs.count(FName); +} + +bool psr::isSingletonReturningFunction(llvm::StringRef FName) noexcept { + static const llvm::DenseSet SRFs( + std::begin(SingletonReturningFunctions), + std::end(SingletonReturningFunctions)); + + return SRFs.count(FName); +}